1/* jQuery responsive breadcrumbs plugin jQuery plugin 2 * https://github.com/cm0s/jquery-rcrumbs 3 * 4 * Copyright (c) 2013, Nicolas Forney 5 * Released under the MIT licence 6 * 7 * version: 1.0.2 8 * 2013/05/12 9 */ 10(function ($, window, document, undefined) { 11 "use strict"; 12 13 var rcrumbs = 'rcrumbs', 14 defaults = { 15 version: '1.0.2', 16 callback: { 17 preCrumbsListDisplay: $.noop, //A function which is executed before the crumbs list is rendered 18 preCrumbDisplay: $.noop, //A function which is executed before each crumb is rendered 19 postCrumbsListDisplay: $.noop, //A function which is executed after the crumbs list is rendered 20 postCrumbDisplay: $.noop //A function which is executed after each crumb is rendered 21 }, 22 ellipsis: true, // Display ellipsis when only the last crumb remains with not enough space to be fully displayed 23 windowResize: true, // To activate/deactivate the resizing of the crumbs on window resize event 24 nbUncollapsableCrumbs: 2, // Number of crumbs which can not be collapsed. 25 animation: { 26 activated: true, // Activate an animation when crumbs are displayed/hidden on a window resize 27 speed: 400 // Animation speed (activated option must be set to true) 28 } 29 }; 30 31 // Plugin constructor 32 function Plugin(element, options) { 33 this.element = element; 34 this.$element = $(element); 35 36 //Merge defaults with given (use deep copy) 37 this.options = $.extend(true, {}, defaults, options); 38 39 this._defaults = defaults; 40 this._name = rcrumbs; 41 Plugin.prototype.plugin = this; 42 this._init(); 43 } 44 45 Plugin.prototype = { 46 47 version: function () { 48 return this.options.version; 49 }, 50 51 _init: function () { 52 //Ensure rcrumbs class is defined on the element in order to be able to correctly apply stylesheets 53 if (!this.$element.hasClass('rcrumbs')) { 54 this.$element.addClass('rcrumbs'); 55 } 56 57 //Variables declaration 58 this.nbCrumbDisplayed = 0; 59 this.$crumbsList = $('ul', this.element); 60 this.$crumbs = $('li', this.$crumbsList);
61 this.$lastCrumb = this.$crumbs.last(); 62 this.reversedCrumbs = $('li', this.$crumbsList).get().reverse(); 63 this.lastNbCrumbDisplayed = 0; 64 this.totalCrumbsWidth = 0; 65 66 this._initCrumbs(); 67 68 this._showOrHideCrumbsList(true); 69 70 if (this.options.windowResize) { 71 this._showOrHideCrumbsListOnWindowResize(); 72 } 73 }, 74 75 /** 76 * Get the width of a hidden DOM element without displaying it in the browser. 77 * @param element DOM element from which the width will be retrieved. 78 */ 79 _getHiddenElWidth: function (element) { 80 var result, 81 elementClone = $(element).clone(false); 82 83 elementClone.css({ 84 visibility: 'hidden', 85 position: 'absolute' 86 }); 87 88 elementClone.appendTo(this.$crumbsList); 89 90 result = elementClone.width(); 91 92 elementClone.remove(); 93 94 return result; 95 }, 96 97 _initCrumbs: function () { 98 var that = this; 99 100 //Remove text node in order to avoid displaying white spaces between li elements and thus make width 101 //calculation for the breadcrumbs resize easier. 102 $(this.$crumbsList).contents().filter(function () { 103 return this.nodeType === 3; //3 => Text node 104 }).remove(); 105 106 //For each li element save its width 107 $.each(this.$crumbs, function (key, value) { 108 var $crumb = $(this); 109 that._storeCrumbWidth($crumb); 110 }); 111 }, 112 113 /** 114 * Save width of the li element passed as parameter 115 * @param $crumb li element on which its width will be stored 116 * @return calculated crumb width 117 */ 118 _storeCrumbWidth: function ($crumb) { 119 var crumbWidth = this._getHiddenElWidth($crumb); 120 $crumb.data('width', crumbWidth); 121 return crumbWidth; 122 }, 123 124 /** 125 * @param disableAnimation used to disable the animation even if the animation.activated option is set to true. 126 */ 127 _showOrHideCrumbsList: function (disableAnimation) { 128 var that = this; 129 this.remainingSpaceToDisplayCrumbs = this.$element.width(); 130 this.nbCrumbDisplayed = 0; 131 this.totalCrumbsWidth = 0; 132 this.nextCrumbToShowWidth = undefined; 133 134 this.options.callback.preCrumbsListDisplay(this); 135 136 //It's important to loop through a reversed list in order to ensure we first try to display the last element 137 $.each(this.reversedCrumbs, function (key, value) { 138 var $crumb = $(this), 139 $nextCrumb = $(that.reversedCrumbs[key + 1]); //May return empty jQuery object 140 141 that._showOrHideCrumb($crumb, $nextCrumb, key, disableAnimation); 142 }); 143 144 this.lastNbCrumbDisplayed = this.nbCrumbDisplayed; 145 146 this.options.callback.postCrumbsListDisplay(this); 147 148 }, 149 150 _showOrHideCrumb: function ($crumb, $nextCrumb, crumbPosition, disableAnimation) { 151 this.options.callback.preCrumbDisplay($crumb); 152 var that = this; 153 this.remainingSpaceToDisplayCrumbs -= $crumb.data('width'); 154 155 if (crumbPosition < this.options.nbUncollapsableCrumbs) { 156 showCrumbWithOrWithoutAnimation(); 157 158 if (this.remainingSpaceToDisplayCrumbs < 0) { 159 enableEllipsis(this.$lastCrumb); 160 } 161 162 this.totalCrumbsWidth += $crumb.data('width'); 163 } else { 164 if (this.remainingSpaceToDisplayCrumbs >= 0) { 165 showCrumbWithOrWithoutAnimation(); 166 this.totalCrumbsWidth += $crumb.data('width'); 167 } else { 168 if (this.lastNbCrumbDisplayed > this.nbCrumbDisplayed - 1 && this.options.animation.activated) { 169 hideCrumbWithAnimation(); 170 } else { 171 $crumb.removeClass('show'); 172 } 173 174 if (!this.nextCrumbToShowWidth) { 175 this.nextCrumbToShowWidth = $crumb.data('width'); 176 } 177 } 178 } 179 180 function showCrumbWithOrWithoutAnimation() { 181 $crumb.addClass('show'); 182 183 if (that.lastNbCrumbDisplayed < (that.nbCrumbDisplayed + 1) && that.options.animation.activated && 184 !disableAnimation) { 185 $crumb.width(0); 186 $crumb.animate({width: $crumb.data('width')}, that.options.animation.speed, function () { 187 that.options.callback.postCrumbDisplay($crumb); 188 }); 189 } else { 190 that.options.callback.postCrumbDisplay($crumb); 191 } 192 that.nbCrumbDisplayed += 1; 193 } 194 195 function hideCrumbWithAnimation() { 196 $crumb.animate({width: 0}, that.options.animation.speed, function () { 197 $crumb.removeClass('show'); 198 }); 199 } 200 201 function enableEllipsis($crumb) { 202 $crumb.css({ 203 'width': (that.remainingSpaceToDisplayCrumbs + $crumb.data('width')) + 'px' 204 }); 205 $crumb.addClass('ellipsis'); 206 } 207 208 function disableEllipsis($crumb) { 209 $crumb.css({ 210 'width': 'auto' 211 }); 212 $crumb.removeClass('ellipsis'); 213 } 214 }, 215 216 _showOrHideCrumbsListOnWindowResize: function () { 217 var that = this; 218 $(window).resize(function () { 219 var rcrumbWidth = that.$element.width(); 220 if (rcrumbWidth < that.totalCrumbsWidth || (that.totalCrumbsWidth + that.nextCrumbToShowWidth) < rcrumbWidth) { 221 $.each(that.reversedCrumbs, function (key, value) { //Stop all crumbs animations 222 var $currentCrumb = $(this); 223 $currentCrumb.stop(true, true); 224 }); 225 226 that._showOrHideCrumbsList(); 227 } 228 //Disable ellipsis on the last crumb when there is enough space 229 if (rcrumbWidth >= that.totalCrumbsWidth && that.$lastCrumb.hasClass('ellipsis')) { 230 that._disableEllipsis(that.$lastCrumb); 231 } 232 }); 233 }, 234 235 _disableEllipsis: function ($crumb) { 236 $crumb.css({ 237 'width': 'auto' 238 }); 239 $crumb.removeClass('ellipsis'); 240 } 241 }; 242 243 244 $.fn[rcrumbs] = function (methodNameOrObject) { 245 // When the function parameter is a string the value is used to call the corresponding plugin method. If the 246 // argument is an object or a falsy value the Plugin is instantiated 247 // Only public method (not prefixed with an underscore) can be called. 248 if (Plugin.prototype[methodNameOrObject] && (methodNameOrObject.indexOf('_') === -1)) { 249 var plugin = $.data(this[0], 'plugin_' + rcrumbs); 250 if (plugin) { 251 //slice is used to pass all argument following the method n
251ame 252 return Plugin.prototype[methodNameOrObject].apply(plugin, Array.prototype.slice.call(arguments, 1)); 253 } else { 254 $.error('jquery.' + rcrumbs + ' plugin must be initialized first on the element'); 255 } 256 } else if (typeof methodNameOrObject === 'object' || !methodNameOrObject) { 257 // Plugin wrapper around the constructor to prevent against multiple instantiations 258 return this.each(function () { 259 if (!$.data(this, 'plugin_' + rcrumbs)) { 260 $.data(this, 'plugin_' + rcrumbs, new Plugin(this, methodNameOrObject)); 261 } else { 262 $.error('jquery.' + rcrumbs + ' plugin cannot be instantiated multiple times on same element'); 263 } 264 }); 265 } else { 266 $.error('Method ' + methodNameOrObject + ' does not exist on jquery.' + rcrumbs); 267 } 268 }; 269})(jQuery, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.