Index: lams_central/web/css/bootstrap-treeview.css =================================================================== diff -u -r658453b9f8bdfbf78bc9151b2cc711796081abc2 -r2708837c1330f2c5fd30195d17115eadc1264dca --- lams_central/web/css/bootstrap-treeview.css (.../bootstrap-treeview.css) (revision 658453b9f8bdfbf78bc9151b2cc711796081abc2) +++ lams_central/web/css/bootstrap-treeview.css (.../bootstrap-treeview.css) (revision 2708837c1330f2c5fd30195d17115eadc1264dca) @@ -37,7 +37,7 @@ } /* MODFIED FOR LAMS */ -.treeview .roffset10 { - margin-left: -15px !important; +.treeview .treeview-empty { + margin-left: -4px !important; margin-right: 10px !important; } \ No newline at end of file Index: lams_central/web/includes/javascript/addLesson.js =================================================================== diff -u -re1d9ed4b09a58b1da0f50a56642926a00f9673e6 -r2708837c1330f2c5fd30195d17115eadc1264dca --- lams_central/web/includes/javascript/addLesson.js (.../addLesson.js) (revision e1d9ed4b09a58b1da0f50a56642926a00f9673e6) +++ lams_central/web/includes/javascript/addLesson.js (.../addLesson.js) (revision 2708837c1330f2c5fd30195d17115eadc1264dca) @@ -20,9 +20,15 @@ function initLessonTab(){ tree = $('#learningDesignTree'); + // customise treeview label + ldTreeview.LABEL_RUN_SEQUENCES_FOLDER = LABEL_RUN_SEQUENCES_FOLDER; + ldTreeview.init('#learningDesignTree', function(event, node) { + // hide existing LD image $('.ldChoiceDependentCanvasElement').css('display', 'none'); + + // if a LD is selected if (node.state.selected && node.learningDesignId) { $('#lessonNameInput').val(node.label); //focus element only if it's visible in the current viewport (to avoid unwanted scrolling) @@ -32,18 +38,21 @@ // display "loading" animation and finally LD thumbnail loadLearningDesignSVG(node.learningDesignId); } else { + // a folder got selected or LD got deselected $('#lessonNameInput').val(null); toggleCanvasResize(CANVAS_RESIZE_OPTION_NONE); } }, function(event, node) { - // if it's a folder - do nothing - if (!node.learningDesignId) { - return false; + if (!node.learningDesignId){ + if (!node.state.expanded) { + ldTreeview.refresh(tree, node); + } + return; } // start lesson - addLesson(); + addLesson(node.learningDesignId, node.label); }); // ability to start a lesson on pressing Enter button in a lesson name input @@ -269,24 +278,30 @@ } -function addLesson(){ +function addLesson(learningDesignId, lessonName){ // prevent double clicking of Add button if (submitInProgress) { return; } // some validation at first - var lessonName = $('#lessonNameInput').val(); + if (!lessonName) { + lessonName = $('#lessonNameInput').val(); + } if (lessonName){ $('#lessonNameInput').removeClass('errorBorder'); } - var ldNode = tree.treeview('getSelected')[0]; - if (!ldNode || !ldNode.learningDesignId) { + if (!learningDesignId) { + var ldNode = tree.treeview('getSelected')[0]; + learningDesignId = ldNode.learningDesignId; + } + + if (!learningDesignId) { $('#ldNotChosenError').show(); doSelectTab(1); return; } - $('#ldIdField').val(ldNode.learningDesignId); + $('#ldIdField').val(learningDesignId); if (lessonName){ var nameValidator = /^[^<>^*@%$]*$/igm; Index: lams_central/web/includes/javascript/authoring/authoringGeneral.js =================================================================== diff -u -re1d9ed4b09a58b1da0f50a56642926a00f9673e6 -r2708837c1330f2c5fd30195d17115eadc1264dca --- lams_central/web/includes/javascript/authoring/authoringGeneral.js (.../authoringGeneral.js) (revision e1d9ed4b09a58b1da0f50a56642926a00f9673e6) +++ lams_central/web/includes/javascript/authoring/authoringGeneral.js (.../authoringGeneral.js) (revision 2708837c1330f2c5fd30195d17115eadc1264dca) @@ -745,9 +745,6 @@ 'close' : null, 'data' : { 'prepareForOpen' : function(dialogTitle, learningDesignTitle, shownElementIDs, highlightFolder){ - // only Save As uses highlightFolder; otherwise the first folder in top level gets expanded and highlighted - ldTreeview.preselectedFolderPath = highlightFolder && layout.ld.folderPath ? layout.ld.folderPath.slice() : []; - $('#ldStoreDialogNameContainer input', layout.ldStoreDialog).val(learningDesignTitle); $('.modal-title', layout.ldStoreDialog).text(dialogTitle); var rightButtons = $('#ldStoreDialogRightButtonContainer', layout.ldStoreDialog); @@ -928,6 +925,7 @@ layout.ldStoreDialog.data('ldTree', ldTree); ldTreeview.allowInvalidDesigns = true; + ldTreeview.LABEL_RUN_SEQUENCES_FOLDER = LABELS.RUN_SEQUENCES_FOLDER; ldTreeview.init('#ldStoreDialogTree', function(event, node) { var isOpenDialog = $('#ldStoreDialogSaveButton', layout.ldStoreDialog).is(':hidden'), Index: lams_central/web/includes/javascript/learning-design-treeview.js =================================================================== diff -u -re1d9ed4b09a58b1da0f50a56642926a00f9673e6 -r2708837c1330f2c5fd30195d17115eadc1264dca --- lams_central/web/includes/javascript/learning-design-treeview.js (.../learning-design-treeview.js) (revision e1d9ed4b09a58b1da0f50a56642926a00f9673e6) +++ lams_central/web/includes/javascript/learning-design-treeview.js (.../learning-design-treeview.js) (revision 2708837c1330f2c5fd30195d17115eadc1264dca) @@ -1,45 +1,65 @@ var ldTreeview = { + // for authoring, we show invalid designs + // for add lesson and other places we need to choose a real LD, we hide them allowInvalidDesigns : false, - preselectedFolderPath : null, + // for simulating double click as treeview does not support it DOUBLE_CLICK_PERIOD : 1000, nodeLastSelectedTime : null, nodeLastSelectedId : null, + // reference to the rendered treeview ldTree : null, + // can be i18n + LABEL_RUN_SEQUENCES_FOLDER : 'Run sequences', + + /** + * Initialises a Learning Design treeview + */ init : function(targetElementSelector, onNodeClick, onNodeDblClick) { - var ldTree = $(targetElementSelector); - this.ldTree = ldTree; + this.ldTree = $(targetElementSelector); + // get top level folders var mainFolders = ldTreeview.getFolderContents(); + // get contents of the first folder mainFolders[0].nodes = ldTreeview.getFolderContents(mainFolders[0]); - ldTree.treeview({ + // initialise the treeview + this.ldTree.treeview({ data : mainFolders, showBorder : false, + // use Font Awesome icons expandIcon : 'fa fa-folder', collapseIcon : 'fa fa-folder-open', emptyIcon : '', + // this has been added to treeview in pull request #350 + // the JS script was then additionally customised for LAMS lazyLoad : true, lazyLoadFunction : function(parentNode, callback, options) { callback(parentNode, ldTreeview.getFolderContents(parentNode), options); - ldTreeview.selectFolder(parentNode); }, + // run same function on any click onNodeSelected : function(event, node){ldTreeview.onClickInternal(event, node, onNodeClick, onNodeDblClick)}, onNodeUnselected : function(event, node){ldTreeview.onClickInternal(event, node, onNodeClick, onNodeDblClick)} }); }, + /** + * Fetches folders and LDs from back end and parses them for treeview + */ getFolderContents : function(folder) { + // if folder is NULL, then we fetch top folders var folderID = folder ? folder.folderID : null, canSave = folder ? folder.canSave : null, canHaveReadOnly = folder ? folder.canHaveReadOnly : null, + allowInvalidDesigns = this.allowInvalidDesigns, + runSequencesFolderLabel = this.LABEL_RUN_SEQUENCES_FOLDER, result = []; $.ajax({ url : LAMS_URL + 'home/getFolderContents.do', data : { 'folderID' : folderID, - 'allowInvalidDesigns' : this.allowInvalidDesigns + 'allowInvalidDesigns' : allowInvalidDesigns }, cache : false, async: false, @@ -50,7 +70,7 @@ $.each(response.folders, function(index){ // folderID == -2 is courses folder var canSave = this.folderID > 0 && !this.isRunSequencesFolder; - result.push({'text' : (this.isRunSequencesFolder ? LABELS.RUN_SEQUENCES_FOLDER : this.name) + result.push({'text' : (this.isRunSequencesFolder ? runSequencesFolderLabel : this.name) + (canSave ? '' : ' '), 'nodes' : [], 'folderID' : this.folderID, @@ -77,72 +97,53 @@ } }); + // if folder is empty, we need to shift its icon a bit to the right if (result.length === 0) { - folder.icon = 'fa fa-folder-open roffset10'; + folder.icon = 'fa fa-folder-open treeview-empty'; } return result; }, + /** + * Closes a folder and opens it again, fetching fresh data from server. + * Treeview library had to be customised for this. + */ refresh : function(ldTree, node) { node = ldTree.treeview('getNode', node.nodeId); node.nodes = []; ldTree.treeview('collapseNode', node); + // toggleNode was hidded in the original script + // 'refresh' was not recognised in the original script ldTree.treeview('toggleNode', ['refresh', node]); }, + /** + * Handler for a click. + * It detects and simulates a double click too. + */ onClickInternal : function(event, node, onNodeClick, onNodeDblClick) { + // node deselected or other node selected if (event.type != 'nodeSelected' && this.nodeLastSelectedId !== node.nodeId){ this.nodeLastSelectedTime = null; } + // if there is no double click handler or the node was deselected, just run the single click if (!onNodeDblClick || event.type != 'nodeSelected') { if (onNodeClick) { onNodeClick(event, node); } return; } + // if user selected the same node again withing a given timeout, simulate double click var currentTimestamp = event.timeStamp; if (this.nodeLastSelectedId == node.nodeId && this.nodeLastSelectedTime && currentTimestamp - this.nodeLastSelectedTime < this.DOUBLE_CLICK_PERIOD) { onNodeDblClick(event, node); } else if (onNodeClick){ onNodeClick(event, node); } + // update counters for next click this.nodeLastSelectedTime = currentTimestamp; this.nodeLastSelectedId = node.nodeId; - }, - - /** - * Highlights the folder where existing LD already resides - */ - selectFolder : function(folder) { - // if there are no children or stop condition (no path) was reached - if (!this.preselectedFolderPath || !folder.nodes || folder.nodes.length === 0) { - return; - } - var chosenFolder = null; - // are there any steps left? - if (this.preselectedFolderPath.length > 0) { - // look for target folder in children - var folderID = this.preselectedFolderPath.shift(); - $.each(folder.nodes, function(index, child){ - if (folderID == child.folderID) { - chosenFolder = child; - return false; - } - }); - } - // if last piece of folder path was consumed, set stop condition - if (this.preselectedFolderPath.length === 0) { - this.preselectedFolderPath = null; - } - // no folder found or path was empty from the beginning - if (!chosenFolder) { - return; - } - // if folder, highlight and expand - if (!chosenFolder.isLeaf) { - ldTree.treeview('selectNode', chosenFolder); - } } } \ No newline at end of file