Index: lams_central/web/includes/javascript/learning-design-treeview.js
===================================================================
diff -u -rfbb560ed5f018b71f18b4eb1b7945432aa4229e2 -r03d58ffa7fa472912057c4a91a9acd1e7f8ffb5e
--- lams_central/web/includes/javascript/learning-design-treeview.js (.../learning-design-treeview.js) (revision fbb560ed5f018b71f18b4eb1b7945432aa4229e2)
+++ lams_central/web/includes/javascript/learning-design-treeview.js (.../learning-design-treeview.js) (revision 03d58ffa7fa472912057c4a91a9acd1e7f8ffb5e)
@@ -1,168 +1,189 @@
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,
- // 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',
- FOLDER_CONTENTS_FETCH_URL : 'home/getFolderContents.do',
-
-
- /**
- * Initialises a Learning Design treeview
- */
- init : function(targetElementSelector, onNodeClick, onNodeDblClick) {
- this.ldTree = $(targetElementSelector);
-
- // get top level folders
- var mainFolders = ldTreeview.getFolderContents();
-
- // 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);
- },
- // 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)}
- });
-
- ldTreeview.refresh(this.ldTree, this.ldTree.treeview('getNode', 0));
- this.ldTree.treeview('expandNode', 0);
- },
-
- /**
- * 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 + this.FOLDER_CONTENTS_FETCH_URL,
- data : {
- 'folderID' : folderID,
- 'allowInvalidDesigns' : allowInvalidDesigns
- },
- cache : false,
- async: false,
- dataType : 'json',
- success : function(response) {
- // parse the response; extract folders and LDs
- if (response.folders) {
- $.each(response.folders, function(index){
- // folderID == -2 is courses folder
- var canSave = this.folderID > 0 && !this.isRunSequencesFolder;
- result.push({'text' : (this.isRunSequencesFolder ? runSequencesFolderLabel
- : ldTreeview.escapeHtml(this.name))
- + (canSave ? '' : ' '),
- 'nodes' : [],
- 'folderID' : this.folderID,
- 'isRunSequenceFolder' : this.isRunSequencesFolder,
- // either take parent's setting or take 2nd (courses) and 3rd (public) folder
- 'canHaveReadOnly' : folderID ? canHaveReadOnly : index > 0,
- 'canSave' : canSave,
- 'canModify' : this.canModify && !this.isRunSequenceFolder });
+ // for authoring, we show invalid designs
+ // for add lesson and other places we need to choose a real LD, we hide them
+ allowInvalidDesigns : false,
+ // for simulating double click as treeview does not support it
+ DOUBLE_CLICK_PERIOD : 600,
+ nodeLastSelectedTime : null,
+ nodeLastSelectedId : null,
+ // reference to the rendered treeview
+ ldTree : null,
+ // can be i18n
+ LABEL_RUN_SEQUENCES_FOLDER : 'Run sequences',
+ FOLDER_CONTENTS_FETCH_URL : 'home/getFolderContents.do',
+
+
+ /**
+ * Initialises a Learning Design treeview
+ */
+ init : function(targetElementSelector, onNodeClick, onNodeDblClick) {
+ this.ldTree = $(targetElementSelector);
+
+ // get top level folders
+ var mainFolders = ldTreeview.getFolderContents();
+
+ // 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);
+ },
+ // 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)}
+ });
+
+ ldTreeview.refresh(this.ldTree, this.ldTree.treeview('getNode', 0));
+ this.ldTree.treeview('expandNode', 0);
+ },
+
+ /**
+ * 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 + this.FOLDER_CONTENTS_FETCH_URL,
+ data : {
+ 'folderID' : folderID,
+ 'allowInvalidDesigns' : allowInvalidDesigns
+ },
+ cache : false,
+ async: false,
+ dataType : 'json',
+ success : function(response) {
+ // parse the response; extract folders and LDs
+ if (response.folders) {
+ $.each(response.folders, function(index){
+ // folderID == -2 is courses folder
+ var canSave = this.folderID > 0 && !this.isRunSequencesFolder;
+ result.push({'text' : (this.isRunSequencesFolder ? runSequencesFolderLabel
+ : ldTreeview.escapeHtml(this.name))
+ + (canSave ? '' : ' '),
+ 'nodes' : [],
+ 'folderID' : this.folderID,
+ 'isRunSequenceFolder' : this.isRunSequencesFolder,
+ // either take parent's setting or take 2nd (courses) and 3rd (public) folder
+ 'canHaveReadOnly' : folderID ? canHaveReadOnly : index > 0,
+ 'canSave' : canSave,
+ 'canModify' : this.canModify && !this.isRunSequenceFolder });
+ });
+ }
+ if (response.learningDesigns) {
+ $.each(response.learningDesigns, function(){
+ var canModify = canSave && this.canModify,
+ name = ldTreeview.escapeHtml(this.name);
+ result.push({'label' : name,
+ 'text' : name + (this.readOnly ? ' ' : ''),
+ 'learningDesignId' : this.learningDesignId,
+ 'canHaveReadOnly' : canHaveReadOnly,
+ 'canModify' : canModify,
+ 'readOnly' : this.readOnly,
+ 'modifiedDate' : this.formattedDate
});
- }
- if (response.learningDesigns) {
- $.each(response.learningDesigns, function(){
- var canModify = canSave && this.canModify,
- name = ldTreeview.escapeHtml(this.name);
- result.push({'label' : name,
- 'text' : name + (this.readOnly ? ' ' : ''),
- 'learningDesignId' : this.learningDesignId,
- 'canHaveReadOnly' : canHaveReadOnly,
- 'canModify' : canModify,
- 'readOnly' : this.readOnly,
- 'modifiedDate' : this.formattedDate
- });
- });
- }
+ });
}
- });
-
- // 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 treeview-empty';
- } else if (folder) {
- // remove previously set folder-open etc. classes so two folder icons are not displayed
- folder.icon = '';
}
- 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);
+ });
+
+ // 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 treeview-empty';
+ } else if (folder) {
+ // remove previously set folder-open etc. classes so two folder icons are not displayed
+ folder.icon = '';
+ }
+ 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) {
+
+ if (event.type == 'nodeSelected'){
+ // on select, deselect all other nodes as we mute the default behaviour doing this
+ let selectedNodes = ldTreeview.ldTree.treeview('getSelected');
+ selectedNodes.forEach(function(selectedNode) {
+ if (selectedNode.nodeId != node.nodeId) {
+ //deselect all other nodes
+ ldTreeview.ldTree.treeview('unselectNode', [selectedNode.nodeId, { silent: true }]);
}
- return;
+ });
+ } else {
+ // deselect event
+ if (ldTreeview.nodeLastSelectedId == node.nodeId) {
+ // prevent deselecting nodes
+ ldTreeview.ldTree.treeview('selectNode', [node.nodeId, {silent: false}]);
}
-
- // 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){
+ // do nothing more. Only real or simulated select events do anything.
+ return;
+ }
+
+ // if there is no double click handler, just run the single click
+ if (!onNodeDblClick) {
+ if (onNodeClick) {
onNodeClick(event, node);
}
- // update counters for next click
- this.nodeLastSelectedTime = currentTimestamp;
- this.nodeLastSelectedId = node.nodeId;
- },
-
- /**
- * Escapes HTML tags to prevent XSS injection.
- */
- escapeHtml : function(unsafe) {
- return unsafe
- .replace(/&/g, "&")
- .replace(//g, ">")
- .replace(/"/g, """)
- .replace(/'/g, "'");
+ 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) {
+ setTimeout(function() {
+ // this has to be run in a timeout as "deselect" goes before "select" event
+ if (ldTreeview.nodeLastSelectedId == node.nodeId) {
+ onNodeDblClick(event, node);
+ }
+ }, 100);
+ } else if (onNodeClick){
+ onNodeClick(event, node);
+ }
+ // update counters for next click
+ this.nodeLastSelectedTime = currentTimestamp;
+ this.nodeLastSelectedId = node.nodeId;
+ },
+
+ /**
+ * Escapes HTML tags to prevent XSS injection.
+ */
+ escapeHtml : function(unsafe) {
+ return unsafe
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+ }
}
\ No newline at end of file