Index: lams_central/web/author2.jsp =================================================================== diff -u -rb78ac844426c4d69e6104349bdf7cae2ecc6644d -r796438a75689e1fd093f305316e14bfcf3f65c55 --- lams_central/web/author2.jsp (.../author2.jsp) (revision b78ac844426c4d69e6104349bdf7cae2ecc6644d) +++ lams_central/web/author2.jsp (.../author2.jsp) (revision 796438a75689e1fd093f305316e14bfcf3f65c55) @@ -7,47 +7,9 @@ Flashless Authoring - + + @@ -58,8 +20,29 @@ +
+
+
+
+ Flow +
+
 
+
+
    +
  • Gate
  • +
  • Branch
  • +
+
+
+ Group +
+
+ + + +
Index: lams_central/web/css/authoring.css =================================================================== diff -u --- lams_central/web/css/authoring.css (revision 0) +++ lams_central/web/css/authoring.css (revision 796438a75689e1fd093f305316e14bfcf3f65c55) @@ -0,0 +1,76 @@ +div#toolbar { + padding: 3px; + height: 27px; +} + +div#toolbar > div { + float: left; + margin-right: 10px; +} + +div#toolbar .ui-button, div#toolbar .split-ui-button { + height: 24px; + font-size: 11px; +} + +div#toolbar .split-ui-button + ul { + z-index: 2; +} + +div#toolbar .split-ui-button + ul span { + font-size: 11px; + color: #2E6E9E; +} + +table#authoringTable { + table-layout: fixed; + width: 100%; +} + +td#layoutCell { + width: 152px; +} + +#groupingButton span { + background: url('../images/icons/group.png') no-repeat 3px 3px; + padding-left: 25px; +} + +td#templateContainerCell { + border: black thin solid; + vertical-align: top; + background-color: rgb(219, 230, 252); +} + +div#templateContainer { + height: 800px; + overflow: auto; +} + +div.template { + height: 40px; + border-bottom: black thin solid; + cursor: pointer; + vertical-align: middle; +} + +div.template img { + display: block; + float: left; + margin: 5px 8px 5px 5px; +} + +div.template div { + float: left; + width: 90px; + padding-top: 10px; + font-size: 10pt; +} + +div.propertiesDialog { + font-size: 12px; +} + +div.propertiesDialog .ui-dialog-titlebar { + padding: 0 0 0 5px; +} \ No newline at end of file Index: lams_central/web/includes/javascript/authoring.js =================================================================== diff -u -r2231143730a8a34f79773076a0c96ecfcb857ba9 -r796438a75689e1fd093f305316e14bfcf3f65c55 --- lams_central/web/includes/javascript/authoring.js (.../authoring.js) (revision 2231143730a8a34f79773076a0c96ecfcb857ba9) +++ lams_central/web/includes/javascript/authoring.js (.../authoring.js) (revision 796438a75689e1fd093f305316e14bfcf3f65c55) @@ -6,20 +6,35 @@ var layout = { 'conf' : { - 'activityWidth' : 125, - 'activityHeight' : 50 + 'activityWidth' : 125, + 'activityHeight' : 50, + 'propertiesDialogDimOpacity' : 0.3, + 'propertiesDialogDimThreshold' : 100, + 'propertiesDialogDimThrottle' : 100 }, + 'defs' : { + 'bin' : 'M 830 700 h -50 l 10 50 h 30 Z', + 'transArrow' : ' l 10 15 a 25 25 0 0 0 -20 0 z' + }, + 'colors' : { + 'activity' : '#A9C8FD', + 'transition' : 'rgb(119,126,157)', + 'binActive' : 'red', + 'selectEffect' : 'blue' + }, 'items' : { - 'bin' : null + 'bin' : null, + 'selectedActivity' : null, + 'propertiesDialogDimLastRun' : 0 } }; $(document).ready(function() { paper = Raphael('canvas'); canvas = $('#canvas'); + initLayout(); initTemplates(); - layout.items.bin = paper.path('M 830 700 h -50 l 10 50 h 30 Z'); }); @@ -30,6 +45,7 @@ 'revert' : 'invalid', 'distance' : 20, 'scroll' : false, + 'scope' : 'template', 'helper' : function(event){ var helper = $(this).clone().css({ 'border' : 'thin black solid', @@ -43,33 +59,82 @@ canvas.droppable({ 'tolerance' : 'touch', - 'accept' : function (draggable) { - return true; - }, + 'scope' : 'template', 'drop' : function (event, draggable) { ActivityUtils.addActivity(draggable); } }); } +function initLayout() { + layout.items.bin = paper.path(layout.defs.bin); + + $('.ui-button').button(); + $(".split-ui-button").each(function(){ + 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 : "right top", + at : "right bottom", + of : $(this).parent() + }); + $(document).one("click", function() { + menu.hide(); + }); + return false; + }); + } + }); + }); + + + $('#groupingButton').click(function(){ + canvas.css('cursor', 'url("images/grouping.gif"), move').click(function(event){ + var x = event.pageX - canvas.offset().left; + var y = event.pageY - canvas.offset().top; + + ActivityUtils.addGrouping(x, y); + CanvasHandlers.resetCanvasMode(); + }); + }); + + CanvasHandlers.resetCanvasMode(); +} + + var ActivityUtils = { + addActivity : function(template) { $(template.helper).remove(); var activityId = ++maxActivityId; - var activity = new Activity(activityId); + var activity = new Activity(activityId, 'tool'); activities.push(activity); var canvasOffset = canvas.offset(); paper.setStart(); - var shape = activity.shape = paper.rect( + var shape = paper.rect( template.offset.left - canvasOffset.left, template.offset.top - canvasOffset.top, layout.conf.activityWidth, layout.conf.activityHeight) .attr({ - 'fill' : '#A9C8FD' + 'fill' : layout.colors.activity }); paper.image($('img', template.draggable).attr('src'), shape.attr('x') @@ -79,14 +144,50 @@ .attr('y') + 40, $('div', template.draggable).text()); activity.items = paper.setFinish(); + activity.items.shape = shape; activity.addDecoration(); activity.addEffects(); }, + addGrouping : function(x, y) { + var activityId = ++maxActivityId; + var activity = new Activity(activityId, 'group'); + activities.push(activity); + + + 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'); + + activity.items = paper.setFinish(); + activity.items.shape = shape; + activity.addDecoration(); + activity.addEffects(); + }, + + removeActivity : function(activity) { if (activity.fromTransition) { - activity.fromTransition.toActivity.toTransition = null; + var toActivity = activity.fromTransition.toActivity; + if (activity.type == 'group' && toActivity.items.groupingEffect) { + toActivity.items.groupingEffect.remove(); + toActivity.items.groupingEffect = null; + } + toActivity.toTransition = null; activity.fromTransition.remove(); } if (activity.toTransition){ @@ -107,27 +208,27 @@ toActivity.toTransition.remove(); } - var startX = fromActivity.shape.attr('x') + fromActivity.shape.attr('width') / 2; - var startY = fromActivity.shape.attr('y') + fromActivity.shape.attr('height') / 2; - var endX = toActivity.shape.attr('x') + toActivity.shape.attr('width') / 2; - var endY = toActivity.shape.attr('y') + toActivity.shape.attr('height') / 2; + var startX = fromActivity.items.shape.attr('x') + fromActivity.items.shape.attr('width') / 2; + var startY = fromActivity.items.shape.attr('y') + fromActivity.items.shape.attr('height') / 2; + var endX = toActivity.items.shape.attr('x') + toActivity.items.shape.attr('width') / 2; + var endY = toActivity.items.shape.attr('y') + toActivity.items.shape.attr('height') / 2; paper.setStart(); paper.path('M ' + startX + ' ' + startY + ' L ' + endX + ' ' + endY) .attr({ - 'stroke' : 'rgb(119,126,157)', + 'stroke' : layout.colors.transition, 'stroke-width' : 2 }); 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 + ' l 10 15 a 25 25 0 0 0 -20 0 z', + var arrowPath = Raphael.transformPath('M ' + arrowX + ' ' + arrowY + layout.defs.transArrow, 'R ' + angle + ' ' + arrowX + ' ' + arrowY); paper.path(arrowPath) .attr({ - 'stroke' : 'rgb(119,126,157)', - 'fill' : 'rgb(119,126,157)' + 'stroke' : layout.colors.transition, + 'fill' : layout.colors.transition }); transition = paper.setFinish(); @@ -142,18 +243,156 @@ }; CanvasHandlers.dragItemsStartHandler(transition, this, mouseupHandler, event, x, y) }); + + if (fromActivity.type == 'group') { + ActivityUtils.addGroupingEffect(toActivity); + } }, 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(); + }, + + + addSelectEffect : function (activity) { + if (!activity.items.selectEffect) { + var shape = activity.items.shape; + + activity.items.selectEffect = paper.rect( + shape.attr('x') - 7, + shape.attr('y') - 7, + layout.conf.activityWidth + 14, + layout.conf.activityHeight + 14) + .attr({ + 'stroke' : layout.colors.selectEffect, + 'stroke-dasharray' : '-' + }); + activity.items.push(activity.items.selectEffect); + + layout.items.selectedActivity = activity; + + var propertiesDialog = activity.propertiesDialog; + if (!activity.propertiesDialog) { + propertiesDialog = ActivityUtils.addPropertiesDialog(activity); + } + + propertiesDialog.dialog('open'); + } + }, + + + 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); + } + }, + + + addPropertiesDialog : function(activity) { + var propertiesDialog = activity.propertiesDialog = + $('
Properties go here
') + .appendTo('body') + .dialog({ + 'closeOnEscape' : false, + 'position' : { + 'my' : 'left top', + 'at' : 'left top', + 'of' : '#canvas' + }, + 'resizable' : false, + 'title' : 'Properties' + }); + propertiesDialog.container = propertiesDialog.closest('.ui-dialog'); + propertiesDialog.container.addClass('propertiesDialog') + .css('opacity', layout.conf.propertiesDialogDimOpacity) + .mousemove(CanvasHandlers.approachPropertiesDialogHandler) + .find('.ui-dialog-titlebar-close').remove(); + + return propertiesDialog; } }; var CanvasHandlers = { + resetCanvasMode : function(){ + canvas.css('cursor', 'default') + .off('click') + .click(CanvasHandlers.unselectActivityHandler) + .off('mousemove') + .mousemove(CanvasHandlers.approachPropertiesDialogHandler); + }, + + + approachPropertiesDialogHandler : function(event) { + var thisRun = new Date().getTime(); + if (thisRun - layout.items.propertiesDialogDimLastRun < layout.conf.propertiesDialogDimThrottle){ + return; + } + layout.items.propertiesDialogDimLastRun = thisRun; + + var activity = layout.items.selectedActivity; + if (activity && activity.propertiesDialog) { + var dialog = $(activity.propertiesDialog.container), + dialogPosition = dialog.offset(), + dialogStartX = dialogPosition.left, + dialogStartY = dialogPosition.top, + dialogEndX = dialogStartX + dialog.width(), + dialogEndY = dialogStartY + dialog.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; + + dialog.css('opacity', opacity); + } + }, + + + selectActivityHandler : function(event, activity) { + if (activity != layout.items.selectedActivity) { + CanvasHandlers.unselectActivityHandler(event); + ActivityUtils.addSelectEffect(activity); + } + event.preventDefault(); + }, + + + unselectActivityHandler : function(event) { + var defaultPrevented = event.originalEvent ? + event.originalEvent.defaultPrevented : event.defaultPrevented; + if (!defaultPrevented) { + var selectedActivity = layout.items.selectedActivity; + if (selectedActivity) { + selectedActivity.items.selectEffect.remove(); + selectedActivity.items.selectEffect = null; + + if (selectedActivity.propertiesDialog) { + selectedActivity.propertiesDialog.dialog('close'); + } + layout.items.selectedActivity = null; + } + } + }, + + dragItemsStartHandler : function(items, draggedElement, mouseupHandler, event, startX, startY) { items.toFront(); items.attr('cursor', 'move'); @@ -163,7 +402,7 @@ }); items.mouseup(function(){ - canvas.off('mousemove'); + CanvasHandlers.resetCanvasMode(); this.unmouseup(); layout.items.bin.attr('fill', 'transparent'); @@ -177,21 +416,25 @@ var dy = event.pageY - startY; items.transform('t' + dx + ' ' + dy); + if (items.groupingEffect) { + items.groupingEffect.toBack(); + } + if (Raphael.isBBoxIntersect(layout.items.bin.getBBox(), items.getBBox())) { - layout.items.bin.attr('fill', 'red'); + layout.items.bin.attr('fill', layout.colors.binActive); } else { layout.items.bin.attr('fill', 'transparent'); } }, dragActivityEndHandler : function(activity) { - if (Raphael.isBBoxIntersect(layout.items.bin.getBBox(), activity.shape.getBBox())) { + if (Raphael.isBBoxIntersect(layout.items.bin.getBBox(), activity.items.shape.getBBox())) { ActivityUtils.removeActivity(activity); return; } - var transformation = activity.shape.attr('transform'); + var transformation = activity.items.shape.attr('transform'); if (transformation.length > 0) { activity.items.forEach(function(elem) { elem.attr({ @@ -202,6 +445,9 @@ } activity.items.transform(''); + if (activity.items.groupingEffect) { + activity.items.groupingEffect.toBack(); + } if (activity.fromTransition) { ActivityUtils.drawTransition(activity, activity.fromTransition.toActivity); } @@ -275,7 +521,7 @@ var endY = event.pageY - canvas.offset().top; var endActivity = null; $.each(activities, function(){ - if (this.shape.isPointInside(endX, endY)) { + if (this.items.shape.isPointInside(endX, endY)) { endActivity = this; return false; } @@ -288,8 +534,9 @@ }; -function Activity(id) { +function Activity(id, type) { this.id = id; + this.type = type; this.items = paper.set(); this.addEffects = function(){ @@ -304,6 +551,9 @@ }; CanvasHandlers.dragItemsStartHandler(activity.items, this, mouseupHandler, event, x, y); } + }) + .click(function(event){ + CanvasHandlers.selectActivityHandler(event, activity); }); };