From 40e05a582cedb3645b044efe1d423a894288cb21 Mon Sep 17 00:00:00 2001 From: Gareth Simpson Date: Fri, 14 May 2021 13:20:35 +0100 Subject: [PATCH] Preserve HTML in breadcrumb labels. Fixes an XSS issue where otherwise escaped tags are reinserted as raw HTML. --- dist/jquery-asBreadcrumbs.es.js | 2 +- dist/jquery-asBreadcrumbs.js | 2 +- dist/jquery-asBreadcrumbs.min.js | 2 +- dist/jquery-asBreadcrumbs.min.js.map | 2 +- src/asBreadcrumbs.js | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dist/jquery-asBreadcrumbs.es.js b/dist/jquery-asBreadcrumbs.es.js index e4a6545..66b3870 100644 --- a/dist/jquery-asBreadcrumbs.es.js +++ b/dist/jquery-asBreadcrumbs.es.js @@ -136,7 +136,7 @@ class asBreadcrumbs { this.$children.each(function(){ const $this = $(this); const $link = that.options.getItemLink($this); - const $dropdownItem = $(that.options.dropdownItem.call(that, that.classes, $this.text(), $link.attr('href'))); + const $dropdownItem = $(that.options.dropdownItem.call(that, that.classes, $this.html(), $link.attr('href'))); that.items.push({ $this, diff --git a/dist/jquery-asBreadcrumbs.js b/dist/jquery-asBreadcrumbs.js index 8477be8..9dd0806 100644 --- a/dist/jquery-asBreadcrumbs.js +++ b/dist/jquery-asBreadcrumbs.js @@ -246,7 +246,7 @@ that.options.dropdownItem.call( that, that.classes, - $this.text(), + $this.html(), $link.attr('href') ) ); diff --git a/dist/jquery-asBreadcrumbs.min.js b/dist/jquery-asBreadcrumbs.min.js index e10abdb..698b192 100644 --- a/dist/jquery-asBreadcrumbs.min.js +++ b/dist/jquery-asBreadcrumbs.min.js @@ -5,5 +5,5 @@ * Copyright (c) amazingSurge * Released under the LGPL-3.0 license */ -!function(s,e){if("function"==typeof define&&define.amd)define(["jquery"],e);else if("undefined"!=typeof exports)e(require("jquery"));else{var t={exports:{}};e(s.jQuery),s.jqueryAsBreadcrumbsEs=t.exports}}(this,function(s){"use strict";function e(s,e){if(!(s instanceof e))throw new TypeError("Cannot call a class as a function")}var t=function(s){return s&&s.__esModule?s:{default:s}}(s),i=function(){function s(s,e){for(var t=0;t'+e+""},dropdown:function(s){var e="dropdown-menu";return"right"===this.options.overflow&&(e+=" dropdown-menu-right"),''},dropdownItem:function(s,e,t){return t?'
  • '+e+"
  • ":'
  • '+e+"
  • "},onInit:null,onReady:null},o=0,l=function(){function s(i,l){e(this,s),this.element=i,this.$element=(0,t.default)(i),this.options=t.default.extend({},n,l,this.$element.data()),this.namespace=this.options.namespace,this.$element.addClass(this.namespace),this.classes={toggleClass:this.options.toggleClass?this.options.toggleClass:this.namespace+"-toggle",toggleIconClass:this.options.toggleIconClass,dropdownClass:this.options.dropdownClass?this.options.dropdownClass:this.namespace+"-dropdown",dropdownMenuClass:this.options.dropdownMenuClass?this.options.dropdownMenuClass:this.namespace+"-dropdown-menu",dropdownItemClass:this.options.dropdownItemClass?this.options.dropdownItemClass:"",dropdownItemDisableClass:this.options.dropdownItemDisableClass?this.options.dropdownItemDisableClass:"",ellipsisClass:this.options.ellipsisClass?this.options.ellipsisClass:this.namespace+"-ellipsis",hiddenClass:this.options.hiddenClass},this.initialized=!1,this.instanceId=++o,this.$children=this.options.getItems(this.$element),this.$firstChild=this.$children.eq(0),this.$dropdown=null,this.$dropdownMenu=null,this.gap=6,this.items=[],this._trigger("init"),this.init()}return i(s,[{key:"init",value:function(){var s=this;this.$element.addClass(this.namespace+"-"+this.options.overflow),this._prepareItems(),this._createDropdown(),this._createEllipsis(),this.render(),this.options.responsive&&(0,t.default)(window).on(this.eventNameWithId("resize"),this._throttle(function(){s.resize()},250)),this.initialized=!0,this._trigger("ready")}},{key:"_prepareItems",value:function(){var s=this;this.$children.each(function(){var e=(0,t.default)(this),i=s.options.getItemLink(e),n=(0,t.default)(s.options.dropdownItem.call(s,s.classes,e.text(),i.attr("href")));s.items.push({$this:e,outerWidth:e.outerWidth(),$item:n})}),"left"===this.options.overflow&&this.items.reverse()}},{key:"_createDropdown",value:function(){this.$dropdown=(0,t.default)(this.options.dropdown.call(this,this.classes)).addClass(this.classes.hiddenClass).appendTo(this.$element),this.$dropdownMenu=this.$dropdown.find("."+this.classes.dropdownMenuClass),this._createDropdownItems(),"right"===this.options.overflow?this.$dropdown.appendTo(this.$element):this.$dropdown.prependTo(this.$element)}},{key:"_createDropdownItems",value:function(){for(var s=0;st?(i=!0,this._showDropdownItem(n)):this._hideDropdownItem(n);i?(this.$ellipsis.removeClass(this.classes.hiddenClass),this.$dropdown.removeClass(this.classes.hiddenClass)):(this.$ellipsis.addClass(this.classes.hiddenClass),this.$dropdown.addClass(this.classes.hiddenClass)),this._trigger("update")}},{key:"resize",value:function(){this.render()}},{key:"getDropdownWidth",value:function(){return this.$dropdown.outerWidth()+(this.options.ellipsisText?this.$ellipsis.outerWidth():0)}},{key:"getConatinerWidth",value:function(){var s=0,e=this;return this.$element.children().each(function(){"inline-block"===(0,t.default)(this).css("display")&&"none"===(0,t.default)(this).css("float")&&(s+=e.gap)}),this.$element.width()-s}},{key:"_showDropdownItem",value:function(s){this.items[s].$item.removeClass(this.classes.hiddenClass),this.items[s].$this.addClass(this.classes.hiddenClass)}},{key:"_hideDropdownItem",value:function(s){this.items[s].$this.removeClass(this.classes.hiddenClass),this.items[s].$item.addClass(this.classes.hiddenClass)}},{key:"_trigger",value:function(s){for(var e=arguments.length,t=Array(e>1?e-1:0),i=1;ie?(n&&(clearTimeout(n),n=null),r=c,a=s.apply(o,l),n||(o=l=null)):n||(n=setTimeout(d,f)),a}}},{key:"destroy",value:function(){this.$element.children().removeClass(this.classes.hiddenClass),this.$dropdown.remove(),this.options.ellipsisText&&this.$ellipsis.remove(),this.initialized=!1,this.$element.data("asBreadcrumbs",null),(0,t.default)(window).off(this.eventNameWithId("resize")),this._trigger("destroy")}}],[{key:"setDefaults",value:function(s){t.default.extend(n,t.default.isPlainObject(s)&&s)}}]),s}(),a={version:"0.2.3"},r="asBreadcrumbs",d=t.default.fn.asBreadcrumbs,h=function(s){for(var e=arguments.length,i=Array(e>1?e-1:0),n=1;n'+e+""},dropdown:function(s){var e="dropdown-menu";return"right"===this.options.overflow&&(e+=" dropdown-menu-right"),''},dropdownItem:function(s,e,t){return t?'
  • '+e+"
  • ":'
  • '+e+"
  • "},onInit:null,onReady:null},o=0,l=function(){function s(i,l){e(this,s),this.element=i,this.$element=(0,t.default)(i),this.options=t.default.extend({},n,l,this.$element.data()),this.namespace=this.options.namespace,this.$element.addClass(this.namespace),this.classes={toggleClass:this.options.toggleClass?this.options.toggleClass:this.namespace+"-toggle",toggleIconClass:this.options.toggleIconClass,dropdownClass:this.options.dropdownClass?this.options.dropdownClass:this.namespace+"-dropdown",dropdownMenuClass:this.options.dropdownMenuClass?this.options.dropdownMenuClass:this.namespace+"-dropdown-menu",dropdownItemClass:this.options.dropdownItemClass?this.options.dropdownItemClass:"",dropdownItemDisableClass:this.options.dropdownItemDisableClass?this.options.dropdownItemDisableClass:"",ellipsisClass:this.options.ellipsisClass?this.options.ellipsisClass:this.namespace+"-ellipsis",hiddenClass:this.options.hiddenClass},this.initialized=!1,this.instanceId=++o,this.$children=this.options.getItems(this.$element),this.$firstChild=this.$children.eq(0),this.$dropdown=null,this.$dropdownMenu=null,this.gap=6,this.items=[],this._trigger("init"),this.init()}return i(s,[{key:"init",value:function(){var s=this;this.$element.addClass(this.namespace+"-"+this.options.overflow),this._prepareItems(),this._createDropdown(),this._createEllipsis(),this.render(),this.options.responsive&&(0,t.default)(window).on(this.eventNameWithId("resize"),this._throttle(function(){s.resize()},250)),this.initialized=!0,this._trigger("ready")}},{key:"_prepareItems",value:function(){var s=this;this.$children.each(function(){var e=(0,t.default)(this),i=s.options.getItemLink(e),n=(0,t.default)(s.options.dropdownItem.call(s,s.classes,e.html(),i.attr("href")));s.items.push({$this:e,outerWidth:e.outerWidth(),$item:n})}),"left"===this.options.overflow&&this.items.reverse()}},{key:"_createDropdown",value:function(){this.$dropdown=(0,t.default)(this.options.dropdown.call(this,this.classes)).addClass(this.classes.hiddenClass).appendTo(this.$element),this.$dropdownMenu=this.$dropdown.find("."+this.classes.dropdownMenuClass),this._createDropdownItems(),"right"===this.options.overflow?this.$dropdown.appendTo(this.$element):this.$dropdown.prependTo(this.$element)}},{key:"_createDropdownItems",value:function(){for(var s=0;st?(i=!0,this._showDropdownItem(n)):this._hideDropdownItem(n);i?(this.$ellipsis.removeClass(this.classes.hiddenClass),this.$dropdown.removeClass(this.classes.hiddenClass)):(this.$ellipsis.addClass(this.classes.hiddenClass),this.$dropdown.addClass(this.classes.hiddenClass)),this._trigger("update")}},{key:"resize",value:function(){this.render()}},{key:"getDropdownWidth",value:function(){return this.$dropdown.outerWidth()+(this.options.ellipsisText?this.$ellipsis.outerWidth():0)}},{key:"getConatinerWidth",value:function(){var s=0,e=this;return this.$element.children().each(function(){"inline-block"===(0,t.default)(this).css("display")&&"none"===(0,t.default)(this).css("float")&&(s+=e.gap)}),this.$element.width()-s}},{key:"_showDropdownItem",value:function(s){this.items[s].$item.removeClass(this.classes.hiddenClass),this.items[s].$this.addClass(this.classes.hiddenClass)}},{key:"_hideDropdownItem",value:function(s){this.items[s].$this.removeClass(this.classes.hiddenClass),this.items[s].$item.addClass(this.classes.hiddenClass)}},{key:"_trigger",value:function(s){for(var e=arguments.length,t=Array(e>1?e-1:0),i=1;ie?(n&&(clearTimeout(n),n=null),r=c,a=s.apply(o,l),n||(o=l=null)):n||(n=setTimeout(d,f)),a}}},{key:"destroy",value:function(){this.$element.children().removeClass(this.classes.hiddenClass),this.$dropdown.remove(),this.options.ellipsisText&&this.$ellipsis.remove(),this.initialized=!1,this.$element.data("asBreadcrumbs",null),(0,t.default)(window).off(this.eventNameWithId("resize")),this._trigger("destroy")}}],[{key:"setDefaults",value:function(s){t.default.extend(n,t.default.isPlainObject(s)&&s)}}]),s}(),a={version:"0.2.3"},r="asBreadcrumbs",d=t.default.fn.asBreadcrumbs,h=function(s){for(var e=arguments.length,i=Array(e>1?e-1:0),n=1;n${label}`;\n },\n\n dropdown: function(classes) {\n const dropdownClass = 'dropdown';\n let dropdownMenuClass = 'dropdown-menu';\n\n if (this.options.overflow === 'right') {\n dropdownMenuClass += ' dropdown-menu-right';\n }\n\n return `
  • \n \n \n \n
      \n
    • `;\n },\n\n dropdownItem: function(classes, label, href) {\n if(!href) {\n return `
    • ${label}
    • `;\n }\n return `
    • ${label}
    • `;\n },\n\n // callbacks\n onInit: null,\n onReady: null\n};\n\nconst NAMESPACE = 'asBreadcrumbs';\nlet instanceId = 0;\n\n/**\n * Plugin constructor\n **/\nclass asBreadcrumbs {\n constructor(element, options) {\n this.element = element;\n this.$element = $(element);\n\n this.options = $.extend({}, DEFAULTS, options, this.$element.data());\n\n this.namespace = this.options.namespace;\n this.$element.addClass(this.namespace);\n\n this.classes = {\n toggleClass: this.options.toggleClass? this.options.toggleClass: `${this.namespace}-toggle`,\n toggleIconClass: this.options.toggleIconClass,\n dropdownClass: this.options.dropdownClass? this.options.dropdownClass: `${this.namespace}-dropdown`,\n dropdownMenuClass: this.options.dropdownMenuClass? this.options.dropdownMenuClass: `${this.namespace}-dropdown-menu`,\n dropdownItemClass: this.options.dropdownItemClass? this.options.dropdownItemClass: '',\n dropdownItemDisableClass: this.options.dropdownItemDisableClass? this.options.dropdownItemDisableClass: '',\n ellipsisClass: this.options.ellipsisClass? this.options.ellipsisClass: `${this.namespace}-ellipsis`,\n hiddenClass: this.options.hiddenClass\n };\n\n // flag\n this.initialized = false;\n this.instanceId = (++instanceId);\n\n this.$children = this.options.getItems(this.$element);\n this.$firstChild = this.$children.eq(0);\n\n this.$dropdown = null;\n this.$dropdownMenu = null;\n\n this.gap = 6;\n this.items = [];\n\n this._trigger('init');\n this.init();\n }\n\n init() {\n this.$element.addClass(`${this.namespace}-${this.options.overflow}`);\n\n this._prepareItems();\n this._createDropdown();\n this._createEllipsis();\n\n this.render();\n\n if (this.options.responsive) {\n $(window).on(this.eventNameWithId('resize'), this._throttle(() => {\n this.resize();\n }, 250));\n }\n\n this.initialized = true;\n this._trigger('ready');\n }\n\n _prepareItems() {\n const that = this;\n\n this.$children.each(function(){\n const $this = $(this);\n const $link = that.options.getItemLink($this);\n const $dropdownItem = $(that.options.dropdownItem.call(that, that.classes, $this.text(), $link.attr('href')));\n\n that.items.push({\n $this,\n outerWidth: $this.outerWidth(),\n $item: $dropdownItem\n });\n });\n\n if (this.options.overflow === \"left\") {\n this.items.reverse();\n }\n }\n\n _createDropdown() {\n this.$dropdown = $(this.options.dropdown.call(this, this.classes)).addClass(this.classes.hiddenClass).appendTo(this.$element);\n this.$dropdownMenu = this.$dropdown.find(`.${this.classes.dropdownMenuClass}`);\n\n this._createDropdownItems();\n\n if (this.options.overflow === 'right') {\n this.$dropdown.appendTo(this.$element);\n } else {\n this.$dropdown.prependTo(this.$element);\n }\n }\n\n _createDropdownItems() {\n for (let i = 0; i < this.items.length; i++) {\n this.items[i].$item.appendTo(this.$dropdownMenu).addClass(this.classes.hiddenClass);\n }\n }\n\n _createEllipsis() {\n if (!this.options.ellipsisText) {\n return;\n }\n\n this.$ellipsis = $(this.options.ellipsis.call(this, this.classes, this.options.ellipsisText)).addClass(this.classes.hiddenClass);\n\n if (this.options.overflow === 'right') {\n this.$ellipsis.insertBefore(this.$dropdown);\n } else {\n this.$ellipsis.insertAfter(this.$dropdown);\n }\n }\n\n render() {\n const dropdownWidth = this.getDropdownWidth();\n let childrenWidthTotal = 0;\n let containerWidth = this.getConatinerWidth();\n\n let showDropdown = false;\n\n for (let i = 0; i < this.items.length; i++) {\n childrenWidthTotal += this.items[i].outerWidth;\n\n if (childrenWidthTotal + dropdownWidth > containerWidth) {\n showDropdown = true;\n this._showDropdownItem(i);\n } else {\n this._hideDropdownItem(i);\n }\n }\n\n if(showDropdown) {\n this.$ellipsis.removeClass(this.classes.hiddenClass);\n this.$dropdown.removeClass(this.classes.hiddenClass);\n } else {\n this.$ellipsis.addClass(this.classes.hiddenClass);\n this.$dropdown.addClass(this.classes.hiddenClass);\n }\n\n this._trigger('update');\n }\n\n resize() {\n this.render();\n }\n\n getDropdownWidth() {\n return this.$dropdown.outerWidth() + (this.options.ellipsisText? this.$ellipsis.outerWidth() : 0);\n }\n\n getConatinerWidth() {\n let width = 0;\n const that = this;\n\n this.$element.children().each(function() {\n if ($(this).css('display') === 'inline-block' && $(this).css('float') === 'none') {\n width += that.gap;\n }\n });\n return this.$element.width() - width;\n }\n\n _showDropdownItem(i) {\n this.items[i].$item.removeClass(this.classes.hiddenClass);\n this.items[i].$this.addClass(this.classes.hiddenClass);\n }\n\n _hideDropdownItem(i) {\n this.items[i].$this.removeClass(this.classes.hiddenClass);\n this.items[i].$item.addClass(this.classes.hiddenClass);\n }\n\n _trigger(eventType, ...params) {\n let data = [this].concat(params);\n\n // event\n this.$element.trigger(`${NAMESPACE}::${eventType}`, data);\n\n // callback\n eventType = eventType.replace(/\\b\\w+\\b/g, (word) => {\n return word.substring(0, 1).toUpperCase() + word.substring(1);\n });\n let onFunction = `on${eventType}`;\n\n if (typeof this.options[onFunction] === 'function') {\n this.options[onFunction].apply(this, params);\n }\n }\n\n eventName(events) {\n if (typeof events !== 'string' || events === '') {\n return `.${this.options.namespace}`;\n }\n\n events = events.split(' ');\n let length = events.length;\n for (let i = 0; i < length; i++) {\n events[i] = `${events[i]}.${this.options.namespace}`;\n }\n return events.join(' ');\n }\n\n eventNameWithId(events) {\n if (typeof events !== 'string' || events === '') {\n return `.${this.options.namespace}-${this.instanceId}`;\n }\n\n events = events.split(' ');\n let length = events.length;\n for (let i = 0; i < length; i++) {\n events[i] = `${events[i]}.${this.options.namespace}-${this.instanceId}`;\n }\n return events.join(' ');\n }\n\n _throttle(func, wait) {\n const _now = Date.now || function() {\n return new Date().getTime();\n };\n\n let timeout;\n let context;\n let args;\n let result;\n let previous = 0;\n let later = function() {\n previous = _now();\n timeout = null;\n result = func.apply(context, args);\n if (!timeout) {\n context = args = null;\n }\n };\n\n return (...params) => {\n /*eslint consistent-this: \"off\"*/\n let now = _now();\n let remaining = wait - (now - previous);\n context = this;\n args = params;\n if (remaining <= 0 || remaining > wait) {\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n }\n previous = now;\n result = func.apply(context, args);\n if (!timeout) {\n context = args = null;\n }\n } else if (!timeout) {\n timeout = setTimeout(later, remaining);\n }\n return result;\n };\n }\n\n destroy() {\n this.$element.children().removeClass(this.classes.hiddenClass);\n this.$dropdown.remove();\n\n if (this.options.ellipsisText) {\n this.$ellipsis.remove();\n }\n\n this.initialized = false;\n\n this.$element.data(NAMESPACE, null);\n $(window).off(this.eventNameWithId('resize'));\n this._trigger('destroy');\n }\n\n static setDefaults(options) {\n $.extend(DEFAULTS, $.isPlainObject(options) && options);\n }\n}\n\nvar info = {\n version:'0.2.3'\n};\n\nconst NAME = 'asBreadcrumbs';\nconst OtherAsBreadcrumbs = $.fn.asBreadcrumbs;\n\nconst jQueryAsBreadcrumbs = function(options, ...args) {\n if (typeof options === 'string') {\n let method = options;\n\n if (/^_/.test(method)) {\n return false;\n } else if ((/^(get)/.test(method))) {\n let instance = this.first().data(NAME);\n if (instance && typeof instance[method] === 'function') {\n return instance[method](...args);\n }\n } else {\n return this.each(function() {\n let instance = $.data(this, NAME);\n if (instance && typeof instance[method] === 'function') {\n instance[method](...args);\n }\n });\n }\n }\n\n return this.each(function() {\n if (!$(this).data(NAME)) {\n $(this).data(NAME, new asBreadcrumbs(this, options));\n }\n });\n};\n\n$.fn.asBreadcrumbs = jQueryAsBreadcrumbs;\n\n$.asBreadcrumbs = $.extend({\n setDefaults: asBreadcrumbs.setDefaults,\n noConflict: function() {\n $.fn.asBreadcrumbs = OtherAsBreadcrumbs;\n return jQueryAsBreadcrumbs;\n }\n}, info);\n"]} \ No newline at end of file +{"version":3,"sources":["jquery-asBreadcrumbs.es.js"],"names":["global","factory","define","amd","exports","require","mod","jQuery","jqueryAsBreadcrumbsEs","this","_jquery","_classCallCheck","instance","Constructor","TypeError","_jquery2","obj","__esModule","default","_interopRequireDefault","_createClass","defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","protoProps","staticProps","prototype","DEFAULTS","namespace","overflow","responsive","ellipsisText","ellipsisClass","hiddenClass","dropdownClass","dropdownMenuClass","dropdownItemClass","dropdownItemDisableClass","toggleClass","toggleIconClass","getItems","$parent","children","getItemLink","$item","find","ellipsis","classes","label","dropdown","options","dropdownItem","href","onInit","onReady","instanceId","asBreadcrumbs","element","$element","extend","data","addClass","initialized","$children","$firstChild","eq","$dropdown","$dropdownMenu","gap","items","_trigger","init","value","_this","_prepareItems","_createDropdown","_createEllipsis","render","window","on","eventNameWithId","_throttle","resize","that","each","$this","$link","$dropdownItem","call","text","attr","push","outerWidth","reverse","appendTo","_createDropdownItems","prependTo","$ellipsis","insertBefore","insertAfter","dropdownWidth","getDropdownWidth","childrenWidthTotal","containerWidth","getConatinerWidth","showDropdown","_showDropdownItem","_hideDropdownItem","removeClass","width","css","eventType","_len","arguments","params","Array","_key","concat","trigger","NAMESPACE","onFunction","replace","word","substring","toUpperCase","apply","events","split","join","func","wait","_this2","_now","Date","now","getTime","timeout","context","args","result"],"mappings":"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","file":"jquery-asBreadcrumbs.min.js","sourcesContent":["/**\n* jQuery asBreadcrumbs v0.2.3\n* https://github.com/amazingSurge/jquery-asBreadcrumbs\n*\n* Copyright (c) amazingSurge\n* Released under the LGPL-3.0 license\n*/\nimport $ from 'jquery';\n\nvar DEFAULTS = {\n namespace: 'breadcrumb',\n overflow: \"left\",\n\n responsive: true,\n\n ellipsisText: \"…\",\n ellipsisClass: null,\n\n hiddenClass: 'is-hidden',\n\n dropdownClass: null,\n dropdownMenuClass: null,\n dropdownItemClass: null,\n dropdownItemDisableClass: 'disabled',\n\n toggleClass: null,\n toggleIconClass: 'caret',\n\n getItems: function($parent) {\n return $parent.children();\n },\n\n getItemLink: function($item) {\n return $item.find('a');\n },\n\n // templates\n ellipsis: function(classes, label) {\n return `
    • ${label}
    • `;\n },\n\n dropdown: function(classes) {\n const dropdownClass = 'dropdown';\n let dropdownMenuClass = 'dropdown-menu';\n\n if (this.options.overflow === 'right') {\n dropdownMenuClass += ' dropdown-menu-right';\n }\n\n return `
    • \n \n \n \n
        \n
      • `;\n },\n\n dropdownItem: function(classes, label, href) {\n if(!href) {\n return `
      • ${label}
      • `;\n }\n return `
      • ${label}
      • `;\n },\n\n // callbacks\n onInit: null,\n onReady: null\n};\n\nconst NAMESPACE = 'asBreadcrumbs';\nlet instanceId = 0;\n\n/**\n * Plugin constructor\n **/\nclass asBreadcrumbs {\n constructor(element, options) {\n this.element = element;\n this.$element = $(element);\n\n this.options = $.extend({}, DEFAULTS, options, this.$element.data());\n\n this.namespace = this.options.namespace;\n this.$element.addClass(this.namespace);\n\n this.classes = {\n toggleClass: this.options.toggleClass? this.options.toggleClass: `${this.namespace}-toggle`,\n toggleIconClass: this.options.toggleIconClass,\n dropdownClass: this.options.dropdownClass? this.options.dropdownClass: `${this.namespace}-dropdown`,\n dropdownMenuClass: this.options.dropdownMenuClass? this.options.dropdownMenuClass: `${this.namespace}-dropdown-menu`,\n dropdownItemClass: this.options.dropdownItemClass? this.options.dropdownItemClass: '',\n dropdownItemDisableClass: this.options.dropdownItemDisableClass? this.options.dropdownItemDisableClass: '',\n ellipsisClass: this.options.ellipsisClass? this.options.ellipsisClass: `${this.namespace}-ellipsis`,\n hiddenClass: this.options.hiddenClass\n };\n\n // flag\n this.initialized = false;\n this.instanceId = (++instanceId);\n\n this.$children = this.options.getItems(this.$element);\n this.$firstChild = this.$children.eq(0);\n\n this.$dropdown = null;\n this.$dropdownMenu = null;\n\n this.gap = 6;\n this.items = [];\n\n this._trigger('init');\n this.init();\n }\n\n init() {\n this.$element.addClass(`${this.namespace}-${this.options.overflow}`);\n\n this._prepareItems();\n this._createDropdown();\n this._createEllipsis();\n\n this.render();\n\n if (this.options.responsive) {\n $(window).on(this.eventNameWithId('resize'), this._throttle(() => {\n this.resize();\n }, 250));\n }\n\n this.initialized = true;\n this._trigger('ready');\n }\n\n _prepareItems() {\n const that = this;\n\n this.$children.each(function(){\n const $this = $(this);\n const $link = that.options.getItemLink($this);\n const $dropdownItem = $(that.options.dropdownItem.call(that, that.classes, $this.html(), $link.attr('href')));\n\n that.items.push({\n $this,\n outerWidth: $this.outerWidth(),\n $item: $dropdownItem\n });\n });\n\n if (this.options.overflow === \"left\") {\n this.items.reverse();\n }\n }\n\n _createDropdown() {\n this.$dropdown = $(this.options.dropdown.call(this, this.classes)).addClass(this.classes.hiddenClass).appendTo(this.$element);\n this.$dropdownMenu = this.$dropdown.find(`.${this.classes.dropdownMenuClass}`);\n\n this._createDropdownItems();\n\n if (this.options.overflow === 'right') {\n this.$dropdown.appendTo(this.$element);\n } else {\n this.$dropdown.prependTo(this.$element);\n }\n }\n\n _createDropdownItems() {\n for (let i = 0; i < this.items.length; i++) {\n this.items[i].$item.appendTo(this.$dropdownMenu).addClass(this.classes.hiddenClass);\n }\n }\n\n _createEllipsis() {\n if (!this.options.ellipsisText) {\n return;\n }\n\n this.$ellipsis = $(this.options.ellipsis.call(this, this.classes, this.options.ellipsisText)).addClass(this.classes.hiddenClass);\n\n if (this.options.overflow === 'right') {\n this.$ellipsis.insertBefore(this.$dropdown);\n } else {\n this.$ellipsis.insertAfter(this.$dropdown);\n }\n }\n\n render() {\n const dropdownWidth = this.getDropdownWidth();\n let childrenWidthTotal = 0;\n let containerWidth = this.getConatinerWidth();\n\n let showDropdown = false;\n\n for (let i = 0; i < this.items.length; i++) {\n childrenWidthTotal += this.items[i].outerWidth;\n\n if (childrenWidthTotal + dropdownWidth > containerWidth) {\n showDropdown = true;\n this._showDropdownItem(i);\n } else {\n this._hideDropdownItem(i);\n }\n }\n\n if(showDropdown) {\n this.$ellipsis.removeClass(this.classes.hiddenClass);\n this.$dropdown.removeClass(this.classes.hiddenClass);\n } else {\n this.$ellipsis.addClass(this.classes.hiddenClass);\n this.$dropdown.addClass(this.classes.hiddenClass);\n }\n\n this._trigger('update');\n }\n\n resize() {\n this.render();\n }\n\n getDropdownWidth() {\n return this.$dropdown.outerWidth() + (this.options.ellipsisText? this.$ellipsis.outerWidth() : 0);\n }\n\n getConatinerWidth() {\n let width = 0;\n const that = this;\n\n this.$element.children().each(function() {\n if ($(this).css('display') === 'inline-block' && $(this).css('float') === 'none') {\n width += that.gap;\n }\n });\n return this.$element.width() - width;\n }\n\n _showDropdownItem(i) {\n this.items[i].$item.removeClass(this.classes.hiddenClass);\n this.items[i].$this.addClass(this.classes.hiddenClass);\n }\n\n _hideDropdownItem(i) {\n this.items[i].$this.removeClass(this.classes.hiddenClass);\n this.items[i].$item.addClass(this.classes.hiddenClass);\n }\n\n _trigger(eventType, ...params) {\n let data = [this].concat(params);\n\n // event\n this.$element.trigger(`${NAMESPACE}::${eventType}`, data);\n\n // callback\n eventType = eventType.replace(/\\b\\w+\\b/g, (word) => {\n return word.substring(0, 1).toUpperCase() + word.substring(1);\n });\n let onFunction = `on${eventType}`;\n\n if (typeof this.options[onFunction] === 'function') {\n this.options[onFunction].apply(this, params);\n }\n }\n\n eventName(events) {\n if (typeof events !== 'string' || events === '') {\n return `.${this.options.namespace}`;\n }\n\n events = events.split(' ');\n let length = events.length;\n for (let i = 0; i < length; i++) {\n events[i] = `${events[i]}.${this.options.namespace}`;\n }\n return events.join(' ');\n }\n\n eventNameWithId(events) {\n if (typeof events !== 'string' || events === '') {\n return `.${this.options.namespace}-${this.instanceId}`;\n }\n\n events = events.split(' ');\n let length = events.length;\n for (let i = 0; i < length; i++) {\n events[i] = `${events[i]}.${this.options.namespace}-${this.instanceId}`;\n }\n return events.join(' ');\n }\n\n _throttle(func, wait) {\n const _now = Date.now || function() {\n return new Date().getTime();\n };\n\n let timeout;\n let context;\n let args;\n let result;\n let previous = 0;\n let later = function() {\n previous = _now();\n timeout = null;\n result = func.apply(context, args);\n if (!timeout) {\n context = args = null;\n }\n };\n\n return (...params) => {\n /*eslint consistent-this: \"off\"*/\n let now = _now();\n let remaining = wait - (now - previous);\n context = this;\n args = params;\n if (remaining <= 0 || remaining > wait) {\n if (timeout) {\n clearTimeout(timeout);\n timeout = null;\n }\n previous = now;\n result = func.apply(context, args);\n if (!timeout) {\n context = args = null;\n }\n } else if (!timeout) {\n timeout = setTimeout(later, remaining);\n }\n return result;\n };\n }\n\n destroy() {\n this.$element.children().removeClass(this.classes.hiddenClass);\n this.$dropdown.remove();\n\n if (this.options.ellipsisText) {\n this.$ellipsis.remove();\n }\n\n this.initialized = false;\n\n this.$element.data(NAMESPACE, null);\n $(window).off(this.eventNameWithId('resize'));\n this._trigger('destroy');\n }\n\n static setDefaults(options) {\n $.extend(DEFAULTS, $.isPlainObject(options) && options);\n }\n}\n\nvar info = {\n version:'0.2.3'\n};\n\nconst NAME = 'asBreadcrumbs';\nconst OtherAsBreadcrumbs = $.fn.asBreadcrumbs;\n\nconst jQueryAsBreadcrumbs = function(options, ...args) {\n if (typeof options === 'string') {\n let method = options;\n\n if (/^_/.test(method)) {\n return false;\n } else if ((/^(get)/.test(method))) {\n let instance = this.first().data(NAME);\n if (instance && typeof instance[method] === 'function') {\n return instance[method](...args);\n }\n } else {\n return this.each(function() {\n let instance = $.data(this, NAME);\n if (instance && typeof instance[method] === 'function') {\n instance[method](...args);\n }\n });\n }\n }\n\n return this.each(function() {\n if (!$(this).data(NAME)) {\n $(this).data(NAME, new asBreadcrumbs(this, options));\n }\n });\n};\n\n$.fn.asBreadcrumbs = jQueryAsBreadcrumbs;\n\n$.asBreadcrumbs = $.extend({\n setDefaults: asBreadcrumbs.setDefaults,\n noConflict: function() {\n $.fn.asBreadcrumbs = OtherAsBreadcrumbs;\n return jQueryAsBreadcrumbs;\n }\n}, info);\n"]} diff --git a/src/asBreadcrumbs.js b/src/asBreadcrumbs.js index 8f05e75..42d75ce 100644 --- a/src/asBreadcrumbs.js +++ b/src/asBreadcrumbs.js @@ -70,7 +70,7 @@ class asBreadcrumbs { this.$children.each(function(){ const $this = $(this); const $link = that.options.getItemLink($this); - const $dropdownItem = $(that.options.dropdownItem.call(that, that.classes, $this.text(), $link.attr('href'))); + const $dropdownItem = $(that.options.dropdownItem.call(that, that.classes, $this.html(), $link.attr('href'))); that.items.push({ $this,