Index: lams_build/3rdParty.userlibraries
===================================================================
RCS file: /usr/local/cvsroot/lams_build/3rdParty.userlibraries,v
diff -u -r1.69 -r1.70
--- lams_build/3rdParty.userlibraries 8 Apr 2013 10:52:41 -0000 1.69
+++ lams_build/3rdParty.userlibraries 5 Nov 2013 17:37:17 -0000 1.70
@@ -45,5 +45,6 @@
+
Index: lams_build/build.xml
===================================================================
RCS file: /usr/local/cvsroot/lams_build/build.xml,v
diff -u -r1.117 -r1.118
--- lams_build/build.xml 9 Sep 2013 06:21:43 -0000 1.117
+++ lams_build/build.xml 5 Nov 2013 17:37:17 -0000 1.118
@@ -199,6 +199,7 @@
+
Index: lams_build/lib/json/gson-2.2.4.jar
===================================================================
RCS file: /usr/local/cvsroot/lams_build/lib/json/gson-2.2.4.jar,v
diff -u
Binary files differ
Index: lams_central/src/java/org/lamsfoundation/lams/authoring/web/AuthoringAction.java
===================================================================
RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/authoring/web/AuthoringAction.java,v
diff -u -r1.38 -r1.39
--- lams_central/src/java/org/lamsfoundation/lams/authoring/web/AuthoringAction.java 21 Oct 2013 13:47:28 -0000 1.38
+++ lams_central/src/java/org/lamsfoundation/lams/authoring/web/AuthoringAction.java 5 Nov 2013 17:37:19 -0000 1.39
@@ -25,6 +25,7 @@
import java.io.IOException;
import java.io.PrintWriter;
+import java.io.Writer;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
@@ -42,6 +43,7 @@
import org.apache.tomcat.util.json.JSONException;
import org.apache.tomcat.util.json.JSONObject;
import org.lamsfoundation.lams.authoring.service.IAuthoringService;
+import org.lamsfoundation.lams.learningdesign.dto.LearningDesignDTO;
import org.lamsfoundation.lams.learningdesign.dto.LicenseDTO;
import org.lamsfoundation.lams.learningdesign.service.ILearningDesignService;
import org.lamsfoundation.lams.lesson.Lesson;
@@ -67,6 +69,9 @@
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
/**
* @author Manpreet Minhas
*
@@ -101,7 +106,7 @@
request.setAttribute("tools", getLearningDesignService().getToolDTOs(request.getRemoteUser()));
return mapping.findForward("openAutoring");
}
-
+
/**
* Output the supplied WDDX packet. If the request parameter USE_JSP_OUTPUT is set, then it sets the session
* attribute "parameterName" to the wddx packet string. If USE_JSP_OUTPUT is not set, then the packet is written out
@@ -157,6 +162,21 @@
return outputPacket(mapping, request, response, wddxPacket, "details");
}
+ public ActionForward getLearningDesignJSON(ActionMapping mapping, ActionForm form, HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ JSONObject responseJSON = new JSONObject();
+
+ long learningDesignID = WebUtil.readLongParam(request, AttributeNames.PARAM_LEARNINGDESIGN_ID);
+ LearningDesignDTO learningDesignDTO = getLearningDesignService().getLearningDesignDTO(learningDesignID,
+ getUserLanguage());
+
+ response.setContentType("application/json;charset=utf-8");
+ Writer responseWriter = response.getWriter();
+ Gson gson = new GsonBuilder().create();
+ gson.toJson(learningDesignDTO, responseWriter);
+ return null;
+ }
+
public ActionForward finishLearningDesignEdit(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
@@ -471,7 +491,6 @@
}
return AuthoringAction.toolService;
}
-
private ILearningDesignService getLearningDesignService() {
if (AuthoringAction.learningDesignService == null) {
Index: lams_central/web/author2.jsp
===================================================================
RCS file: /usr/local/cvsroot/lams_central/web/Attic/author2.jsp,v
diff -u -r1.5 -r1.6
--- lams_central/web/author2.jsp 21 Oct 2013 13:47:27 -0000 1.5
+++ lams_central/web/author2.jsp 5 Nov 2013 17:37:18 -0000 1.6
@@ -21,6 +21,10 @@
+
+
+
+
-
+
+
+
\ No newline at end of file
Index: lams_central/web/css/authoring.css
===================================================================
RCS file: /usr/local/cvsroot/lams_central/web/css/authoring.css,v
diff -u -r1.3 -r1.4
--- lams_central/web/css/authoring.css 21 Oct 2013 13:47:28 -0000 1.3
+++ lams_central/web/css/authoring.css 5 Nov 2013 17:37:18 -0000 1.4
@@ -2,7 +2,7 @@
display: none;
}
-div#openLearningDesignDialog {
+.ui-dialog {
font-size: 12px;
}
@@ -14,7 +14,7 @@
div#openLearningDesignDialog > table {
width: 100%;
- height: 735px;
+ height: 684px;
table-layout: fixed;
border-top: thin dotted #2E6E9E;
}
@@ -52,27 +52,18 @@
td#canvasCell {
text-align: center;
padding: 10px 0px 0px 10px;
+ vertical-align: middle;
}
div#canvasDiv {
overflow: auto;
- height: 685px;
+ height: 665px;
}
img#ldScreenshotLoading {
padding-top: 200px;
}
-#buttonsCell {
- border-top: thin dotted #2E6E9E;
- padding-top: 5px;
-}
-
-#buttonsCell > div {
- float: right;
- margin-left: 10px;
-}
-
div#toolbar {
padding: 3px;
height: 27px;
Fisheye: Tag 1.7 refers to a dead (removed) revision in file `lams_central/web/includes/javascript/authoring.js'.
Fisheye: No comparison available. Pass `N' to diff?
Index: lams_central/web/includes/javascript/authoring/authoringActivity.js
===================================================================
RCS file: /usr/local/cvsroot/lams_central/web/includes/javascript/authoring/authoringActivity.js,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lams_central/web/includes/javascript/authoring/authoringActivity.js 5 Nov 2013 17:37:19 -0000 1.1
@@ -0,0 +1,353 @@
+/**
+ * This file contains methods for Activity manipulation on canvas.
+ */
+
+var ActivityLib = {
+
+ /**
+ * Constructor for a Tool Activity.
+ */
+ ToolActivity: function(id, toolID, x, y, label) {
+ this.id = id;
+ this.type = 'tool';
+ this.toolID = toolID;
+
+ // create activity SVG elements
+ paper.setStart();
+ var shape = paper.rect(x, y, layout.conf.activityWidth, layout.conf.activityHeight)
+ .attr({
+ 'fill' : layout.colors.activity
+ });
+
+ paper.image(layout.toolIcons[toolID], shape.attr('x')
+ + shape.attr('width') / 2 - 15, shape.attr('y') + 2, 30, 30);
+
+ paper.text(shape.attr('x') + shape.attr('width') / 2, shape
+ .attr('y') + 40, label);
+
+ this.items = paper.setFinish();
+ this.items.shape = shape;
+
+ ActivityLib.initActivity(this);
+ },
+
+ /**
+ * Constructor for a Grouping Activity.
+ */
+ GroupingActivity : function(id, x, y) {
+ this.id = id;
+ this.type = 'group';
+
+ // create activity SVG elements
+ paper.setStart();
+ var shape = paper.rect(
+ x - layout.conf.activityWidth/2,
+ y - layout.conf.activityHeight/2,
+ layout.conf.activityWidth, layout.conf.activityHeight)
+ .attr({
+ 'fill' : layout.colors.activity
+ });
+
+ paper.image('../images/grouping.gif',
+ shape.attr('x') + shape.attr('width') / 2 - 15,
+ shape.attr('y') + 2,
+ 30, 30);
+
+ paper.text(shape.attr('x') + shape.attr('width') / 2, shape
+ .attr('y') + 40, 'Grouping');
+
+ this.items = paper.setFinish();
+ this.items.shape = shape;
+
+ ActivityLib.initActivity(this);
+ },
+
+ /**
+ * Constructor for a Gate Activity.
+ */
+ GateActivity : function(id, x, y) {
+ this.id = id;
+ this.type = 'gate';
+
+ // create activity SVG elements
+ paper.setStart();
+ var shape = paper.path('M ' + x + ' ' + y + layout.defs.gate)
+ .attr({
+ 'fill' : layout.colors.gate
+ });
+
+ paper.text(x + 7, y + 14, 'STOP')
+ .attr({
+ 'font-size' : 9,
+ 'font' : 'sans-serif',
+ 'stroke' : layout.colors.gateText
+ });
+
+ this.items = paper.setFinish();
+ this.items.shape = shape;
+
+ ActivityLib.initActivity(this);
+ },
+
+
+ BranchingEdgeActivity : function(id, x, y, branchingActivity) {
+ this.type = 'branchingEdge';
+ if (branchingActivity) {
+ this.isStart = false;
+ branchingActivity.end = this;
+ } else {
+ this.isStart = true;
+ branchingActivity = new ActivityLib.BranchingActivity(id, this);
+ }
+ this.branchingActivity = branchingActivity;
+
+ // create activity SVG elements
+ paper.setStart();
+ var shape = paper.path('M ' + x + ' ' + y +
+ (this.isStart ? layout.defs.branchingEdgeStart : layout.defs.branchingEdgeEnd))
+ .attr({
+ 'fill' : this.isStart ? layout.colors.branchingEdgeStart
+ : layout.colors.branchingEdgeEnd
+ });
+
+ paper.text(x, y + 14, this.isStart ? 'Branching point'
+ : 'Converge point')
+ .attr({
+ 'font-size' : 9,
+ 'font' : 'sans-serif'
+ });
+
+ this.items = paper.setFinish();
+ this.items.shape = shape;
+
+ ActivityLib.initActivity(this);
+ },
+
+
+ BranchingActivity : function(id, branchingEdgeStart) {
+ this.id = id;
+ this.start = branchingEdgeStart;
+ this.branches = [];
+ },
+
+
+ BranchActivity : function(id, branchingActivity, transitionFrom) {
+ this.id = id;
+ this.transitionsFrom = transitionFrom;
+ this.branchingActivity = branchingActivity;
+ branchingActivity.branches.push(this);
+ },
+
+
+ /**
+ * Make a new activity fully functional on canvas.
+ */
+ initActivity : function(activity) {
+ activity.items.mousedown(function(event, x, y){
+ if (event.ctrlKey) {
+ // when CTRL is held down, start drawing a transition
+ HandlerLib.drawTransitionStartHandler(activity, event, x, y);
+ } else {
+ // start dragging the activity
+ var mouseupHandler = function(){
+ HandlerLib.dragActivityEndHandler(activity);
+ };
+
+ HandlerLib.dragItemsStartHandler(activity.items, this, mouseupHandler, event, x, y);
+ }
+ })
+ .click(function(event){
+ // inform that user wants to select, not drag the activity
+ activity.items.clicked = true;
+ HandlerLib.selectActivityHandler(event, activity);
+ })
+ .dblclick(function(){
+ // inform that user wants to open, not drag the activity
+ activity.items.clicked = true;
+ HandlerLib.openActivityAuthoringHandler(activity);
+ })
+ .attr({
+ 'cursor' : 'pointer'
+ });
+
+ if (activity.type == 'branchingEdge' && activity.branchingActivity.end) {
+ var startItems = activity.branchingActivity.start.items;
+ var endItems = activity.branchingActivity.end.items;
+ var mouseover = function(){
+ if (!startItems.isDragged && !endItems.isDragged) {
+ startItems.shape.attr('fill', layout.colors.branchingEdgeMatch);
+ endItems.shape.attr('fill', layout.colors.branchingEdgeMatch);
+ }
+ };
+ var mouseout = function(){
+ if (!startItems.isDragged && !endItems.isDragged) {
+ startItems.shape.attr('fill', layout.colors.branchingEdgeStart);
+ endItems.shape.attr('fill', layout.colors.branchingEdgeEnd);
+ }
+ };
+ startItems.shape.hover(mouseover, mouseout);
+ endItems.shape.hover(mouseover, mouseout);
+ }
+ },
+
+
+ /**
+ * Deletes the given activity.
+ */
+ removeActivity : function(activity, forceRemove) {
+ if (!forceRemove && activity.type == 'branchingEdge'){
+ if (confirm('Are you sure you want to remove the whole branching activity?')){
+ var otherEdge = activity.isStart ? activity.branchingActivity.end
+ : activity.branchingActivity.start;
+ ActivityLib.removeActivity(otherEdge, true);
+ } else {
+ return;
+ }
+ }
+
+ // remove the transitions
+ if (activity.fromTransition) {
+ var toActivity = activity.fromTransition.toActivity;
+ // if grouping activity is gone, remove the grouping effect
+ if (activity.type == 'group' && toActivity.items.groupingEffect) {
+ toActivity.items.groupingEffect.remove();
+ toActivity.items.groupingEffect = null;
+ }
+ toActivity.toTransition = null;
+ activity.fromTransition.remove();
+ }
+ if (activity.toTransition){
+ activity.toTransition.fromActivity.fromTransition = null
+ activity.toTransition.remove();
+ }
+
+ // remove the activity from activities table
+ activities.splice(activities.indexOf(activity), 1);
+ // visually remove the activity
+ activity.items.remove();
+ },
+
+
+ /**
+ * Draws a transition between two activities.
+ */
+ drawTransition : function(fromActivity, toActivity) {
+ // remove the existing activities
+ if (fromActivity.fromTransition) {
+ fromActivity.fromTransition.remove();
+ }
+ if (toActivity.toTransition) {
+ toActivity.toTransition.remove();
+ }
+
+ // calculate middle points of each activity
+ var fromActivityBox = fromActivity.items.shape.getBBox();
+ var toActivityBox = toActivity.items.shape.getBBox();
+ var startX = fromActivityBox.x + fromActivityBox.width / 2;
+ var startY = fromActivityBox.y + fromActivityBox.height / 2;
+ var endX = toActivityBox.x + toActivityBox.width / 2;
+ var endY = toActivityBox.y + toActivityBox.height / 2;
+
+ // do the actual drawing
+ paper.setStart();
+ paper.path('M ' + startX + ' ' + startY + ' L ' + endX + ' ' + endY)
+ .attr({
+ 'stroke' : layout.colors.transition,
+ 'stroke-width' : 2
+ });
+
+ // draw the arrow and turn it in the same direction as the line
+ var angle = 90 + Math.atan2(endY - startY, endX - startX) * 180 / Math.PI;
+ var arrowX = (startX + (endX - startX)/2);
+ var arrowY = (startY + (endY - startY)/2);
+ var arrowPath = Raphael.transformPath('M ' + arrowX + ' ' + arrowY + layout.defs.transArrow,
+ 'R ' + angle + ' ' + arrowX + ' ' + arrowY);
+ paper.path(arrowPath)
+ .attr({
+ 'stroke' : layout.colors.transition,
+ 'fill' : layout.colors.transition
+ });
+ transition = paper.setFinish();
+
+ // set up references in activities and the transition
+ transition.fromActivity = fromActivity;
+ transition.toActivity = toActivity;
+ fromActivity.fromTransition = transition;
+ toActivity.toTransition = transition;
+ transition.toBack();
+ transition.mousedown(function(event, x, y){
+ // allow transition dragging
+ var mouseupHandler = function(){
+ HandlerLib.dragTransitionEndHandler(transition);
+ };
+ HandlerLib.dragItemsStartHandler(transition, this, mouseupHandler, event, x, y)
+ });
+
+ // add grouping effect if previous activity is of grouping type
+ if (fromActivity.type == 'group' && toActivity.type != 'gate') {
+ ActivityLib.addGroupingEffect(toActivity);
+ }
+ },
+
+
+ /**
+ * Removes the given transition.
+ */
+ removeTransition : function(transition) {
+ if (transition.toActivity.items.groupingEffect) {
+ transition.toActivity.items.groupingEffect.remove();
+ transition.toActivity.items.groupingEffect = null;
+ }
+ transition.fromActivity.fromTransition = null;
+ transition.toActivity.toTransition = null;
+ transition.remove();
+ },
+
+
+ /**
+ * Draws an extra border around the selected activity.
+ */
+ addSelectEffect : function (activity) {
+ // do not draw twice
+ if (!activity.items.selectEffect) {
+ var box = activity.items.shape.getBBox();
+
+ // a simple rectange a bit wider than the actual activity boundaries
+ activity.items.selectEffect = paper.rect(
+ box.x - 7,
+ box.y - 7,
+ box.width + 14,
+ box.height + 14)
+ .attr({
+ 'stroke' : layout.colors.selectEffect,
+ 'stroke-dasharray' : '-'
+ });
+ activity.items.push(activity.items.selectEffect);
+
+ // show the properties dialog for the selected activity
+ layout.items.selectedActivity = activity;
+ layout.items.propertiesDialog.dialog('open');
+ }
+ },
+
+
+ /**
+ * Adds visual grouping effect on an activity.
+ */
+ addGroupingEffect : function(activity) {
+ if (!activity.items.groupingEffect) {
+ var shape = activity.items.shape;
+
+ activity.items.groupingEffect = paper.rect(
+ shape.attr('x') + 5,
+ shape.attr('y') + 5,
+ layout.conf.activityWidth,
+ layout.conf.activityHeight)
+ .attr({
+ 'fill' : shape.attr('fill')
+ })
+ .toBack();
+ activity.items.push(activity.items.groupingEffect);
+ }
+ }
+};
\ No newline at end of file
Index: lams_central/web/includes/javascript/authoring/authoringGeneral.js
===================================================================
RCS file: /usr/local/cvsroot/lams_central/web/includes/javascript/authoring/authoringGeneral.js,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lams_central/web/includes/javascript/authoring/authoringGeneral.js 5 Nov 2013 17:37:18 -0000 1.1
@@ -0,0 +1,313 @@
+/**
+ * This file contains global methods for Authoring.
+ */
+
+// few publicly visible variables
+var paper = null;
+var canvas = null;
+var activities = [];
+
+// configuration and storage of various elements
+var layout = {
+ 'toolIcons': {},
+ 'conf' : {
+ 'activityWidth' : 125,
+ 'activityHeight' : 50,
+ 'propertiesDialogDimOpacity' : 0.3,
+ 'propertiesDialogDimThreshold' : 100,
+ 'propertiesDialogDimThrottle' : 100,
+ 'dragStartThreshold' : 300
+ },
+ 'defs' : {
+ 'bin' : 'M 830 680 h -50 l 10 50 h 30 z',
+ 'transArrow' : ' l 10 15 a 25 25 0 0 0 -20 0 z',
+ 'gate' : ' l-8 8 v14 l8 8 h14 l8 -8 v-14 l-8 -8 z',
+ 'branchingEdgeStart' : ' m -8 0 a 8 8 0 1 0 16 0 a 8 8 0 1 0 -16 0',
+ 'branchingEdgeEnd' : ' m -8 0 a 8 8 0 1 0 16 0 a 8 8 0 1 0 -16 0'
+ },
+ 'colors' : {
+ 'activity' : '#A9C8FD',
+ 'gate' : 'red',
+ 'gateText' : 'white',
+ 'transition' : 'rgb(119,126,157)',
+ 'binActive' : 'red',
+ 'selectEffect' : 'blue',
+ 'branchingEdgeStart' : 'green',
+ 'branchingEdgeEnd' : 'red',
+ 'branchingEdgeMatch' : 'blue'
+ },
+ 'items' : {
+ 'bin' : null,
+ 'selectedActivity' : null,
+ 'propertiesDialog' : null
+ }
+};
+
+
+/**
+ * Initialises the whole Authoring window.
+ */
+$(document).ready(function() {
+ paper = Raphael('canvas');
+ canvas = $('#canvas');
+
+ initLayout();
+ initTemplates();
+});
+
+
+/**
+ * Draw boxes with Tool Activity templates.
+ */
+function initTemplates(){
+ $('.template').each(function(){
+ var toolId = $(this).attr('toolId');
+ // register tool icons so they are later easily accessible
+ layout.toolIcons[toolId] = $('img', this).attr('src');
+
+ // if a tool's name is too long and gets broken into two lines
+ // make some adjustments to layout
+ var toolName = $('div', this);
+ if (toolName.text().length > 15){
+ toolName.css('padding-top', '4px');
+ }
+
+ // allow dragging a template to canvas
+ $(this).draggable({
+ 'containment' : '#authoringTable',
+ 'revert' : 'invalid',
+ 'distance' : 20,
+ 'scroll' : false,
+ 'scope' : 'template',
+ 'helper' : function(event){
+ // build a simple helper
+ var helper = $(this).clone().css({
+ 'width' : '135px',
+ 'border' : 'thin black solid',
+ 'z-index' : 1,
+ 'cursor' : 'move'
+ });
+
+ // Chrome does not render name of the tool correctly in the helper
+ // so just remove it
+ helper.children('div').remove();
+ return helper;
+ }
+ });
+ });
+
+ // allow dropping templates to canvas
+ canvas.droppable({
+ 'tolerance' : 'touch',
+ 'scope' : 'template',
+ 'drop' : function (event, draggable) {
+ // get rid of helper div
+ $(draggable.helper).remove();
+
+ // calculate the position and create an instance of the tool activity
+ var toolID = draggable.draggable.attr('toolId');
+ var canvasOffset = canvas.offset();
+ var x = draggable.offset.left - canvasOffset.left;
+ var y = draggable.offset.top - canvasOffset.top;
+ var label = $('div', draggable.draggable).text();
+
+ activities.push(new ActivityLib.ToolActivity(null, toolID, x, y, label));
+ }
+ });
+}
+
+
+/**
+ * Initialises various Authoring widgets.
+ */
+function initLayout() {
+ // draw rubbish bin on canvas
+ layout.items.bin = paper.path(layout.defs.bin);
+
+ // add jQuery UI button functionality
+ $('.ui-button').button();
+ $(".split-ui-button").each(function(){
+ // drop down buttons
+ var buttonContainer = $(this);
+ var buttons = buttonContainer.children();
+
+ buttons.first().button()
+ .next().button({
+ text : false,
+ icons : {
+ primary : "ui-icon-triangle-1-s"
+ }
+ });
+ buttonContainer.buttonset().next().hide().menu();
+
+ buttons.each(function(){
+ var button = $(this);
+ if (!button.attr('onclick')) {
+ button.click(function() {
+ var menu = $(this).parent().next().show().position({
+ my : "left top+2px",
+ at : "left bottom",
+ of : $(this).parent()
+ });
+ $(document).one("click", function() {
+ menu.hide();
+ });
+ return false;
+ });
+ }
+ });
+ });
+
+ // initialise the properties dialog singleton
+ var propertiesDialog = layout.items.propertiesDialog =
+ $('Properties go here
')
+ .appendTo('body')
+ .dialog({
+ 'autoOpen' : false,
+ 'closeOnEscape' : false,
+ 'position' : {
+ 'my' : 'left top',
+ 'at' : 'left top',
+ 'of' : '#canvas'
+ },
+ 'resizable' : false,
+ 'title' : 'Properties'
+ });
+ // for proximity detection throttling (see handlers)
+ propertiesDialog.lastRun = 0;
+ // remove close button, add dimming
+ propertiesDialog.container = propertiesDialog.closest('.ui-dialog');
+ propertiesDialog.container.addClass('propertiesDialog')
+ .css('opacity', layout.conf.propertiesDialogDimOpacity)
+ .mousemove(HandlerLib.approachPropertiesDialogHandler)
+ .find('.ui-dialog-titlebar-close').remove();
+
+ // initalise open Learning Design dialog
+ var openLDDialog = $('#openLearningDesignDialog').dialog({
+ 'autoOpen' : false,
+ 'position' : {
+ 'my' : 'left top',
+ 'at' : 'left+5px top+5px',
+ 'of' : 'body'
+ },
+ 'resizable' : false,
+ 'width' : 990,
+ 'height' : 780,
+ 'dialogClass': 'dialog-no-title',
+ 'buttons' : [
+ {
+ 'text' : 'Open',
+ 'id' : 'openLDButton',
+ 'click' : function() {
+ var dialog = $(this);
+ var tree = dialog.dialog('option', 'ldTree');
+ var ldNode = tree.getHighlightedNode();
+ // no LD was chosen
+ if (!ldNode || !ldNode.data.learningDesignId) {
+ alert("Please choose a sequence");
+ return;
+ }
+
+ dialog.dialog('close');
+ openLearningDesign(ldNode.data.learningDesignId);
+ }
+ },
+ {
+ 'text' : 'Cancel',
+ 'id' : 'cancelLDButton',
+ 'click' : function() {
+ $(this).dialog('close');
+ }
+ }
+ ]
+ });
+
+ $('#ldScreenshotAuthor', openLDDialog).load(function(){
+ // hide "loading" animation
+ $('.ldChoiceDependentCanvasElement').css('display', 'none');
+ // show the thumbnail
+ $(this).css('display', 'inline');
+ });
+ // there should be no focus, just highlight
+ YAHOO.widget.TreeView.FOCUS_CLASS_NAME = null;
+
+
+ $('#infoDialog').dialog({
+ 'autoOpen' : false,
+ 'height' : 35,
+ 'width' : 290,
+ 'modal' : false,
+ 'resizable' : false,
+ 'show' : 'fold',
+ 'hide' : 'fold',
+ 'dialogClass': 'dialog-no-title',
+ 'position' : {my: "right top",
+ at: "right top+5px",
+ of: '#canvas'
+ }
+ });
+
+ HandlerLib.resetCanvasMode();
+}
+
+
+/**
+ * Replace current canvas contents with the loaded sequence.
+ */
+function openLearningDesign(learningDesignId) {
+ // get LD details
+ $.ajax({
+ cache : false,
+ url : LAMS_URL + "authoring/author.do",
+ dataType : 'json',
+ data : {
+ 'method' : 'getLearningDesignJSON',
+ 'learningDesignID': learningDesignId
+ },
+ success : function(ld) {
+ if (!ld) {
+ alert('Error while loading sequence');
+ return;
+ }
+
+ // reset the canvas
+ paper.clear();
+ // draw the rubbish bin again
+ layout.items.bin = paper.path(layout.defs.bin);
+ // create visual representation of the loaded activities
+ activities = [];
+ $.each(ld.activities, function() {
+ var activity = this;
+
+ activities.push(new ActivityLib.ToolActivity(activity.activityID,
+ activity.toolID, activity.xCoord, activity.yCoord,
+ activity.activityTitle));
+ });
+
+ // draw transitions
+ $.each(ld.transitions, function(){
+ var transition = this;
+ var fromActivity = null
+ var toActivity = null;
+
+ // find which activities the transition belongs to
+ $.each(activities, function(){
+ var activity = this;
+ if (activity.id == transition.fromActivityID) {
+ fromActivity = activity;
+ } else if (activity.id == transition.toActivityID) {
+ toActivity = activity;
+ }
+
+ // found both transition ends, draw it and stop the iteration
+ if (fromActivity && toActivity) {
+ ActivityLib.drawTransition(fromActivity, toActivity);
+ return false;
+ }
+ });
+ });
+
+ HandlerLib.resetCanvasMode();
+ }
+ });
+}
\ No newline at end of file
Index: lams_central/web/includes/javascript/authoring/authoringHandler.js
===================================================================
RCS file: /usr/local/cvsroot/lams_central/web/includes/javascript/authoring/authoringHandler.js,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lams_central/web/includes/javascript/authoring/authoringHandler.js 5 Nov 2013 17:37:19 -0000 1.1
@@ -0,0 +1,328 @@
+/**
+ * This file contains event handlers for interaction with canvas and other Authoring elements.
+ */
+
+var HandlerLib = {
+
+ /**
+ * Default mode for canvas. Run after special mode is no longer needed.
+ */
+ resetCanvasMode : function(){
+ canvas.css('cursor', 'default')
+ .off('click')
+ // if clicked anywhere, activity selection is gone
+ .click(HandlerLib.unselectActivityHandler)
+ .off('mouseup')
+ .off('mousemove')
+ // when mouse gets closer to properties dialog, make it fully visible
+ .mousemove(HandlerLib.approachPropertiesDialogHandler);
+ },
+
+
+ /**
+ * Makes properties dialog fully visible.
+ */
+ approachPropertiesDialogHandler : function(event) {
+ // properties dialog is a singleton
+ var dialog = layout.items.propertiesDialog;
+ // do not run this method too often
+ var thisRun = new Date().getTime();
+ if (thisRun - dialog.lastRun < layout.conf.propertiesDialogDimThrottle){
+ return;
+ }
+ dialog.lastRun = thisRun;
+
+ // is the dialog visible at all?
+ var activity = layout.items.selectedActivity;
+ if (activity) {
+ // calculate dim/show threshold
+ var container = dialog.container,
+ dialogPosition = container.offset(),
+ dialogStartX = dialogPosition.left,
+ dialogStartY = dialogPosition.top,
+ dialogEndX = dialogStartX + container.width(),
+ dialogEndY = dialogStartY + container.height(),
+ dimTreshold = layout.conf.propertiesDialogDimThreshold,
+ tooFarX = event.pageX < dialogStartX - dimTreshold || event.pageX > dialogEndX + dimTreshold,
+ tooFarY = event.pageY < dialogStartY - dimTreshold || event.pageY > dialogEndY + dimTreshold,
+ opacity = tooFarX || tooFarY ? layout.conf.propertiesDialogDimOpacity : 1;
+
+ container.css('opacity', opacity);
+ }
+ },
+
+
+ /**
+ * Show selection border around the clicked activity.
+ */
+ selectActivityHandler : function(event, activity) {
+ if (activity != layout.items.selectedActivity) {
+ HandlerLib.unselectActivityHandler(event);
+ ActivityLib.addSelectEffect(activity);
+ }
+ // so canvas handler unselectActivityHandler() is not run
+ event.preventDefault();
+ },
+
+
+ /**
+ * Remove activity selection when user clicks on canvas.
+ */
+ unselectActivityHandler : function(event) {
+ // check if user clicked on empty space on canvas
+ // or on some element on top of it
+ var defaultPrevented = event.originalEvent ?
+ event.originalEvent.defaultPrevented : event.defaultPrevented;
+ if (!defaultPrevented) {
+ var selectedActivity = layout.items.selectedActivity;
+ // does selection exist at all?
+ if (selectedActivity) {
+ selectedActivity.items.selectEffect.remove();
+ selectedActivity.items.selectEffect = null;
+
+ // no selected activity = no properties dialog
+ layout.items.propertiesDialog.dialog('close');
+ layout.items.selectedActivity = null;
+ }
+ }
+ },
+
+
+ /**
+ * Open separate window with activity authoring on double click.
+ */
+ openActivityAuthoringHandler : function(activity){
+ // fetch authoring URL for a Tool Activity
+ if (!activity.authorURL && activity.toolID) {
+ $.ajax({
+ async : false,
+ cache : false,
+ url : LAMS_URL + "authoring/author.do",
+ dataType : 'json',
+ data : {
+ 'method' : 'createToolContent',
+ 'toolID' : activity.toolID,
+ 'contentFolderID' : contentFolderID
+ },
+ success : function(response) {
+ activity.authorURL = response.authorURL;
+ activity.id = response.toolContentID;
+ if (!contentFolderID) {
+ // if LD did not have contentFolderID, it was just generated
+ // so remember it
+ contentFolderID = response.contentFolderID;
+ }
+ }
+ });
+ }
+
+ if (activity.authorURL) {
+ window.open(activity.authorURL, 'activityAuthoring' + activity.id,
+ "HEIGHT=800,WIDTH=1024,resizable=yes,scrollbars=yes,status=false," +
+ "menubar=no,toolbar=no");
+ }
+ },
+
+
+ /**
+ * Start dragging an activity or transition.
+ */
+ dragItemsStartHandler : function(items, draggedElement, mouseupHandler, event, startX, startY) {
+ items.toFront();
+ // clear "clicked" flag, just in case
+ items.clicked = false;
+
+ if (items.dragStarter) {
+ // prevent confusion when double clicking
+ clearTimeout(items.dragStarter);
+ }
+
+ // run only if "click" event was not generated, i.e. user really wants to drag
+ items.dragStarter = setTimeout(function(){
+ items.dragStarter = null;
+ // "clicked" flag is set by mouseup event
+ // and it means that user does not want to drag, but to click
+ if (items.clicked) {
+ items.clicked = false;
+ return;
+ }
+ items.isDragged = true;
+ items.attr('cursor', 'move');
+
+ canvas.mousemove(function(event) {
+ HandlerLib.dragItemsMoveHandler(items, event, startX, startY);
+ });
+
+ var mouseup = function(){
+ // finish dragging - restore various elements' default state
+ items.isDragged = false;
+ items.unmouseup();
+ HandlerLib.resetCanvasMode();
+ layout.items.bin.attr('fill', 'transparent');
+
+ // do whetver needs to be done with the dragged elements
+ mouseupHandler();
+ };
+
+ // if user moves mouse very quickly, mouseup event can be triggered
+ // for canvas, not the dragged elements
+ canvas.mouseup(mouseup);
+ items.mouseup(mouseup);
+ }, layout.conf.dragStartThreshold);
+ },
+
+
+ /**
+ * Moves dragged elements on the canvas.
+ */
+ dragItemsMoveHandler : function(items, event, startX, startY) {
+ var dx = event.pageX - startX;
+ var dy = event.pageY - startY;
+ items.transform('t' + dx + ' ' + dy);
+
+ if (items.groupingEffect) {
+ items.groupingEffect.toBack();
+ }
+
+ // highlight rubbish bin if dragged elements are over it
+ if (Raphael.isBBoxIntersect(layout.items.bin.getBBox(), items.getBBox())) {
+ layout.items.bin.attr('fill', layout.colors.binActive);
+ } else {
+ layout.items.bin.attr('fill', 'transparent');
+ }
+ },
+
+
+ /**
+ * Drop the dragged activity on the canvas.
+ */
+ dragActivityEndHandler : function(activity) {
+ // if the activity was over rubbish bin, remove it
+ if (Raphael.isBBoxIntersect(layout.items.bin.getBBox(), activity.items.shape.getBBox())) {
+ ActivityLib.removeActivity(activity);
+ return;
+ }
+
+ // finally transform the dragged elements
+ var transformation = activity.items.shape.attr('transform');
+ activity.items.transform('');
+ if (transformation.length > 0) {
+ activity.items.forEach(function(elem) {
+ // some elements (rectangles) have "x", some are paths
+ if (elem.attr('x')) {
+ elem.attr({
+ 'x' : elem.attr('x') + transformation[0][1],
+ 'y' : elem.attr('y') + transformation[0][2]
+ });
+ } else {
+ var path = elem.attr('path');
+ elem.attr('path', Raphael.transformPath(path, transformation));
+ }
+ });
+ }
+
+ if (activity.items.groupingEffect) {
+ activity.items.groupingEffect.toBack();
+ }
+
+ // redraw transitions
+ if (activity.fromTransition) {
+ ActivityLib.drawTransition(activity, activity.fromTransition.toActivity);
+ }
+ if (activity.toTransition) {
+ ActivityLib.drawTransition(activity.toTransition.fromActivity, activity);
+ }
+ },
+
+
+ /**
+ * Drop the dragged transition.
+ */
+ dragTransitionEndHandler : function(transition) {
+ // if the transition was over rubbish bin, remove it
+ if (Raphael.isBBoxIntersect(layout.items.bin.getBBox(), transition.getBBox())) {
+ ActivityLib.removeTransition(transition);
+ } else {
+ // cancel drag
+ transition.transform('');
+ transition.toBack();
+ }
+ },
+
+ /**
+ * Start drawing a transition.
+ */
+ drawTransitionStartHandler : function(activity, event, x, y) {
+ if (activity.fromTransition && activity.type != 'branchingEdge') {
+ alert('Transition from this activity already exists');
+ return;
+ }
+
+ var startX = x - canvas.offset().left;
+ var startY = y - canvas.offset().top;
+
+ canvas.mousemove(function(event){
+ HandlerLib.drawTransitionMoveHandler(activity, event, startX, startY);
+ }).mouseup(function(event){
+ HandlerLib.drawTransitionEndHandler(activity, event);
+ });
+ },
+
+
+ /**
+ * Keep drawing a transition.
+ */
+ drawTransitionMoveHandler : function(activity, event, startX, startY) {
+ // remove the temporary transition (dashed line)
+ if (activity.tempTransition) {
+ activity.tempTransition.remove();
+ activity.tempTransition = null;
+ }
+ if (!event.ctrlKey) {
+ canvas.off('mousemove');
+ canvas.off('mouseup');
+ return;
+ }
+
+ var endX = event.pageX - canvas.offset().left;
+ var endY = event.pageY - canvas.offset().top;
+
+ // draw a temporary transition so user sees what he is doing
+ activity.tempTransition = paper.set();
+ activity.tempTransition.push(paper.circle(startX, startY, 3));
+ activity.tempTransition.push(paper.path('M ' + startX + ' ' + startY
+ + 'L ' + endX + ' ' + endY).attr({
+ 'arrow-end' : 'open-wide-long',
+ 'stroke-dasharray' : '- '
+ }));
+ },
+
+
+ /**
+ * Finalise transition drawing.
+ */
+ drawTransitionEndHandler : function(activity, event) {
+ HandlerLib.resetCanvasMode();
+
+ //remove the temporary transition
+ if (activity.tempTransition) {
+ activity.tempTransition.remove();
+ activity.tempTransition = null;
+ }
+
+ var endX = event.pageX - canvas.offset().left;
+ var endY = event.pageY - canvas.offset().top;
+ var endActivity = null;
+ // find the target activity
+ $.each(activities, function(){
+ if (this.items.shape.isPointInside(endX, endY)) {
+ endActivity = this;
+ return false;
+ }
+ });
+
+ if (endActivity) {
+ ActivityLib.drawTransition(activity, endActivity);
+ }
+ }
+};
\ No newline at end of file
Index: lams_central/web/includes/javascript/authoring/authoringMenu.js
===================================================================
RCS file: /usr/local/cvsroot/lams_central/web/includes/javascript/authoring/authoringMenu.js,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ lams_central/web/includes/javascript/authoring/authoringMenu.js 5 Nov 2013 17:37:19 -0000 1.1
@@ -0,0 +1,165 @@
+/**
+ * This file contains methods for menu in Authoring.
+ */
+
+var MenuLib = {
+
+ addBranching : function(){
+ var dialog = $('#infoDialog').text('Place the branching point');
+ dialog.dialog('open');
+
+ var branchingActivity = null;
+ canvas.css('cursor', 'pointer').click(function(event){
+ // pageX and pageY tell event coordinates relative to the whole page
+ // we need relative to canvas
+ var x = event.pageX - canvas.offset().left;
+ var y = event.pageY - canvas.offset().top;
+
+ var isStart = !branchingActivity;
+ var branchingEdge = new ActivityLib.BranchingEdgeActivity(null, x, y, branchingActivity);
+ activities.push(branchingEdge);
+
+ if (isStart) {
+ branchingActivity = branchingEdge.branchingActivity;
+ dialog.text('Place the converge point');
+ } else {
+ dialog.text('');
+ dialog.dialog('close');
+
+ HandlerLib.resetCanvasMode();
+ }
+ });
+ },
+
+ /**
+ * Run when grouping is dropped on canvas. Creates a new grouping activity.
+ */
+ addGrouping : function() {
+ canvas.css('cursor', 'url("../images/grouping.gif"), move').click(function(event){
+ // pageX and pageY tell event coordinates relative to the whole page
+ // we need relative to canvas
+ var x = event.pageX - canvas.offset().left;
+ var y = event.pageY - canvas.offset().top;
+
+ activities.push(new ActivityLib.GroupingActivity(null, x, y));
+ HandlerLib.resetCanvasMode();
+ });
+ },
+
+
+ /**
+ * Run when gate is dropped on canvas. Creates a new gate activity.
+ */
+ addGate : function() {
+ canvas.css('cursor', 'url("../images/stop.gif"), move').click(function(event){
+ // pageX and pageY tell event coordinates relative to the whole page
+ // we need relative to canvas
+ var x = event.pageX - canvas.offset().left;
+ var y = event.pageY - canvas.offset().top;
+
+ activities.push(new ActivityLib.GateActivity(null, x, y));
+ HandlerLib.resetCanvasMode();
+ });
+ },
+
+
+ /**
+ * Opens "Open sequence" dialog where an user can choose a Learning Design to load.
+ */
+ openLearningDesign : function(){
+ var dialog = $('#openLearningDesignDialog');
+ // remove the directory tree, if it remained for last dialog opening
+ $('#learningDesignTree', dialog).empty();
+ dialog.dialog('open');
+
+ // get users' folders and LDs
+ var treeNodes = MenuLib.getFolderContents();
+ // genearate folder tree for the widget
+ var tree = new YAHOO.widget.TreeView('learningDesignTree', treeNodes);
+ // store the tree in the dialog's data
+ dialog.dialog('option', 'ldTree', tree);
+ // make folder contents load dynamically on open
+ tree.setDynamicLoad(function(node, callback){
+ // load subfolder contents
+ var childNodeData = MenuLib.getFolderContents(node.data.folderID);
+ if (childNodeData) {
+ $.each(childNodeData, function(){
+ // create and add a leaf
+ new YAHOO.widget.TextNode(this, node);
+ });
+ }
+
+ // required by YUI
+ callback();
+ });
+
+ tree.singleNodeHighlight = true;
+ tree.subscribe('clickEvent', function(event){
+
+ if (!event.node.data.learningDesignId){
+ // it is a folder
+ return false;
+ }
+
+ // display "loading" animation and finally LD thumbnail
+ $('.ldChoiceDependentCanvasElement').css('display', 'none');
+ if (event.node.highlightState == 0) {
+ $('#ldScreenshotLoading').css('display', 'inline');
+ // get the image of the chosen LD
+ $('#ldScreenshotAuthor').attr('src', LD_THUMBNAIL_URL_BASE + event.node.data.learningDesignId);
+ $('#ldScreenshotAuthor').css('width', 'auto').css('height', 'auto');
+ } else {
+ // toggleCanvasResize(CANVAS_RESIZE_OPTION_NONE);
+ }
+ });
+ tree.subscribe('clickEvent',tree.onEventToggleHighlight);
+ tree.render();
+
+ // expand the first (user) folder
+ tree.getRoot().children[0].expand();
+ },
+
+
+ /**
+ * Loads subfolders and LDs from the server.
+ */
+ getFolderContents : function(folderID) {
+ var result = null;
+
+ $.ajax({
+ url : LAMS_URL + 'home.do',
+ data : {
+ 'method' : 'getFolderContents',
+ 'folderID' : folderID
+ },
+ cache : false,
+ async: false,
+ dataType : 'json',
+ success : function(response) {
+ result = [];
+
+ // parse the response; extract folders and LDs
+ if (response.folders) {
+ $.each(response.folders, function(){
+ result.push({'type' : 'text',
+ 'label' : this.isRunSequencesFolder ?
+ LABEL_RUN_SEQUENCES_FOLDER : this.name,
+ 'folderID' : this.folderID
+ });
+ });
+ }
+ if (response.learningDesigns) {
+ $.each(response.learningDesigns, function(){
+ result.push({'type' : 'text',
+ 'label' : this.name,
+ 'isLeaf' : true,
+ 'learningDesignId' : this.learningDesignId
+ });
+ });
+ }
+ }
+ });
+
+ return result;
+ }
+};
\ No newline at end of file