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 * In this object stored 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 horizontal 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 setting 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"); 194 195 if (properties.expandOnHover) { 196 ev = "mouseenter"; 197 } 198 199 toggleHeader.on("mouseover", toogleEvents.focus); 200 toggleHeader.on("mouseleave", toogleEvents.blur); 201 toggleHeader.on("focus", toogleEvents.focus); 202 toggleHeader.on("blur", toogleEvents.blur); 203 toggleHeader.on("keyup", function(e) { 204 if (e.keyCode == 13 || e.keyCode == 32) { 205 $(this).click(); 206 } 207 }); 208 209 if (acc.hasClass("accordion-horizontal")) { 210 //calc slide width 211 $(document).ready(function() { 212 calcSlideSize(acc); 213 }); 214 215 _.each(toggleHeader, function(header) { 216 headerBackground(header); 217 }); 218 } 219 220 toggleHeader.on(ev, function() { 221 var $this = $(this), 222 panel = $this.closest(".item"), 223 accordion = $this.parents(".accordion"), 224 content = panel.find(".toggle-content"), 225 siblings = panel.siblings(), 226 siblingsContent = siblings.find(".toggle-content"); 227 228 // Horizontal animation 229 if (accordion.hasClass("accordion-horizontal")) { 230 api.animateHorizontal.call(this, properties); 231 // Vertical animation 232 } else { 233 // Close all other items if open 234 // multiple option disabled 235 if (!properties.canOpenMultiple) { 236 siblings.removeClass("active"); 237 siblingsContent.stop().slideUp({ 238 duration: properties.speed, 239 easing: properties.easing 240 }); 241 } 242 243 panel.toggleClass("active"); 244 // Toggle state of selected item 245 // If toggle state is enabled 246 if (properties.canToggle) { 247 content.slideToggle({ 248 duration: properties.speed, 249 easing: properties.easing 250 }); 251 } else { 252 content.slideDown({ 253 duration: properties.speed, 254 easing: properties.easing 255 }); 256 } 257 } 258 }); 259 } 260 /** 261 * initInstance method prepare Dom elements according accordion setup 262 * and call ["accordion"]{@link module:Accordion.accordion} method 263 * @memberOf module:Acordion 264 * @method 265 * @param {jQuery} component Root DOM element of archive component wrapped by jQuery 266 * @param {Object} prop list of properties for accordion component 267 * @alias module:Accordion.initInstance 268 */ 269 api.initInstance = function(component, prop) { 270 // Set tabindex=0 for first header 271 component 272 .find(".toggle-header") 273 .eq(0) 274 .attr("tabindex", "0"); 275 // 276 if (component.hasClass("toggle")) { 277 $.extend(prop, { 278 canToggle: true 279 }); 280 } 281 component.find(".toggle-content").hide(); 282 var current = XA.queryString.getQueryParam(getQueryParamKey(component)); 283 if (current != null) { 284 var arr = current.split(","); 285 var items = component.find("li"); 286 for (var index = 0; index < items.length; index++) { 287 var element = items[index]; 288 if (arr.indexOf(index + "") > -1) { 289 $(element).addClass("active"); 290 $(element) 291 .find(".toggle-content") 292 .show(); 293 } 294 } 295 } else if (prop.expandedByDefault) { 296 component.find("li:first-child").addClass("active"); 297 component 298 .find("li:first-child") 299 .find(".toggle-content") 300 .show(); 301 } 302 accordion(component, prop); 303 }; 304 /** 305 * init method calls in a loop for each 306 * accordions component on a page and run Accordions's 307 * [".initInstance"]{@link module:Accordion.initInstance} method. 308 * @memberOf module:Accordion 309 * @alias module:Accordion.init 310 */ 311 api.init = function() { 312 var accordions = $(".accordion:not(.initialized)"); 313 accordions.each(function() { 314 var properties = $(this).data("properties"), 315 acc = $(this); 316 api.initInstance(acc, properties); 317 acc.addClass("initialized"); 318 }); 319 }; 320 321 return api; 322})(jQuery); 323 324XA.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.