1 /** 2 * @fileOverview Functionality for setting up Selector based Function mappings. 3 * @author <a href="http://www.bobs-bits.com">Stephen Reay</a> 4 */ 5 6 /** 7 * @namespace CSS Selector Based function mappings 8 */ 9 BTM.Mapping = {}; 10 11 /** 12 * BTM Mappings on/off flag 13 * @name BTM.options.runMappings 14 * @see BTM.Mapping.init 15 * @type Boolean 16 * @default true 17 * @field 18 */ 19 BTM.loadOption('runMappings', true); 20 21 /** 22 * The Array containing the functions to run 23 * @type {Array} 24 */ 25 BTM.Mapping.callbacks = []; 26 27 /** 28 * Flag to indicate if mappings have been run for the page 29 * @type {Boolean} 30 */ 31 BTM.Mapping.mappingsHaveRun = false; 32 33 /** 34 * Add an entry for a function to run on specified elements 35 * @param {String} selector the CSS selector string representing the target Elements 36 * @param {Function} callback the Function to call for each Element. The target Element will be passed as the first argument to the Function 37 * @param {Number} [initOrder=5] the "run-level" for this Mapping, lower levels run earlier. 38 * @returns {Number} the index where the new Mapping was created. This (along with the selector String) can be used to refer to the Mapping later, e.g. to remove it 39 */ 40 BTM.Mapping.add = function add(selector, callback, initOrder) { 41 42 initOrder = Object.isUndefined(initOrder) ? 5 : initOrder; 43 44 if (BTM.Mapping.mappingsHaveRun) { 45 return BTM.$$(selector).forEach(callback); 46 } 47 48 if (!BTM.Mapping.callbacks[initOrder]) { 49 BTM.Mapping.callbacks[initOrder] = {}; 50 } 51 52 if (!BTM.Mapping.callbacks[initOrder][selector]) { 53 BTM.Mapping.callbacks[initOrder][selector] = []; 54 } 55 var index = BTM.Mapping.callbacks[initOrder][selector].push(callback); 56 57 return index; 58 }; 59 60 /** 61 * Remove an entry from the Mappings Array 62 * @param {String} selector the CSS selector string representing the target Elements 63 * @param {Number} index the index of the Function in the Array. This is the value returned by @link{BTM.Mapping.add} 64 * @param {Number} [initOrder=5] the "run-level" to remove the Mapping from 65 * @returns {Function|Boolean} the Function that has been removed from the Mappings Array, or false if not found 66 */ 67 BTM.Mapping.remove = function remove(selector, index, initOrder) { 68 69 initOrder = Object.isUndefined(initOrder) ? 5 : initOrder; 70 71 if (BTM.Mapping.callbacks[initOrder] && BTM.Mapping.callbacks[initOrder][selector] && BTM.Mapping.callbacks[initOrder][selector][index]) { 72 var func = delete BTM.Mapping.callbacks[initOrder][selector][index]; 73 return func; 74 } 75 return false; 76 }; 77 78 /** 79 * Worker Function to run mappings 80 * @private 81 * @param {HTMLElement} container the Element to use as a base location when finding Elements to run Mappings on 82 * @param {Object|Function[]} mappings an Object containing an Array of Functions & the CSS Selector, or the Array of Functions 83 * @param {Number|String} level the Level of Mappings to run, or the CSS Selector to identify Elements 84 * @see BTM.Mapping.init 85 */ 86 BTM.Mapping.run = function run(container, mappings, level) { 87 if (Object.isObject(mappings)) { 88 BTM.log('Running Mappings at Level: ' + level); 89 Object.forEach(mappings, BTM.Mapping.run.curry(container), this); 90 } 91 else if (Object.isArray(mappings)) { 92 BTM.log('Running Mappings for Selector: ' + level); 93 var elements = BTM.$$(level, container); 94 for (var i = 0; i < mappings.length; i++) { 95 if (Object.isFunction(mappings[i])) { 96 elements.forEach(mappings[i]); 97 } 98 } 99 } 100 }; 101 102 /** 103 * Run the Mappings. If the BTM option "runMappings" is set to false, this will return false and not run 104 * @param {HTMLElement|String} [container=document.body] element ID or element reference to use as the base when selecting target Elements 105 * @returns {Number} time taken to run all Mappings 106 * @see BTM.options.runMappings 107 */ 108 BTM.Mapping.init = function init(container) { 109 if (!BTM.options.runMappings) { 110 return false; 111 } 112 container = BTM.$(container) || document; 113 BTM.log("Running all Mappings", container); 114 BTM.Mapping.mappingsHaveRun = true; 115 var startTime = new Date(); 116 BTM.Mapping.callbacks.forEach(BTM.Mapping.run.curry(container), this); 117 var finishTime = new Date(); 118 BTM.log("Mappings finished in " + ((finishTime - startTime)/1000) + " seconds"); 119 return finishTime - startTime; 120 }; 121 122 BTM.observe(document, 'DOMContentLoaded', BTM.Mapping.init);