From c427c25ee4f541d3d1a7e6d433cb1a3a5e7416bf Mon Sep 17 00:00:00 2001 From: thisgun Date: Mon, 13 Nov 2017 12:22:03 +0900 Subject: [PATCH 1/4] =?UTF-8?q?=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mobile/skin/member/basic/register.skin.php | 2 +- theme/basic/mobile/skin/member/basic/register.skin.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mobile/skin/member/basic/register.skin.php b/mobile/skin/member/basic/register.skin.php index 05ddf305e..b952cef5f 100644 --- a/mobile/skin/member/basic/register.skin.php +++ b/mobile/skin/member/basic/register.skin.php @@ -66,7 +66,7 @@ add_stylesheet('', -
+
diff --git a/theme/basic/mobile/skin/member/basic/register.skin.php b/theme/basic/mobile/skin/member/basic/register.skin.php index 05ddf305e..b952cef5f 100644 --- a/theme/basic/mobile/skin/member/basic/register.skin.php +++ b/theme/basic/mobile/skin/member/basic/register.skin.php @@ -66,7 +66,7 @@ add_stylesheet('', -
+
From 05fb6f7a68b1f83dfcebc84218dd0d9e1816257b Mon Sep 17 00:00:00 2001 From: thisgun Date: Tue, 14 Nov 2017 11:46:34 +0900 Subject: [PATCH 2/4] =?UTF-8?q?bxslider=20=ED=8C=8C=EC=9D=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/jquery.bxslider.js | 2870 +++++++++++++++++++---------------------- 1 file changed, 1314 insertions(+), 1556 deletions(-) diff --git a/js/jquery.bxslider.js b/js/jquery.bxslider.js index 67ac4d839..915954482 100644 --- a/js/jquery.bxslider.js +++ b/js/jquery.bxslider.js @@ -1,1607 +1,1365 @@ /** - * bxSlider v4.2.12 - * Copyright 2013-2015 Steven Wanderski + * BxSlider v4.1.1 - Fully loaded, responsive content slider + * http://bxslider.com + * + * Copyright 2013, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com * Written while drinking Belgian ales and listening to jazz - * Licensed under MIT (http://opensource.org/licenses/MIT) + * + * Released under the MIT license - http://opensource.org/licenses/MIT */ -;(function($) { +;(function($){ - var defaults = { + var plugin = {}; - // GENERAL - mode: 'horizontal', - slideSelector: '', - infiniteLoop: true, - hideControlOnEnd: false, - speed: 500, - easing: null, - slideMargin: 0, - startSlide: 0, - randomStart: false, - captions: false, - ticker: false, - tickerHover: false, - adaptiveHeight: false, - adaptiveHeightSpeed: 500, - video: false, - useCSS: true, - preloadImages: 'visible', - responsive: true, - slideZIndex: 50, - wrapperClass: 'bx-wrapper', + var defaults = { - // TOUCH - touchEnabled: true, - swipeThreshold: 50, - oneToOneTouch: true, - preventDefaultSwipeX: true, - preventDefaultSwipeY: false, + // GENERAL + mode: 'horizontal', + slideSelector: '', + infiniteLoop: true, + hideControlOnEnd: false, + speed: 500, + easing: null, + slideMargin: 0, + startSlide: 0, + randomStart: false, + captions: false, + ticker: false, + tickerHover: false, + adaptiveHeight: false, + adaptiveHeightSpeed: 50, + video: false, + useCSS: true, + preloadImages: 'visible', + responsive: true, - // ACCESSIBILITY - ariaLive: true, - ariaHidden: true, + // TOUCH + touchEnabled: true, + swipeThreshold: 50, + oneToOneTouch: true, + preventDefaultSwipeX: true, + preventDefaultSwipeY: false, - // KEYBOARD - keyboardEnabled: false, + // PAGER + pager: true, + pagerType: 'full', + pagerShortSeparator: ' / ', + pagerSelector: null, + buildPager: null, + pagerCustom: null, - // PAGER - pager: true, - pagerType: 'full', - pagerShortSeparator: ' / ', - pagerSelector: null, - buildPager: null, - pagerCustom: null, + // CONTROLS + controls: true, + nextText: 'Next', + prevText: 'Prev', + nextSelector: null, + prevSelector: null, + autoControls: false, + startText: 'Start', + stopText: 'Stop', + autoControlsCombine: false, + autoControlsSelector: null, - // CONTROLS - controls: true, - nextText: 'Next', - prevText: 'Prev', - nextSelector: null, - prevSelector: null, - autoControls: false, - startText: 'Start', - stopText: 'Stop', - autoControlsCombine: false, - autoControlsSelector: null, + // AUTO + auto: false, + pause: 4000, + autoStart: true, + autoDirection: 'next', + autoHover: false, + autoDelay: 0, + controlladd: false, - // AUTO - auto: false, - pause: 4000, - autoStart: true, - autoDirection: 'next', - stopAutoOnClick: false, - autoHover: false, - autoDelay: 0, - autoSlideForOnePage: false, + // CAROUSEL + minSlides: 1, + maxSlides: 1, + moveSlides: 0, + slideWidth: 0, - // CAROUSEL - minSlides: 1, - maxSlides: 1, - moveSlides: 0, - slideWidth: 0, - shrinkItems: false, + SUPPORTS_TOUCH : 'ontouchstart' in window, - // CALLBACKS - onSliderLoad: function() { return true; }, - onSlideBefore: function() { return true; }, - onSlideAfter: function() { return true; }, - onSlideNext: function() { return true; }, - onSlidePrev: function() { return true; }, - onSliderResize: function() { return true; } - }; + // CALLBACKS + onSliderLoad: function() {}, + onSlideBefore: function() {}, + onSlideAfter: function() {}, + onSlideNext: function() {}, + onSlidePrev: function() {}, - $.fn.bxSlider = function(options) { + //ADD + interval_arr: [] + } - if (this.length === 0) { - return this; - } + $.fn.bxSlider = function(options){ - // support multiple elements - if (this.length > 1) { - this.each(function() { - $(this).bxSlider(options); - }); - return this; - } + if(this.length == 0) return this; - // create a namespace to be used throughout the plugin - var slider = {}, - // set a reference to our slider element - el = this, - // get the original window dimens (thanks a lot IE) - windowWidth = $(window).width(), - windowHeight = $(window).height(); + // support mutltiple elements + if(this.length > 1){ + this.each(function(){$(this).bxSlider(options)}); + return this; + } - // Return if slider is already initialized - if ($(el).data('bxSlider')) { return; } + // create a namespace to be used throughout the plugin + var slider = {}; + // set a reference to our slider element + var el = this; + plugin.el = this; - /** - * =================================================================================== - * = PRIVATE FUNCTIONS - * =================================================================================== - */ + /** + * Makes slideshow responsive + */ + // first get the original window dimens (thanks alot IE) + var windowWidth = $(window).width(); + var windowHeight = $(window).height(); - /** - * Initializes namespace settings to be used throughout plugin - */ - var init = function() { - // Return if slider is already initialized - if ($(el).data('bxSlider')) { return; } - // merge user-supplied options with the defaults - slider.settings = $.extend({}, defaults, options); - // parse slideWidth setting - slider.settings.slideWidth = parseInt(slider.settings.slideWidth); - // store the original children - slider.children = el.children(slider.settings.slideSelector); - // check if actual number of slides is less than minSlides / maxSlides - if (slider.children.length < slider.settings.minSlides) { slider.settings.minSlides = slider.children.length; } - if (slider.children.length < slider.settings.maxSlides) { slider.settings.maxSlides = slider.children.length; } - // if random start, set the startSlide setting to random number - if (slider.settings.randomStart) { slider.settings.startSlide = Math.floor(Math.random() * slider.children.length); } - // store active slide information - slider.active = { index: slider.settings.startSlide }; - // store if the slider is in carousel mode (displaying / moving multiple slides) - slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1 ? true : false; - // if carousel, force preloadImages = 'all' - if (slider.carousel) { slider.settings.preloadImages = 'all'; } - // calculate the min / max width thresholds based on min / max number of slides - // used to setup and update carousel slides dimensions - slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin); - slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); - // store the current state of the slider (if currently animating, working is true) - slider.working = false; - // initialize the controls object - slider.controls = {}; - // initialize an auto interval - slider.interval = null; - // determine which property to use for transitions - slider.animProp = slider.settings.mode === 'vertical' ? 'top' : 'left'; - // determine if hardware acceleration can be used - slider.usingCSS = slider.settings.useCSS && slider.settings.mode !== 'fade' && (function() { - // create our test div element - var div = document.createElement('div'), - // css transition properties - props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']; - // test for each property - for (var i = 0; i < props.length; i++) { - if (div.style[props[i]] !== undefined) { - slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase(); - slider.animProp = '-' + slider.cssPrefix + '-transform'; - return true; - } - } - return false; - }()); - // if vertical mode always make maxSlides and minSlides equal - if (slider.settings.mode === 'vertical') { slider.settings.maxSlides = slider.settings.minSlides; } - // save original style data - el.data('origStyle', el.attr('style')); - el.children(slider.settings.slideSelector).each(function() { - $(this).data('origStyle', $(this).attr('style')); - }); - // perform all DOM / CSS modifications - setup(); - }; - /** - * Performs all DOM and CSS modifications - */ - var setup = function() { - var preloadSelector = slider.children.eq(slider.settings.startSlide); // set the default preload selector (visible) + /** + * =================================================================================== + * = PRIVATE FUNCTIONS + * =================================================================================== + */ - // wrap el in a wrapper - el.wrap('
'); - // store a namespace reference to .bx-viewport - slider.viewport = el.parent(); + /** + * Initializes namespace settings to be used throughout plugin + */ + var init = function(){ + // merge user-supplied options with the defaults + slider.settings = $.extend({}, defaults, options); + // parse slideWidth setting + slider.settings.slideWidth = parseInt(slider.settings.slideWidth); + // store the original children + slider.children = el.children(slider.settings.slideSelector); + // check if actual number of slides is less than minSlides / maxSlides + if(slider.children.length < slider.settings.minSlides) slider.settings.minSlides = slider.children.length; + if(slider.children.length < slider.settings.maxSlides) slider.settings.maxSlides = slider.children.length; + // if random start, set the startSlide setting to random number + if(slider.settings.randomStart) slider.settings.startSlide = Math.floor(Math.random() * slider.children.length); + // store active slide information + slider.active = { index: slider.settings.startSlide } + // store if the slider is in carousel mode (displaying / moving multiple slides) + slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1; + // if carousel, force preloadImages = 'all' + if(slider.carousel) slider.settings.preloadImages = 'all'; + // calculate the min / max width thresholds based on min / max number of slides + // used to setup and update carousel slides dimensions + slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin); + slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); + // store the current state of the slider (if currently animating, working is true) + slider.working = false; + // initialize the controls object + slider.controls = {}; + // initialize an auto interval + slider.interval = null; + // determine which property to use for transitions + slider.animProp = slider.settings.mode == 'vertical' ? 'top' : 'left'; + // determine if hardware acceleration can be used + slider.usingCSS = slider.settings.useCSS && slider.settings.mode != 'fade' && (function(){ + // create our test div element + var div = document.createElement('div'); + // css transition properties + var props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']; + // test for each property + for(var i in props){ + if(div.style[props[i]] !== undefined){ + slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase(); + slider.animProp = '-' + slider.cssPrefix + '-transform'; + return true; + } + } + return false; + }()); + var useTouchEvents = slider.settings.SUPPORTS_TOUCH; + slider.START_EV = useTouchEvents ? 'touchstart' : 'mousedown', + slider.MOVE_EV = useTouchEvents ? 'touchmove' : 'mousemove', + slider.END_EV = useTouchEvents ? 'touchend' : 'mouseup', + slider.LEAVE_EV = useTouchEvents ? null : 'mouseleave', //we manually detect leave on touch devices, so null event here + slider.CANCEL_EV = 'touchcancel'; - // add aria-live if the setting is enabled and ticker mode is disabled - if (slider.settings.ariaLive && !slider.settings.ticker) { - slider.viewport.attr('aria-live', 'polite'); - } - // add a loading div to display while images are loading - slider.loader = $('
'); - slider.viewport.prepend(slider.loader); - // set el to a massive width, to hold any needed slides - // also strip any margin and padding from el - el.css({ - width: slider.settings.mode === 'horizontal' ? (slider.children.length * 1000 + 215) + '%' : 'auto', - position: 'relative' - }); - // if using CSS, add the easing property - if (slider.usingCSS && slider.settings.easing) { - el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing); - // if not using CSS and no easing value was supplied, use the default JS animation easing (swing) - } else if (!slider.settings.easing) { - slider.settings.easing = 'swing'; - } - // make modifications to the viewport (.bx-viewport) - slider.viewport.css({ - width: '100%', - overflow: 'hidden', - position: 'relative' - }); - slider.viewport.parent().css({ - maxWidth: getViewportMaxWidth() - }); - // apply css to all slider children - slider.children.css({ - float: slider.settings.mode === 'horizontal' ? 'left' : 'none', - listStyle: 'none', - position: 'relative' - }); - // apply the calculated width after the float is applied to prevent scrollbar interference - slider.children.css('width', getSlideWidth()); - // if slideMargin is supplied, add the css - if (slider.settings.mode === 'horizontal' && slider.settings.slideMargin > 0) { slider.children.css('marginRight', slider.settings.slideMargin); } - if (slider.settings.mode === 'vertical' && slider.settings.slideMargin > 0) { slider.children.css('marginBottom', slider.settings.slideMargin); } - // if "fade" mode, add positioning and z-index CSS - if (slider.settings.mode === 'fade') { - slider.children.css({ - position: 'absolute', - zIndex: 0, - display: 'none' - }); - // prepare the z-index on the showing element - slider.children.eq(slider.settings.startSlide).css({zIndex: slider.settings.slideZIndex, display: 'block'}); - } - // create an element to contain all slider controls (pager, start / stop, etc) - slider.controls.el = $('
'); - // if captions are requested, add them - if (slider.settings.captions) { appendCaptions(); } - // check if startSlide is last slide - slider.active.last = slider.settings.startSlide === getPagerQty() - 1; - // if video is true, set up the fitVids plugin - if (slider.settings.video) { el.fitVids(); } - if (slider.settings.preloadImages === 'all' || slider.settings.ticker) { preloadSelector = slider.children; } - // only check for control addition if not in "ticker" mode - if (!slider.settings.ticker) { - // if controls are requested, add them - if (slider.settings.controls) { appendControls(); } - // if auto is true, and auto controls are requested, add them - if (slider.settings.auto && slider.settings.autoControls) { appendControlsAuto(); } - // if pager is requested, add it - if (slider.settings.pager) { appendPager(); } - // if any control option is requested, add the controls wrapper - if (slider.settings.controls || slider.settings.autoControls || slider.settings.pager) { slider.viewport.after(slider.controls.el); } - // if ticker mode, do not allow a pager - } else { - slider.settings.pager = false; - } - loadElements(preloadSelector, start); - }; + // if vertical mode always make maxSlides and minSlides equal + if(slider.settings.mode == 'vertical') slider.settings.maxSlides = slider.settings.minSlides; + // save original style data + el.data("origStyle", el.attr("style")); + el.children(slider.settings.slideSelector).each(function() { + $(this).data("origStyle", $(this).attr("style")); + }); + el.pause = slider.settings.pause; + // perform all DOM / CSS modifications + setup(); + } - var loadElements = function(selector, callback) { - var total = selector.find('img:not([src=""]), iframe').length, - count = 0; - if (total === 0) { - callback(); - return; - } - selector.find('img:not([src=""]), iframe').each(function() { - $(this).one('load error', function() { - if (++count === total) { callback(); } - }).each(function() { - if (this.complete) { $(this).trigger('load'); } - }); - }); - }; + /** + * Performs all DOM and CSS modifications + */ + var setup = function(){ + // wrap el in a wrapper + el.wrap('
'); + // store a namspace reference to .bx-viewport + slider.viewport = el.parent(); + // add a loading div to display while images are loading + slider.loader = $('
'); + slider.viewport.prepend(slider.loader); + // set el to a massive width, to hold any needed slides + // also strip any margin and padding from el + el.css({ + width: slider.settings.mode == 'horizontal' ? (slider.children.length * 100 + 215) + '%' : 'auto', + position: 'relative' + }); + el.state = slider.settings.auto ? 'start' : 'stop'; + // if using CSS, add the easing property + if(slider.usingCSS && slider.settings.easing){ + el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing); + // if not using CSS and no easing value was supplied, use the default JS animation easing (swing) + }else if(!slider.settings.easing){ + slider.settings.easing = 'swing'; + } + var slidesShowing = getNumberSlidesShowing(); + // make modifications to the viewport (.bx-viewport) + slider.viewport.css({ + width: '100%', + overflow: 'hidden', + position: 'relative' + }); + slider.viewport.parent().css({ + maxWidth: getViewportMaxWidth() + }); + // make modification to the wrapper (.bx-wrapper) + if(!slider.settings.pager) { + slider.viewport.parent().css({ + margin: '0 auto 0px' + }); + } + // apply css to all slider children + slider.children.css({ + 'float': slider.settings.mode == 'horizontal' ? 'left' : 'none', + listStyle: 'none', + position: 'relative' + }); + // apply the calculated width after the float is applied to prevent scrollbar interference + slider.children.css('width', getSlideWidth()); + // if slideMargin is supplied, add the css + if(slider.settings.mode == 'horizontal' && slider.settings.slideMargin > 0) slider.children.css('marginRight', slider.settings.slideMargin); + if(slider.settings.mode == 'vertical' && slider.settings.slideMargin > 0) slider.children.css('marginBottom', slider.settings.slideMargin); + // if "fade" mode, add positioning and z-index CSS + if(slider.settings.mode == 'fade'){ + slider.children.css({ + position: 'absolute', + zIndex: 0, + display: 'none' + }); + // prepare the z-index on the showing element + slider.children.eq(slider.settings.startSlide).css({zIndex: 50, display: 'block'}); + } + // create an element to contain all slider controls (pager, start / stop, etc) + slider.controls.el = $('
'); + // if captions are requested, add them + if(slider.settings.captions) appendCaptions(); + // check if startSlide is last slide + slider.active.last = slider.settings.startSlide == getPagerQty() - 1; + // if video is true, set up the fitVids plugin + if(slider.settings.video) el.fitVids(); + // set the default preload selector (visible) + var preloadSelector = slider.children.eq(slider.settings.startSlide); + if (slider.settings.preloadImages == "all") preloadSelector = slider.children; + // only check for control addition if not in "ticker" mode + if(!slider.settings.ticker){ + // if pager is requested, add it + if(slider.settings.pager) appendPager(); + // if controls are requested, add them + if(slider.settings.controls) appendControls(); + // if auto is true, and auto controls are requested, add them + if(slider.settings.auto && slider.settings.autoControls) appendControlsAuto(); + // if any control option is requested, add the controls wrapper + if(slider.settings.controls || slider.settings.autoControls || slider.settings.pager) slider.viewport.after(slider.controls.el); + // if ticker mode, do not allow a pager + }else{ + slider.settings.pager = false; + } + // preload all images, then perform final DOM / CSS modifications that depend on images being loaded + loadElements(preloadSelector, start); + } - /** - * Start the slider - */ - var start = function() { - // if infinite loop, prepare additional slides - if (slider.settings.infiniteLoop && slider.settings.mode !== 'fade' && !slider.settings.ticker) { - var slice = slider.settings.mode === 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides, - sliceAppend = slider.children.slice(0, slice).clone(true).addClass('bx-clone'), - slicePrepend = slider.children.slice(-slice).clone(true).addClass('bx-clone'); - if (slider.settings.ariaHidden) { - sliceAppend.attr('aria-hidden', true); - slicePrepend.attr('aria-hidden', true); - } - el.append(sliceAppend).prepend(slicePrepend); - } - // remove the loading DOM element - slider.loader.remove(); - // set the left / top position of "el" - setSlidePosition(); - // if "vertical" mode, always use adaptiveHeight to prevent odd behavior - if (slider.settings.mode === 'vertical') { slider.settings.adaptiveHeight = true; } - // set the viewport height - slider.viewport.height(getViewportHeight()); - // make sure everything is positioned just right (same as a window resize) - el.redrawSlider(); - // onSliderLoad callback - slider.settings.onSliderLoad.call(el, slider.active.index); - // slider has been fully initialized - slider.initialized = true; - // bind the resize call to the window - if (slider.settings.responsive) { $(window).bind('resize', resizeWindow); } - // if auto is true and has more than 1 page, start the show - if (slider.settings.auto && slider.settings.autoStart && (getPagerQty() > 1 || slider.settings.autoSlideForOnePage)) { initAuto(); } - // if ticker is true, start the ticker - if (slider.settings.ticker) { initTicker(); } - // if pager is requested, make the appropriate pager link active - if (slider.settings.pager) { updatePagerActive(slider.settings.startSlide); } - // check for any updates to the controls (like hideControlOnEnd updates) - if (slider.settings.controls) { updateDirectionControls(); } - // if touchEnabled is true, setup the touch events - if (slider.settings.touchEnabled && !slider.settings.ticker) { initTouch(); } - // if keyboardEnabled is true, setup the keyboard events - if (slider.settings.keyboardEnabled && !slider.settings.ticker) { - $(document).keydown(keyPress); - } - }; + var loadElements = function(selector, callback){ + var total = selector.find('img, iframe').length; + if (total == 0){ + callback(); + return; + } + var count = 0; + selector.find('img, iframe').each(function(){ + $(this).one('load', function() { + if(++count == total) callback(); + }).each(function() { + if(this.complete) $(this).load(); + }); + }); + } - /** - * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value - */ - var getViewportHeight = function() { - var height = 0; - // first determine which children (slides) should be used in our height calculation - var children = $(); - // if mode is not "vertical" and adaptiveHeight is false, include all children - if (slider.settings.mode !== 'vertical' && !slider.settings.adaptiveHeight) { - children = slider.children; - } else { - // if not carousel, return the single active child - if (!slider.carousel) { - children = slider.children.eq(slider.active.index); - // if carousel, return a slice of children - } else { - // get the individual slide index - var currentIndex = slider.settings.moveSlides === 1 ? slider.active.index : slider.active.index * getMoveBy(); - // add the current slide to the children - children = slider.children.eq(currentIndex); - // cycle through the remaining "showing" slides - for (i = 1; i <= slider.settings.maxSlides - 1; i++) { - // if looped back to the start - if (currentIndex + i >= slider.children.length) { - children = children.add(slider.children.eq(i - 1)); - } else { - children = children.add(slider.children.eq(currentIndex + i)); + /** + * Start the slider + */ + var start = function(){ + // if infinite loop, prepare additional slides + if(slider.settings.infiniteLoop && slider.settings.mode != 'fade' && !slider.settings.ticker){ + var slice = slider.settings.mode == 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides; + var sliceAppend = slider.children.slice(0, slice).clone().addClass('bx-clone'); + var slicePrepend = slider.children.slice(-slice).clone().addClass('bx-clone'); + el.append(sliceAppend).prepend(slicePrepend); + } + // remove the loading DOM element + slider.loader.remove(); + // set the left / top position of "el" + setSlidePosition(); + // if "vertical" mode, always use adaptiveHeight to prevent odd behavior + if (slider.settings.mode == 'vertical') slider.settings.adaptiveHeight = true; + // set the viewport height + slider.viewport.height(getViewportHeight()); + // make sure everything is positioned just right (same as a window resize) + el.redrawSlider(); + // onSliderLoad callback + slider.settings.onSliderLoad(slider.active.index); + // slider has been fully initialized + slider.initialized = true; + // bind the resize call to the window + if (slider.settings.responsive) $(window).bind('resize', resizeWindow); + // if auto is true, start the show + if (slider.settings.auto && slider.settings.autoStart) initAuto(); + // if ticker is true, start the ticker + if (slider.settings.ticker) initTicker(); + // if pager is requested, make the appropriate pager link active + if (slider.settings.pager) updatePagerActive(slider.settings.startSlide); + // check for any updates to the controls (like hideControlOnEnd updates) + if (slider.settings.controls) updateDirectionControls(); + // if touchEnabled is true, setup the touch events + if (slider.settings.touchEnabled && !slider.settings.ticker) initTouch(); + } + + /** + * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value + */ + var getViewportHeight = function(){ + var height = 0; + // first determine which children (slides) should be used in our height calculation + var children = $(); + // if mode is not "vertical" and adaptiveHeight is false, include all children + if(slider.settings.mode != 'vertical' && !slider.settings.adaptiveHeight){ + children = slider.children; + }else{ + // if not carousel, return the single active child + if(!slider.carousel){ + children = slider.children.eq(slider.active.index); + // if carousel, return a slice of children + }else{ + // get the individual slide index + var currentIndex = slider.settings.moveSlides == 1 ? slider.active.index : slider.active.index * getMoveBy(); + // add the current slide to the children + children = slider.children.eq(currentIndex); + // cycle through the remaining "showing" slides + for (i = 1; i <= slider.settings.maxSlides - 1; i++){ + // if looped back to the start + if(currentIndex + i >= slider.children.length){ + children = children.add(slider.children.eq(i - 1)); + }else{ + children = children.add(slider.children.eq(currentIndex + i)); + } + } + } + } + // if "vertical" mode, calculate the sum of the heights of the children + if(slider.settings.mode == 'vertical'){ + children.each(function(index) { + height += $(this).outerHeight(); + }); + // add user-supplied margins + if(slider.settings.slideMargin > 0){ + height += slider.settings.slideMargin * (slider.settings.minSlides - 1); + } + // if not "vertical" mode, calculate the max height of the children + }else{ + height = Math.max.apply(Math, children.map(function(){ + return $(this).outerHeight(false); + }).get()); + } + return height; + } + + /** + * Returns the calculated width to be used for the outer wrapper / viewport + */ + var getViewportMaxWidth = function(){ + var width = '100%'; + if(slider.settings.slideWidth > 0){ + if(slider.settings.mode == 'horizontal'){ + width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); + }else{ + width = slider.settings.slideWidth; + } + } + return width; + } + + /** + * Returns the calculated width to be applied to each slide + */ + var getSlideWidth = function(){ + // start with any user-supplied slide width + var newElWidth = slider.settings.slideWidth; + // get the current viewport width + var wrapWidth = slider.viewport.width(); + // if slide width was not supplied, or is larger than the viewport use the viewport width + if(slider.settings.slideWidth == 0 || + (slider.settings.slideWidth > wrapWidth && !slider.carousel) || + slider.settings.mode == 'vertical'){ + newElWidth = wrapWidth; + // if carousel, use the thresholds to determine the width + }else if(slider.settings.maxSlides > 1 && slider.settings.mode == 'horizontal'){ + if(wrapWidth > slider.maxThreshold){ + // newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.maxSlides - 1))) / slider.settings.maxSlides; + }else if(wrapWidth < slider.minThreshold){ + newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides; + } + } + return newElWidth; + } + + /** + * Returns the number of slides currently visible in the viewport (includes partially visible slides) + */ + var getNumberSlidesShowing = function(){ + var slidesShowing = 1; + if(slider.settings.mode == 'horizontal' && slider.settings.slideWidth > 0){ + // if viewport is smaller than minThreshold, return minSlides + if(slider.viewport.width() < slider.minThreshold){ + slidesShowing = slider.settings.minSlides; + // if viewport is larger than minThreshold, return maxSlides + }else if(slider.viewport.width() > slider.maxThreshold){ + slidesShowing = slider.settings.maxSlides; + // if viewport is between min / max thresholds, divide viewport width by first child width + }else{ + var childWidth = slider.children.first().width(); + slidesShowing = Math.floor(slider.viewport.width() / childWidth); + } + // if "vertical" mode, slides showing will always be minSlides + }else if(slider.settings.mode == 'vertical'){ + slidesShowing = slider.settings.minSlides; + } + return slidesShowing; + } + + /** + * Returns the number of pages (one full viewport of slides is one "page") + */ + var getPagerQty = function(){ + var pagerQty = 0; + // if moveSlides is specified by the user + if(slider.settings.moveSlides > 0){ + if(slider.settings.infiniteLoop){ + pagerQty = slider.children.length / getMoveBy(); + }else{ + // use a while loop to determine pages + var breakPoint = 0; + var counter = 0 + // when breakpoint goes above children length, counter is the number of pages + while (breakPoint < slider.children.length){ + ++pagerQty; + breakPoint = counter + getNumberSlidesShowing(); + counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing(); + } + } + // if moveSlides is 0 (auto) divide children length by sides showing, then round up + }else{ + pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing()); + } + return pagerQty; + } + + /** + * Returns the number of indivual slides by which to shift the slider + */ + var getMoveBy = function(){ + // if moveSlides was set by the user and moveSlides is less than number of slides showing + if(slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()){ + return slider.settings.moveSlides; + } + // if moveSlides is 0 (auto) + return getNumberSlidesShowing(); + } + + /** + * Sets the slider's (el) left or top position + */ + var setSlidePosition = function(){ + // if last slide, not infinite loop, and number of children is larger than specified maxSlides + if(slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop){ + if (slider.settings.mode == 'horizontal'){ + // get the last child's position + var lastChild = slider.children.last(); + var position = lastChild.position(); + // set the left position + setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.width())), 'reset', 0); + }else if(slider.settings.mode == 'vertical'){ + // get the last showing index's position + var lastShowingIndex = slider.children.length - slider.settings.minSlides; + var position = slider.children.eq(lastShowingIndex).position(); + // set the top position + setPositionProperty(-position.top, 'reset', 0); + } + // if not last slide + }else{ + // get the position of the first showing slide + var position = slider.children.eq(slider.active.index * getMoveBy()).position(); + // check for last slide + if (slider.active.index == getPagerQty() - 1) slider.active.last = true; + // set the repective position + if (position != undefined){ + if (slider.settings.mode == 'horizontal') setPositionProperty(-position.left, 'reset', 0); + else if (slider.settings.mode == 'vertical') setPositionProperty(-position.top, 'reset', 0); + } + } + } + + /** + * Sets the el's animating property position (which in turn will sometimes animate el). + * If using CSS, sets the transform property. If not using CSS, sets the top / left property. + * + * @param value (int) + * - the animating property's value + * + * @param type (string) 'slider', 'reset', 'ticker' + * - the type of instance for which the function is being + * + * @param duration (int) + * - the amount of time (in ms) the transition should occupy + * + * @param params (array) optional + * - an optional parameter containing any variables that need to be passed in + */ + var setPositionProperty = function(value, type, duration, params){ + // use CSS transform + if(slider.usingCSS){ + // determine the translate3d value + var propValue = slider.settings.mode == 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)'; + // add the CSS transition-duration + el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's'); + if(type == 'slide'){ + // set the property value + el.css(slider.animProp, propValue); + // bind a callback method - executes when CSS transition completes + el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){ + // unbind the callback + el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); + updateAfterSlideTransition(); + }); + }else if(type == 'reset'){ + el.css(slider.animProp, propValue); + }else if(type == 'ticker'){ + // make the transition use 'linear' + el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear'); + el.css(slider.animProp, propValue); + // bind a callback method - executes when CSS transition completes + el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){ + // unbind the callback + el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); + // reset the position + setPositionProperty(params['resetValue'], 'reset', 0); + // start the loop again + tickerLoop(); + }); + } + // use JS animate + }else{ + var animateObj = {}; + animateObj[slider.animProp] = value; + if(type == 'slide'){ + el.animate(animateObj, duration, slider.settings.easing, function(){ + updateAfterSlideTransition(); + }); + }else if(type == 'reset'){ + el.css(slider.animProp, value) + }else if(type == 'ticker'){ + el.animate(animateObj, speed, 'linear', function(){ + setPositionProperty(params['resetValue'], 'reset', 0); + // run the recursive loop after animation + tickerLoop(); + }); + } + } + } + + /** + * Populates the pager with proper amount of pages + */ + var populatePager = function(){ + var pagerHtml = ''; + var pagerQty = getPagerQty(); + // loop through each pager item + for(var i=0; i < pagerQty; i++){ + var linkContent = ''; + // if a buildPager function is supplied, use it to get pager link value, else use index + 1 + if(slider.settings.buildPager && $.isFunction(slider.settings.buildPager)){ + linkContent = slider.settings.buildPager(i); + slider.pagerEl.addClass('bx-custom-pager'); + }else{ + linkContent = i + 1; + slider.pagerEl.addClass('bx-default-pager'); + } + // var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1; + // add the markup to the string + pagerHtml += ''; + }; + // populate the pager element with pager links + slider.pagerEl.html(pagerHtml); + } + + /** + * Appends the pager to the controls element + */ + var appendPager = function(){ + if(!slider.settings.pagerCustom){ + // create the pager DOM element + slider.pagerEl = $('
'); + // if a pager selector was supplied, populate it with the pager + if(slider.settings.pagerSelector){ + $(slider.settings.pagerSelector).html(slider.pagerEl); + // if no pager selector was supplied, add it after the wrapper + }else{ + slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl); + } + // populate the pager + populatePager(); + }else{ + slider.pagerEl = $(slider.settings.pagerCustom); + } + // assign the pager click binding + slider.pagerEl.on('click', 'a', clickPagerBind); + } + + /** + * Appends prev / next controls to the controls element + */ + var appendControls = function(){ + slider.controls.next = $('' + slider.settings.nextText + ''); + slider.controls.prev = $('' + slider.settings.prevText + ''); + // bind click actions to the controls + slider.controls.next.bind('click', clickNextBind); + slider.controls.prev.bind('click', clickPrevBind); + // if nextSlector was supplied, populate it + if(slider.settings.nextSelector){ + $(slider.settings.nextSelector).append(slider.controls.next); + } + // if prevSlector was supplied, populate it + if(slider.settings.prevSelector){ + $(slider.settings.prevSelector).append(slider.controls.prev); + } + // if no custom selectors were supplied + if(!slider.settings.nextSelector && !slider.settings.prevSelector){ + // add the controls to the DOM + slider.controls.directionEl = $('
'); + // add the control elements to the directionEl + slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next); + // slider.viewport.append(slider.controls.directionEl); + slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl); + } + } + + /** + * Appends start / stop auto controls to the controls element + */ + var appendControlsAuto = function(){ + slider.controls.start = $(''); + slider.controls.stop = $(''); + // add the controls to the DOM + slider.controls.autoEl = $('
'); + // bind click actions to the controls + slider.controls.autoEl.delegate('.bx-start', 'click', clickStartBind); + slider.controls.autoEl.delegate('.bx-stop', 'click', clickStopBind); + // if autoControlsCombine, insert only the "start" control + if(slider.settings.autoControlsCombine){ + slider.controls.autoEl.append(slider.controls.start); + // if autoControlsCombine is false, insert both controls + }else{ + slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop); + } + // if auto controls selector was supplied, populate it with the controls + if(slider.settings.autoControlsSelector){ + $(slider.settings.autoControlsSelector).html(slider.controls.autoEl); + // if auto controls selector was not supplied, add it after the wrapper + }else{ + slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl); + } + + // update the auto controls + updateAutoControls(slider.settings.autoStart ? 'stop' : 'start'); + } + + /** + * Appends image captions to the DOM + */ + var appendCaptions = function(){ + // cycle through each child + slider.children.each(function(index){ + // get the image title attribute + var title = $(this).find('img:first').attr('title'); + // append the caption + if (title != undefined && ('' + title).length) { + $(this).append('
' + title + '
'); + } + }); + } + + /** + * Click next binding + * + * @param e (event) + * - DOM event object + */ + var clickNextBind = function(e){ + // if auto show is running, stop it + if (slider.settings.auto) el.stopAuto(); + el.goToNextSlide(); + e.preventDefault(); + } + + /** + * Click prev binding + * + * @param e (event) + * - DOM event object + */ + var clickPrevBind = function(e){ + // if auto show is running, stop it + if (slider.settings.auto) el.stopAuto(); + el.goToPrevSlide(); + e.preventDefault(); + } + + /** + * Click start binding + * + * @param e (event) + * - DOM event object + */ + var clickStartBind = function(e){ + el.startAuto(); + e.preventDefault(); + } + + /** + * Click stop binding + * + * @param e (event) + * - DOM event object + */ + var clickStopBind = function(e){ + el.stopAuto(); + e.preventDefault(); + } + + /** + * Click pager binding + * + * @param e (event) + * - DOM event object + */ + var clickPagerBind = function(e){ + // if auto show is running, stop it + if (slider.settings.auto) el.stopAuto(); + var pagerLink = $(e.currentTarget); + if(pagerLink.attr('data-slide-index') !== undefined){ + var pagerIndex = parseInt(pagerLink.attr('data-slide-index')); + // if clicked pager link is not active, continue with the goToSlide call + if(pagerIndex != slider.active.index) el.goToSlide(pagerIndex); + e.preventDefault(); + } + } + + /** + * Updates the pager links with an active class + * + * @param slideIndex (int) + * - index of slide to make active + */ + var updatePagerActive = function(slideIndex){ + // if "short" pager type + var len = slider.children.length; // nb of children + if(slider.settings.pagerType == 'short'){ + if(slider.settings.maxSlides > 1) { + len = Math.ceil(slider.children.length/slider.settings.maxSlides); + } + slider.pagerEl.html( (slideIndex + 1) + slider.settings.pagerShortSeparator + len); + return; + } + // remove all pager active classes + slider.pagerEl.find('a').removeClass('active'); + // apply the active class for all pagers + slider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); }); + } + + /** + * Performs needed actions after a slide transition + */ + var updateAfterSlideTransition = function(){ + // if infinte loop is true + if(slider.settings.infiniteLoop){ + var position = ''; + // first slide + if(slider.active.index == 0){ + // set the new position + position = slider.children.eq(0).position(); + // carousel, last slide + }else if(slider.active.index == getPagerQty() - 1 && slider.carousel){ + position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position(); + // last slide + }else if(slider.active.index == slider.children.length - 1){ + position = slider.children.eq(slider.children.length - 1).position(); + } + if (slider.settings.mode == 'horizontal') { setPositionProperty(-position.left, 'reset', 0);; } + else if (slider.settings.mode == 'vertical') { setPositionProperty(-position.top, 'reset', 0);; } + } + // declare that the transition is complete + slider.working = false; + // onSlideAfter callback + slider.settings.onSlideAfter(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); + } + + /** + * Updates the auto controls state (either active, or combined switch) + * + * @param state (string) "start", "stop" + * - the new state of the auto show + */ + var updateAutoControls = function(state){ + + el.trigger("updateautocontrols", state); + + // if autoControlsCombine is true, replace the current control with the new state + if(slider.settings.autoControlsCombine){ + slider.controls.autoEl.html(slider.controls[state]); + // if autoControlsCombine is false, apply the "active" class to the appropriate control + }else{ + slider.controls.autoEl.find('a').removeClass('active'); + slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active'); + } + } + + /** + * Updates the direction controls (checks if either should be hidden) + */ + var updateDirectionControls = function(){ + if(getPagerQty() == 1){ + slider.controls.prev.addClass('disabled'); + slider.controls.next.addClass('disabled'); + }else if(!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd){ + // if first slide + if (slider.active.index == 0){ + slider.controls.prev.addClass('disabled'); + slider.controls.next.removeClass('disabled'); + // if last slide + }else if(slider.active.index == getPagerQty() - 1){ + slider.controls.next.addClass('disabled'); + slider.controls.prev.removeClass('disabled'); + // if any slide in the middle + }else{ + slider.controls.prev.removeClass('disabled'); + slider.controls.next.removeClass('disabled'); + } + } + } + + /** + * Initialzes the auto process + */ + var initAuto = function(){ + // if autoDelay was supplied, launch the auto show using a setTimeout() call + if(slider.settings.autoDelay > 0){ + var timeout = setTimeout(el.startAuto, slider.settings.autoDelay); + // if autoDelay was not supplied, start the auto show normally + }else{ + el.startAuto(); + } + // if autoHover is requested + if(slider.settings.autoHover){ + // on el hover + el.hover(function(){ + // if the auto show is currently playing (has an active interval) + if(slider.interval){ + // stop the auto show and pass true agument which will prevent control update + el.stopAuto(true); + // create a new autoPaused value which will be used by the relative "mouseout" event + slider.autoPaused = true; + } + }, function(){ + // if the autoPaused value was created be the prior "mouseover" event + if(slider.autoPaused){ + // start the auto show and pass true agument which will prevent control update + el.startAuto(true); + // reset the autoPaused value + slider.autoPaused = null; + } + }); + } + } + + /** + * Initialzes the ticker process + */ + var initTicker = function(){ + var startPosition = 0; + // if autoDirection is "next", append a clone of the entire slider + if(slider.settings.autoDirection == 'next'){ + el.append(slider.children.clone().addClass('bx-clone')); + // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position + }else{ + el.prepend(slider.children.clone().addClass('bx-clone')); + var position = slider.children.first().position(); + startPosition = slider.settings.mode == 'horizontal' ? -position.left : -position.top; + } + setPositionProperty(startPosition, 'reset', 0); + // do not allow controls in ticker mode + slider.settings.pager = false; + slider.settings.controls = false; + slider.settings.autoControls = false; + // if autoHover is requested + if(slider.settings.tickerHover && !slider.usingCSS){ + // on el hover + slider.viewport.hover(function(){ + el.stop(); + }, function(){ + // calculate the total width of children (used to calculate the speed ratio) + var totalDimens = 0; + slider.children.each(function(index){ + totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); + }); + // calculate the speed ratio (used to determine the new speed to finish the paused animation) + var ratio = slider.settings.speed / totalDimens; + // determine which property to use + var property = slider.settings.mode == 'horizontal' ? 'left' : 'top'; + // calculate the new speed + var newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property))))); + tickerLoop(newSpeed); + }); + } + // start the ticker loop + tickerLoop(); + } + + /** + * Runs a continuous loop, news ticker-style + */ + var tickerLoop = function(resumeSpeed){ + speed = resumeSpeed ? resumeSpeed : slider.settings.speed; + var position = {left: 0, top: 0}; + var reset = {left: 0, top: 0}; + // if "next" animate left position to last child, then reset left to 0 + if(slider.settings.autoDirection == 'next'){ + position = el.find('.bx-clone').first().position(); + // if "prev" animate left position to 0, then reset left to first non-clone child + }else{ + reset = slider.children.first().position(); + } + var animateProperty = slider.settings.mode == 'horizontal' ? -position.left : -position.top; + var resetValue = slider.settings.mode == 'horizontal' ? -reset.left : -reset.top; + var params = {resetValue: resetValue}; + setPositionProperty(animateProperty, 'ticker', speed, params); + } + + /** + * Initializes touch events + */ + var initTouch = function(){ + // initialize object to contain all touch values + slider.touch = { + start: {x: 0, y: 0}, + end: {x: 0, y: 0} + } + slider.viewport.bind(slider.START_EV, onTouchStart); + slider.children.bind('click', onClick_check); + } + + var isScrolling; + /** + * Event handler for "touchstart" + * + * @param e (event) + * - DOM event object + */ + var onTouchStart = function(e){ + // used for testing first move event + isScrolling = undefined; + if(slider.working){ + e.preventDefault(); + }else{ + // record the original position when touch starts + slider.touch.originalPos = el.position(); + var orig = e.originalEvent; + var evt = slider.settings.SUPPORTS_TOUCH ? orig.changedTouches[0] : e; + // record the starting touch x, y coordinates + slider.touch.start.x = evt.pageX; + slider.touch.start.y = evt.pageY; + // bind a "touchmove" event to the viewport + slider.viewport.bind(slider.MOVE_EV, onTouchMove); + // bind a "touchend" event to the viewport + slider.viewport.bind(slider.END_EV, onTouchEnd); + } + } + + var onClick_check = function(e){ + if(slider.working){ + e.preventDefault(); } - } } - } - // if "vertical" mode, calculate the sum of the heights of the children - if (slider.settings.mode === 'vertical') { - children.each(function(index) { - height += $(this).outerHeight(); - }); - // add user-supplied margins - if (slider.settings.slideMargin > 0) { - height += slider.settings.slideMargin * (slider.settings.minSlides - 1); - } - // if not "vertical" mode, calculate the max height of the children - } else { - height = Math.max.apply(Math, children.map(function() { - return $(this).outerHeight(false); - }).get()); - } + /** + * Event handler for "touchmove" + * + * @param e (event) + * - DOM event object + */ + var onTouchMove = function(e){ + var orig = e.originalEvent; + var evt = slider.settings.SUPPORTS_TOUCH ? orig.changedTouches[0] : e; + // if scrolling on y axis, do not prevent default + var xMovement = Math.abs(evt.pageX - slider.touch.start.x); + var yMovement = Math.abs(evt.pageY - slider.touch.start.y); - if (slider.viewport.css('box-sizing') === 'border-box') { - height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')) + - parseFloat(slider.viewport.css('border-top-width')) + parseFloat(slider.viewport.css('border-bottom-width')); - } else if (slider.viewport.css('box-sizing') === 'padding-box') { - height += parseFloat(slider.viewport.css('padding-top')) + parseFloat(slider.viewport.css('padding-bottom')); - } - - return height; - }; - - /** - * Returns the calculated width to be used for the outer wrapper / viewport - */ - var getViewportMaxWidth = function() { - var width = '100%'; - if (slider.settings.slideWidth > 0) { - if (slider.settings.mode === 'horizontal') { - width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin); - } else { - width = slider.settings.slideWidth; - } - } - return width; - }; - - /** - * Returns the calculated width to be applied to each slide - */ - var getSlideWidth = function() { - var newElWidth = slider.settings.slideWidth, // start with any user-supplied slide width - wrapWidth = slider.viewport.width(); // get the current viewport width - // if slide width was not supplied, or is larger than the viewport use the viewport width - if (slider.settings.slideWidth === 0 || - (slider.settings.slideWidth > wrapWidth && !slider.carousel) || - slider.settings.mode === 'vertical') { - newElWidth = wrapWidth; - // if carousel, use the thresholds to determine the width - } else if (slider.settings.maxSlides > 1 && slider.settings.mode === 'horizontal') { - if (wrapWidth > slider.maxThreshold) { - return newElWidth; - } else if (wrapWidth < slider.minThreshold) { - newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides; - } else if (slider.settings.shrinkItems) { - newElWidth = Math.floor((wrapWidth + slider.settings.slideMargin) / (Math.ceil((wrapWidth + slider.settings.slideMargin) / (newElWidth + slider.settings.slideMargin))) - slider.settings.slideMargin); - } - } - return newElWidth; - }; - - /** - * Returns the number of slides currently visible in the viewport (includes partially visible slides) - */ - var getNumberSlidesShowing = function() { - var slidesShowing = 1, - childWidth = null; - if (slider.settings.mode === 'horizontal' && slider.settings.slideWidth > 0) { - // if viewport is smaller than minThreshold, return minSlides - if (slider.viewport.width() < slider.minThreshold) { - slidesShowing = slider.settings.minSlides; - // if viewport is larger than maxThreshold, return maxSlides - } else if (slider.viewport.width() > slider.maxThreshold) { - slidesShowing = slider.settings.maxSlides; - // if viewport is between min / max thresholds, divide viewport width by first child width - } else { - childWidth = slider.children.first().width() + slider.settings.slideMargin; - slidesShowing = Math.floor((slider.viewport.width() + - slider.settings.slideMargin) / childWidth); - } - // if "vertical" mode, slides showing will always be minSlides - } else if (slider.settings.mode === 'vertical') { - slidesShowing = slider.settings.minSlides; - } - return slidesShowing; - }; - - /** - * Returns the number of pages (one full viewport of slides is one "page") - */ - var getPagerQty = function() { - var pagerQty = 0, - breakPoint = 0, - counter = 0; - // if moveSlides is specified by the user - if (slider.settings.moveSlides > 0) { - if (slider.settings.infiniteLoop) { - pagerQty = Math.ceil(slider.children.length / getMoveBy()); - } else { - // when breakpoint goes above children length, counter is the number of pages - while (breakPoint < slider.children.length) { - ++pagerQty; - breakPoint = counter + getNumberSlidesShowing(); - counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing(); - } - } - // if moveSlides is 0 (auto) divide children length by sides showing, then round up - } else { - pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing()); - } - return pagerQty; - }; - - /** - * Returns the number of individual slides by which to shift the slider - */ - var getMoveBy = function() { - // if moveSlides was set by the user and moveSlides is less than number of slides showing - if (slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()) { - return slider.settings.moveSlides; - } - // if moveSlides is 0 (auto) - return getNumberSlidesShowing(); - }; - - /** - * Sets the slider's (el) left or top position - */ - var setSlidePosition = function() { - var position, lastChild, lastShowingIndex; - // if last slide, not infinite loop, and number of children is larger than specified maxSlides - if (slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop) { - if (slider.settings.mode === 'horizontal') { - // get the last child's position - lastChild = slider.children.last(); - position = lastChild.position(); - // set the left position - setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.outerWidth())), 'reset', 0); - } else if (slider.settings.mode === 'vertical') { - // get the last showing index's position - lastShowingIndex = slider.children.length - slider.settings.minSlides; - position = slider.children.eq(lastShowingIndex).position(); - // set the top position - setPositionProperty(-position.top, 'reset', 0); - } - // if not last slide - } else { - // get the position of the first showing slide - position = slider.children.eq(slider.active.index * getMoveBy()).position(); - // check for last slide - if (slider.active.index === getPagerQty() - 1) { slider.active.last = true; } - // set the respective position - if (position !== undefined) { - if (slider.settings.mode === 'horizontal') { setPositionProperty(-position.left, 'reset', 0); } - else if (slider.settings.mode === 'vertical') { setPositionProperty(-position.top, 'reset', 0); } - } - } - }; - - /** - * Sets the el's animating property position (which in turn will sometimes animate el). - * If using CSS, sets the transform property. If not using CSS, sets the top / left property. - * - * @param value (int) - * - the animating property's value - * - * @param type (string) 'slide', 'reset', 'ticker' - * - the type of instance for which the function is being - * - * @param duration (int) - * - the amount of time (in ms) the transition should occupy - * - * @param params (array) optional - * - an optional parameter containing any variables that need to be passed in - */ - var setPositionProperty = function(value, type, duration, params) { - var animateObj, propValue; - // use CSS transform - if (slider.usingCSS) { - // determine the translate3d value - propValue = slider.settings.mode === 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)'; - // add the CSS transition-duration - el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's'); - if (type === 'slide') { - // set the property value - el.css(slider.animProp, propValue); - if (duration !== 0) { - // bind a callback method - executes when CSS transition completes - el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) { - //make sure it's the correct one - if (!$(e.target).is(el)) { return; } - // unbind the callback - el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); - updateAfterSlideTransition(); - }); - } else { //duration = 0 - updateAfterSlideTransition(); - } - } else if (type === 'reset') { - el.css(slider.animProp, propValue); - } else if (type === 'ticker') { - // make the transition use 'linear' - el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear'); - el.css(slider.animProp, propValue); - if (duration !== 0) { - el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e) { - //make sure it's the correct one - if (!$(e.target).is(el)) { return; } - // unbind the callback - el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd'); - // reset the position - setPositionProperty(params.resetValue, 'reset', 0); - // start the loop again - tickerLoop(); - }); - } else { //duration = 0 - setPositionProperty(params.resetValue, 'reset', 0); - tickerLoop(); - } - } - // use JS animate - } else { - animateObj = {}; - animateObj[slider.animProp] = value; - if (type === 'slide') { - el.animate(animateObj, duration, slider.settings.easing, function() { - updateAfterSlideTransition(); - }); - } else if (type === 'reset') { - el.css(slider.animProp, value); - } else if (type === 'ticker') { - el.animate(animateObj, duration, 'linear', function() { - setPositionProperty(params.resetValue, 'reset', 0); - // run the recursive loop after animation - tickerLoop(); - }); - } - } - }; - - /** - * Populates the pager with proper amount of pages - */ - var populatePager = function() { - var pagerHtml = '', - linkContent = '', - pagerQty = getPagerQty(); - // loop through each pager item - for (var i = 0; i < pagerQty; i++) { - linkContent = ''; - // if a buildPager function is supplied, use it to get pager link value, else use index + 1 - if (slider.settings.buildPager && $.isFunction(slider.settings.buildPager) || slider.settings.pagerCustom) { - linkContent = slider.settings.buildPager(i); - slider.pagerEl.addClass('bx-custom-pager'); - } else { - linkContent = i + 1; - slider.pagerEl.addClass('bx-default-pager'); - } - // var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1; - // add the markup to the string - pagerHtml += ''; - } - // populate the pager element with pager links - slider.pagerEl.html(pagerHtml); - }; - - /** - * Appends the pager to the controls element - */ - var appendPager = function() { - if (!slider.settings.pagerCustom) { - // create the pager DOM element - slider.pagerEl = $('
'); - // if a pager selector was supplied, populate it with the pager - if (slider.settings.pagerSelector) { - $(slider.settings.pagerSelector).html(slider.pagerEl); - // if no pager selector was supplied, add it after the wrapper - } else { - slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl); - } - // populate the pager - populatePager(); - } else { - slider.pagerEl = $(slider.settings.pagerCustom); - } - // assign the pager click binding - slider.pagerEl.on('click touchend', 'a', clickPagerBind); - }; - - /** - * Appends prev / next controls to the controls element - */ - var appendControls = function() { - slider.controls.next = $('' + slider.settings.nextText + ''); - slider.controls.prev = $('' + slider.settings.prevText + ''); - // bind click actions to the controls - slider.controls.next.bind('click touchend', clickNextBind); - slider.controls.prev.bind('click touchend', clickPrevBind); - // if nextSelector was supplied, populate it - if (slider.settings.nextSelector) { - $(slider.settings.nextSelector).append(slider.controls.next); - } - // if prevSelector was supplied, populate it - if (slider.settings.prevSelector) { - $(slider.settings.prevSelector).append(slider.controls.prev); - } - // if no custom selectors were supplied - if (!slider.settings.nextSelector && !slider.settings.prevSelector) { - // add the controls to the DOM - slider.controls.directionEl = $('
'); - // add the control elements to the directionEl - slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next); - // slider.viewport.append(slider.controls.directionEl); - slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl); - } - }; - - /** - * Appends start / stop auto controls to the controls element - */ - var appendControlsAuto = function() { - slider.controls.start = $(''); - slider.controls.stop = $(''); - // add the controls to the DOM - slider.controls.autoEl = $('
'); - // bind click actions to the controls - slider.controls.autoEl.on('click', '.bx-start', clickStartBind); - slider.controls.autoEl.on('click', '.bx-stop', clickStopBind); - // if autoControlsCombine, insert only the "start" control - if (slider.settings.autoControlsCombine) { - slider.controls.autoEl.append(slider.controls.start); - // if autoControlsCombine is false, insert both controls - } else { - slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop); - } - // if auto controls selector was supplied, populate it with the controls - if (slider.settings.autoControlsSelector) { - $(slider.settings.autoControlsSelector).html(slider.controls.autoEl); - // if auto controls selector was not supplied, add it after the wrapper - } else { - slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl); - } - // update the auto controls - updateAutoControls(slider.settings.autoStart ? 'stop' : 'start'); - }; - - /** - * Appends image captions to the DOM - */ - var appendCaptions = function() { - // cycle through each child - slider.children.each(function(index) { - // get the image title attribute - var title = $(this).find('img:first').attr('title'); - // append the caption - if (title !== undefined && ('' + title).length) { - $(this).append('
' + title + '
'); - } - }); - }; - - /** - * Click next binding - * - * @param e (event) - * - DOM event object - */ - var clickNextBind = function(e) { - e.preventDefault(); - if (slider.controls.el.hasClass('disabled')) { return; } - // if auto show is running, stop it - if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); } - el.goToNextSlide(); - }; - - /** - * Click prev binding - * - * @param e (event) - * - DOM event object - */ - var clickPrevBind = function(e) { - e.preventDefault(); - if (slider.controls.el.hasClass('disabled')) { return; } - // if auto show is running, stop it - if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); } - el.goToPrevSlide(); - }; - - /** - * Click start binding - * - * @param e (event) - * - DOM event object - */ - var clickStartBind = function(e) { - el.startAuto(); - e.preventDefault(); - }; - - /** - * Click stop binding - * - * @param e (event) - * - DOM event object - */ - var clickStopBind = function(e) { - el.stopAuto(); - e.preventDefault(); - }; - - /** - * Click pager binding - * - * @param e (event) - * - DOM event object - */ - var clickPagerBind = function(e) { - var pagerLink, pagerIndex; - e.preventDefault(); - if (slider.controls.el.hasClass('disabled')) { - return; - } - // if auto show is running, stop it - if (slider.settings.auto && slider.settings.stopAutoOnClick) { el.stopAuto(); } - pagerLink = $(e.currentTarget); - if (pagerLink.attr('data-slide-index') !== undefined) { - pagerIndex = parseInt(pagerLink.attr('data-slide-index')); - // if clicked pager link is not active, continue with the goToSlide call - if (pagerIndex !== slider.active.index) { el.goToSlide(pagerIndex); } - } - }; - - /** - * Updates the pager links with an active class - * - * @param slideIndex (int) - * - index of slide to make active - */ - var updatePagerActive = function(slideIndex) { - // if "short" pager type - var len = slider.children.length; // nb of children - if (slider.settings.pagerType === 'short') { - if (slider.settings.maxSlides > 1) { - len = Math.ceil(slider.children.length / slider.settings.maxSlides); - } - slider.pagerEl.html((slideIndex + 1) + slider.settings.pagerShortSeparator + len); - return; - } - // remove all pager active classes - slider.pagerEl.find('a').removeClass('active'); - // apply the active class for all pagers - slider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); }); - }; - - /** - * Performs needed actions after a slide transition - */ - var updateAfterSlideTransition = function() { - // if infinite loop is true - if (slider.settings.infiniteLoop) { - var position = ''; - // first slide - if (slider.active.index === 0) { - // set the new position - position = slider.children.eq(0).position(); - // carousel, last slide - } else if (slider.active.index === getPagerQty() - 1 && slider.carousel) { - position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position(); - // last slide - } else if (slider.active.index === slider.children.length - 1) { - position = slider.children.eq(slider.children.length - 1).position(); - } - if (position) { - if (slider.settings.mode === 'horizontal') { setPositionProperty(-position.left, 'reset', 0); } - else if (slider.settings.mode === 'vertical') { setPositionProperty(-position.top, 'reset', 0); } - } - } - // declare that the transition is complete - slider.working = false; - // onSlideAfter callback - slider.settings.onSlideAfter.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); - }; - - /** - * Updates the auto controls state (either active, or combined switch) - * - * @param state (string) "start", "stop" - * - the new state of the auto show - */ - var updateAutoControls = function(state) { - // if autoControlsCombine is true, replace the current control with the new state - if (slider.settings.autoControlsCombine) { - slider.controls.autoEl.html(slider.controls[state]); - // if autoControlsCombine is false, apply the "active" class to the appropriate control - } else { - slider.controls.autoEl.find('a').removeClass('active'); - slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active'); - } - }; - - /** - * Updates the direction controls (checks if either should be hidden) - */ - var updateDirectionControls = function() { - if (getPagerQty() === 1) { - slider.controls.prev.addClass('disabled'); - slider.controls.next.addClass('disabled'); - } else if (!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd) { - // if first slide - if (slider.active.index === 0) { - slider.controls.prev.addClass('disabled'); - slider.controls.next.removeClass('disabled'); - // if last slide - } else if (slider.active.index === getPagerQty() - 1) { - slider.controls.next.addClass('disabled'); - slider.controls.prev.removeClass('disabled'); - // if any slide in the middle - } else { - slider.controls.prev.removeClass('disabled'); - slider.controls.next.removeClass('disabled'); - } - } - }; - - /** - * Initializes the auto process - */ - var initAuto = function() { - // if autoDelay was supplied, launch the auto show using a setTimeout() call - if (slider.settings.autoDelay > 0) { - var timeout = setTimeout(el.startAuto, slider.settings.autoDelay); - // if autoDelay was not supplied, start the auto show normally - } else { - el.startAuto(); - - //add focus and blur events to ensure its running if timeout gets paused - $(window).focus(function() { - el.startAuto(); - }).blur(function() { - el.stopAuto(); - }); - } - // if autoHover is requested - if (slider.settings.autoHover) { - // on el hover - el.hover(function() { - // if the auto show is currently playing (has an active interval) - if (slider.interval) { - // stop the auto show and pass true argument which will prevent control update - el.stopAuto(true); - // create a new autoPaused value which will be used by the relative "mouseout" event - slider.autoPaused = true; - } - }, function() { - // if the autoPaused value was created be the prior "mouseover" event - if (slider.autoPaused) { - // start the auto show and pass true argument which will prevent control update - el.startAuto(true); - // reset the autoPaused value - slider.autoPaused = null; - } - }); - } - }; - - /** - * Initializes the ticker process - */ - var initTicker = function() { - var startPosition = 0, - position, transform, value, idx, ratio, property, newSpeed, totalDimens; - // if autoDirection is "next", append a clone of the entire slider - if (slider.settings.autoDirection === 'next') { - el.append(slider.children.clone().addClass('bx-clone')); - // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position - } else { - el.prepend(slider.children.clone().addClass('bx-clone')); - position = slider.children.first().position(); - startPosition = slider.settings.mode === 'horizontal' ? -position.left : -position.top; - } - setPositionProperty(startPosition, 'reset', 0); - // do not allow controls in ticker mode - slider.settings.pager = false; - slider.settings.controls = false; - slider.settings.autoControls = false; - // if autoHover is requested - if (slider.settings.tickerHover) { - if (slider.usingCSS) { - idx = slider.settings.mode === 'horizontal' ? 4 : 5; - slider.viewport.hover(function() { - transform = el.css('-' + slider.cssPrefix + '-transform'); - value = parseFloat(transform.split(',')[idx]); - setPositionProperty(value, 'reset', 0); - }, function() { - totalDimens = 0; - slider.children.each(function(index) { - totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); - }); - // calculate the speed ratio (used to determine the new speed to finish the paused animation) - ratio = slider.settings.speed / totalDimens; - // determine which property to use - property = slider.settings.mode === 'horizontal' ? 'left' : 'top'; - // calculate the new speed - newSpeed = ratio * (totalDimens - (Math.abs(parseInt(value)))); - tickerLoop(newSpeed); - }); - } else { - // on el hover - slider.viewport.hover(function() { - el.stop(); - }, function() { - // calculate the total width of children (used to calculate the speed ratio) - totalDimens = 0; - slider.children.each(function(index) { - totalDimens += slider.settings.mode === 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true); - }); - // calculate the speed ratio (used to determine the new speed to finish the paused animation) - ratio = slider.settings.speed / totalDimens; - // determine which property to use - property = slider.settings.mode === 'horizontal' ? 'left' : 'top'; - // calculate the new speed - newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property))))); - tickerLoop(newSpeed); - }); - } - } - // start the ticker loop - tickerLoop(); - }; - - /** - * Runs a continuous loop, news ticker-style - */ - var tickerLoop = function(resumeSpeed) { - var speed = resumeSpeed ? resumeSpeed : slider.settings.speed, - position = {left: 0, top: 0}, - reset = {left: 0, top: 0}, - animateProperty, resetValue, params; - - // if "next" animate left position to last child, then reset left to 0 - if (slider.settings.autoDirection === 'next') { - position = el.find('.bx-clone').first().position(); - // if "prev" animate left position to 0, then reset left to first non-clone child - } else { - reset = slider.children.first().position(); - } - animateProperty = slider.settings.mode === 'horizontal' ? -position.left : -position.top; - resetValue = slider.settings.mode === 'horizontal' ? -reset.left : -reset.top; - params = {resetValue: resetValue}; - setPositionProperty(animateProperty, 'ticker', speed, params); - }; - - /** - * Check if el is on screen - */ - var isOnScreen = function(el) { - var win = $(window), - viewport = { - top: win.scrollTop(), - left: win.scrollLeft() - }, - bounds = el.offset(); - - viewport.right = viewport.left + win.width(); - viewport.bottom = viewport.top + win.height(); - bounds.right = bounds.left + el.outerWidth(); - bounds.bottom = bounds.top + el.outerHeight(); - - return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom)); - }; - - /** - * Initializes keyboard events - */ - var keyPress = function(e) { - var activeElementTag = document.activeElement.tagName.toLowerCase(), - tagFilters = 'input|textarea', - p = new RegExp(activeElementTag,['i']), - result = p.exec(tagFilters); - - if (result == null && isOnScreen(el)) { - if (e.keyCode === 39) { - clickNextBind(e); - return false; - } else if (e.keyCode === 37) { - clickPrevBind(e); - return false; - } - } - }; - - /** - * Initializes touch events - */ - var initTouch = function() { - // initialize object to contain all touch values - slider.touch = { - start: {x: 0, y: 0}, - end: {x: 0, y: 0} - }; - slider.viewport.bind('touchstart MSPointerDown pointerdown', onTouchStart); - - //for browsers that have implemented pointer events and fire a click after - //every pointerup regardless of whether pointerup is on same screen location as pointerdown or not - slider.viewport.on('click', '.bxslider a', function(e) { - if (slider.viewport.hasClass('click-disabled')) { - e.preventDefault(); - slider.viewport.removeClass('click-disabled'); - } - }); - }; - - /** - * Event handler for "touchstart" - * - * @param e (event) - * - DOM event object - */ - var onTouchStart = function(e) { - //disable slider controls while user is interacting with slides to avoid slider freeze that happens on touch devices when a slide swipe happens immediately after interacting with slider controls - slider.controls.el.addClass('disabled'); - - if (slider.working) { - e.preventDefault(); - slider.controls.el.removeClass('disabled'); - } else { - // record the original position when touch starts - slider.touch.originalPos = el.position(); - var orig = e.originalEvent, - touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig]; - // record the starting touch x, y coordinates - slider.touch.start.x = touchPoints[0].pageX; - slider.touch.start.y = touchPoints[0].pageY; - - if (slider.viewport.get(0).setPointerCapture) { - slider.pointerId = orig.pointerId; - slider.viewport.get(0).setPointerCapture(slider.pointerId); - } - // bind a "touchmove" event to the viewport - slider.viewport.bind('touchmove MSPointerMove pointermove', onTouchMove); - // bind a "touchend" event to the viewport - slider.viewport.bind('touchend MSPointerUp pointerup', onTouchEnd); - slider.viewport.bind('MSPointerCancel pointercancel', onPointerCancel); - } - }; - - /** - * Cancel Pointer for Windows Phone - * - * @param e (event) - * - DOM event object - */ - var onPointerCancel = function(e) { - /* onPointerCancel handler is needed to deal with situations when a touchend - doesn't fire after a touchstart (this happens on windows phones only) */ - setPositionProperty(slider.touch.originalPos.left, 'reset', 0); - - //remove handlers - slider.controls.el.removeClass('disabled'); - slider.viewport.unbind('MSPointerCancel pointercancel', onPointerCancel); - slider.viewport.unbind('touchmove MSPointerMove pointermove', onTouchMove); - slider.viewport.unbind('touchend MSPointerUp pointerup', onTouchEnd); - if (slider.viewport.get(0).releasePointerCapture) { - slider.viewport.get(0).releasePointerCapture(slider.pointerId); - } - }; - - /** - * Event handler for "touchmove" - * - * @param e (event) - * - DOM event object - */ - var onTouchMove = function(e) { - var orig = e.originalEvent, - touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig], - // if scrolling on y axis, do not prevent default - xMovement = Math.abs(touchPoints[0].pageX - slider.touch.start.x), - yMovement = Math.abs(touchPoints[0].pageY - slider.touch.start.y), - value = 0, - change = 0; - - // x axis swipe - if ((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX) { - e.preventDefault(); - // y axis swipe - } else if ((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY) { - e.preventDefault(); - } - if (slider.settings.mode !== 'fade' && slider.settings.oneToOneTouch) { - // if horizontal, drag along x axis - if (slider.settings.mode === 'horizontal') { - change = touchPoints[0].pageX - slider.touch.start.x; - value = slider.touch.originalPos.left + change; - // if vertical, drag along y axis - } else { - change = touchPoints[0].pageY - slider.touch.start.y; - value = slider.touch.originalPos.top + change; - } - setPositionProperty(value, 'reset', 0); - } - }; - - /** - * Event handler for "touchend" - * - * @param e (event) - * - DOM event object - */ - var onTouchEnd = function(e) { - slider.viewport.unbind('touchmove MSPointerMove pointermove', onTouchMove); - //enable slider controls as soon as user stops interacing with slides - slider.controls.el.removeClass('disabled'); - var orig = e.originalEvent, - touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig], - value = 0, - distance = 0; - // record end x, y positions - slider.touch.end.x = touchPoints[0].pageX; - slider.touch.end.y = touchPoints[0].pageY; - // if fade mode, check if absolute x distance clears the threshold - if (slider.settings.mode === 'fade') { - distance = Math.abs(slider.touch.start.x - slider.touch.end.x); - if (distance >= slider.settings.swipeThreshold) { - if (slider.touch.start.x > slider.touch.end.x) { - el.goToNextSlide(); - } else { - el.goToPrevSlide(); - } - el.stopAuto(); - } - // not fade mode - } else { - // calculate distance and el's animate property - if (slider.settings.mode === 'horizontal') { - distance = slider.touch.end.x - slider.touch.start.x; - value = slider.touch.originalPos.left; - } else { - distance = slider.touch.end.y - slider.touch.start.y; - value = slider.touch.originalPos.top; - } - // if not infinite loop and first / last slide, do not attempt a slide transition - if (!slider.settings.infiniteLoop && ((slider.active.index === 0 && distance > 0) || (slider.active.last && distance < 0))) { - setPositionProperty(value, 'reset', 200); - } else { - // check if distance clears threshold - if (Math.abs(distance) >= slider.settings.swipeThreshold) { - if (distance < 0) { - el.goToNextSlide(); - } else { - el.goToPrevSlide(); + // determine if scrolling test has run - one time test + if ( typeof isScrolling == 'undefined') { + isScrolling = !!( isScrolling || xMovement < yMovement ); + } + if (!isScrolling && slider.settings.mode != 'vertical') { + // x axis swipe + if((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX){ + e.preventDefault(); + // y axis swipe + }else if((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY){ + e.preventDefault(); + } + if(slider.settings.mode != 'fade' && slider.settings.oneToOneTouch){ + var value = 0; + // if horizontal, drag along x axis + if(slider.settings.mode == 'horizontal'){ + var change = evt.pageX - slider.touch.start.x; + value = slider.touch.originalPos.left + change; + // if vertical, drag along y axis + }else{ + var change = evt.pageY - slider.touch.start.y; + value = slider.touch.originalPos.top + change; + } + setPositionProperty(value, 'reset', 0); + } } - el.stopAuto(); - } else { - // el.animate(property, 200); - setPositionProperty(value, 'reset', 200); - } - } - } - slider.viewport.unbind('touchend MSPointerUp pointerup', onTouchEnd); - if (slider.viewport.get(0).releasePointerCapture) { - slider.viewport.get(0).releasePointerCapture(slider.pointerId); - } - }; + } - /** - * Window resize event callback - */ - var resizeWindow = function(e) { - // don't do anything if slider isn't initialized. - if (!slider.initialized) { return; } - // Delay if slider working. - if (slider.working) { - window.setTimeout(resizeWindow, 10); - } else { - // get the new window dimens (again, thank you IE) - var windowWidthNew = $(window).width(), - windowHeightNew = $(window).height(); - // make sure that it is a true window resize - // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements - // are resized. Can you just die already?* - if (windowWidth !== windowWidthNew || windowHeight !== windowHeightNew) { - // set the new window dimens - windowWidth = windowWidthNew; - windowHeight = windowHeightNew; - // update all dynamic elements - el.redrawSlider(); - // Call user resize handler - slider.settings.onSliderResize.call(el, slider.active.index); - } - } - }; + /** + * Event handler for "touchend" + * + * @param e (event) + * - DOM event object + */ + var onTouchEnd = function(e){ + slider.viewport.unbind(slider.MOVE_EV, onTouchMove); + var orig = e.originalEvent; + var evt = slider.settings.SUPPORTS_TOUCH ? orig.changedTouches[0] : e; + var value = 0; + // record end x, y positions + slider.touch.end.x = evt.pageX; + slider.touch.end.y = evt.pageY; + // if fade mode, check if absolute x distance clears the threshold + if(slider.settings.mode == 'fade'){ + var distance = Math.abs(slider.touch.start.x - slider.touch.end.x); + if(distance >= slider.settings.swipeThreshold){ + slider.touch.start.x > slider.touch.end.x ? el.goToNextSlide() : el.goToPrevSlide(); + el.stopAuto(); + } + // not fade mode + }else{ + var distance = 0; + // calculate distance and el's animate property + if(slider.settings.mode == 'horizontal'){ + distance = slider.touch.end.x - slider.touch.start.x; + value = slider.touch.originalPos.left; + }else{ + distance = slider.touch.end.y - slider.touch.start.y; + value = slider.touch.originalPos.top; + } + // if not infinite loop and first / last slide, do not attempt a slide transition + if(!slider.settings.infiniteLoop && ((slider.active.index == 0 && distance > 0) || (slider.active.last && distance < 0))){ + setPositionProperty(value, 'reset', 200); + }else{ + // check if distance clears threshold + if(Math.abs(distance) >= slider.settings.swipeThreshold){ + distance < 0 ? el.goToNextSlide() : el.goToPrevSlide(); + el.stopAuto(); + }else{ + // el.animate(property, 200); + setPositionProperty(value, 'reset', 200); + } + } + } + slider.viewport.unbind(slider.END_EV, onTouchEnd); + } - /** - * Adds an aria-hidden=true attribute to each element - * - * @param startVisibleIndex (int) - * - the first visible element's index - */ - var applyAriaHiddenAttributes = function(startVisibleIndex) { - var numberOfSlidesShowing = getNumberSlidesShowing(); - // only apply attributes if the setting is enabled and not in ticker mode - if (slider.settings.ariaHidden && !slider.settings.ticker) { - // add aria-hidden=true to all elements - slider.children.attr('aria-hidden', 'true'); - // get the visible elements and change to aria-hidden=false - slider.children.slice(startVisibleIndex, startVisibleIndex + numberOfSlidesShowing).attr('aria-hidden', 'false'); - } - }; + /** + * Window resize event callback + */ + var resizeWindow = function(e){ + // get the new window dimens (again, thank you IE) + var windowWidthNew = $(window).width(); + var windowHeightNew = $(window).height(); + // make sure that it is a true window resize + // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements + // are resized. Can you just die already?* + if(windowWidth != windowWidthNew || windowHeight != windowHeightNew){ + // set the new window dimens + windowWidth = windowWidthNew; + windowHeight = windowHeightNew; + // update all dynamic elements + el.redrawSlider(); + } + } - /** - * Returns index according to present page range - * - * @param slideOndex (int) - * - the desired slide index - */ - var setSlideIndex = function(slideIndex) { - if (slideIndex < 0) { - if (slider.settings.infiniteLoop) { - return getPagerQty() - 1; - }else { - //we don't go to undefined slides - return slider.active.index; - } - // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop) - } else if (slideIndex >= getPagerQty()) { - if (slider.settings.infiniteLoop) { - return 0; - } else { - //we don't move to undefined pages - return slider.active.index; - } - // set active index to requested slide - } else { - return slideIndex; - } - }; + /** + * =================================================================================== + * = PUBLIC FUNCTIONS + * =================================================================================== + */ - /** - * =================================================================================== - * = PUBLIC FUNCTIONS - * =================================================================================== - */ + /** + * Performs slide transition to the specified slide + * + * @param slideIndex (int) + * - the destination slide's index (zero-based) + * + * @param direction (string) + * - INTERNAL USE ONLY - the direction of travel ("prev" / "next") + */ + el.goToSlide = function(slideIndex, direction, workignore){ + // if plugin is currently in motion, ignore request + if( slider.active.index == slideIndex ) return; + if( !workignore && slider.working ) return; - /** - * Performs slide transition to the specified slide - * - * @param slideIndex (int) - * - the destination slide's index (zero-based) - * - * @param direction (string) - * - INTERNAL USE ONLY - the direction of travel ("prev" / "next") - */ - el.goToSlide = function(slideIndex, direction) { - // onSlideBefore, onSlideNext, onSlidePrev callbacks - // Allow transition canceling based on returned value - var performTransition = true, - moveBy = 0, - position = {left: 0, top: 0}, - lastChild = null, - lastShowingIndex, eq, value, requestEl; - // store the old index - slider.oldIndex = slider.active.index; - //set new index - slider.active.index = setSlideIndex(slideIndex); + // declare that plugin is in motion + slider.working = true; + // store the old index + slider.oldIndex = slider.active.index; + // if slideIndex is less than zero, set active index to last child (this happens during infinite loop) + if(slideIndex < 0){ + slider.active.index = getPagerQty() - 1; + // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop) + }else if(slideIndex >= getPagerQty()){ + slider.active.index = 0; + // set active index to requested slide + }else{ + slider.active.index = slideIndex; + } + // onSlideBefore, onSlideNext, onSlidePrev callbacks + slider.settings.onSlideBefore(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); + if(direction == 'next'){ + slider.settings.onSlideNext(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); + }else if(direction == 'prev'){ + slider.settings.onSlidePrev(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); + } + // check if last slide + slider.active.last = slider.active.index >= getPagerQty() - 1; + // update the pager with active class + if(slider.settings.pager) updatePagerActive(slider.active.index); + // // check for direction control update + if(slider.settings.controls) updateDirectionControls(); + // if slider is set to mode: "fade" + if(slider.settings.mode == 'fade'){ + // if adaptiveHeight is true and next height is different from current height, animate to the new height + if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){ + slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); + } + // fade out the visible child and reset its z-index value + slider.children.filter(':visible').stop( true, true ).fadeOut(slider.settings.speed).css({zIndex: 0}); + // fade in the newly requested slide + slider.children.eq(slider.active.index).css('zIndex', 51).stop( true, true ).fadeIn(slider.settings.speed, function(){ + $(this).css('zIndex', 50); + updateAfterSlideTransition(); + }); + // slider mode is not "fade" + }else{ + // if adaptiveHeight is true and next height is different from current height, animate to the new height + if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){ + slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); + } + var moveBy = 0; + var position = {left: 0, top: 0}; + // if carousel and not infinite loop + if(!slider.settings.infiniteLoop && slider.carousel && slider.active.last){ + if(slider.settings.mode == 'horizontal'){ + // get the last child position + var lastChild = slider.children.eq(slider.children.length - 1); + position = lastChild.position(); + // calculate the position of the last slide + moveBy = slider.viewport.width() - lastChild.outerWidth(); + }else{ + // get last showing index position + var lastShowingIndex = slider.children.length - slider.settings.minSlides; + position = slider.children.eq(lastShowingIndex).position(); + } + // horizontal carousel, going previous while on first slide (infiniteLoop mode) + }else if(slider.carousel && slider.active.last && direction == 'prev'){ + // get the last child position + var eq = slider.settings.moveSlides == 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides); + var lastChild = el.children('.bx-clone').eq(eq); + position = lastChild.position(); + // if infinite loop and "Next" is clicked on the last slide + }else if(direction == 'next' && slider.active.index == 0){ + // get the last clone position + position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position(); + slider.active.last = false; + // normal non-zero requests + }else if(slideIndex >= 0){ + var requestEl = slideIndex * getMoveBy(); + position = slider.children.eq(requestEl).position(); + } - // if plugin is currently in motion, ignore request - if (slider.working || slider.active.index === slider.oldIndex) { return; } - // declare that plugin is in motion - slider.working = true; + /* If the position doesn't exist + * (e.g. if you destroy the slider on a next click), + * it doesn't throw an error. + */ + if ("undefined" !== typeof(position)) { + var value = slider.settings.mode == 'horizontal' ? -(position.left - moveBy) : -position.top; + // plugin values to be animated + setPositionProperty(value, 'slide', slider.settings.speed); + } + } + } - performTransition = slider.settings.onSlideBefore.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index); + /** + * Transitions to the next slide in the show + */ + el.goToNextSlide = function(){ + // if infiniteLoop is false and last page is showing, disregard call + if (!slider.settings.infiniteLoop && slider.active.last) return; + var pagerIndex = parseInt(slider.active.index) + 1; + el.goToSlide(pagerIndex, 'next'); + } - // If transitions canceled, reset and return - if (typeof (performTransition) !== 'undefined' && !performTransition) { - slider.active.index = slider.oldIndex; // restore old index - slider.working = false; // is not in motion - return; - } + /** + * Transitions to the prev slide in the show + */ + el.goToPrevSlide = function(){ + // if infiniteLoop is false and last page is showing, disregard call + if (!slider.settings.infiniteLoop && slider.active.index == 0) return; + var pagerIndex = parseInt(slider.active.index) - 1; + el.goToSlide(pagerIndex, 'prev'); + } - if (direction === 'next') { - // Prevent canceling in future functions or lack there-of from negating previous commands to cancel - if (!slider.settings.onSlideNext.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) { - performTransition = false; - } - } else if (direction === 'prev') { - // Prevent canceling in future functions or lack there-of from negating previous commands to cancel - if (!slider.settings.onSlidePrev.call(el, slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index)) { - performTransition = false; - } - } + /** + * Starts the auto show + * + * @param preventControlUpdate (boolean) + * - if true, auto controls state will not be updated + */ + el.startAuto = function(preventControlUpdate){ + // if an interval already exists, disregard call + if(slider.interval) return; + // create an interval + slider.interval = setInterval(function(){ + slider.settings.autoDirection == 'next' ? el.goToNextSlide() : el.goToPrevSlide(); + }, el.pause); - // check if last slide - slider.active.last = slider.active.index >= getPagerQty() - 1; - // update the pager with active class - if (slider.settings.pager || slider.settings.pagerCustom) { updatePagerActive(slider.active.index); } - // // check for direction control update - if (slider.settings.controls) { updateDirectionControls(); } - // if slider is set to mode: "fade" - if (slider.settings.mode === 'fade') { - // if adaptiveHeight is true and next height is different from current height, animate to the new height - if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) { - slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); - } - // fade out the visible child and reset its z-index value - slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0}); - // fade in the newly requested slide - slider.children.eq(slider.active.index).css('zIndex', slider.settings.slideZIndex + 1).fadeIn(slider.settings.speed, function() { - $(this).css('zIndex', slider.settings.slideZIndex); - updateAfterSlideTransition(); - }); - // slider mode is not "fade" - } else { - // if adaptiveHeight is true and next height is different from current height, animate to the new height - if (slider.settings.adaptiveHeight && slider.viewport.height() !== getViewportHeight()) { - slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed); - } - // if carousel and not infinite loop - if (!slider.settings.infiniteLoop && slider.carousel && slider.active.last) { - if (slider.settings.mode === 'horizontal') { - // get the last child position - lastChild = slider.children.eq(slider.children.length - 1); - position = lastChild.position(); - // calculate the position of the last slide - moveBy = slider.viewport.width() - lastChild.outerWidth(); - } else { - // get last showing index position - lastShowingIndex = slider.children.length - slider.settings.minSlides; - position = slider.children.eq(lastShowingIndex).position(); - } - // horizontal carousel, going previous while on first slide (infiniteLoop mode) - } else if (slider.carousel && slider.active.last && direction === 'prev') { - // get the last child position - eq = slider.settings.moveSlides === 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides); - lastChild = el.children('.bx-clone').eq(eq); - position = lastChild.position(); - // if infinite loop and "Next" is clicked on the last slide - } else if (direction === 'next' && slider.active.index === 0) { - // get the last clone position - position = el.find('> .bx-clone').eq(slider.settings.maxSlides).position(); - slider.active.last = false; - // normal non-zero requests - } else if (slideIndex >= 0) { - //parseInt is applied to allow floats for slides/page - requestEl = slideIndex * parseInt(getMoveBy()); - position = slider.children.eq(requestEl).position(); + // if auto controls are displayed and preventControlUpdate is not true + if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('stop'); + } + + /** + * Stops the auto show + * + * @param preventControlUpdate (boolean) + * - if true, auto controls state will not be updated + */ + el.stopAuto = function(preventControlUpdate){ + // if no interval exists, disregard call + if(!slider.interval) return; + // clear the interval + el.clearTimer(); + slider.interval = null; + // if auto controls are displayed and preventControlUpdate is not true + if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('start'); + } + + /** + * clear + */ + el.clearTimer = function(){ + clearInterval(slider.interval); } - /* If the position doesn't exist - * (e.g. if you destroy the slider on a next click), - * it doesn't throw an error. - */ - if (typeof (position) !== 'undefined') { - value = slider.settings.mode === 'horizontal' ? -(position.left - moveBy) : -position.top; - // plugin values to be animated - setPositionProperty(value, 'slide', slider.settings.speed); - } else { - slider.working = false; - } - } - if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); } - }; + /** + * Returns current slide index (zero-based) + */ + el.getCurrentSlide = function(){ + return slider.active.index; + } - /** - * Transitions to the next slide in the show - */ - el.goToNextSlide = function() { - // if infiniteLoop is false and last page is showing, disregard call - if (!slider.settings.infiniteLoop && slider.active.last) { return; } - var pagerIndex = parseInt(slider.active.index) + 1; - el.goToSlide(pagerIndex, 'next'); - }; + /** + * Returns number of slides in show + */ + el.getSlideCount = function(){ + return slider.children.length; + } - /** - * Transitions to the prev slide in the show - */ - el.goToPrevSlide = function() { - // if infiniteLoop is false and last page is showing, disregard call - if (!slider.settings.infiniteLoop && slider.active.index === 0) { return; } - var pagerIndex = parseInt(slider.active.index) - 1; - el.goToSlide(pagerIndex, 'prev'); - }; + /** + * Update all dynamic slider elements + */ + el.redrawSlider = function(){ + // resize all children in ratio to new screen size + slider.children.add(el.find('.bx-clone')).outerWidth(getSlideWidth()); + // adjust the height + slider.viewport.css('height', getViewportHeight()); + // update the slide position + if(!slider.settings.ticker) setSlidePosition(); + // if active.last was true before the screen resize, we want + // to keep it last no matter what screen size we end on + if (slider.active.last) slider.active.index = getPagerQty() - 1; + // if the active index (page) no longer exists due to the resize, simply set the index as last + if (slider.active.index >= getPagerQty()) slider.active.last = true; + // if a pager is being displayed and a custom pager is not being used, update it + if(slider.settings.pager && !slider.settings.pagerCustom){ + populatePager(); + updatePagerActive(slider.active.index); + } + } - /** - * Starts the auto show - * - * @param preventControlUpdate (boolean) - * - if true, auto controls state will not be updated - */ - el.startAuto = function(preventControlUpdate) { - // if an interval already exists, disregard call - if (slider.interval) { return; } - // create an interval - slider.interval = setInterval(function() { - if (slider.settings.autoDirection === 'next') { - el.goToNextSlide(); - } else { - el.goToPrevSlide(); - } - }, slider.settings.pause); - // if auto controls are displayed and preventControlUpdate is not true - if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('stop'); } - }; + /** + * Destroy the current instance of the slider (revert everything back to original state) + */ + el.destroySlider = function(){ + // don't do anything if slider has already been destroyed + if(!slider.initialized) return; + slider.initialized = false; + $('.bx-clone', this).remove(); + slider.children.each(function() { + $(this).data("origStyle") != undefined ? $(this).attr("style", $(this).data("origStyle")) : $(this).removeAttr('style'); + }); + $(this).data("origStyle") != undefined ? this.attr("style", $(this).data("origStyle")) : $(this).removeAttr('style'); + $(this).unwrap().unwrap(); + if(slider.controls.el) slider.controls.el.remove(); + if(slider.controls.next) slider.controls.next.remove(); + if(slider.controls.prev) slider.controls.prev.remove(); + if(slider.pagerEl) slider.pagerEl.remove(); + $('.bx-caption', this).remove(); + if(slider.controls.autoEl) slider.controls.autoEl.remove(); + el.clearTimer(); + if(slider.settings.responsive) $(window).unbind('resize', resizeWindow); + } - /** - * Stops the auto show - * - * @param preventControlUpdate (boolean) - * - if true, auto controls state will not be updated - */ - el.stopAuto = function(preventControlUpdate) { - // if no interval exists, disregard call - if (!slider.interval) { return; } - // clear the interval - clearInterval(slider.interval); - slider.interval = null; - // if auto controls are displayed and preventControlUpdate is not true - if (slider.settings.autoControls && preventControlUpdate !== true) { updateAutoControls('start'); } - }; + /** + * Reload the slider (revert all DOM changes, and re-initialize) + */ + el.reloadSlider = function(settings){ + if (settings != undefined) options = settings; + el.destroySlider(); + init(); + } - /** - * Returns current slide index (zero-based) - */ - el.getCurrentSlide = function() { - return slider.active.index; - }; + init(); - /** - * Returns current slide element - */ - el.getCurrentSlideElement = function() { - return slider.children.eq(slider.active.index); - }; + // returns the current jQuery object + return this; + } - /** - * Returns a slide element - * @param index (int) - * - The index (zero-based) of the element you want returned. - */ - el.getSlideElement = function(index) { - return slider.children.eq(index); - }; - - /** - * Returns number of slides in show - */ - el.getSlideCount = function() { - return slider.children.length; - }; - - /** - * Return slider.working variable - */ - el.isWorking = function() { - return slider.working; - }; - - /** - * Update all dynamic slider elements - */ - el.redrawSlider = function() { - // resize all children in ratio to new screen size - slider.children.add(el.find('.bx-clone')).outerWidth(getSlideWidth()); - // adjust the height - slider.viewport.css('height', getViewportHeight()); - // update the slide position - if (!slider.settings.ticker) { setSlidePosition(); } - // if active.last was true before the screen resize, we want - // to keep it last no matter what screen size we end on - if (slider.active.last) { slider.active.index = getPagerQty() - 1; } - // if the active index (page) no longer exists due to the resize, simply set the index as last - if (slider.active.index >= getPagerQty()) { slider.active.last = true; } - // if a pager is being displayed and a custom pager is not being used, update it - if (slider.settings.pager && !slider.settings.pagerCustom) { - populatePager(); - updatePagerActive(slider.active.index); - } - if (slider.settings.ariaHidden) { applyAriaHiddenAttributes(slider.active.index * getMoveBy()); } - }; - - /** - * Destroy the current instance of the slider (revert everything back to original state) - */ - el.destroySlider = function() { - // don't do anything if slider has already been destroyed - if (!slider.initialized) { return; } - slider.initialized = false; - $('.bx-clone', this).remove(); - slider.children.each(function() { - if ($(this).data('origStyle') !== undefined) { - $(this).attr('style', $(this).data('origStyle')); - } else { - $(this).removeAttr('style'); - } - }); - if ($(this).data('origStyle') !== undefined) { - this.attr('style', $(this).data('origStyle')); - } else { - $(this).removeAttr('style'); - } - $(this).unwrap().unwrap(); - if (slider.controls.el) { slider.controls.el.remove(); } - if (slider.controls.next) { slider.controls.next.remove(); } - if (slider.controls.prev) { slider.controls.prev.remove(); } - if (slider.pagerEl && slider.settings.controls && !slider.settings.pagerCustom) { slider.pagerEl.remove(); } - $('.bx-caption', this).remove(); - if (slider.controls.autoEl) { slider.controls.autoEl.remove(); } - clearInterval(slider.interval); - if (slider.settings.responsive) { $(window).unbind('resize', resizeWindow); } - if (slider.settings.keyboardEnabled) { $(document).unbind('keydown', keyPress); } - //remove self reference in data - $(this).removeData('bxSlider'); - }; - - /** - * Reload the slider (revert all DOM changes, and re-initialize) - */ - el.reloadSlider = function(settings) { - if (settings !== undefined) { options = settings; } - el.destroySlider(); - init(); - //store reference to self in order to access public functions later - $(el).data('bxSlider', this); - }; - - init(); - - $(el).data('bxSlider', this); - - // returns the current jQuery object - return this; - }; - -})(jQuery); +})(jQuery); \ No newline at end of file From 761722881a9fdf7ab552578a62e01036bb3045ec Mon Sep 17 00:00:00 2001 From: thisgun Date: Tue, 14 Nov 2017 12:07:33 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=EC=86=8C=EC=85=9C=20css=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- skin/social/style.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skin/social/style.css b/skin/social/style.css index d302151e4..9a2e71964 100644 --- a/skin/social/style.css +++ b/skin/social/style.css @@ -104,7 +104,7 @@ .mbskin .toggle .title-name{display:block} .mbskin .toggle .toggle-inner{padding:15px;line-height:1.5em;display:none;background:#fff;border-top:1px solid #e2e2e2;} .mbskin .toggle .toggle-inner div{max-width:100%} -.mbskin .right_i{position:absolute;font-size:0.92em;top:10px;right:10px;padding:0 10px 0 0;border-radius:3px;display:inline-block;z-index: 2;background: #3497d9;color: #fff;border-bottom-color: #1977b5;} +.mbskin .right_i{position:absolute;font-size:0.92em;top:10px;right:10px;padding:0 10px 0 0;border-radius:3px;display:inline-block;z-index: 2;background: #3497d9;color: #fff;border-bottom-color: #1977b5;cursor:pointer} .mbskin .toggle .toggle-title .right_i i{background:url("./img/plus_minus.png") 0 -24px no-repeat;width:20px;height:24px;display:inline-block;vertical-align:middle} .mbskin .toggle .toggle-title.active .right_i i{background:url("./img/plus_minus.png") 0 0 no-repeat} .mbskin .all_agree{position:relative;display:block;;margin-bottom:6px;background:#fff;border:1px solid #c6cacc;border-top:0;padding:13px 15px;line-height:20px} @@ -136,9 +136,9 @@ #sns-link-pnl .connect-fg .connect-title {margin-top:25px;margin-bottom:10px;font-size:1.667em;font-weight:bold;text-align:center} .mbskin .member_connect:after {display:block;visibility:hidden;clear:both;content:""} -.mbskin .member_connect{margin-top:50px;background:#d9d9d9;border-radius:3px;padding:10px;text-align:center} +.mbskin .member_connect{margin-top:80px;background:#d9d9d9;border-radius:3px;padding:10px;text-align:left} .mbskin .member_connect .strong{font-size:1em;font-weight:bold;margin:0 0 10px} -.mbskin .member_connect button{color: #fff;border:0;padding:10px 20px;border:1px solid #6446e7;font-weight:bold;background: #6f50e7;border-radius:3px;font-size:0.91em} +.mbskin .member_connect button{color: #fff;border:0;padding:6px 20px 7px;border:1px solid #6446e7;font-weight:bold;background: #6f50e7;border-radius:3px;font-size:0.91em} .mbskin .member_connect button:hover{background:#6446e7} html.remodal-is-locked {overflow-y:scroll !important} From b8d788c1b49dfbc8187ba021d0a79d9b74dc42cb Mon Sep 17 00:00:00 2001 From: thisgun Date: Tue, 14 Nov 2017 14:48:37 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=EB=A6=AC=EB=89=B4=EC=96=BC=20=EC=9E=98?= =?UTF-8?q?=EB=AA=BB=EB=90=9C=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bbs/content.php | 2 +- css/default.css | 4 +++- head.php | 4 ++-- skin/latest/pic_basic/latest.skin.php | 2 +- theme/basic/css/default.css | 4 +++- theme/basic/head.php | 4 ++-- theme/basic/screenshot.png | Bin 11304 -> 36358 bytes 7 files changed, 12 insertions(+), 8 deletions(-) diff --git a/bbs/content.php b/bbs/content.php index b46d6f338..f9551ed80 100644 --- a/bbs/content.php +++ b/bbs/content.php @@ -67,7 +67,7 @@ $content_skin_url = get_skin_url('content', $co['co_skin']); $skin_file = $content_skin_path.'/content.skin.php'; if ($is_admin) - echo ''; + echo ''; ?> -
  • 메뉴 준비 중입니다. 관리자모드 > 환경설정 > 메뉴설정에서 설정하실 수 있습니다.
  • +
  • 메뉴 준비 중입니다. 관리자모드 > 환경설정 > 메뉴설정에서 설정하실 수 있습니다.
  • @@ -198,7 +198,7 @@ include_once(G5_LIB_PATH.'/popular.lib.php'); } //end foreach $row if ($i == 0) { ?> -
  • 메뉴 준비 중입니다.
    관리자모드 > 환경설정 > 메뉴설정에서 설정하실 수 있습니다.
  • +
  • 메뉴 준비 중입니다.
    관리자모드 > 환경설정 > 메뉴설정에서 설정하실 수 있습니다.
  • diff --git a/skin/latest/pic_basic/latest.skin.php b/skin/latest/pic_basic/latest.skin.php index 8c68d3ee2..5b9eb2726 100644 --- a/skin/latest/pic_basic/latest.skin.php +++ b/skin/latest/pic_basic/latest.skin.php @@ -18,7 +18,7 @@ $thumb_height = 150; if($thumb['src']) { $img = $thumb['src']; } else { - $img = $latest_skin_url.'/img/no_img.gif'; + $img = G5_IMG_URL.'/no_img.png'; } $img_content = ''.$thumb['alt'].''; ?> diff --git a/theme/basic/css/default.css b/theme/basic/css/default.css index 2906b3373..30cea191d 100644 --- a/theme/basic/css/default.css +++ b/theme/basic/css/default.css @@ -140,7 +140,9 @@ transition: all 0.3s ease-out;} .gnb_2da:focus, .gnb_2da:hover {color:#fff} .gnb_1dli_over .gnb_2dul {display:block;left:0} .gnb_1dli_over2 .gnb_2dul {display:block;right:0;background:#fff} -#gnb_empty {padding:10px 0;width:100%;text-align:center;line-height:2em;color:#fff} +.gnb_wrap .gnb_empty {padding:10px 0;width:100%;text-align:center;line-height:2em;color:#fff} +.gnb_wrap .gnb_empty a{color:#fff;text-decoration:underline} +.gnb_wrap .gnb_al_ul .gnb_empty, .gnb_wrap .gnb_al_ul .gnb_empty a{color:#555} #gnb .gnb_menu_btn{background:#4158d1;color:#fff;width:50px;height:50px;border:0;vertical-align:top;font-size:18px} #gnb .gnb_close_btn{background:#4158d1;color:#fff;width:50px;height:50px;border:0;vertical-align:top;font-size:18px;position:absolute;top:-50px;left:0} diff --git a/theme/basic/head.php b/theme/basic/head.php index 1ff55575e..2534e0380 100644 --- a/theme/basic/head.php +++ b/theme/basic/head.php @@ -160,7 +160,7 @@ include_once(G5_LIB_PATH.'/popular.lib.php'); } //end foreach $row if ($i == 0) { ?> -
  • 메뉴 준비 중입니다. 관리자모드 > 환경설정 > 메뉴설정에서 설정하실 수 있습니다.
  • +
  • 메뉴 준비 중입니다. 관리자모드 > 환경설정 > 메뉴설정에서 설정하실 수 있습니다.
  • @@ -193,7 +193,7 @@ include_once(G5_LIB_PATH.'/popular.lib.php'); } //end foreach $row if ($i == 0) { ?> -
  • 메뉴 준비 중입니다.
    관리자모드 > 환경설정 > 메뉴설정에서 설정하실 수 있습니다.
  • +
  • 메뉴 준비 중입니다.
    관리자모드 > 환경설정 > 메뉴설정에서 설정하실 수 있습니다.
  • diff --git a/theme/basic/screenshot.png b/theme/basic/screenshot.png index 423a3993e322ca8e9d300249e51c3336deb8ac68..249f4c1345579f491530ed520a52937ea0b4969c 100644 GIT binary patch literal 36358 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 LNkvXXu0mjfdfJMW literal 11304 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 YuY;XbV-|^EfBl7%l~R(dmM{wbUw`rJHUIzs