/** * Plugin Name : Accordion.JS * Version : 2.1.1 * Author : ZeroWP Team * Author URL : http://zerowp.com/ * Plugin URL : http://accordionjs.zerowp.com/ * License : MIT */ ;(function ( $ ) { "use strict"; $.fn.accordionjs = function( options ) { // Select all accordions that match a CSS selector if (this.length > 1){ this.each(function() { $(this).accordionjs(options); }); return this; } // Current accordion instance var accordion = this; // Setup utility functions var util = { /** * Is integer * * Check if a value is a valid integer number * * @param {number} value * @return {bool} */ isInteger: function(value) { return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; }, //------------------------------------//--------------------------------------// /** * Is array * * Check if a value is a valid array. * * @param {Array} arg * @return {bool} */ isArray: function(arg) { return Object.prototype.toString.call(arg) === '[object Array]'; }, //------------------------------------//--------------------------------------// /** * Is object * * Check if a value is a valid object. * * @param {Object} arg * @return {bool} */ isObject: function isObject(arg) { return Object.prototype.toString.call(arg) === '[object Object]'; }, //------------------------------------//--------------------------------------// /** * Sections is open * * Check if a section from current accordion is open. * * @param {Object}(jQuery) section * @return {bool} */ sectionIsOpen: function( section ){ return section.hasClass( 'acc_active' ); }, //------------------------------------//--------------------------------------// /** * Get hash * * Get hash substring without # or false if the window does not have one. * * @return {string|bool(false)} */ getHash: function(){ if(window.location.hash) { return window.location.hash.substring(1); } return false; }, }; /* Setup options ---------------------*/ var settings = $.extend({ // Allow self close. closeAble : false, // Close other sections. closeOther : true, // Animation Speed. slideSpeed : 150, // The section open on first init. A number from 1 to X or false. activeIndex : 1, // Callback when a section is open openSection: false, // function( section ){} // Callback before a section is open beforeOpenSection: false, // function( section ){} }, options ); // Assign to accordion options data-* attributes if they exists $.each(settings, function( option ) { var data_attr = option.replace(/([A-Z])/g, '-$1').toLowerCase().toString(), //`optionsName` becomes `option-name` new_val = accordion.data( data_attr ); if( new_val || false === new_val ){ settings[ option ] = new_val; } }); /* If the activeIndex is false then all sections are closed by default. If the closeOther is false then other section will not be closed when this is opened. That means, in both cases, sections should be able to be closed independently. */ if( settings.activeIndex === false || settings.closeOther === false ){ settings.closeAble = true; } //------------------------------------//--------------------------------------// /** * "Constructor" * * @return void */ var init = function() { accordion.create(); accordion.openOnClick(); $(window).on( 'load', function(){ accordion.openOnHash(); }); $(window).on( 'hashchange', function(){ accordion.openOnHash(); }); }; //------------------------------------//--------------------------------------// /** * Open section * * Open a single section. * * @param {Object}(jQuery) section The section to open * @param {number} speed * @return void */ this.openSection = function(section, speed){ // Event before a section is opened $(document).trigger('accjs_before_open_section', [ section, ]); // Callback before a section is opened if( typeof settings.beforeOpenSection === "function" ){ settings.beforeOpenSection.call(this, section); } // Setup the collapse speed speed = ( speed >= 0 ) ? speed : settings.slideSpeed; // Get the section content var section_content = section.children().eq(1); // .acc_content // Open the section section_content.slideDown( speed, function(){ // Event when a section is opened $(document).trigger('accjs_open_section', [ section, ]); // Callback when a section is opened if( typeof settings.openSection === "function" ){ settings.openSection.call(this, section); } } ); // Make active section.addClass('acc_active'); }; //------------------------------------//--------------------------------------// /** * Close section * * Close a single section. * * @param {Object}(jQuery) section The section to close * @param {number} speed * @return void */ this.closeSection = function(section, speed){ // Event before a section is closed $(document).trigger('accjs_before_close_section', [ section, ]); // Callback before a section is closed if( typeof settings.beforeCloseSection === "function" ){ settings.beforeCloseSection.call(this, section); } // Setup the collapse speed speed = ( speed >= 0 ) ? speed : settings.slideSpeed; // Get the section content var section_content = section.children().eq(1); // .acc_content // Open the section section_content.slideUp( speed, function(){ // Event when a section is closed $(document).trigger('accjs_close_section', [ section, ]); // Callback when a section is closed if( typeof settings.closeSection === "function" ){ settings.closeSection.call(this, section); } } ); // Make inactive section.removeClass('acc_active'); }; //------------------------------------//--------------------------------------// /** * Close other sections except this one * * @param {Object}(jQuery) section The section to exclude * @param {number} speed * @return void */ this.closeOtherSections = function(section, speed){ var this_acc = section.closest('.accordionjs').children(); $(this_acc).each(function() { accordion.closeSection( $(this).not(section), speed ); }); }; //------------------------------------//--------------------------------------// /** * Create the accordion * * Create the accordion structure. Add the necessary CSS classes and other stuff. * * @return void */ this.create = function() { //Add Main CSS Class accordion.addClass('accordionjs'); // Get all current accordion sections var accordion_sections = accordion.children(); //Add classes to accordion head and content for each section $.each( accordion_sections, function(index, elem){ accordion.createSingleSection( $(elem) ); }); // //Active index if( util.isArray( settings.activeIndex ) ){ var indexes = settings.activeIndex; for (var i = 0; i < indexes.length; i++) { accordion.openSection( accordion_sections.eq( indexes[i] - 1 ), 0 ); } } else if( settings.activeIndex > 1 ){ accordion.openSection( accordion_sections.eq( settings.activeIndex - 1 ), 0 ); } else if( false !== settings.activeIndex ){ accordion.openSection( accordion_sections.eq( 0 ), 0 ); } }; //------------------------------------//--------------------------------------// /** * Create a single section * * Create the structure of a single section by adding the necessary CSS classes. * * @param {string} section The section to create. jQuery object. * @return void */ this.createSingleSection = function( section ) { var childs = section.children(); // Create sections if they were not created already section.addClass('acc_section'); // Add the necessary CSS classes $(childs[0]).addClass('acc_head'); $(childs[1]).addClass('acc_content'); // Collapse section content. // Only if it does not have `.acc_active` CSS class set by default. if( ! section.hasClass('acc_active') ) { section.children('.acc_content').hide(); } }; //------------------------------------//--------------------------------------// /** * Open on click * * Open a section when its header get a click. * * @return void */ this.openOnClick = function() { accordion.on('click', '.acc_head', function( event ){ event.stopImmediatePropagation(); var section = $(this).closest('.acc_section'); if( util.sectionIsOpen( section ) ) { // If closeAble, then close this section but do not touch other. if( settings.closeAble ) { accordion.closeSection( section ); } // If the accordion contains only one section, act like a toggle. else if( accordion.children().length === 1 ) { accordion.closeSection( section ); } } // Section is closed else { // If closeOther, then close other sections when this is opened. if( settings.closeOther ) { accordion.closeOtherSections( section ); accordion.openSection( section ); } // Else open only this section and do not touch other sections. else { accordion.openSection( section ); } } }); }; //------------------------------------//--------------------------------------// /** * Open a section if a hash is present in URL and scroll to it. * * @return void */ this.openOnHash = function() { if( util.getHash() ) { var section = $( '#' + util.getHash() ); if( section.hasClass('acc_section') ) { accordion.openSection( section ); if( settings.closeOther ) { accordion.closeOtherSections( section ); } $("html, body").animate({ scrollTop: parseInt( section.offset().top ) - 50, }, 150); } } }; //"Constructor" init init(); return this; }; }( jQuery ));