@@ 2216-2814 (lines=599) @@ | ||
2213 | * |
|
2214 | */ |
|
2215 | ||
2216 | ;(function ($, window, document, undefined) { |
|
2217 | ||
2218 | "use strict"; |
|
2219 | ||
2220 | window = (typeof window != 'undefined' && window.Math == Math) |
|
2221 | ? window |
|
2222 | : (typeof self != 'undefined' && self.Math == Math) |
|
2223 | ? self |
|
2224 | : Function('return this')() |
|
2225 | ; |
|
2226 | ||
2227 | $.fn.accordion = function(parameters) { |
|
2228 | var |
|
2229 | $allModules = $(this), |
|
2230 | ||
2231 | time = new Date().getTime(), |
|
2232 | performance = [], |
|
2233 | ||
2234 | query = arguments[0], |
|
2235 | methodInvoked = (typeof query == 'string'), |
|
2236 | queryArguments = [].slice.call(arguments, 1), |
|
2237 | ||
2238 | requestAnimationFrame = window.requestAnimationFrame |
|
2239 | || window.mozRequestAnimationFrame |
|
2240 | || window.webkitRequestAnimationFrame |
|
2241 | || window.msRequestAnimationFrame |
|
2242 | || function(callback) { setTimeout(callback, 0); }, |
|
2243 | ||
2244 | returnedValue |
|
2245 | ; |
|
2246 | $allModules |
|
2247 | .each(function() { |
|
2248 | var |
|
2249 | settings = ( $.isPlainObject(parameters) ) |
|
2250 | ? $.extend(true, {}, $.fn.accordion.settings, parameters) |
|
2251 | : $.extend({}, $.fn.accordion.settings), |
|
2252 | ||
2253 | className = settings.className, |
|
2254 | namespace = settings.namespace, |
|
2255 | selector = settings.selector, |
|
2256 | error = settings.error, |
|
2257 | ||
2258 | eventNamespace = '.' + namespace, |
|
2259 | moduleNamespace = 'module-' + namespace, |
|
2260 | moduleSelector = $allModules.selector || '', |
|
2261 | ||
2262 | $module = $(this), |
|
2263 | $title = $module.find(selector.title), |
|
2264 | $content = $module.find(selector.content), |
|
2265 | ||
2266 | element = this, |
|
2267 | instance = $module.data(moduleNamespace), |
|
2268 | observer, |
|
2269 | module |
|
2270 | ; |
|
2271 | ||
2272 | module = { |
|
2273 | ||
2274 | initialize: function() { |
|
2275 | module.debug('Initializing', $module); |
|
2276 | module.bind.events(); |
|
2277 | if(settings.observeChanges) { |
|
2278 | module.observeChanges(); |
|
2279 | } |
|
2280 | module.instantiate(); |
|
2281 | }, |
|
2282 | ||
2283 | instantiate: function() { |
|
2284 | instance = module; |
|
2285 | $module |
|
2286 | .data(moduleNamespace, module) |
|
2287 | ; |
|
2288 | }, |
|
2289 | ||
2290 | destroy: function() { |
|
2291 | module.debug('Destroying previous instance', $module); |
|
2292 | $module |
|
2293 | .off(eventNamespace) |
|
2294 | .removeData(moduleNamespace) |
|
2295 | ; |
|
2296 | }, |
|
2297 | ||
2298 | refresh: function() { |
|
2299 | $title = $module.find(selector.title); |
|
2300 | $content = $module.find(selector.content); |
|
2301 | }, |
|
2302 | ||
2303 | observeChanges: function() { |
|
2304 | if('MutationObserver' in window) { |
|
2305 | observer = new MutationObserver(function(mutations) { |
|
2306 | module.debug('DOM tree modified, updating selector cache'); |
|
2307 | module.refresh(); |
|
2308 | }); |
|
2309 | observer.observe(element, { |
|
2310 | childList : true, |
|
2311 | subtree : true |
|
2312 | }); |
|
2313 | module.debug('Setting up mutation observer', observer); |
|
2314 | } |
|
2315 | }, |
|
2316 | ||
2317 | bind: { |
|
2318 | events: function() { |
|
2319 | module.debug('Binding delegated events'); |
|
2320 | $module |
|
2321 | .on(settings.on + eventNamespace, selector.trigger, module.event.click) |
|
2322 | ; |
|
2323 | } |
|
2324 | }, |
|
2325 | ||
2326 | event: { |
|
2327 | click: function() { |
|
2328 | module.toggle.call(this); |
|
2329 | } |
|
2330 | }, |
|
2331 | ||
2332 | toggle: function(query) { |
|
2333 | var |
|
2334 | $activeTitle = (query !== undefined) |
|
2335 | ? (typeof query === 'number') |
|
2336 | ? $title.eq(query) |
|
2337 | : $(query).closest(selector.title) |
|
2338 | : $(this).closest(selector.title), |
|
2339 | $activeContent = $activeTitle.next($content), |
|
2340 | isAnimating = $activeContent.hasClass(className.animating), |
|
2341 | isActive = $activeContent.hasClass(className.active), |
|
2342 | isOpen = (isActive && !isAnimating), |
|
2343 | isOpening = (!isActive && isAnimating) |
|
2344 | ; |
|
2345 | module.debug('Toggling visibility of content', $activeTitle); |
|
2346 | if(isOpen || isOpening) { |
|
2347 | if(settings.collapsible) { |
|
2348 | module.close.call($activeTitle); |
|
2349 | } |
|
2350 | else { |
|
2351 | module.debug('Cannot close accordion content collapsing is disabled'); |
|
2352 | } |
|
2353 | } |
|
2354 | else { |
|
2355 | module.open.call($activeTitle); |
|
2356 | } |
|
2357 | }, |
|
2358 | ||
2359 | open: function(query) { |
|
2360 | var |
|
2361 | $activeTitle = (query !== undefined) |
|
2362 | ? (typeof query === 'number') |
|
2363 | ? $title.eq(query) |
|
2364 | : $(query).closest(selector.title) |
|
2365 | : $(this).closest(selector.title), |
|
2366 | $activeContent = $activeTitle.next($content), |
|
2367 | isAnimating = $activeContent.hasClass(className.animating), |
|
2368 | isActive = $activeContent.hasClass(className.active), |
|
2369 | isOpen = (isActive || isAnimating) |
|
2370 | ; |
|
2371 | if(isOpen) { |
|
2372 | module.debug('Accordion already open, skipping', $activeContent); |
|
2373 | return; |
|
2374 | } |
|
2375 | module.debug('Opening accordion content', $activeTitle); |
|
2376 | settings.onOpening.call($activeContent); |
|
2377 | if(settings.exclusive) { |
|
2378 | module.closeOthers.call($activeTitle); |
|
2379 | } |
|
2380 | $activeTitle |
|
2381 | .addClass(className.active) |
|
2382 | ; |
|
2383 | $activeContent |
|
2384 | .stop(true, true) |
|
2385 | .addClass(className.animating) |
|
2386 | ; |
|
2387 | if(settings.animateChildren) { |
|
2388 | if($.fn.transition !== undefined && $module.transition('is supported')) { |
|
2389 | $activeContent |
|
2390 | .children() |
|
2391 | .transition({ |
|
2392 | animation : 'fade in', |
|
2393 | queue : false, |
|
2394 | useFailSafe : true, |
|
2395 | debug : settings.debug, |
|
2396 | verbose : settings.verbose, |
|
2397 | duration : settings.duration |
|
2398 | }) |
|
2399 | ; |
|
2400 | } |
|
2401 | else { |
|
2402 | $activeContent |
|
2403 | .children() |
|
2404 | .stop(true, true) |
|
2405 | .animate({ |
|
2406 | opacity: 1 |
|
2407 | }, settings.duration, module.resetOpacity) |
|
2408 | ; |
|
2409 | } |
|
2410 | } |
|
2411 | $activeContent |
|
2412 | .slideDown(settings.duration, settings.easing, function() { |
|
2413 | $activeContent |
|
2414 | .removeClass(className.animating) |
|
2415 | .addClass(className.active) |
|
2416 | ; |
|
2417 | module.reset.display.call(this); |
|
2418 | settings.onOpen.call(this); |
|
2419 | settings.onChange.call(this); |
|
2420 | }) |
|
2421 | ; |
|
2422 | }, |
|
2423 | ||
2424 | close: function(query) { |
|
2425 | var |
|
2426 | $activeTitle = (query !== undefined) |
|
2427 | ? (typeof query === 'number') |
|
2428 | ? $title.eq(query) |
|
2429 | : $(query).closest(selector.title) |
|
2430 | : $(this).closest(selector.title), |
|
2431 | $activeContent = $activeTitle.next($content), |
|
2432 | isAnimating = $activeContent.hasClass(className.animating), |
|
2433 | isActive = $activeContent.hasClass(className.active), |
|
2434 | isOpening = (!isActive && isAnimating), |
|
2435 | isClosing = (isActive && isAnimating) |
|
2436 | ; |
|
2437 | if((isActive || isOpening) && !isClosing) { |
|
2438 | module.debug('Closing accordion content', $activeContent); |
|
2439 | settings.onClosing.call($activeContent); |
|
2440 | $activeTitle |
|
2441 | .removeClass(className.active) |
|
2442 | ; |
|
2443 | $activeContent |
|
2444 | .stop(true, true) |
|
2445 | .addClass(className.animating) |
|
2446 | ; |
|
2447 | if(settings.animateChildren) { |
|
2448 | if($.fn.transition !== undefined && $module.transition('is supported')) { |
|
2449 | $activeContent |
|
2450 | .children() |
|
2451 | .transition({ |
|
2452 | animation : 'fade out', |
|
2453 | queue : false, |
|
2454 | useFailSafe : true, |
|
2455 | debug : settings.debug, |
|
2456 | verbose : settings.verbose, |
|
2457 | duration : settings.duration |
|
2458 | }) |
|
2459 | ; |
|
2460 | } |
|
2461 | else { |
|
2462 | $activeContent |
|
2463 | .children() |
|
2464 | .stop(true, true) |
|
2465 | .animate({ |
|
2466 | opacity: 0 |
|
2467 | }, settings.duration, module.resetOpacity) |
|
2468 | ; |
|
2469 | } |
|
2470 | } |
|
2471 | $activeContent |
|
2472 | .slideUp(settings.duration, settings.easing, function() { |
|
2473 | $activeContent |
|
2474 | .removeClass(className.animating) |
|
2475 | .removeClass(className.active) |
|
2476 | ; |
|
2477 | module.reset.display.call(this); |
|
2478 | settings.onClose.call(this); |
|
2479 | settings.onChange.call(this); |
|
2480 | }) |
|
2481 | ; |
|
2482 | } |
|
2483 | }, |
|
2484 | ||
2485 | closeOthers: function(index) { |
|
2486 | var |
|
2487 | $activeTitle = (index !== undefined) |
|
2488 | ? $title.eq(index) |
|
2489 | : $(this).closest(selector.title), |
|
2490 | $parentTitles = $activeTitle.parents(selector.content).prev(selector.title), |
|
2491 | $activeAccordion = $activeTitle.closest(selector.accordion), |
|
2492 | activeSelector = selector.title + '.' + className.active + ':visible', |
|
2493 | activeContent = selector.content + '.' + className.active + ':visible', |
|
2494 | $openTitles, |
|
2495 | $nestedTitles, |
|
2496 | $openContents |
|
2497 | ; |
|
2498 | if(settings.closeNested) { |
|
2499 | $openTitles = $activeAccordion.find(activeSelector).not($parentTitles); |
|
2500 | $openContents = $openTitles.next($content); |
|
2501 | } |
|
2502 | else { |
|
2503 | $openTitles = $activeAccordion.find(activeSelector).not($parentTitles); |
|
2504 | $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles); |
|
2505 | $openTitles = $openTitles.not($nestedTitles); |
|
2506 | $openContents = $openTitles.next($content); |
|
2507 | } |
|
2508 | if( ($openTitles.length > 0) ) { |
|
2509 | module.debug('Exclusive enabled, closing other content', $openTitles); |
|
2510 | $openTitles |
|
2511 | .removeClass(className.active) |
|
2512 | ; |
|
2513 | $openContents |
|
2514 | .removeClass(className.animating) |
|
2515 | .stop(true, true) |
|
2516 | ; |
|
2517 | if(settings.animateChildren) { |
|
2518 | if($.fn.transition !== undefined && $module.transition('is supported')) { |
|
2519 | $openContents |
|
2520 | .children() |
|
2521 | .transition({ |
|
2522 | animation : 'fade out', |
|
2523 | useFailSafe : true, |
|
2524 | debug : settings.debug, |
|
2525 | verbose : settings.verbose, |
|
2526 | duration : settings.duration |
|
2527 | }) |
|
2528 | ; |
|
2529 | } |
|
2530 | else { |
|
2531 | $openContents |
|
2532 | .children() |
|
2533 | .stop(true, true) |
|
2534 | .animate({ |
|
2535 | opacity: 0 |
|
2536 | }, settings.duration, module.resetOpacity) |
|
2537 | ; |
|
2538 | } |
|
2539 | } |
|
2540 | $openContents |
|
2541 | .slideUp(settings.duration , settings.easing, function() { |
|
2542 | $(this).removeClass(className.active); |
|
2543 | module.reset.display.call(this); |
|
2544 | }) |
|
2545 | ; |
|
2546 | } |
|
2547 | }, |
|
2548 | ||
2549 | reset: { |
|
2550 | ||
2551 | display: function() { |
|
2552 | module.verbose('Removing inline display from element', this); |
|
2553 | $(this).css('display', ''); |
|
2554 | if( $(this).attr('style') === '') { |
|
2555 | $(this) |
|
2556 | .attr('style', '') |
|
2557 | .removeAttr('style') |
|
2558 | ; |
|
2559 | } |
|
2560 | }, |
|
2561 | ||
2562 | opacity: function() { |
|
2563 | module.verbose('Removing inline opacity from element', this); |
|
2564 | $(this).css('opacity', ''); |
|
2565 | if( $(this).attr('style') === '') { |
|
2566 | $(this) |
|
2567 | .attr('style', '') |
|
2568 | .removeAttr('style') |
|
2569 | ; |
|
2570 | } |
|
2571 | }, |
|
2572 | ||
2573 | }, |
|
2574 | ||
2575 | setting: function(name, value) { |
|
2576 | module.debug('Changing setting', name, value); |
|
2577 | if( $.isPlainObject(name) ) { |
|
2578 | $.extend(true, settings, name); |
|
2579 | } |
|
2580 | else if(value !== undefined) { |
|
2581 | if($.isPlainObject(settings[name])) { |
|
2582 | $.extend(true, settings[name], value); |
|
2583 | } |
|
2584 | else { |
|
2585 | settings[name] = value; |
|
2586 | } |
|
2587 | } |
|
2588 | else { |
|
2589 | return settings[name]; |
|
2590 | } |
|
2591 | }, |
|
2592 | internal: function(name, value) { |
|
2593 | module.debug('Changing internal', name, value); |
|
2594 | if(value !== undefined) { |
|
2595 | if( $.isPlainObject(name) ) { |
|
2596 | $.extend(true, module, name); |
|
2597 | } |
|
2598 | else { |
|
2599 | module[name] = value; |
|
2600 | } |
|
2601 | } |
|
2602 | else { |
|
2603 | return module[name]; |
|
2604 | } |
|
2605 | }, |
|
2606 | debug: function() { |
|
2607 | if(!settings.silent && settings.debug) { |
|
2608 | if(settings.performance) { |
|
2609 | module.performance.log(arguments); |
|
2610 | } |
|
2611 | else { |
|
2612 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
2613 | module.debug.apply(console, arguments); |
|
2614 | } |
|
2615 | } |
|
2616 | }, |
|
2617 | verbose: function() { |
|
2618 | if(!settings.silent && settings.verbose && settings.debug) { |
|
2619 | if(settings.performance) { |
|
2620 | module.performance.log(arguments); |
|
2621 | } |
|
2622 | else { |
|
2623 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
2624 | module.verbose.apply(console, arguments); |
|
2625 | } |
|
2626 | } |
|
2627 | }, |
|
2628 | error: function() { |
|
2629 | if(!settings.silent) { |
|
2630 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); |
|
2631 | module.error.apply(console, arguments); |
|
2632 | } |
|
2633 | }, |
|
2634 | performance: { |
|
2635 | log: function(message) { |
|
2636 | var |
|
2637 | currentTime, |
|
2638 | executionTime, |
|
2639 | previousTime |
|
2640 | ; |
|
2641 | if(settings.performance) { |
|
2642 | currentTime = new Date().getTime(); |
|
2643 | previousTime = time || currentTime; |
|
2644 | executionTime = currentTime - previousTime; |
|
2645 | time = currentTime; |
|
2646 | performance.push({ |
|
2647 | 'Name' : message[0], |
|
2648 | 'Arguments' : [].slice.call(message, 1) || '', |
|
2649 | 'Element' : element, |
|
2650 | 'Execution Time' : executionTime |
|
2651 | }); |
|
2652 | } |
|
2653 | clearTimeout(module.performance.timer); |
|
2654 | module.performance.timer = setTimeout(module.performance.display, 500); |
|
2655 | }, |
|
2656 | display: function() { |
|
2657 | var |
|
2658 | title = settings.name + ':', |
|
2659 | totalTime = 0 |
|
2660 | ; |
|
2661 | time = false; |
|
2662 | clearTimeout(module.performance.timer); |
|
2663 | $.each(performance, function(index, data) { |
|
2664 | totalTime += data['Execution Time']; |
|
2665 | }); |
|
2666 | title += ' ' + totalTime + 'ms'; |
|
2667 | if(moduleSelector) { |
|
2668 | title += ' \'' + moduleSelector + '\''; |
|
2669 | } |
|
2670 | if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
|
2671 | console.groupCollapsed(title); |
|
2672 | if(console.table) { |
|
2673 | console.table(performance); |
|
2674 | } |
|
2675 | else { |
|
2676 | $.each(performance, function(index, data) { |
|
2677 | console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); |
|
2678 | }); |
|
2679 | } |
|
2680 | console.groupEnd(); |
|
2681 | } |
|
2682 | performance = []; |
|
2683 | } |
|
2684 | }, |
|
2685 | invoke: function(query, passedArguments, context) { |
|
2686 | var |
|
2687 | object = instance, |
|
2688 | maxDepth, |
|
2689 | found, |
|
2690 | response |
|
2691 | ; |
|
2692 | passedArguments = passedArguments || queryArguments; |
|
2693 | context = element || context; |
|
2694 | if(typeof query == 'string' && object !== undefined) { |
|
2695 | query = query.split(/[\. ]/); |
|
2696 | maxDepth = query.length - 1; |
|
2697 | $.each(query, function(depth, value) { |
|
2698 | var camelCaseValue = (depth != maxDepth) |
|
2699 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) |
|
2700 | : query |
|
2701 | ; |
|
2702 | if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { |
|
2703 | object = object[camelCaseValue]; |
|
2704 | } |
|
2705 | else if( object[camelCaseValue] !== undefined ) { |
|
2706 | found = object[camelCaseValue]; |
|
2707 | return false; |
|
2708 | } |
|
2709 | else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { |
|
2710 | object = object[value]; |
|
2711 | } |
|
2712 | else if( object[value] !== undefined ) { |
|
2713 | found = object[value]; |
|
2714 | return false; |
|
2715 | } |
|
2716 | else { |
|
2717 | module.error(error.method, query); |
|
2718 | return false; |
|
2719 | } |
|
2720 | }); |
|
2721 | } |
|
2722 | if ( $.isFunction( found ) ) { |
|
2723 | response = found.apply(context, passedArguments); |
|
2724 | } |
|
2725 | else if(found !== undefined) { |
|
2726 | response = found; |
|
2727 | } |
|
2728 | if($.isArray(returnedValue)) { |
|
2729 | returnedValue.push(response); |
|
2730 | } |
|
2731 | else if(returnedValue !== undefined) { |
|
2732 | returnedValue = [returnedValue, response]; |
|
2733 | } |
|
2734 | else if(response !== undefined) { |
|
2735 | returnedValue = response; |
|
2736 | } |
|
2737 | return found; |
|
2738 | } |
|
2739 | }; |
|
2740 | if(methodInvoked) { |
|
2741 | if(instance === undefined) { |
|
2742 | module.initialize(); |
|
2743 | } |
|
2744 | module.invoke(query); |
|
2745 | } |
|
2746 | else { |
|
2747 | if(instance !== undefined) { |
|
2748 | instance.invoke('destroy'); |
|
2749 | } |
|
2750 | module.initialize(); |
|
2751 | } |
|
2752 | }) |
|
2753 | ; |
|
2754 | return (returnedValue !== undefined) |
|
2755 | ? returnedValue |
|
2756 | : this |
|
2757 | ; |
|
2758 | }; |
|
2759 | ||
2760 | $.fn.accordion.settings = { |
|
2761 | ||
2762 | name : 'Accordion', |
|
2763 | namespace : 'accordion', |
|
2764 | ||
2765 | silent : false, |
|
2766 | debug : false, |
|
2767 | verbose : false, |
|
2768 | performance : true, |
|
2769 | ||
2770 | on : 'click', // event on title that opens accordion |
|
2771 | ||
2772 | observeChanges : true, // whether accordion should automatically refresh on DOM insertion |
|
2773 | ||
2774 | exclusive : true, // whether a single accordion content panel should be open at once |
|
2775 | collapsible : true, // whether accordion content can be closed |
|
2776 | closeNested : false, // whether nested content should be closed when a panel is closed |
|
2777 | animateChildren : true, // whether children opacity should be animated |
|
2778 | ||
2779 | duration : 350, // duration of animation |
|
2780 | easing : 'easeOutQuad', // easing equation for animation |
|
2781 | ||
2782 | ||
2783 | onOpening : function(){}, // callback before open animation |
|
2784 | onOpen : function(){}, // callback after open animation |
|
2785 | onClosing : function(){}, // callback before closing animation |
|
2786 | onClose : function(){}, // callback after closing animation |
|
2787 | onChange : function(){}, // callback after closing or opening animation |
|
2788 | ||
2789 | error: { |
|
2790 | method : 'The method you called is not defined' |
|
2791 | }, |
|
2792 | ||
2793 | className : { |
|
2794 | active : 'active', |
|
2795 | animating : 'animating' |
|
2796 | }, |
|
2797 | ||
2798 | selector : { |
|
2799 | accordion : '.accordion', |
|
2800 | title : '.title', |
|
2801 | trigger : '.title', |
|
2802 | content : '.content' |
|
2803 | } |
|
2804 | ||
2805 | }; |
|
2806 | ||
2807 | // Adds easing |
|
2808 | $.extend( $.easing, { |
|
2809 | easeOutQuad: function (x, t, b, c, d) { |
|
2810 | return -c *(t/=d)*(t-2) + b; |
|
2811 | } |
|
2812 | }); |
|
2813 | ||
2814 | })( jQuery, window, document ); |
|
2815 | ||
2816 | ||
2817 | /*! |
@@ 11-609 (lines=599) @@ | ||
8 | * |
|
9 | */ |
|
10 | ||
11 | ;(function ($, window, document, undefined) { |
|
12 | ||
13 | "use strict"; |
|
14 | ||
15 | window = (typeof window != 'undefined' && window.Math == Math) |
|
16 | ? window |
|
17 | : (typeof self != 'undefined' && self.Math == Math) |
|
18 | ? self |
|
19 | : Function('return this')() |
|
20 | ; |
|
21 | ||
22 | $.fn.accordion = function(parameters) { |
|
23 | var |
|
24 | $allModules = $(this), |
|
25 | ||
26 | time = new Date().getTime(), |
|
27 | performance = [], |
|
28 | ||
29 | query = arguments[0], |
|
30 | methodInvoked = (typeof query == 'string'), |
|
31 | queryArguments = [].slice.call(arguments, 1), |
|
32 | ||
33 | requestAnimationFrame = window.requestAnimationFrame |
|
34 | || window.mozRequestAnimationFrame |
|
35 | || window.webkitRequestAnimationFrame |
|
36 | || window.msRequestAnimationFrame |
|
37 | || function(callback) { setTimeout(callback, 0); }, |
|
38 | ||
39 | returnedValue |
|
40 | ; |
|
41 | $allModules |
|
42 | .each(function() { |
|
43 | var |
|
44 | settings = ( $.isPlainObject(parameters) ) |
|
45 | ? $.extend(true, {}, $.fn.accordion.settings, parameters) |
|
46 | : $.extend({}, $.fn.accordion.settings), |
|
47 | ||
48 | className = settings.className, |
|
49 | namespace = settings.namespace, |
|
50 | selector = settings.selector, |
|
51 | error = settings.error, |
|
52 | ||
53 | eventNamespace = '.' + namespace, |
|
54 | moduleNamespace = 'module-' + namespace, |
|
55 | moduleSelector = $allModules.selector || '', |
|
56 | ||
57 | $module = $(this), |
|
58 | $title = $module.find(selector.title), |
|
59 | $content = $module.find(selector.content), |
|
60 | ||
61 | element = this, |
|
62 | instance = $module.data(moduleNamespace), |
|
63 | observer, |
|
64 | module |
|
65 | ; |
|
66 | ||
67 | module = { |
|
68 | ||
69 | initialize: function() { |
|
70 | module.debug('Initializing', $module); |
|
71 | module.bind.events(); |
|
72 | if(settings.observeChanges) { |
|
73 | module.observeChanges(); |
|
74 | } |
|
75 | module.instantiate(); |
|
76 | }, |
|
77 | ||
78 | instantiate: function() { |
|
79 | instance = module; |
|
80 | $module |
|
81 | .data(moduleNamespace, module) |
|
82 | ; |
|
83 | }, |
|
84 | ||
85 | destroy: function() { |
|
86 | module.debug('Destroying previous instance', $module); |
|
87 | $module |
|
88 | .off(eventNamespace) |
|
89 | .removeData(moduleNamespace) |
|
90 | ; |
|
91 | }, |
|
92 | ||
93 | refresh: function() { |
|
94 | $title = $module.find(selector.title); |
|
95 | $content = $module.find(selector.content); |
|
96 | }, |
|
97 | ||
98 | observeChanges: function() { |
|
99 | if('MutationObserver' in window) { |
|
100 | observer = new MutationObserver(function(mutations) { |
|
101 | module.debug('DOM tree modified, updating selector cache'); |
|
102 | module.refresh(); |
|
103 | }); |
|
104 | observer.observe(element, { |
|
105 | childList : true, |
|
106 | subtree : true |
|
107 | }); |
|
108 | module.debug('Setting up mutation observer', observer); |
|
109 | } |
|
110 | }, |
|
111 | ||
112 | bind: { |
|
113 | events: function() { |
|
114 | module.debug('Binding delegated events'); |
|
115 | $module |
|
116 | .on(settings.on + eventNamespace, selector.trigger, module.event.click) |
|
117 | ; |
|
118 | } |
|
119 | }, |
|
120 | ||
121 | event: { |
|
122 | click: function() { |
|
123 | module.toggle.call(this); |
|
124 | } |
|
125 | }, |
|
126 | ||
127 | toggle: function(query) { |
|
128 | var |
|
129 | $activeTitle = (query !== undefined) |
|
130 | ? (typeof query === 'number') |
|
131 | ? $title.eq(query) |
|
132 | : $(query).closest(selector.title) |
|
133 | : $(this).closest(selector.title), |
|
134 | $activeContent = $activeTitle.next($content), |
|
135 | isAnimating = $activeContent.hasClass(className.animating), |
|
136 | isActive = $activeContent.hasClass(className.active), |
|
137 | isOpen = (isActive && !isAnimating), |
|
138 | isOpening = (!isActive && isAnimating) |
|
139 | ; |
|
140 | module.debug('Toggling visibility of content', $activeTitle); |
|
141 | if(isOpen || isOpening) { |
|
142 | if(settings.collapsible) { |
|
143 | module.close.call($activeTitle); |
|
144 | } |
|
145 | else { |
|
146 | module.debug('Cannot close accordion content collapsing is disabled'); |
|
147 | } |
|
148 | } |
|
149 | else { |
|
150 | module.open.call($activeTitle); |
|
151 | } |
|
152 | }, |
|
153 | ||
154 | open: function(query) { |
|
155 | var |
|
156 | $activeTitle = (query !== undefined) |
|
157 | ? (typeof query === 'number') |
|
158 | ? $title.eq(query) |
|
159 | : $(query).closest(selector.title) |
|
160 | : $(this).closest(selector.title), |
|
161 | $activeContent = $activeTitle.next($content), |
|
162 | isAnimating = $activeContent.hasClass(className.animating), |
|
163 | isActive = $activeContent.hasClass(className.active), |
|
164 | isOpen = (isActive || isAnimating) |
|
165 | ; |
|
166 | if(isOpen) { |
|
167 | module.debug('Accordion already open, skipping', $activeContent); |
|
168 | return; |
|
169 | } |
|
170 | module.debug('Opening accordion content', $activeTitle); |
|
171 | settings.onOpening.call($activeContent); |
|
172 | if(settings.exclusive) { |
|
173 | module.closeOthers.call($activeTitle); |
|
174 | } |
|
175 | $activeTitle |
|
176 | .addClass(className.active) |
|
177 | ; |
|
178 | $activeContent |
|
179 | .stop(true, true) |
|
180 | .addClass(className.animating) |
|
181 | ; |
|
182 | if(settings.animateChildren) { |
|
183 | if($.fn.transition !== undefined && $module.transition('is supported')) { |
|
184 | $activeContent |
|
185 | .children() |
|
186 | .transition({ |
|
187 | animation : 'fade in', |
|
188 | queue : false, |
|
189 | useFailSafe : true, |
|
190 | debug : settings.debug, |
|
191 | verbose : settings.verbose, |
|
192 | duration : settings.duration |
|
193 | }) |
|
194 | ; |
|
195 | } |
|
196 | else { |
|
197 | $activeContent |
|
198 | .children() |
|
199 | .stop(true, true) |
|
200 | .animate({ |
|
201 | opacity: 1 |
|
202 | }, settings.duration, module.resetOpacity) |
|
203 | ; |
|
204 | } |
|
205 | } |
|
206 | $activeContent |
|
207 | .slideDown(settings.duration, settings.easing, function() { |
|
208 | $activeContent |
|
209 | .removeClass(className.animating) |
|
210 | .addClass(className.active) |
|
211 | ; |
|
212 | module.reset.display.call(this); |
|
213 | settings.onOpen.call(this); |
|
214 | settings.onChange.call(this); |
|
215 | }) |
|
216 | ; |
|
217 | }, |
|
218 | ||
219 | close: function(query) { |
|
220 | var |
|
221 | $activeTitle = (query !== undefined) |
|
222 | ? (typeof query === 'number') |
|
223 | ? $title.eq(query) |
|
224 | : $(query).closest(selector.title) |
|
225 | : $(this).closest(selector.title), |
|
226 | $activeContent = $activeTitle.next($content), |
|
227 | isAnimating = $activeContent.hasClass(className.animating), |
|
228 | isActive = $activeContent.hasClass(className.active), |
|
229 | isOpening = (!isActive && isAnimating), |
|
230 | isClosing = (isActive && isAnimating) |
|
231 | ; |
|
232 | if((isActive || isOpening) && !isClosing) { |
|
233 | module.debug('Closing accordion content', $activeContent); |
|
234 | settings.onClosing.call($activeContent); |
|
235 | $activeTitle |
|
236 | .removeClass(className.active) |
|
237 | ; |
|
238 | $activeContent |
|
239 | .stop(true, true) |
|
240 | .addClass(className.animating) |
|
241 | ; |
|
242 | if(settings.animateChildren) { |
|
243 | if($.fn.transition !== undefined && $module.transition('is supported')) { |
|
244 | $activeContent |
|
245 | .children() |
|
246 | .transition({ |
|
247 | animation : 'fade out', |
|
248 | queue : false, |
|
249 | useFailSafe : true, |
|
250 | debug : settings.debug, |
|
251 | verbose : settings.verbose, |
|
252 | duration : settings.duration |
|
253 | }) |
|
254 | ; |
|
255 | } |
|
256 | else { |
|
257 | $activeContent |
|
258 | .children() |
|
259 | .stop(true, true) |
|
260 | .animate({ |
|
261 | opacity: 0 |
|
262 | }, settings.duration, module.resetOpacity) |
|
263 | ; |
|
264 | } |
|
265 | } |
|
266 | $activeContent |
|
267 | .slideUp(settings.duration, settings.easing, function() { |
|
268 | $activeContent |
|
269 | .removeClass(className.animating) |
|
270 | .removeClass(className.active) |
|
271 | ; |
|
272 | module.reset.display.call(this); |
|
273 | settings.onClose.call(this); |
|
274 | settings.onChange.call(this); |
|
275 | }) |
|
276 | ; |
|
277 | } |
|
278 | }, |
|
279 | ||
280 | closeOthers: function(index) { |
|
281 | var |
|
282 | $activeTitle = (index !== undefined) |
|
283 | ? $title.eq(index) |
|
284 | : $(this).closest(selector.title), |
|
285 | $parentTitles = $activeTitle.parents(selector.content).prev(selector.title), |
|
286 | $activeAccordion = $activeTitle.closest(selector.accordion), |
|
287 | activeSelector = selector.title + '.' + className.active + ':visible', |
|
288 | activeContent = selector.content + '.' + className.active + ':visible', |
|
289 | $openTitles, |
|
290 | $nestedTitles, |
|
291 | $openContents |
|
292 | ; |
|
293 | if(settings.closeNested) { |
|
294 | $openTitles = $activeAccordion.find(activeSelector).not($parentTitles); |
|
295 | $openContents = $openTitles.next($content); |
|
296 | } |
|
297 | else { |
|
298 | $openTitles = $activeAccordion.find(activeSelector).not($parentTitles); |
|
299 | $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles); |
|
300 | $openTitles = $openTitles.not($nestedTitles); |
|
301 | $openContents = $openTitles.next($content); |
|
302 | } |
|
303 | if( ($openTitles.length > 0) ) { |
|
304 | module.debug('Exclusive enabled, closing other content', $openTitles); |
|
305 | $openTitles |
|
306 | .removeClass(className.active) |
|
307 | ; |
|
308 | $openContents |
|
309 | .removeClass(className.animating) |
|
310 | .stop(true, true) |
|
311 | ; |
|
312 | if(settings.animateChildren) { |
|
313 | if($.fn.transition !== undefined && $module.transition('is supported')) { |
|
314 | $openContents |
|
315 | .children() |
|
316 | .transition({ |
|
317 | animation : 'fade out', |
|
318 | useFailSafe : true, |
|
319 | debug : settings.debug, |
|
320 | verbose : settings.verbose, |
|
321 | duration : settings.duration |
|
322 | }) |
|
323 | ; |
|
324 | } |
|
325 | else { |
|
326 | $openContents |
|
327 | .children() |
|
328 | .stop(true, true) |
|
329 | .animate({ |
|
330 | opacity: 0 |
|
331 | }, settings.duration, module.resetOpacity) |
|
332 | ; |
|
333 | } |
|
334 | } |
|
335 | $openContents |
|
336 | .slideUp(settings.duration , settings.easing, function() { |
|
337 | $(this).removeClass(className.active); |
|
338 | module.reset.display.call(this); |
|
339 | }) |
|
340 | ; |
|
341 | } |
|
342 | }, |
|
343 | ||
344 | reset: { |
|
345 | ||
346 | display: function() { |
|
347 | module.verbose('Removing inline display from element', this); |
|
348 | $(this).css('display', ''); |
|
349 | if( $(this).attr('style') === '') { |
|
350 | $(this) |
|
351 | .attr('style', '') |
|
352 | .removeAttr('style') |
|
353 | ; |
|
354 | } |
|
355 | }, |
|
356 | ||
357 | opacity: function() { |
|
358 | module.verbose('Removing inline opacity from element', this); |
|
359 | $(this).css('opacity', ''); |
|
360 | if( $(this).attr('style') === '') { |
|
361 | $(this) |
|
362 | .attr('style', '') |
|
363 | .removeAttr('style') |
|
364 | ; |
|
365 | } |
|
366 | }, |
|
367 | ||
368 | }, |
|
369 | ||
370 | setting: function(name, value) { |
|
371 | module.debug('Changing setting', name, value); |
|
372 | if( $.isPlainObject(name) ) { |
|
373 | $.extend(true, settings, name); |
|
374 | } |
|
375 | else if(value !== undefined) { |
|
376 | if($.isPlainObject(settings[name])) { |
|
377 | $.extend(true, settings[name], value); |
|
378 | } |
|
379 | else { |
|
380 | settings[name] = value; |
|
381 | } |
|
382 | } |
|
383 | else { |
|
384 | return settings[name]; |
|
385 | } |
|
386 | }, |
|
387 | internal: function(name, value) { |
|
388 | module.debug('Changing internal', name, value); |
|
389 | if(value !== undefined) { |
|
390 | if( $.isPlainObject(name) ) { |
|
391 | $.extend(true, module, name); |
|
392 | } |
|
393 | else { |
|
394 | module[name] = value; |
|
395 | } |
|
396 | } |
|
397 | else { |
|
398 | return module[name]; |
|
399 | } |
|
400 | }, |
|
401 | debug: function() { |
|
402 | if(!settings.silent && settings.debug) { |
|
403 | if(settings.performance) { |
|
404 | module.performance.log(arguments); |
|
405 | } |
|
406 | else { |
|
407 | module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
408 | module.debug.apply(console, arguments); |
|
409 | } |
|
410 | } |
|
411 | }, |
|
412 | verbose: function() { |
|
413 | if(!settings.silent && settings.verbose && settings.debug) { |
|
414 | if(settings.performance) { |
|
415 | module.performance.log(arguments); |
|
416 | } |
|
417 | else { |
|
418 | module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':'); |
|
419 | module.verbose.apply(console, arguments); |
|
420 | } |
|
421 | } |
|
422 | }, |
|
423 | error: function() { |
|
424 | if(!settings.silent) { |
|
425 | module.error = Function.prototype.bind.call(console.error, console, settings.name + ':'); |
|
426 | module.error.apply(console, arguments); |
|
427 | } |
|
428 | }, |
|
429 | performance: { |
|
430 | log: function(message) { |
|
431 | var |
|
432 | currentTime, |
|
433 | executionTime, |
|
434 | previousTime |
|
435 | ; |
|
436 | if(settings.performance) { |
|
437 | currentTime = new Date().getTime(); |
|
438 | previousTime = time || currentTime; |
|
439 | executionTime = currentTime - previousTime; |
|
440 | time = currentTime; |
|
441 | performance.push({ |
|
442 | 'Name' : message[0], |
|
443 | 'Arguments' : [].slice.call(message, 1) || '', |
|
444 | 'Element' : element, |
|
445 | 'Execution Time' : executionTime |
|
446 | }); |
|
447 | } |
|
448 | clearTimeout(module.performance.timer); |
|
449 | module.performance.timer = setTimeout(module.performance.display, 500); |
|
450 | }, |
|
451 | display: function() { |
|
452 | var |
|
453 | title = settings.name + ':', |
|
454 | totalTime = 0 |
|
455 | ; |
|
456 | time = false; |
|
457 | clearTimeout(module.performance.timer); |
|
458 | $.each(performance, function(index, data) { |
|
459 | totalTime += data['Execution Time']; |
|
460 | }); |
|
461 | title += ' ' + totalTime + 'ms'; |
|
462 | if(moduleSelector) { |
|
463 | title += ' \'' + moduleSelector + '\''; |
|
464 | } |
|
465 | if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) { |
|
466 | console.groupCollapsed(title); |
|
467 | if(console.table) { |
|
468 | console.table(performance); |
|
469 | } |
|
470 | else { |
|
471 | $.each(performance, function(index, data) { |
|
472 | console.log(data['Name'] + ': ' + data['Execution Time']+'ms'); |
|
473 | }); |
|
474 | } |
|
475 | console.groupEnd(); |
|
476 | } |
|
477 | performance = []; |
|
478 | } |
|
479 | }, |
|
480 | invoke: function(query, passedArguments, context) { |
|
481 | var |
|
482 | object = instance, |
|
483 | maxDepth, |
|
484 | found, |
|
485 | response |
|
486 | ; |
|
487 | passedArguments = passedArguments || queryArguments; |
|
488 | context = element || context; |
|
489 | if(typeof query == 'string' && object !== undefined) { |
|
490 | query = query.split(/[\. ]/); |
|
491 | maxDepth = query.length - 1; |
|
492 | $.each(query, function(depth, value) { |
|
493 | var camelCaseValue = (depth != maxDepth) |
|
494 | ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1) |
|
495 | : query |
|
496 | ; |
|
497 | if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) { |
|
498 | object = object[camelCaseValue]; |
|
499 | } |
|
500 | else if( object[camelCaseValue] !== undefined ) { |
|
501 | found = object[camelCaseValue]; |
|
502 | return false; |
|
503 | } |
|
504 | else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) { |
|
505 | object = object[value]; |
|
506 | } |
|
507 | else if( object[value] !== undefined ) { |
|
508 | found = object[value]; |
|
509 | return false; |
|
510 | } |
|
511 | else { |
|
512 | module.error(error.method, query); |
|
513 | return false; |
|
514 | } |
|
515 | }); |
|
516 | } |
|
517 | if ( $.isFunction( found ) ) { |
|
518 | response = found.apply(context, passedArguments); |
|
519 | } |
|
520 | else if(found !== undefined) { |
|
521 | response = found; |
|
522 | } |
|
523 | if($.isArray(returnedValue)) { |
|
524 | returnedValue.push(response); |
|
525 | } |
|
526 | else if(returnedValue !== undefined) { |
|
527 | returnedValue = [returnedValue, response]; |
|
528 | } |
|
529 | else if(response !== undefined) { |
|
530 | returnedValue = response; |
|
531 | } |
|
532 | return found; |
|
533 | } |
|
534 | }; |
|
535 | if(methodInvoked) { |
|
536 | if(instance === undefined) { |
|
537 | module.initialize(); |
|
538 | } |
|
539 | module.invoke(query); |
|
540 | } |
|
541 | else { |
|
542 | if(instance !== undefined) { |
|
543 | instance.invoke('destroy'); |
|
544 | } |
|
545 | module.initialize(); |
|
546 | } |
|
547 | }) |
|
548 | ; |
|
549 | return (returnedValue !== undefined) |
|
550 | ? returnedValue |
|
551 | : this |
|
552 | ; |
|
553 | }; |
|
554 | ||
555 | $.fn.accordion.settings = { |
|
556 | ||
557 | name : 'Accordion', |
|
558 | namespace : 'accordion', |
|
559 | ||
560 | silent : false, |
|
561 | debug : false, |
|
562 | verbose : false, |
|
563 | performance : true, |
|
564 | ||
565 | on : 'click', // event on title that opens accordion |
|
566 | ||
567 | observeChanges : true, // whether accordion should automatically refresh on DOM insertion |
|
568 | ||
569 | exclusive : true, // whether a single accordion content panel should be open at once |
|
570 | collapsible : true, // whether accordion content can be closed |
|
571 | closeNested : false, // whether nested content should be closed when a panel is closed |
|
572 | animateChildren : true, // whether children opacity should be animated |
|
573 | ||
574 | duration : 350, // duration of animation |
|
575 | easing : 'easeOutQuad', // easing equation for animation |
|
576 | ||
577 | ||
578 | onOpening : function(){}, // callback before open animation |
|
579 | onOpen : function(){}, // callback after open animation |
|
580 | onClosing : function(){}, // callback before closing animation |
|
581 | onClose : function(){}, // callback after closing animation |
|
582 | onChange : function(){}, // callback after closing or opening animation |
|
583 | ||
584 | error: { |
|
585 | method : 'The method you called is not defined' |
|
586 | }, |
|
587 | ||
588 | className : { |
|
589 | active : 'active', |
|
590 | animating : 'animating' |
|
591 | }, |
|
592 | ||
593 | selector : { |
|
594 | accordion : '.accordion', |
|
595 | title : '.title', |
|
596 | trigger : '.title', |
|
597 | content : '.content' |
|
598 | } |
|
599 | ||
600 | }; |
|
601 | ||
602 | // Adds easing |
|
603 | $.extend( $.easing, { |
|
604 | easeOutQuad: function (x, t, b, c, d) { |
|
605 | return -c *(t/=d)*(t-2) + b; |
|
606 | } |
|
607 | }); |
|
608 | ||
609 | })( jQuery, window, document ); |
|
610 | ||
611 |