diff --git a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-coverage.js b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-coverage.js new file mode 100644 index 00000000000..5ec86de7b26 --- /dev/null +++ b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-coverage.js @@ -0,0 +1,908 @@ +if (typeof _yuitest_coverage == "undefined"){ + _yuitest_coverage = {}; + _yuitest_coverline = function(src, line){ + var coverage = _yuitest_coverage[src]; + if (!coverage.lines[line]){ + coverage.calledLines++; + } + coverage.lines[line]++; + }; + _yuitest_coverfunc = function(src, name, line){ + var coverage = _yuitest_coverage[src], + funcId = name + ":" + line; + if (!coverage.functions[funcId]){ + coverage.calledFunctions++; + } + coverage.functions[funcId]++; + }; +} +_yuitest_coverage["build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js"] = { + lines: {}, + functions: {}, + coveredLines: 0, + calledLines: 0, + coveredFunctions: 0, + calledFunctions: 0, + path: "build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", + code: [] +}; +_yuitest_coverage["build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js"].code=["YUI.add('moodle-block_navigation-navigation', function (Y, NAME) {","","/**"," * A 'actionkey' Event to help with Y.delegate()."," * The event consists of the left arrow, right arrow, enter and space keys."," * More keys can be mapped to action meanings."," * actions: collapse , expand, toggle, enter."," *"," * This event is delegated to branches in the navigation tree."," * The on() method to subscribe allows specifying the desired trigger actions as JSON."," *"," * Todo: This could be centralised, a similar Event is defined in blocks/dock.js"," */","Y.Event.define(\"actionkey\", {"," // Webkit and IE repeat keydown when you hold down arrow keys."," // Opera links keypress to page scroll; others keydown."," // Firefox prevents page scroll via preventDefault() on either"," // keydown or keypress."," _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress',",""," _keys: {"," //arrows"," '37': 'collapse',"," '39': 'expand',"," //(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings)"," '32': 'toggle',"," '13': 'enter'"," },",""," _keyHandler: function (e, notifier, args) {"," var actObj;"," if (!args.actions) {"," actObj = {collapse:true, expand:true, toggle:true, enter:true};"," } else {"," actObj = args.actions;"," }"," if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) {"," e.action = this._keys[e.keyCode];"," notifier.fire(e);"," }"," },",""," on: function (node, sub, notifier) {"," // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions)."," if (sub.args === null) {"," //no actions given"," sub._detacher = node.on(this._event, this._keyHandler,this, notifier, {actions:false});"," } else {"," sub._detacher = node.on(this._event, this._keyHandler,this, notifier, sub.args[0]);"," }"," },",""," detach: function (node, sub) {"," //detach our _detacher handle of the subscription made in on()"," sub._detacher.detach();"," },",""," delegate: function (node, sub, notifier, filter) {"," // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions)."," if (sub.args === null) {"," //no actions given"," sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, {actions:false});"," } else {"," sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, sub.args[0]);"," }"," },",""," detachDelegate: function (node, sub) {"," sub._delegateDetacher.detach();"," }","});","","var EXPANSIONLIMIT_EVERYTHING = 0,"," //EXPANSIONLIMIT_COURSE = 20,"," //EXPANSIONLIMIT_SECTION = 30,"," EXPANSIONLIMIT_ACTIVITY = 40;","","/**"," * Mappings for the different types of nodes coming from the navigation."," * Copied from lib/navigationlib.php navigation_node constants."," * @type object"," */","var NODETYPE = {"," /** @type int Root node = 0 */"," ROOTNODE : 0,"," /** @type int System context = 1 */"," SYSTEM : 1,"," /** @type int Course category = 10 */"," CATEGORY : 10,"," /** @type int MYCATEGORY = 11 */"," MYCATEGORY : 11,"," /** @type int Course = 20 */"," COURSE : 20,"," /** @type int Course section = 30 */"," SECTION : 30,"," /** @type int Activity (course module) = 40 */"," ACTIVITY : 40,"," /** @type int Resource (course module = 50 */"," RESOURCE : 50,"," /** @type int Custom node (could be anything) = 60 */"," CUSTOM : 60,"," /** @type int Setting = 70 */"," SETTING : 70,"," /** @type int User context = 80 */"," USER : 80,"," /** @type int Container = 90 */"," CONTAINER : 90","};","","/**"," * Navigation tree class."," *"," * This class establishes the tree initially, creating expandable branches as"," * required, and delegating the expand/collapse event."," */","var TREE = function() {"," TREE.superclass.constructor.apply(this, arguments);","};","TREE.prototype = {"," /**"," * The tree's ID, normally its block instance id."," */"," id : null,"," /**"," * An array of initialised branches."," */"," branches : [],"," /**"," * Initialise the tree object when its first created."," */"," initializer : function(config) {"," this.id = config.id;",""," var node = Y.one('#inst'+config.id);",""," // Can't find the block instance within the page"," if (node === null) {"," return;"," }",""," // Delegate event to toggle expansion"," Y.delegate('click', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this);"," Y.delegate('actionkey', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this);",""," // Gather the expandable branches ready for initialisation."," var expansions = [];"," if (config.expansions) {"," expansions = config.expansions;"," } else if (window['navtreeexpansions'+config.id]) {"," expansions = window['navtreeexpansions'+config.id];"," }"," // Establish each expandable branch as a tree branch."," for (var i in expansions) {"," var branch = new BRANCH({"," tree:this,"," branchobj:expansions[i],"," overrides : {"," expandable : true,"," children : [],"," haschildren : true"," }"," }).wire();"," M.block_navigation.expandablebranchcount++;"," this.branches[branch.get('id')] = branch;"," }"," if (M.block_navigation.expandablebranchcount > 0) {"," // Delegate some events to handle AJAX loading."," Y.delegate('click', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this);"," Y.delegate('actionkey', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this);"," }",""," // Call the generic blocks init method to add all the generic stuff"," if (this.get('candock')) {"," this.initialise_block(Y, node);"," }"," },"," /**"," * Fire actions for a branch when an event occurs."," */"," fire_branch_action : function(event) {"," var id = event.currentTarget.getAttribute('id');"," var branch = this.branches[id];"," branch.ajaxLoad(event);"," },"," /**"," * This is a callback function responsible for expanding and collapsing the"," * branches of the tree. It is delegated to rather than multiple event handles."," */"," toggleExpansion : function(e) {"," // First check if they managed to click on the li iteslf, then find the closest"," // LI ancestor and use that",""," if (e.target.test('a') && (e.keyCode === 0 || e.keyCode === 13)) {"," // A link has been clicked (or keypress is 'enter') don't fire any more events just do the default."," e.stopPropagation();"," return;"," }",""," // Makes sure we can get to the LI containing the branch."," var target = e.target;"," if (!target.test('li')) {"," target = target.ancestor('li');"," }"," if (!target) {"," return;"," }",""," // Toggle expand/collapse providing its not a root level branch."," if (!target.hasClass('depth_1')) {"," if (e.type === 'actionkey') {"," switch (e.action) {"," case 'expand' :"," target.removeClass('collapsed');"," target.set('aria-expanded', true);"," break;"," case 'collapse' :"," target.addClass('collapsed');"," target.set('aria-expanded', false);"," break;"," default :"," target.toggleClass('collapsed');"," target.set('aria-expanded', !target.hasClass('collapsed'));"," }"," e.halt();"," } else {"," target.toggleClass('collapsed');"," target.set('aria-expanded', !target.hasClass('collapsed'));"," }"," }",""," // If the accordian feature has been enabled collapse all siblings."," if (this.get('accordian')) {"," target.siblings('li').each(function(){"," if (this.get('id') !== target.get('id') && !this.hasClass('collapsed')) {"," this.addClass('collapsed');"," this.set('aria-expanded', false);"," }"," });"," }",""," // If this block can dock tell the dock to resize if required and check"," // the width on the dock panel in case it is presently in use."," if (this.get('candock')) {"," M.core_dock.resize();"," var panel = M.core_dock.getPanel();"," if (panel.visible) {"," panel.correctWidth();"," }"," }"," }","};","// The tree extends the YUI base foundation.","Y.extend(TREE, Y.Base, TREE.prototype, {"," NAME : 'navigation-tree',"," ATTRS : {"," instance : {"," value : null"," },"," candock : {"," validator : Y.Lang.isBool,"," value : false"," },"," accordian : {"," validator : Y.Lang.isBool,"," value : false"," },"," expansionlimit : {"," value : 0,"," setter : function(val) {"," return parseInt(val, 10);"," }"," }"," }","});","if (M.core_dock && M.core_dock.genericblock) {"," Y.augment(TREE, M.core_dock.genericblock);","}","","/**"," * The tree branch class."," * This class is used to manage a tree branch, in particular its ability to load"," * its contents by AJAX."," */","BRANCH = function() {"," BRANCH.superclass.constructor.apply(this, arguments);","};","BRANCH.prototype = {"," /**"," * The node for this branch (p)"," */"," node : null,"," /**"," * Initialises the branch when it is first created."," */"," initializer : function(config) {"," var i,"," children;"," if (config.branchobj !== null) {"," // Construct from the provided xml"," for (i in config.branchobj) {"," this.set(i, config.branchobj[i]);"," }"," children = this.get('children');"," this.set('haschildren', (children.length > 0));"," }"," if (config.overrides !== null) {"," // Construct from the provided xml"," for (i in config.overrides) {"," this.set(i, config.overrides[i]);"," }"," }"," // Get the node for this branch"," this.node = Y.one('#', this.get('id'));"," // Now check whether the branch is not expandable because of the expansionlimit"," var expansionlimit = this.get('tree').get('expansionlimit');"," var type = this.get('type');"," if (expansionlimit !== EXPANSIONLIMIT_EVERYTHING && type >= expansionlimit && type <= EXPANSIONLIMIT_ACTIVITY) {"," this.set('expandable', false);"," this.set('haschildren', false);"," }"," },"," /**"," * Draws the branch within the tree."," *"," * This function creates a DOM structure for the branch and then injects"," * it into the navigation tree at the correct point."," */"," draw : function(element) {",""," var isbranch = (this.get('expandable') || this.get('haschildren'));"," var branchli = Y.Node.create('
  • ');"," var link = this.get('link');"," var branchp = Y.Node.create('

    ').setAttribute('id', this.get('id'));"," if (!link) {"," //add tab focus if not link (so still one focus per menu node)."," // it was suggested to have 2 foci. one for the node and one for the link in MDL-27428."," branchp.setAttribute('tabindex', '0');"," }"," if (isbranch) {"," branchli.addClass('collapsed').addClass('contains_branch');"," branchli.set('aria-expanded', false);"," branchp.addClass('branch');"," }",""," // Prepare the icon, should be an object representing a pix_icon"," var branchicon = false;"," var icon = this.get('icon');"," if (icon && (!isbranch || this.get('type') == NODETYPE.ACTIVITY)) {"," branchicon = Y.Node.create('\"\"');"," branchicon.setAttribute('src', M.util.image_url(icon.pix, icon.component));"," branchli.addClass('item_with_icon');"," if (icon.alt) {"," branchicon.setAttribute('alt', icon.alt);"," }"," if (icon.title) {"," branchicon.setAttribute('title', icon.title);"," }"," if (icon.classes) {"," for (var i in icon.classes) {"," branchicon.addClass(icon.classes[i]);"," }"," }"," }",""," if (!link) {"," if (branchicon) {"," branchp.appendChild(branchicon);"," }"," branchp.append(this.get('name'));"," } else {"," var branchlink = Y.Node.create('');"," if (branchicon) {"," branchlink.appendChild(branchicon);"," }"," branchlink.append(this.get('name'));"," if (this.get('hidden')) {"," branchlink.addClass('dimmed');"," }"," branchp.appendChild(branchlink);"," }",""," branchli.appendChild(branchp);"," element.appendChild(branchli);"," this.node = branchp;"," return this;"," },"," /**"," * Attaches required events to the branch structure."," */"," wire : function() {"," this.node = this.node || Y.one('#'+this.get('id'));"," if (!this.node) {"," return false;"," }"," if (this.get('expandable')) {"," this.node.setAttribute('data-expandable', '1');"," this.node.setAttribute('data-loaded', '0');"," }"," return this;"," },"," /**"," * Gets the UL element that children for this branch should be inserted into."," */"," getChildrenUL : function() {"," var ul = this.node.next('ul');"," if (!ul) {"," ul = Y.Node.create('');"," this.node.ancestor().append(ul);"," }"," return ul;"," },"," /**"," * Load the content of the branch via AJAX."," *"," * This function calls ajaxProcessResponse with the result of the AJAX"," * request made here."," */"," ajaxLoad : function(e) {"," if (e.type === 'actionkey' && e.action !== 'enter') {"," e.halt();"," } else {"," e.stopPropagation();"," }"," if (e.type === 'actionkey' && e.action === 'enter' && e.target.test('A')) {"," // No ajaxLoad for enter."," this.node.setAttribute('data-expandable', '0');"," this.node.setAttribute('data-loaded', '1');"," return true;"," }",""," if (this.node.hasClass('loadingbranch')) {"," // Already loading. Just skip."," return true;"," }",""," if (this.node.getAttribute('data-loaded') === '1') {"," // We've already loaded this stuff."," return true;"," }"," this.node.addClass('loadingbranch');",""," var params = {"," elementid : this.get('id'),"," id : this.get('key'),"," type : this.get('type'),"," sesskey : M.cfg.sesskey,"," instance : this.get('tree').get('instance')"," };",""," Y.io(M.cfg.wwwroot+'/lib/ajax/getnavbranch.php', {"," method:'POST',"," data: build_querystring(params),"," on: {"," complete: this.ajaxProcessResponse"," },"," context:this"," });"," return true;"," },"," /**"," * Processes an AJAX request to load the content of this branch through"," * AJAX."," */"," ajaxProcessResponse : function(tid, outcome) {"," this.node.removeClass('loadingbranch');"," this.node.setAttribute('data-loaded', '1');"," try {"," var object = Y.JSON.parse(outcome.responseText);"," if (object.children && object.children.length > 0) {"," var coursecount = 0;"," for (var i in object.children) {"," if (typeof(object.children[i])==='object') {"," if (object.children[i].type == NODETYPE.COURSE) {"," coursecount++;"," }"," this.addChild(object.children[i]);"," }"," }"," if ((this.get('type') == NODETYPE.CATEGORY || this.get('type') == NODETYPE.ROOTNODE || this.get('type') == NODETYPE.MYCATEGORY)"," && coursecount >= M.block_navigation.courselimit) {"," this.addViewAllCoursesChild(this);"," }"," return true;"," }"," } catch (ex) {"," // If we got here then there was an error parsing the result"," }"," // The branch is empty so class it accordingly"," this.node.replaceClass('branch', 'emptybranch');"," return true;"," },"," /**"," * Turns the branch object passed to the method into a proper branch object"," * and then adds it as a child of this branch."," */"," addChild : function(branchobj) {"," // Make the new branch into an object"," var branch = new BRANCH({tree:this.get('tree'), branchobj:branchobj});"," if (branch.draw(this.getChildrenUL())) {"," this.get('tree').branches[branch.get('id')] = branch;"," branch.wire();"," var count = 0, i, children = branch.get('children');"," for (i in children) {"," // Add each branch to the tree"," if (children[i].type == NODETYPE.COURSE) {"," count++;"," }"," if (typeof(children[i]) === 'object') {"," branch.addChild(children[i]);"," }"," }"," if ((branch.get('type') == NODETYPE.CATEGORY || branch.get('type') == NODETYPE.MYCATEGORY)"," && count >= M.block_navigation.courselimit) {"," this.addViewAllCoursesChild(branch);"," }"," }"," return true;"," },",""," /**"," * Add a link to view all courses in a category"," */"," addViewAllCoursesChild: function(branch) {"," var url = null;"," if (branch.get('type') == NODETYPE.ROOTNODE) {"," if (branch.get('key') === 'mycourses') {"," url = M.cfg.wwwroot + '/my';"," } else {"," url = M.cfg.wwwroot + '/course/index.php';"," }"," } else {"," url = M.cfg.wwwroot+'/course/category.php?id=' + branch.get('key');"," }"," branch.addChild({"," name : M.str.moodle.viewallcourses,"," title : M.str.moodle.viewallcourses,"," link : url,"," haschildren : false,"," icon : {'pix':\"i/navigationitem\",'component':'moodle'}"," });"," }","};","Y.extend(BRANCH, Y.Base, BRANCH.prototype, {"," NAME : 'navigation-branch',"," ATTRS : {"," tree : {"," validator : Y.Lang.isObject"," },"," name : {"," value : '',"," validator : Y.Lang.isString,"," setter : function(val) {"," return val.replace(/\\n/g, '
    ');"," }"," },"," title : {"," value : '',"," validator : Y.Lang.isString"," },"," id : {"," value : '',"," validator : Y.Lang.isString,"," getter : function(val) {"," if (val === '') {"," val = 'expandable_branch_'+M.block_navigation.expandablebranchcount;"," M.block_navigation.expandablebranchcount++;"," }"," return val;"," }"," },"," key : {"," value : null"," },"," type : {"," value : null"," },"," link : {"," value : false"," },"," icon : {"," value : false,"," validator : Y.Lang.isObject"," },"," expandable : {"," value : false,"," validator : Y.Lang.isBool"," },"," hidden : {"," value : false,"," validator : Y.Lang.isBool"," },"," haschildren : {"," value : false,"," validator : Y.Lang.isBool"," },"," children : {"," value : [],"," validator : Y.Lang.isArray"," }"," }","});","","/**"," * This namespace will contain all of the contents of the navigation blocks"," * global navigation and settings."," * @namespace"," */","M.block_navigation = M.block_navigation || {"," /** The number of expandable branches in existence */"," expandablebranchcount:1,"," courselimit : 20,"," instance : null,"," /**"," * Add new instance of navigation tree to tree collection"," */"," init_add_tree:function(properties) {"," if (properties.courselimit) {"," this.courselimit = properties.courselimit;"," }"," if (M.core_dock) {"," M.core_dock.init(Y);"," }"," new TREE(properties);"," }","};","","","}, '@VERSION@', {"," \"requires\": ["," \"base\","," \"core_dock\","," \"io-base\","," \"node\","," \"dom\","," \"event-custom\","," \"event-delegate\","," \"json-parse\""," ]","});"]; +_yuitest_coverage["build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js"].lines = {"1":0,"14":0,"31":0,"32":0,"33":0,"35":0,"37":0,"38":0,"39":0,"45":0,"47":0,"49":0,"55":0,"60":0,"62":0,"64":0,"69":0,"73":0,"83":0,"116":0,"117":0,"119":0,"132":0,"134":0,"137":0,"138":0,"142":0,"143":0,"146":0,"147":0,"148":0,"149":0,"150":0,"153":0,"154":0,"163":0,"164":0,"166":0,"168":0,"169":0,"173":0,"174":0,"181":0,"182":0,"183":0,"193":0,"195":0,"196":0,"200":0,"201":0,"202":0,"204":0,"205":0,"209":0,"210":0,"211":0,"213":0,"214":0,"215":0,"217":0,"218":0,"219":0,"221":0,"222":0,"224":0,"226":0,"227":0,"232":0,"233":0,"234":0,"235":0,"236":0,"243":0,"244":0,"245":0,"246":0,"247":0,"253":0,"270":0,"275":0,"276":0,"284":0,"285":0,"287":0,"296":0,"298":0,"300":0,"301":0,"303":0,"304":0,"306":0,"308":0,"309":0,"313":0,"315":0,"316":0,"317":0,"318":0,"319":0,"330":0,"331":0,"332":0,"333":0,"334":0,"337":0,"339":0,"340":0,"341":0,"342":0,"346":0,"347":0,"348":0,"349":0,"350":0,"351":0,"352":0,"353":0,"355":0,"356":0,"358":0,"359":0,"360":0,"365":0,"366":0,"367":0,"369":0,"371":0,"372":0,"373":0,"375":0,"376":0,"377":0,"379":0,"382":0,"383":0,"384":0,"385":0,"391":0,"392":0,"393":0,"395":0,"396":0,"397":0,"399":0,"405":0,"406":0,"407":0,"408":0,"410":0,"419":0,"420":0,"422":0,"424":0,"426":0,"427":0,"428":0,"431":0,"433":0,"436":0,"438":0,"440":0,"442":0,"450":0,"458":0,"465":0,"466":0,"467":0,"468":0,"469":0,"470":0,"471":0,"472":0,"473":0,"474":0,"476":0,"479":0,"481":0,"483":0,"489":0,"490":0,"498":0,"499":0,"500":0,"501":0,"502":0,"503":0,"505":0,"506":0,"508":0,"509":0,"512":0,"514":0,"517":0,"524":0,"525":0,"526":0,"527":0,"529":0,"532":0,"534":0,"543":0,"553":0,"564":0,"565":0,"566":0,"568":0,"608":0,"617":0,"618":0,"620":0,"621":0,"623":0}; +_yuitest_coverage["build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js"].functions = {"_keyHandler:30":0,"on:43":0,"detach:53":0,"delegate:58":0,"detachDelegate:68":0,"TREE:116":0,"initializer:131":0,"fire_branch_action:180":0,"(anonymous 2):233":0,"toggleExpansion:189":0,"setter:269":0,"BRANCH:284":0,"initializer:295":0,"draw:328":0,"wire:390":0,"getChildrenUL:404":0,"ajaxLoad:418":0,"ajaxProcessResponse:464":0,"addChild:496":0,"addViewAllCoursesChild:523":0,"setter:552":0,"getter:563":0,"init_add_tree:616":0,"(anonymous 1):1":0}; +_yuitest_coverage["build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js"].coveredLines = 212; +_yuitest_coverage["build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js"].coveredFunctions = 24; +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 1); +YUI.add('moodle-block_navigation-navigation', function (Y, NAME) { + +/** + * A 'actionkey' Event to help with Y.delegate(). + * The event consists of the left arrow, right arrow, enter and space keys. + * More keys can be mapped to action meanings. + * actions: collapse , expand, toggle, enter. + * + * This event is delegated to branches in the navigation tree. + * The on() method to subscribe allows specifying the desired trigger actions as JSON. + * + * Todo: This could be centralised, a similar Event is defined in blocks/dock.js + */ +_yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "(anonymous 1)", 1); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 14); +Y.Event.define("actionkey", { + // Webkit and IE repeat keydown when you hold down arrow keys. + // Opera links keypress to page scroll; others keydown. + // Firefox prevents page scroll via preventDefault() on either + // keydown or keypress. + _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', + + _keys: { + //arrows + '37': 'collapse', + '39': 'expand', + //(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings) + '32': 'toggle', + '13': 'enter' + }, + + _keyHandler: function (e, notifier, args) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "_keyHandler", 30); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 31); +var actObj; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 32); +if (!args.actions) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 33); +actObj = {collapse:true, expand:true, toggle:true, enter:true}; + } else { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 35); +actObj = args.actions; + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 37); +if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 38); +e.action = this._keys[e.keyCode]; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 39); +notifier.fire(e); + } + }, + + on: function (node, sub, notifier) { + // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions). + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "on", 43); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 45); +if (sub.args === null) { + //no actions given + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 47); +sub._detacher = node.on(this._event, this._keyHandler,this, notifier, {actions:false}); + } else { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 49); +sub._detacher = node.on(this._event, this._keyHandler,this, notifier, sub.args[0]); + } + }, + + detach: function (node, sub) { + //detach our _detacher handle of the subscription made in on() + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "detach", 53); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 55); +sub._detacher.detach(); + }, + + delegate: function (node, sub, notifier, filter) { + // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions). + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "delegate", 58); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 60); +if (sub.args === null) { + //no actions given + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 62); +sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, {actions:false}); + } else { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 64); +sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, sub.args[0]); + } + }, + + detachDelegate: function (node, sub) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "detachDelegate", 68); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 69); +sub._delegateDetacher.detach(); + } +}); + +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 73); +var EXPANSIONLIMIT_EVERYTHING = 0, + //EXPANSIONLIMIT_COURSE = 20, + //EXPANSIONLIMIT_SECTION = 30, + EXPANSIONLIMIT_ACTIVITY = 40; + +/** + * Mappings for the different types of nodes coming from the navigation. + * Copied from lib/navigationlib.php navigation_node constants. + * @type object + */ +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 83); +var NODETYPE = { + /** @type int Root node = 0 */ + ROOTNODE : 0, + /** @type int System context = 1 */ + SYSTEM : 1, + /** @type int Course category = 10 */ + CATEGORY : 10, + /** @type int MYCATEGORY = 11 */ + MYCATEGORY : 11, + /** @type int Course = 20 */ + COURSE : 20, + /** @type int Course section = 30 */ + SECTION : 30, + /** @type int Activity (course module) = 40 */ + ACTIVITY : 40, + /** @type int Resource (course module = 50 */ + RESOURCE : 50, + /** @type int Custom node (could be anything) = 60 */ + CUSTOM : 60, + /** @type int Setting = 70 */ + SETTING : 70, + /** @type int User context = 80 */ + USER : 80, + /** @type int Container = 90 */ + CONTAINER : 90 +}; + +/** + * Navigation tree class. + * + * This class establishes the tree initially, creating expandable branches as + * required, and delegating the expand/collapse event. + */ +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 116); +var TREE = function() { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "TREE", 116); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 117); +TREE.superclass.constructor.apply(this, arguments); +}; +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 119); +TREE.prototype = { + /** + * The tree's ID, normally its block instance id. + */ + id : null, + /** + * An array of initialised branches. + */ + branches : [], + /** + * Initialise the tree object when its first created. + */ + initializer : function(config) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "initializer", 131); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 132); +this.id = config.id; + + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 134); +var node = Y.one('#inst'+config.id); + + // Can't find the block instance within the page + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 137); +if (node === null) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 138); +return; + } + + // Delegate event to toggle expansion + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 142); +Y.delegate('click', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 143); +Y.delegate('actionkey', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this); + + // Gather the expandable branches ready for initialisation. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 146); +var expansions = []; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 147); +if (config.expansions) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 148); +expansions = config.expansions; + } else {_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 149); +if (window['navtreeexpansions'+config.id]) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 150); +expansions = window['navtreeexpansions'+config.id]; + }} + // Establish each expandable branch as a tree branch. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 153); +for (var i in expansions) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 154); +var branch = new BRANCH({ + tree:this, + branchobj:expansions[i], + overrides : { + expandable : true, + children : [], + haschildren : true + } + }).wire(); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 163); +M.block_navigation.expandablebranchcount++; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 164); +this.branches[branch.get('id')] = branch; + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 166); +if (M.block_navigation.expandablebranchcount > 0) { + // Delegate some events to handle AJAX loading. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 168); +Y.delegate('click', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 169); +Y.delegate('actionkey', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this); + } + + // Call the generic blocks init method to add all the generic stuff + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 173); +if (this.get('candock')) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 174); +this.initialise_block(Y, node); + } + }, + /** + * Fire actions for a branch when an event occurs. + */ + fire_branch_action : function(event) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "fire_branch_action", 180); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 181); +var id = event.currentTarget.getAttribute('id'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 182); +var branch = this.branches[id]; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 183); +branch.ajaxLoad(event); + }, + /** + * This is a callback function responsible for expanding and collapsing the + * branches of the tree. It is delegated to rather than multiple event handles. + */ + toggleExpansion : function(e) { + // First check if they managed to click on the li iteslf, then find the closest + // LI ancestor and use that + + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "toggleExpansion", 189); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 193); +if (e.target.test('a') && (e.keyCode === 0 || e.keyCode === 13)) { + // A link has been clicked (or keypress is 'enter') don't fire any more events just do the default. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 195); +e.stopPropagation(); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 196); +return; + } + + // Makes sure we can get to the LI containing the branch. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 200); +var target = e.target; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 201); +if (!target.test('li')) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 202); +target = target.ancestor('li'); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 204); +if (!target) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 205); +return; + } + + // Toggle expand/collapse providing its not a root level branch. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 209); +if (!target.hasClass('depth_1')) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 210); +if (e.type === 'actionkey') { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 211); +switch (e.action) { + case 'expand' : + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 213); +target.removeClass('collapsed'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 214); +target.set('aria-expanded', true); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 215); +break; + case 'collapse' : + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 217); +target.addClass('collapsed'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 218); +target.set('aria-expanded', false); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 219); +break; + default : + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 221); +target.toggleClass('collapsed'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 222); +target.set('aria-expanded', !target.hasClass('collapsed')); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 224); +e.halt(); + } else { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 226); +target.toggleClass('collapsed'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 227); +target.set('aria-expanded', !target.hasClass('collapsed')); + } + } + + // If the accordian feature has been enabled collapse all siblings. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 232); +if (this.get('accordian')) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 233); +target.siblings('li').each(function(){ + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "(anonymous 2)", 233); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 234); +if (this.get('id') !== target.get('id') && !this.hasClass('collapsed')) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 235); +this.addClass('collapsed'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 236); +this.set('aria-expanded', false); + } + }); + } + + // If this block can dock tell the dock to resize if required and check + // the width on the dock panel in case it is presently in use. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 243); +if (this.get('candock')) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 244); +M.core_dock.resize(); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 245); +var panel = M.core_dock.getPanel(); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 246); +if (panel.visible) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 247); +panel.correctWidth(); + } + } + } +}; +// The tree extends the YUI base foundation. +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 253); +Y.extend(TREE, Y.Base, TREE.prototype, { + NAME : 'navigation-tree', + ATTRS : { + instance : { + value : null + }, + candock : { + validator : Y.Lang.isBool, + value : false + }, + accordian : { + validator : Y.Lang.isBool, + value : false + }, + expansionlimit : { + value : 0, + setter : function(val) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "setter", 269); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 270); +return parseInt(val, 10); + } + } + } +}); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 275); +if (M.core_dock && M.core_dock.genericblock) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 276); +Y.augment(TREE, M.core_dock.genericblock); +} + +/** + * The tree branch class. + * This class is used to manage a tree branch, in particular its ability to load + * its contents by AJAX. + */ +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 284); +BRANCH = function() { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "BRANCH", 284); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 285); +BRANCH.superclass.constructor.apply(this, arguments); +}; +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 287); +BRANCH.prototype = { + /** + * The node for this branch (p) + */ + node : null, + /** + * Initialises the branch when it is first created. + */ + initializer : function(config) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "initializer", 295); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 296); +var i, + children; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 298); +if (config.branchobj !== null) { + // Construct from the provided xml + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 300); +for (i in config.branchobj) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 301); +this.set(i, config.branchobj[i]); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 303); +children = this.get('children'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 304); +this.set('haschildren', (children.length > 0)); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 306); +if (config.overrides !== null) { + // Construct from the provided xml + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 308); +for (i in config.overrides) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 309); +this.set(i, config.overrides[i]); + } + } + // Get the node for this branch + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 313); +this.node = Y.one('#', this.get('id')); + // Now check whether the branch is not expandable because of the expansionlimit + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 315); +var expansionlimit = this.get('tree').get('expansionlimit'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 316); +var type = this.get('type'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 317); +if (expansionlimit !== EXPANSIONLIMIT_EVERYTHING && type >= expansionlimit && type <= EXPANSIONLIMIT_ACTIVITY) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 318); +this.set('expandable', false); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 319); +this.set('haschildren', false); + } + }, + /** + * Draws the branch within the tree. + * + * This function creates a DOM structure for the branch and then injects + * it into the navigation tree at the correct point. + */ + draw : function(element) { + + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "draw", 328); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 330); +var isbranch = (this.get('expandable') || this.get('haschildren')); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 331); +var branchli = Y.Node.create('
  • '); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 332); +var link = this.get('link'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 333); +var branchp = Y.Node.create('

    ').setAttribute('id', this.get('id')); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 334); +if (!link) { + //add tab focus if not link (so still one focus per menu node). + // it was suggested to have 2 foci. one for the node and one for the link in MDL-27428. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 337); +branchp.setAttribute('tabindex', '0'); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 339); +if (isbranch) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 340); +branchli.addClass('collapsed').addClass('contains_branch'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 341); +branchli.set('aria-expanded', false); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 342); +branchp.addClass('branch'); + } + + // Prepare the icon, should be an object representing a pix_icon + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 346); +var branchicon = false; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 347); +var icon = this.get('icon'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 348); +if (icon && (!isbranch || this.get('type') == NODETYPE.ACTIVITY)) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 349); +branchicon = Y.Node.create(''); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 350); +branchicon.setAttribute('src', M.util.image_url(icon.pix, icon.component)); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 351); +branchli.addClass('item_with_icon'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 352); +if (icon.alt) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 353); +branchicon.setAttribute('alt', icon.alt); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 355); +if (icon.title) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 356); +branchicon.setAttribute('title', icon.title); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 358); +if (icon.classes) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 359); +for (var i in icon.classes) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 360); +branchicon.addClass(icon.classes[i]); + } + } + } + + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 365); +if (!link) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 366); +if (branchicon) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 367); +branchp.appendChild(branchicon); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 369); +branchp.append(this.get('name')); + } else { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 371); +var branchlink = Y.Node.create(''); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 372); +if (branchicon) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 373); +branchlink.appendChild(branchicon); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 375); +branchlink.append(this.get('name')); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 376); +if (this.get('hidden')) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 377); +branchlink.addClass('dimmed'); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 379); +branchp.appendChild(branchlink); + } + + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 382); +branchli.appendChild(branchp); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 383); +element.appendChild(branchli); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 384); +this.node = branchp; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 385); +return this; + }, + /** + * Attaches required events to the branch structure. + */ + wire : function() { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "wire", 390); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 391); +this.node = this.node || Y.one('#'+this.get('id')); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 392); +if (!this.node) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 393); +return false; + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 395); +if (this.get('expandable')) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 396); +this.node.setAttribute('data-expandable', '1'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 397); +this.node.setAttribute('data-loaded', '0'); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 399); +return this; + }, + /** + * Gets the UL element that children for this branch should be inserted into. + */ + getChildrenUL : function() { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "getChildrenUL", 404); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 405); +var ul = this.node.next('ul'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 406); +if (!ul) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 407); +ul = Y.Node.create(''); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 408); +this.node.ancestor().append(ul); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 410); +return ul; + }, + /** + * Load the content of the branch via AJAX. + * + * This function calls ajaxProcessResponse with the result of the AJAX + * request made here. + */ + ajaxLoad : function(e) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "ajaxLoad", 418); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 419); +if (e.type === 'actionkey' && e.action !== 'enter') { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 420); +e.halt(); + } else { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 422); +e.stopPropagation(); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 424); +if (e.type === 'actionkey' && e.action === 'enter' && e.target.test('A')) { + // No ajaxLoad for enter. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 426); +this.node.setAttribute('data-expandable', '0'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 427); +this.node.setAttribute('data-loaded', '1'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 428); +return true; + } + + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 431); +if (this.node.hasClass('loadingbranch')) { + // Already loading. Just skip. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 433); +return true; + } + + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 436); +if (this.node.getAttribute('data-loaded') === '1') { + // We've already loaded this stuff. + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 438); +return true; + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 440); +this.node.addClass('loadingbranch'); + + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 442); +var params = { + elementid : this.get('id'), + id : this.get('key'), + type : this.get('type'), + sesskey : M.cfg.sesskey, + instance : this.get('tree').get('instance') + }; + + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 450); +Y.io(M.cfg.wwwroot+'/lib/ajax/getnavbranch.php', { + method:'POST', + data: build_querystring(params), + on: { + complete: this.ajaxProcessResponse + }, + context:this + }); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 458); +return true; + }, + /** + * Processes an AJAX request to load the content of this branch through + * AJAX. + */ + ajaxProcessResponse : function(tid, outcome) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "ajaxProcessResponse", 464); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 465); +this.node.removeClass('loadingbranch'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 466); +this.node.setAttribute('data-loaded', '1'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 467); +try { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 468); +var object = Y.JSON.parse(outcome.responseText); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 469); +if (object.children && object.children.length > 0) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 470); +var coursecount = 0; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 471); +for (var i in object.children) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 472); +if (typeof(object.children[i])==='object') { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 473); +if (object.children[i].type == NODETYPE.COURSE) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 474); +coursecount++; + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 476); +this.addChild(object.children[i]); + } + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 479); +if ((this.get('type') == NODETYPE.CATEGORY || this.get('type') == NODETYPE.ROOTNODE || this.get('type') == NODETYPE.MYCATEGORY) + && coursecount >= M.block_navigation.courselimit) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 481); +this.addViewAllCoursesChild(this); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 483); +return true; + } + } catch (ex) { + // If we got here then there was an error parsing the result + } + // The branch is empty so class it accordingly + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 489); +this.node.replaceClass('branch', 'emptybranch'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 490); +return true; + }, + /** + * Turns the branch object passed to the method into a proper branch object + * and then adds it as a child of this branch. + */ + addChild : function(branchobj) { + // Make the new branch into an object + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "addChild", 496); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 498); +var branch = new BRANCH({tree:this.get('tree'), branchobj:branchobj}); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 499); +if (branch.draw(this.getChildrenUL())) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 500); +this.get('tree').branches[branch.get('id')] = branch; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 501); +branch.wire(); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 502); +var count = 0, i, children = branch.get('children'); + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 503); +for (i in children) { + // Add each branch to the tree + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 505); +if (children[i].type == NODETYPE.COURSE) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 506); +count++; + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 508); +if (typeof(children[i]) === 'object') { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 509); +branch.addChild(children[i]); + } + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 512); +if ((branch.get('type') == NODETYPE.CATEGORY || branch.get('type') == NODETYPE.MYCATEGORY) + && count >= M.block_navigation.courselimit) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 514); +this.addViewAllCoursesChild(branch); + } + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 517); +return true; + }, + + /** + * Add a link to view all courses in a category + */ + addViewAllCoursesChild: function(branch) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "addViewAllCoursesChild", 523); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 524); +var url = null; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 525); +if (branch.get('type') == NODETYPE.ROOTNODE) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 526); +if (branch.get('key') === 'mycourses') { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 527); +url = M.cfg.wwwroot + '/my'; + } else { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 529); +url = M.cfg.wwwroot + '/course/index.php'; + } + } else { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 532); +url = M.cfg.wwwroot+'/course/category.php?id=' + branch.get('key'); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 534); +branch.addChild({ + name : M.str.moodle.viewallcourses, + title : M.str.moodle.viewallcourses, + link : url, + haschildren : false, + icon : {'pix':"i/navigationitem",'component':'moodle'} + }); + } +}; +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 543); +Y.extend(BRANCH, Y.Base, BRANCH.prototype, { + NAME : 'navigation-branch', + ATTRS : { + tree : { + validator : Y.Lang.isObject + }, + name : { + value : '', + validator : Y.Lang.isString, + setter : function(val) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "setter", 552); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 553); +return val.replace(/\n/g, '
    '); + } + }, + title : { + value : '', + validator : Y.Lang.isString + }, + id : { + value : '', + validator : Y.Lang.isString, + getter : function(val) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "getter", 563); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 564); +if (val === '') { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 565); +val = 'expandable_branch_'+M.block_navigation.expandablebranchcount; + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 566); +M.block_navigation.expandablebranchcount++; + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 568); +return val; + } + }, + key : { + value : null + }, + type : { + value : null + }, + link : { + value : false + }, + icon : { + value : false, + validator : Y.Lang.isObject + }, + expandable : { + value : false, + validator : Y.Lang.isBool + }, + hidden : { + value : false, + validator : Y.Lang.isBool + }, + haschildren : { + value : false, + validator : Y.Lang.isBool + }, + children : { + value : [], + validator : Y.Lang.isArray + } + } +}); + +/** + * This namespace will contain all of the contents of the navigation blocks + * global navigation and settings. + * @namespace + */ +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 608); +M.block_navigation = M.block_navigation || { + /** The number of expandable branches in existence */ + expandablebranchcount:1, + courselimit : 20, + instance : null, + /** + * Add new instance of navigation tree to tree collection + */ + init_add_tree:function(properties) { + _yuitest_coverfunc("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", "init_add_tree", 616); +_yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 617); +if (properties.courselimit) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 618); +this.courselimit = properties.courselimit; + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 620); +if (M.core_dock) { + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 621); +M.core_dock.init(Y); + } + _yuitest_coverline("build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js", 623); +new TREE(properties); + } +}; + + +}, '@VERSION@', { + "requires": [ + "base", + "core_dock", + "io-base", + "node", + "dom", + "event-custom", + "event-delegate", + "json-parse" + ] +}); diff --git a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js new file mode 100644 index 00000000000..9ba9df72208 --- /dev/null +++ b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-debug.js @@ -0,0 +1,639 @@ +YUI.add('moodle-block_navigation-navigation', function (Y, NAME) { + +/** + * A 'actionkey' Event to help with Y.delegate(). + * The event consists of the left arrow, right arrow, enter and space keys. + * More keys can be mapped to action meanings. + * actions: collapse , expand, toggle, enter. + * + * This event is delegated to branches in the navigation tree. + * The on() method to subscribe allows specifying the desired trigger actions as JSON. + * + * Todo: This could be centralised, a similar Event is defined in blocks/dock.js + */ +Y.Event.define("actionkey", { + // Webkit and IE repeat keydown when you hold down arrow keys. + // Opera links keypress to page scroll; others keydown. + // Firefox prevents page scroll via preventDefault() on either + // keydown or keypress. + _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', + + _keys: { + //arrows + '37': 'collapse', + '39': 'expand', + //(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings) + '32': 'toggle', + '13': 'enter' + }, + + _keyHandler: function (e, notifier, args) { + var actObj; + if (!args.actions) { + actObj = {collapse:true, expand:true, toggle:true, enter:true}; + } else { + actObj = args.actions; + } + if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) { + e.action = this._keys[e.keyCode]; + notifier.fire(e); + } + }, + + on: function (node, sub, notifier) { + // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions). + if (sub.args === null) { + //no actions given + sub._detacher = node.on(this._event, this._keyHandler,this, notifier, {actions:false}); + } else { + sub._detacher = node.on(this._event, this._keyHandler,this, notifier, sub.args[0]); + } + }, + + detach: function (node, sub) { + //detach our _detacher handle of the subscription made in on() + sub._detacher.detach(); + }, + + delegate: function (node, sub, notifier, filter) { + // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions). + if (sub.args === null) { + //no actions given + sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, {actions:false}); + } else { + sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, sub.args[0]); + } + }, + + detachDelegate: function (node, sub) { + sub._delegateDetacher.detach(); + } +}); + +var EXPANSIONLIMIT_EVERYTHING = 0, + //EXPANSIONLIMIT_COURSE = 20, + //EXPANSIONLIMIT_SECTION = 30, + EXPANSIONLIMIT_ACTIVITY = 40; + +/** + * Mappings for the different types of nodes coming from the navigation. + * Copied from lib/navigationlib.php navigation_node constants. + * @type object + */ +var NODETYPE = { + /** @type int Root node = 0 */ + ROOTNODE : 0, + /** @type int System context = 1 */ + SYSTEM : 1, + /** @type int Course category = 10 */ + CATEGORY : 10, + /** @type int MYCATEGORY = 11 */ + MYCATEGORY : 11, + /** @type int Course = 20 */ + COURSE : 20, + /** @type int Course section = 30 */ + SECTION : 30, + /** @type int Activity (course module) = 40 */ + ACTIVITY : 40, + /** @type int Resource (course module = 50 */ + RESOURCE : 50, + /** @type int Custom node (could be anything) = 60 */ + CUSTOM : 60, + /** @type int Setting = 70 */ + SETTING : 70, + /** @type int User context = 80 */ + USER : 80, + /** @type int Container = 90 */ + CONTAINER : 90 +}; + +/** + * Navigation tree class. + * + * This class establishes the tree initially, creating expandable branches as + * required, and delegating the expand/collapse event. + */ +var TREE = function() { + TREE.superclass.constructor.apply(this, arguments); +}; +TREE.prototype = { + /** + * The tree's ID, normally its block instance id. + */ + id : null, + /** + * An array of initialised branches. + */ + branches : [], + /** + * Initialise the tree object when its first created. + */ + initializer : function(config) { + this.id = config.id; + + var node = Y.one('#inst'+config.id); + + // Can't find the block instance within the page + if (node === null) { + return; + } + + // Delegate event to toggle expansion + Y.delegate('click', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this); + Y.delegate('actionkey', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this); + + // Gather the expandable branches ready for initialisation. + var expansions = []; + if (config.expansions) { + expansions = config.expansions; + } else if (window['navtreeexpansions'+config.id]) { + expansions = window['navtreeexpansions'+config.id]; + } + // Establish each expandable branch as a tree branch. + for (var i in expansions) { + var branch = new BRANCH({ + tree:this, + branchobj:expansions[i], + overrides : { + expandable : true, + children : [], + haschildren : true + } + }).wire(); + M.block_navigation.expandablebranchcount++; + this.branches[branch.get('id')] = branch; + } + if (M.block_navigation.expandablebranchcount > 0) { + // Delegate some events to handle AJAX loading. + Y.delegate('click', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this); + Y.delegate('actionkey', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this); + } + + // Call the generic blocks init method to add all the generic stuff + if (this.get('candock')) { + this.initialise_block(Y, node); + } + }, + /** + * Fire actions for a branch when an event occurs. + */ + fire_branch_action : function(event) { + var id = event.currentTarget.getAttribute('id'); + var branch = this.branches[id]; + branch.ajaxLoad(event); + }, + /** + * This is a callback function responsible for expanding and collapsing the + * branches of the tree. It is delegated to rather than multiple event handles. + */ + toggleExpansion : function(e) { + // First check if they managed to click on the li iteslf, then find the closest + // LI ancestor and use that + + if (e.target.test('a') && (e.keyCode === 0 || e.keyCode === 13)) { + // A link has been clicked (or keypress is 'enter') don't fire any more events just do the default. + e.stopPropagation(); + return; + } + + // Makes sure we can get to the LI containing the branch. + var target = e.target; + if (!target.test('li')) { + target = target.ancestor('li'); + } + if (!target) { + return; + } + + // Toggle expand/collapse providing its not a root level branch. + if (!target.hasClass('depth_1')) { + if (e.type === 'actionkey') { + switch (e.action) { + case 'expand' : + target.removeClass('collapsed'); + target.set('aria-expanded', true); + break; + case 'collapse' : + target.addClass('collapsed'); + target.set('aria-expanded', false); + break; + default : + target.toggleClass('collapsed'); + target.set('aria-expanded', !target.hasClass('collapsed')); + } + e.halt(); + } else { + target.toggleClass('collapsed'); + target.set('aria-expanded', !target.hasClass('collapsed')); + } + } + + // If the accordian feature has been enabled collapse all siblings. + if (this.get('accordian')) { + target.siblings('li').each(function(){ + if (this.get('id') !== target.get('id') && !this.hasClass('collapsed')) { + this.addClass('collapsed'); + this.set('aria-expanded', false); + } + }); + } + + // If this block can dock tell the dock to resize if required and check + // the width on the dock panel in case it is presently in use. + if (this.get('candock')) { + M.core_dock.resize(); + var panel = M.core_dock.getPanel(); + if (panel.visible) { + panel.correctWidth(); + } + } + } +}; +// The tree extends the YUI base foundation. +Y.extend(TREE, Y.Base, TREE.prototype, { + NAME : 'navigation-tree', + ATTRS : { + instance : { + value : null + }, + candock : { + validator : Y.Lang.isBool, + value : false + }, + accordian : { + validator : Y.Lang.isBool, + value : false + }, + expansionlimit : { + value : 0, + setter : function(val) { + return parseInt(val, 10); + } + } + } +}); +if (M.core_dock && M.core_dock.genericblock) { + Y.augment(TREE, M.core_dock.genericblock); +} + +/** + * The tree branch class. + * This class is used to manage a tree branch, in particular its ability to load + * its contents by AJAX. + */ +BRANCH = function() { + BRANCH.superclass.constructor.apply(this, arguments); +}; +BRANCH.prototype = { + /** + * The node for this branch (p) + */ + node : null, + /** + * Initialises the branch when it is first created. + */ + initializer : function(config) { + var i, + children; + if (config.branchobj !== null) { + // Construct from the provided xml + for (i in config.branchobj) { + this.set(i, config.branchobj[i]); + } + children = this.get('children'); + this.set('haschildren', (children.length > 0)); + } + if (config.overrides !== null) { + // Construct from the provided xml + for (i in config.overrides) { + this.set(i, config.overrides[i]); + } + } + // Get the node for this branch + this.node = Y.one('#', this.get('id')); + // Now check whether the branch is not expandable because of the expansionlimit + var expansionlimit = this.get('tree').get('expansionlimit'); + var type = this.get('type'); + if (expansionlimit !== EXPANSIONLIMIT_EVERYTHING && type >= expansionlimit && type <= EXPANSIONLIMIT_ACTIVITY) { + this.set('expandable', false); + this.set('haschildren', false); + } + }, + /** + * Draws the branch within the tree. + * + * This function creates a DOM structure for the branch and then injects + * it into the navigation tree at the correct point. + */ + draw : function(element) { + + var isbranch = (this.get('expandable') || this.get('haschildren')); + var branchli = Y.Node.create('
  • '); + var link = this.get('link'); + var branchp = Y.Node.create('

    ').setAttribute('id', this.get('id')); + if (!link) { + //add tab focus if not link (so still one focus per menu node). + // it was suggested to have 2 foci. one for the node and one for the link in MDL-27428. + branchp.setAttribute('tabindex', '0'); + } + if (isbranch) { + branchli.addClass('collapsed').addClass('contains_branch'); + branchli.set('aria-expanded', false); + branchp.addClass('branch'); + } + + // Prepare the icon, should be an object representing a pix_icon + var branchicon = false; + var icon = this.get('icon'); + if (icon && (!isbranch || this.get('type') == NODETYPE.ACTIVITY)) { + branchicon = Y.Node.create(''); + branchicon.setAttribute('src', M.util.image_url(icon.pix, icon.component)); + branchli.addClass('item_with_icon'); + if (icon.alt) { + branchicon.setAttribute('alt', icon.alt); + } + if (icon.title) { + branchicon.setAttribute('title', icon.title); + } + if (icon.classes) { + for (var i in icon.classes) { + branchicon.addClass(icon.classes[i]); + } + } + } + + if (!link) { + if (branchicon) { + branchp.appendChild(branchicon); + } + branchp.append(this.get('name')); + } else { + var branchlink = Y.Node.create(''); + if (branchicon) { + branchlink.appendChild(branchicon); + } + branchlink.append(this.get('name')); + if (this.get('hidden')) { + branchlink.addClass('dimmed'); + } + branchp.appendChild(branchlink); + } + + branchli.appendChild(branchp); + element.appendChild(branchli); + this.node = branchp; + return this; + }, + /** + * Attaches required events to the branch structure. + */ + wire : function() { + this.node = this.node || Y.one('#'+this.get('id')); + if (!this.node) { + return false; + } + if (this.get('expandable')) { + this.node.setAttribute('data-expandable', '1'); + this.node.setAttribute('data-loaded', '0'); + } + return this; + }, + /** + * Gets the UL element that children for this branch should be inserted into. + */ + getChildrenUL : function() { + var ul = this.node.next('ul'); + if (!ul) { + ul = Y.Node.create(''); + this.node.ancestor().append(ul); + } + return ul; + }, + /** + * Load the content of the branch via AJAX. + * + * This function calls ajaxProcessResponse with the result of the AJAX + * request made here. + */ + ajaxLoad : function(e) { + if (e.type === 'actionkey' && e.action !== 'enter') { + e.halt(); + } else { + e.stopPropagation(); + } + if (e.type === 'actionkey' && e.action === 'enter' && e.target.test('A')) { + // No ajaxLoad for enter. + this.node.setAttribute('data-expandable', '0'); + this.node.setAttribute('data-loaded', '1'); + return true; + } + + if (this.node.hasClass('loadingbranch')) { + // Already loading. Just skip. + return true; + } + + if (this.node.getAttribute('data-loaded') === '1') { + // We've already loaded this stuff. + return true; + } + this.node.addClass('loadingbranch'); + + var params = { + elementid : this.get('id'), + id : this.get('key'), + type : this.get('type'), + sesskey : M.cfg.sesskey, + instance : this.get('tree').get('instance') + }; + + Y.io(M.cfg.wwwroot+'/lib/ajax/getnavbranch.php', { + method:'POST', + data: build_querystring(params), + on: { + complete: this.ajaxProcessResponse + }, + context:this + }); + return true; + }, + /** + * Processes an AJAX request to load the content of this branch through + * AJAX. + */ + ajaxProcessResponse : function(tid, outcome) { + this.node.removeClass('loadingbranch'); + this.node.setAttribute('data-loaded', '1'); + try { + var object = Y.JSON.parse(outcome.responseText); + if (object.children && object.children.length > 0) { + var coursecount = 0; + for (var i in object.children) { + if (typeof(object.children[i])==='object') { + if (object.children[i].type == NODETYPE.COURSE) { + coursecount++; + } + this.addChild(object.children[i]); + } + } + if ((this.get('type') == NODETYPE.CATEGORY || this.get('type') == NODETYPE.ROOTNODE || this.get('type') == NODETYPE.MYCATEGORY) + && coursecount >= M.block_navigation.courselimit) { + this.addViewAllCoursesChild(this); + } + return true; + } + } catch (ex) { + // If we got here then there was an error parsing the result + } + // The branch is empty so class it accordingly + this.node.replaceClass('branch', 'emptybranch'); + return true; + }, + /** + * Turns the branch object passed to the method into a proper branch object + * and then adds it as a child of this branch. + */ + addChild : function(branchobj) { + // Make the new branch into an object + var branch = new BRANCH({tree:this.get('tree'), branchobj:branchobj}); + if (branch.draw(this.getChildrenUL())) { + this.get('tree').branches[branch.get('id')] = branch; + branch.wire(); + var count = 0, i, children = branch.get('children'); + for (i in children) { + // Add each branch to the tree + if (children[i].type == NODETYPE.COURSE) { + count++; + } + if (typeof(children[i]) === 'object') { + branch.addChild(children[i]); + } + } + if ((branch.get('type') == NODETYPE.CATEGORY || branch.get('type') == NODETYPE.MYCATEGORY) + && count >= M.block_navigation.courselimit) { + this.addViewAllCoursesChild(branch); + } + } + return true; + }, + + /** + * Add a link to view all courses in a category + */ + addViewAllCoursesChild: function(branch) { + var url = null; + if (branch.get('type') == NODETYPE.ROOTNODE) { + if (branch.get('key') === 'mycourses') { + url = M.cfg.wwwroot + '/my'; + } else { + url = M.cfg.wwwroot + '/course/index.php'; + } + } else { + url = M.cfg.wwwroot+'/course/category.php?id=' + branch.get('key'); + } + branch.addChild({ + name : M.str.moodle.viewallcourses, + title : M.str.moodle.viewallcourses, + link : url, + haschildren : false, + icon : {'pix':"i/navigationitem",'component':'moodle'} + }); + } +}; +Y.extend(BRANCH, Y.Base, BRANCH.prototype, { + NAME : 'navigation-branch', + ATTRS : { + tree : { + validator : Y.Lang.isObject + }, + name : { + value : '', + validator : Y.Lang.isString, + setter : function(val) { + return val.replace(/\n/g, '
    '); + } + }, + title : { + value : '', + validator : Y.Lang.isString + }, + id : { + value : '', + validator : Y.Lang.isString, + getter : function(val) { + if (val === '') { + val = 'expandable_branch_'+M.block_navigation.expandablebranchcount; + M.block_navigation.expandablebranchcount++; + } + return val; + } + }, + key : { + value : null + }, + type : { + value : null + }, + link : { + value : false + }, + icon : { + value : false, + validator : Y.Lang.isObject + }, + expandable : { + value : false, + validator : Y.Lang.isBool + }, + hidden : { + value : false, + validator : Y.Lang.isBool + }, + haschildren : { + value : false, + validator : Y.Lang.isBool + }, + children : { + value : [], + validator : Y.Lang.isArray + } + } +}); + +/** + * This namespace will contain all of the contents of the navigation blocks + * global navigation and settings. + * @namespace + */ +M.block_navigation = M.block_navigation || { + /** The number of expandable branches in existence */ + expandablebranchcount:1, + courselimit : 20, + instance : null, + /** + * Add new instance of navigation tree to tree collection + */ + init_add_tree:function(properties) { + if (properties.courselimit) { + this.courselimit = properties.courselimit; + } + if (M.core_dock) { + M.core_dock.init(Y); + } + new TREE(properties); + } +}; + + +}, '@VERSION@', { + "requires": [ + "base", + "core_dock", + "io-base", + "node", + "dom", + "event-custom", + "event-delegate", + "json-parse" + ] +}); diff --git a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js new file mode 100644 index 00000000000..2f091161889 --- /dev/null +++ b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation-min.js @@ -0,0 +1,2 @@ +YUI.add("moodle-block_navigation-navigation",function(e,t){e.Event.define("actionkey",{_event:e.UA.webkit||e.UA.ie?"keydown":"keypress",_keys:{37:"collapse",39:"expand",32:"toggle",13:"enter"},_keyHandler:function(e,t,n){var r;n.actions?r=n.actions:r={collapse:!0,expand:!0,toggle:!0,enter:!0},this._keys[e.keyCode]&&r[this._keys[e.keyCode]]&&(e.action=this._keys[e.keyCode],t.fire(e))},on:function(e,t,n){t.args===null?t._detacher=e.on(this._event,this._keyHandler,this,n,{actions:!1}):t._detacher=e.on(this._event,this._keyHandler,this,n,t.args[0])},detach:function(e,t){t._detacher.detach()},delegate:function(e,t,n,r){t.args===null?t._delegateDetacher=e.delegate(this._event,this._keyHandler,r,this,n,{actions:!1}):t._delegateDetacher=e.delegate(this._event,this._keyHandler,r,this,n,t.args[0])},detachDelegate:function(e,t){t._delegateDetacher.detach()}});var n=0,r=40,i={ROOTNODE:0,SYSTEM:1,CATEGORY:10,MYCATEGORY:11,COURSE:20,SECTION:30,ACTIVITY:40,RESOURCE:50,CUSTOM:60,SETTING:70,USER:80,CONTAINER:90},s=function(){s.superclass.constructor.apply(this,arguments)};s.prototype={id:null,branches:[],initializer:function(t){this.id=t.id;var n=e.one("#inst"+t.id);if(n===null)return;e.delegate("click",this.toggleExpansion,n.one(".block_tree"),".tree_item.branch",this),e.delegate("actionkey",this.toggleExpansion,n.one(".block_tree"),".tree_item.branch",this);var r=[];t.expansions?r=t.expansions:window["navtreeexpansions"+t.id]&&(r=window["navtreeexpansions"+t.id]);for(var i in r){var s=(new BRANCH({tree:this,branchobj:r[i],overrides:{expandable:!0,children:[],haschildren:!0}})).wire();M.block_navigation.expandablebranchcount++,this.branches[s.get("id")]=s}M.block_navigation.expandablebranchcount>0&&(e.delegate("click",this.fire_branch_action,n.one(".block_tree"),".tree_item.branch[data-expandable]",this),e.delegate("actionkey",this.fire_branch_action,n.one(".block_tree"),".tree_item.branch[data-expandable]",this)),this.get("candock")&&this.initialise_block(e,n)},fire_branch_action:function(e){var t=e.currentTarget.getAttribute("id"),n=this.branches[t];n.ajaxLoad(e)},toggleExpansion:function(e){if(!(!e.target.test("a")||e.keyCode!==0&&e.keyCode!==13)){e.stopPropagation();return}var t=e.target;t.test("li")||(t=t.ancestor("li"));if(!t)return;if(!t.hasClass("depth_1"))if(e.type==="actionkey"){switch(e.action){case"expand":t.removeClass("collapsed"),t.set("aria-expanded",!0);break;case"collapse":t.addClass("collapsed"),t.set("aria-expanded",!1);break;default:t.toggleClass("collapsed"),t.set("aria-expanded",!t.hasClass("collapsed"))}e.halt()}else t.toggleClass("collapsed"),t.set("aria-expanded",!t.hasClass("collapsed"));this.get("accordian")&&t.siblings("li").each(function(){this.get("id")!==t.get("id")&&!this.hasClass("collapsed")&&(this.addClass("collapsed"),this.set("aria-expanded",!1))});if(this.get("candock")){M.core_dock.resize();var n=M.core_dock.getPanel();n.visible&&n.correctWidth()}}},e.extend(s,e.Base,s.prototype,{NAME:"navigation-tree",ATTRS:{instance:{value:null},candock:{validator:e.Lang.isBool,value:!1},accordian:{validator:e.Lang.isBool,value:!1},expansionlimit:{value:0,setter:function(e){return parseInt(e,10)}}}}),M.core_dock&&M.core_dock.genericblock&&e.augment(s,M.core_dock.genericblock),BRANCH=function(){BRANCH.superclass.constructor.apply(this,arguments)},BRANCH.prototype={node:null,initializer:function(t){var i,s;if(t.branchobj!==null){for(i in t.branchobj)this.set(i,t.branchobj[i]);s=this.get("children"),this.set("haschildren",s.length>0)}if(t.overrides!==null)for(i in t.overrides)this.set(i,t.overrides[i]);this.node=e.one("#",this.get("id"));var o=this.get("tree").get("expansionlimit"),u=this.get("type");o!==n&&u>=o&&u<=r&&(this.set("expandable",!1),this.set("haschildren",!1))},draw:function(t){var n=this.get("expandable")||this.get("haschildren"),r=e.Node.create("
  • "),s=this.get("link"),o=e.Node.create('

    ').setAttribute("id",this.get("id"));s||o.setAttribute("tabindex","0"),n&&(r.addClass("collapsed").addClass("contains_branch"),r.set("aria-expanded",!1),o.addClass("branch"));var u=!1,a=this.get("icon");if(a&&(!n||this.get("type")==i.ACTIVITY)){u=e.Node.create(''),u.setAttribute("src",M.util.image_url(a.pix,a.component)),r.addClass("item_with_icon"),a.alt&&u.setAttribute("alt",a.alt),a.title&&u.setAttribute("title",a.title);if(a.classes)for(var f in a.classes)u.addClass(a.classes[f])}if(!s)u&&o.appendChild(u),o.append(this.get("name"));else{var l=e.Node.create('');u&&l.appendChild(u),l.append(this.get("name")),this.get("hidden")&&l.addClass("dimmed"),o.appendChild(l)}return r.appendChild(o),t.appendChild(r),this.node=o,this},wire:function(){return this.node=this.node||e.one("#"+this.get("id")),this.node?(this.get("expandable")&&(this.node.setAttribute("data-expandable","1"),this.node.setAttribute("data-loaded","0")),this):!1},getChildrenUL:function(){var t=this.node.next("ul");return t||(t=e.Node.create(""),this.node.ancestor().append(t)),t},ajaxLoad:function(t){t.type==="actionkey"&&t.action!=="enter"?t.halt():t.stopPropagation();if(t.type==="actionkey"&&t.action==="enter"&&t.target.test("A"))return this.node.setAttribute("data-expandable","0"),this.node.setAttribute("data-loaded","1"),!0;if(this.node.hasClass("loadingbranch"))return!0;if(this.node.getAttribute("data-loaded")==="1")return!0;this.node.addClass("loadingbranch");var n={elementid:this.get("id"),id:this.get("key"),type:this.get("type"),sesskey:M.cfg.sesskey,instance:this.get("tree").get("instance")};return e.io(M.cfg.wwwroot+"/lib/ajax/getnavbranch.php",{method:"POST",data:build_querystring(n),on:{complete:this.ajaxProcessResponse},context:this}),!0},ajaxProcessResponse:function(t,n){this.node.removeClass("loadingbranch"),this.node.setAttribute("data-loaded","1");try{var r=e.JSON.parse(n.responseText);if(r.children&&r.children.length>0){var s=0;for(var o in r.children)typeof r.children[o]=="object"&&(r.children[o].type== +i.COURSE&&s++,this.addChild(r.children[o]));return(this.get("type")==i.CATEGORY||this.get("type")==i.ROOTNODE||this.get("type")==i.MYCATEGORY)&&s>=M.block_navigation.courselimit&&this.addViewAllCoursesChild(this),!0}}catch(u){}return this.node.replaceClass("branch","emptybranch"),!0},addChild:function(e){var t=new BRANCH({tree:this.get("tree"),branchobj:e});if(t.draw(this.getChildrenUL())){this.get("tree").branches[t.get("id")]=t,t.wire();var n=0,r,s=t.get("children");for(r in s)s[r].type==i.COURSE&&n++,typeof s[r]=="object"&&t.addChild(s[r]);(t.get("type")==i.CATEGORY||t.get("type")==i.MYCATEGORY)&&n>=M.block_navigation.courselimit&&this.addViewAllCoursesChild(t)}return!0},addViewAllCoursesChild:function(e){var t=null;e.get("type")==i.ROOTNODE?e.get("key")==="mycourses"?t=M.cfg.wwwroot+"/my":t=M.cfg.wwwroot+"/course/index.php":t=M.cfg.wwwroot+"/course/category.php?id="+e.get("key"),e.addChild({name:M.str.moodle.viewallcourses,title:M.str.moodle.viewallcourses,link:t,haschildren:!1,icon:{pix:"i/navigationitem",component:"moodle"}})}},e.extend(BRANCH,e.Base,BRANCH.prototype,{NAME:"navigation-branch",ATTRS:{tree:{validator:e.Lang.isObject},name:{value:"",validator:e.Lang.isString,setter:function(e){return e.replace(/\n/g,"
    ")}},title:{value:"",validator:e.Lang.isString},id:{value:"",validator:e.Lang.isString,getter:function(e){return e===""&&(e="expandable_branch_"+M.block_navigation.expandablebranchcount,M.block_navigation.expandablebranchcount++),e}},key:{value:null},type:{value:null},link:{value:!1},icon:{value:!1,validator:e.Lang.isObject},expandable:{value:!1,validator:e.Lang.isBool},hidden:{value:!1,validator:e.Lang.isBool},haschildren:{value:!1,validator:e.Lang.isBool},children:{value:[],validator:e.Lang.isArray}}}),M.block_navigation=M.block_navigation||{expandablebranchcount:1,courselimit:20,instance:null,init_add_tree:function(t){t.courselimit&&(this.courselimit=t.courselimit),M.core_dock&&M.core_dock.init(e),new s(t)}}},"@VERSION@",{requires:["base","core_dock","io-base","node","dom","event-custom","event-delegate","json-parse"]}); diff --git a/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js new file mode 100644 index 00000000000..9ba9df72208 --- /dev/null +++ b/blocks/navigation/yui/build/moodle-block_navigation-navigation/moodle-block_navigation-navigation.js @@ -0,0 +1,639 @@ +YUI.add('moodle-block_navigation-navigation', function (Y, NAME) { + +/** + * A 'actionkey' Event to help with Y.delegate(). + * The event consists of the left arrow, right arrow, enter and space keys. + * More keys can be mapped to action meanings. + * actions: collapse , expand, toggle, enter. + * + * This event is delegated to branches in the navigation tree. + * The on() method to subscribe allows specifying the desired trigger actions as JSON. + * + * Todo: This could be centralised, a similar Event is defined in blocks/dock.js + */ +Y.Event.define("actionkey", { + // Webkit and IE repeat keydown when you hold down arrow keys. + // Opera links keypress to page scroll; others keydown. + // Firefox prevents page scroll via preventDefault() on either + // keydown or keypress. + _event: (Y.UA.webkit || Y.UA.ie) ? 'keydown' : 'keypress', + + _keys: { + //arrows + '37': 'collapse', + '39': 'expand', + //(@todo: lrt/rtl/M.core_dock.cfg.orientation decision to assign arrow to meanings) + '32': 'toggle', + '13': 'enter' + }, + + _keyHandler: function (e, notifier, args) { + var actObj; + if (!args.actions) { + actObj = {collapse:true, expand:true, toggle:true, enter:true}; + } else { + actObj = args.actions; + } + if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) { + e.action = this._keys[e.keyCode]; + notifier.fire(e); + } + }, + + on: function (node, sub, notifier) { + // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions). + if (sub.args === null) { + //no actions given + sub._detacher = node.on(this._event, this._keyHandler,this, notifier, {actions:false}); + } else { + sub._detacher = node.on(this._event, this._keyHandler,this, notifier, sub.args[0]); + } + }, + + detach: function (node, sub) { + //detach our _detacher handle of the subscription made in on() + sub._detacher.detach(); + }, + + delegate: function (node, sub, notifier, filter) { + // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions). + if (sub.args === null) { + //no actions given + sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, {actions:false}); + } else { + sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, sub.args[0]); + } + }, + + detachDelegate: function (node, sub) { + sub._delegateDetacher.detach(); + } +}); + +var EXPANSIONLIMIT_EVERYTHING = 0, + //EXPANSIONLIMIT_COURSE = 20, + //EXPANSIONLIMIT_SECTION = 30, + EXPANSIONLIMIT_ACTIVITY = 40; + +/** + * Mappings for the different types of nodes coming from the navigation. + * Copied from lib/navigationlib.php navigation_node constants. + * @type object + */ +var NODETYPE = { + /** @type int Root node = 0 */ + ROOTNODE : 0, + /** @type int System context = 1 */ + SYSTEM : 1, + /** @type int Course category = 10 */ + CATEGORY : 10, + /** @type int MYCATEGORY = 11 */ + MYCATEGORY : 11, + /** @type int Course = 20 */ + COURSE : 20, + /** @type int Course section = 30 */ + SECTION : 30, + /** @type int Activity (course module) = 40 */ + ACTIVITY : 40, + /** @type int Resource (course module = 50 */ + RESOURCE : 50, + /** @type int Custom node (could be anything) = 60 */ + CUSTOM : 60, + /** @type int Setting = 70 */ + SETTING : 70, + /** @type int User context = 80 */ + USER : 80, + /** @type int Container = 90 */ + CONTAINER : 90 +}; + +/** + * Navigation tree class. + * + * This class establishes the tree initially, creating expandable branches as + * required, and delegating the expand/collapse event. + */ +var TREE = function() { + TREE.superclass.constructor.apply(this, arguments); +}; +TREE.prototype = { + /** + * The tree's ID, normally its block instance id. + */ + id : null, + /** + * An array of initialised branches. + */ + branches : [], + /** + * Initialise the tree object when its first created. + */ + initializer : function(config) { + this.id = config.id; + + var node = Y.one('#inst'+config.id); + + // Can't find the block instance within the page + if (node === null) { + return; + } + + // Delegate event to toggle expansion + Y.delegate('click', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this); + Y.delegate('actionkey', this.toggleExpansion, node.one('.block_tree'), '.tree_item.branch', this); + + // Gather the expandable branches ready for initialisation. + var expansions = []; + if (config.expansions) { + expansions = config.expansions; + } else if (window['navtreeexpansions'+config.id]) { + expansions = window['navtreeexpansions'+config.id]; + } + // Establish each expandable branch as a tree branch. + for (var i in expansions) { + var branch = new BRANCH({ + tree:this, + branchobj:expansions[i], + overrides : { + expandable : true, + children : [], + haschildren : true + } + }).wire(); + M.block_navigation.expandablebranchcount++; + this.branches[branch.get('id')] = branch; + } + if (M.block_navigation.expandablebranchcount > 0) { + // Delegate some events to handle AJAX loading. + Y.delegate('click', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this); + Y.delegate('actionkey', this.fire_branch_action, node.one('.block_tree'), '.tree_item.branch[data-expandable]', this); + } + + // Call the generic blocks init method to add all the generic stuff + if (this.get('candock')) { + this.initialise_block(Y, node); + } + }, + /** + * Fire actions for a branch when an event occurs. + */ + fire_branch_action : function(event) { + var id = event.currentTarget.getAttribute('id'); + var branch = this.branches[id]; + branch.ajaxLoad(event); + }, + /** + * This is a callback function responsible for expanding and collapsing the + * branches of the tree. It is delegated to rather than multiple event handles. + */ + toggleExpansion : function(e) { + // First check if they managed to click on the li iteslf, then find the closest + // LI ancestor and use that + + if (e.target.test('a') && (e.keyCode === 0 || e.keyCode === 13)) { + // A link has been clicked (or keypress is 'enter') don't fire any more events just do the default. + e.stopPropagation(); + return; + } + + // Makes sure we can get to the LI containing the branch. + var target = e.target; + if (!target.test('li')) { + target = target.ancestor('li'); + } + if (!target) { + return; + } + + // Toggle expand/collapse providing its not a root level branch. + if (!target.hasClass('depth_1')) { + if (e.type === 'actionkey') { + switch (e.action) { + case 'expand' : + target.removeClass('collapsed'); + target.set('aria-expanded', true); + break; + case 'collapse' : + target.addClass('collapsed'); + target.set('aria-expanded', false); + break; + default : + target.toggleClass('collapsed'); + target.set('aria-expanded', !target.hasClass('collapsed')); + } + e.halt(); + } else { + target.toggleClass('collapsed'); + target.set('aria-expanded', !target.hasClass('collapsed')); + } + } + + // If the accordian feature has been enabled collapse all siblings. + if (this.get('accordian')) { + target.siblings('li').each(function(){ + if (this.get('id') !== target.get('id') && !this.hasClass('collapsed')) { + this.addClass('collapsed'); + this.set('aria-expanded', false); + } + }); + } + + // If this block can dock tell the dock to resize if required and check + // the width on the dock panel in case it is presently in use. + if (this.get('candock')) { + M.core_dock.resize(); + var panel = M.core_dock.getPanel(); + if (panel.visible) { + panel.correctWidth(); + } + } + } +}; +// The tree extends the YUI base foundation. +Y.extend(TREE, Y.Base, TREE.prototype, { + NAME : 'navigation-tree', + ATTRS : { + instance : { + value : null + }, + candock : { + validator : Y.Lang.isBool, + value : false + }, + accordian : { + validator : Y.Lang.isBool, + value : false + }, + expansionlimit : { + value : 0, + setter : function(val) { + return parseInt(val, 10); + } + } + } +}); +if (M.core_dock && M.core_dock.genericblock) { + Y.augment(TREE, M.core_dock.genericblock); +} + +/** + * The tree branch class. + * This class is used to manage a tree branch, in particular its ability to load + * its contents by AJAX. + */ +BRANCH = function() { + BRANCH.superclass.constructor.apply(this, arguments); +}; +BRANCH.prototype = { + /** + * The node for this branch (p) + */ + node : null, + /** + * Initialises the branch when it is first created. + */ + initializer : function(config) { + var i, + children; + if (config.branchobj !== null) { + // Construct from the provided xml + for (i in config.branchobj) { + this.set(i, config.branchobj[i]); + } + children = this.get('children'); + this.set('haschildren', (children.length > 0)); + } + if (config.overrides !== null) { + // Construct from the provided xml + for (i in config.overrides) { + this.set(i, config.overrides[i]); + } + } + // Get the node for this branch + this.node = Y.one('#', this.get('id')); + // Now check whether the branch is not expandable because of the expansionlimit + var expansionlimit = this.get('tree').get('expansionlimit'); + var type = this.get('type'); + if (expansionlimit !== EXPANSIONLIMIT_EVERYTHING && type >= expansionlimit && type <= EXPANSIONLIMIT_ACTIVITY) { + this.set('expandable', false); + this.set('haschildren', false); + } + }, + /** + * Draws the branch within the tree. + * + * This function creates a DOM structure for the branch and then injects + * it into the navigation tree at the correct point. + */ + draw : function(element) { + + var isbranch = (this.get('expandable') || this.get('haschildren')); + var branchli = Y.Node.create('
  • '); + var link = this.get('link'); + var branchp = Y.Node.create('

    ').setAttribute('id', this.get('id')); + if (!link) { + //add tab focus if not link (so still one focus per menu node). + // it was suggested to have 2 foci. one for the node and one for the link in MDL-27428. + branchp.setAttribute('tabindex', '0'); + } + if (isbranch) { + branchli.addClass('collapsed').addClass('contains_branch'); + branchli.set('aria-expanded', false); + branchp.addClass('branch'); + } + + // Prepare the icon, should be an object representing a pix_icon + var branchicon = false; + var icon = this.get('icon'); + if (icon && (!isbranch || this.get('type') == NODETYPE.ACTIVITY)) { + branchicon = Y.Node.create(''); + branchicon.setAttribute('src', M.util.image_url(icon.pix, icon.component)); + branchli.addClass('item_with_icon'); + if (icon.alt) { + branchicon.setAttribute('alt', icon.alt); + } + if (icon.title) { + branchicon.setAttribute('title', icon.title); + } + if (icon.classes) { + for (var i in icon.classes) { + branchicon.addClass(icon.classes[i]); + } + } + } + + if (!link) { + if (branchicon) { + branchp.appendChild(branchicon); + } + branchp.append(this.get('name')); + } else { + var branchlink = Y.Node.create(''); + if (branchicon) { + branchlink.appendChild(branchicon); + } + branchlink.append(this.get('name')); + if (this.get('hidden')) { + branchlink.addClass('dimmed'); + } + branchp.appendChild(branchlink); + } + + branchli.appendChild(branchp); + element.appendChild(branchli); + this.node = branchp; + return this; + }, + /** + * Attaches required events to the branch structure. + */ + wire : function() { + this.node = this.node || Y.one('#'+this.get('id')); + if (!this.node) { + return false; + } + if (this.get('expandable')) { + this.node.setAttribute('data-expandable', '1'); + this.node.setAttribute('data-loaded', '0'); + } + return this; + }, + /** + * Gets the UL element that children for this branch should be inserted into. + */ + getChildrenUL : function() { + var ul = this.node.next('ul'); + if (!ul) { + ul = Y.Node.create(''); + this.node.ancestor().append(ul); + } + return ul; + }, + /** + * Load the content of the branch via AJAX. + * + * This function calls ajaxProcessResponse with the result of the AJAX + * request made here. + */ + ajaxLoad : function(e) { + if (e.type === 'actionkey' && e.action !== 'enter') { + e.halt(); + } else { + e.stopPropagation(); + } + if (e.type === 'actionkey' && e.action === 'enter' && e.target.test('A')) { + // No ajaxLoad for enter. + this.node.setAttribute('data-expandable', '0'); + this.node.setAttribute('data-loaded', '1'); + return true; + } + + if (this.node.hasClass('loadingbranch')) { + // Already loading. Just skip. + return true; + } + + if (this.node.getAttribute('data-loaded') === '1') { + // We've already loaded this stuff. + return true; + } + this.node.addClass('loadingbranch'); + + var params = { + elementid : this.get('id'), + id : this.get('key'), + type : this.get('type'), + sesskey : M.cfg.sesskey, + instance : this.get('tree').get('instance') + }; + + Y.io(M.cfg.wwwroot+'/lib/ajax/getnavbranch.php', { + method:'POST', + data: build_querystring(params), + on: { + complete: this.ajaxProcessResponse + }, + context:this + }); + return true; + }, + /** + * Processes an AJAX request to load the content of this branch through + * AJAX. + */ + ajaxProcessResponse : function(tid, outcome) { + this.node.removeClass('loadingbranch'); + this.node.setAttribute('data-loaded', '1'); + try { + var object = Y.JSON.parse(outcome.responseText); + if (object.children && object.children.length > 0) { + var coursecount = 0; + for (var i in object.children) { + if (typeof(object.children[i])==='object') { + if (object.children[i].type == NODETYPE.COURSE) { + coursecount++; + } + this.addChild(object.children[i]); + } + } + if ((this.get('type') == NODETYPE.CATEGORY || this.get('type') == NODETYPE.ROOTNODE || this.get('type') == NODETYPE.MYCATEGORY) + && coursecount >= M.block_navigation.courselimit) { + this.addViewAllCoursesChild(this); + } + return true; + } + } catch (ex) { + // If we got here then there was an error parsing the result + } + // The branch is empty so class it accordingly + this.node.replaceClass('branch', 'emptybranch'); + return true; + }, + /** + * Turns the branch object passed to the method into a proper branch object + * and then adds it as a child of this branch. + */ + addChild : function(branchobj) { + // Make the new branch into an object + var branch = new BRANCH({tree:this.get('tree'), branchobj:branchobj}); + if (branch.draw(this.getChildrenUL())) { + this.get('tree').branches[branch.get('id')] = branch; + branch.wire(); + var count = 0, i, children = branch.get('children'); + for (i in children) { + // Add each branch to the tree + if (children[i].type == NODETYPE.COURSE) { + count++; + } + if (typeof(children[i]) === 'object') { + branch.addChild(children[i]); + } + } + if ((branch.get('type') == NODETYPE.CATEGORY || branch.get('type') == NODETYPE.MYCATEGORY) + && count >= M.block_navigation.courselimit) { + this.addViewAllCoursesChild(branch); + } + } + return true; + }, + + /** + * Add a link to view all courses in a category + */ + addViewAllCoursesChild: function(branch) { + var url = null; + if (branch.get('type') == NODETYPE.ROOTNODE) { + if (branch.get('key') === 'mycourses') { + url = M.cfg.wwwroot + '/my'; + } else { + url = M.cfg.wwwroot + '/course/index.php'; + } + } else { + url = M.cfg.wwwroot+'/course/category.php?id=' + branch.get('key'); + } + branch.addChild({ + name : M.str.moodle.viewallcourses, + title : M.str.moodle.viewallcourses, + link : url, + haschildren : false, + icon : {'pix':"i/navigationitem",'component':'moodle'} + }); + } +}; +Y.extend(BRANCH, Y.Base, BRANCH.prototype, { + NAME : 'navigation-branch', + ATTRS : { + tree : { + validator : Y.Lang.isObject + }, + name : { + value : '', + validator : Y.Lang.isString, + setter : function(val) { + return val.replace(/\n/g, '
    '); + } + }, + title : { + value : '', + validator : Y.Lang.isString + }, + id : { + value : '', + validator : Y.Lang.isString, + getter : function(val) { + if (val === '') { + val = 'expandable_branch_'+M.block_navigation.expandablebranchcount; + M.block_navigation.expandablebranchcount++; + } + return val; + } + }, + key : { + value : null + }, + type : { + value : null + }, + link : { + value : false + }, + icon : { + value : false, + validator : Y.Lang.isObject + }, + expandable : { + value : false, + validator : Y.Lang.isBool + }, + hidden : { + value : false, + validator : Y.Lang.isBool + }, + haschildren : { + value : false, + validator : Y.Lang.isBool + }, + children : { + value : [], + validator : Y.Lang.isArray + } + } +}); + +/** + * This namespace will contain all of the contents of the navigation blocks + * global navigation and settings. + * @namespace + */ +M.block_navigation = M.block_navigation || { + /** The number of expandable branches in existence */ + expandablebranchcount:1, + courselimit : 20, + instance : null, + /** + * Add new instance of navigation tree to tree collection + */ + init_add_tree:function(properties) { + if (properties.courselimit) { + this.courselimit = properties.courselimit; + } + if (M.core_dock) { + M.core_dock.init(Y); + } + new TREE(properties); + } +}; + + +}, '@VERSION@', { + "requires": [ + "base", + "core_dock", + "io-base", + "node", + "dom", + "event-custom", + "event-delegate", + "json-parse" + ] +}); diff --git a/blocks/navigation/yui/src/navigation/build.json b/blocks/navigation/yui/src/navigation/build.json new file mode 100644 index 00000000000..5e28a6c024b --- /dev/null +++ b/blocks/navigation/yui/src/navigation/build.json @@ -0,0 +1,10 @@ +{ + "name": "moodle-block_navigation-navigation", + "builds": { + "moodle-block_navigation-navigation": { + "jsfiles": [ + "navigation.js" + ] + } + } +} diff --git a/blocks/navigation/yui/navigation/navigation.js b/blocks/navigation/yui/src/navigation/js/navigation.js similarity index 93% rename from blocks/navigation/yui/navigation/navigation.js rename to blocks/navigation/yui/src/navigation/js/navigation.js index b513e56e960..eee568f1707 100644 --- a/blocks/navigation/yui/navigation/navigation.js +++ b/blocks/navigation/yui/src/navigation/js/navigation.js @@ -1,5 +1,3 @@ -YUI.add('moodle-block_navigation-navigation', function(Y){ - /** * A 'actionkey' Event to help with Y.delegate(). * The event consists of the left arrow, right arrow, enter and space keys. @@ -28,10 +26,11 @@ Y.Event.define("actionkey", { }, _keyHandler: function (e, notifier, args) { + var actObj; if (!args.actions) { - var actObj = {collapse:true, expand:true, toggle:true, enter:true}; + actObj = {collapse:true, expand:true, toggle:true, enter:true}; } else { - var actObj = args.actions; + actObj = args.actions; } if (this._keys[e.keyCode] && actObj[this._keys[e.keyCode]]) { e.action = this._keys[e.keyCode]; @@ -41,7 +40,7 @@ Y.Event.define("actionkey", { on: function (node, sub, notifier) { // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions). - if (sub.args == null) { + if (sub.args === null) { //no actions given sub._detacher = node.on(this._event, this._keyHandler,this, notifier, {actions:false}); } else { @@ -49,14 +48,14 @@ Y.Event.define("actionkey", { } }, - detach: function (node, sub, notifier) { + detach: function (node, sub) { //detach our _detacher handle of the subscription made in on() sub._detacher.detach(); }, delegate: function (node, sub, notifier, filter) { // subscribe to _event and ask keyHandler to handle with given args[0] (the desired actions). - if (sub.args == null) { + if (sub.args === null) { //no actions given sub._delegateDetacher = node.delegate(this._event, this._keyHandler,filter, this, notifier, {actions:false}); } else { @@ -64,14 +63,14 @@ Y.Event.define("actionkey", { } }, - detachDelegate: function (node, sub, notifier) { + detachDelegate: function (node, sub) { sub._delegateDetacher.detach(); } }); var EXPANSIONLIMIT_EVERYTHING = 0, - EXPANSIONLIMIT_COURSE = 20, - EXPANSIONLIMIT_SECTION = 30, + //EXPANSIONLIMIT_COURSE = 20, + //EXPANSIONLIMIT_SECTION = 30, EXPANSIONLIMIT_ACTIVITY = 40; /** @@ -104,7 +103,7 @@ var NODETYPE = { USER : 80, /** @type int Container = 90 */ CONTAINER : 90 -} +}; /** * Navigation tree class. @@ -112,9 +111,9 @@ var NODETYPE = { * This class establishes the tree initially, creating expandable branches as * required, and delegating the expand/collapse event. */ -var TREE = function(config) { +var TREE = function() { TREE.superclass.constructor.apply(this, arguments); -} +}; TREE.prototype = { /** * The tree's ID, normally its block instance id. @@ -189,7 +188,7 @@ TREE.prototype = { // First check if they managed to click on the li iteslf, then find the closest // LI ancestor and use that - if (e.target.test('a') && (e.keyCode == 0 || e.keyCode == 13)) { + if (e.target.test('a') && (e.keyCode === 0 || e.keyCode === 13)) { // A link has been clicked (or keypress is 'enter') don't fire any more events just do the default. e.stopPropagation(); return; @@ -198,7 +197,7 @@ TREE.prototype = { // Makes sure we can get to the LI containing the branch. var target = e.target; if (!target.test('li')) { - target = target.ancestor('li') + target = target.ancestor('li'); } if (!target) { return; @@ -206,7 +205,7 @@ TREE.prototype = { // Toggle expand/collapse providing its not a root level branch. if (!target.hasClass('depth_1')) { - if (e.type == 'actionkey') { + if (e.type === 'actionkey') { switch (e.action) { case 'expand' : target.removeClass('collapsed'); @@ -247,7 +246,7 @@ TREE.prototype = { } } } -} +}; // The tree extends the YUI base foundation. Y.extend(TREE, Y.Base, TREE.prototype, { NAME : 'navigation-tree', @@ -266,7 +265,7 @@ Y.extend(TREE, Y.Base, TREE.prototype, { expansionlimit : { value : 0, setter : function(val) { - return parseInt(val); + return parseInt(val, 10); } } } @@ -280,9 +279,9 @@ if (M.core_dock && M.core_dock.genericblock) { * This class is used to manage a tree branch, in particular its ability to load * its contents by AJAX. */ -var BRANCH = function(config) { +BRANCH = function() { BRANCH.superclass.constructor.apply(this, arguments); -} +}; BRANCH.prototype = { /** * The node for this branch (p) @@ -292,17 +291,19 @@ BRANCH.prototype = { * Initialises the branch when it is first created. */ initializer : function(config) { + var i, + children; if (config.branchobj !== null) { // Construct from the provided xml - for (var i in config.branchobj) { + for (i in config.branchobj) { this.set(i, config.branchobj[i]); } - var children = this.get('children'); + children = this.get('children'); this.set('haschildren', (children.length > 0)); } if (config.overrides !== null) { // Construct from the provided xml - for (var i in config.overrides) { + for (i in config.overrides) { this.set(i, config.overrides[i]); } } @@ -311,7 +312,7 @@ BRANCH.prototype = { // Now check whether the branch is not expandable because of the expansionlimit var expansionlimit = this.get('tree').get('expansionlimit'); var type = this.get('type'); - if (expansionlimit != EXPANSIONLIMIT_EVERYTHING && type >= expansionlimit && type <= EXPANSIONLIMIT_ACTIVITY) { + if (expansionlimit !== EXPANSIONLIMIT_EVERYTHING && type >= expansionlimit && type <= EXPANSIONLIMIT_ACTIVITY) { this.set('expandable', false); this.set('haschildren', false); } @@ -413,12 +414,12 @@ BRANCH.prototype = { * request made here. */ ajaxLoad : function(e) { - if (e.type == 'actionkey' && e.action != 'enter') { + if (e.type === 'actionkey' && e.action !== 'enter') { e.halt(); } else { e.stopPropagation(); } - if (e.type = 'actionkey' && e.action == 'enter' && e.target.test('A')) { + if (e.type === 'actionkey' && e.action === 'enter' && e.target.test('A')) { // No ajaxLoad for enter. this.node.setAttribute('data-expandable', '0'); this.node.setAttribute('data-loaded', '1'); @@ -466,7 +467,7 @@ BRANCH.prototype = { if (object.children && object.children.length > 0) { var coursecount = 0; for (var i in object.children) { - if (typeof(object.children[i])=='object') { + if (typeof(object.children[i])==='object') { if (object.children[i].type == NODETYPE.COURSE) { coursecount++; } @@ -502,7 +503,7 @@ BRANCH.prototype = { if (children[i].type == NODETYPE.COURSE) { count++; } - if (typeof(children[i])=='object') { + if (typeof(children[i]) === 'object') { branch.addChild(children[i]); } } @@ -536,7 +537,7 @@ BRANCH.prototype = { icon : {'pix':"i/navigationitem",'component':'moodle'} }); } -} +}; Y.extend(BRANCH, Y.Base, BRANCH.prototype, { NAME : 'navigation-branch', ATTRS : { @@ -558,7 +559,7 @@ Y.extend(BRANCH, Y.Base, BRANCH.prototype, { value : '', validator : Y.Lang.isString, getter : function(val) { - if (val == '') { + if (val === '') { val = 'expandable_branch_'+M.block_navigation.expandablebranchcount; M.block_navigation.expandablebranchcount++; } @@ -620,5 +621,3 @@ M.block_navigation = M.block_navigation || { new TREE(properties); } }; - -}, '@VERSION@', {requires:['base', 'core_dock', 'io-base', 'node', 'dom', 'event-custom', 'event-delegate', 'json-parse']}); diff --git a/blocks/navigation/yui/src/navigation/meta/navigation.json b/blocks/navigation/yui/src/navigation/meta/navigation.json new file mode 100644 index 00000000000..b4c37600ab5 --- /dev/null +++ b/blocks/navigation/yui/src/navigation/meta/navigation.json @@ -0,0 +1,14 @@ +{ + "moodle-block_navigation-navigation": { + "requires": [ + "base", + "core_dock", + "io-base", + "node", + "dom", + "event-custom", + "event-delegate", + "json-parse" + ] + } +}