Index: lams_central/web/authoring/authoring.jsp =================================================================== diff -u -r78d3840bba4ebbc2d65e9d8d064f3fc209b189ab -rcaf0b925fc9dc4ec29fa3c462afceac023b0b552 --- lams_central/web/authoring/authoring.jsp (.../authoring.jsp) (revision 78d3840bba4ebbc2d65e9d8d064f3fc209b189ab) +++ lams_central/web/authoring/authoring.jsp (.../authoring.jsp) (revision caf0b925fc9dc4ec29fa3c462afceac023b0b552) @@ -190,14 +190,6 @@ // PropertyLib - - OK_BUTTON : '', - - CLEAR_ALL_BUTTON : '', - - REFRESH_BUTTON : '', - - REMOVE_CONDITION_BUTTON : '', PROPERTIES_DIALOG_TITLE : '', @@ -309,9 +301,8 @@
  • -
  • -
  • -
  • +
  • +
  • @@ -545,7 +536,7 @@ -
    +
    @@ -565,12 +556,24 @@ + + +
    -
    -
    + +
    +
    +
    + +
    +
    +
    @@ -763,7 +766,7 @@ -
    + @@ -811,17 +814,17 @@ -
    + -
    + -
    + @@ -936,8 +939,8 @@
    @@ -978,6 +984,37 @@ +
    +
    + + + + +
    + +
    + + + + + +
    +
    Index: lams_central/web/css/authoring.css =================================================================== diff -u -r78d3840bba4ebbc2d65e9d8d064f3fc209b189ab -rcaf0b925fc9dc4ec29fa3c462afceac023b0b552 --- lams_central/web/css/authoring.css (.../authoring.css) (revision 78d3840bba4ebbc2d65e9d8d064f3fc209b189ab) +++ lams_central/web/css/authoring.css (.../authoring.css) (revision caf0b925fc9dc4ec29fa3c462afceac023b0b552) @@ -36,7 +36,7 @@ .dialogContainer .modal-body { height : 100%; max-height: calc(100% - 60px); - padding: 0; + padding: 5px; } .dialogContainer button { @@ -47,7 +47,7 @@ outline: none; } -.dialogContainer button .fa { +.dialogContainer .modal-header button .fa { font-size: 16px; margin-left: 10px; } @@ -71,15 +71,11 @@ } -div.propertiesDialogContainer .modal-header, -div#groupNamingDialog .modal-header, -div#exportLDDialog .modal-header { +div.smallHeader .modal-header { padding: 5px; } -div.propertiesDialogContainer .modal-title, -div#groupNamingDialog .modal-title, -div#exportLDDialog .modal-title { +div.smallHeader .modal-title { font-size: 16px; } @@ -108,8 +104,11 @@ width: 99%; } -div#groupNamingDialog .btn-group { - margin: 5px 0; +div#groupNamingDialog .btn-group, +div#gtbDialog .btn-group, +div#ctbDialog .btn-group, +div#outputConditionsDialog .btn-group { + margin: 10px 0 10px 10px; } input.groupName { @@ -164,11 +163,12 @@ div#ldStoreDialogContents td#ldStoreDialogTreeCell { padding: 2px 2px 0px 5px; vertical-align: top; - width: 200px; border-right: thin dotted #2E6E9E; + width: 200px; } div#ldStoreDialogContents div#ldStoreDialogTree { + width: 200px; overflow: auto; } @@ -228,12 +228,15 @@ margin-left: 10px; } +div.branchMappingDialog .container-fluid { + padding-right: 0; +} div.branchMappingDialog > table { width: 100%; height: 98%; table-layout: fixed; - border-collapse: collapse; + border-collapse: collapse;outputConditionsDialogContents } div.branchMappingDialog td { @@ -258,58 +261,58 @@ div.branchMappingDialog .branchMappingButton { width: 40%; - height: 25px; display: block; margin: auto; - margin-bottom: 20px; + margin-top: 10px; + margin-bottom: 10px; } div.branchMappingDialog td.branchMappingListCell div { text-align: left; cursor: pointer; } - -div#outputConditionsDialog div#complexConditions > div { +div#outputConditionsDialogContents div#complexConditions > div { font-weight: bold; margin: 10px 0 0 2px; } -div#outputConditionsDialog select { +div#outputConditionsDialogContents select { margin-bottom: 10px; + width: 95%; } -div#outputConditionsDialog .spinner { +div#outputConditionsDialogContents .spinner { width: 40px; } -div#outputConditionsDialog div#multiRangeDiv { +div#outputConditionsDialogContents div#multiRangeDiv { display: inline-block; } -div#outputConditionsDialog #rangeAddButton { +div#outputConditionsDialogContents #rangeAddButton { margin-left: 10px; } -div#outputConditionsDialog table#rangeConditions { +div#outputConditionsDialogContents table#rangeConditions { width: 100%; margin-top: 15px; border-collapse: collapse; text-align: center; } -div#outputConditionsDialog table#rangeConditions tr td, -div#outputConditionsDialog table#rangeConditions tr th { +div#outputConditionsDialogContents table#rangeConditions tr td, +div#outputConditionsDialogContents table#rangeConditions tr th { padding: 3px; border: black thin solid; cursor: pointer; } -div#outputConditionsDialog table#rangeConditions input { +div#outputConditionsDialogContents table#rangeConditions input { width: 95%; } -div#outputConditionsDialog tr.selected { +div#outputConditionsDialogContents tr.selected { background-color: #dfeffc; } Index: lams_central/web/includes/javascript/authoring/authoringGeneral.js =================================================================== diff -u -r78d3840bba4ebbc2d65e9d8d064f3fc209b189ab -rcaf0b925fc9dc4ec29fa3c462afceac023b0b552 --- lams_central/web/includes/javascript/authoring/authoringGeneral.js (.../authoringGeneral.js) (revision 78d3840bba4ebbc2d65e9d8d064f3fc209b189ab) +++ lams_central/web/includes/javascript/authoring/authoringGeneral.js (.../authoringGeneral.js) (revision caf0b925fc9dc4ec29fa3c462afceac023b0b552) @@ -686,12 +686,19 @@ 'autoOpen' : false, 'resizable' : false, 'draggable' : false, - 'open' : function(){ - var dialog = $(this); + var dialog = $(this), + treeHeight = Math.max(90, $(window).height() - 325) + 'px'; $('.modal-dialog', dialog).width(Math.max(500, $(window).width() - 50)); - $('.modal-content', dialog).height(Math.max(375, $(window).height() - 65)); - $('#ldStoreDialogTree', dialog).css('max-height', Math.max(90, $(window).height() - 325) + 'px'); + $('#ldStoreDialogTree', layout.ldStoreDialog).css({ + 'height' : treeHeight, + 'max-height' : treeHeight + }); + // limit size of the canvas so dialog does not resize after SVG loads + $('#ldStoreDialogCanvasDiv', dialog).css({ + 'max-width' : $(window).width() - 275 + 'px', + 'max-height': $(window).height() - 190 + 'px', + }); GeneralLib.showLearningDesignThumbnail(); $('#ldStoreDialogLeftButtonContainer button', dialog).prop('disabled', true); @@ -710,7 +717,7 @@ $('.modal-title', layout.ldStoreDialog).text(dialogTitle); var rightButtons = $('#ldStoreDialogRightButtonContainer', layout.ldStoreDialog); $('button', rightButtons).hide(); - $('#ldStoreDialogNameContainer', layout.ldStoreDialog).hide(); + $('#ldStoreDialogNameContainer, #ldStoreDialogImportPartFrame', layout.ldStoreDialog).hide(); $(shownElementIDs, layout.ldStoreDialog).show(); }, /** @@ -864,7 +871,7 @@ if (!frame.attr('src')){ return; } - frame.css('visibility', 'visible').height(+frame.contents().find('svg').attr('height') + 40); + frame.height(+frame.contents().find('svg').attr('height') + 40); }); // there should be no focus, just highlight @@ -2592,8 +2599,6 @@ showLearningDesignThumbnail : function(learningDesignID, title) { // display "loading" animation and finally LD thumbnail $('#ldScreenshotAuthor, #ldScreenshotLoading', layout.ldStoreDialog).hide(); - // the "import part" frame can't use "display:none" CSS attribute as its JS won't execute right - $('#ldStoreDialogImportPartFrame', layout.ldStoreDialog).css('visibility', 'hidden'); if (learningDesignID) { if ($('#ldStoreDialogImportPartButton', layout.ldStoreDialog).is(':visible')) { Index: lams_central/web/includes/javascript/authoring/authoringMenu.js =================================================================== diff -u -r78d3840bba4ebbc2d65e9d8d064f3fc209b189ab -rcaf0b925fc9dc4ec29fa3c462afceac023b0b552 --- lams_central/web/includes/javascript/authoring/authoringMenu.js (.../authoringMenu.js) (revision 78d3840bba4ebbc2d65e9d8d064f3fc209b189ab) +++ lams_central/web/includes/javascript/authoring/authoringMenu.js (.../authoringMenu.js) (revision caf0b925fc9dc4ec29fa3c462afceac023b0b552) @@ -272,7 +272,9 @@ $('iframe', this).attr('src', LAMS_URL + 'authoring/exportToolContent.do?method=export&learningDesignID=' + layout.ld.learningDesignID); } - }).click(function(){ + }, false) + .addClass('smallHeader') + .click(function(){ exportLDDialog.modal('hide'); }); $('#exportLDDialogContents').clone().attr('id', null).show().appendTo($('.modal-body', exportLDDialog).empty()); @@ -281,44 +283,6 @@ /** - * Creates a PNG image out of current SVG contents. - */ - exportPNG : function(download){ - ActivityLib.removeSelectEffect(); - - var imageCode = null; - if (!download || layout.conf.supportsDownloadAttribute) { - var crop = MenuLib.getCanvasCrop(); - if (crop.x >= crop.x2) { - return; - } - - var ctx = crop.workspace.getContext('2d'), - w = crop.x2 - crop.x, - // slight adjustment so bottom activities are not clipped - h = crop.y2 - crop.y + 2, - cut = ctx.getImageData(crop.x, crop.y, w, h); - - crop.workspace.width = w; - crop.workspace.height = h; - ctx.putImageData(cut, 0, 0); - - imageCode = crop.workspace.toDataURL("image/png"); - } - if (download) { - $('a', layout.exportImageDialog).attr({ - 'href' : imageCode, - 'download' : (layout.ld.title ? layout.ld.title : 'Untitled') + '.png' - }); - - layout.exportImageDialog.modal('show'); - } else { - return imageCode; - } - }, - - - /** * Creates a SVG image out of current SVG contents. */ exportSVG : function(download){ @@ -459,7 +423,8 @@ */ importLearningDesign : function(){ var dialog = showDialog("dialogImportLearningDesign", { - 'height' : 315, + 'modal' : true, + 'height' : 350, 'width' : 850, 'title' : LABELS.IMPORT_DIALOG_TITLE, 'open' : function() { @@ -468,17 +433,17 @@ $('iframe', dialog).attr('src', LAMS_URL + 'authoring/importToolContent.do?method=import').load(function(){ // override the close function so it works with the dialog, not window this.contentWindow.closeWin = function(){ - dialog.dialog('close'); + dialog.modal('hide'); } }); }, 'close' : function(){ - // stop checking in LD was imported + // stop checking in LD was clearInterval(loadCheckInterval); // completely delete the dialog $(this).remove(); } - }), + }, false), currentLearningDesignID = null, regEx = /learningDesignID=(\d+)/g, // since window.onload does not really work after submitting a form inside the window, @@ -504,7 +469,7 @@ */ importPartLearningDesign : function(){ layout.ldStoreDialog.data('prepareForOpen')(LABELS.IMPORT_PART_DIALOG_TITLE, null, - '#ldStoreDialogImportPartButton, #ldStoreDialogCancelButton', false); + '#ldStoreDialogImportPartButton, #ldStoreDialogCancelButton, #ldStoreDialogImportPartFrame', false); layout.ldStoreDialog.modal('show'); }, Index: lams_central/web/includes/javascript/authoring/authoringProperty.js =================================================================== diff -u -r78d3840bba4ebbc2d65e9d8d064f3fc209b189ab -rcaf0b925fc9dc4ec29fa3c462afceac023b0b552 --- lams_central/web/includes/javascript/authoring/authoringProperty.js (.../authoringProperty.js) (revision 78d3840bba4ebbc2d65e9d8d064f3fc209b189ab) +++ lams_central/web/includes/javascript/authoring/authoringProperty.js (.../authoringProperty.js) (revision caf0b925fc9dc4ec29fa3c462afceac023b0b552) @@ -773,7 +773,7 @@ // for proximity detection throttling (see handlers) propertiesDialog.data('lastRun', 0); // remove close button, add dimming - propertiesDialog.addClass('propertiesDialogContainer') + propertiesDialog.addClass('propertiesDialogContainer smallHeader') .css('opacity', layout.conf.propertiesDialogDimOpacity) .mousemove(HandlerPropertyLib.approachPropertiesDialogHandler) .find('.modal-header button').remove(); @@ -817,8 +817,10 @@ 'modal' : true, 'draggable' : true, 'width' : 400, - 'title' : LABELS.GROUP_NAMING_DIALOG_TITLE - }, false); + 'title' : LABELS.GROUP_NAMING_DIALOG_TITLE, + 'close' : null + }, false) + .addClass('smallHeader'); $('.modal-body', layout.groupNamingDialog).empty().append(groupNamingContent.show()); @@ -827,437 +829,394 @@ layout.dialogs.push(layout.groupNamingDialog); + var branchMappingDialogContents = $('#branchMappingDialogContents').clone().attr('id', null); + $('.branchMappingOKButton', branchMappingDialogContents).click(function(){ + var dialog = layout.groupsToBranchesMappingDialog, + branchingActivity = dialog.data('branchingActivity'), + groupsToBranches = [], + assignedToDefault = false, + defaultBranch = null, + close = true; + + // find references to groups and branches + $('.branchMappingBoundItemCell div, .branchMappingFreeItemCell div', dialog).each(function(){ + var groupUIID = +$(this).attr('uiid'), + boundItem = $(this).data('boundItem'), + branchUIID = boundItem ? +boundItem.attr('uiid') : null, + group = null, + branch = null; + + // look for branch + if (branchUIID) { + $.each(branchingActivity.branches, function(){ + if (branchUIID == this.uiid) { + branch = this; + return false; + } + }); + } else { + // assign to default branch + if (!defaultBranch) { + $.each(branchingActivity.branches, function(){ + if (this.defaultBranch) { + defaultBranch = this; + return false; + } + }); + // fall back to first branch + if (!defaultBranch) { + defaultBranch = branchingActivity.branches[0]; + defaultBranch.defaultBranch = true; + } + } + branch = defaultBranch; + assignedToDefault = true; + } + + // look for group + $.each(branchingActivity.grouping.groups, function(){ + if (groupUIID == this.uiid) { + group = this; + return false; + } + }); + + // add the mapping + groupsToBranches.push({ + 'uiid' : ++layout.ld.maxUIID, + 'group' : group, + 'branch' : branch + }); + }); + + if (assignedToDefault){ + // ask the user if it's OK to assign groups to default branch + close = confirm(LABELS.GROUPS_TO_DEFAULT_BRANCH_CONFIRM); + } + + if (close) { + branchingActivity.groupsToBranches = groupsToBranches; + dialog.modal('hide'); + GeneralLib.setModified(true); + } + }); + + // initialise the dialog buttons + $('.branchMappingAddButton', branchMappingDialogContents).click(function(){ + PropertyLib.addBranchMapping(layout.groupsToBranchesMappingDialog); + }); + $('.branchMappingRemoveButton', branchMappingDialogContents).click(function(){ + PropertyLib.removeBranchMapping(layout.groupsToBranchesMappingDialog); + }); + $('.branchMappingFreeItemHeaderCell', branchMappingDialogContents).text(LABELS.BRANCH_MAPPING_CONDITIONS_HEADER); + $('.branchMappingBoundItemHeaderCell', branchMappingDialogContents).text(LABELS.BRANCH_MAPPING_CONDITION_HEADER); + // initialise dialog for matching groups to branches in branching activities - var gtbDialog = layout.groupsToBranchesMappingDialog = $('#branchMappingDialog') - .clone() - .attr('id','gtbDialog') - .dialog({ + layout.groupsToBranchesMappingDialog = showDialog('gtbDialog',{ 'autoOpen' : false, 'modal' : true, - 'show' : 'fold', - 'hide' : 'fold', - 'position' : { - 'of' : '#canvas' - }, 'width' : 800, - 'height' : 400, 'title' : LABELS.GROUPS_TO_BRANCHES_MATCH_DIALOG_TITLE, - 'buttons' : [ - { - 'text' : LABELS.OK_BUTTON, - 'click' : function() { - var dialog = $(this), - branchingActivity = dialog.dialog('option', 'branchingActivity'), - groupsToBranches = [], - assignedToDefault = false, - defaultBranch = null, - close = true; - - // find references to groups and branches - $('.branchMappingBoundItemCell div, .branchMappingFreeItemCell div', dialog).each(function(){ - var groupUIID = +$(this).attr('uiid'), - boundItem = $(this).data('boundItem'), - branchUIID = boundItem ? +boundItem.attr('uiid') : null, - group = null, - branch = null; - - // look for branch - if (branchUIID) { - $.each(branchingActivity.branches, function(){ - if (branchUIID == this.uiid) { - branch = this; - return false; - } - }); - } else { - // assign to default branch - if (!defaultBranch) { - $.each(branchingActivity.branches, function(){ - if (this.defaultBranch) { - defaultBranch = this; - return false; - } - }); - // fall back to first branch - if (!defaultBranch) { - defaultBranch = branchingActivity.branches[0]; - defaultBranch.defaultBranch = true; - } - } - branch = defaultBranch; - assignedToDefault = true; - } - - // look for group - $.each(branchingActivity.grouping.groups, function(){ - if (groupUIID == this.uiid) { - group = this; - return false; - } - }); - - // add the mapping - groupsToBranches.push({ - 'uiid' : ++layout.ld.maxUIID, - 'group' : group, - 'branch' : branch - }); - }); - - if (assignedToDefault){ - // ask the user if it's OK to assign groups to default branch - close = confirm(LABELS.GROUPS_TO_DEFAULT_BRANCH_CONFIRM); - } - - if (close) { - branchingActivity.groupsToBranches = groupsToBranches; - dialog.dialog('close'); - GeneralLib.setModified(true); - } - } - } - ] + 'close' : null + }, false) + .addClass('smallHeader'); + + $('.modal-body', layout.groupsToBranchesMappingDialog).empty().append(branchMappingDialogContents.show()); + layout.dialogs.push(layout.groupsToBranchesMappingDialog); + + var outputConditionsDialogContents = $('#outputConditionsDialogContents'); + $('#outputConditionsClearAllButton', outputConditionsDialogContents).click(function(){ + // remove all range conditions + var rows = $('#rangeConditions td', layout.outputConditionsDialog).closest('tr'); + rows.each(function(){ + // check for conditions already linked to branches/gate states + if ($(this).data('mappingEntry').branch) { + if (!confirm(LABELS.CLEAR_ALL_CONFIRM)) { + rows = null; + } + return false; + } + }); + + if (rows) { + rows.remove(); + } }); - // initialise buttons and labels - $('.branchMappingAddButton', gtbDialog).button({ - 'icons' : { - 'primary' : 'ui-icon-seek-next' - }, - 'text' : false - }).click(function(){ - PropertyLib.addBranchMapping(gtbDialog); + $('#outputConditionsRemoveButton', outputConditionsDialogContents).click(function(){ + // remove the selected range condition + var selected = $('#rangeConditions tr.selected', layout.outputConditionsDialog); + if (!selected.data('mappingEntry').branch + || confirm(LABELS.REMOVE_CONDITION_CONFIRM)) { + selected.remove(); + } }); - $('.branchMappingRemoveButton', gtbDialog).button({ - 'icons' : { - 'primary' : 'ui-icon-seek-prev' - }, - 'text' : false - }).click(function(){ - PropertyLib.removeBranchMapping(gtbDialog); + + $('#outputConditionsRefreshButton', outputConditionsDialogContents).click(function(){ + // get output definitions again + $(this).data('refreshDefinitions')(); + $(this).data('buildContent')(true); }); - $('.branchMappingFreeItemHeaderCell', gtbDialog).text(LABELS.BRANCH_MAPPING_GROUPS_HEADER); - $('.branchMappingBoundItemHeaderCell', gtbDialog).text(LABELS.BRANCH_MAPPING_GROUP_HEADER); - layout.dialogs.push(gtbDialog); + $('#outputConditionsCancelButton', outputConditionsDialogContents).click(function(){ + layout.outputConditionsDialog.modal('hide'); + }); + $('#outputConditionsOKButton', outputConditionsDialogContents).click(function(){ + var dialog = layout.outputConditionsDialog, + activity = dialog.data('parentObject'); + + // extract created mappings from UI + activity.conditionsToBranches = []; + $('#rangeConditions tr, #complexConditions li', dialog).each(function(){ + // if it's hidden, then another output was selected, so skip it + var mappingEntry = $(this).is(':visible') ? $(this).data('mappingEntry') : null; + if (!mappingEntry) { + return true; + } + + // new UIID for new conditions + if (!mappingEntry.uiid) { + mappingEntry.uiid = ++layout.ld.maxUIID; + } + if (!mappingEntry.condition.conditionUIID) { + mappingEntry.condition.conditionUIID = ++layout.ld.maxUIID; + } + + // range conditions can have their names changed + var input = $('input', this); + if (input.length > 0) { + mappingEntry.condition.displayName = input.val(); + } + activity.conditionsToBranches.push(mappingEntry); + }); + + dialog.modal('hide'); + // go straight to mapping dialog + PropertyLib.openConditionsToBranchesMappingDialog(activity); + }); // initialise dialog for defining input conditions - var outputConditionsDialog = layout.outputConditionsDialog = $('#outputConditionsDialog').dialog({ + layout.outputConditionsDialog = showDialog('outputConditionsDialog',{ 'autoOpen' : false, 'modal' : true, - 'show' : 'fold', - 'hide' : 'fold', - 'position' : { - 'of' : '#canvas' - }, 'width' : 400, 'height' : 400, 'title' : LABELS.CONDITIONS_DIALOG_TITLE, - 'buttons' : [ - { - 'class' : 'outputSelectDependent rangeOutputButton', - 'text' : LABELS.CLEAR_ALL_BUTTON, - 'click' : function() { - // remove all range conditions - var rows = $('#rangeConditions td', this).closest('tr'); - rows.each(function(){ - // check for conditions already linked to branches/gate states - if ($(this).data('mappingEntry').branch) { - if (!confirm(LABELS.CLEAR_ALL_CONFIRM)) { - rows = null; - } - return false; + 'open' : function(){ + $(this).data('buildContent')(); + }, + 'close' : null, + 'data' : { + /** + * Get output definitions from a Tool activity + */ + 'refreshDefinitions' : function(){ + var dialog = layout.outputConditionsDialog, + activity = dialog.data('parentObject'); + // sets the output definitions and their default value + ActivityLib.getOutputDefinitions(activity.input); + }, + + + /** + * Link output data to UI widgets + */ + 'buildContent' : function(useDefaultConditions) { + var dialog = layout.outputConditionsDialog, + activity = dialog.data('parentObject'), + outputSelect = $('#outputSelect', dialog), + emptyOption = $('option[value="none"]', outputSelect).attr('selected', 'selected'), + // conditions can have names like "output.name#6", but real output names do not have a suffix + outputName = activity.conditionsToBranches && activity.conditionsToBranches.length > 0 + ? activity.conditionsToBranches[0].condition.name.split('#')[0] : null; + // remove all previously defined outputs + $('option[value!="none"]', outputSelect).remove(); + + if (!activity.input.outputDefinitions) { + dialog.data('refreshDefinitions')(); + } + + if (activity.input.outputDefinitions) { + // build output dropdown and bind data to each option + $.each(activity.input.outputDefinitions,function(){ + var suffix = ''; + switch(this.type) { + case 'OUTPUT_COMPLEX' : + suffix = LABELS.COMPLEX_OUTPUT_SUFFIX; + break; + + case 'OUTPUT_LONG' : + suffix = LABELS.RANGE_OUTPUT_SUFFIX; + break; + }; + + this.toolActivityUIID = activity.input.uiid; + var option = $('