1/* global _:true */ 2/** 3 * Component Accordion 4 * @module Accordion 5 * @param {jQuery} $ Instance of jQuery 6 * @return {Object} List of accordion methods 7 */ 8XA.component.accordions = (function($) { 9 /** 10 * This object stores all public api methods 11 * @type {Object.<Methods>} 12 * @memberOf module:Accordion 13 * */ 14 var api = {}; 15 /** 16 * toogleEvents list of toggle events 17 * @memberOf module:Accordion 18 * @private 19 */ 20 var toogleEvents = { 21 focus: function() { 22 $(this).addClass("show"); 23 }, 24 blur: function() { 25 $(this).removeClass("show"); 26 } 27 }; 28 /** 29 * headerBackground method set up background image for toggle-header 30 * @memberOf module:Accordion 31 * @param {DomElement} header toggle-header DOM element of accordion component 32 * @alias module:Accordion.headerBackground 33 * @private 34 */ 35 function headerBackground(header) { 36 var backgroundIcon = $(header), 37 background = $(header).find("img"), 38 backgroundSrc = background.attr("src"); 39 40 if (backgroundSrc) { 41 backgroundIcon.parents(".accordion").addClass("accordion-image"); 42 43 backgroundIcon.css({ 44 background: "url(" + backgroundSrc + ")", 45 "background-repeat": "no-repeat", 46 "background-size": "cover", 47 "background-position": "50% 100%" 48 }); 49 50 background.hide(); 51 } 52 } 53 /** 54 * calcSlideSize method calculate and set up width of accordion items 55 * @memberOf module:Accordion 56 * @param {DomElement} acc Root Dom element of accordion component 57 * @alias module:Accordion.calcSlideSize 58 * @private 59 */ 60 function calcSlideSize(acc) { 61 var accordionWidth = $(acc).width(), 62 accordionItems = $(acc).find(".item"), 63 maxHeight = 0; 64 65 _.each(accordionItems, function(item) { 66 var itemContent = $(item).find(".toggle-content"), 67 itemHeader = $(item).find(".toggle-header"), 68 slideWidth = 69 accordionWidth - 70 accordionItems.length * itemHeader.outerWidth(); 71 72 if ($(item).hasClass("active")) { 73 $(item).css({ 74 width: slideWidth 75 }); 76 } 77 78 //width 79 itemContent.css({ 80 width: $(acc).hasClass("accordion-image") 81 ? slideWidth + itemHeader.outerWidth() 82 : slideWidth - 83 itemHeader.outerWidth() - 84 parseInt(itemHeader.css("padding")) 85 }); 86 87 //height 88 if ( 89 $(item) 90 .find(".toggle-content") 91 .height() > maxHeight 92 ) { 93 maxHeight = $(item) 94 .find(".toggle-content") 95 .height(); 96 } 97 }); 98 } 99 100 /** 101 * animateHorizontal method set up animation for horizontally oriented 102 * accordion component 103 * @memberOf module:Accordion 104 * @param {Object} properties list of properties for accordion component 105 * @alias module:Accordion.animateHorizontal 106 */ 107 api.animateHorizontal = function(properties) { 108 var accordion = $(this).parents(".accordion"), 109 panel = $(this).closest(".item"), 110 header = panel.find(".toggle-header"), 111 content = panel.find(".toggle-content"), 112 items = accordion.find(".item"), 113 siblings = panel.siblings(), 114 siblingsContent = siblings.find(".toggle-content"); 115 116 panel.toggleClass("active"); 117 siblings.removeClass("active"); 118 siblings.stop(true).animate( 119 { 120 width: 0 121 }, 122 properties.speed, 123 properties.easing, 124 function() { 125 siblingsContent.css({ 126 display: "none" 127 }); 128 } 129 ); 130 131 if (panel.hasClass("active")) { 132 var slideWidth = accordion.hasClass("accordion-image") 133 ? content.outerWidth() 134 : accordion.width() - 135 ((items.length - 1) * panel.outerWidth() + 2), 136 contentWidth = accordion.hasClass("accordion-image") 137 ? slideWidth 138 : slideWidth - header.outerWidth(); 139 140 panel.stop(true).animate( 141 { 142 width: slideWidth 143 }, 144 properties.speed, 145 properties.easing, 146 function() {} 147 ); 148 149 content.css({ 150 width: contentWidth, 151 display: "block" 152 }); 153 } else { 154 panel.stop(true).animate( 155 { 156 width: 0 157 }, 158 properties.speed, 159 properties.easing, 160 function() { 161 content.css({ 162 display: "none" 163 }); 164 } 165 ); 166 } 167 }; 168 /** 169 * getQueryParamKey get an Id of accordion component 170 * @memberOf module:Accordion 171 * @param {jQuery} accordions Root Dom element of accordion component 172 * @private 173 * @return {null|string} return id of accordion component 174 */ 175 function getQueryParamKey(accordions) { 176 var firstAccordionId = accordions[0].id; 177 if (accordions.length > 0 && firstAccordionId != "") { 178 return firstAccordionId.toLocaleLowerCase(); 179 } 180 return null; 181 } 182 /** 183 * accordion method that sets up watchers that animate accordion slide 184 * @memberOf module:Accordion 185 * @method 186 * @private 187 * @param {jQuery} acc Root DOM element of archive component wrapped by jQuery 188 * @param {Object} prop list of properties for accordion component 189 * @alias module:Accordion.accordion 190 */ 191 function accordion(acc, properties) { 192 var ev = "click", 193 toggleHeader = acc.find(".toggle-header").filter(function (index, element) { 194 return $(element).closest('.accordion').is(acc); 195 }); 196 197 if (properties.expandOnHover) { 198 ev += " mouseenter"; 199 } 200 201 toggleHeader.on("mouseover", toogleEvents.focus); 202 toggleHeader.on("mouseleave", toogleEvents.blur); 203 toggleHeader.on("focus", toogleEvents.focus); 204 toggleHeader.on("blur", toogleEvents.blur); 205 toggleHeader.on("keyup", function(e) { 206 if (e.keyCode == 13 || e.keyCode == 32) { 207 $(this).click(); 208 } 209 }); 210 211 if (acc.hasClass("accordion-horizontal")) { 212 //calc slide width 213 $(document).ready(function() { 214 calcSlideSize(acc); 215 }); 216 217 _.each(toggleHeader, function(header) {
218 headerBackground(header); 219 }); 220 } 221 222 toggleHeader.on(ev, function() { 223 var $this = $(this), 224 panel = $this.closest(".item"), 225 accordion = $this.parents(".accordion"), 226 content = panel.find(".toggle-content:first"), 227 siblings = panel.siblings(), 228 siblingsContent = siblings.find(".toggle-content"); 229 230 // Horizontal animation 231 if (accordion.hasClass("accordion-horizontal")) { 232 api.animateHorizontal.call(this, properties); 233 // Vertical animation 234 } else { 235 // Closes all other items if open 236 // multiple option disabled 237 if (!properties.canOpenMultiple) { 238 siblings.removeClass("active"); 239 siblingsContent.stop().slideUp({ 240 duration: properties.speed, 241 easing: properties.easing 242 }); 243 } 244 245 panel.toggleClass("active"); 246 // Toggle state of selected item 247 // If toggle state is enabled 248 if (properties.canToggle) { 249 content.slideToggle({ 250 duration: properties.speed, 251 easing: properties.easing 252 }); 253 } else { 254 content.slideDown({ 255 duration: properties.speed, 256 easing: properties.easing 257 }); 258 } 259 } 260 }); 261 } 262 /** 263 * initInstance method prepare Dom elements according accordion setup 264 * and call ["accordion"]{@link module:Accordion.accordion} method 265 * @memberOf module:Acordion 266 * @method 267 * @param {jQuery} component Root DOM element of archive component wrapped by jQuery 268 * @param {Object} prop list of properties for accordion component 269 * @alias module:Accordion.initInstance 270 */ 271 api.initInstance = function(component, prop) { 272 // Set tabindex=0 for first header 273 component 274 .find(".toggle-header") 275 .eq(0) 276 .attr("tabindex", "0"); 277 // 278 if (component.hasClass("toggle")) { 279 $.extend(prop, { 280 canToggle: true 281 }); 282 } 283 component.find(".toggle-content").hide(); 284 var current = XA.queryString.getQueryParam(getQueryParamKey(component)); 285 if (current != null) { 286 var arr = current.split(","); 287 var items = component.find("ul").first().children(); 288 for (var index = 0; index < items.length; index++) { 289 var element = items[index]; 290 if (arr.indexOf(index + "") > -1) { 291 $(element).addClass("active"); 292 $(element) 293 .find(".toggle-content") 294 .show(); 295 } 296 } 297 } else if (prop.expandedByDefault) { 298 component.find("li:first-child").addClass("active"); 299 component 300 .find("li:first-child") 301 .find(".toggle-content") 302 .show(); 303 } 304 accordion(component, prop); 305 }; 306 /** 307 * init method calls in a loop for each 308 * accordions component on a page and run Accordions 309 * [".initInstance"]{@link module:Accordion.initInstance} method. 310 * @memberOf module:Accordion 311 * @alias module:Accordion.init 312 */ 313 api.init = function() { 314 var accordions = $(".accordion:not(.initialized)"); 315 accordions.each(function() { 316 var properties = $(this).data("properties"), 317 acc = $(this); 318 api.initInstance(acc, properties); 319 acc.addClass("initialized"); 320 }); 321 }; 322 323 return api; 324})(jQuery); 325 326XA.register("accordions", XA.component.accordions);
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.