토글 슬라이드 속도문제(스크립트소스좀 봐주세요)

토글 슬라이드 속도문제(스크립트소스좀 봐주세요)

QA

토글 슬라이드 속도문제(스크립트소스좀 봐주세요)

본문


/**
 * jQuery Collapsable - jQuery plugin for collapsable boxes 
 * http://zipper.github.io/jquery.collapsable/
 *
 * @author Radek Šerý <*** 개인정보보호를 위한 이메일주소 노출방지 ***>
 * @copyright Copyright (c) 2014-2016 Radek Šerý
 * @license MIT
 *
 * @version 2.0.2
 */
;(function($) {
 // @feature: díky předávání collapsableEvent do expand.collapsable (atd.) je možné použít e.collapsableEvent.preventDefault() místo defaults.preventDefault! cool, ne?!
 /**
  * Collapsable defaults
  * @type {{control: string, box: string, event: string, fx: boolean, fxDuration: number, accordion: boolean, collapsableAll: boolean, preventDefault: boolean, extLinks: {selector: null, preventDefault: boolean, activeClass: string}, classNames: {expanded: string, collapsed: string, defaultExpanded: string}}}
  */
 var defaults = {
  control: '.ca-control', // CSS selector for control element
  box: '.ca-box',         // CSS selector for hideable element (box)
  event: 'click',         // event triggering the expand/collapse
  preventDefault: true,   // whether prevenDefault should be called when specified event occurs on control; even if false, e.collapsableEvent.preventDefault() may be used inside collapsable event handlers
  fx: null,               // effect for expanding/collapsing, [ false | toggle | slide | fade | {Object} ]
  fxDuration: 0,          // duration of the effect, affects delay between `expand.collapsable`(`collapse.collapsable`) and `expanded.collapsable` (`collapsed.collapsable`) evetns are triggered; default value is 500 when fx set to slide
  accordion: false,       // determines, if there could be more than one expanded box in same time; related to jQuery set on which initialized
  collapsableAll: true,   // possibility of collapsing all boxes from set
  extLinks: {             // external links for operating collapsable set, can be anywhere else in DOM
   selector: '',       // CSS selector for external links; it has to be anchors; the click event is binded
   preventDefault: false // whether preventDefault is called on extLinks click
  },
  classNames: {            // CSS class names to be used on collapsable box; they are added to element, on which collapsable has been called
   expanded: 'ca-expanded',
   collapsed: 'ca-collapsed',
   defaultExpanded: 'ca-default-expanded',
   extLinkActive: 'ca-ext-active'
  }
  // callbacks are no more available, use event handlers instead
 };

 /**
  * Public methods available via jQuery adapter
  * @type {{init: methods.init, expandAll: methods.expandAll, collapseAll: methods.collapseAll, destroy: methods.destroy}}
  */
 var methods = {
  init: function (options) {
   return new Collapsable(this, options);
  },
  expandAll: function (data) {
   handlePublicMethods.call(this, 'expandAll', data);
  },
  collapseAll: function (data) {
   handlePublicMethods.call(this, 'collapseAll', data);
  },
  destroy: function (data) {
   handlePublicMethods.call(this, 'destroy', data);
  }
 };

 /**
  * Last used uid index
  * @type {number}
  * @private
  */
 var caUid = 0;

 /**
  * Generates unique id for new Collapsable object
  * @returns {String}  New uid
  * @private
  */
 function getUid() {
  return 'ca-uid-' + caUid++;
 }

 /**
  * Handles public method called on jQuery object using adapter
  * @param {String} action - collapseAll|expandAll|destroy
  * @param {Object} data - Data passed by user
  * @private
  */
 function handlePublicMethods(action, data) {
  var processed = [];
  this.each(function () {
   var instance = $(this).data('collapsable');
   if (instance) {
    var uid = instance.parent.uid;
    if (processed.indexOf(uid) === -1) {
     processed.push(uid);
     instance.parent[action](data);
    }
   }
  });
 }

 /**
  * Finds ext links specified in options and bind click event to them for opening
  * @this Collapsable
  * @todo create possibility for extLinks would only open the boxes? for now, it might be achieved using event handlers and e.preventDefault
  * @private
  */
 function handleExtLinks() {
  var opts = this.opts;
  if ((this.$extLinks = $(opts.extLinks.selector).filter('a')).length) {
   this.$extLinks.on('click.collapsable', function (event) {
    if (opts.extLinks.preventDefault)
     event.preventDefault();
    var collapsable = $($(this).attr('href')).data('collapsable');
    if (collapsable) {
     collapsable.$controlLink.first().trigger(opts.event + '.collapsable', event);
    }
   });
  }
 }
 
 

 /**
  * Prepare default expanded item. Checks the necessity of expanded item (collapsableAll set to false && accordion set
  * to true) and limits amount of default expanded items to 1 when accordion option set to true. Also when there's
  * fragment in url targeting existing collapsable item, default expanded set using class in DOM will be overridden.
  *
  * @summary Sets the defaultExpanded flag to appropriate CollapsableItems
  * @this Collapsable
  * @private
  */
 function prepareDefaultExpanded() {
  var fragment = window.location.href;
  var i = fragment.search(/#/);
  var defaultExpanded = -1;
  var defaultExpandedFromUrl = -1;
  var $items = $($.map(this.items, function (item) {
   return item.$collapsable.get();
  }));
  // search for #hash in url
  if (i !== -1) {
   fragment = fragment.substring(i + 1);
   defaultExpandedFromUrl = $items.index($('#' + fragment));
   if (defaultExpandedFromUrl !== -1) {
    this.items[defaultExpandedFromUrl].defaultExpanded = true;
    // max 1, we can return now
    if (this.opts.accordion) {
     return;
    }
   }
  }
  // max 1 expanded item
  if (this.opts.accordion) {
   defaultExpanded = $items.index($('.' + this.opts.classNames.defaultExpanded));
   // max 1, we can return now
   if (defaultExpanded !== -1) {
    this.items[defaultExpanded].defaultExpanded = true;
    return;
   }
  }
  // not accordion, we add flag to all items with class
  else {
   var that = this;
   $items.each(function (i) {
    if ($(this).hasClass(that.opts.classNames.defaultExpanded)) {
     defaultExpanded = i; // for later use it is sufficient to have last index only
     that.items[i].defaultExpanded = true;
    }
   });
  }
  // if we need one and none was found yet, we take the first
  if (defaultExpandedFromUrl === -1 && defaultExpanded === -1 && !this.opts.collapsableAll) {
   this.items[0].defaultExpanded = true;
  }
 }

 /**
  * Expand or collapse item based on flags set in prepareDefaultExpanded method; called on initialization within the
  * context of Collapsable
  * @todo When !opts.collapseAll && opts.accordion, we now force-open the first item with defaultExpanded flag, regardless how it got it (hash in url or class); potentially force-open the one from URL instead of first, if hash set? or maybe try to open some without forcing and only if failed, do force-open (would require two passes)?
  * @this Collapsable
  * @private
  */
 function handleDefaultExpanded() {
  var event = $.Event('init.collapsable');
  var opts = this.opts;
  var items = this.items;
  // save fx so it can be set back
  var fx = opts.fx;
  // for initialization, we don't want to use any effect
  if (opts.fx)
   opts.fx = 'toggle';
  var l = items.length;
  var force = !opts.collapsableAll; // if we can't collapse all, we force expanding the first one chosen in prepareDefaultExpanded
  for (var i = 0; i < l; i++) {
   if (items[i].defaultExpanded) {
    items[i].expand(event, null, force);
    force = false;
   } else {
    items[i].collapse(event, null, true); // on init, we want to force-close all - if false returned, than the class might have been set in first place (so it would go into if statement above)
   }
  }
  opts.fx = fx;
 }

 /**
  * It is possible to set the `fx` options to `slide` or `fade` - these are shortcuts for objects with
  * `{ expand: 'slideDown', collapse: 'slideUp' }` or `{ expand: 'fadeIn', collapse: 'fadeOut' }`. This function
  * converts those strings into objects. It also sets default duration for these effects to 500ms.
  * @this Collapsable
  * @private
  */
 function prepareFxOpt() {
  var opts = this.opts;
  // default fxDuration in case of slide function
  if (opts.fx === 'slide' || opts.fx === 'fade') {
   opts.fxDuration = opts.fxDuration || 0;
  }
  // convert alias into objects
  if (opts.fx === 'slide') {
   opts.fx = {
    expand: 'slideDown',
    collapse: 'slideUp'
   };
  } else if (this.opts.fx === 'fade') {
   opts.fx = {
    expand: 'fadeIn',
    collapse: 'fadeOut'
   };
  }
 }

 /**
  * Represents set of collapsable elements which were initialized by one call with same options
  * @name Collapsable
  * @param {jQuery} $boxSet - Set of object to be initilized
  * @param {Object} options - See plugin defaults
  * @returns {Collapsable}
  * @constructor
  */
 var Collapsable = function ($boxSet, options) {
  this.opts = $.extend(true, {}, $.fn.collapsable.defaults, options);
  this.items = [];
  var that = this;
  this.uid = getUid();
  this.promiseOpen = false;
  handleExtLinks.call(this);
  prepareFxOpt.call(this);
  $boxSet.each(function () {
   var collapsable = new CollapsableItem(that, this);
   if (collapsable.$box.length && collapsable.$control.length) {
    that.items.push(collapsable);
   }
  });
  prepareDefaultExpanded.call(this);
  handleDefaultExpanded.call(this);
  return this;
 };
 /**
  * Returns indexes of expanded items in Collapsable.items
  * @returns {Array}
  */
 Collapsable.prototype.getExpanded = function () {
  var expanded = [];
  var l = this.items.length;
  for (var i = 0; i < l; i++) {
   if (this.items[i].isExpanded) {
    expanded.push(i);
   }
  }
  return expanded;
 };

 /**
  * Expands all collapsed items
  * @param {Object} data - Data to be passed to triggered event
  */
 Collapsable.prototype.expandAll = function (data) {
  // if accordion, we only want to expand one (first) box, or none if already expanded
  if (this.opts.accordion && this.getExpanded().length) {
   return;
  }
  var event = $.Event('expandAll.collapsable');
  var l = this.items.length;
  for (var i = 0; i < l; i++) {
   if (! this.items[i].isExpanded) {
    var expanded = this.items[i].expand(event, data);
    if (this.opts.accordion && expanded) {
     break;
    }
   }
  }
 };

 /**
  * Collapses all expanded items
  * @param {Object} data - Data to be passed to triggered event
  */
 Collapsable.prototype.collapseAll = function (data) {
  var event = $.Event('collapseAll.collapsable');
  var expandedItems = this.getExpanded();
  var l = expandedItems.length;
  for (var i = 0; i < l; i++) {
   this.items[expandedItems[i]].collapse(event, data);
  }
 };

 /**
  * Destroy collapsable and reverts DOM changes to state prior initialization
  */
 Collapsable.prototype.destroy = function () {
  var opts = this.opts;
  var l = this.items.length;
  for (var i = 0; i < l; i++) {
   var item = this.items[i];
   // remove classes and event handlers from main element
   item.$collapsable
    .removeClass(opts.classNames.collapsed + ' ' + opts.classNames.expanded)
    .removeData('collapsable');
   // revert control element
   item.$control.find('[data-ca-created]').each(function () {
    $(this).parent().html($(this).html());
   });
   item.$control
    .find('.ca-link').addBack('.ca-link')
    .off(opts.event + '.collapsable')
    .removeClass('ca-link')
    .removeAttr('aria-controls')
    .removeAttr('aria-expanded');
   // revert box element
   var style = item.$box.data('ca-pre-init-style') || '';
   item.$box
    .attr('style', style)
    .removeData('ca-pre-init-style')
    .removeAttr('aria-hidden');
   item.$collapsable.trigger('destroy.collapsable');
  }
  // remove
  this.$extLinks.off('click.collapsable');
 };

 /**
  * Prepares DOM structure for collapsable element. Each ca-control element is tested for being anchor. If there's
  * match, the element (anchor) is added class `ca-link`. If no match, we try to find anchor inside and add class
  * to each of them as well. If ca-control is not an anchor and contains no anchor, we wrap inside to anchor with
  * appropriate class and custom data attribute for potential destroy handle. It also stores default style attribute
  * of box element for later use in destroy handle.
  * @summary Prepares DOM structure for collapsable element
  * @this CollapsableItem
  * @private
  */
 function prepareCollapsableDOM() {
  var collapsableItem = this;
  if (! collapsableItem.id) {
   collapsableItem.id = getUid();
   collapsableItem.$collapsable.attr('id', this.id);
  }
  var boxId = collapsableItem.$box.attr('id') || collapsableItem.id + '-ca-box';
  collapsableItem.$box
   .attr('id', boxId)
   .data('ca-pre-init-style', collapsableItem.$box.attr('style'));
  collapsableItem.$control.each(function() {
   var $el = $(this);
   var $a;
   // a.ca-control -> add class .ca-link
   if ($el.is('a')) {
    $a = $el;
   }
   // .ca-control a -> add class .ca-link
   else if (($a = $el.find('a')).length) {
   }
   // no anchor found, create custom
   else {
    $el.wrapInner('<a data-ca-created href="#' + collapsableItem.id + '"></a>');
    $a = $el.find('a');
   }
   $a.addClass('ca-link');
   $a.attr('aria-controls', boxId);
  });
 }

 /**
  * Single item in Collapsable object, represents one collapsable element in page
  * @param {Collapsable} parent - Reference to group of Collapsable elements initialized in same time, sharing same options
  * @param {jQuery} element     - One instance of collapsable element
  * @returns {CollapsableItem}
  * @constructor
  */
 var CollapsableItem = function(parent, element) {
  this.parent = parent;
  this.$collapsable = $(element);
  this.id = this.$collapsable.attr('id');
  this.$control = this.$collapsable.find(parent.opts.control);
  this.$box     = this.$collapsable.find(parent.opts.box);
  if (this.$control.length == 0 || this.$box.length == 0)
   return;
  var that = this;
  var opts = this.parent.opts; // shortcut
  prepareCollapsableDOM.call(this);
  this.$controlLink = this.$control.find('.ca-link').addBack('.ca-link');
  // collapsableEvent contains arguments passed when trigger is called, used for passing event that triggered opening (eg. extLink click)
  this.$controlLink.on(opts.event + '.collapsable', function(event, collapsableEvent) {
   var passEvent = collapsableEvent ? collapsableEvent : event;
   if (opts.preventDefault) {
    event.preventDefault();
   }
   if (that.isExpanded) {
    that.collapse(passEvent);
   }
   else {
    that.expand(passEvent);
   }
  });
  this.$collapsable.data('collapsable', this);
  return this;
 };

 /**
  * Handling common parts of expanding and collapsing
  * @param {String} action - Either `expand` or `collapse`
  * @param {Object} data - Data passed to triggered event
  * @param {Event} collapsableEvent - Event to be passed to event handlers
  * @returns {boolean}
  */
 function handleExpandCollapse(action, collapsableEvent, data) {
  var opts = this.parent.opts;
  var that = this;
  var trigger = 'expanded';
  var addClass = opts.classNames.expanded;
  var removeClass = opts.classNames.collapsed;
  // capitalize first letter
  if (action === 'collapse') {
   trigger = 'collapsed';
   addClass = opts.classNames.collapsed;
   removeClass = opts.classNames.expanded;
  }
  var event = $.Event(trigger + '.collapsable', { customData: data, collapsableEvent: collapsableEvent });
  this.isExpanded = action === 'expand';
  // update extLinks
  this.parent.$extLinks
   .filter('[href="#' + this.id + '"]')
   [action === 'expand' ? 'addClass' : 'removeClass'](opts.classNames.extLinkActive);
  // aria support
  this.$controlLink.attr('aria-expanded', action === 'expand');
  this.$box.attr('aria-hidden', action !== 'expand');
  // actually toggle the box state
  if(opts.fx && typeof opts.fx === 'object') {
   this.$box[opts.fx[action]](opts.fxDuration, function () {
    that.$collapsable.trigger(event);
   });
  }
  else {
   if(opts.fx === 'toggle') {
    this.$box[action === 'expand' ? 'show' : 'hide']();
   }
   setTimeout(function () {
    that.$collapsable.trigger(event);
   }, opts.fxDuration);
  }
  // update classes on collapsable element itself
  this.$collapsable
   .removeClass(removeClass)
   .addClass(addClass);
  return true;
 }
 /**
  * Expands single CollapsableItem; could be prevented by `preventDefault` called on `expand.collapsable` event
  * @param {Object} collapsableEvent  - Event passed to triggered event
  * @param {Object} data - Data passed to triggered event
  * @param {Boolean} force - Forcing CollapsableItem to expand regardless on onExpand return value, should be used only on initilization (force open default expanded item when collapsableAll === false)
  * @returns {Boolean}     - Returns if CollapsableItem has been expanded or not
  */
 CollapsableItem.prototype.expand = function(collapsableEvent, data, force) {
  var opts = this.parent.opts;
  var expandedItem = this.parent.getExpanded(); // accordion -> max one expanded item
  this.parent.promiseOpen = true; // allows us to collapse expanded item even if there might be collapseAll === false option
  if (opts.accordion) {
   // before expanding, we have to collapse previously opened item, if accordion element hasn't collapsed, we can't continue
   if (expandedItem.length && this.parent.items[expandedItem[0]].collapse(collapsableEvent, data, force) === false) {
    this.parent.promiseOpen = false;
    return false;
   }
  }
  this.parent.promiseOpen = false;
  var event = $.Event('expand.collapsable', { customData: data, collapsableEvent: collapsableEvent });
  this.$collapsable.trigger(event);
  if (event.isDefaultPrevented() && ! force) {
   // collapsableAll === false && accordion === true -> if the box has not opened, we must make sure something is opened, therefore we force-open previously opened box (opts.accordion is true means we tried to collapse something), simulating it has never closed in first place
   if (! opts.collapsableAll && opts.accordion) {
    this.parent.items[expandedItem[0]].expand(collapsableEvent, data, true);
   }
   return false;
  }
  return handleExpandCollapse.call(this, 'expand', collapsableEvent)
 };
 /**
  * Collapses single CollapsableItem; could be prevented by `preventDefault` called on `collapse.collapsable` event
  * @param {Object} collapsableEvent  - Event passed to triggered event
  * @param {Object} data - Data passed to triggered event
  * @param {Boolean} force - Forcing CollapsableItem to collapse regardless on onCollapse return value
  * @returns {Boolean}     - Returns if CollapsableItem has been collapsed or not
  */
 CollapsableItem.prototype.collapse = function(collapsableEvent, data, force) {
  var opts = this.parent.opts;
  // if we can't collapse all, we are not promised to open something and there is only one opened box, then we can't continue
  if (! opts.collapsableAll && ! this.parent.promiseOpen && this.parent.getExpanded().length < 2) {
   return false;
  }
  var event = $.Event('collapse.collapsable', { customData: data, collapsableEvent: collapsableEvent });
  this.$collapsable.trigger(event);
  if (event.isDefaultPrevented() && !force) {
   return false;
  }
  return handleExpandCollapse.call(this, 'collapse', collapsableEvent);
 };

 /**
  * The jQuery plugin namespace.
  * @external "jQuery.fn"
  * @see {@link http://learn.jquery.com/plugins The jQuery Plugin Guide}
  */

 /**
  * jQuery adapter for Collapsable object, returns elements on which it was called, so it's chainable
  * @function external:"jQuery.fn".collapsable
  * @param {Object} options - Options to override plugin defaults
  * @returns {jQuery}
  */
 $.fn.collapsable = function(options) {
  if (methods[options]) {
   return methods[options].apply(this, Array.prototype.slice.call(arguments, 1));
  }
  else if (typeof options === 'object' || !options) {
   methods.init.apply(this, arguments);
   return this;
  }
  else {
   $.error('Method ' + options + ' does not exist on jQuery.collapsable');
  }
 };
 $.fn.collapsable.defaults = defaults;
})(jQuery); 
 

이 질문에 댓글 쓰기 :

답변 1

소스가 길어 다 보지는 못했지만 속도문제는

다음을 수정하면 될 듯 보이네요.

 

var defaults 객체의 

fxDuration: 0 을 1초면 1000 0.5초면 500 등 밀리세컨드로 수정하셔 시도해 보세요. 

답변을 작성하시기 전에 로그인 해주세요.
전체 409
QA 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT