Index: lams_central/web/author2.jsp =================================================================== diff -u -r3764cd835f0cd39d0a151f12185ae229e9aaff37 -r77fdf7d8fee9946573a774963d4904acf62976d9 --- lams_central/web/author2.jsp (.../author2.jsp) (revision 3764cd835f0cd39d0a151f12185ae229e9aaff37) +++ lams_central/web/author2.jsp (.../author2.jsp) (revision 77fdf7d8fee9946573a774963d4904acf62976d9) @@ -89,8 +89,11 @@ + + +
-
Open sequence
+
Open sequence
@@ -113,6 +116,8 @@ + +
@@ -150,6 +155,7 @@
+
@@ -160,9 +166,63 @@ + + + + + + + + + + + + + + + + + + + + + + +
+ Grouping type: + + +
+ Number of groups: + + + +
+ Number of learners: + + + +
+ Equal group sizes? + + +
+ View learners before selection? + + +
+
Name Groups
+
- + +
@@ -175,7 +235,7 @@
- Title: + Type:
+ \ No newline at end of file Index: lams_central/web/css/authoring.css =================================================================== diff -u -r3764cd835f0cd39d0a151f12185ae229e9aaff37 -r77fdf7d8fee9946573a774963d4904acf62976d9 --- lams_central/web/css/authoring.css (.../authoring.css) (revision 3764cd835f0cd39d0a151f12185ae229e9aaff37) +++ lams_central/web/css/authoring.css (.../authoring.css) (revision 77fdf7d8fee9946573a774963d4904acf62976d9) @@ -13,7 +13,7 @@ /**** Dialog styles ****/ .ui-dialog { - font-size: 12px; + font-size: 12px !important; } div.dialogContainer, .ldChoiceDependentCanvasElement, @@ -33,10 +33,22 @@ padding: 0 0 0 5px; } +input[name="propertiesContentFieldGroupDivide"] { + margin-right: 10px; +} +input.propertiesContentFieldLearnerCount, input.propertiesContentFieldGroupCount { + width: 40px; +} + +input.groupName { + margin-bottom: 5px; + width: 100%; +} + + div#infoDialog { font-weight: bold; - display: none; } Index: lams_central/web/includes/javascript/authoring/authoringActivity.js =================================================================== diff -u -r3764cd835f0cd39d0a151f12185ae229e9aaff37 -r77fdf7d8fee9946573a774963d4904acf62976d9 --- lams_central/web/includes/javascript/authoring/authoringActivity.js (.../authoringActivity.js) (revision 3764cd835f0cd39d0a151f12185ae229e9aaff37) +++ lams_central/web/includes/javascript/authoring/authoringActivity.js (.../authoringActivity.js) (revision 77fdf7d8fee9946573a774963d4904acf62976d9) @@ -26,10 +26,19 @@ /** * Constructor for a Grouping Activity. */ - GroupingActivity : function(id, x, y, title) { + GroupingActivity : function(id, x, y, title, groupingID, groupingType, groupDivide, groupCount, learnerCount, + equalSizes, viewLearners, groupNames) { this.id = id; + this.groupingID = groupingID; this.type = 'grouping'; this.title = title; + this.groupingType = groupingType || 'random'; + this.groupDivide = groupDivide || 'groups'; + this.groupCount = groupCount || 2; + this.learnerCount = learnerCount || 1; + this.equalSizes = equalSizes || false; + this.viewLearners = viewLearners || false; + this.groupNames = groupNames || []; this.transitions = { 'from' : [], 'to' : [] @@ -242,24 +251,36 @@ */ loadPropertiesDialogContent : { tool : function() { - var activity = this; - var content = activity.propertiesContent; + var activity = this, + content = activity.propertiesContent; if (!content) { // first run, create the content - content = activity.propertiesContent = $('#propertiesContentTool').clone().show(); + content = activity.propertiesContent = $('#propertiesContentTool').clone().attr('id', null).show(); $('.propertiesContentFieldTitle', content).val(activity.title); $('input, select', content).change(function(){ // extract changed properties and redraw the activity - activity.title = $('.propertiesContentFieldTitle', activity.propertiesContent).val(); + var redrawNeeded = false, + newTitle = $('.propertiesContentFieldTitle', activity.propertiesContent).val(); + if (newTitle != activity.title) { + activity.title = newTitle; + redrawNeeded = true; + } + activity.grouping = $('.propertiesContentFieldGrouping option:selected', activity.propertiesContent) .data('grouping'); - activity.offline = $('.propertiesContentFieldOffline', activity.propertiesContent) - .is(':checked'); activity.defineInMonitor = $('.propertiesContentFieldDefineMonitor', activity.propertiesContent) - .is(':checked'); + .is(':checked'); + var newOfflineValue = $('.propertiesContentFieldOffline', activity.propertiesContent) + .is(':checked'); + if (newOfflineValue != activity.offline) { + activity.offline = newOfflineValue; + redrawNeeded = true; + } - activity.draw(); + if (redrawNeeded) { + activity.draw(); + } }); } @@ -285,39 +306,111 @@ grouping : function() { - var activity = this; - var content = activity.propertiesContent; + var activity = this, + content = activity.propertiesContent; + if (!content) { + + // make onChange function a local variable, because it's used several times + var changeFunction = function(){ + // extract changed properties and redraw the activity, if needed + var redrawNeeded = false, + newTitle = $('.propertiesContentFieldTitle', activity.propertiesContent).val(); + if (newTitle != activity.title) { + activity.title = newTitle; + redrawNeeded = true; + } + + activity.groupingType = $('.propertiesContentFieldGroupingType', activity.propertiesContent).val(); + + $('input[name="propertiesContentFieldGroupDivide"]', activity.propertiesContent).each(function(){ + // enable/disable division types, depending on radio buttons next to them + $(this).next().find('.spinner').spinner('option', 'disabled', !$(this).is(':checked')); + }) + // hide group/learner division with some grouping types + .add($('.propertiesContentFieldLearnerCount', activity.propertiesContent).closest('tr')) + .css('display', activity.groupingType == 'monitor' ? 'none' : ''); + + $('.propertiesContentFieldEqualSizes, .propertiesContentFieldViewLearners', activity.propertiesContent) + .closest('tr').css('display', activity.groupingType == 'learner' ? '' : 'none'); + + activity.groupDivide = activity.groupingType == 'monitor' || + $('.propertiesContentFieldGroupCountEnable', activity.propertiesContent).is(':checked') ? + 'groups' : 'learners'; + $('.propertiesContentFieldNameGroups', activity.propertiesContent).css('display', + activity.groupDivide == 'groups' ? '' : 'none'); + + activity.groupCount = $('.propertiesContentFieldGroupCount', activity.propertiesContent).val(); + activity.learnerCount = $('.propertiesContentFieldLearnerCount', activity.propertiesContent).val(); + activity.equalSizes = $('.propertiesContentFieldEqualSizes', activity.propertiesContent).is(':checked'); + activity.viewLearners = $('.propertiesContentFieldViewLearners', activity.propertiesContent).is(':checked'); + + if (redrawNeeded) { + activity.draw(); + } + }; + // first run, create the content - content = activity.propertiesContent = $('#propertiesContentGrouping').clone().show(); + content = activity.propertiesContent = $('#propertiesContentGrouping').clone().attr('id', null).show(); + + // init widgets $('.propertiesContentFieldTitle', content).val(activity.title); - - $('input, select', content).change(function(){ - // extract changed properties and redraw the activity - activity.title = $('.propertiesContentFieldTitle', activity.propertiesContent).val(); - activity.draw(); + $('.propertiesContentFieldGroupingType', content).val(activity.groupingType); + if (activity.groupDivide == 'learners') { + $('.propertiesContentFieldLearnerCountEnable', content).attr('checked', 'checked'); + } else { + $('.propertiesContentFieldGroupCountEnable', content).attr('checked', 'checked'); + } + + // create groups/learners spinners + $('.propertiesContentFieldGroupCount', content).spinner({ + 'min' : 2, + 'disabled' : activity.groupDivide == 'learners' + }).spinner('value', activity.groupCount) + .on('spinchange', changeFunction); + + $('.propertiesContentFieldLearnerCount', content).spinner({ + 'min' : 1, + 'disabled' : activity.groupDivide == 'groups' + }).spinner('value', activity.learnerCount) + .on('spinchange', changeFunction); + + $('.propertiesContentFieldEqualSizes').attr('checked', activity.equalSizes ? 'checked' : null); + $('.propertiesContentFieldViewLearners').attr('checked', activity.viewLearners ? 'checked' : null); + $('.propertiesContentFieldNameGroups', content).button().click(function(){ + ActivityLib.openGroupNamingDialog(activity); }); + + $('input, select', content).change(changeFunction); + changeFunction(); } }, gate : function() { - var activity = this; - var content = activity.propertiesContent; + var activity = this, + content = activity.propertiesContent; if (!content) { // first run, create the content - content = activity.propertiesContent = $('#propertiesContentGate').clone().show(); + content = activity.propertiesContent = $('#propertiesContentGate').clone().attr('id', null).show(); $('.propertiesContentFieldTitle', content).val(activity.title); + $('.propertiesContentFieldGateType', content).val(activity.gateType); $('input, select', content).change(function(){ // extract changed properties and redraw the activity - activity.title = $('.propertiesContentFieldTitle', activity.propertiesContent).val(); + var redrawNeeded = false, + newTitle = $('.propertiesContentFieldTitle', activity.propertiesContent).val(); + if (newTitle != activity.title) { + activity.title = newTitle; + redrawNeeded = true; + } activity.gateType = $('.propertiesContentFieldGateType', activity.propertiesContent).val(); - activity.draw(); + + if (redrawNeeded) { + activity.draw(); + } }); } - - $('.propertiesContentFieldGateType', activity.propertiesContent).val(activity.gateType); } }, @@ -762,5 +855,25 @@ translateEventOnCanvas : function(event) { return [event.pageX + canvas.scrollLeft() - canvas.offset().left, event.pageY + canvas.scrollTop() - canvas.offset().top]; + }, + + + /** + * Fills group naming dialog with existing group names and opens it. + */ + openGroupNamingDialog : function(activity) { + var dialog = layout.items.groupNamingDialog; + // remove existing entries and add reference to the initiating activity + dialog.empty().dialog('option', 'activity', activity); + + for (var groupIndex = 1; groupIndex <= activity.groupCount; groupIndex++) { + // generate group names if they do not exist + var groupName = groupIndex > activity.groupNames.length ? + 'Group ' + groupIndex : activity.groupNames[groupIndex - 1]; + $('').addClass('groupName').appendTo(dialog).val(groupName); + dialog.append('
'); + } + + dialog.dialog('open'); } }; \ No newline at end of file Index: lams_central/web/includes/javascript/authoring/authoringGeneral.js =================================================================== diff -u -r3764cd835f0cd39d0a151f12185ae229e9aaff37 -r77fdf7d8fee9946573a774963d4904acf62976d9 --- lams_central/web/includes/javascript/authoring/authoringGeneral.js (.../authoringGeneral.js) (revision 3764cd835f0cd39d0a151f12185ae229e9aaff37) +++ lams_central/web/includes/javascript/authoring/authoringGeneral.js (.../authoringGeneral.js) (revision 77fdf7d8fee9946573a774963d4904acf62976d9) @@ -10,11 +10,12 @@ var layout = { 'activities' : null, 'items' : { - 'bin' : null, - 'selectedActivity' : null, - 'propertiesDialog' : null, - 'infoDialog' : null, - 'copiedActivity' : null + 'bin' : null, + 'selectedActivity' : null, + 'propertiesDialog' : null, + 'infoDialog' : null, + 'copiedActivity' : null, + 'groupNamingDialog' : null }, 'toolIcons': { 'grouping' : '../images/grouping.gif', @@ -178,7 +179,7 @@ 'at' : 'left top', 'of' : '#canvas' }, - 'resizable' : false, + 'resizable' : true, 'title' : 'Properties' }); // for proximity detection throttling (see handlers) @@ -190,7 +191,9 @@ .mousemove(HandlerLib.approachPropertiesDialogHandler) .find('.ui-dialog-titlebar-close').remove(); + + // initalise open Learning Design dialog var ldStoreDialog = $('#ldStoreDialog').dialog({ 'autoOpen' : false, @@ -206,7 +209,6 @@ 'buttons' : [ { 'text' : 'Open', - 'id' : 'openLDButton', 'click' : function() { var dialog = $(this); var tree = dialog.dialog('option', 'ldTree'); @@ -223,7 +225,6 @@ }, { 'text' : 'Cancel', - 'id' : 'cancelLDButton', 'click' : function() { $(this).dialog('close'); } @@ -275,21 +276,61 @@ }); tree.subscribe('clickEvent',tree.onEventToggleHighlight); - + // initialise a small info dialog layout.items.infoDialog = $('
').attr('id', 'infoDialog').dialog({ 'autoOpen' : false, - 'height' : 35, 'width' : 290, - 'modal' : false, + 'height' : 35, 'resizable' : false, 'show' : 'fold', 'hide' : 'fold', 'dialogClass': 'dialog-no-title', - 'position' : {my: "right top", + 'position' : { + my: "right top", at: "right top+5px", of: '#canvas' } }); + + + // initialise dialog from group nameing + layout.items.groupNamingDialog = $('
').dialog({ + 'autoOpen' : false, + 'modal' : true, + 'show' : 'fold', + 'hide' : 'fold', + 'position' : { + 'of' : '#canvas' + }, + 'title' : 'Group Naming', + 'buttons' : [ + { + 'text' : 'OK', + 'click' : function() { + var dialog = $(this), + activity = dialog.dialog('option', 'activity'); + + // extract group names from text fields + activity.groupNames = []; + $('input', dialog).each(function(){ + // do not take into account empty group names + var groupName = $(this).val().trim(); + if (groupName) { + activity.groupNames.push(groupName); + } + }); + + dialog.dialog('close'); + } + }, + { + 'text' : 'Cancel', + 'click' : function() { + $(this).dialog('close'); + } + } + ] + }); } @@ -321,7 +362,7 @@ paperWidth = paper.width, paperHeight = paper.height, // helper for finding last activity in a branch - branchToLastActivityMapping = {}; + branchToActivities = {}; // create visual representation of the loaded activities $.each(ld.activities, function() { @@ -340,10 +381,45 @@ // Grouping Activity case 2 : - activity = new ActivityLib.GroupingActivity(activityData.activityID, - activityData.xCoord, - activityData.yCoord, - activityData.activityTitle); + // find extra metadata for this grouping + $.each(ld.groupings, function(){ + var groupingData = this; + if (groupingData.groupingID == activityData.createGroupingID) { + var groupingType = null, + groupNames = []; + + // translate backend grouping type to human readable for better understanding + switch(groupingData.groupingTypeID) { + case 2: + groupingType = 'monitor'; + break; + case 4: + groupingType = 'learner'; + break; + default: + groupingType = 'random'; + break; + }; + // get groups names + $.each(groupingData.groups, function(){ + groupNames.push(this.groupName); + }); + + activity = new ActivityLib.GroupingActivity(activityData.activityID, + activityData.xCoord, + activityData.yCoord, + activityData.activityTitle, + groupingData.groupingID, + groupingType, + groupingData.learnersPerGroup ? 'learners' : 'groups', + groupingData.numberOfGroups, + groupingData.learnersPerGroup, + groupingData.equalNumberOfLearnersPerGroup, + groupingData.viewStudentsBeforeSelection, + groupNames); + return false; + } + }) break; // Gate Activity @@ -396,6 +472,7 @@ $.each(layout.activities, function(){ if (this.type == 'branchingEdge' && activityData.parentActivityID == this.branchingActivity.id) { + // create a branch inside the branching activity this.branchingActivity.branches.push( new ActivityLib.BranchActivity(activityData.activityID, activityData.activityTitle, @@ -412,35 +489,29 @@ return true; } layout.activities.push(activity); + // for later reference + activityData.activity = activity; - // find the branch the activity belongs to + + // store information about the branch the activity belongs to if (activityData.parentActivityID) { - $.each(layout.activities, function(){ - if (this.type == 'branchingEdge' && this.isStart) { - var branchingActivity = this.branchingActivity; - $.each(branchingActivity.branches, function(){ - var branch = this; - // is this the branch? - if (activityData.parentActivityID == branch.id) { - if (activityData.orderID == 1) { - // this is the first activity in the branch - branch.transitionFrom = ActivityLib.drawTransition( - branchingActivity.start, activity, true); - } - - // check if this is the last activity in the branch - var branchData = branchToLastActivityMapping[branch.id]; - if (!branchData || branchData.orderID < activityData.orderID) { - branchToLastActivityMapping[branch.id] = { - 'branch' : branch, - 'orderID' : activityData.orderID, - 'activity' : activity - }; - } - } - }); - } - }); + var branchData = branchToActivities[activityData.parentActivityID]; + if (!branchData) { + branchData = branchToActivities[activityData.parentActivityID] = { + 'lastActivityOrderID' : activityData.orderID, + 'lastActivity' : activity + }; + } + + if (activityData.orderID > branchData.lastActivityOrderID) { + // is it the last activity in the branch? + branchData.lastActivityOrderID = activityData.orderID; + branchData.lastActivity = activity; + } + if (activityData.orderID == 1) { + // is it the first activity in the branch + branchData.firstActivity = activity; + } } // if we do arranging afterwards, paper will be resized anyway @@ -460,11 +531,42 @@ } }); - // draw transitions from last activities in branches to end edge point - $.each(branchToLastActivityMapping, function(branchID, branchData) { - ActivityLib.drawTransition(branchData.activity, branchData.branch.branchingActivity.end, true); + // apply existing groupings to activities + $.each(ld.activities, function(){ + if (this.applyGrouping && this.activity) { + var groupedActivity = this.activity, + groupingID = this.groupingID; + $.each(layout.activities, function(){ + if (this.type == 'grouping' && groupingID == this.groupingID) { + // add reference and redraw the grouped activity + groupedActivity.grouping = this; + groupedActivity.draw(); + return false; + } + }); + } }); + + // draw starting and ending transitions in branches + $.each(layout.activities, function(){ + if (this.type == 'branchingEdge' && this.isStart) { + var branchingActivity = this.branchingActivity; + $.each(branchingActivity.branches, function(){ + var branch = this, + branchData = branchToActivities[branch.id]; + + // add reference to the transition inside branch + branch.transitionFrom = ActivityLib.drawTransition(branchingActivity.start, + branchData.firstActivity, true); + ActivityLib.drawTransition(branchData.lastActivity, branchingActivity.end, true); + }); + } + }); + + // draw transitions from last activities in branches to end edge point + + // draw plain transitions $.each(ld.transitions, function(){ var transition = this,