web-apps/vendor/framework7/js/framework7.js
2016-11-11 16:24:21 +03:00

17518 lines
790 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Framework7 1.5.0
* Full featured mobile HTML framework for building iOS & Android apps
*
* http://framework7.io/
*
* Copyright 2016, Vladimir Kharlampidi
* The iDangero.us
* http://www.idangero.us/
*
* Licensed under MIT
*
* Released on: November 8, 2016
*/
(function () {
'use strict';
/*===========================
Framework 7
===========================*/
window.Framework7 = function (params) {
// App
var app = this;
// Version
app.version = '1.5.0';
// Default Parameters
app.params = {
//
root: 'body',
//
cache: true,
cacheIgnore: [],
cacheIgnoreGetParameters: false,
cacheDuration: 1000 * 60 * 10, // Ten minutes
preloadPreviousPage: true,
uniqueHistory: false,
uniqueHistoryIgnoreGetParameters: false,
dynamicPageUrl: 'content-{{index}}',
allowDuplicateUrls: false,
router: true,
routerRemoveTimeout: false,
routerRemoveWithTimeout: false,
// Push State
pushState: false,
pushStateRoot: undefined,
pushStateNoAnimation: false,
pushStateSeparator: '#!/',
pushStateOnLoad: true,
// Fast clicks
fastClicks: true,
fastClicksDistanceThreshold: 10,
fastClicksDelayBetweenClicks: 50,
fastClicksExclude: '', // CSS selector
// Tap Hold
tapHold: false,
tapHoldDelay: 750,
tapHoldPreventClicks: true,
// Active State
activeState: true,
activeStateElements: 'a, button, label, span',
// Animate Nav Back Icon
animateNavBackIcon: false,
// Swipe Back
swipeBackPage: true,
swipeBackPageThreshold: 0,
swipeBackPageActiveArea: 30,
swipeBackPageAnimateShadow: true,
swipeBackPageAnimateOpacity: true,
// Ajax
ajaxLinks: undefined, // or CSS selector
// External Links
externalLinks: '.external', // CSS selector
// Sortable
sortable: true,
// Scroll toolbars
hideNavbarOnPageScroll: false,
hideToolbarOnPageScroll: false,
hideTabbarOnPageScroll: false,
showBarsOnPageScrollEnd: true,
showBarsOnPageScrollTop: true,
// Swipeout
swipeout: true,
swipeoutActionsNoFold: false,
swipeoutNoFollow: false,
swipeoutRemoveWithTimeout: false,
// Smart Select Back link template
smartSelectOpenIn: 'page', // or 'popup' or 'picker'
smartSelectBackText: 'Back',
smartSelectPopupCloseText: 'Close',
smartSelectPickerCloseText: 'Done',
smartSelectSearchbar: false,
smartSelectBackOnSelect: false,
// Tap Navbar or Statusbar to scroll to top
scrollTopOnNavbarClick: false,
scrollTopOnStatusbarClick: false,
// Panels
swipePanel: false, // or 'left' or 'right'
swipePanelActiveArea: 0,
swipePanelCloseOpposite: true,
swipePanelOnlyClose: false,
swipePanelNoFollow: false,
swipePanelThreshold: 0,
panelsCloseByOutside: true,
// Modals
modalButtonOk: 'OK',
modalButtonCancel: 'Cancel',
modalUsernamePlaceholder: 'Username',
modalPasswordPlaceholder: 'Password',
modalTitle: 'Framework7',
modalCloseByOutside: false,
actionsCloseByOutside: true,
popupCloseByOutside: true,
modalPreloaderTitle: 'Loading... ',
modalStack: true,
// Lazy Load
imagesLazyLoadThreshold: 0,
imagesLazyLoadSequential: true,
// Name space
viewClass: 'view',
viewMainClass: 'view-main',
viewsClass: 'views',
// Notifications defaults
notificationCloseOnClick: false,
notificationCloseIcon: true,
notificationCloseButtonText: 'Close',
// Animate Pages
animatePages: true,
// Template7
templates: {},
template7Data: {},
template7Pages: false,
precompileTemplates: false,
// Material
material: false,
materialPageLoadDelay: 0,
materialPreloaderSvg: '<svg xmlns="http://www.w3.org/2000/svg" height="75" width="75" viewbox="0 0 75 75"><circle cx="37.5" cy="37.5" r="33.5" stroke-width="8"/></svg>',
materialPreloaderHtml:
'<span class="preloader-inner">' +
'<span class="preloader-inner-gap"></span>' +
'<span class="preloader-inner-left">' +
'<span class="preloader-inner-half-circle"></span>' +
'</span>' +
'<span class="preloader-inner-right">' +
'<span class="preloader-inner-half-circle"></span>' +
'</span>' +
'</span>',
materialRipple: true,
materialRippleElements: '.ripple, a.link, a.item-link, .button, .modal-button, .tab-link, .label-radio, .label-checkbox, .actions-modal-button, a.searchbar-clear, a.floating-button, .floating-button > a, .speed-dial-buttons a',
// Auto init
init: true,
};
// Extend defaults with parameters
for (var param in params) {
app.params[param] = params[param];
}
// DOM lib
var $ = Dom7;
// Template7 lib
var t7 = Template7;
app._compiledTemplates = {};
// App Root
app.root = $(app.params.root);
app.root.eq(0).addClass('framework7-root');
// Touch events
app.touchEvents = {
start: app.support.touch ? 'touchstart' : 'mousedown',
move: app.support.touch ? 'touchmove' : 'mousemove',
end: app.support.touch ? 'touchend' : 'mouseup'
};
// Link to local storage
app.ls = window.localStorage;
// RTL
app.rtl = $('body').css('direction') === 'rtl';
if (app.rtl) $('html').attr('dir', 'rtl');
// Overwrite statusbar overlay
if (typeof app.params.statusbarOverlay !== 'undefined') {
if (app.params.statusbarOverlay) $('html').addClass('with-statusbar-overlay');
else $('html').removeClass('with-statusbar-overlay');
}
/*======================================================
************ Views ************
======================================================*/
app.views = [];
var View = function (selector, params) {
var defaults = {
dynamicNavbar: false,
domCache: false,
linksView: undefined,
reloadPages: false,
uniqueHistory: app.params.uniqueHistory,
uniqueHistoryIgnoreGetParameters: app.params.uniqueHistoryIgnoreGetParameters,
allowDuplicateUrls: app.params.allowDuplicateUrls,
swipeBackPage: app.params.swipeBackPage,
swipeBackPageAnimateShadow: app.params.swipeBackPageAnimateShadow,
swipeBackPageAnimateOpacity: app.params.swipeBackPageAnimateOpacity,
swipeBackPageActiveArea: app.params.swipeBackPageActiveArea,
swipeBackPageThreshold: app.params.swipeBackPageThreshold,
animatePages: app.params.animatePages,
preloadPreviousPage: app.params.preloadPreviousPage
};
var i;
// Params
params = params || {};
// Disable dynamic navbar for material theme
if (params.dynamicNavbar && app.params.material) params.dynamicNavbar = false;
// Extend params with defaults
for (var def in defaults) {
if (typeof params[def] === 'undefined') {
params[def] = defaults[def];
}
}
// View
var view = this;
view.params = params;
// Selector
view.selector = selector;
// Container
var container = $(selector);
view.container = container[0];
// Fix Selector
if (typeof selector !== 'string') {
// Supposed to be HTMLElement or Dom7
selector = (container.attr('id') ? '#' + container.attr('id') : '') + (container.attr('class') ? '.' + container.attr('class').replace(/ /g, '.').replace('.active', '') : '');
view.selector = selector;
}
// Is main
view.main = container.hasClass(app.params.viewMainClass);
// Content cache
view.contentCache = {};
// Context cache
view.contextCache = {};
// Pages cache
view.pagesCache = {};
view.pageElementsCache = {};
// Store View in element for easy access
container[0].f7View = view;
// Pages
view.pagesContainer = container.find('.pages')[0];
view.initialPages = [];
view.initialPagesUrl = [];
view.initialNavbars = [];
if (view.params.domCache) {
var initialPages = container.find('.page');
for (i = 0; i < initialPages.length; i++) {
view.initialPages.push(initialPages[i]);
view.initialPagesUrl.push('#' + initialPages.eq(i).attr('data-page'));
}
if (view.params.dynamicNavbar) {
var initialNavbars = container.find('.navbar-inner');
for (i = 0; i < initialNavbars.length; i++) {
view.initialNavbars.push(initialNavbars[i]);
}
}
}
view.allowPageChange = true;
// Location
var docLocation = document.location.href;
// History
view.history = [];
var viewURL = docLocation;
var pushStateSeparator = app.params.pushStateSeparator;
var pushStateRoot = app.params.pushStateRoot;
if (app.params.pushState && view.main) {
if (pushStateRoot) {
viewURL = pushStateRoot;
}
else {
if (pushStateSeparator && viewURL.indexOf(pushStateSeparator) >= 0 && viewURL.indexOf(pushStateSeparator + '#') < 0) viewURL = viewURL.split(pushStateSeparator)[0];
}
}
// Active Page
var currentPage, currentPageData;
if (!view.activePage) {
currentPage = $(view.pagesContainer).find('.page-on-center');
if (currentPage.length === 0) {
currentPage = $(view.pagesContainer).find('.page:not(.cached)');
currentPage = currentPage.eq(currentPage.length - 1);
}
if (currentPage.length > 0) {
currentPageData = currentPage[0].f7PageData;
}
}
// View startup URL
if (view.params.domCache && currentPage) {
view.url = container.attr('data-url') || view.params.url || '#' + currentPage.attr('data-page');
view.pagesCache[view.url] = currentPage.attr('data-page');
}
else view.url = container.attr('data-url') || view.params.url || viewURL;
// Update current page Data
if (currentPageData) {
currentPageData.view = view;
currentPageData.url = view.url;
if (view.params.domCache && view.params.dynamicNavbar && !currentPageData.navbarInnerContainer) {
currentPageData.navbarInnerContainer = view.initialNavbars[view.initialPages.indexOf(currentPageData.container)];
}
view.activePage = currentPageData;
currentPage[0].f7PageData = currentPageData;
}
// Store to history main view's url
if (view.url) {
view.history.push(view.url);
}
// Touch events
var isTouched = false,
isMoved = false,
touchesStart = {},
isScrolling,
activePage = [],
previousPage = [],
viewContainerWidth,
touchesDiff,
allowViewTouchMove = true,
touchStartTime,
activeNavbar = [],
previousNavbar = [],
activeNavElements,
previousNavElements,
activeNavBackIcon,
previousNavBackIcon,
dynamicNavbar,
pageShadow,
el;
view.handleTouchStart = function (e) {
if (!allowViewTouchMove || !view.params.swipeBackPage || isTouched || app.swipeoutOpenedEl || !view.allowPageChange) return;
isMoved = false;
isTouched = true;
isScrolling = undefined;
touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
touchStartTime = (new Date()).getTime();
dynamicNavbar = view.params.dynamicNavbar && container.find('.navbar-inner').length > 1;
};
view.handleTouchMove = function (e) {
if (!isTouched) return;
var pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
if (typeof isScrolling === 'undefined') {
isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
}
if (isScrolling || e.f7PreventSwipeBack || app.preventSwipeBack) {
isTouched = false;
return;
}
if (!isMoved) {
var cancel = false;
// Calc values during first move fired
viewContainerWidth = container.width();
var target = $(e.target);
var swipeout = target.hasClass('swipeout') ? target : target.parents('.swipeout');
if (swipeout.length > 0) {
if (!app.rtl && swipeout.find('.swipeout-actions-left').length > 0) cancel = true;
if (app.rtl && swipeout.find('.swipeout-actions-right').length > 0) cancel = true;
}
activePage = target.is('.page') ? target : target.parents('.page');
if (activePage.hasClass('no-swipeback')) cancel = true;
previousPage = container.find('.page-on-left:not(.cached)');
var notFromBorder = touchesStart.x - container.offset().left > view.params.swipeBackPageActiveArea;
if (app.rtl) {
notFromBorder = touchesStart.x < container.offset().left - container[0].scrollLeft + viewContainerWidth - view.params.swipeBackPageActiveArea;
}
else {
notFromBorder = touchesStart.x - container.offset().left > view.params.swipeBackPageActiveArea;
}
if (notFromBorder) cancel = true;
if (previousPage.length === 0 || activePage.length === 0) cancel = true;
if (cancel) {
isTouched = false;
return;
}
if (view.params.swipeBackPageAnimateShadow && !app.device.android) {
pageShadow = activePage.find('.swipeback-page-shadow');
if (pageShadow.length === 0) {
pageShadow = $('<div class="swipeback-page-shadow"></div>');
activePage.append(pageShadow);
}
}
if (dynamicNavbar) {
activeNavbar = container.find('.navbar-on-center:not(.cached)');
previousNavbar = container.find('.navbar-on-left:not(.cached)');
activeNavElements = activeNavbar.find('.left, .center, .right, .subnavbar, .fading');
previousNavElements = previousNavbar.find('.left, .center, .right, .subnavbar, .fading');
if (app.params.animateNavBackIcon) {
activeNavBackIcon = activeNavbar.find('.left.sliding .back .icon');
previousNavBackIcon = previousNavbar.find('.left.sliding .back .icon');
}
}
// Close/Hide Any Picker
if ($('.picker-modal.modal-in').length > 0) {
app.closeModal($('.picker-modal.modal-in'));
}
}
e.f7PreventPanelSwipe = true;
isMoved = true;
e.preventDefault();
// RTL inverter
var inverter = app.rtl ? -1 : 1;
// Touches diff
touchesDiff = (pageX - touchesStart.x - view.params.swipeBackPageThreshold) * inverter;
if (touchesDiff < 0) touchesDiff = 0;
var percentage = touchesDiff / viewContainerWidth;
// Swipe Back Callback
var callbackData = {
percentage: percentage,
activePage: activePage[0],
previousPage: previousPage[0],
activeNavbar: activeNavbar[0],
previousNavbar: previousNavbar[0]
};
if (view.params.onSwipeBackMove) {
view.params.onSwipeBackMove(callbackData);
}
container.trigger('swipeBackMove', callbackData);
// Transform pages
var activePageTranslate = touchesDiff * inverter;
var previousPageTranslate = (touchesDiff / 5 - viewContainerWidth / 5) * inverter;
if (app.device.pixelRatio === 1) {
activePageTranslate = Math.round(activePageTranslate);
previousPageTranslate = Math.round(previousPageTranslate);
}
activePage.transform('translate3d(' + activePageTranslate + 'px,0,0)');
if (view.params.swipeBackPageAnimateShadow && !app.device.android) pageShadow[0].style.opacity = 1 - 1 * percentage;
previousPage.transform('translate3d(' + previousPageTranslate + 'px,0,0)');
if (view.params.swipeBackPageAnimateOpacity) previousPage[0].style.opacity = 0.9 + 0.1 * percentage;
// Dynamic Navbars Animation
if (dynamicNavbar) {
var i;
for (i = 0; i < activeNavElements.length; i++) {
el = $(activeNavElements[i]);
if (!el.is('.subnavbar.sliding')) el[0].style.opacity = (1 - percentage * 1.3);
if (el[0].className.indexOf('sliding') >= 0) {
var activeNavTranslate = percentage * el[0].f7NavbarRightOffset;
if (app.device.pixelRatio === 1) activeNavTranslate = Math.round(activeNavTranslate);
el.transform('translate3d(' + activeNavTranslate + 'px,0,0)');
if (app.params.animateNavBackIcon) {
if (el[0].className.indexOf('left') >= 0 && activeNavBackIcon.length > 0) {
activeNavBackIcon.transform('translate3d(' + -activeNavTranslate + 'px,0,0)');
}
}
}
}
for (i = 0; i < previousNavElements.length; i++) {
el = $(previousNavElements[i]);
if (!el.is('.subnavbar.sliding')) el[0].style.opacity = percentage * 1.3 - 0.3;
if (el[0].className.indexOf('sliding') >= 0) {
var previousNavTranslate = el[0].f7NavbarLeftOffset * (1 - percentage);
if (app.device.pixelRatio === 1) previousNavTranslate = Math.round(previousNavTranslate);
el.transform('translate3d(' + previousNavTranslate + 'px,0,0)');
if (app.params.animateNavBackIcon) {
if (el[0].className.indexOf('left') >= 0 && previousNavBackIcon.length > 0) {
previousNavBackIcon.transform('translate3d(' + -previousNavTranslate + 'px,0,0)');
}
}
}
}
}
};
view.handleTouchEnd = function (e) {
if (!isTouched || !isMoved) {
isTouched = false;
isMoved = false;
return;
}
isTouched = false;
isMoved = false;
if (touchesDiff === 0) {
$([activePage[0], previousPage[0]]).transform('').css({opacity: '', boxShadow: ''});
if (dynamicNavbar) {
activeNavElements.transform('').css({opacity: ''});
previousNavElements.transform('').css({opacity: ''});
if (activeNavBackIcon && activeNavBackIcon.length > 0) activeNavBackIcon.transform('');
if (previousNavBackIcon && activeNavBackIcon.length > 0) previousNavBackIcon.transform('');
}
return;
}
var timeDiff = (new Date()).getTime() - touchStartTime;
var pageChanged = false;
// Swipe back to previous page
if (
timeDiff < 300 && touchesDiff > 10 ||
timeDiff >= 300 && touchesDiff > viewContainerWidth / 2
) {
activePage.removeClass('page-on-center').addClass('page-on-right');
previousPage.removeClass('page-on-left').addClass('page-on-center');
if (dynamicNavbar) {
activeNavbar.removeClass('navbar-on-center').addClass('navbar-on-right');
previousNavbar.removeClass('navbar-on-left').addClass('navbar-on-center');
}
pageChanged = true;
}
// Reset custom styles
// Add transitioning class for transition-duration
$([activePage[0], previousPage[0]]).transform('').css({opacity: '', boxShadow: ''}).addClass('page-transitioning');
if (dynamicNavbar) {
activeNavElements.css({opacity: ''})
.each(function () {
var translate = pageChanged ? this.f7NavbarRightOffset : 0;
var sliding = $(this);
sliding.transform('translate3d(' + translate + 'px,0,0)');
if (app.params.animateNavBackIcon) {
if (sliding.hasClass('left') && activeNavBackIcon.length > 0) {
activeNavBackIcon.addClass('page-transitioning').transform('translate3d(' + -translate + 'px,0,0)');
}
}
}).addClass('page-transitioning');
previousNavElements.transform('').css({opacity: ''}).each(function () {
var translate = pageChanged ? 0 : this.f7NavbarLeftOffset;
var sliding = $(this);
sliding.transform('translate3d(' + translate + 'px,0,0)');
if (app.params.animateNavBackIcon) {
if (sliding.hasClass('left') && previousNavBackIcon.length > 0) {
previousNavBackIcon.addClass('page-transitioning').transform('translate3d(' + -translate + 'px,0,0)');
}
}
}).addClass('page-transitioning');
}
allowViewTouchMove = false;
view.allowPageChange = false;
// Swipe Back Callback
var callbackData = {
activePage: activePage[0],
previousPage: previousPage[0],
activeNavbar: activeNavbar[0],
previousNavbar: previousNavbar[0]
};
if (pageChanged) {
// Update View's URL
var url = view.history[view.history.length - 2];
view.url = url;
// Page before animation callback
app.pageBackCallback('before', view, {pageContainer: activePage[0], url: url, position: 'center', newPage: previousPage, oldPage: activePage, swipeBack: true});
app.pageAnimCallback('before', view, {pageContainer: previousPage[0], url: url, position: 'left', newPage: previousPage, oldPage: activePage, swipeBack: true});
if (view.params.onSwipeBackBeforeChange) {
view.params.onSwipeBackBeforeChange(callbackData);
}
container.trigger('swipeBackBeforeChange', callbackData);
}
else {
if (view.params.onSwipeBackBeforeReset) {
view.params.onSwipeBackBeforeReset(callbackData);
}
container.trigger('swipeBackBeforeReset', callbackData);
}
activePage.transitionEnd(function () {
$([activePage[0], previousPage[0]]).removeClass('page-transitioning');
if (dynamicNavbar) {
activeNavElements.removeClass('page-transitioning').css({opacity: ''});
previousNavElements.removeClass('page-transitioning').css({opacity: ''});
if (activeNavBackIcon && activeNavBackIcon.length > 0) activeNavBackIcon.removeClass('page-transitioning');
if (previousNavBackIcon && previousNavBackIcon.length > 0) previousNavBackIcon.removeClass('page-transitioning');
}
allowViewTouchMove = true;
view.allowPageChange = true;
if (pageChanged) {
if (app.params.pushState && view.main) history.back();
// Page after animation callback
app.pageBackCallback('after', view, {pageContainer: activePage[0], url: url, position: 'center', newPage: previousPage, oldPage: activePage, swipeBack: true});
app.pageAnimCallback('after', view, {pageContainer: previousPage[0], url: url, position: 'left', newPage: previousPage, oldPage: activePage, swipeBack: true});
app.router.afterBack(view, activePage, previousPage);
if (view.params.onSwipeBackAfterChange) {
view.params.onSwipeBackAfterChange(callbackData);
}
container.trigger('swipeBackAfterChange', callbackData);
}
else {
if (view.params.onSwipeBackAfterReset) {
view.params.onSwipeBackAfterReset(callbackData);
}
container.trigger('swipeBackAfterReset', callbackData);
}
if (pageShadow && pageShadow.length > 0) pageShadow.remove();
});
};
view.attachEvents = function (detach) {
var action = detach ? 'off' : 'on';
var passiveListener = app.touchEvents.start === 'touchstart' && app.support.passiveListener ? {passive: true, capture: false} : false;
container[action](app.touchEvents.start, view.handleTouchStart, passiveListener);
container[action](app.touchEvents.move, view.handleTouchMove);
container[action](app.touchEvents.end, view.handleTouchEnd, passiveListener);
};
view.detachEvents = function () {
view.attachEvents(true);
};
// Init
if (view.params.swipeBackPage && !app.params.material) {
view.attachEvents();
}
// Add view to app
app.views.push(view);
if (view.main) app.mainView = view;
// Router
view.router = {
load: function (options) {
return app.router.load(view, options);
},
back: function (options) {
return app.router.back(view, options);
},
// Shortcuts
loadPage: function (options) {
options = options || {};
if (typeof options === 'string') {
var url = options;
options = {};
if (url && url.indexOf('#') === 0 && view.params.domCache) {
options.pageName = url.split('#')[1];
}
else options.url = url;
}
return app.router.load(view, options);
},
loadContent: function (content) {
return app.router.load(view, {content: content});
},
reloadPage: function (url) {
return app.router.load(view, {url: url, reload: true});
},
reloadContent: function (content) {
return app.router.load(view, {content: content, reload: true});
},
reloadPreviousPage: function (url) {
return app.router.load(view, {url: url, reloadPrevious: true, reload: true});
},
reloadPreviousContent: function (content) {
return app.router.load(view, {content: content, reloadPrevious: true, reload: true});
},
refreshPage: function () {
var options = {
url: view.url,
reload: true,
ignoreCache: true
};
if (options.url && options.url.indexOf('#') === 0) {
if (view.params.domCache && view.pagesCache[options.url]) {
options.pageName = view.pagesCache[options.url];
options.url = undefined;
delete options.url;
}
else if (view.contentCache[options.url]) {
options.content = view.contentCache[options.url];
options.url = undefined;
delete options.url;
}
}
return app.router.load(view, options);
},
refreshPreviousPage: function () {
var options = {
url: view.history[view.history.length - 2],
reload: true,
reloadPrevious: true,
ignoreCache: true
};
if (options.url && options.url.indexOf('#') === 0 && view.params.domCache && view.pagesCache[options.url]) {
options.pageName = view.pagesCache[options.url];
options.url = undefined;
delete options.url;
}
return app.router.load(view, options);
}
};
// Aliases for temporary backward compatibility
view.loadPage = view.router.loadPage;
view.loadContent = view.router.loadContent;
view.reloadPage = view.router.reloadPage;
view.reloadContent = view.router.reloadContent;
view.reloadPreviousPage = view.router.reloadPreviousPage;
view.reloadPreviousContent = view.router.reloadPreviousContent;
view.refreshPage = view.router.refreshPage;
view.refreshPreviousPage = view.router.refreshPreviousPage;
view.back = view.router.back;
// Bars methods
view.hideNavbar = function () {
return app.hideNavbar(container.find('.navbar'));
};
view.showNavbar = function () {
return app.showNavbar(container.find('.navbar'));
};
view.hideToolbar = function () {
return app.hideToolbar(container.find('.toolbar'));
};
view.showToolbar = function () {
return app.showToolbar(container.find('.toolbar'));
};
// Push State on load
if (app.params.pushState && app.params.pushStateOnLoad && view.main) {
var pushStateUrl;
var pushStateUrlSplit = docLocation.split(pushStateSeparator)[1];
if (pushStateRoot) {
pushStateUrl = docLocation.split(app.params.pushStateRoot + pushStateSeparator)[1];
}
else if (pushStateSeparator && docLocation.indexOf(pushStateSeparator) >= 0 && docLocation.indexOf(pushStateSeparator + '#') < 0) {
pushStateUrl = pushStateUrlSplit;
}
var pushStateAnimatePages = app.params.pushStateNoAnimation ? false : undefined;
var historyState = history.state;
if (pushStateUrl) {
if (pushStateUrl.indexOf('#') >= 0 && view.params.domCache && historyState && historyState.pageName && 'viewIndex' in historyState) {
app.router.load(view, {pageName: historyState.pageName, url: historyState.url, animatePages: pushStateAnimatePages, pushState: false});
}
else if (pushStateUrl.indexOf('#') >= 0 && view.params.domCache && view.initialPagesUrl.indexOf(pushStateUrl) >= 0) {
app.router.load(view, {pageName: pushStateUrl.replace('#',''), animatePages: pushStateAnimatePages, pushState: false});
}
else app.router.load(view, {url: pushStateUrl, animatePages: pushStateAnimatePages, pushState: false});
}
else if (view.params.domCache && docLocation.indexOf(pushStateSeparator + '#') >= 0) {
if (historyState && historyState.pageName && 'viewIndex' in historyState) {
app.router.load(view, {pageName: historyState.pageName, url: historyState.url, animatePages: pushStateAnimatePages, pushState: false});
}
else if (pushStateSeparator && pushStateUrlSplit.indexOf('#') === 0) {
if (view.initialPagesUrl.indexOf(pushStateUrlSplit)) {
app.router.load(view, {pageName: pushStateUrlSplit.replace('#', ''), animatePages: pushStateAnimatePages, pushState: false});
}
}
}
}
// Destroy
view.destroy = function () {
view.detachEvents();
view = undefined;
};
// Plugin hook
app.pluginHook('addView', view);
// Return view
return view;
};
app.addView = function (selector, params) {
return new View(selector, params);
};
app.getCurrentView = function (index) {
var popoverView = $('.popover.modal-in .view');
var popupView = $('.popup.modal-in .view');
var panelView = $('.panel.active .view');
var appViews = $('.views');
// Find active view as tab
var appView = appViews.children('.view');
// Propably in tabs or split view
if (appView.length > 1) {
if (appView.hasClass('tab')) {
// Tabs
appView = appViews.children('.view.active');
}
else {
// Split View, leave appView intact
}
}
if (popoverView.length > 0 && popoverView[0].f7View) return popoverView[0].f7View;
if (popupView.length > 0 && popupView[0].f7View) return popupView[0].f7View;
if (panelView.length > 0 && panelView[0].f7View) return panelView[0].f7View;
if (appView.length > 0) {
if (appView.length === 1 && appView[0].f7View) return appView[0].f7View;
if (appView.length > 1) {
var currentViews = [];
for (var i = 0; i < appView.length; i++) {
if (appView[i].f7View) currentViews.push(appView[i].f7View);
}
if (currentViews.length > 0 && typeof index !== 'undefined') return currentViews[index];
if (currentViews.length > 1) return currentViews;
if (currentViews.length === 1) return currentViews[0];
return undefined;
}
}
return undefined;
};
/*======================================================
************ Navbars && Toolbars ************
======================================================*/
// On Navbar Init Callback
app.navbarInitCallback = function (view, pageContainer, navbarContainer, navbarInnerContainer) {
if (!navbarContainer && navbarInnerContainer) navbarContainer = $(navbarInnerContainer).parent('.navbar')[0];
if (!navbarInnerContainer || navbarInnerContainer.f7NavbarInitialized && view && !view.params.domCache) return;
var navbarData = {
container: navbarContainer,
innerContainer: navbarInnerContainer
};
var pageData = pageContainer && pageContainer.f7PageData;
var eventData = {
page: pageData,
navbar: navbarData
};
if (navbarInnerContainer.f7NavbarInitialized && ((view && view.params.domCache) || (!view && $(navbarContainer).parents('.popup, .popover, .login-screen, .modal, .actions-modal, .picker-modal').length > 0))) {
// Reinit Navbar
app.reinitNavbar(navbarContainer, navbarInnerContainer);
// Plugin hook
app.pluginHook('navbarReinit', eventData);
// Event
$(navbarInnerContainer).trigger('navbarReinit', eventData);
return;
}
navbarInnerContainer.f7NavbarInitialized = true;
// Before Init
app.pluginHook('navbarBeforeInit', navbarData, pageData);
$(navbarInnerContainer).trigger('navbarBeforeInit', eventData);
// Initialize Navbar
app.initNavbar(navbarContainer, navbarInnerContainer);
// On init
app.pluginHook('navbarInit', navbarData, pageData);
$(navbarInnerContainer).trigger('navbarInit', eventData);
};
// Navbar Remove Callback
app.navbarRemoveCallback = function (view, pageContainer, navbarContainer, navbarInnerContainer) {
if (!navbarContainer && navbarInnerContainer) navbarContainer = $(navbarInnerContainer).parent('.navbar')[0];
var navbarData = {
container: navbarContainer,
innerContainer: navbarInnerContainer
};
var pageData;
if (pageContainer) {
pageData = pageContainer.f7PageData;
}
var eventData = {
page: pageData,
navbar: navbarData
};
app.pluginHook('navbarBeforeRemove', navbarData, pageData);
$(navbarInnerContainer).trigger('navbarBeforeRemove', eventData);
navbarData = null;
pageData = null;
};
app.initNavbar = function (navbarContainer, navbarInnerContainer) {
// Init Subnavbar Searchbar
if (app.initSearchbar) app.initSearchbar(navbarInnerContainer);
};
app.reinitNavbar = function (navbarContainer, navbarInnerContainer) {
// Re init navbar methods
};
app.initNavbarWithCallback = function (navbarContainer) {
navbarContainer = $(navbarContainer);
var viewContainer = navbarContainer.parents('.' + app.params.viewClass);
var view;
if (viewContainer.length === 0) return;
if (navbarContainer.parents('.navbar-through').length === 0 && viewContainer.find('.navbar-through').length === 0) return;
view = viewContainer[0].f7View || undefined;
navbarContainer.find('.navbar-inner').each(function () {
var navbarInnerContainer = this;
var pageContainer;
if ($(navbarInnerContainer).attr('data-page')) {
// For dom cache
pageContainer = viewContainer.find('.page[data-page="' + $(navbarInnerContainer).attr('data-page') + '"]')[0];
}
if (!pageContainer) {
var pages = viewContainer.find('.page');
if (pages.length === 1) {
pageContainer = pages[0];
}
else {
viewContainer.find('.page').each(function () {
if (this.f7PageData && this.f7PageData.navbarInnerContainer === navbarInnerContainer) {
pageContainer = this;
}
});
}
}
app.navbarInitCallback(view, pageContainer, navbarContainer[0], navbarInnerContainer);
});
};
// Size Navbars
app.sizeNavbars = function (viewContainer) {
if (app.params.material) return;
var navbarInner = viewContainer ? $(viewContainer).find('.navbar .navbar-inner:not(.cached)') : $('.navbar .navbar-inner:not(.cached)');
navbarInner.each(function () {
var n = $(this);
if (n.hasClass('cached')) return;
var left = app.rtl ? n.find('.right') : n.find('.left'),
right = app.rtl ? n.find('.left') : n.find('.right'),
center = n.find('.center'),
subnavbar = n.find('.subnavbar'),
noLeft = left.length === 0,
noRight = right.length === 0,
leftWidth = noLeft ? 0 : left.outerWidth(true),
rightWidth = noRight ? 0 : right.outerWidth(true),
centerWidth = center.outerWidth(true),
navbarStyles = n.styles(),
navbarWidth = n[0].offsetWidth - parseInt(navbarStyles.paddingLeft, 10) - parseInt(navbarStyles.paddingRight, 10),
onLeft = n.hasClass('navbar-on-left'),
currLeft, diff;
if (noRight) {
currLeft = navbarWidth - centerWidth;
}
if (noLeft) {
currLeft = 0;
}
if (!noLeft && !noRight) {
currLeft = (navbarWidth - rightWidth - centerWidth + leftWidth) / 2;
}
var requiredLeft = (navbarWidth - centerWidth) / 2;
if (navbarWidth - leftWidth - rightWidth > centerWidth) {
if (requiredLeft < leftWidth) {
requiredLeft = leftWidth;
}
if (requiredLeft + centerWidth > navbarWidth - rightWidth) {
requiredLeft = navbarWidth - rightWidth - centerWidth;
}
diff = requiredLeft - currLeft;
}
else {
diff = 0;
}
// RTL inverter
var inverter = app.rtl ? -1 : 1;
if (center.hasClass('sliding')) {
center[0].f7NavbarLeftOffset = -(currLeft + diff) * inverter;
center[0].f7NavbarRightOffset = (navbarWidth - currLeft - diff - centerWidth) * inverter;
if (onLeft) {
if (app.params.animateNavBackIcon) {
var activeNavbarBackLink = n.parent().find('.navbar-on-center').find('.left.sliding .back .icon ~ span');
if (activeNavbarBackLink.length > 0) {
center[0].f7NavbarLeftOffset += activeNavbarBackLink[0].offsetLeft;
}
}
center.transform('translate3d(' + center[0].f7NavbarLeftOffset + 'px, 0, 0)');
}
}
if (!noLeft && left.hasClass('sliding')) {
if (app.rtl) {
left[0].f7NavbarLeftOffset = -(navbarWidth - left[0].offsetWidth) / 2 * inverter;
left[0].f7NavbarRightOffset = leftWidth * inverter;
}
else {
left[0].f7NavbarLeftOffset = -leftWidth;
left[0].f7NavbarRightOffset = (navbarWidth - left[0].offsetWidth) / 2;
if (app.params.animateNavBackIcon && left.find('.back .icon').length > 0) {
left[0].f7NavbarRightOffset -= left.find('.back .icon')[0].offsetWidth;
}
}
if (onLeft) left.transform('translate3d(' + left[0].f7NavbarLeftOffset + 'px, 0, 0)');
}
if (!noRight && right.hasClass('sliding')) {
if (app.rtl) {
right[0].f7NavbarLeftOffset = -rightWidth * inverter;
right[0].f7NavbarRightOffset = (navbarWidth - right[0].offsetWidth) / 2 * inverter;
}
else {
right[0].f7NavbarLeftOffset = -(navbarWidth - right[0].offsetWidth) / 2;
right[0].f7NavbarRightOffset = rightWidth;
}
if (onLeft) right.transform('translate3d(' + right[0].f7NavbarLeftOffset + 'px, 0, 0)');
}
if (subnavbar.length && subnavbar.hasClass('sliding')) {
subnavbar[0].f7NavbarLeftOffset = app.rtl ? subnavbar[0].offsetWidth : -subnavbar[0].offsetWidth;
subnavbar[0].f7NavbarRightOffset = -subnavbar[0].f7NavbarLeftOffset;
}
// Center left
var centerLeft = diff;
if (app.rtl && noLeft && noRight && center.length > 0) centerLeft = -centerLeft;
center.css({left: centerLeft + 'px'});
});
};
// Hide/Show Navbars/Toolbars
app.hideNavbar = function (navbarContainer) {
$(navbarContainer).addClass('navbar-hidden');
return true;
};
app.showNavbar = function (navbarContainer) {
var navbar = $(navbarContainer);
navbar.addClass('navbar-hiding').removeClass('navbar-hidden').transitionEnd(function () {
navbar.removeClass('navbar-hiding');
});
return true;
};
app.hideToolbar = function (toolbarContainer) {
$(toolbarContainer).addClass('toolbar-hidden');
return true;
};
app.showToolbar = function (toolbarContainer) {
var toolbar = $(toolbarContainer);
toolbar.addClass('toolbar-hiding').removeClass('toolbar-hidden').transitionEnd(function () {
toolbar.removeClass('toolbar-hiding');
});
};
/*======================================================
************ Searchbar ************
======================================================*/
var Searchbar = function (container, params) {
var defaults = {
input: null,
clearButton: null,
cancelButton: null,
searchList: null,
searchIn: '.item-title',
searchBy: '',
found: null,
notFound: null,
overlay: null,
ignore: '.searchbar-ignore',
customSearch: false,
removeDiacritics: false,
hideDividers: true,
hideGroups: true,
/* Callbacks
onSearch
onEnable
onDisable
onClear
*/
};
params = params || {};
for (var def in defaults) {
if (typeof params[def] === 'undefined' || params[def] === null) {
params[def] = defaults[def];
}
}
// Instance
var s = this;
// Material
s.material = app.params.material;
// Params
s.params = params;
// Container
container = $(container);
s.container = container;
// Active
s.active = false;
// Input
s.input = s.params.input ? $(s.params.input) : s.container.find('input[type="search"]');
s.clearButton = s.params.clearButton ? $(s.params.clearButton) : s.container.find('.searchbar-clear');
s.cancelButton = s.params.cancelButton ? $(s.params.cancelButton) : s.container.find('.searchbar-cancel');
// Search List
s.searchList = $(s.params.searchList);
// Is Virtual List
s.isVirtualList = s.searchList.hasClass('virtual-list');
// Is In Page
s.pageContainer = s.container.parents('.page').eq(0);
// Overlay
if (!s.params.overlay) {
s.overlay = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-overlay') : $('.searchbar-overlay');
}
else {
s.overlay = $(s.params.overlay);
}
// Found and not found
if (!s.params.found) {
s.found = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-found') : $('.searchbar-found');
}
else {
s.found = $(s.params.found);
}
if (!s.params.notFound) {
s.notFound = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-not-found') : $('.searchbar-not-found');
}
else {
s.notFound = $(s.params.notFound);
}
// Set Cancel button
var cancelMarginProp = app.rtl ? 'margin-left' : 'margin-right';
var cancelButtonHasMargin = false;
s.setCancelButtonMargin = function () {
s.cancelButton.transition(0).show();
s.cancelButton.css(cancelMarginProp, -s.cancelButton[0].offsetWidth + 'px');
var clientLeft = s.cancelButton[0].clientLeft;
s.cancelButton.transition('');
cancelButtonHasMargin = true;
};
// Trigger
s.triggerEvent = function (eventName, callbackName, eventData) {
s.container.trigger(eventName, eventData);
if (s.searchList.length > 0) s.searchList.trigger(eventName, eventData);
if (callbackName && s.params[callbackName]) s.params[callbackName](s, eventData);
};
// Enable/disalbe
s.enable = function (e) {
function _enable() {
if ((s.searchList.length || s.params.customSearch) && !s.container.hasClass('searchbar-active') && !s.query) s.overlay.addClass('searchbar-overlay-active');
s.container.addClass('searchbar-active');
if (s.cancelButton.length > 0 && !s.material) {
if (!cancelButtonHasMargin) {
s.setCancelButtonMargin();
}
s.cancelButton.css(cancelMarginProp, '0px');
}
s.triggerEvent('enableSearch', 'onEnable');
s.active = true;
}
if (app.device.ios && !app.params.material && e && e.type === 'focus') {
setTimeout(function () {
_enable();
}, 400);
}
else {
_enable();
}
};
s.disable = function () {
s.input.val('').trigger('change');
s.container.removeClass('searchbar-active searchbar-not-empty');
if (s.cancelButton.length > 0 && !s.material) s.cancelButton.css(cancelMarginProp, -s.cancelButton[0].offsetWidth + 'px');
if (s.searchList.length || s.params.customSearch) s.overlay.removeClass('searchbar-overlay-active');
s.active = false;
function _disable() {
s.input.blur();
}
if (app.device.ios) {
setTimeout(function () {
_disable();
}, 400);
}
else {
_disable();
}
s.triggerEvent('disableSearch', 'onDisable');
};
// Clear
s.clear = function (e) {
if (!s.query && e && $(e.target).hasClass('searchbar-clear')) {
s.disable();
return;
}
s.input.val('').trigger('change').focus();
s.triggerEvent('clearSearch', 'onClear');
};
// Search
s.handleInput = function () {
setTimeout(function () {
var value = s.input.val().trim();
if ((s.searchList.length > 0 || s.params.customSearch) && (s.params.searchIn || s.isVirtualList)) s.search(value, true);
}, 0);
};
var previousQuery = '';
var virtualList;
s.search = function (query, internal) {
if (query.trim() === previousQuery) return;
previousQuery = query.trim();
if (!internal) {
if (!s.active) {
s.enable();
}
s.input.val(query);
}
s.query = s.value = query;
// Add active/inactive classes on overlay
if (query.length === 0) {
s.container.removeClass('searchbar-not-empty');
if (s.searchList.length && s.container.hasClass('searchbar-active')) s.overlay.addClass('searchbar-overlay-active');
}
else {
s.container.addClass('searchbar-not-empty');
if (s.searchList.length && s.container.hasClass('searchbar-active')) s.overlay.removeClass('searchbar-overlay-active');
}
if (s.params.customSearch) {
s.triggerEvent('search', 'onSearch', {query: query});
return;
}
var foundItems = [], _vlQuery;
if (s.isVirtualList) {
virtualList = s.searchList[0].f7VirtualList;
if (query.trim() === '') {
virtualList.resetFilter();
s.notFound.hide();
s.found.show();
return;
}
_vlQuery = s.params.removeDiacritics ? $.removeDiacritics(query) : query;
if (virtualList.params.searchAll) {
foundItems = virtualList.params.searchAll(_vlQuery, virtualList.items) || [];
}
else if (virtualList.params.searchByItem) {
for (var i = 0; i < virtualList.items.length; i++) {
if(virtualList.params.searchByItem(_vlQuery, i, virtualList.params.items[i])) {
foundItems.push(i);
}
}
}
}
else {
var values;
if (s.params.removeDiacritics) values = $.removeDiacritics(query.trim().toLowerCase()).split(' ');
else {
values = query.trim().toLowerCase().split(' ');
}
s.searchList.find('li').removeClass('hidden-by-searchbar').each(function (index, el) {
el = $(el);
var compareWithText = [];
el.find(s.params.searchIn).each(function () {
var itemText = $(this).text().trim().toLowerCase();
if (s.params.removeDiacritics) itemText = $.removeDiacritics(itemText);
compareWithText.push(itemText);
});
compareWithText = compareWithText.join(' ');
var wordsMatch = 0;
for (var i = 0; i < values.length; i++) {
if (compareWithText.indexOf(values[i]) >= 0) wordsMatch++;
}
if (wordsMatch !== values.length && !(s.params.ignore && el.is(s.params.ignore))) {
el.addClass('hidden-by-searchbar');
}
else {
foundItems.push(el[0]);
}
});
if (s.params.hideDividers) {
s.searchList.find('.item-divider, .list-group-title').each(function () {
var title = $(this);
var nextElements = title.nextAll('li');
var hide = true;
for (var i = 0; i < nextElements.length; i++) {
var nextEl = $(nextElements[i]);
if (nextEl.hasClass('list-group-title') || nextEl.hasClass('item-divider')) break;
if (!nextEl.hasClass('hidden-by-searchbar')) {
hide = false;
}
}
var ignore = s.params.ignore && title.is(s.params.ignore);
if (hide && !ignore) title.addClass('hidden-by-searchbar');
else title.removeClass('hidden-by-searchbar');
});
}
if (s.params.hideGroups) {
s.searchList.find('.list-group').each(function () {
var group = $(this);
var ignore = s.params.ignore && group.is(s.params.ignore);
var notHidden = group.find('li:not(.hidden-by-searchbar)');
if (notHidden.length === 0 && !ignore) {
group.addClass('hidden-by-searchbar');
}
else {
group.removeClass('hidden-by-searchbar');
}
});
}
}
s.triggerEvent('search', 'onSearch', {query: query, foundItems: foundItems});
if (foundItems.length === 0) {
s.notFound.show();
s.found.hide();
}
else {
s.notFound.hide();
s.found.show();
}
if (s.isVirtualList) {
virtualList.filterItems(foundItems);
}
};
// Events
function preventSubmit(e) {
e.preventDefault();
}
s.attachEvents = function (destroy) {
var method = destroy ? 'off' : 'on';
s.container[method]('submit', preventSubmit);
if (!s.material) s.cancelButton[method]('click', s.disable);
s.overlay[method]('click', s.disable);
s.input[method]('focus', s.enable);
s.input[method]('change keydown keypress keyup', s.handleInput);
s.clearButton[method]('click', s.clear);
};
s.detachEvents = function() {
s.attachEvents(true);
};
// Init Destroy
s.init = function () {
s.attachEvents();
};
s.destroy = function () {
if (!s) return;
s.detachEvents();
s = null;
};
// Init
s.init();
s.container[0].f7Searchbar = s;
return s;
};
app.searchbar = function (container, params) {
return new Searchbar(container, params);
};
app.initSearchbar = function (container) {
container = $(container);
var searchbar = container.hasClass('searchbar') ? container : container.find('.searchbar');
if (searchbar.length === 0) return;
if (!searchbar.hasClass('searchbar-init')) return;
var sb = app.searchbar(searchbar, searchbar.dataset());
function onBeforeRemove() {
if (sb) sb.destroy();
}
if (container.hasClass('page')) {
container.once('pageBeforeRemove', onBeforeRemove);
}
else if (container.hasClass('navbar-inner')) {
container.once('navbarBeforeRemove', onBeforeRemove);
}
};
/*======================================================
************ Messagebar ************
======================================================*/
var Messagebar = function (container, params) {
var defaults = {
textarea: null,
maxHeight: null,
};
params = params || {};
for (var def in defaults) {
if (typeof params[def] === 'undefined' || params[def] === null) {
params[def] = defaults[def];
}
}
// Instance
var m = this;
// Params
m.params = params;
// Container
m.container = $(container);
if (m.container.length === 0) return;
// Textarea
m.textarea = m.params.textarea ? $(m.params.textarea) : m.container.find('textarea');
// Is In Page
m.pageContainer = m.container.parents('.page').eq(0);
m.pageContent = m.pageContainer.find('.page-content');
// Initial Sizes
m.pageContentPadding = parseInt(m.pageContent.css('padding-bottom'));
m.initialBarHeight = m.container[0].offsetHeight;
m.initialAreaHeight = m.textarea[0].offsetHeight;
// Resize textarea
m.sizeTextarea = function () {
// Reset
m.textarea.css({'height': ''});
var height = m.textarea[0].offsetHeight;
var diff = height - m.textarea[0].clientHeight;
var scrollHeight = m.textarea[0].scrollHeight;
// Update
if (scrollHeight + diff > height) {
var newAreaHeight = scrollHeight + diff;
var newBarHeight = m.initialBarHeight + (newAreaHeight - m.initialAreaHeight);
var maxBarHeight = m.params.maxHeight || m.container.parents('.view')[0].offsetHeight - 88;
if (newBarHeight > maxBarHeight) {
newBarHeight = parseInt(maxBarHeight, 10);
newAreaHeight = newBarHeight - m.initialBarHeight + m.initialAreaHeight;
}
m.textarea.css('height', newAreaHeight + 'px');
m.container.css('height', newBarHeight + 'px');
var onBottom = (m.pageContent[0].scrollTop === m.pageContent[0].scrollHeight - m.pageContent[0].offsetHeight);
if (m.pageContent.length > 0) {
m.pageContent.css('padding-bottom', newBarHeight + 'px');
if (m.pageContent.find('.messages-new-first').length === 0 && onBottom) {
m.pageContent.scrollTop(m.pageContent[0].scrollHeight - m.pageContent[0].offsetHeight);
}
}
}
else {
if (m.pageContent.length > 0) {
m.container.css({'height': '', 'bottom': ''});
m.pageContent.css({'padding-bottom': ''});
}
}
};
// Clear
m.clear = function () {
m.textarea.val('').trigger('change');
};
m.value = function (value) {
if (typeof value === 'undefined') return m.textarea.val();
else m.textarea.val(value).trigger('change');
};
// Handle textarea
m.textareaTimeout = undefined;
m.handleTextarea = function (e) {
clearTimeout(m.textareaTimeout);
m.textareaTimeout = setTimeout(function () {
m.sizeTextarea();
}, 0);
};
//Events
function preventSubmit(e) {
e.preventDefault();
}
m.attachEvents = function (destroy) {
var method = destroy ? 'off' : 'on';
m.container[method]('submit', preventSubmit);
m.textarea[method]('change keydown keypress keyup paste cut', m.handleTextarea);
};
m.detachEvents = function () {
m.attachEvents(true);
};
// Init Destroy
m.init = function () {
m.attachEvents();
};
m.destroy = function () {
m.detachEvents();
m = null;
};
// Init
m.init();
m.container[0].f7Messagebar = m;
return m;
};
app.messagebar = function (container, params) {
return new Messagebar(container, params);
};
app.initPageMessagebar = function (pageContainer) {
pageContainer = $(pageContainer);
var messagebar = pageContainer.hasClass('messagebar') ? pageContainer : pageContainer.find('.messagebar');
if (messagebar.length === 0) return;
if (!messagebar.hasClass('messagebar-init')) return;
var mb = app.messagebar(messagebar, messagebar.dataset());
// Destroy on page remove
function pageBeforeRemove() {
mb.destroy();
pageContainer.off('pageBeforeRemove', pageBeforeRemove);
}
if (pageContainer.hasClass('page')) {
pageContainer.on('pageBeforeRemove', pageBeforeRemove);
}
};
/*======================================================
************ XHR ************
======================================================*/
// XHR Caching
app.cache = [];
app.removeFromCache = function (url) {
var index = false;
for (var i = 0; i < app.cache.length; i++) {
if (app.cache[i].url === url) index = i;
}
if (index !== false) app.cache.splice(index, 1);
};
// XHR
app.xhr = false;
app.get = function (url, view, ignoreCache, callback) {
// should we ignore get params or not
var _url = url;
if (app.params.cacheIgnoreGetParameters && url.indexOf('?') >= 0) {
_url = url.split('?')[0];
}
if (app.params.cache && !ignoreCache && url.indexOf('nocache') < 0 && app.params.cacheIgnore.indexOf(_url) < 0) {
// Check is the url cached
for (var i = 0; i < app.cache.length; i++) {
if (app.cache[i].url === _url) {
// Check expiration
if ((new Date()).getTime() - app.cache[i].time < app.params.cacheDuration) {
// Load from cache
callback(app.cache[i].content);
return false;
}
}
}
}
app.xhr = $.ajax({
url: url,
method: 'GET',
beforeSend: app.params.onAjaxStart,
complete: function (xhr) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0) {
if (app.params.cache) {
app.removeFromCache(_url);
app.cache.push({
url: _url,
time: (new Date()).getTime(),
content: xhr.responseText
});
}
callback(xhr.responseText, false);
}
else {
callback(xhr.responseText, true);
}
if (app.params.onAjaxComplete) app.params.onAjaxComplete(xhr);
},
error: function (xhr) {
callback(xhr.responseText, true);
if (app.params.onAjaxError) app.params.onAjaxError(xhr);
}
});
if (view) view.xhr = app.xhr;
return app.xhr;
};
/*======================================================
************ Pages ************
======================================================*/
// Page Callbacks API
app.pageCallbacks = {};
app.onPage = function (callbackName, pageName, callback) {
if (pageName && pageName.split(' ').length > 1) {
var pageNames = pageName.split(' ');
var returnCallbacks = [];
for (var i = 0; i < pageNames.length; i++) {
returnCallbacks.push(app.onPage(callbackName, pageNames[i], callback));
}
returnCallbacks.remove = function () {
for (var i = 0; i < returnCallbacks.length; i++) {
returnCallbacks[i].remove();
}
};
returnCallbacks.trigger = function () {
for (var i = 0; i < returnCallbacks.length; i++) {
returnCallbacks[i].trigger();
}
};
return returnCallbacks;
}
var callbacks = app.pageCallbacks[callbackName][pageName];
if (!callbacks) {
callbacks = app.pageCallbacks[callbackName][pageName] = [];
}
app.pageCallbacks[callbackName][pageName].push(callback);
return {
remove: function () {
var removeIndex;
for (var i = 0; i < callbacks.length; i++) {
if (callbacks[i].toString() === callback.toString()) {
removeIndex = i;
}
}
if (typeof removeIndex !== 'undefined') callbacks.splice(removeIndex, 1);
},
trigger: callback
};
};
//Create callbacks methods dynamically
function createPageCallback(callbackName) {
var capitalized = callbackName.replace(/^./, function (match) {
return match.toUpperCase();
});
app['onPage' + capitalized] = function (pageName, callback) {
return app.onPage(callbackName, pageName, callback);
};
}
var pageCallbacksNames = ('beforeInit init reinit beforeAnimation afterAnimation back afterBack beforeRemove').split(' ');
for (var i = 0; i < pageCallbacksNames.length; i++) {
app.pageCallbacks[pageCallbacksNames[i]] = {};
createPageCallback(pageCallbacksNames[i]);
}
app.triggerPageCallbacks = function (callbackName, pageName, pageData) {
var allPagesCallbacks = app.pageCallbacks[callbackName]['*'];
if (allPagesCallbacks) {
for (var j = 0; j < allPagesCallbacks.length; j++) {
allPagesCallbacks[j](pageData);
}
}
var callbacks = app.pageCallbacks[callbackName][pageName];
if (!callbacks || callbacks.length === 0) return;
for (var i = 0; i < callbacks.length; i++) {
callbacks[i](pageData);
}
};
// On Page Init Callback
app.pageInitCallback = function (view, params) {
var pageContainer = params.pageContainer;
if (!pageContainer) return;
if (pageContainer.f7PageInitialized && view && !view.params.domCache) return;
var pageQuery = params.query;
if (!pageQuery) {
if (params.url && params.url.indexOf('?') > 0) {
pageQuery = $.parseUrlQuery(params.url || '');
}
else if (pageContainer.f7PageData && pageContainer.f7PageData.query) {
pageQuery = pageContainer.f7PageData.query;
}
else {
pageQuery = {};
}
}
// Page Data
var pageData = {
container: pageContainer,
url: params.url,
query: pageQuery,
name: $(pageContainer).attr('data-page'),
view: view,
from: params.position,
context: params.context,
navbarInnerContainer: params.navbarInnerContainer,
fromPage: params.fromPage
};
if (params.fromPage && !params.fromPage.navbarInnerContainer && params.oldNavbarInnerContainer) {
params.fromPage.navbarInnerContainer = params.oldNavbarInnerContainer;
}
if (pageContainer.f7PageInitialized && ((view && view.params.domCache) || (!view && $(pageContainer).parents('.popup, .popover, .login-screen, .modal, .actions-modal, .picker-modal').length > 0))) {
// Reinit Page
app.reinitPage(pageContainer);
// Callbacks
app.pluginHook('pageReinit', pageData);
if (app.params.onPageReinit) app.params.onPageReinit(app, pageData);
app.triggerPageCallbacks('reinit', pageData.name, pageData);
$(pageData.container).trigger('pageReinit', {page: pageData});
return;
}
pageContainer.f7PageInitialized = true;
// Store pagedata in page
pageContainer.f7PageData = pageData;
// Update View's activePage
if (view && !params.preloadOnly && !params.reloadPrevious) {
// Add data-page on view
$(view.container).attr('data-page', pageData.name);
// Update View active page data
view.activePage = pageData;
}
// Before Init Callbacks
app.pluginHook('pageBeforeInit', pageData);
if (app.params.onPageBeforeInit) app.params.onPageBeforeInit(app, pageData);
app.triggerPageCallbacks('beforeInit', pageData.name, pageData);
$(pageData.container).trigger('pageBeforeInit', {page: pageData});
// Init page
app.initPage(pageContainer);
// Init Callback
app.pluginHook('pageInit', pageData);
if (app.params.onPageInit) app.params.onPageInit(app, pageData);
app.triggerPageCallbacks('init', pageData.name, pageData);
$(pageData.container).trigger('pageInit', {page: pageData});
};
app.pageRemoveCallback = function (view, pageContainer, position) {
var pageContext;
if (!pageContainer) return;
if (pageContainer.f7PageData) pageContext = pageContainer.f7PageData.context;
// Page Data
var pageData = {
container: pageContainer,
name: $(pageContainer).attr('data-page'),
view: view,
url: pageContainer.f7PageData && pageContainer.f7PageData.url,
query: pageContainer.f7PageData && pageContainer.f7PageData.query,
navbarInnerContainer: pageContainer.f7PageData && pageContainer.f7PageData.navbarInnerContainer,
from: position,
context: pageContext
};
// Before Init Callback
app.pluginHook('pageBeforeRemove', pageData);
if (app.params.onPageBeforeRemove) app.params.onPageBeforeRemove(app, pageData);
app.triggerPageCallbacks('beforeRemove', pageData.name, pageData);
$(pageData.container).trigger('pageBeforeRemove', {page: pageData});
pageData = null;
};
app.pageBackCallback = function (callback, view, params) {
// Page Data
var pageContainer = params.pageContainer;
var pageContext;
if (!pageContainer) return;
if (pageContainer.f7PageData) pageContext = pageContainer.f7PageData.context;
var pageData = {
container: pageContainer,
name: $(pageContainer).attr('data-page'),
url: pageContainer.f7PageData && pageContainer.f7PageData.url,
query: pageContainer.f7PageData && pageContainer.f7PageData.query,
view: view,
from: params.position,
context: pageContext,
navbarInnerContainer: pageContainer.f7PageData && pageContainer.f7PageData.navbarInnerContainer,
swipeBack: params.swipeBack
};
if (callback === 'after') {
app.pluginHook('pageAfterBack', pageData);
if (app.params.onPageAfterBack) app.params.onPageAfterBack(app, pageData);
app.triggerPageCallbacks('afterBack', pageData.name, pageData);
$(pageContainer).trigger('pageAfterBack', {page: pageData});
}
if (callback === 'before') {
app.pluginHook('pageBack', pageData);
if (app.params.onPageBack) app.params.onPageBack(app, pageData);
app.triggerPageCallbacks('back', pageData.name, pageData);
$(pageData.container).trigger('pageBack', {page: pageData});
}
};
app.pageAnimCallback = function (callback, view, params) {
var pageContainer = params.pageContainer;
var pageContext;
if (!pageContainer) return;
if (pageContainer.f7PageData) pageContext = pageContainer.f7PageData.context;
var pageQuery = params.query;
if (!pageQuery) {
if (params.url && params.url.indexOf('?') > 0) {
pageQuery = $.parseUrlQuery(params.url || '');
}
else if (pageContainer.f7PageData && pageContainer.f7PageData.query) {
pageQuery = pageContainer.f7PageData.query;
}
else {
pageQuery = {};
}
}
// Page Data
var pageData = {
container: pageContainer,
url: params.url,
query: pageQuery,
name: $(pageContainer).attr('data-page'),
view: view,
from: params.position,
context: pageContext,
swipeBack: params.swipeBack,
navbarInnerContainer: pageContainer.f7PageData && pageContainer.f7PageData.navbarInnerContainer,
fromPage: params.fromPage
};
var oldPage = params.oldPage,
newPage = params.newPage;
// Update page date
pageContainer.f7PageData = pageData;
if (callback === 'after') {
app.pluginHook('pageAfterAnimation', pageData);
if (app.params.onPageAfterAnimation) app.params.onPageAfterAnimation(app, pageData);
app.triggerPageCallbacks('afterAnimation', pageData.name, pageData);
$(pageData.container).trigger('pageAfterAnimation', {page: pageData});
}
if (callback === 'before') {
// Add data-page on view
$(view.container).attr('data-page', pageData.name);
// Update View's activePage
if (view) view.activePage = pageData;
// Hide/show navbar dynamically
if (newPage.hasClass('no-navbar') && !oldPage.hasClass('no-navbar')) {
view.hideNavbar();
}
if (!newPage.hasClass('no-navbar') && (oldPage.hasClass('no-navbar') || oldPage.hasClass('no-navbar-by-scroll'))) {
view.showNavbar();
}
// Hide/show navbar toolbar
if (newPage.hasClass('no-toolbar') && !oldPage.hasClass('no-toolbar')) {
view.hideToolbar();
}
if (!newPage.hasClass('no-toolbar') && (oldPage.hasClass('no-toolbar') || oldPage.hasClass('no-toolbar-by-scroll'))) {
view.showToolbar();
}
// Hide/show tabbar
var tabBar;
if (newPage.hasClass('no-tabbar') && !oldPage.hasClass('no-tabbar')) {
tabBar = $(view.container).find('.tabbar');
if (tabBar.length === 0) tabBar = $(view.container).parents('.' + app.params.viewsClass).find('.tabbar');
app.hideToolbar(tabBar);
}
if (!newPage.hasClass('no-tabbar') && (oldPage.hasClass('no-tabbar') || oldPage.hasClass('no-tabbar-by-scroll'))) {
tabBar = $(view.container).find('.tabbar');
if (tabBar.length === 0) tabBar = $(view.container).parents('.' + app.params.viewsClass).find('.tabbar');
app.showToolbar(tabBar);
}
oldPage.removeClass('no-navbar-by-scroll no-toolbar-by-scroll');
// Callbacks
app.pluginHook('pageBeforeAnimation', pageData);
if (app.params.onPageBeforeAnimation) app.params.onPageBeforeAnimation(app, pageData);
app.triggerPageCallbacks('beforeAnimation', pageData.name, pageData);
$(pageData.container).trigger('pageBeforeAnimation', {page: pageData});
}
};
// Init Page Events and Manipulations
app.initPage = function (pageContainer) {
pageContainer = $(pageContainer);
if (pageContainer.length === 0) return;
// Size navbars on page load
if (app.sizeNavbars) app.sizeNavbars(pageContainer.parents('.' + app.params.viewClass)[0]);
// Init messages
if (app.initPageMessages) app.initPageMessages(pageContainer);
// Init forms storage
if (app.initFormsStorage) app.initFormsStorage(pageContainer);
// Init smart select
if (app.initSmartSelects) app.initSmartSelects(pageContainer);
// Init slider
if (app.initPageSwiper) app.initPageSwiper(pageContainer);
// Init pull to refres
if (app.initPullToRefresh) app.initPullToRefresh(pageContainer);
// Init infinite scroll
if (app.initPageInfiniteScroll) app.initPageInfiniteScroll(pageContainer);
// Init searchbar
if (app.initSearchbar) app.initSearchbar(pageContainer);
// Init message bar
if (app.initPageMessagebar) app.initPageMessagebar(pageContainer);
// Init scroll toolbars
if (app.initPageScrollToolbars) app.initPageScrollToolbars(pageContainer);
// Init lazy images
if (app.initImagesLazyLoad) app.initImagesLazyLoad(pageContainer);
// Init progress bars
if (app.initPageProgressbar) app.initPageProgressbar(pageContainer);
// Init resizeable textareas
if (app.initPageResizableTextarea) app.initPageResizableTextarea(pageContainer);
// Init Material Preloader
if (app.params.material && app.initPageMaterialPreloader) app.initPageMaterialPreloader(pageContainer);
// Init Material Inputs
if (app.params.material && app.initPageMaterialInputs) app.initPageMaterialInputs(pageContainer);
// Init Material Tabbar
if (app.params.material && app.initPageMaterialTabbar) app.initPageMaterialTabbar(pageContainer);
};
app.reinitPage = function (pageContainer) {
pageContainer = $(pageContainer);
if (pageContainer.length === 0) return;
// Size navbars on page reinit
if (app.sizeNavbars) app.sizeNavbars(pageContainer.parents('.' + app.params.viewClass)[0]);
// Reinit slider
if (app.reinitPageSwiper) app.reinitPageSwiper(pageContainer);
// Reinit lazy load
if (app.reinitLazyLoad) app.reinitLazyLoad(pageContainer);
};
app.initPageWithCallback = function (pageContainer) {
pageContainer = $(pageContainer);
var viewContainer = pageContainer.parents('.' + app.params.viewClass);
if (viewContainer.length === 0) return;
var view = viewContainer[0].f7View || undefined;
var url = view && view.url ? view.url : undefined;
if (viewContainer && pageContainer.attr('data-page')) {
viewContainer.attr('data-page', pageContainer.attr('data-page'));
}
app.pageInitCallback(view, {pageContainer: pageContainer[0], url: url, position: 'center'});
};
/*======================================================
************ Navigation / Router ************
======================================================*/
app.router = {
_remove: function (el) {
if (app.params.routerRemoveTimeout || app.params.routerRemoveWithTimeout) {
setTimeout(function () {
$(el).remove();
}, 0);
}
else $(el).remove();
},
// Temporary DOM Element
temporaryDom: document.createElement('div'),
// Find page or navbar in passed container which are related to View
findElement: function (selector, container, view, notCached) {
container = $(container);
if (notCached) selector = selector + ':not(.cached)';
var found = container.find(selector);
if (found.length > 1) {
if (typeof view.selector === 'string') {
// Search in related view
found = container.find(view.selector + ' ' + selector);
}
if (found.length > 1) {
// Search in main view
found = container.find('.' + app.params.viewMainClass + ' ' + selector);
}
}
if (found.length === 1) return found;
else {
// Try to find non cached
if (!notCached) found = app.router.findElement(selector, container, view, true);
if (found && found.length === 1) return found;
if (found && found.length > 1) return $(found[0]);
else return undefined;
}
},
// Set pages classess for animationEnd
animatePages: function (leftPage, rightPage, direction, view) {
// Loading new page
var removeClasses = 'page-on-center page-on-right page-on-left';
if (direction === 'to-left') {
leftPage.removeClass(removeClasses).addClass('page-from-center-to-left');
rightPage.removeClass(removeClasses).addClass('page-from-right-to-center');
}
// Go back
if (direction === 'to-right') {
leftPage.removeClass(removeClasses).addClass('page-from-left-to-center');
rightPage.removeClass(removeClasses).addClass('page-from-center-to-right');
}
},
// Prepare navbar before animarion
prepareNavbar: function (newNavbarInner, oldNavbarInner, newNavbarPosition) {
$(newNavbarInner).find('.sliding').each(function () {
var sliding = $(this);
var slidingOffset = newNavbarPosition === 'right' ? this.f7NavbarRightOffset : this.f7NavbarLeftOffset;
if (app.params.animateNavBackIcon) {
if (sliding.hasClass('left') && sliding.find('.back .icon').length > 0) {
sliding.find('.back .icon').transform('translate3d(' + (-slidingOffset) + 'px,0,0)');
}
}
sliding.transform('translate3d(' + slidingOffset + 'px,0,0)');
});
},
// Set navbars classess for animation
animateNavbars: function (leftNavbarInner, rightNavbarInner, direction, view) {
// Loading new page
var removeClasses = 'navbar-on-right navbar-on-center navbar-on-left';
if (direction === 'to-left') {
rightNavbarInner.removeClass(removeClasses).addClass('navbar-from-right-to-center');
rightNavbarInner.find('.sliding').each(function () {
var sliding = $(this);
sliding.transform('translate3d(0px,0,0)');
if (app.params.animateNavBackIcon) {
if (sliding.hasClass('left') && sliding.find('.back .icon').length > 0) {
sliding.find('.back .icon').transform('translate3d(0px,0,0)');
}
}
});
leftNavbarInner.removeClass(removeClasses).addClass('navbar-from-center-to-left');
leftNavbarInner.find('.sliding').each(function () {
var sliding = $(this);
var rightText;
if (app.params.animateNavBackIcon) {
if (sliding.hasClass('center') && rightNavbarInner.find('.sliding.left .back .icon').length > 0) {
rightText = rightNavbarInner.find('.sliding.left .back span');
if (rightText.length > 0) this.f7NavbarLeftOffset += rightText[0].offsetLeft;
}
if (sliding.hasClass('left') && sliding.find('.back .icon').length > 0) {
sliding.find('.back .icon').transform('translate3d(' + (-this.f7NavbarLeftOffset) + 'px,0,0)');
}
}
sliding.transform('translate3d(' + (this.f7NavbarLeftOffset) + 'px,0,0)');
});
}
// Go back
if (direction === 'to-right') {
leftNavbarInner.removeClass(removeClasses).addClass('navbar-from-left-to-center');
leftNavbarInner.find('.sliding').each(function () {
var sliding = $(this);
sliding.transform('translate3d(0px,0,0)');
if (app.params.animateNavBackIcon) {
if (sliding.hasClass('left') && sliding.find('.back .icon').length > 0) {
sliding.find('.back .icon').transform('translate3d(0px,0,0)');
}
}
});
rightNavbarInner.removeClass(removeClasses).addClass('navbar-from-center-to-right');
rightNavbarInner.find('.sliding').each(function () {
var sliding = $(this);
if (app.params.animateNavBackIcon) {
if (sliding.hasClass('left') && sliding.find('.back .icon').length > 0) {
sliding.find('.back .icon').transform('translate3d(' + (-this.f7NavbarRightOffset) + 'px,0,0)');
}
}
sliding.transform('translate3d(' + (this.f7NavbarRightOffset) + 'px,0,0)');
});
}
},
preprocess: function(view, content, url, next) {
// Plugin hook
app.pluginHook('routerPreprocess', view, content, url, next);
// Preprocess by plugin
content = app.pluginProcess('preprocess', content);
if (view && view.params && view.params.preprocess) {
content = view.params.preprocess(content, url, next);
if (typeof content !== 'undefined') {
next(content);
}
}
else if (app.params.preprocess) {
content = app.params.preprocess(content, url, next);
if (typeof content !== 'undefined') {
next(content);
}
}
else {
next(content);
}
},
preroute: function(view, options, isBack) {
if (isBack) options.isBack = true;
app.pluginHook('routerPreroute', view, options);
if ((app.params.preroute && app.params.preroute(view, options) === false) || (view && view.params.preroute && view.params.preroute(view, options) === false)) {
return true;
}
else {
return false;
}
},
template7Render: function (view, options) {
var url = options.url,
content = options.content, //initial content
t7_rendered_content = options.content, // will be rendered using Template7
context = options.context, // Context data for Template7
contextName = options.contextName,
template = options.template, // Template 7 compiled template
pageName = options.pageName;
var t7_ctx, t7_template;
if (typeof content === 'string') {
if (url) {
if (app.template7Cache[url] && !options.ignoreCache) t7_template = t7.cache[url];
else {
t7_template = t7.compile(content);
t7.cache[url] = t7_template;
}
}
else t7_template = t7.compile(content);
}
else if (template) {
t7_template = template;
}
if (context) {
t7_ctx = context;
if (context && url) {
view.contextCache[url] = context;
}
}
else {
if (contextName) {
if (contextName.indexOf('.') >= 0) {
var _ctx_path = contextName.split('.');
var _ctx = t7.data[_ctx_path[0]];
for (var i = 1; i < _ctx_path.length; i++) {
if (_ctx_path[i]) _ctx = _ctx[_ctx_path[i]];
}
t7_ctx = _ctx;
}
else t7_ctx = t7.data[contextName];
}
if (!t7_ctx && url) {
t7_ctx = t7.data['url:' + url];
}
if (!t7_ctx && typeof content === 'string' && !template) {
//try to find by page name in content
var pageNameMatch = content.match(/(data-page=["'][^"^']*["'])/);
if (pageNameMatch) {
var page = pageNameMatch[0].split('data-page=')[1].replace(/['"]/g, '');
if (page) t7_ctx = t7.data['page:' + page];
}
}
if (!t7_ctx && template && t7.templates) {
// Try to find matched template name in t7.templates
for (var templateName in t7.templates) {
if (t7.templates[templateName] === template) t7_ctx = t7.data[templateName];
}
}
if (!t7_ctx && url && url in view.contextCache) {
t7_ctx = view.contextCache[url];
}
if (!t7_ctx) {
t7_ctx = {};
}
}
if (t7_template && t7_ctx) {
if (typeof t7_ctx === 'function') t7_ctx = t7_ctx();
if (url) {
// Extend data with URL query
var query = $.parseUrlQuery(url);
t7_ctx.url_query = {};
for (var key in query) {
t7_ctx.url_query[key] = query[key];
}
}
try {
t7_rendered_content = t7_template(t7_ctx);
}
catch (e) {
t7_rendered_content = '';
if (window.console && window.console.error) {
console.error(e);
}
}
}
return {content: t7_rendered_content, context: t7_ctx};
}
};
app.router._load = function (view, options) {
options = options || {};
var url = options.url,
content = options.content, //initial content
t7_rendered = {content: options.content},
template = options.template, // Template 7 compiled template
pageName = options.pageName,
viewContainer = $(view.container),
pagesContainer = $(view.pagesContainer),
animatePages = options.animatePages,
newPage, oldPage, pagesInView, i, oldNavbarInner, newNavbarInner, navbar, dynamicNavbar, reloadPosition,
isDynamicPage = typeof url === 'undefined' && content || template,
pushState = options.pushState,
pageElement = options.pageElement;
if (typeof animatePages === 'undefined') animatePages = view.params.animatePages;
// Plugin hook
app.pluginHook('routerLoad', view, options);
// Render with Template7
if (app.params.template7Pages && typeof content === 'string' || template) {
t7_rendered = app.router.template7Render(view, options);
if (t7_rendered.content && !content) {
content = t7_rendered.content;
}
}
app.router.temporaryDom.innerHTML = '';
// Parse DOM
if (!pageName && !pageElement) {
if ((typeof content === 'string') || (url && (typeof content === 'string'))) {
app.router.temporaryDom.innerHTML = t7_rendered.content;
} else {
if ('length' in content && content.length > 1) {
for (var ci = 0; ci < content.length; ci++) {
$(app.router.temporaryDom).append(content[ci]);
}
} else {
$(app.router.temporaryDom).append(content);
}
}
}
// Reload position
reloadPosition = options.reload && (options.reloadPrevious ? 'left' : 'center');
// Find new page
if (pageName) newPage = pagesContainer.find('.page[data-page="' + pageName + '"]');
else {
if (pageElement) newPage = $(pageElement);
else newPage = app.router.findElement('.page', app.router.temporaryDom, view);
}
// If page not found exit
if (!newPage || newPage.length === 0 || (pageName && view.activePage && view.activePage.name === pageName)) {
view.allowPageChange = true;
return;
}
newPage.addClass(options.reload ? 'page-on-' + reloadPosition : 'page-on-right');
// Find old page (should be the last one) and remove older pages
pagesInView = pagesContainer.children('.page:not(.cached)');
if (pageElement) {
pagesInView = pagesInView.filter(function (index, page) {
if (page !== pageElement) return page;
});
}
if (options.reload && options.reloadPrevious && pagesInView.length === 1) {
view.allowPageChange = true;
return;
}
if (options.reload) {
oldPage = pagesInView.eq(pagesInView.length - 1);
}
else {
if (pagesInView.length > 1) {
for (i = 0; i < pagesInView.length - 2; i++) {
if (!view.params.domCache) {
app.pageRemoveCallback(view, pagesInView[i], 'left');
app.router._remove(pagesInView[i]);
}
else {
$(pagesInView[i]).addClass('cached');
}
}
if (!view.params.domCache) {
app.pageRemoveCallback(view, pagesInView[i], 'left');
app.router._remove(pagesInView[i]);
}
else {
$(pagesInView[i]).addClass('cached');
}
}
oldPage = pagesContainer.children('.page:not(.cached)');
}
if (pageElement && oldPage.length > 1) {
oldPage = oldPage.filter(function (index, page) {
if (page !== pageElement) return page;
});
}
if(view.params.domCache || pageElement) newPage.removeClass('cached');
// Dynamic navbar
if (view.params.dynamicNavbar) {
dynamicNavbar = true;
// Find navbar
if (pageName) {
newNavbarInner = viewContainer.find('.navbar-inner[data-page="' + pageName + '"]');
}
else {
newNavbarInner = app.router.findElement('.navbar-inner', app.router.temporaryDom, view);
}
if (!newNavbarInner || newNavbarInner.length === 0) {
// Look in page
newNavbarInner = newPage.find('.navbar-inner');
if (!newNavbarInner || newNavbarInner.length === 0) {
// Set false
dynamicNavbar = false;
}
else {
if (newNavbarInner.parent('.navbar').length > 0) {
newNavbarInner.prependTo(newPage);
}
}
}
if (dynamicNavbar && newPage.find('.navbar').length > 0) {
app.router._remove(newPage.find('.navbar'));
}
navbar = viewContainer.children('.navbar');
if (options.reload) {
oldNavbarInner = navbar.find('.navbar-inner:not(.cached):last-child');
}
else {
oldNavbarInner = navbar.find('.navbar-inner:not(.cached)');
if (oldNavbarInner.length > 0) {
for (i = 0; i < oldNavbarInner.length - 1; i++) {
if (!view.params.domCache) {
app.navbarRemoveCallback(view, pagesInView[i], navbar[0], oldNavbarInner[i]);
app.router._remove(oldNavbarInner[i]);
}
else
$(oldNavbarInner[i]).addClass('cached');
}
if (!newNavbarInner && oldNavbarInner.length === 1) {
if (!view.params.domCache) {
app.navbarRemoveCallback(view, pagesInView[0], navbar[0], oldNavbarInner[0]);
app.router._remove(oldNavbarInner[0]);
}
else
$(oldNavbarInner[0]).addClass('cached');
}
oldNavbarInner = navbar.find('.navbar-inner:not(.cached)');
}
}
}
if (dynamicNavbar) {
newNavbarInner.addClass(options.reload ? 'navbar-on-' + reloadPosition : 'navbar-on-right');
if(view.params.domCache || pageElement) newNavbarInner.removeClass('cached');
newPage[0].f7RelatedNavbar = newNavbarInner[0];
newNavbarInner[0].f7RelatedPage = newPage[0];
}
// save content areas into view's cache
if (!url) {
var newPageName = pageName || newPage.attr('data-page');
if (isDynamicPage) url = '#' + app.params.dynamicPageUrl.replace(/{{name}}/g, newPageName).replace(/{{index}}/g, view.history.length - (options.reload ? 1 : 0));
else url = '#' + newPageName;
if (!view.params.domCache) {
view.contentCache[url] = content;
}
if (view.params.domCache && pageName) {
view.pagesCache[url] = pageName;
}
}
else if (url && pageElement) {
view.pageElementsCache[url] = {
page: newPage,
navbarInner: newNavbarInner
};
}
// Push State
if (app.params.pushState && !options.reloadPrevious && view.main) {
if (typeof pushState === 'undefined') pushState = true;
var pushStateRoot = app.params.pushStateRoot || '';
var method = options.reload ? 'replaceState' : 'pushState';
if (pushState) {
if (!isDynamicPage && !pageName) {
history[method]({url: url, viewIndex: app.views.indexOf(view)}, '', pushStateRoot + app.params.pushStateSeparator + url);
}
else if (isDynamicPage && content) {
history[method]({content: typeof content === 'string' ? content : '', url: url, viewIndex: app.views.indexOf(view)}, '', pushStateRoot + app.params.pushStateSeparator + url);
}
else if (pageName) {
history[method]({pageName: pageName, url: url, viewIndex: app.views.indexOf(view)}, '', pushStateRoot + app.params.pushStateSeparator + url);
}
}
}
// Update View history
view.url = url;
if (options.reload) {
var lastUrl = view.history[view.history.length - (options.reloadPrevious ? 2 : 1)];
if (lastUrl &&
lastUrl.indexOf('#') === 0 &&
lastUrl in view.contentCache &&
lastUrl !== url &&
view.history.indexOf(lastUrl) === -1) {
view.contentCache[lastUrl] = null;
delete view.contentCache[lastUrl];
}
else if (lastUrl &&
lastUrl in view.pageElementsCache &&
lastUrl !== url &&
(view.history.indexOf(lastUrl) === -1 || view.history.indexOf(lastUrl) === view.history.length - 1)) {
view.pageElementsCache[lastUrl] = null;
delete view.pageElementsCache[lastUrl];
}
if (lastUrl &&
lastUrl in view.contextCache &&
lastUrl !== url &&
(view.history.indexOf(lastUrl) === -1 || view.history.indexOf(lastUrl) === view.history.length - 1)) {
view.contextCache[lastUrl] = null;
delete view.contextCache[lastUrl];
}
view.history[view.history.length - (options.reloadPrevious ? 2 : 1)] = url;
}
else {
view.history.push(url);
}
// Unique history
var historyBecameUnique = false;
if (view.params.uniqueHistory) {
var _history = view.history;
var _url = url;
if (view.params.uniqueHistoryIgnoreGetParameters) {
_history = [];
_url = url.split('?')[0];
for (i = 0; i < view.history.length; i++) {
_history.push(view.history[i].split('?')[0]);
}
}
if (_history.indexOf(_url) !== _history.lastIndexOf(_url)) {
view.history = view.history.slice(0, _history.indexOf(_url));
view.history.push(url);
historyBecameUnique = true;
}
}
// Dom manipulations
if (options.reloadPrevious) {
oldPage = oldPage.prev('.page');
newPage.insertBefore(oldPage);
if (dynamicNavbar) {
oldNavbarInner = oldNavbarInner.prev('.navbar-inner');
newNavbarInner.insertAfter(oldNavbarInner);
}
}
else {
pagesContainer.append(newPage[0]);
if (dynamicNavbar) navbar.append(newNavbarInner[0]);
}
// Remove Old Page And Navbar
if (options.reload) {
if (view.params.domCache && view.initialPages.indexOf(oldPage[0]) >= 0) {
oldPage.addClass('cached');
if (dynamicNavbar) oldNavbarInner.addClass('cached');
}
else {
app.pageRemoveCallback(view, oldPage[0], reloadPosition);
if (dynamicNavbar) app.navbarRemoveCallback(view, oldPage[0], navbar[0], oldNavbarInner[0]);
app.router._remove(oldPage);
if (dynamicNavbar) app.router._remove(oldNavbarInner);
}
}
// Page Init Events
app.pageInitCallback(view, {
pageContainer: newPage[0],
url: url,
position: options.reload ? reloadPosition : 'right',
navbarInnerContainer: dynamicNavbar ? newNavbarInner && newNavbarInner[0] : undefined,
oldNavbarInnerContainer: dynamicNavbar ? oldNavbarInner && oldNavbarInner[0] : undefined,
context: t7_rendered.context,
query: options.query,
fromPage: oldPage && oldPage.length && oldPage[0].f7PageData,
reload: options.reload,
reloadPrevious: options.reloadPrevious
});
// Navbar init event
if (dynamicNavbar) {
app.navbarInitCallback(view, newPage[0], navbar[0], newNavbarInner[0], url, options.reload ? reloadPosition : 'right');
}
if (options.reload) {
view.allowPageChange = true;
if (historyBecameUnique) view.refreshPreviousPage();
return;
}
if (dynamicNavbar && animatePages) {
app.router.prepareNavbar(newNavbarInner, oldNavbarInner, 'right');
}
// Force reLayout
var clientLeft = newPage[0].clientLeft;
// Before Anim Callback
app.pageAnimCallback('before', view, {
pageContainer: newPage[0],
url: url,
position: 'right',
oldPage: oldPage,
newPage: newPage,
query: options.query,
fromPage: oldPage && oldPage.length && oldPage[0].f7PageData
});
function afterAnimation() {
view.allowPageChange = true;
newPage.removeClass('page-from-right-to-center page-on-right page-on-left').addClass('page-on-center');
oldPage.removeClass('page-from-center-to-left page-on-center page-on-right').addClass('page-on-left');
if (dynamicNavbar) {
newNavbarInner.removeClass('navbar-from-right-to-center navbar-on-left navbar-on-right').addClass('navbar-on-center');
oldNavbarInner.removeClass('navbar-from-center-to-left navbar-on-center navbar-on-right').addClass('navbar-on-left');
}
app.pageAnimCallback('after', view, {
pageContainer: newPage[0],
url: url,
position: 'right',
oldPage: oldPage,
newPage: newPage,
query: options.query,
fromPage: oldPage && oldPage.length && oldPage[0].f7PageData
});
if (app.params.pushState && view.main) app.pushStateClearQueue();
if (!(view.params.swipeBackPage || view.params.preloadPreviousPage)) {
if (view.params.domCache) {
oldPage.addClass('cached');
if (dynamicNavbar) oldNavbarInner.addClass('cached');
}
else {
if (!(url.indexOf('#') === 0 && newPage.attr('data-page').indexOf('smart-select-') === 0)) {
app.pageRemoveCallback(view, oldPage[0], 'left');
if (dynamicNavbar) app.navbarRemoveCallback(view, oldPage[0], navbar[0], oldNavbarInner[0]);
app.router._remove(oldPage);
if (dynamicNavbar) app.router._remove(oldNavbarInner);
}
}
}
if (view.params.uniqueHistory && historyBecameUnique) {
view.refreshPreviousPage();
}
}
if (animatePages) {
// Set pages before animation
if (app.params.material && app.params.materialPageLoadDelay) {
setTimeout(function () {
app.router.animatePages(oldPage, newPage, 'to-left', view);
}, app.params.materialPageLoadDelay);
}
else {
app.router.animatePages(oldPage, newPage, 'to-left', view);
}
// Dynamic navbar animation
if (dynamicNavbar) {
setTimeout(function() {
app.router.animateNavbars(oldNavbarInner, newNavbarInner, 'to-left', view);
}, 0);
}
newPage.animationEnd(function (e) {
afterAnimation();
});
}
else {
if (dynamicNavbar) newNavbarInner.find('.sliding, .sliding .back .icon').transform('');
afterAnimation();
}
};
app.router.load = function (view, options) {
options = options || {};
if (app.router.preroute(view, options)) {
return false;
}
var url = options.url;
var content = options.content;
var pageName = options.pageName;
var pageElement = options.pageElement;
if (pageName) {
if (pageName.indexOf('?') > 0) {
options.query = $.parseUrlQuery(pageName);
options.pageName = pageName = pageName.split('?')[0];
}
}
var template = options.template;
if (view.params.reloadPages === true) options.reload = true;
if (!view.allowPageChange) return false;
if (url && view.url === url && !options.reload && !view.params.allowDuplicateUrls) return false;
view.allowPageChange = false;
if (app.xhr && view.xhr && view.xhr === app.xhr) {
app.xhr.abort();
app.xhr = false;
}
function proceed(content) {
app.router.preprocess(view, content, url, function (content) {
options.content = content;
app.router._load(view, options);
});
}
if (content || pageName || pageElement) {
proceed(content);
return;
}
else if (template) {
app.router._load(view, options);
return;
}
if (!options.url || options.url === '#') {
view.allowPageChange = true;
return;
}
app.get(options.url, view, options.ignoreCache, function (content, error) {
if (error) {
view.allowPageChange = true;
return;
}
proceed(content);
});
};
app.router._back = function (view, options) {
options = options || {};
var url = options.url,
content = options.content,
t7_rendered = {content: options.content}, // will be rendered using Template7
template = options.template, // Template 7 compiled template
animatePages = options.animatePages,
preloadOnly = options.preloadOnly,
pushState = options.pushState,
ignoreCache = options.ignoreCache,
force = options.force,
pageName = options.pageName,
pageElement = options.pageElement;
var viewContainer = $(view.container),
pagesContainer = $(view.pagesContainer),
pagesInView = pagesContainer.children('.page:not(.cached)'),
oldPage, newPage, oldNavbarInner, newNavbarInner, navbar, navbarInners, dynamicNavbar, manipulateDom = true;
if (typeof animatePages === 'undefined') animatePages = view.params.animatePages;
app.pluginHook('routerBack', view, options);
// Render with Template7
if (app.params.template7Pages && typeof content === 'string' || template) {
t7_rendered = app.router.template7Render(view, options);
if (t7_rendered.content && !content) {
content = t7_rendered.content;
}
}
// Animation
function afterAnimation() {
app.pageBackCallback('after', view, {
pageContainer: oldPage[0],
url: url,
position: 'center',
oldPage: oldPage,
newPage: newPage,
});
app.pageAnimCallback('after', view, {
pageContainer: newPage[0],
url: url,
position: 'left',
oldPage: oldPage,
newPage: newPage,
query: options.query,
fromPage: oldPage && oldPage.length && oldPage[0].f7PageData
});
app.router.afterBack(view, oldPage[0], newPage[0]);
}
function animateBack() {
// Page before animation callback
app.pageBackCallback('before', view, {
pageContainer: oldPage[0],
url: url,
position: 'center',
oldPage: oldPage,
newPage: newPage,
});
app.pageAnimCallback('before', view, {
pageContainer: newPage[0],
url: url,
position: 'left',
oldPage: oldPage,
newPage: newPage,
query: options.query,
fromPage: oldPage && oldPage.length && oldPage[0].f7PageData
});
if (animatePages) {
// Set pages before animation
app.router.animatePages(newPage, oldPage, 'to-right', view);
// Dynamic navbar animation
if (dynamicNavbar) {
setTimeout(function () {
app.router.animateNavbars(newNavbarInner, oldNavbarInner, 'to-right', view);
}, 0);
}
newPage.animationEnd(function () {
afterAnimation();
});
}
else {
if (dynamicNavbar) newNavbarInner.find('.sliding, .sliding .back .icon').transform('');
afterAnimation();
}
}
function parseNewPage() {
app.router.temporaryDom.innerHTML = '';
// Parse DOM
if ((typeof content === 'string') || (url && (typeof content === 'string'))) {
app.router.temporaryDom.innerHTML = t7_rendered.content;
} else {
if ('length' in content && content.length > 1) {
for (var ci = 0; ci < content.length; ci++) {
$(app.router.temporaryDom).append(content[ci]);
}
} else {
$(app.router.temporaryDom).append(content);
}
}
if (pageElement) newPage = $(pageElement);
else newPage = app.router.findElement('.page', app.router.temporaryDom, view);
if (view.params.dynamicNavbar) {
// Find navbar
newNavbarInner = app.router.findElement('.navbar-inner', app.router.temporaryDom, view);
}
}
function setPages() {
// If pages not found or there are still more than one, exit
if (!newPage || newPage.length === 0) {
view.allowPageChange = true;
return;
}
if (view.params.dynamicNavbar && typeof dynamicNavbar === 'undefined') {
if (!newNavbarInner || newNavbarInner.length === 0) {
dynamicNavbar = false;
}
else {
dynamicNavbar = true;
}
}
newPage.addClass('page-on-left').removeClass('cached');
if (dynamicNavbar) {
navbar = viewContainer.children('.navbar');
navbarInners = navbar.find('.navbar-inner:not(.cached)');
newNavbarInner.addClass('navbar-on-left').removeClass('cached');
}
// Remove/hide previous page in force mode
if (force) {
var pageToRemove, navbarToRemove;
pageToRemove = $(pagesInView[pagesInView.length - 2]);
if (dynamicNavbar) navbarToRemove = $(pageToRemove[0] && pageToRemove[0].f7RelatedNavbar || navbarInners[navbarInners.length - 2]);
if (view.params.domCache && view.initialPages.indexOf(pageToRemove[0]) >= 0) {
if (pageToRemove.length && pageToRemove[0] !== newPage[0]) pageToRemove.addClass('cached');
if (dynamicNavbar && navbarToRemove.length && navbarToRemove[0] !== newNavbarInner[0]) {
navbarToRemove.addClass('cached');
}
}
else {
var removeNavbar = dynamicNavbar && navbarToRemove.length;
if (pageToRemove.length) {
app.pageRemoveCallback(view, pageToRemove[0], 'right');
if (removeNavbar) {
app.navbarRemoveCallback(view, pageToRemove[0], navbar[0], navbarToRemove[0]);
}
app.router._remove(pageToRemove);
if (removeNavbar) app.router._remove(navbarToRemove);
}
else if (removeNavbar) {
app.navbarRemoveCallback(view, pageToRemove[0], navbar[0], navbarToRemove[0]);
app.router._remove(navbarToRemove);
}
}
pagesInView = pagesContainer.children('.page:not(.cached)');
if (dynamicNavbar) {
navbarInners = viewContainer.children('.navbar').find('.navbar-inner:not(.cached)');
}
if (view.history.indexOf(url) >= 0) {
view.history = view.history.slice(0, view.history.indexOf(url) + 2);
}
else {
if (view.history[[view.history.length - 2]]) {
view.history[view.history.length - 2] = url;
}
else {
view.history.unshift(url);
}
}
}
oldPage = $(pagesInView[pagesInView.length - 1]);
if (view.params.domCache) {
if (oldPage[0] === newPage[0]) {
oldPage = pagesContainer.children('.page.page-on-center');
if (oldPage.length === 0 && view.activePage) oldPage = $(view.activePage.container);
}
}
if (dynamicNavbar && !oldNavbarInner) {
oldNavbarInner = $(navbarInners[navbarInners.length - 1]);
if (view.params.domCache) {
if (oldNavbarInner[0] === newNavbarInner[0]) {
oldNavbarInner = navbar.children('.navbar-inner.navbar-on-center:not(.cached)');
}
if (oldNavbarInner.length === 0) {
oldNavbarInner = navbar.children('.navbar-inner[data-page="'+oldPage.attr('data-page')+'"]');
}
}
if (oldNavbarInner.length === 0 || newNavbarInner[0] === oldNavbarInner[0]) dynamicNavbar = false;
}
if (dynamicNavbar) {
if (manipulateDom) newNavbarInner.insertBefore(oldNavbarInner);
newNavbarInner[0].f7RelatedPage = newPage[0];
newPage[0].f7RelatedNavbar = newNavbarInner[0];
}
if (manipulateDom) newPage.insertBefore(oldPage);
// Page Init Events
app.pageInitCallback(view, {
pageContainer: newPage[0],
url: url,
position: 'left',
navbarInnerContainer: dynamicNavbar ? newNavbarInner[0] : undefined,
oldNavbarInnerContainer: dynamicNavbar ? oldNavbarInner && oldNavbarInner[0] : undefined,
context: t7_rendered.context,
query: options.query,
fromPage: oldPage && oldPage.length && oldPage[0].f7PageData,
preloadOnly: preloadOnly
});
if (dynamicNavbar) {
app.navbarInitCallback(view, newPage[0], navbar[0], newNavbarInner[0], url, 'right');
}
if (dynamicNavbar && newNavbarInner.hasClass('navbar-on-left') && animatePages) {
app.router.prepareNavbar(newNavbarInner, oldNavbarInner, 'left');
}
if (preloadOnly) {
view.allowPageChange = true;
return;
}
// Update View's URL
view.url = url;
// Force reLayout
var clientLeft = newPage[0].clientLeft;
animateBack();
// Push state
if (app.params.pushState && view.main) {
if (typeof pushState === 'undefined') pushState = true;
if (!preloadOnly && history.state && pushState) {
history.back();
}
}
return;
}
// Simple go back when we have pages on left
if (pagesInView.length > 1 && !force) {
// Exit if only preloadOnly
if (preloadOnly) {
view.allowPageChange = true;
return;
}
// Update View's URL
view.url = view.history[view.history.length - 2];
url = view.url;
// Define old and new pages
newPage = $(pagesInView[pagesInView.length - 2]);
oldPage = $(pagesInView[pagesInView.length - 1]);
// Dynamic navbar
if (view.params.dynamicNavbar) {
dynamicNavbar = true;
// Find navbar
navbarInners = viewContainer.children('.navbar').find('.navbar-inner:not(.cached)');
newNavbarInner = $(navbarInners[0]);
oldNavbarInner = $(navbarInners[1]);
if (newNavbarInner.length === 0 || oldNavbarInner.length === 0 || oldNavbarInner[0] === newNavbarInner[0]) {
dynamicNavbar = false;
}
}
manipulateDom = false;
setPages();
return;
}
if (!force) {
// Go back when there is no pages on left
if (!preloadOnly) {
view.url = view.history[view.history.length - 2];
url = view.url;
}
if (content) {
parseNewPage();
setPages();
return;
}
else if (pageName) {
// Get dom cached pages
newPage = $(viewContainer).find('.page[data-page="' + pageName + '"]');
if (view.params.dynamicNavbar) {
newNavbarInner = $(viewContainer).children('.navbar').find('.navbar-inner[data-page="' + pageName + '"]');
if (newNavbarInner.length === 0 && newPage[0].f7RelatedNavbar) {
newNavbarInner = $(newPage[0].f7RelatedNavbar);
}
if (newNavbarInner.length === 0 && newPage[0].f7PageData) {
newNavbarInner = $(newPage[0].f7PageData.navbarInnerContainer);
}
}
setPages();
return;
}
else if (url && url in view.pageElementsCache) {
newPage = view.pageElementsCache[url].page;
newNavbarInner = view.pageElementsCache[url].navbarInner;
setPages();
return;
}
else {
view.allowPageChange = true;
return;
}
}
else {
if (url && url === view.url || pageName && view.activePage && view.activePage.name === pageName) {
view.allowPageChange = true;
return;
}
// Go back with force url
if (content) {
parseNewPage();
setPages();
return;
}
else if (pageName && view.params.domCache) {
if (pageName) url = '#' + pageName;
newPage = $(viewContainer).find('.page[data-page="' + pageName + '"]');
if (newPage[0].f7PageData && newPage[0].f7PageData.url) {
url = newPage[0].f7PageData.url;
}
if (view.params.dynamicNavbar) {
newNavbarInner = $(viewContainer).children('.navbar').find('.navbar-inner[data-page="' + pageName + '"]');
if (newNavbarInner.length === 0 && newPage[0].f7RelatedNavbar) {
newNavbarInner = $(newPage[0].f7RelatedNavbar);
}
if (newNavbarInner.length === 0 && newPage[0].f7PageData) {
newNavbarInner = $(newPage[0].f7PageData.navbarInnerContainer);
}
}
setPages();
return;
}
else if (pageElement && url) {
newPage = $(pageElement);
if (view.params.dynamicNavbar) {
newNavbarInner = newPage.find('.navbar-inner');
if (newNavbarInner.length > 0) {
newPage.prepend(newNavbarInner);
app.router._remove(newPage.find('.navbar'));
}
}
setPages();
return;
}
else {
view.allowPageChange = true;
return;
}
}
};
app.router.back = function (view, options) {
options = options || {};
if (app.router.preroute(view, options, true)) {
return false;
}
var url = options.url;
var content = options.content;
var pageName = options.pageName;
var pageElement = options.pageElement;
if (pageName) {
if (pageName.indexOf('?') > 0) {
options.query = $.parseUrlQuery(pageName);
options.pageName = pageName = pageName.split('?')[0];
}
}
var force = options.force;
if (!view.allowPageChange) return false;
view.allowPageChange = false;
if (app.xhr && view.xhr && view.xhr === app.xhr) {
app.xhr.abort();
app.xhr = false;
}
var pagesInView = $(view.pagesContainer).find('.page:not(.cached)');
function proceed(content) {
app.router.preprocess(view, content, url, function (content) {
options.content = content;
app.router._back(view, options);
});
}
if (pagesInView.length > 1 && !force) {
// Simple go back to previos page in view
app.router._back(view, options);
return;
}
if (!force) {
url = view.history[view.history.length - 2] || options.url;
if (!options.url) options.url = url;
if (!url) {
view.allowPageChange = true;
return;
}
if (url.indexOf('#') === 0 && view.contentCache[url]) {
proceed(view.contentCache[url]);
return;
}
else if (url.indexOf('#') === 0 && view.params.domCache) {
if (!pageName) options.pageName = url.split('#')[1];
proceed();
return;
}
else if (url && url in view.pageElementsCache) {
proceed();
}
else if (url.indexOf('#') !== 0) {
// Load ajax page
app.get(options.url, view, options.ignoreCache, function (content, error) {
if (error) {
view.allowPageChange = true;
return;
}
proceed(content);
});
return;
}
}
else {
// Go back with force url
if (!url && content) {
proceed(content);
return;
}
else if (!url && pageName) {
if (pageName) url = '#' + pageName;
proceed();
return;
}
else if (url && pageElement) {
proceed();
return;
}
else if (url) {
app.get(options.url, view, options.ignoreCache, function (content, error) {
if (error) {
view.allowPageChange = true;
return;
}
proceed(content);
});
return;
}
}
view.allowPageChange = true;
return;
};
app.router.afterBack = function (view, oldPage, newPage) {
// Remove old page and set classes on new one
oldPage = $(oldPage);
newPage = $(newPage);
if (view.params.domCache && view.initialPages.indexOf(oldPage[0]) >= 0) {
oldPage.removeClass('page-from-center-to-right').addClass('cached');
}
else {
app.pageRemoveCallback(view, oldPage[0], 'right');
app.router._remove(oldPage);
}
newPage.removeClass('page-from-left-to-center page-on-left').addClass('page-on-center');
view.allowPageChange = true;
// Update View's History
var previousURL = view.history.pop();
var newNavbar;
// Updated dynamic navbar
if (view.params.dynamicNavbar) {
var inners = $(view.container).children('.navbar').find('.navbar-inner:not(.cached)');
var oldNavbar = $(oldPage[0].f7RelatedNavbar || inners[1]);
if (view.params.domCache && view.initialNavbars.indexOf(oldNavbar[0]) >= 0) {
oldNavbar.removeClass('navbar-from-center-to-right').addClass('cached');
}
else {
app.navbarRemoveCallback(view, oldPage[0], undefined, oldNavbar[0]);
app.router._remove(oldNavbar);
}
newNavbar = $(inners[0]).removeClass('navbar-on-left navbar-from-left-to-center').addClass('navbar-on-center');
}
// Remove pages in dom cache
if (view.params.domCache) {
$(view.container).find('.page.cached').each(function () {
var page = $(this);
var index = page.index();
var pageUrl = page[0].f7PageData && page[0].f7PageData.url;
if (pageUrl && view.history.indexOf(pageUrl) < 0 && view.initialPages.indexOf(this) < 0) {
app.pageRemoveCallback(view, page[0], 'right');
if (page[0].f7RelatedNavbar && view.params.dynamicNavbar) app.navbarRemoveCallback(view, page[0], undefined, page[0].f7RelatedNavbar);
app.router._remove(page);
if (page[0].f7RelatedNavbar && view.params.dynamicNavbar) app.router._remove(page[0].f7RelatedNavbar);
}
});
}
// Check previous page is content based only and remove it from content cache
if (!view.params.domCache &&
previousURL &&
previousURL.indexOf('#') > -1 &&
(previousURL in view.contentCache) &&
// If the same page is in the history multiple times, don't remove it.
view.history.indexOf(previousURL) === -1) {
view.contentCache[previousURL] = null;
delete view.contentCache[previousURL];
}
if (previousURL &&
(previousURL in view.pageElementsCache) &&
// If the same page is in the history multiple times, don't remove it.
view.history.indexOf(previousURL) === -1) {
view.pageElementsCache[previousURL] = null;
delete view.pageElementsCache[previousURL];
}
// Check for context cache
if (previousURL &&
(previousURL in view.contextCache) &&
// If the same page is in the history multiple times, don't remove it.
view.history.indexOf(previousURL) === -1) {
view.contextCache[previousURL] = null;
delete view.contextCache[previousURL];
}
if (app.params.pushState && view.main) app.pushStateClearQueue();
// Preload previous page
if (view.params.preloadPreviousPage) {
if (view.params.domCache && view.history.length > 1) {
var preloadUrl = view.history[view.history.length - 2];
var previousPage;
var previousNavbar;
if (preloadUrl && view.pagesCache[preloadUrl]) {
// Load by page name
previousPage = $(view.container).find('.page[data-page="' + view.pagesCache[preloadUrl] + '"]');
if (previousPage.next('.page')[0] !== newPage[0]) previousPage.insertBefore(newPage);
if (newNavbar) {
previousNavbar = $(view.container).children('.navbar').find('.navbar-inner[data-page="' + view.pagesCache[preloadUrl] + '"]');
if(!previousNavbar || previousNavbar.length === 0) previousNavbar = newNavbar.prev('.navbar-inner.cached');
if (previousNavbar.next('.navbar-inner')[0] !== newNavbar[0]) previousNavbar.insertBefore(newNavbar);
}
}
else {
// Just load previous page
previousPage = newPage.prev('.page.cached');
if (newNavbar) previousNavbar = newNavbar.prev('.navbar-inner.cached');
}
if (previousPage && previousPage.length > 0) previousPage.removeClass('cached page-on-right page-on-center').addClass('page-on-left');
if (previousNavbar && previousNavbar.length > 0) previousNavbar.removeClass('cached navbar-on-right navbar-on-center').addClass('navbar-on-left');
}
else {
app.router.back(view, {preloadOnly: true});
}
}
};
/*======================================================
************ Modals ************
======================================================*/
var _modalTemplateTempDiv = document.createElement('div');
app.modalStack = [];
app.modalStackClearQueue = function () {
if (app.modalStack.length) {
(app.modalStack.shift())();
}
};
app.modal = function (params) {
params = params || {};
var modalHTML = '';
if (app.params.modalTemplate) {
if (!app._compiledTemplates.modal) app._compiledTemplates.modal = t7.compile(app.params.modalTemplate);
modalHTML = app._compiledTemplates.modal(params);
}
else {
var buttonsHTML = '';
if (params.buttons && params.buttons.length > 0) {
for (var i = 0; i < params.buttons.length; i++) {
buttonsHTML += '<span class="modal-button' + (params.buttons[i].bold ? ' modal-button-bold' : '') + '">' + params.buttons[i].text + '</span>';
}
}
var titleHTML = params.title ? '<div class="modal-title">' + params.title + '</div>' : '';
var textHTML = params.text ? '<div class="modal-text">' + params.text + '</div>' : '';
var afterTextHTML = params.afterText ? params.afterText : '';
var noButtons = !params.buttons || params.buttons.length === 0 ? 'modal-no-buttons' : '';
var verticalButtons = params.verticalButtons ? 'modal-buttons-vertical': '';
var modalButtonsHTML = params.buttons && params.buttons.length > 0 ? '<div class="modal-buttons modal-buttons-' + params.buttons.length + ' ' + verticalButtons + '">' + buttonsHTML + '</div>' : '';
modalHTML = '<div class="modal ' + noButtons + ' ' + (params.cssClass || '') + '"><div class="modal-inner">' + (titleHTML + textHTML + afterTextHTML) + '</div>' + modalButtonsHTML + '</div>';
}
_modalTemplateTempDiv.innerHTML = modalHTML;
var modal = $(_modalTemplateTempDiv).children();
app.root.append(modal[0]);
// Add events on buttons
modal.find('.modal-button').each(function (index, el) {
$(el).on('click', function (e) {
if (params.buttons[index].close !== false) app.closeModal(modal);
if (params.buttons[index].onClick) params.buttons[index].onClick(modal, e);
if (params.onClick) params.onClick(modal, index);
});
});
app.openModal(modal);
return modal[0];
};
app.alert = function (text, title, callbackOk) {
if (typeof title === 'function') {
callbackOk = arguments[1];
title = undefined;
}
return app.modal({
text: text || '',
title: typeof title === 'undefined' ? app.params.modalTitle : title,
buttons: [ {text: app.params.modalButtonOk, bold: true, onClick: callbackOk} ]
});
};
app.confirm = function (text, title, callbackOk, callbackCancel) {
if (typeof title === 'function') {
callbackCancel = arguments[2];
callbackOk = arguments[1];
title = undefined;
}
return app.modal({
text: text || '',
title: typeof title === 'undefined' ? app.params.modalTitle : title,
buttons: [
{text: app.params.modalButtonCancel, onClick: callbackCancel},
{text: app.params.modalButtonOk, bold: true, onClick: callbackOk}
]
});
};
app.prompt = function (text, title, callbackOk, callbackCancel) {
if (typeof title === 'function') {
callbackCancel = arguments[2];
callbackOk = arguments[1];
title = undefined;
}
return app.modal({
text: text || '',
title: typeof title === 'undefined' ? app.params.modalTitle : title,
afterText: '<div class="input-field"><input type="text" class="modal-text-input"></div>',
buttons: [
{
text: app.params.modalButtonCancel
},
{
text: app.params.modalButtonOk,
bold: true
}
],
onClick: function (modal, index) {
if (index === 0 && callbackCancel) callbackCancel($(modal).find('.modal-text-input').val());
if (index === 1 && callbackOk) callbackOk($(modal).find('.modal-text-input').val());
}
});
};
app.modalLogin = function (text, title, callbackOk, callbackCancel) {
if (typeof title === 'function') {
callbackCancel = arguments[2];
callbackOk = arguments[1];
title = undefined;
}
return app.modal({
text: text || '',
title: typeof title === 'undefined' ? app.params.modalTitle : title,
afterText: '<div class="input-field modal-input-double"><input type="text" name="modal-username" placeholder="' + app.params.modalUsernamePlaceholder + '" class="modal-text-input"></div><div class="input-field modal-input-double"><input type="password" name="modal-password" placeholder="' + app.params.modalPasswordPlaceholder + '" class="modal-text-input"></div>',
buttons: [
{
text: app.params.modalButtonCancel
},
{
text: app.params.modalButtonOk,
bold: true
}
],
onClick: function (modal, index) {
var username = $(modal).find('.modal-text-input[name="modal-username"]').val();
var password = $(modal).find('.modal-text-input[name="modal-password"]').val();
if (index === 0 && callbackCancel) callbackCancel(username, password);
if (index === 1 && callbackOk) callbackOk(username, password);
}
});
};
app.modalPassword = function (text, title, callbackOk, callbackCancel) {
if (typeof title === 'function') {
callbackCancel = arguments[2];
callbackOk = arguments[1];
title = undefined;
}
return app.modal({
text: text || '',
title: typeof title === 'undefined' ? app.params.modalTitle : title,
afterText: '<div class="input-field"><input type="password" name="modal-password" placeholder="' + app.params.modalPasswordPlaceholder + '" class="modal-text-input"></div>',
buttons: [
{
text: app.params.modalButtonCancel
},
{
text: app.params.modalButtonOk,
bold: true
}
],
onClick: function (modal, index) {
var password = $(modal).find('.modal-text-input[name="modal-password"]').val();
if (index === 0 && callbackCancel) callbackCancel(password);
if (index === 1 && callbackOk) callbackOk(password);
}
});
};
app.showPreloader = function (title) {
return app.modal({
title: title || app.params.modalPreloaderTitle,
text: '<div class="preloader">' + (app.params.material ? app.params.materialPreloaderHtml : '') + '</div>',
cssClass: 'modal-preloader'
});
};
app.hidePreloader = function () {
app.closeModal('.modal.modal-in');
};
app.showIndicator = function () {
if ($('.preloader-indicator-overlay').length > 0) return;
app.root.append('<div class="preloader-indicator-overlay"></div><div class="preloader-indicator-modal"><span class="preloader preloader-white">' + (app.params.material ? app.params.materialPreloaderHtml : '') + '</span></div>');
};
app.hideIndicator = function () {
$('.preloader-indicator-overlay, .preloader-indicator-modal').remove();
};
// Action Sheet
app.actions = function (target, params) {
var toPopover = false, modal, groupSelector, buttonSelector;
if (arguments.length === 1) {
// Actions
params = target;
}
else {
// Popover
if (app.device.ios) {
if (app.device.ipad) toPopover = true;
}
else {
if ($(window).width() >= 768) toPopover = true;
}
}
params = params || [];
if (params.length > 0 && !$.isArray(params[0])) {
params = [params];
}
var modalHTML;
if (toPopover) {
var actionsToPopoverTemplate = app.params.modalActionsToPopoverTemplate ||
'<div class="popover actions-popover">' +
'<div class="popover-inner">' +
'{{#each this}}' +
'<div class="list-block">' +
'<ul>' +
'{{#each this}}' +
'{{#if label}}' +
'<li class="actions-popover-label {{#if color}}color-{{color}}{{/if}} {{#if bold}}actions-popover-bold{{/if}}">{{text}}</li>' +
'{{else}}' +
'<li><a href="#" class="item-link list-button {{#if color}}color-{{color}}{{/if}} {{#if bg}}bg-{{bg}}{{/if}} {{#if bold}}actions-popover-bold{{/if}} {{#if disabled}}disabled{{/if}}">{{text}}</a></li>' +
'{{/if}}' +
'{{/each}}' +
'</ul>' +
'</div>' +
'{{/each}}' +
'</div>' +
'</div>';
if (!app._compiledTemplates.actionsToPopover) {
app._compiledTemplates.actionsToPopover = t7.compile(actionsToPopoverTemplate);
}
var popoverHTML = app._compiledTemplates.actionsToPopover(params);
modal = $(app.popover(popoverHTML, target, true));
groupSelector = '.list-block ul';
buttonSelector = '.list-button';
}
else {
if (app.params.modalActionsTemplate) {
if (!app._compiledTemplates.actions) app._compiledTemplates.actions = t7.compile(app.params.modalActionsTemplate);
modalHTML = app._compiledTemplates.actions(params);
}
else {
var buttonsHTML = '';
for (var i = 0; i < params.length; i++) {
for (var j = 0; j < params[i].length; j++) {
if (j === 0) buttonsHTML += '<div class="actions-modal-group">';
var button = params[i][j];
var buttonClass = button.label ? 'actions-modal-label' : 'actions-modal-button';
if (button.bold) buttonClass += ' actions-modal-button-bold';
if (button.color) buttonClass += ' color-' + button.color;
if (button.bg) buttonClass += ' bg-' + button.bg;
if (button.disabled) buttonClass += ' disabled';
buttonsHTML += '<div class="' + buttonClass + '">' + button.text + '</div>';
if (j === params[i].length - 1) buttonsHTML += '</div>';
}
}
modalHTML = '<div class="actions-modal">' + buttonsHTML + '</div>';
}
_modalTemplateTempDiv.innerHTML = modalHTML;
modal = $(_modalTemplateTempDiv).children();
app.root.append(modal[0]);
groupSelector = '.actions-modal-group';
buttonSelector = '.actions-modal-button';
}
var groups = modal.find(groupSelector);
groups.each(function (index, el) {
var groupIndex = index;
$(el).children().each(function (index, el) {
var buttonIndex = index;
var buttonParams = params[groupIndex][buttonIndex];
var clickTarget;
if (!toPopover && $(el).is(buttonSelector)) clickTarget = $(el);
if (toPopover && $(el).find(buttonSelector).length > 0) clickTarget = $(el).find(buttonSelector);
if (clickTarget) {
clickTarget.on('click', function (e) {
if (buttonParams.close !== false) app.closeModal(modal);
if (buttonParams.onClick) buttonParams.onClick(modal, e);
});
}
});
});
if (!toPopover) app.openModal(modal);
return modal[0];
};
app.popover = function (modal, target, removeOnClose) {
if (typeof removeOnClose === 'undefined') removeOnClose = true;
if (typeof modal === 'string' && modal.indexOf('<') >= 0) {
var _modal = document.createElement('div');
_modal.innerHTML = modal.trim();
if (_modal.childNodes.length > 0) {
modal = _modal.childNodes[0];
if (removeOnClose) modal.classList.add('remove-on-close');
app.root.append(modal);
}
else return false; //nothing found
}
modal = $(modal);
target = $(target);
if (modal.length === 0 || target.length === 0) return false;
if (modal.parents('body').length === 0) {
if (removeOnClose) modal.addClass('remove-on-close');
app.root.append(modal[0]);
}
if (modal.find('.popover-angle').length === 0 && !app.params.material) {
modal.append('<div class="popover-angle"></div>');
}
modal.show();
var material = app.params.material;
function sizePopover() {
modal.css({left: '', top: ''});
var modalWidth = modal.width();
var modalHeight = modal.height(); // 13 - height of angle
var modalAngle, modalAngleSize = 0, modalAngleLeft, modalAngleTop;
if (!material) {
modalAngle = modal.find('.popover-angle');
modalAngleSize = modalAngle.width() / 2;
modalAngle.removeClass('on-left on-right on-top on-bottom').css({left: '', top: ''});
}
else {
modal.removeClass('popover-on-left popover-on-right popover-on-top popover-on-bottom').css({left: '', top: ''});
}
var targetWidth = target.outerWidth();
var targetHeight = target.outerHeight();
var targetOffset = target.offset();
var targetParentPage = target.parents('.page');
if (targetParentPage.length > 0) {
targetOffset.top = targetOffset.top - targetParentPage[0].scrollTop;
}
var windowHeight = $(window).height();
var windowWidth = $(window).width();
var modalTop = 0;
var modalLeft = 0;
var diff = 0;
// Top Position
var modalPosition = material ? 'bottom' : 'top';
if (material) {
if (modalHeight < windowHeight - targetOffset.top - targetHeight) {
// On bottom
modalPosition = 'bottom';
modalTop = targetOffset.top;
}
else if (modalHeight < targetOffset.top) {
// On top
modalTop = targetOffset.top - modalHeight + targetHeight;
modalPosition = 'top';
}
else {
// On middle
modalPosition = 'bottom';
modalTop = targetOffset.top;
}
if (modalTop <= 0) {
modalTop = 8;
}
else if (modalTop + modalHeight >= windowHeight) {
modalTop = windowHeight - modalHeight - 8;
}
// Horizontal Position
modalLeft = targetOffset.left;
if (modalLeft + modalWidth >= windowWidth - 8) {
modalLeft = targetOffset.left + targetWidth - modalWidth - 8;
}
if (modalLeft < 8) {
modalLeft = 8;
}
if (modalPosition === 'top') {
modal.addClass('popover-on-top');
}
if (modalPosition === 'bottom') {
modal.addClass('popover-on-bottom');
}
if (target.hasClass('floating-button-to-popover') && !modal.hasClass('modal-in')) {
modal.addClass('popover-floating-button');
var diffX = (modalLeft + modalWidth / 2) - (targetOffset.left + targetWidth / 2),
diffY = (modalTop + modalHeight / 2) - (targetOffset.top + targetHeight / 2);
target
.addClass('floating-button-to-popover-in')
.transform('translate3d(' + diffX + 'px, ' + diffY + 'px,0)')
.transitionEnd(function (e) {
if (!target.hasClass('floating-button-to-popover-in')) return;
target
.addClass('floating-button-to-popover-scale')
.transform('translate3d(' + diffX + 'px, ' + diffY + 'px,0) scale(' + (modalWidth/targetWidth) + ', ' + (modalHeight/targetHeight) + ')');
});
modal.once('close', function () {
target
.removeClass('floating-button-to-popover-in floating-button-to-popover-scale')
.addClass('floating-button-to-popover-out')
.transform('')
.transitionEnd(function (e) {
target.removeClass('floating-button-to-popover-out');
});
});
modal.once('closed', function () {
modal.removeClass('popover-floating-button');
});
}
}
else {
if ((modalHeight + modalAngleSize) < targetOffset.top) {
// On top
modalTop = targetOffset.top - modalHeight - modalAngleSize;
}
else if ((modalHeight + modalAngleSize) < windowHeight - targetOffset.top - targetHeight) {
// On bottom
modalPosition = 'bottom';
modalTop = targetOffset.top + targetHeight + modalAngleSize;
}
else {
// On middle
modalPosition = 'middle';
modalTop = targetHeight / 2 + targetOffset.top - modalHeight / 2;
diff = modalTop;
if (modalTop <= 0) {
modalTop = 5;
}
else if (modalTop + modalHeight >= windowHeight) {
modalTop = windowHeight - modalHeight - 5;
}
diff = diff - modalTop;
}
// Horizontal Position
if (modalPosition === 'top' || modalPosition === 'bottom') {
modalLeft = targetWidth / 2 + targetOffset.left - modalWidth / 2;
diff = modalLeft;
if (modalLeft < 5) modalLeft = 5;
if (modalLeft + modalWidth > windowWidth) modalLeft = windowWidth - modalWidth - 5;
if (modalPosition === 'top') {
modalAngle.addClass('on-bottom');
}
if (modalPosition === 'bottom') {
modalAngle.addClass('on-top');
}
diff = diff - modalLeft;
modalAngleLeft = (modalWidth / 2 - modalAngleSize + diff);
modalAngleLeft = Math.max(Math.min(modalAngleLeft, modalWidth - modalAngleSize * 2 - 13), 13);
modalAngle.css({left: modalAngleLeft + 'px'});
}
else if (modalPosition === 'middle') {
modalLeft = targetOffset.left - modalWidth - modalAngleSize;
modalAngle.addClass('on-right');
if (modalLeft < 5 || (modalLeft + modalWidth > windowWidth)) {
if (modalLeft < 5) modalLeft = targetOffset.left + targetWidth + modalAngleSize;
if (modalLeft + modalWidth > windowWidth) modalLeft = windowWidth - modalWidth - 5;
modalAngle.removeClass('on-right').addClass('on-left');
}
modalAngleTop = (modalHeight / 2 - modalAngleSize + diff);
modalAngleTop = Math.max(Math.min(modalAngleTop, modalHeight - modalAngleSize * 2 - 13), 13);
modalAngle.css({top: modalAngleTop + 'px'});
}
}
// Apply Styles
modal.css({top: modalTop + 'px', left: modalLeft + 'px'});
}
sizePopover();
$(window).on('resize', sizePopover);
modal.on('close', function () {
$(window).off('resize', sizePopover);
});
app.openModal(modal);
return modal[0];
};
app.popup = function (modal, removeOnClose) {
if (typeof removeOnClose === 'undefined') removeOnClose = true;
if (typeof modal === 'string' && modal.indexOf('<') >= 0) {
var _modal = document.createElement('div');
_modal.innerHTML = modal.trim();
if (_modal.childNodes.length > 0) {
modal = _modal.childNodes[0];
if (removeOnClose) modal.classList.add('remove-on-close');
app.root.append(modal);
}
else return false; //nothing found
}
modal = $(modal);
if (modal.length === 0) return false;
if (modal.parents('body').length === 0) {
if (removeOnClose) modal.addClass('remove-on-close');
app.root.append(modal[0]);
}
modal.show();
app.openModal(modal);
return modal[0];
};
app.pickerModal = function (modal, removeOnClose) {
if (typeof removeOnClose === 'undefined') removeOnClose = true;
if (typeof modal === 'string' && modal.indexOf('<') >= 0) {
modal = $(modal);
if (modal.length > 0) {
if (removeOnClose) modal.addClass('remove-on-close');
app.root.append(modal[0]);
}
else return false; //nothing found
}
modal = $(modal);
if (modal.length === 0) return false;
if (modal.parents('body').length === 0) {
if (removeOnClose) modal.addClass('remove-on-close');
app.root.append(modal[0]);
}
if ($('.picker-modal.modal-in:not(.modal-out)').length > 0 && !modal.hasClass('modal-in')) {
app.closeModal('.picker-modal.modal-in:not(.modal-out)');
}
modal.show();
app.openModal(modal);
return modal[0];
};
app.loginScreen = function (modal) {
if (!modal) modal = '.login-screen';
modal = $(modal);
if (modal.length === 0) return false;
if ($('.login-screen.modal-in:not(.modal-out)').length > 0 && !modal.hasClass('modal-in')) {
app.closeModal('.login-screen.modal-in:not(.modal-out)');
}
modal.show();
app.openModal(modal);
return modal[0];
};
app.openModal = function (modal) {
modal = $(modal);
var isModal = modal.hasClass('modal');
if ($('.modal.modal-in:not(.modal-out)').length && app.params.modalStack && isModal) {
app.modalStack.push(function () {
app.openModal(modal);
});
return;
}
// do nothing if this modal already shown
if (true === modal.data('f7-modal-shown')) {
return;
}
modal.data('f7-modal-shown', true);
modal.once('close', function() {
modal.removeData('f7-modal-shown');
});
var isPopover = modal.hasClass('popover');
var isPopup = modal.hasClass('popup');
var isLoginScreen = modal.hasClass('login-screen');
var isPickerModal = modal.hasClass('picker-modal');
if (isModal) {
modal.show();
modal.css({
marginTop: - Math.round(modal.outerHeight() / 2) + 'px'
});
}
var overlay;
if (!isLoginScreen && !isPickerModal) {
if ($('.modal-overlay').length === 0 && !isPopup) {
app.root.append('<div class="modal-overlay"></div>');
}
if ($('.popup-overlay').length === 0 && isPopup) {
app.root.append('<div class="popup-overlay"></div>');
}
overlay = isPopup ? $('.popup-overlay') : $('.modal-overlay');
}
if (app.params.material && isPickerModal) {
if (modal.hasClass('picker-calendar')) {
if ($('.picker-modal-overlay').length === 0 && !isPopup) {
app.root.append('<div class="picker-modal-overlay"></div>');
}
overlay = $('.picker-modal-overlay');
}
}
//Make sure that styles are applied, trigger relayout;
var clientLeft = modal[0].clientLeft;
// Trugger open event
modal.trigger('open');
// Picker modal body class
if (isPickerModal) {
$('body').addClass('with-picker-modal');
}
// Init Pages and Navbars in modal
if (modal.find('.' + app.params.viewClass).length > 0) {
modal.find('.page').each(function () {
app.initPageWithCallback(this);
});
modal.find('.navbar').each(function () {
app.initNavbarWithCallback(this);
});
}
// Classes for transition in
if (!isLoginScreen && !isPickerModal) overlay.addClass('modal-overlay-visible');
if (app.params.material && isPickerModal && overlay) overlay.addClass('modal-overlay-visible');
modal.removeClass('modal-out').addClass('modal-in').transitionEnd(function (e) {
if (modal.hasClass('modal-out')) modal.trigger('closed');
else modal.trigger('opened');
});
return true;
};
app.closeModal = function (modal) {
modal = $(modal || '.modal-in');
if (typeof modal !== 'undefined' && modal.length === 0) {
return;
}
var isModal = modal.hasClass('modal');
var isPopover = modal.hasClass('popover');
var isPopup = modal.hasClass('popup');
var isLoginScreen = modal.hasClass('login-screen');
var isPickerModal = modal.hasClass('picker-modal');
var removeOnClose = modal.hasClass('remove-on-close');
var overlay;
if (isPopup) overlay = $('.popup-overlay');
else {
if (isPickerModal && app.params.material) overlay = $('.picker-modal-overlay');
else if (!isPickerModal) overlay = $('.modal-overlay');
}
if (isPopup){
if (modal.length === $('.popup.modal-in').length) {
overlay.removeClass('modal-overlay-visible');
}
}
else if (overlay && overlay.length > 0) {
overlay.removeClass('modal-overlay-visible');
}
modal.trigger('close');
// Picker modal body class
if (isPickerModal) {
$('body').removeClass('with-picker-modal');
$('body').addClass('picker-modal-closing');
}
if (!(isPopover && !app.params.material)) {
modal.removeClass('modal-in').addClass('modal-out').transitionEnd(function (e) {
if (modal.hasClass('modal-out')) modal.trigger('closed');
else {
modal.trigger('opened');
if (isPopover) return;
}
if (isPickerModal) {
$('body').removeClass('picker-modal-closing');
}
if (isPopup || isLoginScreen || isPickerModal || isPopover) {
modal.removeClass('modal-out').hide();
if (removeOnClose && modal.length > 0) {
modal.remove();
}
}
else {
modal.remove();
}
});
if (isModal && app.params.modalStack) {
app.modalStackClearQueue();
}
}
else {
modal.removeClass('modal-in modal-out').trigger('closed').hide();
if (removeOnClose) {
modal.remove();
}
}
return true;
};
/*===============================================================================
************ Progress Bar ************
===============================================================================*/
app.setProgressbar = function (container, progress, speed) {
container = $(container || app.root);
if (container.length === 0) return;
if (progress) progress = Math.min(Math.max(progress, 0), 100);
var progressbar;
if (container.hasClass('progressbar')) progressbar = container;
else {
progressbar = container.children('.progressbar');
}
if (progressbar.length === 0 || progressbar.hasClass('progressbar-infinite')) return;
var clientLeft = progressbar[0].clientLeft;
progressbar.children('span').transform('translate3d(' + (-100 + progress) + '%,0,0)');
if (typeof speed !== 'undefined') {
progressbar.children('span').transition(speed);
}
else {
progressbar.children('span').transition('');
}
return progressbar[0];
};
app.showProgressbar = function (container, progress, color) {
if (typeof container === 'number') {
container = app.root;
progress = arguments[0];
color = arguments[1];
}
if (progress && typeof progress === 'string' && parseFloat(progress) !== progress * 1) {
color = progress;
progress = undefined;
}
container = $(container || app.root);
if (container.length === 0) return;
var progressbar;
if (container.hasClass('progressbar')) progressbar = container;
else {
progressbar = container.children('.progressbar:not(.progressbar-out), .progressbar-infinite:not(.progressbar-out)');
if (progressbar.length === 0) {
// Create one
if (typeof progress !== 'undefined') {
// Determined
progressbar = $('<span class="progressbar progressbar-in' + (color ? ' color-' + color : '') + '"><span></span></span>');
}
else {
// Infinite
progressbar = $('<span class="progressbar-infinite progressbar-in' + (color ? ' color-' + color : '') + '"></span>');
}
container.append(progressbar);
}
}
if (progress) app.setProgressbar(container, progress);
return progressbar[0];
};
app.hideProgressbar = function (container) {
container = $(container || app.root);
if (container.length === 0) return;
var progressbar;
if (container.hasClass('progressbar')) progressbar = container;
else {
progressbar = container.children('.progressbar, .progressbar-infinite');
}
if (progressbar.length === 0 || !progressbar.hasClass('progressbar-in') || progressbar.hasClass('progressbar-out')) return;
progressbar.removeClass('progressbar-in').addClass('progressbar-out').animationEnd(function () {
progressbar.remove();
progressbar = null;
});
return;
};
app.initPageProgressbar = function (pageContainer) {
pageContainer = $(pageContainer);
pageContainer.find('.progressbar').each(function () {
var p = $(this);
if (p.children('span').length === 0) p.append('<span></span>');
if (p.attr('data-progress')) app.setProgressbar(p, p.attr('data-progress'));
});
};
/*======================================================
************ Panels ************
======================================================*/
app.allowPanelOpen = true;
app.openPanel = function (panelPosition) {
if (!app.allowPanelOpen) return false;
var panel = $('.panel-' + panelPosition);
if (panel.length === 0 || panel.hasClass('active')) return false;
app.closePanel(); // Close if some panel is opened
app.allowPanelOpen = false;
var effect = panel.hasClass('panel-reveal') ? 'reveal' : 'cover';
panel.css({display: 'block'}).addClass('active');
panel.trigger('open');
if (app.params.material) {
$('.panel-overlay').show();
}
if (panel.find('.' + app.params.viewClass).length > 0) {
if (app.sizeNavbars) app.sizeNavbars(panel.find('.' + app.params.viewClass)[0]);
}
// Trigger reLayout
var clientLeft = panel[0].clientLeft;
// Transition End;
var transitionEndTarget = effect === 'reveal' ? $('.' + app.params.viewsClass) : panel;
var openedTriggered = false;
function panelTransitionEnd() {
transitionEndTarget.transitionEnd(function (e) {
if ($(e.target).is(transitionEndTarget)) {
if (panel.hasClass('active')) {
panel.trigger('opened');
}
else {
panel.trigger('closed');
}
if (app.params.material) $('.panel-overlay').css({display: ''});
app.allowPanelOpen = true;
}
else panelTransitionEnd();
});
}
panelTransitionEnd();
$('body').addClass('with-panel-' + panelPosition + '-' + effect);
return true;
};
app.closePanel = function () {
var activePanel = $('.panel.active');
if (activePanel.length === 0) return false;
var effect = activePanel.hasClass('panel-reveal') ? 'reveal' : 'cover';
var panelPosition = activePanel.hasClass('panel-left') ? 'left' : 'right';
activePanel.removeClass('active');
var transitionEndTarget = effect === 'reveal' ? $('.' + app.params.viewsClass) : activePanel;
activePanel.trigger('close');
app.allowPanelOpen = false;
transitionEndTarget.transitionEnd(function () {
if (activePanel.hasClass('active')) return;
activePanel.css({display: ''});
activePanel.trigger('closed');
$('body').removeClass('panel-closing');
app.allowPanelOpen = true;
});
$('body').addClass('panel-closing').removeClass('with-panel-' + panelPosition + '-' + effect);
};
/*======================================================
************ Swipe panels ************
======================================================*/
app.initSwipePanels = function () {
var panel, side;
if (app.params.swipePanel) {
panel = $('.panel.panel-' + app.params.swipePanel);
side = app.params.swipePanel;
if (panel.length === 0 && side !== 'both') return;
}
else {
if (app.params.swipePanelOnlyClose) {
if ($('.panel').length === 0) return;
}
else return;
}
var panelOverlay = $('.panel-overlay');
var isTouched, isMoved, isScrolling, touchesStart = {}, touchStartTime, touchesDiff, translate, overlayOpacity, opened, panelWidth, effect, direction;
var views = $('.' + app.params.viewsClass);
function handleTouchStart(e) {
if (!app.allowPanelOpen || (!app.params.swipePanel && !app.params.swipePanelOnlyClose) || isTouched) return;
if ($('.modal-in, .photo-browser-in').length > 0) return;
if (!(app.params.swipePanelCloseOpposite || app.params.swipePanelOnlyClose)) {
if ($('.panel.active').length > 0 && !panel.hasClass('active')) return;
}
touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
if (app.params.swipePanelCloseOpposite || app.params.swipePanelOnlyClose) {
if ($('.panel.active').length > 0) {
side = $('.panel.active').hasClass('panel-left') ? 'left' : 'right';
}
else {
if (app.params.swipePanelOnlyClose) return;
side = app.params.swipePanel;
}
if (!side) return;
}
panel = $('.panel.panel-' + side);
opened = panel.hasClass('active');
if (app.params.swipePanelActiveArea && !opened) {
if (side === 'left') {
if (touchesStart.x > app.params.swipePanelActiveArea) return;
}
if (side === 'right') {
if (touchesStart.x < window.innerWidth - app.params.swipePanelActiveArea) return;
}
}
isMoved = false;
isTouched = true;
isScrolling = undefined;
touchStartTime = (new Date()).getTime();
direction = undefined;
}
function handleTouchMove(e) {
if (!isTouched) return;
if (e.f7PreventPanelSwipe) return;
var pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
if (typeof isScrolling === 'undefined') {
isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
}
if (isScrolling) {
isTouched = false;
return;
}
if (!direction) {
if (pageX > touchesStart.x) {
direction = 'to-right';
}
else {
direction = 'to-left';
}
if(side === 'both'){
if ($('.panel.active').length > 0) {
side = $('.panel.active').hasClass('panel-left') ? 'left' : 'right';
}
else {
side = direction === 'to-right' ? 'left' : 'right';
}
panel = $('.panel.panel-' + side);
}
if (
side === 'left' &&
(
direction === 'to-left' && !panel.hasClass('active')
) ||
side === 'right' &&
(
direction === 'to-right' && !panel.hasClass('active')
)
)
{
isTouched = false;
return;
}
}
if (app.params.swipePanelNoFollow) {
var timeDiff = (new Date()).getTime() - touchStartTime;
if (timeDiff < 300) {
if (direction === 'to-left') {
if (side === 'right') app.openPanel(side);
if (side === 'left' && panel.hasClass('active')) app.closePanel();
}
if (direction === 'to-right') {
if (side === 'left') app.openPanel(side);
if (side === 'right' && panel.hasClass('active')) app.closePanel();
}
}
isTouched = false;
isMoved = false;
return;
}
if (!isMoved) {
effect = panel.hasClass('panel-cover') ? 'cover' : 'reveal';
if (!opened) {
panel.show();
panelOverlay.show();
}
panelWidth = panel[0].offsetWidth;
panel.transition(0);
if (panel.find('.' + app.params.viewClass).length > 0) {
if (app.sizeNavbars) app.sizeNavbars(panel.find('.' + app.params.viewClass)[0]);
}
}
isMoved = true;
e.preventDefault();
var threshold = opened ? 0 : -app.params.swipePanelThreshold;
if (side === 'right') threshold = -threshold;
touchesDiff = pageX - touchesStart.x + threshold;
if (side === 'right') {
translate = touchesDiff - (opened ? panelWidth : 0);
if (translate > 0) translate = 0;
if (translate < -panelWidth) {
translate = -panelWidth;
}
}
else {
translate = touchesDiff + (opened ? panelWidth : 0);
if (translate < 0) translate = 0;
if (translate > panelWidth) {
translate = panelWidth;
}
}
if (effect === 'reveal') {
views.transform('translate3d(' + translate + 'px,0,0)').transition(0);
panelOverlay.transform('translate3d(' + translate + 'px,0,0)').transition(0);
app.pluginHook('swipePanelSetTransform', views[0], panel[0], Math.abs(translate / panelWidth));
}
else {
panel.transform('translate3d(' + translate + 'px,0,0)').transition(0);
if (app.params.material) {
panelOverlay.transition(0);
overlayOpacity = Math.abs(translate/panelWidth);
panelOverlay.css({opacity: overlayOpacity});
}
app.pluginHook('swipePanelSetTransform', views[0], panel[0], Math.abs(translate / panelWidth));
}
}
function handleTouchEnd(e) {
if (!isTouched || !isMoved) {
isTouched = false;
isMoved = false;
return;
}
isTouched = false;
isMoved = false;
var timeDiff = (new Date()).getTime() - touchStartTime;
var action;
var edge = (translate === 0 || Math.abs(translate) === panelWidth);
if (!opened) {
if (translate === 0) {
action = 'reset';
}
else if (
timeDiff < 300 && Math.abs(translate) > 0 ||
timeDiff >= 300 && (Math.abs(translate) >= panelWidth / 2)
) {
action = 'swap';
}
else {
action = 'reset';
}
}
else {
if (translate === -panelWidth) {
action = 'reset';
}
else if (
timeDiff < 300 && Math.abs(translate) >= 0 ||
timeDiff >= 300 && (Math.abs(translate) <= panelWidth / 2)
) {
if (side === 'left' && translate === panelWidth) action = 'reset';
else action = 'swap';
}
else {
action = 'reset';
}
}
if (action === 'swap') {
app.allowPanelOpen = true;
if (opened) {
app.closePanel();
if (edge) {
panel.css({display: ''});
$('body').removeClass('panel-closing');
}
}
else {
app.openPanel(side);
}
if (edge) app.allowPanelOpen = true;
}
if (action === 'reset') {
if (opened) {
app.allowPanelOpen = true;
app.openPanel(side);
}
else {
app.closePanel();
if (edge) {
app.allowPanelOpen = true;
panel.css({display: ''});
}
else {
var target = effect === 'reveal' ? views : panel;
panel.trigger('close');
$('body').addClass('panel-closing');
target.transitionEnd(function () {
panel.trigger('closed');
panel.css({display: ''});
$('body').removeClass('panel-closing');
app.allowPanelOpen = true;
});
}
}
}
if (effect === 'reveal') {
views.transition('');
views.transform('');
}
panel.transition('').transform('');
panelOverlay.css({display: ''}).transform('').transition('').css('opacity', '');
}
var passiveListener = app.touchEvents.start === 'touchstart' && app.support.passiveListener ? {passive: true, capture: false} : false;
$(document).on(app.touchEvents.start, handleTouchStart, passiveListener);
$(document).on(app.touchEvents.move, handleTouchMove);
$(document).on(app.touchEvents.end, handleTouchEnd, passiveListener);
};
/*======================================================
************ Image Lazy Loading ************
************ Based on solution by Marc Godard, https://github.com/MarcGodard ************
======================================================*/
app.initImagesLazyLoad = function (pageContainer) {
pageContainer = $(pageContainer);
// Lazy images
var lazyLoadImages;
if (pageContainer.hasClass('lazy')) {
lazyLoadImages = pageContainer;
pageContainer = lazyLoadImages.parents('.page');
}
else {
lazyLoadImages = pageContainer.find('.lazy');
}
if (lazyLoadImages.length === 0) return;
// Scrollable page content
var pageContent;
if (pageContainer.hasClass('page-content')) {
pageContent = pageContainer;
pageContainer = pageContainer.parents('.page');
}
else {
pageContent = pageContainer.find('.page-content');
}
if (pageContent.length === 0) return;
// Placeholder
var placeholderSrc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEXCwsK592mkAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==';
if (typeof app.params.imagesLazyLoadPlaceholder === 'string') {
placeholderSrc = app.params.imagesLazyLoadPlaceholder;
}
if (app.params.imagesLazyLoadPlaceholder !== false) lazyLoadImages.each(function(){
if ($(this).attr('data-src')) $(this).attr('src', placeholderSrc);
});
// load image
var imagesSequence = [];
var imageIsLoading = false;
function loadImage(el) {
el = $(el);
var bg = el.attr('data-background');
var src = bg ? bg : el.attr('data-src');
if (!src) return;
function onLoad() {
el.removeClass('lazy').addClass('lazy-loaded');
if (bg) {
el.css('background-image', 'url(' + src + ')');
}
else {
el.attr('src', src);
}
if (app.params.imagesLazyLoadSequential) {
imageIsLoading = false;
if (imagesSequence.length > 0) {
loadImage(imagesSequence.shift());
}
}
}
if (app.params.imagesLazyLoadSequential) {
if (imageIsLoading) {
if (imagesSequence.indexOf(el[0]) < 0) imagesSequence.push(el[0]);
return;
}
}
// Loading flag
imageIsLoading = true;
var image = new Image();
image.onload = onLoad;
image.onerror = onLoad;
image.src =src;
}
function lazyHandler() {
lazyLoadImages = pageContainer.find('.lazy');
lazyLoadImages.each(function(index, el) {
el = $(el);
if (el.parents('.tab:not(.active)').length > 0) {
return;
}
if (isElementInViewport(el[0])) {
loadImage(el);
}
});
}
function isElementInViewport (el) {
var rect = el.getBoundingClientRect();
var threshold = app.params.imagesLazyLoadThreshold || 0;
return (
rect.top >= (0 - threshold) &&
rect.left >= (0 - threshold) &&
rect.top <= (window.innerHeight + threshold) &&
rect.left <= (window.innerWidth + threshold)
);
}
function attachEvents(destroy) {
var method = destroy ? 'off' : 'on';
lazyLoadImages[method]('lazy', lazyHandler);
lazyLoadImages.parents('.tab')[method]('show', lazyHandler);
pageContainer[method]('lazy', lazyHandler);
pageContent[method]('lazy', lazyHandler);
pageContent[method]('scroll', lazyHandler);
$(window)[method]('resize', lazyHandler);
}
function detachEvents() {
attachEvents(true);
}
// Store detach function
pageContainer[0].f7DestroyImagesLazyLoad = detachEvents;
// Attach events
attachEvents();
// Destroy on page remove
if (pageContainer.hasClass('page')) {
pageContainer.once('pageBeforeRemove', detachEvents);
}
// Run loader on page load/init
lazyHandler();
// Run after page animation
pageContainer.once('pageAfterAnimation', lazyHandler);
};
app.destroyImagesLazyLoad = function (pageContainer) {
pageContainer = $(pageContainer);
if (pageContainer.length > 0 && pageContainer[0].f7DestroyImagesLazyLoad) {
pageContainer[0].f7DestroyImagesLazyLoad();
}
};
app.reinitImagesLazyLoad = function (pageContainer) {
pageContainer = $(pageContainer);
if (pageContainer.length > 0) {
pageContainer.trigger('lazy');
}
};
/*======================================================
************ Material Preloader ************
======================================================*/
app.initPageMaterialPreloader = function (pageContainer) {
$(pageContainer).find('.preloader').each(function () {
if ($(this).children().length === 0) {
$(this).html(app.params.materialPreloaderHtml);
}
});
};
/*======================================================
************ Messages ************
======================================================*/
var Messages = function (container, params) {
var defaults = {
autoLayout: true,
newMessagesFirst: false,
scrollMessages: true,
scrollMessagesOnlyOnEdge: false,
messageTemplate:
'{{#if day}}' +
'<div class="messages-date">{{day}} {{#if time}}, <span>{{time}}</span>{{/if}}</div>' +
'{{/if}}' +
'<div class="message message-{{type}} {{#if hasImage}}message-pic{{/if}} {{#if avatar}}message-with-avatar{{/if}} {{#if position}}message-appear-from-{{position}}{{/if}}">' +
'{{#if name}}<div class="message-name">{{name}}</div>{{/if}}' +
'<div class="message-text">{{text}}{{#if date}}<div class="message-date">{{date}}</div>{{/if}}</div>' +
'{{#if avatar}}<div class="message-avatar" style="background-image:url({{avatar}})"></div>{{/if}}' +
'{{#if label}}<div class="message-label">{{label}}</div>{{/if}}' +
'</div>'
};
params = params || {};
for (var def in defaults) {
if (typeof params[def] === 'undefined' || params[def] === null) {
params[def] = defaults[def];
}
}
// Instance
var m = this;
// Params
m.params = params;
// Container
m.container = $(container);
if (m.container.length === 0) return;
// Autolayout
if (m.params.autoLayout) m.container.addClass('messages-auto-layout');
// New messages first
if (m.params.newMessagesFirst) m.container.addClass('messages-new-first');
// Is In Page
m.pageContainer = m.container.parents('.page').eq(0);
m.pageContent = m.pageContainer.find('.page-content');
// Compiled template
m.template = Template7.compile(m.params.messageTemplate);
// Auto Layout
m.layout = function () {
if (!m.container.hasClass('messages-auto-layout')) m.container.addClass('messages-auto-layout');
m.container.find('.message').each(function () {
var message = $(this);
if (message.find('.message-text img').length > 0) {
var childNodes = message.find('.message-text')[0].childNodes;
var onlyPic = true;
for (var i = 0 ; i < childNodes.length; i++) {
if (childNodes[i].nodeType === 1 && childNodes[i].nodeName.toLowerCase() !== 'img') onlyPic = false;
if (childNodes[i].nodeType === 3 && childNodes[i].textContent.trim() !== '') onlyPic = false;
}
if (onlyPic) message.addClass('message-pic');
else message.removeClass('message-pic');
}
if (message.find('.message-avatar').length > 0) message.addClass('message-with-avatar');
});
m.container.find('.message').each(function () {
var message = $(this);
var isSent = message.hasClass('message-sent');
var next = message.next('.message-' + (isSent ? 'sent' : 'received'));
var prev = message.prev('.message-' + (isSent ? 'sent' : 'received'));
if (next.length === 0) {
message.addClass('message-last message-with-tail');
}
else message.removeClass('message-last message-with-tail');
if (prev.length === 0) {
message.addClass('message-first');
}
else message.removeClass('message-first');
if (prev.length > 0 && prev.find('.message-name').length > 0 && message.find('.message-name').length > 0) {
if (prev.find('.message-name').text() !== message.find('.message-name').text()) {
prev.addClass('message-last message-with-tail');
message.addClass('message-first');
}
}
});
};
// Add Message
m.appendMessage = function (props, animate) {
return m.addMessage(props, 'append', animate);
};
m.prependMessage = function (props, animate) {
return m.addMessage(props, 'prepend', animate);
};
m.addMessage = function (props, method, animate) {
return m.addMessages([props], method, animate);
};
m.addMessages = function (newMessages, method, animate) {
if (typeof animate === 'undefined') {
animate = true;
}
if (typeof method === 'undefined') {
method = m.params.newMessagesFirst ? 'prepend' : 'append';
}
var newMessagesHTML = '', i;
for (i = 0; i < newMessages.length; i++) {
var props = newMessages[i] || {};
props.type = props.type || 'sent';
if (!props.text) continue;
props.hasImage = props.text.indexOf('<img') >= 0;
if (props.onlyImage === false) props.hasImage = false;
if (animate) props.position = method === 'append' ? 'bottom' : 'top';
newMessagesHTML += m.template(props);
}
var scrollHeightBefore = m.pageContent[0].scrollHeight,
heightBefore = m.pageContent[0].offsetHeight,
scrollBefore = m.pageContent[0].scrollTop;
m.container[method](newMessagesHTML);
if (m.params.autoLayout) m.layout();
if (method === 'prepend') {
m.pageContent[0].scrollTop = scrollBefore + (m.pageContent[0].scrollHeight - scrollHeightBefore);
}
if (m.params.scrollMessages && (method === 'append' && !m.params.newMessagesFirst) || (method === 'prepend' && m.params.newMessagesFirst)) {
if (m.params.scrollMessagesOnlyOnEdge) {
var onEdge = false;
if (m.params.newMessagesFirst) {
if (scrollBefore === 0) onEdge = true;
}
else {
if (scrollBefore - (scrollHeightBefore - heightBefore) >= -10) onEdge = true;
}
if (onEdge) m.scrollMessages(animate ? undefined : 0);
}
else m.scrollMessages(animate ? undefined : 0);
}
var messages = m.container.find('.message');
if (newMessages.length === 1) {
return method === 'append' ? messages[messages.length - 1] : messages[0];
}
else {
var messagesToReturn = [];
if (method === 'append') {
for (i = messages.length - newMessages.length; i < messages.length; i++) {
messagesToReturn.push(messages[i]);
}
}
else {
for (i = 0; i < newMessages.length; i++) {
messagesToReturn.push(messages[i]);
}
}
return messagesToReturn;
}
};
m.removeMessage = function (message) {
message = $(message);
if (message.length === 0) {
return false;
}
else {
message.remove();
if (m.params.autoLayout) m.layout();
return true;
}
};
m.removeMessages = function (messages) {
m.removeMessage(messages);
};
m.clean = function () {
m.container.html('');
};
// Scroll
m.scrollMessages = function (duration, scrollTop) {
if (typeof duration === 'undefined') duration = 400;
var currentScroll = m.pageContent[0].scrollTop;
var newScroll;
if (typeof scrollTop !== 'undefined') newScroll = scrollTop;
else {
newScroll = m.params.newMessagesFirst ? 0 : m.pageContent[0].scrollHeight - m.pageContent[0].offsetHeight;
if (newScroll === currentScroll) return;
}
m.pageContent.scrollTop(newScroll, duration);
};
// Init Destroy
m.init = function () {
if (m.params.messages) {
m.addMessages(m.params.messages, undefined, false);
}
else {
if (m.params.autoLayout) m.layout();
m.scrollMessages(0);
}
};
m.destroy = function () {
m = null;
};
// Init
m.init();
m.container[0].f7Messages = m;
return m;
};
app.messages = function (container, params) {
return new Messages (container, params);
};
app.initPageMessages = function (pageContainer) {
pageContainer = $(pageContainer);
var messages = pageContainer.find('.messages');
if (messages.length === 0) return;
if (!messages.hasClass('messages-init')) {
return;
}
var m = app.messages(messages, messages.dataset());
// Destroy on page remove
function pageBeforeRemove() {
m.destroy();
pageContainer.off('pageBeforeRemove', pageBeforeRemove);
}
if (pageContainer.hasClass('page')) {
pageContainer.on('pageBeforeRemove', pageBeforeRemove);
}
};
/*===============================================================================
************ Swipeout Actions (Swipe to delete) ************
===============================================================================*/
app.swipeoutOpenedEl = undefined;
app.allowSwipeout = true;
app.initSwipeout = function (swipeoutEl) {
var isTouched, isMoved, isScrolling, touchesStart = {}, touchStartTime, touchesDiff, swipeOutEl, swipeOutContent, actionsRight, actionsLeft, actionsLeftWidth, actionsRightWidth, translate, opened, openedActions, buttonsLeft, buttonsRight, direction, overswipeLeftButton, overswipeRightButton, overswipeLeft, overswipeRight, noFoldLeft, noFoldRight;
$(document).on(app.touchEvents.start, function (e) {
if (app.swipeoutOpenedEl) {
var target = $(e.target);
if (!(
app.swipeoutOpenedEl.is(target[0]) ||
target.parents('.swipeout').is(app.swipeoutOpenedEl) ||
target.hasClass('modal-in') ||
target.hasClass('modal-overlay') ||
target.hasClass('actions-modal') ||
target.parents('.actions-modal.modal-in, .modal.modal-in').length > 0
)) {
app.swipeoutClose(app.swipeoutOpenedEl);
}
}
});
function handleTouchStart(e) {
if (!app.allowSwipeout) return;
isMoved = false;
isTouched = true;
isScrolling = undefined;
touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
touchStartTime = (new Date()).getTime();
}
function handleTouchMove(e) {
if (!isTouched) return;
var pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
if (typeof isScrolling === 'undefined') {
isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
}
if (isScrolling) {
isTouched = false;
return;
}
if (!isMoved) {
if ($('.list-block.sortable-opened').length > 0) return;
/*jshint validthis:true */
swipeOutEl = $(this);
swipeOutContent = swipeOutEl.find('.swipeout-content');
actionsRight = swipeOutEl.find('.swipeout-actions-right');
actionsLeft = swipeOutEl.find('.swipeout-actions-left');
actionsLeftWidth = actionsRightWidth = buttonsLeft = buttonsRight = overswipeRightButton = overswipeLeftButton = null;
noFoldLeft = actionsLeft.hasClass('swipeout-actions-no-fold') || app.params.swipeoutActionsNoFold;
noFoldRight = actionsRight.hasClass('swipeout-actions-no-fold') || app.params.swipeoutActionsNoFold;
if (actionsLeft.length > 0) {
actionsLeftWidth = actionsLeft.outerWidth();
buttonsLeft = actionsLeft.children('a');
overswipeLeftButton = actionsLeft.find('.swipeout-overswipe');
}
if (actionsRight.length > 0) {
actionsRightWidth = actionsRight.outerWidth();
buttonsRight = actionsRight.children('a');
overswipeRightButton = actionsRight.find('.swipeout-overswipe');
}
opened = swipeOutEl.hasClass('swipeout-opened');
if (opened) {
openedActions = swipeOutEl.find('.swipeout-actions-left.swipeout-actions-opened').length > 0 ? 'left' : 'right';
}
swipeOutEl.removeClass('transitioning');
if (!app.params.swipeoutNoFollow) {
swipeOutEl.find('.swipeout-actions-opened').removeClass('swipeout-actions-opened');
swipeOutEl.removeClass('swipeout-opened');
}
}
isMoved = true;
e.preventDefault();
touchesDiff = pageX - touchesStart.x;
translate = touchesDiff;
if (opened) {
if (openedActions === 'right') translate = translate - actionsRightWidth;
else translate = translate + actionsLeftWidth;
}
if (translate > 0 && actionsLeft.length === 0 || translate < 0 && actionsRight.length === 0) {
if (!opened) {
isTouched = isMoved = false;
swipeOutContent.transform('');
if (buttonsRight && buttonsRight.length > 0) {
buttonsRight.transform('');
}
if (buttonsLeft && buttonsLeft.length > 0) {
buttonsLeft.transform('');
}
return;
}
translate = 0;
}
if (translate < 0) direction = 'to-left';
else if (translate > 0) direction = 'to-right';
else {
if (direction) direction = direction;
else direction = 'to-left';
}
var i, buttonOffset, progress;
e.f7PreventPanelSwipe = true;
if (app.params.swipeoutNoFollow) {
if (opened) {
if (openedActions === 'right' && touchesDiff > 0) {
app.swipeoutClose(swipeOutEl);
}
if (openedActions === 'left' && touchesDiff < 0) {
app.swipeoutClose(swipeOutEl);
}
}
else {
if (touchesDiff < 0 && actionsRight.length > 0) {
app.swipeoutOpen(swipeOutEl, 'right');
}
if (touchesDiff > 0 && actionsLeft.length > 0) {
app.swipeoutOpen(swipeOutEl, 'left');
}
}
isTouched = false;
isMoved = false;
return;
}
overswipeLeft = false;
overswipeRight = false;
var $button;
if (actionsRight.length > 0) {
// Show right actions
progress = translate / actionsRightWidth;
if (translate < -actionsRightWidth) {
translate = -actionsRightWidth - Math.pow(-translate - actionsRightWidth, 0.8);
if (overswipeRightButton.length > 0) {
overswipeRight = true;
}
}
for (i = 0; i < buttonsRight.length; i++) {
if (typeof buttonsRight[i]._buttonOffset === 'undefined') {
buttonsRight[i]._buttonOffset = buttonsRight[i].offsetLeft;
}
buttonOffset = buttonsRight[i]._buttonOffset;
$button = $(buttonsRight[i]);
if (overswipeRightButton.length > 0 && $button.hasClass('swipeout-overswipe')) {
$button.css({left: (overswipeRight ? -buttonOffset : 0) + 'px'});
if (overswipeRight) {
$button.addClass('swipeout-overswipe-active');
}
else {
$button.removeClass('swipeout-overswipe-active');
}
}
$button.transform('translate3d(' + (translate - buttonOffset * (1 + Math.max(progress, -1))) + 'px,0,0)');
}
}
if (actionsLeft.length > 0) {
// Show left actions
progress = translate / actionsLeftWidth;
if (translate > actionsLeftWidth) {
translate = actionsLeftWidth + Math.pow(translate - actionsLeftWidth, 0.8);
if (overswipeLeftButton.length > 0) {
overswipeLeft = true;
}
}
for (i = 0; i < buttonsLeft.length; i++) {
if (typeof buttonsLeft[i]._buttonOffset === 'undefined') {
buttonsLeft[i]._buttonOffset = actionsLeftWidth - buttonsLeft[i].offsetLeft - buttonsLeft[i].offsetWidth;
}
buttonOffset = buttonsLeft[i]._buttonOffset;
$button = $(buttonsLeft[i]);
if (overswipeLeftButton.length > 0 && $button.hasClass('swipeout-overswipe')) {
$button.css({left: (overswipeLeft ? buttonOffset : 0) + 'px'});
if (overswipeLeft) {
$button.addClass('swipeout-overswipe-active');
}
else {
$button.removeClass('swipeout-overswipe-active');
}
}
if (buttonsLeft.length > 1) {
$button.css('z-index', buttonsLeft.length - i);
}
$button.transform('translate3d(' + (translate + buttonOffset * (1 - Math.min(progress, 1))) + 'px,0,0)');
}
}
swipeOutContent.transform('translate3d(' + translate + 'px,0,0)');
}
function handleTouchEnd(e) {
if (!isTouched || !isMoved) {
isTouched = false;
isMoved = false;
return;
}
isTouched = false;
isMoved = false;
var timeDiff = (new Date()).getTime() - touchStartTime;
var action, actionsWidth, actions, buttons, i, noFold;
noFold = direction === 'to-left' ? noFoldRight : noFoldLeft;
actions = direction === 'to-left' ? actionsRight : actionsLeft;
actionsWidth = direction === 'to-left' ? actionsRightWidth : actionsLeftWidth;
if (
timeDiff < 300 && (touchesDiff < -10 && direction === 'to-left' || touchesDiff > 10 && direction === 'to-right') ||
timeDiff >= 300 && Math.abs(translate) > actionsWidth / 2
) {
action = 'open';
}
else {
action = 'close';
}
if (timeDiff < 300) {
if (Math.abs(translate) === 0) action = 'close';
if (Math.abs(translate) === actionsWidth) action = 'open';
}
if (action === 'open') {
app.swipeoutOpenedEl = swipeOutEl;
swipeOutEl.trigger('open');
swipeOutEl.addClass('swipeout-opened transitioning');
var newTranslate = direction === 'to-left' ? -actionsWidth : actionsWidth;
swipeOutContent.transform('translate3d(' + newTranslate + 'px,0,0)');
actions.addClass('swipeout-actions-opened');
buttons = direction === 'to-left' ? buttonsRight : buttonsLeft;
if (buttons) {
for (i = 0; i < buttons.length; i++) {
$(buttons[i]).transform('translate3d(' + newTranslate + 'px,0,0)');
}
}
if (overswipeRight) {
actionsRight.find('.swipeout-overswipe')[0].click();
}
if (overswipeLeft) {
actionsLeft.find('.swipeout-overswipe')[0].click();
}
}
else {
swipeOutEl.trigger('close');
app.swipeoutOpenedEl = undefined;
swipeOutEl.addClass('transitioning').removeClass('swipeout-opened');
swipeOutContent.transform('');
actions.removeClass('swipeout-actions-opened');
}
var buttonOffset;
if (buttonsLeft && buttonsLeft.length > 0 && buttonsLeft !== buttons) {
for (i = 0; i < buttonsLeft.length; i++) {
buttonOffset = buttonsLeft[i]._buttonOffset;
if (typeof buttonOffset === 'undefined') {
buttonsLeft[i]._buttonOffset = actionsLeftWidth - buttonsLeft[i].offsetLeft - buttonsLeft[i].offsetWidth;
}
$(buttonsLeft[i]).transform('translate3d(' + (buttonOffset) + 'px,0,0)');
}
}
if (buttonsRight && buttonsRight.length > 0 && buttonsRight !== buttons) {
for (i = 0; i < buttonsRight.length; i++) {
buttonOffset = buttonsRight[i]._buttonOffset;
if (typeof buttonOffset === 'undefined') {
buttonsRight[i]._buttonOffset = buttonsRight[i].offsetLeft;
}
$(buttonsRight[i]).transform('translate3d(' + (-buttonOffset) + 'px,0,0)');
}
}
swipeOutContent.transitionEnd(function (e) {
if (opened && action === 'open' || closed && action === 'close') return;
swipeOutEl.trigger(action === 'open' ? 'opened' : 'closed');
if (opened && action === 'close') {
if (actionsRight.length > 0) {
buttonsRight.transform('');
}
if (actionsLeft.length > 0) {
buttonsLeft.transform('');
}
}
});
}
if (swipeoutEl) {
$(swipeoutEl).on(app.touchEvents.start, handleTouchStart);
$(swipeoutEl).on(app.touchEvents.move, handleTouchMove);
$(swipeoutEl).on(app.touchEvents.end, handleTouchEnd);
}
else {
$(document).on(app.touchEvents.start, '.list-block li.swipeout', handleTouchStart);
$(document).on(app.touchEvents.move, '.list-block li.swipeout', handleTouchMove);
$(document).on(app.touchEvents.end, '.list-block li.swipeout', handleTouchEnd);
}
};
app.swipeoutOpen = function (el, dir, callback) {
el = $(el);
if (arguments.length === 2) {
if (typeof arguments[1] === 'function') {
callback = dir;
}
}
if (el.length === 0) return;
if (el.length > 1) el = $(el[0]);
if (!el.hasClass('swipeout') || el.hasClass('swipeout-opened')) return;
if (!dir) {
if (el.find('.swipeout-actions-right').length > 0) dir = 'right';
else dir = 'left';
}
var swipeOutActions = el.find('.swipeout-actions-' + dir);
if (swipeOutActions.length === 0) return;
var noFold = swipeOutActions.hasClass('swipeout-actions-no-fold') || app.params.swipeoutActionsNoFold;
el.trigger('open').addClass('swipeout-opened').removeClass('transitioning');
swipeOutActions.addClass('swipeout-actions-opened');
var buttons = swipeOutActions.children('a');
var swipeOutActionsWidth = swipeOutActions.outerWidth();
var translate = dir === 'right' ? -swipeOutActionsWidth : swipeOutActionsWidth;
var i;
if (buttons.length > 1) {
for (i = 0; i < buttons.length; i++) {
if (dir === 'right') {
$(buttons[i]).transform('translate3d(' + (- buttons[i].offsetLeft) + 'px,0,0)');
}
else {
$(buttons[i]).css('z-index', buttons.length - i).transform('translate3d(' + (swipeOutActionsWidth - buttons[i].offsetWidth - buttons[i].offsetLeft) + 'px,0,0)');
}
}
var clientLeft = buttons[1].clientLeft;
}
el.addClass('transitioning');
for (i = 0; i < buttons.length; i++) {
$(buttons[i]).transform('translate3d(' + (translate) + 'px,0,0)');
}
el.find('.swipeout-content').transform('translate3d(' + translate + 'px,0,0)').transitionEnd(function () {
el.trigger('opened');
if (callback) callback.call(el[0]);
});
app.swipeoutOpenedEl = el;
};
app.swipeoutClose = function (el, callback) {
el = $(el);
if (el.length === 0) return;
if (!el.hasClass('swipeout-opened')) return;
var dir = el.find('.swipeout-actions-opened').hasClass('swipeout-actions-right') ? 'right' : 'left';
var swipeOutActions = el.find('.swipeout-actions-opened').removeClass('swipeout-actions-opened');
var noFold = swipeOutActions.hasClass('swipeout-actions-no-fold') || app.params.swipeoutActionsNoFold;
var buttons = swipeOutActions.children('a');
var swipeOutActionsWidth = swipeOutActions.outerWidth();
app.allowSwipeout = false;
el.trigger('close');
el.removeClass('swipeout-opened').addClass('transitioning');
var closeTO;
function onSwipeoutClose() {
app.allowSwipeout = true;
if (el.hasClass('swipeout-opened')) return;
el.removeClass('transitioning');
buttons.transform('');
el.trigger('closed');
if (callback) callback.call(el[0]);
if (closeTO) clearTimeout(closeTO);
}
el.find('.swipeout-content').transform('').transitionEnd(onSwipeoutClose);
closeTO = setTimeout(onSwipeoutClose, 500);
for (var i = 0; i < buttons.length; i++) {
if (dir === 'right') {
$(buttons[i]).transform('translate3d(' + (-buttons[i].offsetLeft) + 'px,0,0)');
}
else {
$(buttons[i]).transform('translate3d(' + (swipeOutActionsWidth - buttons[i].offsetWidth - buttons[i].offsetLeft) + 'px,0,0)');
}
$(buttons[i]).css({left:0 + 'px'}).removeClass('swipeout-overswipe-active');
}
if (app.swipeoutOpenedEl && app.swipeoutOpenedEl[0] === el[0]) app.swipeoutOpenedEl = undefined;
};
app.swipeoutDelete = function (el, callback) {
el = $(el);
if (el.length === 0) return;
if (el.length > 1) el = $(el[0]);
app.swipeoutOpenedEl = undefined;
el.trigger('delete');
el.css({height: el.outerHeight() + 'px'});
var clientLeft = el[0].clientLeft;
el.css({height: 0 + 'px'}).addClass('deleting transitioning').transitionEnd(function () {
el.trigger('deleted');
if (callback) callback.call(el[0]);
if (el.parents('.virtual-list').length > 0) {
var virtualList = el.parents('.virtual-list')[0].f7VirtualList;
var virtualIndex = el[0].f7VirtualListIndex;
if (virtualList && typeof virtualIndex !== 'undefined') virtualList.deleteItem(virtualIndex);
}
else {
if (app.params.swipeoutRemoveWithTimeout) {
setTimeout(function () {
el.remove();
}, 0);
}
else el.remove();
}
});
var translate = '-100%';
el.find('.swipeout-content').transform('translate3d(' + translate + ',0,0)');
};
/*===============================================================================
************ Sortable ************
===============================================================================*/
app.sortableToggle = function (sortableContainer) {
sortableContainer = $(sortableContainer);
if (sortableContainer.length === 0) sortableContainer = $('.list-block.sortable');
sortableContainer.toggleClass('sortable-opened');
if (sortableContainer.hasClass('sortable-opened')) {
sortableContainer.trigger('open');
}
else {
sortableContainer.trigger('close');
}
return sortableContainer;
};
app.sortableOpen = function (sortableContainer) {
sortableContainer = $(sortableContainer);
if (sortableContainer.length === 0) sortableContainer = $('.list-block.sortable');
sortableContainer.addClass('sortable-opened');
sortableContainer.trigger('open');
return sortableContainer;
};
app.sortableClose = function (sortableContainer) {
sortableContainer = $(sortableContainer);
if (sortableContainer.length === 0) sortableContainer = $('.list-block.sortable');
sortableContainer.removeClass('sortable-opened');
sortableContainer.trigger('close');
return sortableContainer;
};
app.initSortable = function () {
var isTouched, isMoved, touchStartY, touchesDiff, sortingEl, sortingElHeight, sortingItems, minTop, maxTop, insertAfter, insertBefore, sortableContainer, startIndex;
function handleTouchStart(e) {
isMoved = false;
isTouched = true;
touchStartY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
/*jshint validthis:true */
sortingEl = $(this).parent();
startIndex = sortingEl.index();
sortingItems = sortingEl.parent().find('li');
sortableContainer = sortingEl.parents('.sortable');
e.preventDefault();
app.allowPanelOpen = app.allowSwipeout = false;
}
function handleTouchMove(e) {
if (!isTouched || !sortingEl) return;
var pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
if (!isMoved) {
sortingEl.addClass('sorting');
sortableContainer.addClass('sortable-sorting');
minTop = sortingEl[0].offsetTop;
maxTop = sortingEl.parent().height() - sortingEl[0].offsetTop - sortingEl.height();
sortingElHeight = sortingEl[0].offsetHeight;
}
isMoved = true;
e.preventDefault();
e.f7PreventPanelSwipe = true;
touchesDiff = pageY - touchStartY;
var translate = touchesDiff;
if (translate < -minTop) translate = -minTop;
if (translate > maxTop) translate = maxTop;
sortingEl.transform('translate3d(0,' + translate + 'px,0)');
insertBefore = insertAfter = undefined;
sortingItems.each(function () {
var currentEl = $(this);
if (currentEl[0] === sortingEl[0]) return;
var currentElOffset = currentEl[0].offsetTop;
var currentElHeight = currentEl.height();
var sortingElOffset = sortingEl[0].offsetTop + translate;
if ((sortingElOffset >= currentElOffset - currentElHeight / 2) && sortingEl.index() < currentEl.index()) {
currentEl.transform('translate3d(0, '+(-sortingElHeight)+'px,0)');
insertAfter = currentEl;
insertBefore = undefined;
}
else if ((sortingElOffset <= currentElOffset + currentElHeight / 2) && sortingEl.index() > currentEl.index()) {
currentEl.transform('translate3d(0, '+(sortingElHeight)+'px,0)');
insertAfter = undefined;
if (!insertBefore) insertBefore = currentEl;
}
else {
$(this).transform('translate3d(0, 0%,0)');
}
});
}
function handleTouchEnd(e) {
app.allowPanelOpen = app.allowSwipeout = true;
if (!isTouched || !isMoved) {
isTouched = false;
isMoved = false;
return;
}
e.preventDefault();
sortingItems.transform('');
sortingEl.removeClass('sorting');
sortableContainer.removeClass('sortable-sorting');
var virtualList, oldIndex, newIndex;
if (insertAfter) {
sortingEl.insertAfter(insertAfter);
sortingEl.trigger('sort', {startIndex: startIndex, newIndex: sortingEl.index()});
}
if (insertBefore) {
sortingEl.insertBefore(insertBefore);
sortingEl.trigger('sort', {startIndex: startIndex, newIndex: sortingEl.index()});
}
if ((insertAfter || insertBefore) && sortableContainer.hasClass('virtual-list')) {
virtualList = sortableContainer[0].f7VirtualList;
oldIndex = sortingEl[0].f7VirtualListIndex;
newIndex = insertBefore ? insertBefore[0].f7VirtualListIndex : insertAfter[0].f7VirtualListIndex;
if (virtualList) virtualList.moveItem(oldIndex, newIndex);
}
insertAfter = insertBefore = undefined;
isTouched = false;
isMoved = false;
}
$(document).on(app.touchEvents.start, '.list-block.sortable .sortable-handler', handleTouchStart);
if (app.support.touch) {
$(document).on(app.touchEvents.move, '.list-block.sortable .sortable-handler', handleTouchMove);
$(document).on(app.touchEvents.end, '.list-block.sortable .sortable-handler', handleTouchEnd);
}
else {
$(document).on(app.touchEvents.move, handleTouchMove);
$(document).on(app.touchEvents.end, handleTouchEnd);
}
};
/*===============================================================================
************ Smart Select ************
===============================================================================*/
app.initSmartSelects = function (pageContainer) {
pageContainer = $(pageContainer);
var selects;
if (pageContainer.is('.smart-select')) {
selects = pageContainer;
}
else {
selects = pageContainer.find('.smart-select');
}
if (selects.length === 0) return;
selects.each(function () {
var smartSelect = $(this);
var $select = smartSelect.find('select');
if ($select.length === 0) return;
var select = $select[0];
if (select.length === 0) return;
var valueText = [];
for (var i = 0; i < select.length; i++) {
if (select[i].selected) valueText.push(select[i].textContent.trim());
}
var itemAfter = smartSelect.find('.item-after');
if (itemAfter.length === 0) {
smartSelect.find('.item-inner').append('<div class="item-after">' + valueText.join(', ') + '</div>');
}
else {
var selectedText = itemAfter.text();
if (itemAfter.hasClass('smart-select-value')) {
for (i = 0; i < select.length; i++) {
select[i].selected = select[i].textContent.trim() === selectedText.trim();
}
} else {
itemAfter.text(valueText.join(', '));
}
}
$select.on('change', function () {
var valueText = [];
for (var i = 0; i < select.length; i++) {
if (select[i].selected) valueText.push(select[i].textContent.trim());
}
smartSelect.find('.item-after').text(valueText.join(', '));
});
});
};
app.smartSelectAddOption = function (select, option, index) {
select = $(select);
var smartSelect = select.parents('.smart-select');
if (typeof index === 'undefined') {
select.append(option);
}
else {
$(option).insertBefore(select.find('option').eq(index));
}
app.initSmartSelects(smartSelect);
var selectName = smartSelect.find('select').attr('name');
var opened = $('.page.smart-select-page[data-select-name="' + selectName + '"]').length > 0;
if (opened) {
app.smartSelectOpen(smartSelect, true);
}
};
app.smartSelectOpen = function (smartSelect, reLayout) {
smartSelect = $(smartSelect);
if (smartSelect.length === 0) return;
// Find related view
var view = smartSelect.parents('.' + app.params.viewClass);
if (view.length === 0) return;
view = view[0].f7View;
// Parameters
var openIn = smartSelect.attr('data-open-in') || app.params.smartSelectOpenIn;
if (openIn === 'popup') {
if ($('.popup.smart-select-popup').length > 0) return;
}
else if (openIn === 'picker') {
if ($('.picker-modal.modal-in').length > 0 && !reLayout){
if (smartSelect[0].f7SmartSelectPicker !== $('.picker-modal.modal-in:not(.modal-out)')[0]) app.closeModal($('.picker-modal.modal-in:not(.modal-out)'));
else return;
}
}
else {
if (!view) return;
}
var smartSelectData = smartSelect.dataset();
var pageTitle = smartSelectData.pageTitle || smartSelect.find('.item-title').text();
var backText = smartSelectData.backText || app.params.smartSelectBackText;
var closeText;
if (openIn === 'picker') {
closeText = smartSelectData.pickerCloseText || smartSelectData.backText || app.params.smartSelectPickerCloseText ;
}
else {
closeText = smartSelectData.popupCloseText || smartSelectData.backText || app.params.smartSelectPopupCloseText ;
}
var backOnSelect = smartSelectData.backOnSelect !== undefined ? smartSelectData.backOnSelect : app.params.smartSelectBackOnSelect;
var formTheme = smartSelectData.formTheme || app.params.smartSelectFormTheme;
var navbarTheme = smartSelectData.navbarTheme || app.params.smartSelectNavbarTheme;
var toolbarTheme = smartSelectData.toolbarTheme || app.params.smartSelectToolbarTheme;
var virtualList = smartSelectData.virtualList;
var virtualListHeight = smartSelectData.virtualListHeight;
var material = app.params.material;
var pickerHeight = smartSelectData.pickerHeight || app.params.smartSelectPickerHeight;
// Collect all options/values
var select = smartSelect.find('select')[0];
var $select = $(select);
var $selectData = $select.dataset();
if (select.disabled || smartSelect.hasClass('disabled') || $select.hasClass('disabled')) {
return;
}
var values = [];
var id = (new Date()).getTime();
var inputType = select.multiple ? 'checkbox' : 'radio';
var inputName = inputType + '-' + id;
var maxLength = $select.attr('maxlength');
var selectName = select.name;
var option, optionHasMedia, optionImage, optionIcon, optionGroup, optionGroupLabel, optionPreviousGroup, optionIsLabel, previousGroup, optionColor, optionClassName, optionData;
for (var i = 0; i < select.length; i++) {
option = $(select[i]);
optionData = option.dataset();
optionImage = optionData.optionImage || $selectData.optionImage || smartSelectData.optionImage;
optionIcon = optionData.optionIcon || $selectData.optionIcon || smartSelectData.optionIcon;
optionHasMedia = optionImage || optionIcon || inputType === 'checkbox';
if (material) optionHasMedia = optionImage || optionIcon;
optionColor = optionData.optionColor;
optionClassName = optionData.optionClass;
if (option[0].disabled) optionClassName += ' disabled';
optionGroup = option.parent('optgroup')[0];
optionGroupLabel = optionGroup && optionGroup.label;
optionIsLabel = false;
if (optionGroup) {
if (optionGroup !== previousGroup) {
optionIsLabel = true;
previousGroup = optionGroup;
values.push({
groupLabel: optionGroupLabel,
isLabel: optionIsLabel
});
}
}
values.push({
value: option[0].value,
text: option[0].textContent.trim(),
selected: option[0].selected,
group: optionGroup,
groupLabel: optionGroupLabel,
image: optionImage,
icon: optionIcon,
color: optionColor,
className: optionClassName,
disabled: option[0].disabled,
inputType: inputType,
id: id,
hasMedia: optionHasMedia,
checkbox: inputType === 'checkbox',
inputName: inputName,
material: app.params.material
});
}
// Item template/HTML
if (!app._compiledTemplates.smartSelectItem) {
app._compiledTemplates.smartSelectItem = t7.compile(app.params.smartSelectItemTemplate ||
'{{#if isLabel}}' +
'<li class="item-divider">{{groupLabel}}</li>' +
'{{else}}' +
'<li{{#if className}} class="{{className}}"{{/if}}>' +
'<label class="label-{{inputType}} item-content">' +
'<input type="{{inputType}}" name="{{inputName}}" value="{{value}}" {{#if selected}}checked{{/if}}>' +
'{{#if material}}' +
'{{#if hasMedia}}' +
'<div class="item-media">' +
'{{#if icon}}<i class="icon {{icon}}"></i>{{/if}}' +
'{{#if image}}<img src="{{image}}">{{/if}}' +
'</div>' +
'<div class="item-inner">' +
'<div class="item-title{{#if color}} color-{{color}}{{/if}}">{{text}}</div>' +
'</div>' +
'<div class="item-after">' +
'<i class="icon icon-form-{{inputType}}"></i>' +
'</div>' +
'{{else}}' +
'<div class="item-media">' +
'<i class="icon icon-form-{{inputType}}"></i>' +
'</div>' +
'<div class="item-inner">' +
'<div class="item-title{{#if color}} color-{{color}}{{/if}}">{{text}}</div>' +
'</div>' +
'{{/if}}' +
'{{else}}' +
'{{#if hasMedia}}' +
'<div class="item-media">' +
'{{#if checkbox}}<i class="icon icon-form-checkbox"></i>{{/if}}' +
'{{#if icon}}<i class="icon {{icon}}"></i>{{/if}}' +
'{{#if image}}<img src="{{image}}">{{/if}}' +
'</div>' +
'{{/if}}' +
'<div class="item-inner">' +
'<div class="item-title{{#if color}} color-{{color}}{{/if}}">{{text}}</div>' +
'</div>' +
'{{/if}}' +
'</label>' +
'</li>' +
'{{/if}}'
);
}
var smartSelectItemTemplate = app._compiledTemplates.smartSelectItem;
var inputsHTML = '';
if (!virtualList) {
for (var j = 0; j < values.length; j++) {
inputsHTML += smartSelectItemTemplate(values[j]);
}
}
// Toolbar / Navbar
var toolbarHTML = '', navbarHTML;
var noNavbar = '', noToolbar = '', noTabbar = '', navbarLayout;
if (openIn === 'picker') {
if (!app._compiledTemplates.smartSelectToolbar) {
app._compiledTemplates.smartSelectToolbar = t7.compile(app.params.smartSelectToolbarTemplate ||
'<div class="toolbar {{#if toolbarTheme}}theme-{{toolbarTheme}}{{/if}}">' +
'<div class="toolbar-inner">' +
'<div class="left"></div>' +
'<div class="right"><a href="#" class="link close-picker"><span>{{closeText}}</span></a></div>' +
'</div>' +
'</div>'
);
}
toolbarHTML = app._compiledTemplates.smartSelectToolbar({
pageTitle: pageTitle,
closeText: closeText,
openIn: openIn,
toolbarTheme: toolbarTheme,
inPicker: openIn === 'picker'
});
}
else {
// Navbar HTML
if (!app._compiledTemplates.smartSelectNavbar) {
app._compiledTemplates.smartSelectNavbar = t7.compile(app.params.smartSelectNavbarTemplate ||
'<div class="navbar {{#if navbarTheme}}theme-{{navbarTheme}}{{/if}}">' +
'<div class="navbar-inner">' +
'{{leftTemplate}}' +
'<div class="center sliding">{{pageTitle}}</div>' +
'</div>' +
'</div>'
);
}
navbarHTML = app._compiledTemplates.smartSelectNavbar({
pageTitle: pageTitle,
backText: backText,
closeText: closeText,
openIn: openIn,
navbarTheme: navbarTheme,
inPopup: openIn === 'popup',
inPage: openIn === 'page',
leftTemplate: openIn === 'popup' ?
(app.params.smartSelectPopupCloseTemplate || (material ? '<div class="left"><a href="#" class="link close-popup icon-only"><i class="icon icon-back"></i></a></div>' : '<div class="left"><a href="#" class="link close-popup"><i class="icon icon-back"></i><span>{{closeText}}</span></a></div>')).replace(/{{closeText}}/g, closeText) :
(app.params.smartSelectBackTemplate || (material ? '<div class="left"><a href="#" class="back link icon-only"><i class="icon icon-back"></i></a></div>' : '<div class="left sliding"><a href="#" class="back link"><i class="icon icon-back"></i><span>{{backText}}</span></a></div>')).replace(/{{backText}}/g, backText)
});
// Determine navbar layout type - static/fixed/through
if (openIn === 'page') {
navbarLayout = 'static';
if (smartSelect.parents('.navbar-through').length > 0) navbarLayout = 'through';
if (smartSelect.parents('.navbar-fixed').length > 0) navbarLayout = 'fixed';
noToolbar = smartSelect.parents('.page').hasClass('no-toolbar') ? 'no-toolbar' : '';
noNavbar = smartSelect.parents('.page').hasClass('no-navbar') ? 'no-navbar' : 'navbar-' + navbarLayout;
noTabbar = smartSelect.parents('.page').hasClass('no-tabbar') ? 'no-tabbar' : '';
}
else {
navbarLayout = 'fixed';
}
}
// Page Layout
var pageName = 'smart-select-' + inputName;
var useSearchbar = typeof smartSelect.data('searchbar') === 'undefined' ? app.params.smartSelectSearchbar : (smartSelect.data('searchbar') === 'true' ? true : false);
var searchbarPlaceholder, searchbarCancel;
if (useSearchbar) {
searchbarPlaceholder = smartSelect.data('searchbar-placeholder') || 'Search';
searchbarCancel = smartSelect.data('searchbar-cancel') || 'Cancel';
}
var searchbarHTML = '<form class="searchbar searchbar-init" data-search-list=".smart-select-list-' + id + '" data-search-in=".item-title">' +
'<div class="searchbar-input">' +
'<input type="search" placeholder="' + searchbarPlaceholder + '">' +
'<a href="#" class="searchbar-clear"></a>' +
'</div>' +
(material ? '' : '<a href="#" class="searchbar-cancel">' + searchbarCancel + '</a>') +
'</form>' +
'<div class="searchbar-overlay"></div>';
var pageHTML =
(openIn !== 'picker' && navbarLayout === 'through' ? navbarHTML : '') +
'<div class="pages">' +
' <div data-page="' + pageName + '" data-select-name="' + selectName + '" class="page smart-select-page ' + noNavbar + ' ' + noToolbar + ' ' + noTabbar + '">' +
(openIn !== 'picker' && navbarLayout === 'fixed' ? navbarHTML : '') +
(useSearchbar ? searchbarHTML : '') +
' <div class="page-content">' +
(openIn !== 'picker' && navbarLayout === 'static' ? navbarHTML : '') +
' <div class="list-block ' + (virtualList ? 'virtual-list' : '') + ' smart-select-list-' + id + ' ' + (formTheme ? 'theme-' + formTheme : '') + '">' +
' <ul>' +
(virtualList ? '' : inputsHTML) +
' </ul>' +
' </div>' +
' </div>' +
' </div>' +
'</div>';
// Define popup and picker
var popup, picker;
// Scroll SS Picker To Input
function scrollToInput() {
var pageContent = smartSelect.parents('.page-content');
if (pageContent.length === 0) return;
var paddingTop = parseInt(pageContent.css('padding-top'), 10),
paddingBottom = parseInt(pageContent.css('padding-bottom'), 10),
pageHeight = pageContent[0].offsetHeight - paddingTop - picker.height(),
pageScrollHeight = pageContent[0].scrollHeight - paddingTop - picker.height(),
newPaddingBottom;
var inputTop = smartSelect.offset().top - paddingTop + smartSelect[0].offsetHeight;
if (inputTop > pageHeight) {
var scrollTop = pageContent.scrollTop() + inputTop - pageHeight;
if (scrollTop + pageHeight > pageScrollHeight) {
newPaddingBottom = scrollTop + pageHeight - pageScrollHeight + paddingBottom;
if (pageHeight === pageScrollHeight) {
newPaddingBottom = picker.height();
}
pageContent.css({'padding-bottom': (newPaddingBottom) + 'px'});
}
pageContent.scrollTop(scrollTop, 300);
}
}
// Close SS Picker on HTML Click
function closeOnHTMLClick(e) {
var close = true;
if (e.target === smartSelect[0] || $(e.target).parents(smartSelect[0]).length > 0) {
close = false;
}
if ($(e.target).parents('.picker-modal').length > 0) {
close = false;
}
if (close) {
app.closeModal('.smart-select-picker.modal-in');
}
}
// Check max length
function checkMaxLength(container) {
if (select.selectedOptions.length >= maxLength) {
container.find('input[type="checkbox"]').each(function () {
if (!this.checked) {
$(this).parents('li').addClass('disabled');
}
else {
$(this).parents('li').removeClass('disabled');
}
});
}
else {
container.find('.disabled').removeClass('disabled');
}
}
// Event Listeners on new page
function handleInputs(container) {
container = $(container);
if (virtualList) {
var virtualListInstance = app.virtualList(container.find('.virtual-list'), {
items: values,
template: smartSelectItemTemplate,
height: virtualListHeight || undefined,
searchByItem: function (query, index, item) {
if (item.text.toLowerCase().indexOf(query.trim().toLowerCase()) >=0 ) return true;
return false;
}
});
container.once(openIn === 'popup' || openIn === 'picker' ? 'closed': 'pageBeforeRemove', function () {
if (virtualListInstance && virtualListInstance.destroy) virtualListInstance.destroy();
});
}
if (maxLength) {
checkMaxLength(container);
}
if (backOnSelect) {
container.find('input[type="radio"][name="' + inputName + '"]:checked').parents('label').once('click', function () {
if (openIn === 'popup') app.closeModal(popup);
else if (openIn === 'picker') app.closeModal(picker);
else view.router.back();
});
}
container.on('change', 'input[name="' + inputName + '"]', function () {
var input = this;
var value = input.value;
var optionText = [];
if (input.type === 'checkbox') {
var values = [];
for (var i = 0; i < select.options.length; i++) {
var option = select.options[i];
if (option.value === value) {
option.selected = input.checked;
}
if (option.selected) {
optionText.push(option.textContent.trim());
}
}
if (maxLength) {
checkMaxLength(container);
}
}
else {
optionText = [smartSelect.find('option[value="' + value + '"]').text()];
select.value = value;
}
$select.trigger('change');
smartSelect.find('.item-after').text(optionText.join(', '));
if (backOnSelect && inputType === 'radio') {
if (openIn === 'popup') app.closeModal(popup);
else if (openIn === 'picker') app.closeModal(picker);
else view.router.back();
}
});
}
function pageInit(e) {
var page = e.detail.page;
if (page.name === pageName) {
handleInputs(page.container);
}
}
if (openIn === 'popup') {
if (reLayout) {
popup = $('.popup.smart-select-popup .view');
popup.html(pageHTML);
}
else {
popup = app.popup(
'<div class="popup smart-select-popup smart-select-popup-' + inputName + '">' +
'<div class="view navbar-fixed">' +
pageHTML +
'</div>' +
'</div>'
);
popup = $(popup);
}
app.initPage(popup.find('.page'));
handleInputs(popup);
}
else if (openIn === 'picker') {
if (reLayout) {
picker = $('.picker-modal.smart-select-picker .view');
picker.html(pageHTML);
}
else {
picker = app.pickerModal(
'<div class="picker-modal smart-select-picker smart-select-picker-' + inputName + '"' + (pickerHeight ? ' style="height:' + pickerHeight + '"' : '') + '>' +
toolbarHTML +
'<div class="picker-modal-inner">' +
'<div class="view">' +
pageHTML +
'</div>' +
'</div>' +
'</div>'
);
picker = $(picker);
// Scroll To Input
scrollToInput();
// Close On Click
$('html').on('click', closeOnHTMLClick);
// On Close
picker.once('close', function () {
// Reset linked picker
smartSelect[0].f7SmartSelectPicker = undefined;
// Detach html click
$('html').off('click', closeOnHTMLClick);
// Restore page padding bottom
smartSelect.parents('.page-content').css({paddingBottom: ''});
});
// Link Picker
smartSelect[0].f7SmartSelectPicker = picker[0];
}
// Init Page
app.initPage(picker.find('.page'));
// Attach events
handleInputs(picker);
}
else {
$(document).once('pageInit', '.smart-select-page', pageInit);
view.router.load({
content: pageHTML,
reload: reLayout ? true : undefined
});
}
};
/*===============================================================================
************ Virtual List ************
===============================================================================*/
var VirtualList = function (listBlock, params) {
var defaults = {
cols: 1,
height: app.params.material ? 48 : 44,
cache: true,
dynamicHeightBufferSize: 1,
showFilteredItemsOnly: false
};
params = params || {};
for (var def in defaults) {
if (typeof params[def] === 'undefined') {
params[def] = defaults[def];
}
}
// Preparation
var vl = this;
vl.listBlock = $(listBlock);
vl.params = params;
vl.items = vl.params.items;
if (vl.params.showFilteredItemsOnly) {
vl.filteredItems = [];
}
if (vl.params.template) {
if (typeof vl.params.template === 'string') vl.template = t7.compile(vl.params.template);
else if (typeof vl.params.template === 'function') vl.template = vl.params.template;
}
vl.pageContent = vl.listBlock.parents('.page-content');
// Bad scroll
var updatableScroll;
if (typeof vl.params.updatableScroll !== 'undefined') {
updatableScroll = vl.params.updatableScroll;
}
else {
updatableScroll = true;
if (app.device.ios && app.device.osVersion.split('.')[0] < 8) {
updatableScroll = false;
}
}
// Append <ul>
vl.ul = vl.params.ul ? $(vl.params.ul) : vl.listBlock.children('ul');
if (vl.ul.length === 0) {
vl.listBlock.append('<ul></ul>');
vl.ul = vl.listBlock.children('ul');
}
// DOM cached items
vl.domCache = {};
vl.displayDomCache = {};
// Temporary DOM Element
vl.tempDomElement = document.createElement('ul');
// Last repain position
vl.lastRepaintY = null;
// Fragment
vl.fragment = document.createDocumentFragment();
// Filter
vl.filterItems = function (indexes, resetScrollTop) {
vl.filteredItems = [];
var firstIndex = indexes[0];
var lastIndex = indexes[indexes.length - 1];
for (var i = 0; i < indexes.length; i++) {
vl.filteredItems.push(vl.items[indexes[i]]);
}
if (typeof resetScrollTop === 'undefined') resetScrollTop = true;
if (resetScrollTop) {
vl.pageContent[0].scrollTop = 0;
}
vl.update();
};
vl.resetFilter = function () {
if (vl.params.showFilteredItemsOnly) {
vl.filteredItems = [];
}
else {
vl.filteredItems = null;
delete vl.filteredItems;
}
vl.update();
};
var pageHeight, rowsPerScreen, rowsBefore, rowsAfter, rowsToRender, maxBufferHeight = 0, listHeight;
var dynamicHeight = typeof vl.params.height === 'function';
// Set list size
vl.setListSize = function () {
var items = vl.filteredItems || vl.items;
pageHeight = vl.pageContent[0].offsetHeight;
if (dynamicHeight) {
listHeight = 0;
vl.heights = [];
for (var i = 0; i < items.length; i++) {
var itemHeight = vl.params.height(items[i]);
listHeight += itemHeight;
vl.heights.push(itemHeight);
}
}
else {
listHeight = Math.ceil(items.length / vl.params.cols) * vl.params.height;
rowsPerScreen = Math.ceil(pageHeight / vl.params.height);
rowsBefore = vl.params.rowsBefore || rowsPerScreen * 2;
rowsAfter = vl.params.rowsAfter || rowsPerScreen;
rowsToRender = (rowsPerScreen + rowsBefore + rowsAfter);
maxBufferHeight = rowsBefore / 2 * vl.params.height;
}
if (updatableScroll) {
vl.ul.css({height: listHeight + 'px'});
}
};
// Render items
vl.render = function (force, forceScrollTop) {
if (force) vl.lastRepaintY = null;
var scrollTop = -(vl.listBlock[0].getBoundingClientRect().top - vl.pageContent[0].getBoundingClientRect().top);
if (typeof forceScrollTop !== 'undefined') scrollTop = forceScrollTop;
if (vl.lastRepaintY === null || Math.abs(scrollTop - vl.lastRepaintY) > maxBufferHeight || (!updatableScroll && (vl.pageContent[0].scrollTop + pageHeight >= vl.pageContent[0].scrollHeight))) {
vl.lastRepaintY = scrollTop;
}
else {
return;
}
var items = vl.filteredItems || vl.items,
fromIndex, toIndex, heightBeforeFirstItem = 0, heightBeforeLastItem = 0;
if (dynamicHeight) {
var itemTop = 0, j, itemHeight;
maxBufferHeight = pageHeight;
for (j = 0; j < vl.heights.length; j++) {
itemHeight = vl.heights[j];
if (typeof fromIndex === 'undefined') {
if (itemTop + itemHeight >= scrollTop - pageHeight * 2 * vl.params.dynamicHeightBufferSize) fromIndex = j;
else heightBeforeFirstItem += itemHeight;
}
if (typeof toIndex === 'undefined') {
if (itemTop + itemHeight >= scrollTop + pageHeight * 2 * vl.params.dynamicHeightBufferSize || j === vl.heights.length - 1) toIndex = j + 1;
heightBeforeLastItem += itemHeight;
}
itemTop += itemHeight;
}
toIndex = Math.min(toIndex, items.length);
}
else {
fromIndex = (parseInt(scrollTop / vl.params.height) - rowsBefore) * vl.params.cols;
if (fromIndex < 0) {
fromIndex = 0;
}
toIndex = Math.min(fromIndex + rowsToRender * vl.params.cols, items.length);
}
var topPosition;
vl.reachEnd = false;
for (var i = fromIndex; i < toIndex; i++) {
var item, index;
// Define real item index
index = vl.items.indexOf(items[i]);
if (i === fromIndex) vl.currentFromIndex = index;
if (i === toIndex - 1) vl.currentToIndex = index;
if (index === vl.items.length - 1) vl.reachEnd = true;
// Find items
if (vl.domCache[index]) {
item = vl.domCache[index];
}
else {
if (vl.template) {
vl.tempDomElement.innerHTML = vl.template(items[i], {index: index}).trim();
}
else if (vl.params.renderItem) {
vl.tempDomElement.innerHTML = vl.params.renderItem(index, items[i]).trim();
}
else {
vl.tempDomElement.innerHTML = items[i].trim();
}
item = vl.tempDomElement.childNodes[0];
if (vl.params.cache) vl.domCache[index] = item;
}
item.f7VirtualListIndex = index;
// Set item top position
if (i === fromIndex) {
if (dynamicHeight) {
topPosition = heightBeforeFirstItem;
}
else {
topPosition = (i * vl.params.height / vl.params.cols);
}
}
item.style.top = topPosition + 'px';
// Before item insert
if (vl.params.onItemBeforeInsert) vl.params.onItemBeforeInsert(vl, item);
// Append item to fragment
vl.fragment.appendChild(item);
}
// Update list height with not updatable scroll
if (!updatableScroll) {
if (dynamicHeight) {
vl.ul[0].style.height = heightBeforeLastItem + 'px';
}
else {
vl.ul[0].style.height = i * vl.params.height / vl.params.cols + 'px';
}
}
// Update list html
if (vl.params.onBeforeClear) vl.params.onBeforeClear(vl, vl.fragment);
vl.ul[0].innerHTML = '';
if (vl.params.onItemsBeforeInsert) vl.params.onItemsBeforeInsert(vl, vl.fragment);
vl.ul[0].appendChild(vl.fragment);
if (vl.params.onItemsAfterInsert) vl.params.onItemsAfterInsert(vl, vl.fragment);
if (typeof forceScrollTop !== 'undefined' && force) {
vl.pageContent.scrollTop(forceScrollTop, 0);
}
};
vl.scrollToItem = function (index) {
if (index > vl.items.length) return false;
var itemTop = 0, listTop;
if (dynamicHeight) {
for (var i = 0; i < index; i++) {
itemTop += vl.heights[i];
}
}
else {
itemTop = index * vl.params.height;
}
listTop = vl.listBlock[0].offsetTop;
vl.render(true, listTop + itemTop - parseInt(vl.pageContent.css('padding-top'), 10));
return true;
};
// Handle scroll event
vl.handleScroll = function (e) {
vl.render();
};
// Handle resize event
vl._isVisible = function (el) {
return !!( el.offsetWidth || el.offsetHeight || el.getClientRects().length );
};
vl.handleResize = function (e) {
if (vl._isVisible(vl.listBlock[0])) {
vl.setListSize();
vl.render(true);
}
};
vl.attachEvents = function (detach) {
var action = detach ? 'off' : 'on';
vl.pageContent[action]('scroll', vl.handleScroll);
vl.listBlock.parents('.tab').eq(0)[action]('show', vl.handleResize);
$(window)[action]('resize', vl.handleResize);
};
// Init Virtual List
vl.init = function () {
vl.attachEvents();
vl.setListSize();
vl.render();
};
// Append
vl.appendItems = function (items) {
for (var i = 0; i < items.length; i++) {
vl.items.push(items[i]);
}
vl.update();
};
vl.appendItem = function (item) {
vl.appendItems([item]);
};
// Replace
vl.replaceAllItems = function (items) {
vl.items = items;
delete vl.filteredItems;
vl.domCache = {};
vl.update();
};
vl.replaceItem = function (index, item) {
vl.items[index] = item;
if (vl.params.cache) delete vl.domCache[index];
vl.update();
};
// Prepend
vl.prependItems = function (items) {
for (var i = items.length - 1; i >= 0; i--) {
vl.items.unshift(items[i]);
}
if (vl.params.cache) {
var newCache = {};
for (var cached in vl.domCache) {
newCache[parseInt(cached, 10) + items.length] = vl.domCache[cached];
}
vl.domCache = newCache;
}
vl.update();
};
vl.prependItem = function (item) {
vl.prependItems([item]);
};
// Move
vl.moveItem = function (oldIndex, newIndex) {
if (oldIndex === newIndex) return;
// remove item from array
var item = vl.items.splice(oldIndex, 1)[0];
if (newIndex >= vl.items.length) {
// Add item to the end
vl.items.push(item);
newIndex = vl.items.length - 1;
}
else {
// Add item to new index
vl.items.splice(newIndex, 0, item);
}
// Update cache
if (vl.params.cache) {
var newCache = {};
for (var cached in vl.domCache) {
var cachedIndex = parseInt(cached, 10);
var leftIndex = oldIndex < newIndex ? oldIndex : newIndex;
var rightIndex = oldIndex < newIndex ? newIndex : oldIndex;
var indexShift = oldIndex < newIndex ? -1 : 1;
if (cachedIndex < leftIndex || cachedIndex > rightIndex) newCache[cachedIndex] = vl.domCache[cachedIndex];
if (cachedIndex === leftIndex) newCache[rightIndex] = vl.domCache[cachedIndex];
if (cachedIndex > leftIndex && cachedIndex <= rightIndex) newCache[cachedIndex + indexShift] = vl.domCache[cachedIndex];
}
vl.domCache = newCache;
}
vl.update();
};
// Insert before
vl.insertItemBefore = function (index, item) {
if (index === 0) {
vl.prependItem(item);
return;
}
if (index >= vl.items.length) {
vl.appendItem(item);
return;
}
vl.items.splice(index, 0, item);
// Update cache
if (vl.params.cache) {
var newCache = {};
for (var cached in vl.domCache) {
var cachedIndex = parseInt(cached, 10);
if (cachedIndex >= index) {
newCache[cachedIndex + 1] = vl.domCache[cachedIndex];
}
}
vl.domCache = newCache;
}
vl.update();
};
// Delete
vl.deleteItems = function (indexes) {
var prevIndex, indexShift = 0;
for (var i = 0; i < indexes.length; i++) {
var index = indexes[i];
if (typeof prevIndex !== 'undefined') {
if (index > prevIndex) {
indexShift = -i;
}
}
index = index + indexShift;
prevIndex = indexes[i];
// Delete item
var deletedItem = vl.items.splice(index, 1)[0];
// Delete from filtered
if (vl.filteredItems && vl.filteredItems.indexOf(deletedItem) >= 0) {
vl.filteredItems.splice(vl.filteredItems.indexOf(deletedItem), 1);
}
// Update cache
if (vl.params.cache) {
var newCache = {};
for (var cached in vl.domCache) {
var cachedIndex = parseInt(cached, 10);
if (cachedIndex === index) {
delete vl.domCache[index];
}
else if (parseInt(cached, 10) > index) {
newCache[cachedIndex - 1] = vl.domCache[cached];
}
else {
newCache[cachedIndex] = vl.domCache[cached];
}
}
vl.domCache = newCache;
}
}
vl.update();
};
vl.deleteAllItems = function () {
vl.items = [];
delete vl.filteredItems;
if (vl.params.cache) vl.domCache = {};
vl.update();
};
vl.deleteItem = function (index) {
vl.deleteItems([index]);
};
// Clear cache
vl.clearCache = function () {
vl.domCache = {};
};
// Update Virtual List
vl.update = function () {
vl.setListSize();
vl.render(true);
};
// Destroy
vl.destroy = function () {
vl.attachEvents(true);
delete vl.items;
delete vl.domCache;
};
// Init Virtual List
vl.init();
// Store vl in container
vl.listBlock[0].f7VirtualList = vl;
return vl;
};
// App Method
app.virtualList = function (listBlock, params) {
return new VirtualList(listBlock, params);
};
app.reinitVirtualList = function (pageContainer) {
var page = $(pageContainer);
var vlists = page.find('.virtual-list');
if (vlists.length === 0) return;
for (var i = 0; i < vlists.length; i++) {
var vlistInstance = vlists[i].f7VirtualList;
if (vlistInstance) {
vlistInstance.update();
}
}
};
/*======================================================
************ Pull To Refresh ************
======================================================*/
app.initPullToRefresh = function (pageContainer) {
var eventsTarget = $(pageContainer);
if (!eventsTarget.hasClass('pull-to-refresh-content')) {
eventsTarget = eventsTarget.find('.pull-to-refresh-content');
}
if (!eventsTarget || eventsTarget.length === 0) return;
var touchId, isTouched, isMoved, touchesStart = {}, isScrolling, touchesDiff, touchStartTime, container, refresh = false, useTranslate = false, startTranslate = 0, translate, scrollTop, wasScrolled, layer, triggerDistance, dynamicTriggerDistance, pullStarted;
var page = eventsTarget.hasClass('page') ? eventsTarget : eventsTarget.parents('.page');
var hasNavbar = false;
if (page.find('.navbar').length > 0 || page.parents('.navbar-fixed, .navbar-through').length > 0 || page.hasClass('navbar-fixed') || page.hasClass('navbar-through')) hasNavbar = true;
if (page.hasClass('no-navbar')) hasNavbar = false;
if (!hasNavbar) eventsTarget.addClass('pull-to-refresh-no-navbar');
container = eventsTarget;
// Define trigger distance
if (container.attr('data-ptr-distance')) {
dynamicTriggerDistance = true;
}
else {
triggerDistance = 44;
}
function handleTouchStart(e) {
if (isTouched) {
if (app.device.os === 'android') {
if ('targetTouches' in e && e.targetTouches.length > 1) return;
}
else return;
}
/*jshint validthis:true */
container = $(this);
if (container.hasClass('refreshing')) {
return;
}
isMoved = false;
pullStarted = false;
isTouched = true;
isScrolling = undefined;
wasScrolled = undefined;
if (e.type === 'touchstart') touchId = e.targetTouches[0].identifier;
touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
touchStartTime = (new Date()).getTime();
}
function handleTouchMove(e) {
if (!isTouched) return;
var pageX, pageY, touch;
if (e.type === 'touchmove') {
if (touchId && e.touches) {
for (var i = 0; i < e.touches.length; i++) {
if (e.touches[i].identifier === touchId) {
touch = e.touches[i];
}
}
}
if (!touch) touch = e.targetTouches[0];
pageX = touch.pageX;
pageY = touch.pageY;
}
else {
pageX = e.pageX;
pageY = e.pageY;
}
if (!pageX || !pageY) return;
if (typeof isScrolling === 'undefined') {
isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
}
if (!isScrolling) {
isTouched = false;
return;
}
scrollTop = container[0].scrollTop;
if (typeof wasScrolled === 'undefined' && scrollTop !== 0) wasScrolled = true;
if (!isMoved) {
/*jshint validthis:true */
container.removeClass('transitioning');
if (scrollTop > container[0].offsetHeight) {
isTouched = false;
return;
}
if (dynamicTriggerDistance) {
triggerDistance = container.attr('data-ptr-distance');
if (triggerDistance.indexOf('%') >= 0) triggerDistance = container[0].offsetHeight * parseInt(triggerDistance, 10) / 100;
}
startTranslate = container.hasClass('refreshing') ? triggerDistance : 0;
if (container[0].scrollHeight === container[0].offsetHeight || app.device.os !== 'ios') {
useTranslate = true;
}
else {
useTranslate = false;
}
}
isMoved = true;
touchesDiff = pageY - touchesStart.y;
if (touchesDiff > 0 && scrollTop <= 0 || scrollTop < 0) {
// iOS 8 fix
if (app.device.os === 'ios' && parseInt(app.device.osVersion.split('.')[0], 10) > 7 && scrollTop === 0 && !wasScrolled) useTranslate = true;
if (useTranslate) {
e.preventDefault();
translate = (Math.pow(touchesDiff, 0.85) + startTranslate);
container.transform('translate3d(0,' + translate + 'px,0)');
}
if ((useTranslate && Math.pow(touchesDiff, 0.85) > triggerDistance) || (!useTranslate && touchesDiff >= triggerDistance * 2)) {
refresh = true;
container.addClass('pull-up').removeClass('pull-down');
}
else {
refresh = false;
container.removeClass('pull-up').addClass('pull-down');
}
if (!pullStarted) {
container.trigger('pullstart');
pullStarted = true;
}
container.trigger('pullmove', {
event: e,
scrollTop: scrollTop,
translate: translate,
touchesDiff: touchesDiff
});
}
else {
pullStarted = false;
container.removeClass('pull-up pull-down');
refresh = false;
return;
}
}
function handleTouchEnd(e) {
if (e.type === 'touchend' && e.changedTouches && e.changedTouches.length > 0 && touchId) {
if (e.changedTouches[0].identifier !== touchId) return;
}
if (!isTouched || !isMoved) {
isTouched = false;
isMoved = false;
return;
}
if (translate) {
container.addClass('transitioning');
translate = 0;
}
container.transform('');
if (refresh) {
container.addClass('refreshing');
container.trigger('refresh', {
done: function () {
app.pullToRefreshDone(container);
}
});
}
else {
container.removeClass('pull-down');
}
isTouched = false;
isMoved = false;
if (pullStarted) container.trigger('pullend');
}
// Attach Events
var passiveListener = app.touchEvents.start === 'touchstart' && app.support.passiveListener ? {passive: true, capture: false} : false;
eventsTarget.on(app.touchEvents.start, handleTouchStart, passiveListener);
eventsTarget.on(app.touchEvents.move, handleTouchMove);
eventsTarget.on(app.touchEvents.end, handleTouchEnd, passiveListener);
// Detach Events on page remove
if (page.length === 0) return;
function destroyPullToRefresh() {
eventsTarget.off(app.touchEvents.start, handleTouchStart);
eventsTarget.off(app.touchEvents.move, handleTouchMove);
eventsTarget.off(app.touchEvents.end, handleTouchEnd);
}
eventsTarget[0].f7DestroyPullToRefresh = destroyPullToRefresh;
function detachEvents() {
destroyPullToRefresh();
page.off('pageBeforeRemove', detachEvents);
}
page.on('pageBeforeRemove', detachEvents);
};
app.pullToRefreshDone = function (container) {
container = $(container);
if (container.length === 0) container = $('.pull-to-refresh-content.refreshing');
container.removeClass('refreshing').addClass('transitioning');
container.transitionEnd(function () {
container.removeClass('transitioning pull-up pull-down');
container.trigger('refreshdone');
});
};
app.pullToRefreshTrigger = function (container) {
container = $(container);
if (container.length === 0) container = $('.pull-to-refresh-content');
if (container.hasClass('refreshing')) return;
container.addClass('transitioning refreshing');
container.trigger('refresh', {
done: function () {
app.pullToRefreshDone(container);
}
});
};
app.destroyPullToRefresh = function (pageContainer) {
pageContainer = $(pageContainer);
var pullToRefreshContent = pageContainer.hasClass('pull-to-refresh-content') ? pageContainer : pageContainer.find('.pull-to-refresh-content');
if (pullToRefreshContent.length === 0) return;
if (pullToRefreshContent[0].f7DestroyPullToRefresh) pullToRefreshContent[0].f7DestroyPullToRefresh();
};
/* ===============================================================================
************ Infinite Scroll ************
=============================================================================== */
function handleInfiniteScroll() {
/*jshint validthis:true */
var inf = $(this);
var scrollTop = inf[0].scrollTop;
var scrollHeight = inf[0].scrollHeight;
var height = inf[0].offsetHeight;
var distance = inf[0].getAttribute('data-distance');
var virtualListContainer = inf.find('.virtual-list');
var virtualList;
var onTop = inf.hasClass('infinite-scroll-top');
if (!distance) distance = 50;
if (typeof distance === 'string' && distance.indexOf('%') >= 0) {
distance = parseInt(distance, 10) / 100 * height;
}
if (distance > height) distance = height;
if (onTop) {
if (scrollTop < distance) {
inf.trigger('infinite');
}
}
else {
if (scrollTop + height >= scrollHeight - distance) {
if (virtualListContainer.length > 0) {
virtualList = virtualListContainer[0].f7VirtualList;
if (virtualList && !virtualList.reachEnd) return;
}
inf.trigger('infinite');
}
}
}
app.attachInfiniteScroll = function (infiniteContent) {
$(infiniteContent).on('scroll', handleInfiniteScroll);
};
app.detachInfiniteScroll = function (infiniteContent) {
$(infiniteContent).off('scroll', handleInfiniteScroll);
};
app.initPageInfiniteScroll = function (pageContainer) {
pageContainer = $(pageContainer);
var infiniteContent = pageContainer.find('.infinite-scroll');
if (infiniteContent.length === 0) return;
app.attachInfiniteScroll(infiniteContent);
function detachEvents() {
app.detachInfiniteScroll(infiniteContent);
pageContainer.off('pageBeforeRemove', detachEvents);
}
pageContainer.on('pageBeforeRemove', detachEvents);
};
/*=============================================================
************ Hide/show Toolbar/Navbar on scroll ************
=============================================================*/
app.initPageScrollToolbars = function (pageContainer) {
pageContainer = $(pageContainer);
var scrollContent = pageContainer.find('.page-content');
if (scrollContent.length === 0) return;
var hideNavbar = (app.params.hideNavbarOnPageScroll || scrollContent.hasClass('hide-navbar-on-scroll') || scrollContent.hasClass('hide-bars-on-scroll')) && !(scrollContent.hasClass('keep-navbar-on-scroll') || scrollContent.hasClass('keep-bars-on-scroll'));
var hideToolbar = (app.params.hideToolbarOnPageScroll || scrollContent.hasClass('hide-toolbar-on-scroll') || scrollContent.hasClass('hide-bars-on-scroll')) && !(scrollContent.hasClass('keep-toolbar-on-scroll') || scrollContent.hasClass('keep-bars-on-scroll'));
var hideTabbar = (app.params.hideTabbarOnPageScroll || scrollContent.hasClass('hide-tabbar-on-scroll')) && !(scrollContent.hasClass('keep-tabbar-on-scroll'));
if (!(hideNavbar || hideToolbar || hideTabbar)) return;
var viewContainer = scrollContent.parents('.' + app.params.viewClass);
if (viewContainer.length === 0) return;
var navbar = viewContainer.find('.navbar'),
toolbar = viewContainer.find('.toolbar'),
tabbar;
if (hideTabbar) {
tabbar = viewContainer.find('.tabbar');
if (tabbar.length === 0) tabbar = viewContainer.parents('.' + app.params.viewsClass).find('.tabbar');
}
var hasNavbar = navbar.length > 0,
hasToolbar = toolbar.length > 0,
hasTabbar = tabbar && tabbar.length > 0;
var previousScroll, currentScroll;
previousScroll = currentScroll = scrollContent[0].scrollTop;
var scrollHeight, offsetHeight, reachEnd, action, navbarHidden, toolbarHidden, tabbarHidden;
var toolbarHeight = (hasToolbar && hideToolbar) ? toolbar[0].offsetHeight : 0;
var tabbarHeight = (hasTabbar && hideTabbar) ? tabbar[0].offsetHeight : 0;
var bottomBarHeight = tabbarHeight || toolbarHeight;
function handleScroll(e) {
if (pageContainer.hasClass('page-on-left')) return;
currentScroll = scrollContent[0].scrollTop;
scrollHeight = scrollContent[0].scrollHeight;
offsetHeight = scrollContent[0].offsetHeight;
reachEnd = currentScroll + offsetHeight >= scrollHeight - bottomBarHeight;
navbarHidden = navbar.hasClass('navbar-hidden');
toolbarHidden = toolbar.hasClass('toolbar-hidden');
tabbarHidden = tabbar && tabbar.hasClass('toolbar-hidden');
if (reachEnd) {
if (app.params.showBarsOnPageScrollEnd) {
action = 'show';
}
}
else if (previousScroll > currentScroll) {
if (app.params.showBarsOnPageScrollTop || currentScroll <= 44) {
action = 'show';
}
else {
action = 'hide';
}
}
else {
if (currentScroll > 44) {
action = 'hide';
}
else {
action = 'show';
}
}
if (action === 'show') {
if (hasNavbar && hideNavbar && navbarHidden) {
app.showNavbar(navbar);
pageContainer.removeClass('no-navbar-by-scroll');
navbarHidden = false;
}
if (hasToolbar && hideToolbar && toolbarHidden) {
app.showToolbar(toolbar);
pageContainer.removeClass('no-toolbar-by-scroll');
toolbarHidden = false;
}
if (hasTabbar && hideTabbar && tabbarHidden) {
app.showToolbar(tabbar);
pageContainer.removeClass('no-tabbar-by-scroll');
tabbarHidden = false;
}
}
else {
if (hasNavbar && hideNavbar && !navbarHidden) {
app.hideNavbar(navbar);
pageContainer.addClass('no-navbar-by-scroll');
navbarHidden = true;
}
if (hasToolbar && hideToolbar && !toolbarHidden) {
app.hideToolbar(toolbar);
pageContainer.addClass('no-toolbar-by-scroll');
toolbarHidden = true;
}
if (hasTabbar && hideTabbar && !tabbarHidden) {
app.hideToolbar(tabbar);
pageContainer.addClass('no-tabbar-by-scroll');
tabbarHidden = true;
}
}
previousScroll = currentScroll;
}
scrollContent.on('scroll', handleScroll);
scrollContent[0].f7ScrollToolbarsHandler = handleScroll;
};
app.destroyScrollToolbars = function (pageContainer) {
pageContainer = $(pageContainer);
var scrollContent = pageContainer.find('.page-content');
if (scrollContent.length === 0) return;
var handler = scrollContent[0].f7ScrollToolbarsHandler;
if (!handler) return;
scrollContent.off('scroll', scrollContent[0].f7ScrollToolbarsHandler);
};
/*======================================================
************ Material Tabbar ************
======================================================*/
app.materialTabbarSetHighlight = function (tabbar, activeLink) {
tabbar = $(tabbar);
activeLink = activeLink || tabbar.find('.tab-link.active');
var tabLinkWidth, highlightTranslate;
if (tabbar.hasClass('tabbar-scrollable')) {
tabLinkWidth = activeLink[0].offsetWidth + 'px';
highlightTranslate = (app.rtl ? - activeLink[0].offsetLeft: activeLink[0].offsetLeft) + 'px';
}
else {
tabLinkWidth = 1 / tabbar.find('.tab-link').length * 100 + '%';
highlightTranslate = (app.rtl ? - activeLink.index(): activeLink.index()) * 100 + '%';
}
tabbar.find('.tab-link-highlight')
.css({width: tabLinkWidth})
.transform('translate3d(' + highlightTranslate + ',0,0)');
};
app.initPageMaterialTabbar = function (pageContainer) {
pageContainer = $(pageContainer);
var tabbar = $(pageContainer).find('.tabbar');
function tabbarSetHighlight() {
app.materialTabbarSetHighlight(tabbar);
}
if (tabbar.length > 0) {
if (tabbar.find('.tab-link-highlight').length === 0) {
tabbar.find('.toolbar-inner').append('<span class="tab-link-highlight"></span>');
}
tabbarSetHighlight();
$(window).on('resize', tabbarSetHighlight);
pageContainer.once('pageBeforeRemove', function () {
$(window).off('resize', tabbarSetHighlight);
});
}
};
/* ===============================================================================
************ Tabs ************
=============================================================================== */
app.showTab = function (tab, tabLink, force) {
var newTab = $(tab);
if (arguments.length === 2) {
if (typeof tabLink === 'boolean') {
force = tabLink;
}
}
if (newTab.length === 0) return false;
if (newTab.hasClass('active')) {
if (force) newTab.trigger('show');
return false;
}
var tabs = newTab.parent('.tabs');
if (tabs.length === 0) return false;
// Return swipeouts in hidden tabs
app.allowSwipeout = true;
// Animated tabs
var isAnimatedTabs = tabs.parent().hasClass('tabs-animated-wrap');
if (isAnimatedTabs) {
var tabTranslate = (app.rtl ? newTab.index() : -newTab.index()) * 100;
tabs.transform('translate3d(' + tabTranslate + '%,0,0)');
}
// Swipeable tabs
var isSwipeableTabs = tabs.parent().hasClass('tabs-swipeable-wrap'), swiper;
if (isSwipeableTabs) {
swiper = tabs.parent()[0].swiper;
if (swiper.activeIndex !== newTab.index()) swiper.slideTo(newTab.index(), undefined, false);
}
// Remove active class from old tabs
var oldTab = tabs.children('.tab.active').removeClass('active').trigger('hide');
// Add active class to new tab
newTab.addClass('active');
// Trigger 'show' event on new tab
newTab.trigger('show');
// Update navbars in new tab
if (!isAnimatedTabs && !isSwipeableTabs && newTab.find('.navbar').length > 0) {
// Find tab's view
var viewContainer;
if (newTab.hasClass(app.params.viewClass)) viewContainer = newTab[0];
else viewContainer = newTab.parents('.' + app.params.viewClass)[0];
app.sizeNavbars(viewContainer);
}
// Find related link for new tab
if (tabLink) tabLink = $(tabLink);
else {
// Search by id
if (typeof tab === 'string') tabLink = $('.tab-link[href="' + tab + '"]');
else tabLink = $('.tab-link[href="#' + newTab.attr('id') + '"]');
// Search by data-tab
if (!tabLink || tabLink && tabLink.length === 0) {
$('[data-tab]').each(function () {
if (newTab.is($(this).attr('data-tab'))) tabLink = $(this);
});
}
}
if (tabLink.length === 0) return;
// Find related link for old tab
var oldTabLink;
if (oldTab && oldTab.length > 0) {
// Search by id
var oldTabId = oldTab.attr('id');
if (oldTabId) oldTabLink = $('.tab-link[href="#' + oldTabId + '"]');
// Search by data-tab
if (!oldTabLink || oldTabLink && oldTabLink.length === 0) {
$('[data-tab]').each(function () {
if (oldTab.is($(this).attr('data-tab'))) oldTabLink = $(this);
});
}
}
// Update links' classes
if (tabLink && tabLink.length > 0) {
tabLink.addClass('active');
// Material Highlight
if (app.params.material) {
var tabbar = tabLink.parents('.tabbar');
if (tabbar.length > 0) {
if (tabbar.find('.tab-link-highlight').length === 0) {
tabbar.find('.toolbar-inner').append('<span class="tab-link-highlight"></span>');
}
app.materialTabbarSetHighlight(tabbar, tabLink);
}
}
}
if (oldTabLink && oldTabLink.length > 0) oldTabLink.removeClass('active');
return true;
};
/*===============================================================================
************ Accordion ************
===============================================================================*/
app.accordionToggle = function (item) {
item = $(item);
if (item.length === 0) return;
if (item.hasClass('accordion-item-expanded')) app.accordionClose(item);
else app.accordionOpen(item);
};
app.accordionOpen = function (item) {
item = $(item);
var list = item.parents('.accordion-list').eq(0);
var content = item.children('.accordion-item-content');
if (content.length === 0) content = item.find('.accordion-item-content');
var expandedItem = list.length > 0 && item.parent().children('.accordion-item-expanded');
if (expandedItem.length > 0) {
app.accordionClose(expandedItem);
}
content.css('height', content[0].scrollHeight + 'px').transitionEnd(function () {
if (item.hasClass('accordion-item-expanded')) {
content.transition(0);
content.css('height', 'auto');
var clientLeft = content[0].clientLeft;
content.transition('');
item.trigger('opened');
}
else {
content.css('height', '');
item.trigger('closed');
}
});
item.trigger('open');
item.addClass('accordion-item-expanded');
};
app.accordionClose = function (item) {
item = $(item);
var content = item.children('.accordion-item-content');
if (content.length === 0) content = item.find('.accordion-item-content');
item.removeClass('accordion-item-expanded');
content.transition(0);
content.css('height', content[0].scrollHeight + 'px');
// Relayout
var clientLeft = content[0].clientLeft;
// Close
content.transition('');
content.css('height', '').transitionEnd(function () {
if (item.hasClass('accordion-item-expanded')) {
content.transition(0);
content.css('height', 'auto');
var clientLeft = content[0].clientLeft;
content.transition('');
item.trigger('opened');
}
else {
content.css('height', '');
item.trigger('closed');
}
});
item.trigger('close');
};
/*===============================================================================
************ Fast Clicks ************
************ Inspired by https://github.com/ftlabs/fastclick ************
===============================================================================*/
app.initFastClicks = function () {
if (app.params.activeState) {
$('html').addClass('watch-active-state');
}
if (app.device.ios && app.device.webView) {
// Strange hack required for iOS 8 webview to work on inputs
window.addEventListener('touchstart', function () {});
}
var touchStartX, touchStartY, touchStartTime, targetElement, trackClick, activeSelection, scrollParent, lastClickTime, isMoved, tapHoldFired, tapHoldTimeout;
var activableElement, activeTimeout, needsFastClick, needsFastClickTimeOut;
var rippleWave, rippleTarget, rippleTransform, rippleTimeout;
function findActivableElement(el) {
var target = $(el);
var parents = target.parents(app.params.activeStateElements);
var activable;
if (target.is(app.params.activeStateElements)) {
activable = target;
}
if (parents.length > 0) {
activable = activable ? activable.add(parents) : parents;
}
return activable ? activable : target;
}
function isInsideScrollableView(el) {
var pageContent = el.parents('.page-content, .panel');
if (pageContent.length === 0) {
return false;
}
// This event handler covers the "tap to stop scrolling".
if (pageContent.prop('scrollHandlerSet') !== 'yes') {
pageContent.on('scroll', function() {
clearTimeout(activeTimeout);
clearTimeout(rippleTimeout);
});
pageContent.prop('scrollHandlerSet', 'yes');
}
return true;
}
function addActive() {
if (!activableElement) return;
activableElement.addClass('active-state');
}
function removeActive(el) {
if (!activableElement) return;
activableElement.removeClass('active-state');
activableElement = null;
}
function isFormElement(el) {
var nodes = ('input select textarea label').split(' ');
if (el.nodeName && nodes.indexOf(el.nodeName.toLowerCase()) >= 0) return true;
return false;
}
function androidNeedsBlur(el) {
var noBlur = ('button input textarea select').split(' ');
if (document.activeElement && el !== document.activeElement && document.activeElement !== document.body) {
if (noBlur.indexOf(el.nodeName.toLowerCase()) >= 0) {
return false;
}
else {
return true;
}
}
else {
return false;
}
}
function targetNeedsFastClick(el) {
var $el = $(el);
if (el.nodeName.toLowerCase() === 'input' && el.type === 'file') return false;
if (el.nodeName.toLowerCase() === 'select' && app.device.android) return false;
if ($el.hasClass('no-fastclick') || $el.parents('.no-fastclick').length > 0) return false;
if (app.params.fastClicksExclude && $el.is(app.params.fastClicksExclude)) return false;
return true;
}
function targetNeedsFocus(el) {
if (document.activeElement === el) {
return false;
}
var tag = el.nodeName.toLowerCase();
var skipInputs = ('button checkbox file image radio submit').split(' ');
if (el.disabled || el.readOnly) return false;
if (tag === 'textarea') return true;
if (tag === 'select') {
if (app.device.android) return false;
else return true;
}
if (tag === 'input' && skipInputs.indexOf(el.type) < 0) return true;
}
function targetNeedsPrevent(el) {
el = $(el);
var prevent = true;
if (el.is('label') || el.parents('label').length > 0) {
if (app.device.android) {
prevent = false;
}
else if (app.device.ios && el.is('input')) {
prevent = true;
}
else prevent = false;
}
return prevent;
}
// Mouse Handlers
function handleMouseDown (e) {
findActivableElement(e.target).addClass('active-state');
if ('which' in e && e.which === 3) {
setTimeout(function () {
$('.active-state').removeClass('active-state');
}, 0);
}
if (app.params.material && app.params.materialRipple) {
touchStartX = e.pageX;
touchStartY = e.pageY;
rippleTouchStart(e.target, e.pageX, e.pageY);
}
}
function handleMouseMove (e) {
$('.active-state').removeClass('active-state');
if (app.params.material && app.params.materialRipple) {
rippleTouchMove();
}
}
function handleMouseUp (e) {
$('.active-state').removeClass('active-state');
if (app.params.material && app.params.materialRipple) {
rippleTouchEnd();
}
}
// Material Touch Ripple Effect
function findRippleElement(el) {
var needsRipple = app.params.materialRippleElements;
var $el = $(el);
if ($el.is(needsRipple)) {
if ($el.hasClass('no-ripple')) {
return false;
}
return $el;
}
else if ($el.parents(needsRipple).length > 0) {
var rippleParent = $el.parents(needsRipple).eq(0);
if (rippleParent.hasClass('no-ripple')) {
return false;
}
return rippleParent;
}
else return false;
}
function createRipple(x, y, el) {
var box = el[0].getBoundingClientRect();
var center = {
x: x - box.left,
y: y - box.top
},
height = box.height,
width = box.width;
var diameter = Math.max(Math.pow((Math.pow(height, 2) + Math.pow(width, 2)), 0.5), 48);
rippleWave = $(
'<div class="ripple-wave" style="width: ' + diameter + 'px; height: '+diameter+'px; margin-top:-'+diameter/2+'px; margin-left:-'+diameter/2+'px; left:'+center.x+'px; top:'+center.y+'px;"></div>'
);
el.prepend(rippleWave);
var clientLeft = rippleWave[0].clientLeft;
rippleTransform = 'translate3d('+(-center.x + width/2)+'px, '+(-center.y + height/2)+'px, 0) scale(1)';
rippleWave.transform(rippleTransform);
}
function removeRipple() {
if (!rippleWave) return;
var toRemove = rippleWave;
var removeTimeout = setTimeout(function () {
toRemove.remove();
}, 400);
rippleWave
.addClass('ripple-wave-fill')
.transform(rippleTransform.replace('scale(1)', 'scale(1.01)'))
.transitionEnd(function () {
clearTimeout(removeTimeout);
var rippleWave = $(this)
.addClass('ripple-wave-out')
.transform(rippleTransform.replace('scale(1)', 'scale(1.01)'));
removeTimeout = setTimeout(function () {
rippleWave.remove();
}, 700);
setTimeout(function () {
rippleWave.transitionEnd(function(){
clearTimeout(removeTimeout);
$(this).remove();
});
}, 0);
});
rippleWave = rippleTarget = undefined;
}
function rippleTouchStart (el, x, y) {
rippleTarget = findRippleElement(el);
if (!rippleTarget || rippleTarget.length === 0) {
rippleTarget = undefined;
return;
}
if (!isInsideScrollableView(rippleTarget)) {
createRipple(touchStartX, touchStartY, rippleTarget);
}
else {
rippleTimeout = setTimeout(function () {
createRipple(touchStartX, touchStartY, rippleTarget);
}, 80);
}
}
function rippleTouchMove() {
clearTimeout(rippleTimeout);
removeRipple();
}
function rippleTouchEnd() {
if (rippleWave) {
removeRipple();
}
else if (rippleTarget && !isMoved) {
clearTimeout(rippleTimeout);
createRipple(touchStartX, touchStartY, rippleTarget);
setTimeout(removeRipple, 0);
}
else {
removeRipple();
}
}
// Send Click
function sendClick(e) {
var touch = e.changedTouches[0];
var evt = document.createEvent('MouseEvents');
var eventType = 'click';
if (app.device.android && targetElement.nodeName.toLowerCase() === 'select') {
eventType = 'mousedown';
}
evt.initMouseEvent(eventType, true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null);
evt.forwardedTouchEvent = true;
targetElement.dispatchEvent(evt);
}
// Touch Handlers
function handleTouchStart(e) {
isMoved = false;
tapHoldFired = false;
if (e.targetTouches.length > 1) {
if (activableElement) removeActive();
return true;
}
if (e.touches.length > 1 && activableElement) {
removeActive();
}
if (app.params.tapHold) {
if (tapHoldTimeout) clearTimeout(tapHoldTimeout);
tapHoldTimeout = setTimeout(function () {
if (e && e.touches && e.touches.length > 1) return;
tapHoldFired = true;
e.preventDefault();
$(e.target).trigger('taphold');
}, app.params.tapHoldDelay);
}
if (needsFastClickTimeOut) clearTimeout(needsFastClickTimeOut);
needsFastClick = targetNeedsFastClick(e.target);
if (!needsFastClick) {
trackClick = false;
return true;
}
if (app.device.ios || (app.device.android && 'getSelection' in window)) {
var selection = window.getSelection();
if (selection.rangeCount && selection.focusNode !== document.body && (!selection.isCollapsed || document.activeElement === selection.focusNode)) {
activeSelection = true;
return true;
}
else {
activeSelection = false;
}
}
if (app.device.android) {
if (androidNeedsBlur(e.target)) {
document.activeElement.blur();
}
}
trackClick = true;
targetElement = e.target;
touchStartTime = (new Date()).getTime();
touchStartX = e.targetTouches[0].pageX;
touchStartY = e.targetTouches[0].pageY;
// Detect scroll parent
if (app.device.ios) {
scrollParent = undefined;
$(targetElement).parents().each(function () {
var parent = this;
if (parent.scrollHeight > parent.offsetHeight && !scrollParent) {
scrollParent = parent;
scrollParent.f7ScrollTop = scrollParent.scrollTop;
}
});
}
if ((e.timeStamp - lastClickTime) < app.params.fastClicksDelayBetweenClicks) {
e.preventDefault();
}
if (app.params.activeState) {
activableElement = findActivableElement(targetElement);
// If it's inside a scrollable view, we don't trigger active-state yet,
// because it can be a scroll instead. Based on the link:
// http://labnote.beedesk.com/click-scroll-and-pseudo-active-on-mobile-webk
if (!isInsideScrollableView(activableElement)) {
addActive();
} else {
activeTimeout = setTimeout(addActive, 80);
}
}
if (app.params.material && app.params.materialRipple) {
rippleTouchStart(targetElement, touchStartX, touchStartY);
}
}
function handleTouchMove(e) {
if (!trackClick) return;
var _isMoved = false;
var distance = app.params.fastClicksDistanceThreshold;
if (distance) {
var pageX = e.targetTouches[0].pageX;
var pageY = e.targetTouches[0].pageY;
if (Math.abs(pageX - touchStartX) > distance || Math.abs(pageY - touchStartY) > distance) {
_isMoved = true;
}
}
else {
_isMoved = true;
}
if (_isMoved) {
trackClick = false;
targetElement = null;
isMoved = true;
if (app.params.tapHold) {
clearTimeout(tapHoldTimeout);
}
if (app.params.activeState) {
clearTimeout(activeTimeout);
removeActive();
}
if (app.params.material && app.params.materialRipple) {
rippleTouchMove();
}
}
}
function handleTouchEnd(e) {
clearTimeout(activeTimeout);
clearTimeout(tapHoldTimeout);
if (!trackClick) {
if (!activeSelection && needsFastClick) {
if (!(app.device.android && !e.cancelable)) {
e.preventDefault();
}
}
return true;
}
if (document.activeElement === e.target) {
if (app.params.activeState) removeActive();
if (app.params.material && app.params.materialRipple) {
rippleTouchEnd();
}
return true;
}
if (!activeSelection) {
e.preventDefault();
}
if ((e.timeStamp - lastClickTime) < app.params.fastClicksDelayBetweenClicks) {
setTimeout(removeActive, 0);
return true;
}
lastClickTime = e.timeStamp;
trackClick = false;
if (app.device.ios && scrollParent) {
if (scrollParent.scrollTop !== scrollParent.f7ScrollTop) {
return false;
}
}
// Add active-state here because, in a very fast tap, the timeout didn't
// have the chance to execute. Removing active-state in a timeout gives
// the chance to the animation execute.
if (app.params.activeState) {
addActive();
setTimeout(removeActive, 0);
}
// Remove Ripple
if (app.params.material && app.params.materialRipple) {
rippleTouchEnd();
}
// Trigger focus when required
if (targetNeedsFocus(targetElement)) {
if (app.device.ios && app.device.webView) {
if ((event.timeStamp - touchStartTime) > 159) {
targetElement = null;
return false;
}
targetElement.focus();
return false;
}
else {
targetElement.focus();
}
}
// Blur active elements
if (document.activeElement && targetElement !== document.activeElement && document.activeElement !== document.body && targetElement.nodeName.toLowerCase() !== 'label') {
document.activeElement.blur();
}
// Send click
e.preventDefault();
sendClick(e);
return false;
}
function handleTouchCancel(e) {
trackClick = false;
targetElement = null;
// Remove Active State
clearTimeout(activeTimeout);
clearTimeout(tapHoldTimeout);
if (app.params.activeState) {
removeActive();
}
// Remove Ripple
if (app.params.material && app.params.materialRipple) {
rippleTouchEnd();
}
}
function handleClick(e) {
var allowClick = false;
if (trackClick) {
targetElement = null;
trackClick = false;
return true;
}
if (e.target.type === 'submit' && e.detail === 0) {
return true;
}
if (!targetElement) {
if (!isFormElement(e.target)) {
allowClick = true;
}
}
if (!needsFastClick) {
allowClick = true;
}
if (document.activeElement === targetElement) {
allowClick = true;
}
if (e.forwardedTouchEvent) {
allowClick = true;
}
if (!e.cancelable) {
allowClick = true;
}
if (app.params.tapHold && app.params.tapHoldPreventClicks && tapHoldFired) {
allowClick = false;
}
if (!allowClick) {
e.stopImmediatePropagation();
e.stopPropagation();
if (targetElement) {
if (targetNeedsPrevent(targetElement) || isMoved) {
e.preventDefault();
}
}
else {
e.preventDefault();
}
targetElement = null;
}
needsFastClickTimeOut = setTimeout(function () {
needsFastClick = false;
}, (app.device.ios || app.device.androidChrome ? 100 : 400));
if (app.params.tapHold) {
tapHoldTimeout = setTimeout(function () {
tapHoldFired = false;
}, (app.device.ios || app.device.androidChrome ? 100 : 400));
}
return allowClick;
}
if (app.support.touch) {
document.addEventListener('click', handleClick, true);
document.addEventListener('touchstart', handleTouchStart);
document.addEventListener('touchmove', handleTouchMove);
document.addEventListener('touchend', handleTouchEnd);
document.addEventListener('touchcancel', handleTouchCancel);
}
else {
if (app.params.activeState) {
document.addEventListener('mousedown', handleMouseDown);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
}
}
if (app.params.material && app.params.materialRipple) {
document.addEventListener('contextmenu', function (e) {
if (activableElement) removeActive();
rippleTouchEnd();
});
}
};
/*===============================================================================
************ Handle clicks and make them fast (on tap); ************
===============================================================================*/
app.initClickEvents = function () {
function handleScrollTop(e) {
/*jshint validthis:true */
var clicked = $(this);
var target = $(e.target);
var isLink = clicked[0].nodeName.toLowerCase() === 'a' ||
clicked.parents('a').length > 0 ||
target[0].nodeName.toLowerCase() === 'a' ||
target.parents('a').length > 0;
if (isLink) return;
var pageContent, page;
if (app.params.scrollTopOnNavbarClick && clicked.is('.navbar .center')) {
// Find active page
var navbar = clicked.parents('.navbar');
// Static Layout
pageContent = navbar.parents('.page-content');
if (pageContent.length === 0) {
// Fixed Layout
if (navbar.parents('.page').length > 0) {
pageContent = navbar.parents('.page').find('.page-content');
}
// Through Layout
if (pageContent.length === 0) {
if (navbar.nextAll('.pages').length > 0) {
pageContent = navbar.nextAll('.pages').find('.page:not(.page-on-left):not(.page-on-right):not(.cached)').find('.page-content');
}
}
}
}
if (app.params.scrollTopOnStatusbarClick && clicked.is('.statusbar-overlay')) {
if ($('.popup.modal-in').length > 0) {
// Check for opened popup
pageContent = $('.popup.modal-in').find('.page:not(.page-on-left):not(.page-on-right):not(.cached)').find('.page-content');
}
else if ($('.panel.active').length > 0) {
// Check for opened panel
pageContent = $('.panel.active').find('.page:not(.page-on-left):not(.page-on-right):not(.cached)').find('.page-content');
}
else if ($('.views > .view.active').length > 0) {
// View in tab bar app layout
pageContent = $('.views > .view.active').find('.page:not(.page-on-left):not(.page-on-right):not(.cached)').find('.page-content');
}
else {
// Usual case
pageContent = $('.views').find('.page:not(.page-on-left):not(.page-on-right):not(.cached)').find('.page-content');
}
}
if (pageContent && pageContent.length > 0) {
// Check for tab
if (pageContent.hasClass('tab')) {
pageContent = pageContent.parent('.tabs').children('.page-content.active');
}
if (pageContent.length > 0) pageContent.scrollTop(0, 300);
}
}
function handleClicks(e) {
/*jshint validthis:true */
var clicked = $(this);
var url = clicked.attr('href');
var isLink = clicked[0].nodeName.toLowerCase() === 'a';
// Check if link is external
if (isLink) {
if (clicked.is(app.params.externalLinks) || (url && url.indexOf('javascript:') >= 0)) {
if(url && clicked.attr('target') === '_system') {
e.preventDefault();
window.open(url, '_system');
}
return;
}
}
// Collect Clicked data- attributes
var clickedData = clicked.dataset();
// Smart Select
if (clicked.hasClass('smart-select')) {
if (app.smartSelectOpen) app.smartSelectOpen(clicked);
}
// Open Panel
if (clicked.hasClass('open-panel')) {
if ($('.panel').length === 1) {
if ($('.panel').hasClass('panel-left')) app.openPanel('left');
else app.openPanel('right');
}
else {
if (clickedData.panel === 'right') app.openPanel('right');
else app.openPanel('left');
}
}
// Close Panel
if (clicked.hasClass('close-panel')) {
app.closePanel();
}
if (clicked.hasClass('panel-overlay') && app.params.panelsCloseByOutside) {
app.closePanel();
}
// Popover
if (clicked.hasClass('open-popover')) {
var popover;
if (clickedData.popover) {
popover = clickedData.popover;
}
else popover = '.popover';
app.popover(popover, clicked);
}
if (clicked.hasClass('close-popover')) {
app.closeModal('.popover.modal-in');
}
// Popup
var popup;
if (clicked.hasClass('open-popup')) {
if (clickedData.popup) {
popup = clickedData.popup;
}
else popup = '.popup';
app.popup(popup);
}
if (clicked.hasClass('close-popup')) {
if (clickedData.popup) {
popup = clickedData.popup;
}
else popup = '.popup.modal-in';
app.closeModal(popup);
}
// Login Screen
var loginScreen;
if (clicked.hasClass('open-login-screen')) {
if (clickedData.loginScreen) {
loginScreen = clickedData.loginScreen;
}
else loginScreen = '.login-screen';
app.loginScreen(loginScreen);
}
if (clicked.hasClass('close-login-screen')) {
app.closeModal('.login-screen.modal-in');
}
// Close Modal
if (clicked.hasClass('modal-overlay')) {
if ($('.modal.modal-in').length > 0 && app.params.modalCloseByOutside)
app.closeModal('.modal.modal-in');
if ($('.actions-modal.modal-in').length > 0 && app.params.actionsCloseByOutside)
app.closeModal('.actions-modal.modal-in');
if ($('.popover.modal-in').length > 0) app.closeModal('.popover.modal-in');
}
if (clicked.hasClass('popup-overlay')) {
if ($('.popup.modal-in').length > 0 && app.params.popupCloseByOutside)
app.closeModal('.popup.modal-in');
}
if (clicked.hasClass('picker-modal-overlay')) {
if ($('.picker-modal.modal-in').length > 0)
app.closeModal('.picker-modal.modal-in');
}
// Picker
if (clicked.hasClass('close-picker')) {
var pickerToClose = $('.picker-modal.modal-in');
if (pickerToClose.length > 0) {
app.closeModal(pickerToClose);
}
else {
pickerToClose = $('.popover.modal-in .picker-modal');
if (pickerToClose.length > 0) {
app.closeModal(pickerToClose.parents('.popover'));
}
}
}
if (clicked.hasClass('open-picker')) {
var pickerToOpen;
if (clickedData.picker) {
pickerToOpen = clickedData.picker;
}
else pickerToOpen = '.picker-modal';
app.pickerModal(pickerToOpen, clicked);
}
// Tabs
var isTabLink;
if (clicked.hasClass('tab-link')) {
isTabLink = true;
app.showTab(clickedData.tab || clicked.attr('href'), clicked);
}
// Swipeout Close
if (clicked.hasClass('swipeout-close')) {
app.swipeoutClose(clicked.parents('.swipeout-opened'));
}
// Swipeout Delete
if (clicked.hasClass('swipeout-delete')) {
if (clickedData.confirm) {
var text = clickedData.confirm;
var title = clickedData.confirmTitle;
if (title) {
app.confirm(text, title, function () {
app.swipeoutDelete(clicked.parents('.swipeout'));
}, function () {
if (clickedData.closeOnCancel) app.swipeoutClose(clicked.parents('.swipeout'));
});
}
else {
app.confirm(text, function () {
app.swipeoutDelete(clicked.parents('.swipeout'));
}, function () {
if (clickedData.closeOnCancel) app.swipeoutClose(clicked.parents('.swipeout'));
});
}
}
else {
app.swipeoutDelete(clicked.parents('.swipeout'));
}
}
// Sortable
if (clicked.hasClass('toggle-sortable')) {
app.sortableToggle(clickedData.sortable);
}
if (clicked.hasClass('open-sortable')) {
app.sortableOpen(clickedData.sortable);
}
if (clicked.hasClass('close-sortable')) {
app.sortableClose(clickedData.sortable);
}
// Accordion
if (clicked.hasClass('accordion-item-toggle') || (clicked.hasClass('item-link') && clicked.parent().hasClass('accordion-item'))) {
var accordionItem = clicked.parent('.accordion-item');
if (accordionItem.length === 0) accordionItem = clicked.parents('.accordion-item');
if (accordionItem.length === 0) accordionItem = clicked.parents('li');
app.accordionToggle(accordionItem);
}
// Speed Dial
if (clicked.hasClass('floating-button') && clicked.parent().hasClass('speed-dial')) {
clicked.parent().toggleClass('speed-dial-opened');
}
if (clicked.hasClass('close-speed-dial')) {
$('.speed-dial-opened').removeClass('speed-dial-opened');
}
// Load Page
if (app.params.ajaxLinks && !clicked.is(app.params.ajaxLinks) || !isLink || !app.params.router) {
return;
}
if (isLink) {
e.preventDefault();
}
var validUrl = url && url.length > 0 && url !== '#' && !isTabLink;
var template = clickedData.template;
if (validUrl || clicked.hasClass('back') || template) {
var view;
if (clickedData.view) {
view = $(clickedData.view)[0].f7View;
}
else {
view = clicked.parents('.' + app.params.viewClass)[0] && clicked.parents('.' + app.params.viewClass)[0].f7View;
if (view && view.params.linksView) {
if (typeof view.params.linksView === 'string') view = $(view.params.linksView)[0].f7View;
else if (view.params.linksView instanceof View) view = view.params.linksView;
}
}
if (!view) {
if (app.mainView) view = app.mainView;
}
if (!view) return;
var pageName;
if (!template) {
if (url && url.indexOf('#') === 0 && url !== '#') {
if (view.params.domCache) {
pageName = url.split('#')[1];
}
else return;
}
if (url === '#' && !clicked.hasClass('back')) return;
}
else {
url = undefined;
}
var animatePages;
if (typeof clickedData.animatePages !== 'undefined') {
animatePages = clickedData.animatePages;
}
else {
if (clicked.hasClass('with-animation')) animatePages = true;
if (clicked.hasClass('no-animation')) animatePages = false;
}
var options = {
animatePages: animatePages,
ignoreCache: clickedData.ignoreCache,
force: clickedData.force,
reload: clickedData.reload,
reloadPrevious: clickedData.reloadPrevious,
pageName: pageName,
pushState: clickedData.pushState,
url: url
};
if (app.params.template7Pages) {
options.contextName = clickedData.contextName;
var context = clickedData.context;
if (context) {
options.context = JSON.parse(context);
}
}
if (template && template in t7.templates) {
options.template = t7.templates[template];
}
if (clicked.hasClass('back')) view.router.back(options);
else view.router.load(options);
}
}
$(document).on('click', 'a, .open-panel, .close-panel, .panel-overlay, .modal-overlay, .popup-overlay, .swipeout-delete, .swipeout-close, .close-popup, .open-popup, .open-popover, .open-login-screen, .close-login-screen .smart-select, .toggle-sortable, .open-sortable, .close-sortable, .accordion-item-toggle, .close-picker, .picker-modal-overlay', handleClicks);
if (app.params.scrollTopOnNavbarClick || app.params.scrollTopOnStatusbarClick) {
$(document).on('click', '.statusbar-overlay, .navbar .center', handleScrollTop);
}
// Prevent scrolling on overlays
function preventScrolling(e) {
e.preventDefault();
}
if (app.support.touch && !app.device.android) {
$(document).on((app.params.fastClicks ? 'touchstart' : 'touchmove'), '.panel-overlay, .modal-overlay, .preloader-indicator-overlay, .popup-overlay, .searchbar-overlay', preventScrolling);
}
};
/*======================================================
************ App Resize Actions ************
======================================================*/
// Prevent iPad horizontal body scrolling when soft keyboard is opened
function _fixIpadBodyScrolLeft() {
if (app.device.ipad) {
document.body.scrollLeft = 0;
setTimeout(function () {
document.body.scrollLeft = 0;
}, 0);
}
}
app.initResize = function () {
$(window).on('resize', app.resize);
$(window).on('orientationchange', app.orientationchange);
};
app.resize = function () {
if (app.sizeNavbars) app.sizeNavbars();
_fixIpadBodyScrolLeft();
};
app.orientationchange = function () {
if (app.device && app.device.minimalUi) {
if (window.orientation === 90 || window.orientation === -90) document.body.scrollTop = 0;
}
_fixIpadBodyScrolLeft();
};
/*===============================================================================
************ Store and parse forms data ************
===============================================================================*/
app.formsData = {};
app.formStoreData = function (formId, formJSON) {
// Store form data in app.formsData
app.formsData[formId] = formJSON;
// Store form data in local storage also
app.ls['f7form-' + formId] = JSON.stringify(formJSON);
};
app.formDeleteData = function (formId) {
// Delete form data from app.formsData
if (app.formsData[formId]) {
app.formsData[formId] = '';
delete app.formsData[formId];
}
// Delete form data from local storage also
if (app.ls['f7form-' + formId]) {
app.ls['f7form-' + formId] = '';
app.ls.removeItem('f7form-' + formId);
}
};
app.formGetData = function (formId) {
// First of all check in local storage
if (app.ls['f7form-' + formId]) {
return JSON.parse(app.ls['f7form-' + formId]);
}
// Try to get it from formsData obj
else if (app.formsData[formId]) return app.formsData[formId];
};
app.formToData = function (form) {
form = $(form);
if (form.length !== 1) return false;
// Form data
var formData = {};
// Skip input types
var skipTypes = ['submit', 'image', 'button', 'file'];
var skipNames = [];
form.find('input, select, textarea').each(function () {
var input = $(this);
var name = input.attr('name');
var type = input.attr('type');
var tag = this.nodeName.toLowerCase();
if (skipTypes.indexOf(type) >= 0) return;
if (skipNames.indexOf(name) >= 0 || !name) return;
if (tag === 'select' && input.prop('multiple')) {
skipNames.push(name);
formData[name] = [];
form.find('select[name="' + name + '"] option').each(function () {
if (this.selected) formData[name].push(this.value);
});
}
else {
switch (type) {
case 'checkbox' :
skipNames.push(name);
formData[name] = [];
form.find('input[name="' + name + '"]').each(function () {
if (this.checked) formData[name].push(this.value);
});
break;
case 'radio' :
skipNames.push(name);
form.find('input[name="' + name + '"]').each(function () {
if (this.checked) formData[name] = this.value;
});
break;
default :
formData[name] = input.val();
break;
}
}
});
form.trigger('formToJSON formToData', {formData: formData});
return formData;
};
app.formToJSON = app.formToData;
app.formFromData = function (form, formData) {
form = $(form);
if (form.length !== 1) return false;
// Skip input types
var skipTypes = ['submit', 'image', 'button', 'file'];
var skipNames = [];
form.find('input, select, textarea').each(function () {
var input = $(this);
var name = input.attr('name');
var type = input.attr('type');
var tag = this.nodeName.toLowerCase();
if (!formData[name]) return;
if (skipTypes.indexOf(type) >= 0) return;
if (skipNames.indexOf(name) >= 0 || !name) return;
if (tag === 'select' && input.prop('multiple')) {
skipNames.push(name);
form.find('select[name="' + name + '"] option').each(function () {
if (formData[name].indexOf(this.value) >= 0) this.selected = true;
else this.selected = false;
});
}
else {
switch (type) {
case 'checkbox' :
skipNames.push(name);
form.find('input[name="' + name + '"]').each(function () {
if (formData[name].indexOf(this.value) >= 0) this.checked = true;
else this.checked = false;
});
break;
case 'radio' :
skipNames.push(name);
form.find('input[name="' + name + '"]').each(function () {
if (formData[name] === this.value) this.checked = true;
else this.checked = false;
});
break;
default :
input.val(formData[name]);
break;
}
}
if (tag === 'select' && input.parents('.smart-select').length > 0) {
input.trigger('change');
}
});
form.trigger('formFromJSON formFromData', {formData: formData});
};
app.formFromJSON = app.formFromData;
app.initFormsStorage = function (pageContainer) {
pageContainer = $(pageContainer);
var forms = pageContainer.find('form.store-data');
if (forms.length === 0) return;
// Parse forms data and fill form if there is such data
forms.each(function () {
var id = this.getAttribute('id');
if (!id) return;
var formData = app.formGetData(id);
if (formData) app.formFromData(this, formData);
});
// Update forms data on inputs change
function storeForm() {
/*jshint validthis:true */
var form = $(this);
var formId = form[0].id;
if (!formId) return;
var formJSON = app.formToData(form);
if (!formJSON) return;
app.formStoreData(formId, formJSON);
form.trigger('store', {data: formJSON});
}
forms.on('change submit', storeForm);
// Detach Listeners
function pageBeforeRemove() {
forms.off('change submit', storeForm);
pageContainer.off('pageBeforeRemove', pageBeforeRemove);
}
pageContainer.on('pageBeforeRemove', pageBeforeRemove);
};
/*===============================================================================
************ Ajax submit for forms ************
===============================================================================*/
// Ajax submit on forms
$(document).on('submit change', 'form.ajax-submit, form.ajax-submit-onchange', function (e) {
var form = $(this);
if (e.type === 'change' && !form.hasClass('ajax-submit-onchange')) return;
if (e.type === 'submit') e.preventDefault();
var method = (form.attr('method') || 'GET').toUpperCase();
var contentType = form.prop('enctype') || form.attr('enctype');
var url = form.attr('action');
if (!url) return;
var data;
if (method === 'POST') data = new FormData(form[0]);
else data = $.serializeObject(app.formToJSON(form[0]));
var xhr = $.ajax({
method: method,
url: url,
contentType: contentType,
data: data,
beforeSend: function (xhr) {
form.trigger('beforeSubmit', {data:data, xhr: xhr});
},
error: function (xhr) {
form.trigger('submitError', {data:data, xhr: xhr});
},
success: function (data) {
form.trigger('submitted', {data: data, xhr: xhr});
}
});
});
/*===============================================================================
************ Resizable textarea ************
===============================================================================*/
app.resizeTextarea = function (textarea) {
textarea = $(textarea);
if (!textarea.hasClass('resizable')) {
return;
}
textarea.css({'height': ''});
var height = textarea[0].offsetHeight;
var diff = height - textarea[0].clientHeight;
var scrollHeight = textarea[0].scrollHeight;
if (scrollHeight + diff > height) {
var newAreaHeight = scrollHeight + diff;
textarea.css('height', newAreaHeight + 'px');
}
};
app.resizableTextarea = function (textarea) {
textarea = $(textarea);
if (textarea.length === 0) return;
var textareaTimeout;
function handleTextarea() {
clearTimeout(textareaTimeout);
textareaTimeout = setTimeout(function () {
app.resizeTextarea(textarea);
}, 0);
}
textarea[0].f7DestroyResizableTextarea = function () {
textarea.off('change keydown keypress keyup paste cut', handleTextarea);
};
return textarea.on('change keydown keypress keyup paste cut', handleTextarea);
};
app.destroyResizableTextarea = function (pageContainer) {
pageContainer = $(pageContainer);
if (pageContainer.length > 0 && pageContainer.is('textarea') && pageContainer[0].f7DestroyResizableTextarea) {
pageContainer[0].f7DestroyResizableTextarea();
}
else if (pageContainer.length > 0) {
pageContainer.find('textarea.resiable').each(function () {
var textarea = this;
if (textarea.f7DestroyResizableTextarea) {
textarea.f7DestroyResizableTextarea ();
}
});
}
};
app.initPageResizableTextarea = function (pageContainer) {
pageContainer = $(pageContainer);
var textareas = pageContainer.find('textarea.resizable');
textareas.each(function () {
app.resizableTextarea(this);
});
};
/*======================================================
************ Material Text Inputs ************
======================================================*/
app.initPageMaterialInputs = function (pageContainer) {
pageContainer = $(pageContainer);
var textareas = pageContainer.find('textarea.resizable');
pageContainer.find('.item-input').each(function () {
var itemInput = $(this);
var notInputs = ['checkbox', 'button', 'submit', 'range', 'radio', 'image'];
itemInput.find('input, select, textarea').each(function () {
var input = $(this);
if (notInputs.indexOf(input.attr('type')) < 0) {
itemInput.addClass('item-input-field');
if (input.val().trim() !== '') {
input.parents('.item-input, .input-field').add(input.parents('.item-inner')).addClass('not-empty-state');
}
}
});
if (itemInput.parents('.input-item, .inputs-list').length > 0) return;
itemInput.parents('.list-block').eq(0).addClass('inputs-list');
});
};
/*======================================================
************ Material Focus Inputs ************
======================================================*/
app.initMaterialWatchInputs = function () {
var notInputs = ['checkbox', 'button', 'submit', 'range', 'radio', 'image'];
function addFocusState(e) {
/*jshint validthis:true*/
var i = $(this);
var type = i.attr('type');
if (notInputs.indexOf(type) >= 0) return;
var els = i.add(i.parents('.item-input, .input-field')).add(i.parents('.item-inner').eq(0));
els.addClass('focus-state');
}
function removeFocusState(e) {
/*jshint validthis:true*/
var i = $(this), value = i.val();
var type = i.attr('type');
if (notInputs.indexOf(type) >= 0) return;
var els = i.add(i.parents('.item-input, .input-field')).add(i.parents('.item-inner').eq(0));
els.removeClass('focus-state');
if (value && value.trim() !== '') {
els.addClass('not-empty-state');
}
else {
els.removeClass('not-empty-state');
}
}
function watchChangeState(e) {
/*jshint validthis:true*/
var i = $(this), value = i.val();
var type = i.attr('type');
if (notInputs.indexOf(type) >= 0) return;
var els = i.add(i.parents('.item-input, .input-field')).add(i.parents('.item-inner').eq(0));
if (value && value.trim() !== '') {
els.addClass('not-empty-state');
}
else {
els.removeClass('not-empty-state');
}
}
$(document).on('change', '.item-input input, .item-input select, .item-input textarea, input, textarea, select', watchChangeState, true);
$(document).on('focus', '.item-input input, .item-input select, .item-input textarea, input, textarea, select', addFocusState, true);
$(document).on('blur', '.item-input input, .item-input select, .item-input textarea, input, textarea, select', removeFocusState, true);
};
/*======================================================
************ Handle Browser's History ************
======================================================*/
app.pushStateQueue = [];
app.pushStateClearQueue = function () {
if (app.pushStateQueue.length === 0) return;
var queue = app.pushStateQueue.pop();
var animatePages;
if (app.params.pushStateNoAnimation === true) animatePages = false;
if (queue.action === 'back') {
app.router.back(queue.view, {animatePages: animatePages});
}
if (queue.action === 'loadPage') {
app.router.load(queue.view, {url: queue.stateUrl, animatePages: animatePages, pushState: false});
}
if (queue.action === 'loadContent') {
app.router.load(queue.view, {content: queue.stateContent, animatePages: animatePages, pushState: false});
}
if (queue.action === 'loadPageName') {
app.router.load(queue.view, {pageName: queue.statePageName, url: queue.stateUrl, animatePages: animatePages, pushState: false});
}
};
app.initPushState = function () {
var blockPopstate = true;
$(window).on('load', function () {
setTimeout(function () {
blockPopstate = false;
}, 0);
});
if (document.readyState && document.readyState === 'complete') {
blockPopstate = false;
}
function handlePopState(e) {
if (blockPopstate) return;
var mainView = app.mainView;
if (!mainView) return;
var state = e.state;
if (!state) {
state = {
viewIndex: app.views.indexOf(mainView),
url : mainView.history[0]
};
}
if (state.viewIndex < 0) return;
var view = app.views[state.viewIndex];
var stateUrl = state && state.url || undefined;
var stateContent = state && state.content || undefined;
var statePageName = state && state.pageName || undefined;
var animatePages;
if (app.params.pushStateNoAnimation === true) animatePages = false;
if (stateUrl !== view.url) {
if (view.history.indexOf(stateUrl) >= 0) {
// Go Back
if (view.allowPageChange) {
app.router.back(view, {url:undefined, animatePages: animatePages, pushState: false, preloadOnly:false});
}
else {
app.pushStateQueue.push({
action: 'back',
view: view
});
}
}
else if (stateContent) {
// Load Page
if (view.allowPageChange) {
app.router.load(view, {content:stateContent, animatePages: animatePages, pushState: false});
}
else {
app.pushStateQueue.unshift({
action: 'loadContent',
stateContent: stateContent,
view: view
});
}
}
else if (statePageName) {
// Load Page by page name with Dom Cache
if (view.allowPageChange) {
app.router.load(view, {pageName:statePageName, url: stateUrl, animatePages: animatePages, pushState: false});
}
else {
app.pushStateQueue.unshift({
action: 'loadPageName',
statePageName: statePageName,
view: view
});
}
}
else {
// Load Page
if (view.allowPageChange) {
app.router.load(view, {url:stateUrl, animatePages: animatePages, pushState: false});
}
else {
app.pushStateQueue.unshift({
action: 'loadPage',
stateUrl: stateUrl,
view: view
});
}
}
}
}
$(window).on('popstate', handlePopState);
};
/*===========================
Framework7 Swiper Additions
===========================*/
app.swiper = function (container, params) {
return new Swiper(container, params);
};
app.initPageSwiper = function (pageContainer) {
pageContainer = $(pageContainer);
var swipers = pageContainer.find('.swiper-init, .tabs-swipeable-wrap');
if (swipers.length === 0) return;
function destroySwiperOnRemove(slider) {
function destroySwiper() {
slider.destroy();
pageContainer.off('pageBeforeRemove', destroySwiper);
}
pageContainer.on('pageBeforeRemove', destroySwiper);
}
swipers.each(function () {
var swiper = $(this), initialSlide;
var params;
if (swiper.hasClass('tabs-swipeable-wrap')) {
swiper.addClass('swiper-container').children('.tabs').addClass('swiper-wrapper').children('.tab').addClass('swiper-slide');
initialSlide = swiper.children('.tabs').children('.tab.active').index();
}
if (swiper.data('swiper')) {
params = JSON.parse(swiper.data('swiper'));
}
else {
params = swiper.dataset();
}
if (typeof params.initialSlide === 'undefined' && typeof initialSlide !== 'undefined') {
params.initialSlide = initialSlide;
}
if (swiper.hasClass('tabs-swipeable-wrap')) {
params.onSlideChangeStart = function (s) {
app.showTab(s.slides.eq(s.activeIndex));
};
}
var _slider = app.swiper(swiper[0], params);
destroySwiperOnRemove(_slider);
});
};
app.reinitPageSwiper = function (pageContainer) {
pageContainer = $(pageContainer);
var sliders = pageContainer.find('.swiper-init, .tabs-swipeable-wrap');
if (sliders.length === 0) return;
for (var i = 0; i < sliders.length; i++) {
var sliderInstance = sliders[0].swiper;
if (sliderInstance) {
sliderInstance.update(true);
}
}
};
/*======================================================
************ Photo Browser ************
======================================================*/
var PhotoBrowser = function (params) {
var pb = this, i;
var defaults = {
photos : [],
initialSlide: 0,
spaceBetween: 20,
speed: 300,
zoom: true,
zoomMax: 3,
zoomMin: 1,
exposition: true,
expositionHideCaptions: false,
type: 'standalone',
navbar: true,
toolbar: true,
theme: 'light',
swipeToClose: true,
backLinkText: 'Close',
ofText: 'of',
loop: false,
lazyLoading: false,
lazyLoadingInPrevNext: false,
lazyLoadingOnTransitionStart: false,
material: app.params.material,
materialPreloaderSvg: app.params.materialPreloaderSvg,
materialPreloaderHtml: app.params.materialPreloaderHtml,
/*
Callbacks:
onLazyImageLoad(pb, slide, img)
onLazyImageReady(pb, slide, img)
onOpen(pb)
onClose(pb)
onTransitionStart(swiper)
onTransitionEnd(swiper)
onSlideChangeStart(swiper)
onSlideChangeEnd(swiper)
onTap(swiper, e)
onClick(swiper, e)
onDoubleTap(swiper, e)
onSwipeToClose(pb)
*/
};
params = params || {};
if (!params.backLinkText && app.params.material) defaults.backLinkText = '';
for (var def in defaults) {
if (typeof params[def] === 'undefined') {
params[def] = defaults[def];
}
}
if (params.maxZoom) {
params.zoomMax = params.maxZoom;
}
if (params.minZoom) {
params.zoomMin = params.minZoom;
}
pb.params = params;
pb.params.iconsColorClass = pb.params.iconsColor ? 'color-' + pb.params.iconsColor : (pb.params.theme === 'dark' ? 'color-white' : '');
pb.params.preloaderColorClass = pb.params.theme === 'dark' ? 'preloader-white' : '';
// Templates
var photoTemplate = pb.params.photoTemplate ||
'<div class="photo-browser-slide swiper-slide">' +
'<span class="swiper-zoom-container">' +
'<img src="{{js "this.url || this"}}">' +
'</span>' +
'</div>';
var photoLazyTemplate = pb.params.lazyPhotoTemplate ||
'<div class="photo-browser-slide photo-browser-slide-lazy swiper-slide">' +
'<div class="preloader {{@root.preloaderColorClass}}">{{#if @root.material}}{{@root.materialPreloaderHtml}}{{/if}}</div>' +
'<span class="swiper-zoom-container">' +
'<img data-src="{{js "this.url || this"}}" class="swiper-lazy">' +
'</span>' +
'</div>';
var objectTemplate = pb.params.objectTemplate ||
'<div class="photo-browser-slide photo-browser-object-slide swiper-slide">{{js "this.html || this"}}</div>';
var captionTemplate = pb.params.captionTemplate ||
'<div class="photo-browser-caption" data-caption-index="{{@index}}">' +
'{{caption}}' +
'</div>';
var navbarTemplate = pb.params.navbarTemplate ||
'<div class="navbar">' +
'<div class="navbar-inner">' +
'<div class="left sliding">' +
'<a href="#" class="link ' + (params.type === 'popup' ? 'close-popup' : 'photo-browser-close-link')+ ' {{#unless backLinkText}}icon-only{{/unless}} {{js "this.type === \'page\' ? \'back\' : \'\'"}}">' +
'<i class="icon icon-back {{iconsColorClass}}"></i>' +
'{{#if backLinkText}}<span>{{backLinkText}}</span>{{/if}}' +
'</a>' +
'</div>' +
'<div class="center sliding">' +
'<span class="photo-browser-current"></span> ' +
'<span class="photo-browser-of">{{ofText}}</span> ' +
'<span class="photo-browser-total"></span>' +
'</div>' +
'<div class="right"></div>' +
'</div>' +
'</div>';
var toolbarTemplate = pb.params.toolbarTemplate ||
'<div class="toolbar tabbar">' +
'<div class="toolbar-inner">' +
'<a href="#" class="link photo-browser-prev">' +
'<i class="icon icon-prev {{iconsColorClass}}"></i>' +
'</a>' +
'<a href="#" class="link photo-browser-next">' +
'<i class="icon icon-next {{iconsColorClass}}"></i>' +
'</a>' +
'</div>' +
'</div>';
var htmlTemplate = t7.compile('<div class="photo-browser photo-browser-{{theme}}">' +
'<div class="view navbar-fixed toolbar-fixed">' +
'{{#unless material}}{{#if navbar}}' +
navbarTemplate +
'{{/if}}{{/unless}}' +
'<div class="page no-toolbar {{#unless navbar}}no-navbar{{/unless}} toolbar-fixed navbar-fixed" data-page="photo-browser-slides">' +
'{{#if material}}{{#if navbar}}' +
navbarTemplate +
'{{/if}}{{/if}}' +
'{{#if toolbar}}' +
toolbarTemplate +
'{{/if}}' +
'<div class="photo-browser-captions photo-browser-captions-{{js "this.captionsTheme || this.theme"}}">' +
'{{#each photos}}{{#if caption}}' +
captionTemplate +
'{{/if}}{{/each}}' +
'</div>' +
'<div class="photo-browser-swiper-container swiper-container">' +
'<div class="photo-browser-swiper-wrapper swiper-wrapper">' +
'{{#each photos}}' +
'{{#js_compare "this.html || ((typeof this === \'string\' || this instanceof String) && (this.indexOf(\'<\') >= 0 || this.indexOf(\'>\') >= 0))"}}' +
objectTemplate +
'{{else}}' +
'{{#if @root.lazyLoading}}' +
photoLazyTemplate +
'{{else}}' +
photoTemplate +
'{{/if}}' +
'{{/js_compare}}' +
'{{/each}}' +
'</div>' +
'</div>' +
'</div>' +
'</div>' +
'</div>')(pb.params);
pb.activeIndex = pb.params.initialSlide;
pb.openIndex = pb.activeIndex;
pb.opened = false;
pb.open = function (index) {
if (typeof index === 'undefined') index = pb.activeIndex;
index = parseInt(index, 10);
if (pb.opened && pb.swiper) {
pb.swiper.slideTo(index);
return;
}
pb.opened = true;
pb.openIndex = index;
if (pb.params.type === 'standalone') {
app.root.append(htmlTemplate);
}
if (pb.params.type === 'popup') {
pb.popup = app.popup('<div class="popup photo-browser-popup">' + htmlTemplate + '</div>');
$(pb.popup).on('closed', pb.onPopupClose);
}
if (pb.params.type === 'page') {
$(document).on('pageBeforeInit', pb.onPageBeforeInit);
$(document).on('pageBeforeRemove', pb.onPageBeforeRemove);
if (!pb.params.view) pb.params.view = app.mainView;
pb.params.view.loadContent(htmlTemplate);
return;
}
pb.layout(pb.openIndex);
if (pb.params.onOpen) {
pb.params.onOpen(pb);
}
};
pb.close = function () {
pb.opened = false;
if (!pb.swiperContainer || pb.swiperContainer.length === 0) {
return;
}
if (pb.params.onClose) {
pb.params.onClose(pb);
}
// Detach events
pb.attachEvents(true);
// Delete from DOM
if (pb.params.type === 'standalone') {
pb.container.removeClass('photo-browser-in').addClass('photo-browser-out').animationEnd(function () {
pb.container.remove();
});
}
// Destroy slider
pb.swiper.destroy();
// Delete references
pb.swiper = pb.swiperContainer = pb.swiperWrapper = pb.slides = undefined; //gestureSlide = gestureImg = gestureImgWrap = undefined;
};
pb.onPopupClose = function (e) {
pb.close();
$(pb.popup).off('pageBeforeInit', pb.onPopupClose);
};
pb.onPageBeforeInit = function (e) {
if (e.detail.page.name === 'photo-browser-slides') {
pb.layout(pb.openIndex);
}
$(document).off('pageBeforeInit', pb.onPageBeforeInit);
};
pb.onPageBeforeRemove = function (e) {
if (e.detail.page.name === 'photo-browser-slides') {
pb.close();
}
$(document).off('pageBeforeRemove', pb.onPageBeforeRemove);
};
pb.onSliderTransitionStart = function (swiper) {
pb.activeIndex = swiper.activeIndex;
var current = swiper.activeIndex + 1;
var total = swiper.slides.length;
if (pb.params.loop) {
total = total - 2;
current = current - swiper.loopedSlides;
if (current < 1) current = total + current;
if (current > total) current = current - total;
}
pb.container.find('.photo-browser-current').text(current);
pb.container.find('.photo-browser-total').text(total);
$('.photo-browser-prev, .photo-browser-next').removeClass('photo-browser-link-inactive');
if (swiper.isBeginning && !pb.params.loop) {
$('.photo-browser-prev').addClass('photo-browser-link-inactive');
}
if (swiper.isEnd && !pb.params.loop) {
$('.photo-browser-next').addClass('photo-browser-link-inactive');
}
// Update captions
if (pb.captions.length > 0) {
pb.captionsContainer.find('.photo-browser-caption-active').removeClass('photo-browser-caption-active');
var captionIndex = pb.params.loop ? swiper.slides.eq(swiper.activeIndex).attr('data-swiper-slide-index') : pb.activeIndex;
pb.captionsContainer.find('[data-caption-index="' + captionIndex + '"]').addClass('photo-browser-caption-active');
}
// Stop Video
var previousSlideVideo = swiper.slides.eq(swiper.previousIndex).find('video');
if (previousSlideVideo.length > 0) {
if ('pause' in previousSlideVideo[0]) previousSlideVideo[0].pause();
}
// Callback
if (pb.params.onTransitionStart) pb.params.onTransitionStart(swiper);
};
pb.onSliderTransitionEnd = function (swiper) {
if (pb.params.onTransitionEnd) pb.params.onTransitionEnd(swiper);
};
pb.layout = function (index) {
if (pb.params.type === 'page') {
pb.container = $('.photo-browser-swiper-container').parents('.view');
}
else {
pb.container = $('.photo-browser');
}
if (pb.params.type === 'standalone') {
pb.container.addClass('photo-browser-in');
app.sizeNavbars(pb.container);
}
pb.swiperContainer = pb.container.find('.photo-browser-swiper-container');
pb.swiperWrapper = pb.container.find('.photo-browser-swiper-wrapper');
pb.slides = pb.container.find('.photo-browser-slide');
pb.captionsContainer = pb.container.find('.photo-browser-captions');
pb.captions = pb.container.find('.photo-browser-caption');
var sliderSettings = {
nextButton: pb.params.nextButton || '.photo-browser-next',
prevButton: pb.params.prevButton || '.photo-browser-prev',
indexButton: pb.params.indexButton,
initialSlide: index,
spaceBetween: pb.params.spaceBetween,
speed: pb.params.speed,
loop: pb.params.loop,
lazyLoading: pb.params.lazyLoading,
lazyLoadingInPrevNext: pb.params.lazyLoadingInPrevNext,
lazyLoadingOnTransitionStart: pb.params.lazyLoadingOnTransitionStart,
preloadImages: pb.params.lazyLoading ? false : true,
zoom: pb.params.zoom,
zoomMax: pb.params.zoomMax,
zoomMin: pb.params.zoomMin,
onTap: function (swiper, e) {
if (pb.params.onTap) pb.params.onTap(swiper, e);
},
onClick: function (swiper, e) {
if (pb.params.exposition) pb.toggleExposition();
if (pb.params.onClick) pb.params.onClick(swiper, e);
},
onDoubleTap: function (swiper, e) {
// pb.toggleZoom(e);
if (pb.params.onDoubleTap) pb.params.onDoubleTap(swiper, e);
},
onTransitionStart: function (swiper) {
pb.onSliderTransitionStart(swiper);
},
onTransitionEnd: function (swiper) {
pb.onSliderTransitionEnd(swiper);
},
onSlideChangeStart: pb.params.onSlideChangeStart,
onSlideChangeEnd: pb.params.onSlideChangeEnd,
onLazyImageLoad: function (swiper, slide, img) {
if (pb.params.onLazyImageLoad) pb.params.onLazyImageLoad(pb, slide, img);
},
onLazyImageReady: function (swiper, slide, img) {
$(slide).removeClass('photo-browser-slide-lazy');
if (pb.params.onLazyImageReady) pb.params.onLazyImageReady(pb, slide, img);
}
};
if (pb.params.swipeToClose && pb.params.type !== 'page') {
sliderSettings.onTouchStart = pb.swipeCloseTouchStart;
sliderSettings.onTouchMoveOpposite = pb.swipeCloseTouchMove;
sliderSettings.onTouchEnd = pb.swipeCloseTouchEnd;
}
pb.swiper = app.swiper(pb.swiperContainer, sliderSettings);
if (index === 0) {
pb.onSliderTransitionStart(pb.swiper);
}
pb.attachEvents();
};
pb.attachEvents = function (detach) {
var action = detach ? 'off' : 'on';
pb.container.find('.photo-browser-close-link')[action]('click', pb.close);
};
// Expose
pb.exposed = false;
pb.toggleExposition = function () {
if (pb.container) pb.container.toggleClass('photo-browser-exposed');
if (pb.params.expositionHideCaptions) pb.captionsContainer.toggleClass('photo-browser-captions-exposed');
pb.exposed = !pb.exposed;
};
pb.enableExposition = function () {
if (pb.container) pb.container.addClass('photo-browser-exposed');
if (pb.params.expositionHideCaptions) pb.captionsContainer.addClass('photo-browser-captions-exposed');
pb.exposed = true;
};
pb.disableExposition = function () {
if (pb.container) pb.container.removeClass('photo-browser-exposed');
if (pb.params.expositionHideCaptions) pb.captionsContainer.removeClass('photo-browser-captions-exposed');
pb.exposed = false;
};
// Swipe Up To Close
var swipeToCloseIsTouched = false;
var allowSwipeToClose = true;
var swipeToCloseDiff, swipeToCloseStart, swipeToCloseCurrent, swipeToCloseStarted = false, swipeToCloseActiveSlide, swipeToCloseTimeStart;
pb.swipeCloseTouchStart = function (swiper, e) {
if (!allowSwipeToClose) return;
swipeToCloseIsTouched = true;
};
pb.swipeCloseTouchMove = function (swiper, e) {
if (!swipeToCloseIsTouched) return;
if (!swipeToCloseStarted) {
swipeToCloseStarted = true;
swipeToCloseStart = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
swipeToCloseActiveSlide = pb.swiper.slides.eq(pb.swiper.activeIndex);
swipeToCloseTimeStart = (new Date()).getTime();
}
e.preventDefault();
swipeToCloseCurrent = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
swipeToCloseDiff = swipeToCloseStart - swipeToCloseCurrent;
var opacity = 1 - Math.abs(swipeToCloseDiff) / 300;
swipeToCloseActiveSlide.transform('translate3d(0,' + (-swipeToCloseDiff) + 'px,0)');
pb.swiper.container.css('opacity', opacity).transition(0);
};
pb.swipeCloseTouchEnd = function (swiper, e) {
swipeToCloseIsTouched = false;
if (!swipeToCloseStarted) {
swipeToCloseStarted = false;
return;
}
swipeToCloseStarted = false;
allowSwipeToClose = false;
var diff = Math.abs(swipeToCloseDiff);
var timeDiff = (new Date()).getTime() - swipeToCloseTimeStart;
if ((timeDiff < 300 && diff > 20) || (timeDiff >= 300 && diff > 100)) {
setTimeout(function () {
if (pb.params.type === 'standalone') {
pb.close();
}
if (pb.params.type === 'popup') {
app.closeModal(pb.popup);
}
if (pb.params.onSwipeToClose) {
pb.params.onSwipeToClose(pb);
}
allowSwipeToClose = true;
}, 0);
return;
}
if (diff !== 0) {
swipeToCloseActiveSlide.addClass('transitioning').transitionEnd(function () {
allowSwipeToClose = true;
swipeToCloseActiveSlide.removeClass('transitioning');
});
}
else {
allowSwipeToClose = true;
}
pb.swiper.container.css('opacity', '').transition('');
swipeToCloseActiveSlide.transform('');
};
return pb;
};
app.photoBrowser = function (params) {
return new PhotoBrowser(params);
};
/*===============================================================================
************ Autocomplete ************
===============================================================================*/
var Autocomplete = function (params) {
var a = this;
// Params
var defaults = {
// Standalone Options
/*
opener: undefined,
*/
popupCloseText: 'Close',
backText: 'Back',
searchbarPlaceholderText: 'Search...',
searchbarCancelText: 'Cancel',
openIn: 'page',
backOnSelect: false,
notFoundText: 'Nothing found',
/*
pageTitle: undefined,
*/
// Handle Data
/*
source: undefined,
limit: undefined,
*/
valueProperty: 'id',
textProperty: 'text',
// Dropdown Options
/*
dropdownPlaceholderText: 'Type anything...',
*/
updateInputValueOnSelect: true,
expandInput: false,
// Preloader
preloaderColor: false,
preloader: false,
// Templates
/*
itemTemplate: undefined,
navbarTemplate: undefined,
dropdownTemplate: undefined
dropdownItemTemplate: undefined,
dropdownPlaceholderTemplate: undefined
*/
// Color themes
/*
navbarTheme: undefined,
formTheme: undefined,
*/
// Callbacks
/*
onChange: function (a, value) - for not dropdown
onOpen: function (a)
onClose: function (a)
*/
};
params = params || {};
for (var def in defaults) {
if (typeof params[def] === 'undefined') {
params[def] = defaults[def];
}
}
a.params = params;
// Opener Link & View
if (a.params.opener) {
a.opener = $(a.params.opener);
}
var view = a.params.view;
if (!a.params.view && a.opener && a.opener.length) {
// Find related view
view = a.opener.parents('.' + app.params.viewClass);
if (view.length === 0) return;
view = view[0].f7View;
}
// Input
if (a.params.input) {
a.input = $(a.params.input);
if (a.input.length === 0 && a.params.openIn === 'dropdown') return;
}
// Array with selected items
a.value = a.params.value || [];
// ID & Inputs
a.id = (new Date()).getTime();
a.inputType = a.params.multiple ? 'checkbox' : 'radio';
a.inputName = a.inputType + '-' + a.id;
// Is Material
var material = app.params.material;
// Back On Select
var backOnSelect = a.params.backOnSelect;
if (a.params.openIn !== 'dropdown') {
// Item Template
a.itemTemplate = t7.compile(a.params.itemTemplate ||
'<li>' +
'<label class="label-{{inputType}} item-content">' +
'<input type="{{inputType}}" name="{{inputName}}" value="{{value}}" {{#if selected}}checked{{/if}}>' +
'{{#if material}}' +
'<div class="item-media">' +
'<i class="icon icon-form-{{inputType}}"></i>' +
'</div>' +
'<div class="item-inner">' +
'<div class="item-title">{{text}}</div>' +
'</div>' +
'{{else}}' +
'{{#if checkbox}}' +
'<div class="item-media">' +
'<i class="icon icon-form-checkbox"></i>' +
'</div>' +
'{{/if}}' +
'<div class="item-inner">' +
'<div class="item-title">{{text}}</div>' +
'</div>' +
'{{/if}}' +
'</label>' +
'</li>'
);
// Page Layout
var pageTitle = a.params.pageTitle || '';
if (!pageTitle && a.opener && a.opener.length) {
pageTitle = a.opener.find('.item-title').text();
}
var pageName = 'autocomplete-' + a.inputName;
var navbarTheme = a.params.navbarTheme,
formTheme = a.params.formTheme;
// Navbar HTML
var navbarHTML;
var noNavbar = '', noToolbar = '', navbarLayout;
a.navbarTemplate = t7.compile(a.params.navbarTemplate ||
'<div class="navbar {{#if navbarTheme}}theme-{{navbarTheme}}{{/if}}">' +
'<div class="navbar-inner">' +
'<div class="left sliding">' +
'{{#if material}}' +
'<a href="#" class="link {{#if inPopup}}close-popup{{else}}back{{/if}} icon-only"><i class="icon icon-back"></i></a>' +
'{{else}}' +
'<a href="#" class="link {{#if inPopup}}close-popup{{else}}back{{/if}}">' +
'<i class="icon icon-back"></i>' +
'{{#if inPopup}}' +
'<span>{{popupCloseText}}</span>' +
'{{else}}' +
'<span>{{backText}}</span>' +
'{{/if}}' +
'</a>' +
'{{/if}}' +
'</div>' +
'<div class="center sliding">{{pageTitle}}</div>' +
'{{#if preloader}}' +
'<div class="right">' +
'<div class="autocomplete-preloader preloader {{#if preloaderColor}}preloader-{{preloaderColor}}{{/if}}"></div>' +
'</div>' +
'{{/if}}' +
'</div>' +
'</div>'
);
navbarHTML = a.navbarTemplate({
pageTitle: pageTitle,
backText: a.params.backText,
popupCloseText: a.params.popupCloseText,
openIn: a.params.openIn,
navbarTheme: navbarTheme,
inPopup: a.params.openIn === 'popup',
inPage: a.params.openIn === 'page',
material: material,
preloader: a.params.preloader,
preloaderColor: a.params.preloaderColor,
});
// Determine navbar layout type - static/fixed/through
if (a.params.openIn === 'page') {
navbarLayout = 'static';
if (a.opener) {
if (a.opener.parents('.navbar-through').length > 0) navbarLayout = 'through';
if (a.opener.parents('.navbar-fixed').length > 0) navbarLayout = 'fixed';
noToolbar = a.opener.parents('.page').hasClass('no-toolbar') ? 'no-toolbar' : '';
noNavbar = a.opener.parents('.page').hasClass('no-navbar') ? 'no-navbar' : 'navbar-' + navbarLayout;
}
else if (view.container) {
if ($(view.container).hasClass('navbar-through') || $(view.container).find('.navbar-through').length > 0) navbarLayout = 'through';
if ($(view.container).hasClass('navbar-fixed') || $(view.container).find('.navbar-fixed').length > 0) navbarLayout = 'fixed';
noToolbar = $(view.activePage.container).hasClass('no-toolbar') ? 'no-toolbar' : '';
noNavbar = $(view.activePage.container).hasClass('no-navbar') ? 'no-navbar' : 'navbar-' + navbarLayout;
}
}
else {
navbarLayout = 'fixed';
}
var searchbarHTML =
'<form class="searchbar">' +
'<div class="searchbar-input">' +
'<input type="search" placeholder="' + a.params.searchbarPlaceholderText + '">' +
'<a href="#" class="searchbar-clear"></a>' +
'</div>' +
(material ? '' : '<a href="#" class="searchbar-cancel">' + a.params.searchbarCancelText + '</a>') +
'</form>' +
'<div class="searchbar-overlay"></div>';
var pageHTML =
(navbarLayout === 'through' ? navbarHTML : '') +
'<div class="pages">' +
'<div data-page="' + pageName + '" class="page autocomplete-page ' + noNavbar + ' ' + noToolbar + '">' +
(navbarLayout === 'fixed' ? navbarHTML : '') +
searchbarHTML +
'<div class="page-content">' +
(navbarLayout === 'static' ? navbarHTML : '') +
'<div class="list-block autocomplete-found autocomplete-list-' + a.id + ' ' + (formTheme ? 'theme-' + formTheme : '') + '">' +
'<ul></ul>' +
'</div>' +
'<div class="list-block autocomplete-not-found">' +
'<ul><li class="item-content"><div class="item-inner"><div class="item-title">' + a.params.notFoundText + '</div></div></li></ul>' +
'</div>' +
'<div class="list-block autocomplete-values">' +
'<ul></ul>' +
'</div>' +
'</div>' +
'</div>' +
'</div>';
}
else {
a.dropdownItemTemplate = t7.compile(a.params.dropdownItemTemplate ||
'<li>' +
'<label class="{{#unless placeholder}}label-radio{{/unless}} item-content" data-value="{{value}}">' +
'<div class="item-inner">' +
'<div class="item-title">{{text}}</div>' +
'</div>' +
'</label>' +
'</li>'
);
a.dropdownPlaceholderTemplate = t7.compile(a.params.dropdownPlaceholderTemplate ||
'<li class="autocomplete-dropdown-placeholder">' +
'<div class="item-content">' +
'<div class="item-inner">' +
'<div class="item-title">{{text}}</div>' +
'</div>' +
'</label>' +
'</li>'
);
a.dropdownTemplate = t7.compile(a.params.dropdownTemplate ||
'<div class="autocomplete-dropdown">' +
'<div class="autocomplete-dropdown-inner">' +
'<div class="list-block">' +
'<ul></ul>' +
'</div>' +
'</div>' +
'{{#if preloader}}' +
'<div class="autocomplete-preloader preloader {{#if preloaderColor}}preloader-{{preloaderColor}}{{/if}}">{{#if material}}{{materialPreloaderHtml}}{{/if}}</div>' +
'{{/if}}' +
'</div>'
);
}
// Define popup
a.popup = undefined;
// Define Dropdown
a.dropdown = undefined;
// Handle Input Value Change
function handleInputValue (e) {
var query = a.input.val();
if (a.params.source) {
a.params.source(a, query, function (items) {
var itemsHTML = '';
var limit = a.params.limit ? Math.min(a.params.limit, items.length) : items.length;
a.items = items;
var i, j;
var regExp = new RegExp('('+query+')', 'i');
for (i = 0; i < limit; i++) {
var itemValue = typeof items[i] === 'object' ? items[i][a.params.valueProperty] : items[i];
itemsHTML += a.dropdownItemTemplate({
value: itemValue,
text: (typeof items[i] !== 'object' ? items[i] : items[i][a.params.textProperty]).replace(regExp, '<b>$1</b>')
});
}
if (itemsHTML === '' && query === '' && a.params.dropdownPlaceholderText) {
itemsHTML += a.dropdownPlaceholderTemplate({
text: a.params.dropdownPlaceholderText,
});
}
a.dropdown.find('ul').html(itemsHTML);
});
}
}
// Handle Drop Down Click
function handleDropdownClick (e) {
/*jshint validthis:true */
var clicked = $(this);
var clickedItem;
for (var i = 0; i < a.items.length; i++) {
var itemValue = typeof a.items[i] === 'object' ? a.items[i][a.params.valueProperty] : a.items[i];
var value = clicked.attr('data-value');
if (itemValue === value || itemValue * 1 === value * 1) {
clickedItem = a.items[i];
}
}
if (a.params.updateInputValueOnSelect) {
a.input.val(typeof clickedItem === 'object' ? clickedItem[a.params.textProperty] : clickedItem);
a.input.trigger('input change');
}
if (a.params.onChange) {
a.params.onChange(a, clickedItem);
}
a.close();
}
// Handle HTML Click to close Dropdown
function closeOnHTMLClick (e) {
var target = $(e.target);
if (!(target.is(a.input[0]) || a.dropdown && target.parents(a.dropdown[0]).length > 0)) {
a.close();
}
}
a.positionDropDown = function () {
var listBlock = a.input.parents('.list-block'),
pageContent = a.input.parents('.page-content'),
paddingTop = parseInt(pageContent.css('padding-top'), 10),
paddingBottom = parseInt(pageContent.css('padding-top'), 10),
// inputOffset = a.input.offset(),
listBlockOffsetLeft = listBlock.length > 0 ? listBlock.offset().left - listBlock.parent().offset().left : 0,
inputOffsetLeft = a.input.offset().left - (listBlock.length > 0 ? listBlock.offset().left : 0),
inputOffsetTop = a.input.offset().top - (pageContent.offset().top - pageContent[0].scrollTop),
maxHeight = pageContent[0].scrollHeight - paddingBottom - (inputOffsetTop + pageContent[0].scrollTop) - a.input[0].offsetHeight;
a.dropdown.css({
left: (listBlock.length > 0 ? listBlockOffsetLeft : inputOffsetLeft) + 'px',
top: inputOffsetTop + pageContent[0].scrollTop + a.input[0].offsetHeight + 'px',
width: (listBlock.length > 0 ? listBlock[0].offsetWidth : a.input[0].offsetWidth) + 'px'
});
a.dropdown.children('.autocomplete-dropdown-inner').css({
maxHeight: maxHeight + 'px',
paddingLeft: listBlock.length > 0 && !a.params.expandInput ? inputOffsetLeft - (material ? 16 : 15) + 'px' : ''
});
};
// Event Listeners on new page
a.pageInit = function (e) {
var page = e.detail.page;
a.page = $(page.container);
a.pageData = page;
if (page.name !== pageName) {
return;
}
var container = $(page.container);
// Init Search Bar
var searchbar = app.searchbar(container.find('.searchbar'), {
customSearch: true,
onSearch: function (searchbar, data) {
if (data.query.length === 0 && searchbar.active) {
searchbar.overlay.addClass('searchbar-overlay-active');
}
else {
searchbar.overlay.removeClass('searchbar-overlay-active');
}
var i, j, k;
if (a.params.source) {
a.params.source(a, data.query, function(items) {
var itemsHTML = '';
var limit = a.params.limit ? Math.min(a.params.limit, items.length) : items.length;
a.items = items;
for (i = 0; i < limit; i++) {
var selected = false;
var itemValue = typeof items[i] === 'object' ? items[i][a.params.valueProperty] : items[i];
for (j = 0; j < a.value.length; j++) {
var aValue = typeof a.value[j] === 'object' ? a.value[j][a.params.valueProperty] : a.value[j];
if (aValue === itemValue || aValue * 1 === itemValue * 1) selected = true;
}
itemsHTML += a.itemTemplate({
value: itemValue,
text: typeof items[i] !== 'object' ? items[i] : items[i][a.params.textProperty],
inputType: a.inputType,
id: a.id,
inputName: a.inputName,
selected: selected,
checkbox: a.inputType === 'checkbox',
material: material
});
}
container.find('.autocomplete-found ul').html(itemsHTML);
if (items.length === 0) {
if (data.query.length !== 0) {
container.find('.autocomplete-not-found').show();
container.find('.autocomplete-found, .autocomplete-values').hide();
}
else {
container.find('.autocomplete-values').show();
container.find('.autocomplete-found, .autocomplete-not-found').hide();
}
}
else {
container.find('.autocomplete-found').show();
container.find('.autocomplete-not-found, .autocomplete-values').hide();
}
});
}
}
});
// Save searchbar instance
a.searchbar = searchbar;
// Update values
function updateValues() {
var valuesHTML = '';
var i;
for (i = 0; i < a.value.length; i++) {
valuesHTML += a.itemTemplate({
value: typeof a.value[i] === 'object' ? a.value[i][a.params.valueProperty] : a.value[i],
text: typeof a.value[i] === 'object' ? a.value[i][a.params.textProperty]: a.value[i],
inputType: a.inputType,
id: a.id,
inputName: a.inputName + '-checked',
checkbox: a.inputType === 'checkbox',
material: material,
selected: true
});
}
container.find('.autocomplete-values ul').html(valuesHTML);
}
// Handle Inputs
container.on('change', 'input[type="radio"], input[type="checkbox"]', function () {
var i;
var input = this;
var value = input.value;
var text = $(input).parents('li').find('.item-title').text();
var isValues = $(input).parents('.autocomplete-values').length > 0;
var item, itemValue, aValue;
if (isValues) {
if (a.inputType === 'checkbox' && !input.checked) {
for (i = 0; i < a.value.length; i++) {
aValue = typeof a.value[i] === 'string' ? a.value[i] : a.value[i][a.params.valueProperty];
if (aValue === value || aValue * 1 === value * 1) {
a.value.splice(i, 1);
}
}
updateValues();
if (a.params.onChange) a.params.onChange(a, a.value);
}
return;
}
// Find Related Item
for (i = 0; i < a.items.length; i++) {
itemValue = typeof a.items[i] === 'string' ? a.items[i] : a.items[i][a.params.valueProperty];
if (itemValue === value || itemValue * 1 === value * 1) item = a.items[i];
}
// Update Selected Value
if (a.inputType === 'radio') {
a.value = [item];
}
else {
if (input.checked) {
a.value.push(item);
}
else {
for (i = 0; i < a.value.length; i++) {
aValue = typeof a.value[i] === 'string' ? a.value[i] : a.value[i][a.params.valueProperty];
if (aValue === value || aValue * 1 === value * 1) {
a.value.splice(i, 1);
}
}
}
}
// Update Values Block
updateValues();
// On Select Callback
if ((a.inputType === 'radio' && input.checked || a.inputType === 'checkbox') && a.params.onChange ) {
a.params.onChange(a, a.value);
}
if (backOnSelect && a.inputType === 'radio') {
if (a.params.openIn === 'popup') app.closeModal(a.popup);
else view.router.back();
}
});
// Update Values On Page Init
updateValues();
if (a.params.onOpen) a.params.onOpen(a);
};
// Show Hide Preloader
a.showPreloader = function () {
if (a.params.openIn === 'dropdown') {
if (a.dropdown) a.dropdown.find('.autocomplete-preloader').addClass('autocomplete-preloader-visible');
}
else $('.autocomplete-preloader').addClass('autocomplete-preloader-visible');
};
a.hidePreloader = function () {
if (a.params.openIn === 'dropdown') {
if (a.dropdown) a.dropdown.find('.autocomplete-preloader').removeClass('autocomplete-preloader-visible');
}
else $('.autocomplete-preloader').removeClass('autocomplete-preloader-visible');
};
// Open Autocomplete Page/Popup
a.open = function () {
if (a.opened) return;
a.opened = true;
if (a.params.openIn === 'dropdown') {
if (!a.dropdown) {
a.dropdown = $(a.dropdownTemplate({
preloader: a.params.preloader,
preloaderColor: a.params.preloaderColor,
material: material,
materialPreloaderHtml: app.params.materialPreloaderHtml
}));
a.dropdown.on('click', 'label', handleDropdownClick);
}
var listBlock = a.input.parents('.list-block');
if (listBlock.length && a.input.parents('.item-content').length > 0 && a.params.expandInput) {
a.input.parents('.item-content').addClass('item-content-dropdown-expand');
}
a.positionDropDown();
a.input.parents('.page-content').append(a.dropdown);
a.dropdown.addClass('autocomplete-dropdown-in');
a.input.trigger('input');
$(window).on('resize', a.positionDropDown);
if (a.params.onOpen) a.params.onOpen(a);
}
else {
$(document).once('pageInit', '.autocomplete-page', a.pageInit);
if (a.params.openIn === 'popup') {
a.popup = app.popup(
'<div class="popup autocomplete-popup autocomplete-popup-' + a.inputName + '">' +
'<div class="view navbar-fixed">' +
pageHTML +
'</div>' +
'</div>'
);
a.popup = $(a.popup);
a.popup.once('closed', function () {
a.popup = undefined;
a.opened = false;
if (a.params.onClose) a.params.onClose(a);
});
}
else {
view.router.load({
content: pageHTML
});
$(document).once('pageBack', '.autocomplete-page', function () {
a.opened = false;
if (a.params.onClose) a.params.onClose(a);
});
}
}
};
a.close = function (e) {
if (!a.opened) return;
if (a.params.openIn === 'dropdown') {
if (e && e.type === 'blur' && a.dropdown.find('label.active-state').length > 0) return;
a.dropdown.removeClass('autocomplete-dropdown-in').remove();
a.input.parents('.item-content-dropdown-expand').removeClass('item-content-dropdown-expand');
a.opened = false;
$(window).off('resize', a.positionDropDown);
if (a.params.onClose) a.params.onClose(a);
}
if (a.params.openIn === 'popup') {
if (a.popup) app.closeModal(a.popup);
}
};
// Init Events
a.initEvents = function (detach) {
var method = detach ? 'off' : 'on';
if (a.params.openIn !== 'dropdown' && a.opener) {
a.opener[method]('click', a.open);
}
if (a.params.openIn === 'dropdown' && a.input) {
a.input[method]('focus', a.open);
a.input[method]('input', handleInputValue);
if (app.device.android) {
$('html')[method]('click', closeOnHTMLClick);
}
else {
a.input[method]('blur', a.close);
}
}
if (detach && a.dropdown) {
a.dropdown = null;
}
};
// Init/Destroy Methods
a.init = function () {
a.initEvents();
};
a.destroy = function () {
a.initEvents(true);
a = null;
};
// Init
a.init();
return a;
};
app.autocomplete = function (params) {
return new Autocomplete(params);
};
/*======================================================
************ Picker ************
======================================================*/
var Picker = function (params) {
var p = this;
var defaults = {
updateValuesOnMomentum: false,
updateValuesOnTouchmove: true,
rotateEffect: false,
momentumRatio: 7,
freeMode: false,
// Common settings
closeByOutsideClick: true,
scrollToInput: true,
inputReadOnly: true,
convertToPopover: true,
onlyInPopover: false,
toolbar: true,
toolbarCloseText: 'Done',
toolbarTemplate:
'<div class="toolbar">' +
'<div class="toolbar-inner">' +
'<div class="left"></div>' +
'<div class="right">' +
'<a href="#" class="link close-picker">{{closeText}}</a>' +
'</div>' +
'</div>' +
'</div>'
};
params = params || {};
for (var def in defaults) {
if (typeof params[def] === 'undefined') {
params[def] = defaults[def];
}
}
p.params = params;
p.cols = [];
p.initialized = false;
// Inline flag
p.inline = p.params.container ? true : false;
// 3D Transforms origin bug, only on safari
var originBug = app.device.ios || (navigator.userAgent.toLowerCase().indexOf('safari') >= 0 && navigator.userAgent.toLowerCase().indexOf('chrome') < 0) && !app.device.android;
// Should be converted to popover
function isPopover() {
var toPopover = false;
if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
if (!p.inline && p.params.input) {
if (p.params.onlyInPopover) toPopover = true;
else {
if (app.device.ios) {
toPopover = app.device.ipad ? true : false;
}
else {
if ($(window).width() >= 768) toPopover = true;
}
}
}
return toPopover;
}
function inPopover() {
if (p.opened && p.container && p.container.length > 0 && p.container.parents('.popover').length > 0) return true;
else return false;
}
// Value
p.setValue = function (arrValues, transition) {
var valueIndex = 0;
if (p.cols.length === 0) {
p.value = arrValues;
p.updateValue(arrValues);
return;
}
for (var i = 0; i < p.cols.length; i++) {
if (p.cols[i] && !p.cols[i].divider) {
p.cols[i].setValue(arrValues[valueIndex], transition);
valueIndex++;
}
}
};
p.updateValue = function (forceValues) {
var newValue = forceValues || [];
var newDisplayValue = [];
for (var i = 0; i < p.cols.length; i++) {
if (!p.cols[i].divider) {
newValue.push(p.cols[i].value);
newDisplayValue.push(p.cols[i].displayValue);
}
}
if (newValue.indexOf(undefined) >= 0) {
return;
}
p.value = newValue;
p.displayValue = newDisplayValue;
if (p.params.onChange) {
p.params.onChange(p, p.value, p.displayValue);
}
if (p.input && p.input.length > 0) {
$(p.input).val(p.params.formatValue ? p.params.formatValue(p, p.value, p.displayValue) : p.value.join(' '));
$(p.input).trigger('change');
}
};
// Columns Handlers
p.initPickerCol = function (colElement, updateItems) {
var colContainer = $(colElement);
var colIndex = colContainer.index();
var col = p.cols[colIndex];
if (col.divider) return;
col.container = colContainer;
col.wrapper = col.container.find('.picker-items-col-wrapper');
col.items = col.wrapper.find('.picker-item');
var i, j;
var wrapperHeight, itemHeight, itemsHeight, minTranslate, maxTranslate;
col.replaceValues = function (values, displayValues) {
col.destroyEvents();
col.values = values;
col.displayValues = displayValues;
var newItemsHTML = p.columnHTML(col, true);
col.wrapper.html(newItemsHTML);
col.items = col.wrapper.find('.picker-item');
col.calcSize();
col.setValue(col.values[0], 0, true);
col.initEvents();
};
col.calcSize = function () {
if (p.params.rotateEffect) {
col.container.removeClass('picker-items-col-absolute');
if (!col.width) col.container.css({width:''});
}
var colWidth, colHeight;
colWidth = 0;
colHeight = col.container[0].offsetHeight;
wrapperHeight = col.wrapper[0].offsetHeight;
itemHeight = col.items[0].offsetHeight;
itemsHeight = itemHeight * col.items.length;
minTranslate = colHeight / 2 - itemsHeight + itemHeight / 2;
maxTranslate = colHeight / 2 - itemHeight / 2;
if (col.width) {
colWidth = col.width;
if (parseInt(colWidth, 10) === colWidth) colWidth = colWidth + 'px';
col.container.css({width: colWidth});
}
if (p.params.rotateEffect) {
if (!col.width) {
col.items.each(function () {
var item = $(this);
item.css({width:'auto'});
colWidth = Math.max(colWidth, item[0].offsetWidth);
item.css({width:''});
});
col.container.css({width: (colWidth + 2) + 'px'});
}
col.container.addClass('picker-items-col-absolute');
}
};
col.calcSize();
col.wrapper.transform('translate3d(0,' + maxTranslate + 'px,0)').transition(0);
var activeIndex = 0;
var animationFrameId;
// Set Value Function
col.setValue = function (newValue, transition, valueCallbacks) {
if (typeof transition === 'undefined') transition = '';
var newActiveIndex = col.wrapper.find('.picker-item[data-picker-value="' + newValue + '"]').index();
if(typeof newActiveIndex === 'undefined' || newActiveIndex === -1) {
return;
}
var newTranslate = -newActiveIndex * itemHeight + maxTranslate;
// Update wrapper
col.wrapper.transition(transition);
col.wrapper.transform('translate3d(0,' + (newTranslate) + 'px,0)');
// Watch items
if (p.params.updateValuesOnMomentum && col.activeIndex && col.activeIndex !== newActiveIndex ) {
$.cancelAnimationFrame(animationFrameId);
col.wrapper.transitionEnd(function(){
$.cancelAnimationFrame(animationFrameId);
});
updateDuringScroll();
}
// Update items
col.updateItems(newActiveIndex, newTranslate, transition, valueCallbacks);
};
col.updateItems = function (activeIndex, translate, transition, valueCallbacks) {
if (typeof translate === 'undefined') {
translate = $.getTranslate(col.wrapper[0], 'y');
}
if(typeof activeIndex === 'undefined') activeIndex = -Math.round((translate - maxTranslate)/itemHeight);
if (activeIndex < 0) activeIndex = 0;
if (activeIndex >= col.items.length) activeIndex = col.items.length - 1;
var previousActiveIndex = col.activeIndex;
col.activeIndex = activeIndex;
col.wrapper.find('.picker-selected').removeClass('picker-selected');
col.items.transition(transition);
var selectedItem = col.items.eq(activeIndex).addClass('picker-selected').transform('');
// Set 3D rotate effect
if (p.params.rotateEffect) {
var percentage = (translate - (Math.floor((translate - maxTranslate)/itemHeight) * itemHeight + maxTranslate)) / itemHeight;
col.items.each(function () {
var item = $(this);
var itemOffsetTop = item.index() * itemHeight;
var translateOffset = maxTranslate - translate;
var itemOffset = itemOffsetTop - translateOffset;
var percentage = itemOffset / itemHeight;
var itemsFit = Math.ceil(col.height / itemHeight / 2) + 1;
var angle = (-18*percentage);
if (angle > 180) angle = 180;
if (angle < -180) angle = -180;
// Far class
if (Math.abs(percentage) > itemsFit) item.addClass('picker-item-far');
else item.removeClass('picker-item-far');
// Set transform
item.transform('translate3d(0, ' + (-translate + maxTranslate) + 'px, ' + (originBug ? -110 : 0) + 'px) rotateX(' + angle + 'deg)');
});
}
if (valueCallbacks || typeof valueCallbacks === 'undefined') {
// Update values
col.value = selectedItem.attr('data-picker-value');
col.displayValue = col.displayValues ? col.displayValues[activeIndex] : col.value;
// On change callback
if (previousActiveIndex !== activeIndex) {
if (col.onChange) {
col.onChange(p, col.value, col.displayValue);
}
p.updateValue();
}
}
};
function updateDuringScroll() {
animationFrameId = $.requestAnimationFrame(function () {
col.updateItems(undefined, undefined, 0);
updateDuringScroll();
});
}
// Update items on init
if (updateItems) col.updateItems(0, maxTranslate, 0);
var allowItemClick = true;
var isTouched, isMoved, touchStartY, touchCurrentY, touchStartTime, touchEndTime, startTranslate, returnTo, currentTranslate, prevTranslate, velocityTranslate, velocityTime;
function handleTouchStart (e) {
if (isMoved || isTouched) return;
e.preventDefault();
isTouched = true;
touchStartY = touchCurrentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
touchStartTime = (new Date()).getTime();
allowItemClick = true;
startTranslate = currentTranslate = $.getTranslate(col.wrapper[0], 'y');
}
function handleTouchMove (e) {
if (!isTouched) return;
e.preventDefault();
allowItemClick = false;
touchCurrentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
if (!isMoved) {
// First move
$.cancelAnimationFrame(animationFrameId);
isMoved = true;
startTranslate = currentTranslate = $.getTranslate(col.wrapper[0], 'y');
col.wrapper.transition(0);
}
var diff = touchCurrentY - touchStartY;
currentTranslate = startTranslate + diff;
returnTo = undefined;
// Normalize translate
if (currentTranslate < minTranslate) {
currentTranslate = minTranslate - Math.pow(minTranslate - currentTranslate, 0.8);
returnTo = 'min';
}
if (currentTranslate > maxTranslate) {
currentTranslate = maxTranslate + Math.pow(currentTranslate - maxTranslate, 0.8);
returnTo = 'max';
}
// Transform wrapper
col.wrapper.transform('translate3d(0,' + currentTranslate + 'px,0)');
// Update items
col.updateItems(undefined, currentTranslate, 0, p.params.updateValuesOnTouchmove);
// Calc velocity
velocityTranslate = currentTranslate - prevTranslate || currentTranslate;
velocityTime = (new Date()).getTime();
prevTranslate = currentTranslate;
}
function handleTouchEnd (e) {
if (!isTouched || !isMoved) {
isTouched = isMoved = false;
return;
}
isTouched = isMoved = false;
col.wrapper.transition('');
if (returnTo) {
if (returnTo === 'min') {
col.wrapper.transform('translate3d(0,' + minTranslate + 'px,0)');
}
else col.wrapper.transform('translate3d(0,' + maxTranslate + 'px,0)');
}
touchEndTime = new Date().getTime();
var velocity, newTranslate;
if (touchEndTime - touchStartTime > 300) {
newTranslate = currentTranslate;
}
else {
velocity = Math.abs(velocityTranslate / (touchEndTime - velocityTime));
newTranslate = currentTranslate + velocityTranslate * p.params.momentumRatio;
}
newTranslate = Math.max(Math.min(newTranslate, maxTranslate), minTranslate);
// Active Index
var activeIndex = -Math.floor((newTranslate - maxTranslate)/itemHeight);
// Normalize translate
if (!p.params.freeMode) newTranslate = -activeIndex * itemHeight + maxTranslate;
// Transform wrapper
col.wrapper.transform('translate3d(0,' + (parseInt(newTranslate,10)) + 'px,0)');
// Update items
col.updateItems(activeIndex, newTranslate, '', true);
// Watch items
if (p.params.updateValuesOnMomentum) {
updateDuringScroll();
col.wrapper.transitionEnd(function(){
$.cancelAnimationFrame(animationFrameId);
});
}
// Allow click
setTimeout(function () {
allowItemClick = true;
}, 100);
}
function handleClick(e) {
if (!allowItemClick) return;
$.cancelAnimationFrame(animationFrameId);
/*jshint validthis:true */
var value = $(this).attr('data-picker-value');
col.setValue(value);
}
col.initEvents = function (detach) {
var method = detach ? 'off' : 'on';
col.container[method](app.touchEvents.start, handleTouchStart);
col.container[method](app.touchEvents.move, handleTouchMove);
col.container[method](app.touchEvents.end, handleTouchEnd);
col.items[method]('click', handleClick);
};
col.destroyEvents = function () {
col.initEvents(true);
};
col.container[0].f7DestroyPickerCol = function () {
col.destroyEvents();
};
col.initEvents();
};
p.destroyPickerCol = function (colContainer) {
colContainer = $(colContainer);
if ('f7DestroyPickerCol' in colContainer[0]) colContainer[0].f7DestroyPickerCol();
};
// Resize cols
function resizeCols() {
if (!p.opened) return;
for (var i = 0; i < p.cols.length; i++) {
if (!p.cols[i].divider) {
p.cols[i].calcSize();
p.cols[i].setValue(p.cols[i].value, 0, false);
}
}
}
$(window).on('resize', resizeCols);
// HTML Layout
p.columnHTML = function (col, onlyItems) {
var columnItemsHTML = '';
var columnHTML = '';
if (col.divider) {
columnHTML += '<div class="picker-items-col picker-items-col-divider ' + (col.textAlign ? 'picker-items-col-' + col.textAlign : '') + ' ' + (col.cssClass || '') + '">' + col.content + '</div>';
}
else {
for (var j = 0; j < col.values.length; j++) {
columnItemsHTML += '<div class="picker-item" data-picker-value="' + col.values[j] + '">' + (col.displayValues ? col.displayValues[j] : col.values[j]) + '</div>';
}
columnHTML += '<div class="picker-items-col ' + (col.textAlign ? 'picker-items-col-' + col.textAlign : '') + ' ' + (col.cssClass || '') + '"><div class="picker-items-col-wrapper">' + columnItemsHTML + '</div></div>';
}
return onlyItems ? columnItemsHTML : columnHTML;
};
p.layout = function () {
var pickerHTML = '';
var pickerClass = '';
var i;
p.cols = [];
var colsHTML = '';
for (i = 0; i < p.params.cols.length; i++) {
var col = p.params.cols[i];
colsHTML += p.columnHTML(p.params.cols[i]);
p.cols.push(col);
}
pickerClass = 'picker-modal picker-columns ' + (p.params.cssClass || '') + (p.params.rotateEffect ? ' picker-3d' : '');
pickerHTML =
'<div class="' + (pickerClass) + '">' +
(p.params.toolbar ? p.params.toolbarTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText) : '') +
'<div class="picker-modal-inner picker-items">' +
colsHTML +
'<div class="picker-center-highlight"></div>' +
'</div>' +
'</div>';
p.pickerHTML = pickerHTML;
};
// Input Events
function openOnInput(e) {
e.preventDefault();
if (p.opened) return;
p.open();
if (p.params.scrollToInput && !isPopover()) {
var pageContent = p.input.parents('.page-content');
if (pageContent.length === 0) return;
var paddingTop = parseInt(pageContent.css('padding-top'), 10),
paddingBottom = parseInt(pageContent.css('padding-bottom'), 10),
pageHeight = pageContent[0].offsetHeight - paddingTop - p.container.height(),
pageScrollHeight = pageContent[0].scrollHeight - paddingTop - p.container.height(),
newPaddingBottom;
var inputTop = p.input.offset().top - paddingTop + p.input[0].offsetHeight;
if (inputTop > pageHeight) {
var scrollTop = pageContent.scrollTop() + inputTop - pageHeight;
if (scrollTop + pageHeight > pageScrollHeight) {
newPaddingBottom = scrollTop + pageHeight - pageScrollHeight + paddingBottom;
if (pageHeight === pageScrollHeight) {
newPaddingBottom = p.container.height();
}
pageContent.css({'padding-bottom': (newPaddingBottom) + 'px'});
}
pageContent.scrollTop(scrollTop, 300);
}
}
}
function closeOnHTMLClick(e) {
if (inPopover()) return;
if (p.input && p.input.length > 0) {
if (e.target !== p.input[0] && $(e.target).parents('.picker-modal').length === 0) p.close();
}
else {
if ($(e.target).parents('.picker-modal').length === 0) p.close();
}
}
if (p.params.input) {
p.input = $(p.params.input);
if (p.input.length > 0) {
if (p.params.inputReadOnly) p.input.prop('readOnly', true);
if (!p.inline) {
p.input.on('click', openOnInput);
}
if (p.params.inputReadOnly) {
p.input.on('focus mousedown', function (e) {
e.preventDefault();
});
}
}
}
if (!p.inline && p.params.closeByOutsideClick) $('html').on('click', closeOnHTMLClick);
// Open
function onPickerClose() {
p.opened = false;
if (p.input && p.input.length > 0) {
p.input.parents('.page-content').css({'padding-bottom': ''});
if (app.params.material) p.input.trigger('blur');
}
if (p.params.onClose) p.params.onClose(p);
// Destroy events
p.container.find('.picker-items-col').each(function () {
p.destroyPickerCol(this);
});
}
p.opened = false;
p.open = function () {
var toPopover = isPopover();
if (!p.opened) {
// Layout
p.layout();
// Append
if (toPopover) {
p.pickerHTML = '<div class="popover popover-picker-columns"><div class="popover-inner">' + p.pickerHTML + '</div></div>';
p.popover = app.popover(p.pickerHTML, p.params.input, true);
p.container = $(p.popover).find('.picker-modal');
$(p.popover).on('close', function () {
onPickerClose();
});
}
else if (p.inline) {
p.container = $(p.pickerHTML);
p.container.addClass('picker-modal-inline');
$(p.params.container).append(p.container);
}
else {
p.container = $(app.pickerModal(p.pickerHTML));
$(p.container)
.on('close', function () {
onPickerClose();
});
}
// Store picker instance
p.container[0].f7Picker = p;
// Init Events
p.container.find('.picker-items-col').each(function () {
var updateItems = true;
if ((!p.initialized && p.params.value) || (p.initialized && p.value)) updateItems = false;
p.initPickerCol(this, updateItems);
});
// Set value
if (!p.initialized) {
if (p.value) p.setValue(p.value, 0);
else if (p.params.value) {
p.setValue(p.params.value, 0);
}
}
else {
if (p.value) p.setValue(p.value, 0);
}
// Material Focus
if (p.input && p.input.length > 0 && app.params.material) {
p.input.trigger('focus');
}
}
// Set flag
p.opened = true;
p.initialized = true;
if (p.params.onOpen) p.params.onOpen(p);
};
// Close
p.close = function () {
if (!p.opened || p.inline) return;
if (inPopover()) {
app.closeModal(p.popover);
return;
}
else {
app.closeModal(p.container);
return;
}
};
// Destroy
p.destroy = function () {
p.close();
if (p.params.input && p.input.length > 0) {
p.input.off('click focus', openOnInput);
}
$('html').off('click', closeOnHTMLClick);
$(window).off('resize', resizeCols);
};
if (p.inline) {
p.open();
}
else {
if (!p.initialized && p.params.value) p.setValue(p.params.value);
}
return p;
};
app.picker = function (params) {
return new Picker(params);
};
/*======================================================
************ Calendar ************
======================================================*/
var Calendar = function (params) {
var p = this;
var defaults = {
monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August' , 'September' , 'October', 'November', 'December'],
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
firstDay: 1, // First day of the week, Monday
weekendDays: [0, 6], // Sunday and Saturday
multiple: false,
rangePicker: false,
dateFormat: 'yyyy-mm-dd',
direction: 'horizontal', // or 'vertical'
minDate: null,
maxDate: null,
disabled: null, // dates range of disabled days
events: null, // dates range of days with events
rangesClasses: null, //array with custom classes date ranges
touchMove: true,
animate: true,
closeOnSelect: false,
monthPicker: true,
monthPickerTemplate:
'<div class="picker-calendar-month-picker">' +
'<a href="#" class="link icon-only picker-calendar-prev-month"><i class="icon icon-prev"></i></a>' +
'<span class="current-month-value"></span>' +
'<a href="#" class="link icon-only picker-calendar-next-month"><i class="icon icon-next"></i></a>' +
'</div>',
yearPicker: true,
yearPickerTemplate:
'<div class="picker-calendar-year-picker">' +
'<a href="#" class="link icon-only picker-calendar-prev-year"><i class="icon icon-prev"></i></a>' +
'<span class="current-year-value"></span>' +
'<a href="#" class="link icon-only picker-calendar-next-year"><i class="icon icon-next"></i></a>' +
'</div>',
weekHeader: true,
// Common settings
closeByOutsideClick: true,
scrollToInput: true,
inputReadOnly: true,
convertToPopover: true,
onlyInPopover: false,
toolbar: true,
toolbarCloseText: 'Done',
headerPlaceholder: 'Select date',
header: app.params.material,
footer: app.params.material,
toolbarTemplate:
'<div class="toolbar">' +
'<div class="toolbar-inner">' +
'{{monthPicker}}' +
'{{yearPicker}}' +
'</div>' +
'</div>',
headerTemplate:
'<div class="picker-header">' +
'<div class="picker-calendar-selected-date">{{placeholder}}</div>' +
'</div>',
footerTemplate:
'<div class="picker-footer">' +
'<a href="#" class="button close-picker">{{closeText}}</a>' +
'</div>',
/* Callbacks
onMonthAdd
onChange
onOpen
onClose
onDayClick
onMonthYearChangeStart
onMonthYearChangeEnd
*/
};
params = params || {};
for (var def in defaults) {
if (typeof params[def] === 'undefined') {
params[def] = defaults[def];
}
}
p.params = params;
p.initialized = false;
// Inline flag
p.inline = p.params.container ? true : false;
// Is horizontal
p.isH = p.params.direction === 'horizontal';
// RTL inverter
var inverter = p.isH ? (app.rtl ? -1 : 1) : 1;
// Animating flag
p.animating = false;
// Should be converted to popover
function isPopover() {
var toPopover = false;
if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
if (!p.inline && p.params.input) {
if (p.params.onlyInPopover) toPopover = true;
else {
if (app.device.ios) {
toPopover = app.device.ipad ? true : false;
}
else {
if ($(window).width() >= 768) toPopover = true;
}
}
}
return toPopover;
}
function inPopover() {
if (p.opened && p.container && p.container.length > 0 && p.container.parents('.popover').length > 0) return true;
else return false;
}
// Format date
function formatDate(date) {
date = new Date(date);
var year = date.getFullYear();
var month = date.getMonth();
var month1 = month + 1;
var day = date.getDate();
var weekDay = date.getDay();
return p.params.dateFormat
.replace(/yyyy/g, year)
.replace(/yy/g, (year + '').substring(2))
.replace(/mm/g, month1 < 10 ? '0' + month1 : month1)
.replace(/m(\W+)/g, month1 + '$1')
.replace(/MM/g, p.params.monthNames[month])
.replace(/M(\W+)/g, p.params.monthNamesShort[month] + '$1')
.replace(/dd/g, day < 10 ? '0' + day : day)
.replace(/d(\W+)/g, day + '$1')
.replace(/DD/g, p.params.dayNames[weekDay])
.replace(/D(\W+)/g, p.params.dayNamesShort[weekDay] + '$1');
}
// Value
p.addValue = function (value) {
if (p.params.multiple) {
if (!p.value) p.value = [];
var inValuesIndex;
for (var i = 0; i < p.value.length; i++) {
if (new Date(value).getTime() === new Date(p.value[i]).getTime()) {
inValuesIndex = i;
}
}
if (typeof inValuesIndex === 'undefined') {
p.value.push(value);
}
else {
p.value.splice(inValuesIndex, 1);
}
p.updateValue();
}
else if (p.params.rangePicker) {
if (!p.value) p.value = [];
if (p.value.length === 2 || p.value.length === 0) {
p.value = [];
}
if (p.value[0] !== value) p.value.push(value);
else p.value = [];
p.value.sort(function (a,b) {
return a - b;
});
p.updateValue();
}
else {
p.value = [value];
p.updateValue();
}
};
p.setValue = function (arrValues) {
p.value = arrValues;
p.updateValue();
};
p.updateValue = function (onlyHeader) {
var i, inputValue;
if (p.container && p.container.length > 0) {
p.wrapper.find('.picker-calendar-day-selected').removeClass('picker-calendar-day-selected');
var valueDate;
if (p.params.rangePicker && p.value.length === 2) {
for (i = p.value[0]; i <= p.value[1]; i += 24*60*60*1000) {
valueDate = new Date(i);
p.wrapper.find('.picker-calendar-day[data-date="' + valueDate.getFullYear() + '-' + valueDate.getMonth() + '-' + valueDate.getDate() + '"]').addClass('picker-calendar-day-selected');
}
}
else {
for (i = 0; i < p.value.length; i++) {
valueDate = new Date(p.value[i]);
p.wrapper.find('.picker-calendar-day[data-date="' + valueDate.getFullYear() + '-' + valueDate.getMonth() + '-' + valueDate.getDate() + '"]').addClass('picker-calendar-day-selected');
}
}
}
if (p.params.onChange) {
p.params.onChange(p, p.value);
}
if ((p.input && p.input.length > 0) || (app.params.material && p.params.header)) {
if (p.params.formatValue) inputValue = p.params.formatValue(p, p.value);
else {
inputValue = [];
for (i = 0; i < p.value.length; i++) {
inputValue.push(formatDate(p.value[i]));
}
inputValue = inputValue.join(p.params.rangePicker ? ' - ' : ', ');
}
if (app.params.material && p.params.header && p.container && p.container.length > 0) {
p.container.find('.picker-calendar-selected-date').text(inputValue);
}
if (p.input && p.input.length > 0 && !onlyHeader) {
$(p.input).val(inputValue);
$(p.input).trigger('change');
}
}
};
// Columns Handlers
p.initCalendarEvents = function () {
var col;
var allowItemClick = true;
var isTouched, isMoved, touchStartX, touchStartY, touchCurrentX, touchCurrentY, touchStartTime, touchEndTime, startTranslate, currentTranslate, wrapperWidth, wrapperHeight, percentage, touchesDiff, isScrolling;
function handleTouchStart (e) {
if (isMoved || isTouched) return;
// e.preventDefault();
isTouched = true;
touchStartX = touchCurrentY = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
touchStartY = touchCurrentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
touchStartTime = (new Date()).getTime();
percentage = 0;
allowItemClick = true;
isScrolling = undefined;
startTranslate = currentTranslate = p.monthsTranslate;
}
function handleTouchMove (e) {
if (!isTouched) return;
touchCurrentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
touchCurrentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
if (typeof isScrolling === 'undefined') {
isScrolling = !!(isScrolling || Math.abs(touchCurrentY - touchStartY) > Math.abs(touchCurrentX - touchStartX));
}
if (p.isH && isScrolling) {
isTouched = false;
return;
}
e.preventDefault();
if (p.animating) {
isTouched = false;
return;
}
allowItemClick = false;
if (!isMoved) {
// First move
isMoved = true;
wrapperWidth = p.wrapper[0].offsetWidth;
wrapperHeight = p.wrapper[0].offsetHeight;
p.wrapper.transition(0);
}
touchesDiff = p.isH ? touchCurrentX - touchStartX : touchCurrentY - touchStartY;
percentage = touchesDiff/(p.isH ? wrapperWidth : wrapperHeight);
currentTranslate = (p.monthsTranslate * inverter + percentage) * 100;
// Transform wrapper
p.wrapper.transform('translate3d(' + (p.isH ? currentTranslate : 0) + '%, ' + (p.isH ? 0 : currentTranslate) + '%, 0)');
}
function handleTouchEnd (e) {
if (!isTouched || !isMoved) {
isTouched = isMoved = false;
return;
}
isTouched = isMoved = false;
touchEndTime = new Date().getTime();
if (touchEndTime - touchStartTime < 300) {
if (Math.abs(touchesDiff) < 10) {
p.resetMonth();
}
else if (touchesDiff >= 10) {
if (app.rtl) p.nextMonth();
else p.prevMonth();
}
else {
if (app.rtl) p.prevMonth();
else p.nextMonth();
}
}
else {
if (percentage <= -0.5) {
if (app.rtl) p.prevMonth();
else p.nextMonth();
}
else if (percentage >= 0.5) {
if (app.rtl) p.nextMonth();
else p.prevMonth();
}
else {
p.resetMonth();
}
}
// Allow click
setTimeout(function () {
allowItemClick = true;
}, 100);
}
function handleDayClick(e) {
if (!allowItemClick) return;
var day = $(e.target).parents('.picker-calendar-day');
if (day.length === 0 && $(e.target).hasClass('picker-calendar-day')) {
day = $(e.target);
}
if (day.length === 0) return;
if (day.hasClass('picker-calendar-day-selected') && !(p.params.multiple || p.params.rangePicker)) return;
if (day.hasClass('picker-calendar-day-disabled')) return;
if (!p.params.rangePicker) {
if (day.hasClass('picker-calendar-day-next')) p.nextMonth();
if (day.hasClass('picker-calendar-day-prev')) p.prevMonth();
}
var dateYear = day.attr('data-year');
var dateMonth = day.attr('data-month');
var dateDay = day.attr('data-day');
if (p.params.onDayClick) {
p.params.onDayClick(p, day[0], dateYear, dateMonth, dateDay);
}
p.addValue(new Date(dateYear, dateMonth, dateDay).getTime());
if (p.params.closeOnSelect) {
if (p.params.rangePicker && p.value.length === 2 || !p.params.rangePicker) p.close();
}
}
p.container.find('.picker-calendar-prev-month').on('click', p.prevMonth);
p.container.find('.picker-calendar-next-month').on('click', p.nextMonth);
p.container.find('.picker-calendar-prev-year').on('click', p.prevYear);
p.container.find('.picker-calendar-next-year').on('click', p.nextYear);
p.wrapper.on('click', handleDayClick);
var passiveListener = app.touchEvents.start === 'touchstart' && app.support.passiveListener ? {passive: true, capture: false} : false;
if (p.params.touchMove) {
p.wrapper.on(app.touchEvents.start, handleTouchStart, passiveListener);
p.wrapper.on(app.touchEvents.move, handleTouchMove);
p.wrapper.on(app.touchEvents.end, handleTouchEnd, passiveListener);
}
p.container[0].f7DestroyCalendarEvents = function () {
p.container.find('.picker-calendar-prev-month').off('click', p.prevMonth);
p.container.find('.picker-calendar-next-month').off('click', p.nextMonth);
p.container.find('.picker-calendar-prev-year').off('click', p.prevYear);
p.container.find('.picker-calendar-next-year').off('click', p.nextYear);
p.wrapper.off('click', handleDayClick);
if (p.params.touchMove) {
p.wrapper.off(app.touchEvents.start, handleTouchStart, passiveListener);
p.wrapper.off(app.touchEvents.move, handleTouchMove);
p.wrapper.off(app.touchEvents.end, handleTouchEnd, passiveListener);
}
};
};
p.destroyCalendarEvents = function (colContainer) {
if ('f7DestroyCalendarEvents' in p.container[0]) p.container[0].f7DestroyCalendarEvents();
};
// Scan Dates Range
p.dateInRange = function (dayDate, range) {
var match = false;
var i;
if (!range) return false;
if ($.isArray(range)) {
for (i = 0; i < range.length; i ++) {
if (range[i].from || range[i].to) {
if (range[i].from && range[i].to) {
if ((dayDate <= new Date(range[i].to).getTime()) && (dayDate >= new Date(range[i].from).getTime())) {
match = true;
}
}
else if (range[i].from) {
if (dayDate >= new Date(range[i].from).getTime()) {
match = true;
}
}
else if (range[i].to) {
if (dayDate <= new Date(range[i].to).getTime()) {
match = true;
}
}
} else if (dayDate === new Date(range[i]).getTime()) {
match = true;
}
}
}
else if (range.from || range.to) {
if (range.from && range.to) {
if ((dayDate <= new Date(range.to).getTime()) && (dayDate >= new Date(range.from).getTime())) {
match = true;
}
}
else if (range.from) {
if (dayDate >= new Date(range.from).getTime()) {
match = true;
}
}
else if (range.to) {
if (dayDate <= new Date(range.to).getTime()) {
match = true;
}
}
}
else if (typeof range === 'function') {
match = range(new Date(dayDate));
}
return match;
};
// Calendar Methods
p.daysInMonth = function (date) {
var d = new Date(date);
return new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
};
p.monthHTML = function (date, offset) {
date = new Date(date);
var year = date.getFullYear(),
month = date.getMonth(),
day = date.getDate();
if (offset === 'next') {
if (month === 11) date = new Date(year + 1, 0);
else date = new Date(year, month + 1, 1);
}
if (offset === 'prev') {
if (month === 0) date = new Date(year - 1, 11);
else date = new Date(year, month - 1, 1);
}
if (offset === 'next' || offset === 'prev') {
month = date.getMonth();
year = date.getFullYear();
}
var daysInPrevMonth = p.daysInMonth(new Date(date.getFullYear(), date.getMonth()).getTime() - 10 * 24 * 60 * 60 * 1000),
daysInMonth = p.daysInMonth(date),
firstDayOfMonthIndex = new Date(date.getFullYear(), date.getMonth()).getDay();
if (firstDayOfMonthIndex === 0) firstDayOfMonthIndex = 7;
var dayDate, currentValues = [], i, j, k,
rows = 6, cols = 7,
monthHTML = '',
dayIndex = 0 + (p.params.firstDay - 1),
today = new Date().setHours(0,0,0,0),
minDate = p.params.minDate ? new Date(p.params.minDate).getTime() : null,
maxDate = p.params.maxDate ? new Date(p.params.maxDate).getTime() : null,
disabled,
hasEvent;
if (p.value && p.value.length) {
for (i = 0; i < p.value.length; i++) {
currentValues.push(new Date(p.value[i]).setHours(0,0,0,0));
}
}
for (i = 1; i <= rows; i++) {
var rowHTML = '';
var row = i;
for (j = 1; j <= cols; j++) {
var col = j;
dayIndex ++;
var dayNumber = dayIndex - firstDayOfMonthIndex;
var weekDayIndex = (col - 1 + p.params.firstDay > 6) ? (col - 1 - 7 + p.params.firstDay) : (col - 1 + p.params.firstDay);
var addClass = '';
if (dayNumber < 0) {
dayNumber = daysInPrevMonth + dayNumber + 1;
addClass += ' picker-calendar-day-prev';
dayDate = new Date(month - 1 < 0 ? year - 1 : year, month - 1 < 0 ? 11 : month - 1, dayNumber).getTime();
}
else {
dayNumber = dayNumber + 1;
if (dayNumber > daysInMonth) {
dayNumber = dayNumber - daysInMonth;
addClass += ' picker-calendar-day-next';
dayDate = new Date(month + 1 > 11 ? year + 1 : year, month + 1 > 11 ? 0 : month + 1, dayNumber).getTime();
}
else {
dayDate = new Date(year, month, dayNumber).getTime();
}
}
// Today
if (dayDate === today) addClass += ' picker-calendar-day-today';
// Selected
if (p.params.rangePicker && currentValues.length === 2) {
if (dayDate >= currentValues[0] && dayDate <= currentValues[1]) addClass += ' picker-calendar-day-selected';
}
else {
if (currentValues.indexOf(dayDate) >= 0) addClass += ' picker-calendar-day-selected';
}
// Weekend
if (p.params.weekendDays.indexOf(weekDayIndex) >= 0) {
addClass += ' picker-calendar-day-weekend';
}
// Has Events
hasEvent = false;
if (p.params.events) {
if (p.dateInRange(dayDate, p.params.events)) {
hasEvent = true;
}
}
if (hasEvent) {
addClass += ' picker-calendar-day-has-events';
}
// Custom Ranges
if (p.params.rangesClasses) {
for (k = 0; k < p.params.rangesClasses.length; k++) {
if (p.dateInRange(dayDate, p.params.rangesClasses[k].range)) {
addClass += ' ' + p.params.rangesClasses[k].cssClass;
}
}
}
// Disabled
disabled = false;
if ((minDate && dayDate < minDate) || (maxDate && dayDate > maxDate)) {
disabled = true;
}
if (p.params.disabled) {
if (p.dateInRange(dayDate, p.params.disabled)) {
disabled = true;
}
}
if (disabled) {
addClass += ' picker-calendar-day-disabled';
}
dayDate = new Date(dayDate);
var dayYear = dayDate.getFullYear();
var dayMonth = dayDate.getMonth();
rowHTML += '<div data-year="' + dayYear + '" data-month="' + dayMonth + '" data-day="' + dayNumber + '" class="picker-calendar-day' + (addClass) + '" data-date="' + (dayYear + '-' + dayMonth + '-' + dayNumber) + '"><span>'+dayNumber+'</span></div>';
}
monthHTML += '<div class="picker-calendar-row">' + rowHTML + '</div>';
}
monthHTML = '<div class="picker-calendar-month" data-year="' + year + '" data-month="' + month + '">' + monthHTML + '</div>';
return monthHTML;
};
p.animating = false;
p.updateCurrentMonthYear = function (dir) {
if (typeof dir === 'undefined') {
p.currentMonth = parseInt(p.months.eq(1).attr('data-month'), 10);
p.currentYear = parseInt(p.months.eq(1).attr('data-year'), 10);
}
else {
p.currentMonth = parseInt(p.months.eq(dir === 'next' ? (p.months.length - 1) : 0).attr('data-month'), 10);
p.currentYear = parseInt(p.months.eq(dir === 'next' ? (p.months.length - 1) : 0).attr('data-year'), 10);
}
p.container.find('.current-month-value').text(p.params.monthNames[p.currentMonth]);
p.container.find('.current-year-value').text(p.currentYear);
};
p.onMonthChangeStart = function (dir) {
p.updateCurrentMonthYear(dir);
p.months.removeClass('picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next');
var currentIndex = dir === 'next' ? p.months.length - 1 : 0;
p.months.eq(currentIndex).addClass('picker-calendar-month-current');
p.months.eq(dir === 'next' ? currentIndex - 1 : currentIndex + 1).addClass(dir === 'next' ? 'picker-calendar-month-prev' : 'picker-calendar-month-next');
if (p.params.onMonthYearChangeStart) {
p.params.onMonthYearChangeStart(p, p.currentYear, p.currentMonth);
}
};
p.onMonthChangeEnd = function (dir, rebuildBoth) {
p.animating = false;
var nextMonthHTML, prevMonthHTML, newMonthHTML;
p.wrapper.find('.picker-calendar-month:not(.picker-calendar-month-prev):not(.picker-calendar-month-current):not(.picker-calendar-month-next)').remove();
if (typeof dir === 'undefined') {
dir = 'next';
rebuildBoth = true;
}
if (!rebuildBoth) {
newMonthHTML = p.monthHTML(new Date(p.currentYear, p.currentMonth), dir);
}
else {
p.wrapper.find('.picker-calendar-month-next, .picker-calendar-month-prev').remove();
prevMonthHTML = p.monthHTML(new Date(p.currentYear, p.currentMonth), 'prev');
nextMonthHTML = p.monthHTML(new Date(p.currentYear, p.currentMonth), 'next');
}
if (dir === 'next' || rebuildBoth) {
p.wrapper.append(newMonthHTML || nextMonthHTML);
}
if (dir === 'prev' || rebuildBoth) {
p.wrapper.prepend(newMonthHTML || prevMonthHTML);
}
p.months = p.wrapper.find('.picker-calendar-month');
p.setMonthsTranslate(p.monthsTranslate);
if (p.params.onMonthAdd) {
p.params.onMonthAdd(p, dir === 'next' ? p.months.eq(p.months.length - 1)[0] : p.months.eq(0)[0]);
}
if (p.params.onMonthYearChangeEnd) {
p.params.onMonthYearChangeEnd(p, p.currentYear, p.currentMonth);
}
};
p.setMonthsTranslate = function (translate) {
translate = translate || p.monthsTranslate || 0;
if (typeof p.monthsTranslate === 'undefined') p.monthsTranslate = translate;
p.months.removeClass('picker-calendar-month-current picker-calendar-month-prev picker-calendar-month-next');
var prevMonthTranslate = -(translate + 1) * 100 * inverter;
var currentMonthTranslate = -translate * 100 * inverter;
var nextMonthTranslate = -(translate - 1) * 100 * inverter;
p.months.eq(0).transform('translate3d(' + (p.isH ? prevMonthTranslate : 0) + '%, ' + (p.isH ? 0 : prevMonthTranslate) + '%, 0)').addClass('picker-calendar-month-prev');
p.months.eq(1).transform('translate3d(' + (p.isH ? currentMonthTranslate : 0) + '%, ' + (p.isH ? 0 : currentMonthTranslate) + '%, 0)').addClass('picker-calendar-month-current');
p.months.eq(2).transform('translate3d(' + (p.isH ? nextMonthTranslate : 0) + '%, ' + (p.isH ? 0 : nextMonthTranslate) + '%, 0)').addClass('picker-calendar-month-next');
};
p.nextMonth = function (transition) {
if (typeof transition === 'undefined' || typeof transition === 'object') {
transition = '';
if (!p.params.animate) transition = 0;
}
var nextMonth = parseInt(p.months.eq(p.months.length - 1).attr('data-month'), 10);
var nextYear = parseInt(p.months.eq(p.months.length - 1).attr('data-year'), 10);
var nextDate = new Date(nextYear, nextMonth);
var nextDateTime = nextDate.getTime();
var transitionEndCallback = p.animating ? false : true;
if (p.params.maxDate) {
if (nextDateTime > new Date(p.params.maxDate).getTime()) {
return p.resetMonth();
}
}
p.monthsTranslate --;
if (nextMonth === p.currentMonth) {
var nextMonthTranslate = -(p.monthsTranslate) * 100 * inverter;
var nextMonthHTML = $(p.monthHTML(nextDateTime, 'next')).transform('translate3d(' + (p.isH ? nextMonthTranslate : 0) + '%, ' + (p.isH ? 0 : nextMonthTranslate) + '%, 0)').addClass('picker-calendar-month-next');
p.wrapper.append(nextMonthHTML[0]);
p.months = p.wrapper.find('.picker-calendar-month');
if (p.params.onMonthAdd) {
p.params.onMonthAdd(p, p.months.eq(p.months.length - 1)[0]);
}
}
p.animating = true;
p.onMonthChangeStart('next');
var translate = (p.monthsTranslate * 100) * inverter;
p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? translate : 0) + '%, ' + (p.isH ? 0 : translate) + '%, 0)');
if (transitionEndCallback) {
p.wrapper.transitionEnd(function () {
p.onMonthChangeEnd('next');
});
}
if (!p.params.animate) {
p.onMonthChangeEnd('next');
}
};
p.prevMonth = function (transition) {
if (typeof transition === 'undefined' || typeof transition === 'object') {
transition = '';
if (!p.params.animate) transition = 0;
}
var prevMonth = parseInt(p.months.eq(0).attr('data-month'), 10);
var prevYear = parseInt(p.months.eq(0).attr('data-year'), 10);
var prevDate = new Date(prevYear, prevMonth + 1, -1);
var prevDateTime = prevDate.getTime();
var transitionEndCallback = p.animating ? false : true;
if (p.params.minDate) {
if (prevDateTime < new Date(p.params.minDate).getTime()) {
return p.resetMonth();
}
}
p.monthsTranslate ++;
if (prevMonth === p.currentMonth) {
var prevMonthTranslate = -(p.monthsTranslate) * 100 * inverter;
var prevMonthHTML = $(p.monthHTML(prevDateTime, 'prev')).transform('translate3d(' + (p.isH ? prevMonthTranslate : 0) + '%, ' + (p.isH ? 0 : prevMonthTranslate) + '%, 0)').addClass('picker-calendar-month-prev');
p.wrapper.prepend(prevMonthHTML[0]);
p.months = p.wrapper.find('.picker-calendar-month');
if (p.params.onMonthAdd) {
p.params.onMonthAdd(p, p.months.eq(0)[0]);
}
}
p.animating = true;
p.onMonthChangeStart('prev');
var translate = (p.monthsTranslate * 100) * inverter;
p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? translate : 0) + '%, ' + (p.isH ? 0 : translate) + '%, 0)');
if (transitionEndCallback) {
p.wrapper.transitionEnd(function () {
p.onMonthChangeEnd('prev');
});
}
if (!p.params.animate) {
p.onMonthChangeEnd('prev');
}
};
p.resetMonth = function (transition) {
if (typeof transition === 'undefined') transition = '';
var translate = (p.monthsTranslate * 100) * inverter;
p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? translate : 0) + '%, ' + (p.isH ? 0 : translate) + '%, 0)');
};
p.setYearMonth = function (year, month, transition) {
if (typeof year === 'undefined') year = p.currentYear;
if (typeof month === 'undefined') month = p.currentMonth;
if (typeof transition === 'undefined' || typeof transition === 'object') {
transition = '';
if (!p.params.animate) transition = 0;
}
var targetDate;
if (year < p.currentYear) {
targetDate = new Date(year, month + 1, -1).getTime();
}
else {
targetDate = new Date(year, month).getTime();
}
if (p.params.maxDate && targetDate > new Date(p.params.maxDate).getTime()) {
return false;
}
if (p.params.minDate && targetDate < new Date(p.params.minDate).getTime()) {
return false;
}
var currentDate = new Date(p.currentYear, p.currentMonth).getTime();
var dir = targetDate > currentDate ? 'next' : 'prev';
var newMonthHTML = p.monthHTML(new Date(year, month));
p.monthsTranslate = p.monthsTranslate || 0;
var prevTranslate = p.monthsTranslate;
var monthTranslate, wrapperTranslate;
var transitionEndCallback = p.animating ? false : true;
if (targetDate > currentDate) {
// To next
p.monthsTranslate --;
if (!p.animating) p.months.eq(p.months.length - 1).remove();
p.wrapper.append(newMonthHTML);
p.months = p.wrapper.find('.picker-calendar-month');
monthTranslate = -(prevTranslate - 1) * 100 * inverter;
p.months.eq(p.months.length - 1).transform('translate3d(' + (p.isH ? monthTranslate : 0) + '%, ' + (p.isH ? 0 : monthTranslate) + '%, 0)').addClass('picker-calendar-month-next');
}
else {
// To prev
p.monthsTranslate ++;
if (!p.animating) p.months.eq(0).remove();
p.wrapper.prepend(newMonthHTML);
p.months = p.wrapper.find('.picker-calendar-month');
monthTranslate = -(prevTranslate + 1) * 100 * inverter;
p.months.eq(0).transform('translate3d(' + (p.isH ? monthTranslate : 0) + '%, ' + (p.isH ? 0 : monthTranslate) + '%, 0)').addClass('picker-calendar-month-prev');
}
if (p.params.onMonthAdd) {
p.params.onMonthAdd(p, dir === 'next' ? p.months.eq(p.months.length - 1)[0] : p.months.eq(0)[0]);
}
p.animating = true;
p.onMonthChangeStart(dir);
wrapperTranslate = (p.monthsTranslate * 100) * inverter;
p.wrapper.transition(transition).transform('translate3d(' + (p.isH ? wrapperTranslate : 0) + '%, ' + (p.isH ? 0 : wrapperTranslate) + '%, 0)');
if (transitionEndCallback) {
p.wrapper.transitionEnd(function () {
p.onMonthChangeEnd(dir, true);
});
}
if (!p.params.animate) {
p.onMonthChangeEnd(dir);
}
};
p.nextYear = function () {
p.setYearMonth(p.currentYear + 1);
};
p.prevYear = function () {
p.setYearMonth(p.currentYear - 1);
};
// HTML Layout
p.layout = function () {
var pickerHTML = '';
var pickerClass = '';
var i;
var layoutDate = p.value && p.value.length ? p.value[0] : new Date().setHours(0,0,0,0);
var prevMonthHTML = p.monthHTML(layoutDate, 'prev');
var currentMonthHTML = p.monthHTML(layoutDate);
var nextMonthHTML = p.monthHTML(layoutDate, 'next');
var monthsHTML = '<div class="picker-calendar-months"><div class="picker-calendar-months-wrapper">' + (prevMonthHTML + currentMonthHTML + nextMonthHTML) + '</div></div>';
// Week days header
var weekHeaderHTML = '';
if (p.params.weekHeader) {
for (i = 0; i < 7; i++) {
var weekDayIndex = (i + p.params.firstDay > 6) ? (i - 7 + p.params.firstDay) : (i + p.params.firstDay);
var dayName = p.params.dayNamesShort[weekDayIndex];
weekHeaderHTML += '<div class="picker-calendar-week-day ' + ((p.params.weekendDays.indexOf(weekDayIndex) >= 0) ? 'picker-calendar-week-day-weekend' : '') + '"> ' + dayName + '</div>';
}
weekHeaderHTML = '<div class="picker-calendar-week-days">' + weekHeaderHTML + '</div>';
}
pickerClass = 'picker-modal picker-calendar' +
(p.params.rangePicker ? ' picker-calendar-range' : '') +
(p.params.cssClass ? ' ' + p.params.cssClass : '');
var toolbarHTML = p.params.toolbar ? p.params.toolbarTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText) : '';
if (p.params.toolbar) {
toolbarHTML = p.params.toolbarTemplate
.replace(/{{closeText}}/g, p.params.toolbarCloseText)
.replace(/{{monthPicker}}/g, (p.params.monthPicker ? p.params.monthPickerTemplate : ''))
.replace(/{{yearPicker}}/g, (p.params.yearPicker ? p.params.yearPickerTemplate : ''));
}
var headerHTML = p.params.header ? p.params.headerTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText).replace(/{{placeholder}}/g, p.params.headerPlaceholder) : '';
var footerHTML = p.params.footer ? p.params.footerTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText) : '';
pickerHTML =
'<div class="' + (pickerClass) + '">' +
headerHTML +
footerHTML +
toolbarHTML +
'<div class="picker-modal-inner">' +
weekHeaderHTML +
monthsHTML +
'</div>' +
'</div>';
p.pickerHTML = pickerHTML;
};
// Input Events
function openOnInput(e) {
e.preventDefault();
if (p.opened) return;
p.open();
if (p.params.scrollToInput && !isPopover() && !app.params.material) {
var pageContent = p.input.parents('.page-content');
if (pageContent.length === 0) return;
var paddingTop = parseInt(pageContent.css('padding-top'), 10),
paddingBottom = parseInt(pageContent.css('padding-bottom'), 10),
pageHeight = pageContent[0].offsetHeight - paddingTop - p.container.height(),
pageScrollHeight = pageContent[0].scrollHeight - paddingTop - p.container.height(),
newPaddingBottom;
var inputTop = p.input.offset().top - paddingTop + p.input[0].offsetHeight;
if (inputTop > pageHeight) {
var scrollTop = pageContent.scrollTop() + inputTop - pageHeight;
if (scrollTop + pageHeight > pageScrollHeight) {
newPaddingBottom = scrollTop + pageHeight - pageScrollHeight + paddingBottom;
if (pageHeight === pageScrollHeight) {
newPaddingBottom = p.container.height();
}
pageContent.css({'padding-bottom': (newPaddingBottom) + 'px'});
}
pageContent.scrollTop(scrollTop, 300);
}
}
}
function closeOnHTMLClick(e) {
if (inPopover()) return;
if (p.input && p.input.length > 0) {
if (e.target !== p.input[0] && $(e.target).parents('.picker-modal').length === 0) p.close();
}
else {
if ($(e.target).parents('.picker-modal').length === 0) p.close();
}
}
if (p.params.input) {
p.input = $(p.params.input);
if (p.input.length > 0) {
if (p.params.inputReadOnly) p.input.prop('readOnly', true);
if (!p.inline) {
p.input.on('click', openOnInput);
}
if (p.params.inputReadOnly) {
p.input.on('focus mousedown', function (e) {
e.preventDefault();
});
}
}
}
if (!p.inline && p.params.closeByOutsideClick) $('html').on('click', closeOnHTMLClick);
// Open
function onPickerClose() {
p.opened = false;
if (p.input && p.input.length > 0) {
p.input.parents('.page-content').css({'padding-bottom': ''});
if (app.params.material) p.input.trigger('blur');
}
if (p.params.onClose) p.params.onClose(p);
// Destroy events
p.destroyCalendarEvents();
}
p.opened = false;
p.open = function () {
var toPopover = isPopover();
var updateValue = false;
if (!p.opened) {
// Set date value
if (!p.value) {
if (p.params.value) {
p.value = p.params.value;
updateValue = true;
}
}
// Layout
p.layout();
// Append
if (toPopover) {
p.pickerHTML = '<div class="popover popover-picker-calendar"><div class="popover-inner">' + p.pickerHTML + '</div></div>';
p.popover = app.popover(p.pickerHTML, p.params.input, true);
p.container = $(p.popover).find('.picker-modal');
$(p.popover).on('close', function () {
onPickerClose();
});
}
else if (p.inline) {
p.container = $(p.pickerHTML);
p.container.addClass('picker-modal-inline');
$(p.params.container).append(p.container);
}
else {
p.container = $(app.pickerModal(p.pickerHTML));
$(p.container)
.on('close', function () {
onPickerClose();
});
}
// Store calendar instance
p.container[0].f7Calendar = p;
p.wrapper = p.container.find('.picker-calendar-months-wrapper');
// Months
p.months = p.wrapper.find('.picker-calendar-month');
// Update current month and year
p.updateCurrentMonthYear();
// Set initial translate
p.monthsTranslate = 0;
p.setMonthsTranslate();
// Init events
p.initCalendarEvents();
// Update input value
if (updateValue) p.updateValue();
else if (app.params.material && p.value) p.updateValue(true);
// Material Focus
if (p.input && p.input.length > 0 && app.params.material) {
p.input.trigger('focus');
}
}
// Set flag
p.opened = true;
p.initialized = true;
if (p.params.onMonthAdd) {
p.months.each(function () {
p.params.onMonthAdd(p, this);
});
}
if (p.params.onOpen) p.params.onOpen(p);
};
// Close
p.close = function () {
if (!p.opened || p.inline) return;
if (inPopover()) {
app.closeModal(p.popover);
return;
}
else {
app.closeModal(p.container);
return;
}
};
// Destroy
p.destroy = function () {
p.close();
if (p.params.input && p.input.length > 0) {
p.input.off('click focus', openOnInput);
}
$('html').off('click', closeOnHTMLClick);
};
if (p.inline) {
p.open();
}
else {
if (!p.initialized && p.params.value) p.setValue(p.params.value);
}
return p;
};
app.calendar = function (params) {
return new Calendar(params);
};
/*======================================================
************ Notifications ************
======================================================*/
var _tempNotificationElement;
app.addNotification = function (params) {
if (!params) return;
if (typeof params.media === 'undefined') params.media = app.params.notificationMedia;
if (typeof params.title === 'undefined') params.title = app.params.notificationTitle;
if (typeof params.subtitle === 'undefined') params.subtitle = app.params.notificationSubtitle;
if (typeof params.closeIcon === 'undefined') params.closeIcon = app.params.notificationCloseIcon;
if (typeof params.hold === 'undefined') params.hold = app.params.notificationHold;
if (typeof params.closeOnClick === 'undefined') params.closeOnClick = app.params.notificationCloseOnClick;
if (typeof params.button === 'undefined') params.button = app.params.notificationCloseButtonText && {
text: app.params.notificationCloseButtonText,
close: true
};
if (!_tempNotificationElement) _tempNotificationElement = document.createElement('div');
params.material = app.params.material;
var container = $('.notifications');
if (container.length === 0) {
app.root.append('<div class="notifications list-block' + (params.material ? '' : ' media-list') + '"><ul></ul></div>');
container = $('.notifications');
}
var list = container.children('ul');
var notificationTemplate = app.params.notificationTemplate ||
'{{#if custom}}' +
'<li>{{custom}}</li>' +
'{{else}}' +
'<li class="notification-item notification-hidden">' +
'<div class="item-content">' +
'{{#if material}}' +
'<div class="item-inner">' +
'<div class="item-title">{{js "this.message || this.title || this.subtitle"}}</div>' +
'{{#if ../button}}{{#button}}' +
'<div class="item-after">' +
'<a href="#" class="button {{#if color}}color-{{color}}{{/if}} {{#js_compare "this.close !== false"}}close-notification{{/js_compare}}">{{text}}</a>' +
'</div>' +
'{{/button}}{{/if}}' +
'</div>' +
'{{else}}' +
'{{#if media}}' +
'<div class="item-media">{{media}}</div>' +
'{{/if}}' +
'<div class="item-inner">' +
'<div class="item-title-row">' +
'{{#if title}}' +
'<div class="item-title">{{title}}</div>' +
'{{/if}}' +
'{{#if closeIcon}}' +
'<div class="item-after"><a href="#" class="close-notification"><span></span></a></div>' +
'{{/if}}' +
'</div>' +
'{{#if subtitle}}' +
'<div class="item-subtitle">{{subtitle}}</div>' +
'{{/if}}' +
'{{#if message}}' +
'<div class="item-text">{{message}}</div>' +
'</div>' +
'{{/if}}' +
'{{/if}}' +
'</div>' +
'</li>' +
'{{/if}}';
if (!app._compiledTemplates.notification) {
app._compiledTemplates.notification = t7.compile(notificationTemplate);
}
_tempNotificationElement.innerHTML = app._compiledTemplates.notification(params);
var item = $(_tempNotificationElement).children();
item.on('click', function (e) {
var close = false;
var target = $(e.target);
if (params.material && target.hasClass('button')) {
if (params.button && params.button.onClick) params.button.onClick.call(target[0], e, item[0]);
}
if (target.is('.close-notification') || $(e.target).parents('.close-notification').length > 0) {
close = true;
}
else {
if (params.onClick) params.onClick(e, item[0]);
if (params.closeOnClick) close = true;
}
if (close) app.closeNotification(item[0]);
});
if (params.onClose) {
item.data('f7NotificationOnClose', function () {
params.onClose(item[0]);
});
}
if (params.additionalClass) {
item.addClass(params.additionalClass);
}
if (params.hold) {
setTimeout(function () {
if (item.length > 0) app.closeNotification(item[0]);
}, params.hold);
}
if (!app.params.material) {
app.closeNotification(list.children('li.notification-item:last-child'));
}
list.append(item[0]);
container.show();
var itemHeight = item.outerHeight(), clientLeft;
if (params.material) {
container.transform('translate3d(0, '+itemHeight+'px, 0)');
container.transition(0);
clientLeft = item[0].clientLeft;
container.transform('translate3d(0, 0, 0)');
container.transition('');
}
else {
item.transform('translate3d(0,' + (-itemHeight) + 'px,0)');
item.transition(0);
clientLeft = item[0].clientLeft;
item.transition('');
item.transform('translate3d(0,0px,0)');
}
container.transform('translate3d(0, 0,0)');
item.removeClass('notification-hidden');
return item[0];
};
app.closeNotification = function (item) {
item = $(item);
if (item.length === 0) return;
if (item.hasClass('notification-item-removing')) return;
var container = $('.notifications');
var itemHeight = item.outerHeight();
item.css('height', itemHeight + 'px').transition(0).addClass('notification-item-removing');
var clientLeft = item[0].clientLeft;
item.css({
height: '0px',
marginBottom: '0px'
}).transition('');
if (item.data('f7NotificationOnClose')) item.data('f7NotificationOnClose')();
if (container.find('.notification-item:not(.notification-item-removing)').length === 0) {
container.transform('');
}
item.addClass('notification-hidden').transitionEnd(function () {
item.remove();
if (container.find('.notification-item').length === 0) {
container.hide();
}
});
};
/*===========================
Compile Template7 Templates On App Init
===========================*/
app.initTemplate7Templates = function () {
if (!window.Template7) return;
Template7.templates = Template7.templates || app.params.templates || {};
Template7.data = Template7.data || app.params.template7Data || {};
Template7.cache = Template7.cache || {};
app.templates = Template7.templates;
app.template7Data = Template7.data;
app.template7Cache = Template7.cache;
// Precompile templates on app init
if (!app.params.precompileTemplates) return;
$('script[type="text/template7"]').each(function () {
var id = $(this).attr('id');
if (!id) return;
Template7.templates[id] = Template7.compile($(this).html());
});
};
/*=======================================
************ Plugins API ************
=======================================*/
var _plugins = [];
app.initPlugins = function () {
// Initialize plugins
for (var plugin in app.plugins) {
var p = app.plugins[plugin](app, app.params[plugin]);
if (p) _plugins.push(p);
}
};
// Plugin Hooks
app.pluginHook = function (hook) {
for (var i = 0; i < _plugins.length; i++) {
if (_plugins[i].hooks && hook in _plugins[i].hooks) {
_plugins[i].hooks[hook](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
}
}
};
// Prevented by plugin
app.pluginPrevent = function (action) {
var prevent = false;
for (var i = 0; i < _plugins.length; i++) {
if (_plugins[i].prevents && action in _plugins[i].prevents) {
if (_plugins[i].prevents[action](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5])) prevent = true;
}
}
return prevent;
};
// Preprocess content by plugin
app.pluginProcess = function (process, data) {
var processed = data;
for (var i = 0; i < _plugins.length; i++) {
if (_plugins[i].preprocess && process in _plugins[i].preprocess) {
processed = _plugins[i].preprocess[process](data, arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
}
}
return processed;
};
/*======================================================
************ App Init ************
======================================================*/
app.init = function () {
// Compile Template7 templates on app load
if (app.initTemplate7Templates) app.initTemplate7Templates();
// Init Plugins
if (app.initPlugins) app.initPlugins();
// Init Device
if (app.getDeviceInfo) app.getDeviceInfo();
// Init Click events
if (app.initFastClicks && app.params.fastClicks) app.initFastClicks();
if (app.initClickEvents) app.initClickEvents();
// Init each page callbacks
$('.page:not(.cached)').each(function () {
app.initPageWithCallback(this);
});
// Init each navbar callbacks
$('.navbar:not(.cached)').each(function () {
app.initNavbarWithCallback(this);
});
// Init resize events
if (app.initResize) app.initResize();
// Init push state
if (app.initPushState && app.params.pushState) app.initPushState();
// Init Live Swipeouts events
if (app.initSwipeout && app.params.swipeout) app.initSwipeout();
// Init Live Sortable events
if (app.initSortable && app.params.sortable) app.initSortable();
// Init Live Swipe Panels
if (app.initSwipePanels && (app.params.swipePanel || app.params.swipePanelOnlyClose)) app.initSwipePanels();
// Init Material Inputs
if (app.params.material && app.initMaterialWatchInputs) app.initMaterialWatchInputs();
// App Init callback
if (app.params.onAppInit) app.params.onAppInit();
// Plugin app init hook
app.pluginHook('appInit');
};
if (app.params.init) app.init();
//Return instance
return app;
};
/*===========================
Dom7 Library
===========================*/
var Dom7 = (function () {
var Dom7 = function (arr) {
var _this = this, i = 0;
// Create array-like object
for (i = 0; i < arr.length; i++) {
_this[i] = arr[i];
}
_this.length = arr.length;
// Return collection with methods
return this;
};
var $ = function (selector, context) {
var arr = [], i = 0;
if (selector && !context) {
if (selector instanceof Dom7) {
return selector;
}
}
if (selector) {
// String
if (typeof selector === 'string') {
var els, tempParent, html;
selector = html = selector.trim();
if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) {
var toCreate = 'div';
if (html.indexOf('<li') === 0) toCreate = 'ul';
if (html.indexOf('<tr') === 0) toCreate = 'tbody';
if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) toCreate = 'tr';
if (html.indexOf('<tbody') === 0) toCreate = 'table';
if (html.indexOf('<option') === 0) toCreate = 'select';
tempParent = document.createElement(toCreate);
tempParent.innerHTML = html;
for (i = 0; i < tempParent.childNodes.length; i++) {
arr.push(tempParent.childNodes[i]);
}
}
else {
if (!context && selector[0] === '#' && !selector.match(/[ .<>:~]/)) {
// Pure ID selector
els = [document.getElementById(selector.split('#')[1])];
}
else {
// Other selectors
els = (context || document).querySelectorAll(selector);
}
for (i = 0; i < els.length; i++) {
if (els[i]) arr.push(els[i]);
}
}
}
// Node/element
else if (selector.nodeType || selector === window || selector === document) {
arr.push(selector);
}
//Array of elements or instance of Dom
else if (selector.length > 0 && selector[0].nodeType) {
for (i = 0; i < selector.length; i++) {
arr.push(selector[i]);
}
}
}
return new Dom7(arr);
};
Dom7.prototype = {
// Classes and attriutes
addClass: function (className) {
if (typeof className === 'undefined') {
return this;
}
var classes = className.split(' ');
for (var i = 0; i < classes.length; i++) {
for (var j = 0; j < this.length; j++) {
if (typeof this[j].classList !== 'undefined') this[j].classList.add(classes[i]);
}
}
return this;
},
removeClass: function (className) {
var classes = className.split(' ');
for (var i = 0; i < classes.length; i++) {
for (var j = 0; j < this.length; j++) {
if (typeof this[j].classList !== 'undefined') this[j].classList.remove(classes[i]);
}
}
return this;
},
hasClass: function (className) {
if (!this[0]) return false;
else return this[0].classList.contains(className);
},
toggleClass: function (className) {
var classes = className.split(' ');
for (var i = 0; i < classes.length; i++) {
for (var j = 0; j < this.length; j++) {
if (typeof this[j].classList !== 'undefined') this[j].classList.toggle(classes[i]);
}
}
return this;
},
attr: function (attrs, value) {
if (arguments.length === 1 && typeof attrs === 'string') {
// Get attr
if (this[0]) return this[0].getAttribute(attrs);
else return undefined;
}
else {
// Set attrs
for (var i = 0; i < this.length; i++) {
if (arguments.length === 2) {
// String
this[i].setAttribute(attrs, value);
}
else {
// Object
for (var attrName in attrs) {
this[i][attrName] = attrs[attrName];
this[i].setAttribute(attrName, attrs[attrName]);
}
}
}
return this;
}
},
removeAttr: function (attr) {
for (var i = 0; i < this.length; i++) {
this[i].removeAttribute(attr);
}
return this;
},
prop: function (props, value) {
if (arguments.length === 1 && typeof props === 'string') {
// Get prop
if (this[0]) return this[0][props];
else return undefined;
}
else {
// Set props
for (var i = 0; i < this.length; i++) {
if (arguments.length === 2) {
// String
this[i][props] = value;
}
else {
// Object
for (var propName in props) {
this[i][propName] = props[propName];
}
}
}
return this;
}
},
data: function (key, value) {
if (typeof value === 'undefined') {
// Get value
if (this[0]) {
if (this[0].dom7ElementDataStorage && (key in this[0].dom7ElementDataStorage)) {
return this[0].dom7ElementDataStorage[key];
}
else {
var dataKey = this[0].getAttribute('data-' + key);
if (dataKey) {
return dataKey;
}
else return undefined;
}
}
else return undefined;
}
else {
// Set value
for (var i = 0; i < this.length; i++) {
var el = this[i];
if (!el.dom7ElementDataStorage) el.dom7ElementDataStorage = {};
el.dom7ElementDataStorage[key] = value;
}
return this;
}
},
removeData: function(key) {
for (var i = 0; i < this.length; i++) {
var el = this[i];
if (el.dom7ElementDataStorage && el.dom7ElementDataStorage[key]) {
el.dom7ElementDataStorage[key] = null;
delete el.dom7ElementDataStorage[key];
}
}
},
dataset: function () {
var el = this[0];
if (el) {
var dataset = {};
if (el.dataset) {
for (var dataKey in el.dataset) {
dataset[dataKey] = el.dataset[dataKey];
}
}
else {
for (var i = 0; i < el.attributes.length; i++) {
var attr = el.attributes[i];
if (attr.name.indexOf('data-') >= 0) {
dataset[$.toCamelCase(attr.name.split('data-')[1])] = attr.value;
}
}
}
for (var key in dataset) {
if (dataset[key] === 'false') dataset[key] = false;
else if (dataset[key] === 'true') dataset[key] = true;
else if (parseFloat(dataset[key]) === dataset[key] * 1) dataset[key] = dataset[key] * 1;
}
return dataset;
}
else return undefined;
},
val: function (value) {
if (typeof value === 'undefined') {
if (this[0]) return this[0].value;
else return undefined;
}
else {
for (var i = 0; i < this.length; i++) {
this[i].value = value;
}
return this;
}
},
// Transforms
transform : function (transform) {
for (var i = 0; i < this.length; i++) {
var elStyle = this[i].style;
elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform;
}
return this;
},
transition: function (duration) {
if (typeof duration !== 'string') {
duration = duration + 'ms';
}
for (var i = 0; i < this.length; i++) {
var elStyle = this[i].style;
elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration;
}
return this;
},
//Events
on: function (eventName, targetSelector, listener, capture) {
function handleLiveEvent(e) {
var target = e.target;
if ($(target).is(targetSelector)) listener.call(target, e);
else {
var parents = $(target).parents();
for (var k = 0; k < parents.length; k++) {
if ($(parents[k]).is(targetSelector)) listener.call(parents[k], e);
}
}
}
var events = eventName.split(' ');
var i, j;
for (i = 0; i < this.length; i++) {
if (typeof targetSelector === 'function' || targetSelector === false) {
// Usual events
if (typeof targetSelector === 'function') {
listener = arguments[1];
capture = arguments[2] || false;
}
for (j = 0; j < events.length; j++) {
this[i].addEventListener(events[j], listener, capture);
}
}
else {
//Live events
for (j = 0; j < events.length; j++) {
if (!this[i].dom7LiveListeners) this[i].dom7LiveListeners = [];
this[i].dom7LiveListeners.push({listener: listener, liveListener: handleLiveEvent});
this[i].addEventListener(events[j], handleLiveEvent, capture);
}
}
}
return this;
},
off: function (eventName, targetSelector, listener, capture) {
var events = eventName.split(' ');
for (var i = 0; i < events.length; i++) {
for (var j = 0; j < this.length; j++) {
if (typeof targetSelector === 'function' || targetSelector === false) {
// Usual events
if (typeof targetSelector === 'function') {
listener = arguments[1];
capture = arguments[2] || false;
}
this[j].removeEventListener(events[i], listener, capture);
}
else {
// Live event
if (this[j].dom7LiveListeners) {
for (var k = 0; k < this[j].dom7LiveListeners.length; k++) {
if (this[j].dom7LiveListeners[k].listener === listener) {
this[j].removeEventListener(events[i], this[j].dom7LiveListeners[k].liveListener, capture);
}
}
}
}
}
}
return this;
},
once: function (eventName, targetSelector, listener, capture) {
var dom = this;
if (typeof targetSelector === 'function') {
listener = arguments[1];
capture = arguments[2];
targetSelector = false;
}
function proxy(e) {
listener.call(e.target, e);
dom.off(eventName, targetSelector, proxy, capture);
}
return dom.on(eventName, targetSelector, proxy, capture);
},
trigger: function (eventName, eventData) {
var events = eventName.split(' ');
for (var i = 0; i < events.length; i++) {
for (var j = 0; j < this.length; j++) {
var evt;
try {
evt = new CustomEvent(events[i], {detail: eventData, bubbles: true, cancelable: true});
}
catch (e) {
evt = document.createEvent('Event');
evt.initEvent(events[i], true, true);
evt.detail = eventData;
}
this[j].dispatchEvent(evt);
}
}
return this;
},
transitionEnd: function (callback) {
var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'],
i, j, dom = this;
function fireCallBack(e) {
/*jshint validthis:true */
if (e.target !== this) return;
callback.call(this, e);
for (i = 0; i < events.length; i++) {
dom.off(events[i], fireCallBack);
}
}
if (callback) {
for (i = 0; i < events.length; i++) {
dom.on(events[i], fireCallBack);
}
}
return this;
},
animationEnd: function (callback) {
var events = ['webkitAnimationEnd', 'OAnimationEnd', 'MSAnimationEnd', 'animationend'],
i, j, dom = this;
function fireCallBack(e) {
callback(e);
for (i = 0; i < events.length; i++) {
dom.off(events[i], fireCallBack);
}
}
if (callback) {
for (i = 0; i < events.length; i++) {
dom.on(events[i], fireCallBack);
}
}
return this;
},
// Sizing/Styles
width: function () {
if (this[0] === window) {
return window.innerWidth;
}
else {
if (this.length > 0) {
return parseFloat(this.css('width'));
}
else {
return null;
}
}
},
outerWidth: function (includeMargins) {
if (this.length > 0) {
if (includeMargins) {
var styles = this.styles();
return this[0].offsetWidth + parseFloat(styles.getPropertyValue('margin-right')) + parseFloat(styles.getPropertyValue('margin-left'));
}
else
return this[0].offsetWidth;
}
else return null;
},
height: function () {
if (this[0] === window) {
return window.innerHeight;
}
else {
if (this.length > 0) {
return parseFloat(this.css('height'));
}
else {
return null;
}
}
},
outerHeight: function (includeMargins) {
if (this.length > 0) {
if (includeMargins) {
var styles = this.styles();
return this[0].offsetHeight + parseFloat(styles.getPropertyValue('margin-top')) + parseFloat(styles.getPropertyValue('margin-bottom'));
}
else
return this[0].offsetHeight;
}
else return null;
},
offset: function () {
if (this.length > 0) {
var el = this[0];
var box = el.getBoundingClientRect();
var body = document.body;
var clientTop = el.clientTop || body.clientTop || 0;
var clientLeft = el.clientLeft || body.clientLeft || 0;
var scrollTop = window.pageYOffset || el.scrollTop;
var scrollLeft = window.pageXOffset || el.scrollLeft;
return {
top: box.top + scrollTop - clientTop,
left: box.left + scrollLeft - clientLeft
};
}
else {
return null;
}
},
hide: function () {
for (var i = 0; i < this.length; i++) {
this[i].style.display = 'none';
}
return this;
},
show: function () {
for (var i = 0; i < this.length; i++) {
this[i].style.display = 'block';
}
return this;
},
styles: function () {
var i, styles;
if (this[0]) return window.getComputedStyle(this[0], null);
else return undefined;
},
css: function (props, value) {
var i;
if (arguments.length === 1) {
if (typeof props === 'string') {
if (this[0]) return window.getComputedStyle(this[0], null).getPropertyValue(props);
}
else {
for (i = 0; i < this.length; i++) {
for (var prop in props) {
this[i].style[prop] = props[prop];
}
}
return this;
}
}
if (arguments.length === 2 && typeof props === 'string') {
for (i = 0; i < this.length; i++) {
this[i].style[props] = value;
}
return this;
}
return this;
},
//Dom manipulation
each: function (callback) {
for (var i = 0; i < this.length; i++) {
callback.call(this[i], i, this[i]);
}
return this;
},
filter: function (callback) {
var matchedItems = [];
var dom = this;
for (var i = 0; i < dom.length; i++) {
if (callback.call(dom[i], i, dom[i])) matchedItems.push(dom[i]);
}
return new Dom7(matchedItems);
},
html: function (html) {
if (typeof html === 'undefined') {
return this[0] ? this[0].innerHTML : undefined;
}
else {
for (var i = 0; i < this.length; i++) {
this[i].innerHTML = html;
}
return this;
}
},
text: function (text) {
if (typeof text === 'undefined') {
if (this[0]) {
return this[0].textContent.trim();
}
else return null;
}
else {
for (var i = 0; i < this.length; i++) {
this[i].textContent = text;
}
return this;
}
},
is: function (selector) {
if (!this[0] || typeof selector === 'undefined') return false;
var compareWith, i;
if (typeof selector === 'string') {
var el = this[0];
if (el === document) return selector === document;
if (el === window) return selector === window;
if (el.matches) return el.matches(selector);
else if (el.webkitMatchesSelector) return el.webkitMatchesSelector(selector);
else if (el.mozMatchesSelector) return el.mozMatchesSelector(selector);
else if (el.msMatchesSelector) return el.msMatchesSelector(selector);
else {
compareWith = $(selector);
for (i = 0; i < compareWith.length; i++) {
if (compareWith[i] === this[0]) return true;
}
return false;
}
}
else if (selector === document) return this[0] === document;
else if (selector === window) return this[0] === window;
else {
if (selector.nodeType || selector instanceof Dom7) {
compareWith = selector.nodeType ? [selector] : selector;
for (i = 0; i < compareWith.length; i++) {
if (compareWith[i] === this[0]) return true;
}
return false;
}
return false;
}
},
indexOf: function (el) {
for (var i = 0; i < this.length; i++) {
if (this[i] === el) return i;
}
},
index: function () {
if (this[0]) {
var child = this[0];
var i = 0;
while ((child = child.previousSibling) !== null) {
if (child.nodeType === 1) i++;
}
return i;
}
else return undefined;
},
eq: function (index) {
if (typeof index === 'undefined') return this;
var length = this.length;
var returnIndex;
if (index > length - 1) {
return new Dom7([]);
}
if (index < 0) {
returnIndex = length + index;
if (returnIndex < 0) return new Dom7([]);
else return new Dom7([this[returnIndex]]);
}
return new Dom7([this[index]]);
},
append: function (newChild) {
var i, j;
for (i = 0; i < this.length; i++) {
if (typeof newChild === 'string') {
var tempDiv = document.createElement('div');
tempDiv.innerHTML = newChild;
while (tempDiv.firstChild) {
this[i].appendChild(tempDiv.firstChild);
}
}
else if (newChild instanceof Dom7) {
for (j = 0; j < newChild.length; j++) {
this[i].appendChild(newChild[j]);
}
}
else {
this[i].appendChild(newChild);
}
}
return this;
},
appendTo: function (parent) {
$(parent).append(this);
return this;
},
prepend: function (newChild) {
var i, j;
for (i = 0; i < this.length; i++) {
if (typeof newChild === 'string') {
var tempDiv = document.createElement('div');
tempDiv.innerHTML = newChild;
for (j = tempDiv.childNodes.length - 1; j >= 0; j--) {
this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]);
}
// this[i].insertAdjacentHTML('afterbegin', newChild);
}
else if (newChild instanceof Dom7) {
for (j = 0; j < newChild.length; j++) {
this[i].insertBefore(newChild[j], this[i].childNodes[0]);
}
}
else {
this[i].insertBefore(newChild, this[i].childNodes[0]);
}
}
return this;
},
prependTo: function (parent) {
$(parent).prepend(this);
return this;
},
insertBefore: function (selector) {
var before = $(selector);
for (var i = 0; i < this.length; i++) {
if (before.length === 1) {
before[0].parentNode.insertBefore(this[i], before[0]);
}
else if (before.length > 1) {
for (var j = 0; j < before.length; j++) {
before[j].parentNode.insertBefore(this[i].cloneNode(true), before[j]);
}
}
}
},
insertAfter: function (selector) {
var after = $(selector);
for (var i = 0; i < this.length; i++) {
if (after.length === 1) {
after[0].parentNode.insertBefore(this[i], after[0].nextSibling);
}
else if (after.length > 1) {
for (var j = 0; j < after.length; j++) {
after[j].parentNode.insertBefore(this[i].cloneNode(true), after[j].nextSibling);
}
}
}
},
next: function (selector) {
if (this.length > 0) {
if (selector) {
if (this[0].nextElementSibling && $(this[0].nextElementSibling).is(selector)) return new Dom7([this[0].nextElementSibling]);
else return new Dom7([]);
}
else {
if (this[0].nextElementSibling) return new Dom7([this[0].nextElementSibling]);
else return new Dom7([]);
}
}
else return new Dom7([]);
},
nextAll: function (selector) {
var nextEls = [];
var el = this[0];
if (!el) return new Dom7([]);
while (el.nextElementSibling) {
var next = el.nextElementSibling;
if (selector) {
if($(next).is(selector)) nextEls.push(next);
}
else nextEls.push(next);
el = next;
}
return new Dom7(nextEls);
},
prev: function (selector) {
if (this.length > 0) {
if (selector) {
if (this[0].previousElementSibling && $(this[0].previousElementSibling).is(selector)) return new Dom7([this[0].previousElementSibling]);
else return new Dom7([]);
}
else {
if (this[0].previousElementSibling) return new Dom7([this[0].previousElementSibling]);
else return new Dom7([]);
}
}
else return new Dom7([]);
},
prevAll: function (selector) {
var prevEls = [];
var el = this[0];
if (!el) return new Dom7([]);
while (el.previousElementSibling) {
var prev = el.previousElementSibling;
if (selector) {
if($(prev).is(selector)) prevEls.push(prev);
}
else prevEls.push(prev);
el = prev;
}
return new Dom7(prevEls);
},
siblings: function (selector) {
return this.nextAll(selector).add(this.prevAll(selector));
},
parent: function (selector) {
var parents = [];
for (var i = 0; i < this.length; i++) {
if (this[i].parentNode !== null) {
if (selector) {
if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode);
}
else {
parents.push(this[i].parentNode);
}
}
}
return $($.unique(parents));
},
parents: function (selector) {
var parents = [];
for (var i = 0; i < this.length; i++) {
var parent = this[i].parentNode;
while (parent) {
if (selector) {
if ($(parent).is(selector)) parents.push(parent);
}
else {
parents.push(parent);
}
parent = parent.parentNode;
}
}
return $($.unique(parents));
},
closest: function (selector) {
var closest = this;
if (typeof selector === 'undefined') {
return new Dom7([]);
}
if (!closest.is(selector)) {
closest = closest.parents(selector).eq(0);
}
return closest;
},
find : function (selector) {
var foundElements = [];
for (var i = 0; i < this.length; i++) {
var found = this[i].querySelectorAll(selector);
for (var j = 0; j < found.length; j++) {
foundElements.push(found[j]);
}
}
return new Dom7(foundElements);
},
children: function (selector) {
var children = [];
for (var i = 0; i < this.length; i++) {
var childNodes = this[i].childNodes;
for (var j = 0; j < childNodes.length; j++) {
if (!selector) {
if (childNodes[j].nodeType === 1) children.push(childNodes[j]);
}
else {
if (childNodes[j].nodeType === 1 && $(childNodes[j]).is(selector)) children.push(childNodes[j]);
}
}
}
return new Dom7($.unique(children));
},
remove: function () {
for (var i = 0; i < this.length; i++) {
if (this[i].parentNode) this[i].parentNode.removeChild(this[i]);
}
return this;
},
detach: function () {
return this.remove();
},
add: function () {
var dom = this;
var i, j;
for (i = 0; i < arguments.length; i++) {
var toAdd = $(arguments[i]);
for (j = 0; j < toAdd.length; j++) {
dom[dom.length] = toAdd[j];
dom.length++;
}
}
return dom;
},
empty: function () {
for (var i = 0; i < this.length; i++) {
var el = this[i];
if (el.nodeType === 1) {
for (var j = 0; j < el.childNodes.length; j++) {
if (el.childNodes[j].parentNode) el.childNodes[j].parentNode.removeChild(el.childNodes[j]);
}
el.textContent = '';
}
}
return this;
}
};
// Shortcuts
(function () {
var shortcuts = ('click blur focus focusin focusout keyup keydown keypress submit change mousedown mousemove mouseup mouseenter mouseleave mouseout mouseover touchstart touchend touchmove resize scroll').split(' ');
var notTrigger = ('resize scroll').split(' ');
function createMethod(name) {
Dom7.prototype[name] = function (targetSelector, listener, capture) {
var i;
if (typeof targetSelector === 'undefined') {
for (i = 0; i < this.length; i++) {
if (notTrigger.indexOf(name) < 0) {
if (name in this[i]) this[i][name]();
else {
$(this[i]).trigger(name);
}
}
}
return this;
}
else {
return this.on(name, targetSelector, listener, capture);
}
};
}
for (var i = 0; i < shortcuts.length; i++) {
createMethod(shortcuts[i]);
}
})();
// Global Ajax Setup
var globalAjaxOptions = {};
$.ajaxSetup = function (options) {
if (options.type) options.method = options.type;
$.each(options, function (optionName, optionValue) {
globalAjaxOptions[optionName] = optionValue;
});
};
// Ajax
var _jsonpRequests = 0;
$.ajax = function (options) {
var defaults = {
method: 'GET',
data: false,
async: true,
cache: true,
user: '',
password: '',
headers: {},
xhrFields: {},
statusCode: {},
processData: true,
dataType: 'text',
contentType: 'application/x-www-form-urlencoded',
timeout: 0
};
var callbacks = ['beforeSend', 'error', 'complete', 'success', 'statusCode'];
//For jQuery guys
if (options.type) options.method = options.type;
// Merge global and defaults
$.each(globalAjaxOptions, function (globalOptionName, globalOptionValue) {
if (callbacks.indexOf(globalOptionName) < 0) defaults[globalOptionName] = globalOptionValue;
});
// Function to run XHR callbacks and events
function fireAjaxCallback (eventName, eventData, callbackName) {
var a = arguments;
if (eventName) $(document).trigger(eventName, eventData);
if (callbackName) {
// Global callback
if (callbackName in globalAjaxOptions) globalAjaxOptions[callbackName](a[3], a[4], a[5], a[6]);
// Options callback
if (options[callbackName]) options[callbackName](a[3], a[4], a[5], a[6]);
}
}
// Merge options and defaults
$.each(defaults, function (prop, defaultValue) {
if (!(prop in options)) options[prop] = defaultValue;
});
// Default URL
if (!options.url) {
options.url = window.location.toString();
}
// Parameters Prefix
var paramsPrefix = options.url.indexOf('?') >= 0 ? '&' : '?';
// UC method
var _method = options.method.toUpperCase();
// Data to modify GET URL
if ((_method === 'GET' || _method === 'HEAD' || _method === 'OPTIONS' || _method === 'DELETE') && options.data) {
var stringData;
if (typeof options.data === 'string') {
// Should be key=value string
if (options.data.indexOf('?') >= 0) stringData = options.data.split('?')[1];
else stringData = options.data;
}
else {
// Should be key=value object
stringData = $.serializeObject(options.data);
}
if (stringData.length) {
options.url += paramsPrefix + stringData;
if (paramsPrefix === '?') paramsPrefix = '&';
}
}
// JSONP
if (options.dataType === 'json' && options.url.indexOf('callback=') >= 0) {
var callbackName = 'f7jsonp_' + Date.now() + (_jsonpRequests++);
var abortTimeout;
var callbackSplit = options.url.split('callback=');
var requestUrl = callbackSplit[0] + 'callback=' + callbackName;
if (callbackSplit[1].indexOf('&') >= 0) {
var addVars = callbackSplit[1].split('&').filter(function (el) { return el.indexOf('=') > 0; }).join('&');
if (addVars.length > 0) requestUrl += '&' + addVars;
}
// Create script
var script = document.createElement('script');
script.type = 'text/javascript';
script.onerror = function() {
clearTimeout(abortTimeout);
fireAjaxCallback(undefined, undefined, 'error', null, 'scripterror');
};
script.src = requestUrl;
// Handler
window[callbackName] = function (data) {
clearTimeout(abortTimeout);
fireAjaxCallback(undefined, undefined, 'success', data);
script.parentNode.removeChild(script);
script = null;
delete window[callbackName];
};
document.querySelector('head').appendChild(script);
if (options.timeout > 0) {
abortTimeout = setTimeout(function () {
script.parentNode.removeChild(script);
script = null;
fireAjaxCallback(undefined, undefined, 'error', null, 'timeout');
}, options.timeout);
}
return;
}
// Cache for GET/HEAD requests
if (_method === 'GET' || _method === 'HEAD' || _method === 'OPTIONS' || _method === 'DELETE') {
if (options.cache === false) {
options.url += (paramsPrefix + '_nocache=' + Date.now());
}
}
// Create XHR
var xhr = new XMLHttpRequest();
// Save Request URL
xhr.requestUrl = options.url;
xhr.requestParameters = options;
// Open XHR
xhr.open(_method, options.url, options.async, options.user, options.password);
// Create POST Data
var postData = null;
if ((_method === 'POST' || _method === 'PUT' || _method === 'PATCH') && options.data) {
if (options.processData) {
var postDataInstances = [ArrayBuffer, Blob, Document, FormData];
// Post Data
if (postDataInstances.indexOf(options.data.constructor) >= 0) {
postData = options.data;
}
else {
// POST Headers
var boundary = '---------------------------' + Date.now().toString(16);
if (options.contentType === 'multipart\/form-data') {
xhr.setRequestHeader('Content-Type', 'multipart\/form-data; boundary=' + boundary);
}
else {
xhr.setRequestHeader('Content-Type', options.contentType);
}
postData = '';
var _data = $.serializeObject(options.data);
if (options.contentType === 'multipart\/form-data') {
boundary = '---------------------------' + Date.now().toString(16);
_data = _data.split('&');
var _newData = [];
for (var i = 0; i < _data.length; i++) {
_newData.push('Content-Disposition: form-data; name="' + _data[i].split('=')[0] + '"\r\n\r\n' + _data[i].split('=')[1] + '\r\n');
}
postData = '--' + boundary + '\r\n' + _newData.join('--' + boundary + '\r\n') + '--' + boundary + '--\r\n';
}
else {
postData = options.contentType === 'application/x-www-form-urlencoded' ? _data : _data.replace(/&/g, '\r\n');
}
}
}
else {
postData = options.data;
}
}
// Additional headers
if (options.headers) {
$.each(options.headers, function (headerName, headerCallback) {
xhr.setRequestHeader(headerName, headerCallback);
});
}
// Check for crossDomain
if (typeof options.crossDomain === 'undefined') {
options.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(options.url) && RegExp.$2 !== window.location.host;
}
if (!options.crossDomain) {
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
}
if (options.xhrFields) {
$.each(options.xhrFields, function (fieldName, fieldValue) {
xhr[fieldName] = fieldValue;
});
}
var xhrTimeout;
// Handle XHR
xhr.onload = function (e) {
if (xhrTimeout) clearTimeout(xhrTimeout);
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0) {
var responseData;
if (options.dataType === 'json') {
try {
responseData = JSON.parse(xhr.responseText);
fireAjaxCallback('ajaxSuccess', {xhr: xhr}, 'success', responseData, xhr.status, xhr);
}
catch (err) {
fireAjaxCallback('ajaxError', {xhr: xhr, parseerror: true}, 'error', xhr, 'parseerror');
}
}
else {
responseData = xhr.responseType === 'text' || xhr.responseType === '' ? xhr.responseText : xhr.response;
fireAjaxCallback('ajaxSuccess', {xhr: xhr}, 'success', responseData, xhr.status, xhr);
}
}
else {
fireAjaxCallback('ajaxError', {xhr: xhr}, 'error', xhr, xhr.status);
}
if (options.statusCode) {
if (globalAjaxOptions.statusCode && globalAjaxOptions.statusCode[xhr.status]) globalAjaxOptions.statusCode[xhr.status](xhr);
if (options.statusCode[xhr.status]) options.statusCode[xhr.status](xhr);
}
fireAjaxCallback('ajaxComplete', {xhr: xhr}, 'complete', xhr, xhr.status);
};
xhr.onerror = function (e) {
if (xhrTimeout) clearTimeout(xhrTimeout);
fireAjaxCallback('ajaxError', {xhr: xhr}, 'error', xhr, xhr.status);
};
// Ajax start callback
fireAjaxCallback('ajaxStart', {xhr: xhr}, 'start', xhr);
fireAjaxCallback(undefined, undefined, 'beforeSend', xhr);
// Timeout
if (options.timeout > 0) {
xhr.onabort = function () {
if (xhrTimeout) clearTimeout(xhrTimeout);
};
xhrTimeout = setTimeout(function () {
xhr.abort();
fireAjaxCallback('ajaxError', {xhr: xhr, timeout: true}, 'error', xhr, 'timeout');
fireAjaxCallback('ajaxComplete', {xhr: xhr, timeout: true}, 'complete', xhr, 'timeout');
}, options.timeout);
}
// Send XHR
xhr.send(postData);
// Return XHR object
return xhr;
};
// Shrotcuts
(function () {
var methods = ('get post getJSON').split(' ');
function createMethod(method) {
$[method] = function (url, data, success, error) {
return $.ajax({
url: url,
method: method === 'post' ? 'POST' : 'GET',
data: typeof data === 'function' ? undefined : data,
success: typeof data === 'function' ? data : success,
error: typeof data === 'function' ? success : error,
dataType: method === 'getJSON' ? 'json' : undefined
});
};
}
for (var i = 0; i < methods.length; i++) {
createMethod(methods[i]);
}
})();
// DOM Library Utilites
$.parseUrlQuery = function (url) {
var url = url || location.href;
var query = {}, i, params, param;
if (typeof url === 'string' && url.length) {
url = (url.indexOf('#') > -1) ? url.split('#')[0] : url;
if (url.indexOf('?') > -1) url = url.split('?')[1];
else return query;
params = url.split('&');
for (i = 0; i < params.length; i ++) {
param = params[i].split('=');
query[param[0]] = param[1];
}
}
return query;
};
$.isArray = function (arr) {
if (Object.prototype.toString.apply(arr) === '[object Array]') return true;
else return false;
};
$.each = function (obj, callback) {
if (typeof obj !== 'object') return;
if (!callback) return;
var i, prop;
if ($.isArray(obj) || obj instanceof Dom7) {
// Array
for (i = 0; i < obj.length; i++) {
callback(i, obj[i]);
}
}
else {
// Object
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
callback(prop, obj[prop]);
}
}
}
};
$.unique = function (arr) {
var unique = [];
for (var i = 0; i < arr.length; i++) {
if (unique.indexOf(arr[i]) === -1) unique.push(arr[i]);
}
return unique;
};
$.serializeObject = $.param = function (obj, parents) {
if (typeof obj === 'string') return obj;
var resultArray = [];
var separator = '&';
parents = parents || [];
var newParents;
function var_name(name) {
if (parents.length > 0) {
var _parents = '';
for (var j = 0; j < parents.length; j++) {
if (j === 0) _parents += parents[j];
else _parents += '[' + encodeURIComponent(parents[j]) + ']';
}
return _parents + '[' + encodeURIComponent(name) + ']';
}
else {
return encodeURIComponent(name);
}
}
function var_value(value) {
return encodeURIComponent(value);
}
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
var toPush;
if ($.isArray(obj[prop])) {
toPush = [];
for (var i = 0; i < obj[prop].length; i ++) {
if (!$.isArray(obj[prop][i]) && typeof obj[prop][i] === 'object') {
newParents = parents.slice();
newParents.push(prop);
newParents.push(i + '');
toPush.push($.serializeObject(obj[prop][i], newParents));
}
else {
toPush.push(var_name(prop) + '[]=' + var_value(obj[prop][i]));
}
}
if (toPush.length > 0) resultArray.push(toPush.join(separator));
}
else if (obj[prop] === null) {
resultArray.push(var_name(prop) + '=');
}
else if (typeof obj[prop] === 'object') {
// Object, convert to named array
newParents = parents.slice();
newParents.push(prop);
toPush = $.serializeObject(obj[prop], newParents);
if (toPush !== '') resultArray.push(toPush);
}
else if (typeof obj[prop] !== 'undefined' && obj[prop] !== '') {
// Should be string or plain value
resultArray.push(var_name(prop) + '=' + var_value(obj[prop]));
}
}
}
return resultArray.join(separator);
};
$.toCamelCase = function (string) {
return string.toLowerCase().replace(/-(.)/g, function(match, group1) {
return group1.toUpperCase();
});
};
$.dataset = function (el) {
return $(el).dataset();
};
$.getTranslate = function (el, axis) {
var matrix, curTransform, curStyle, transformMatrix;
// automatic axis detection
if (typeof axis === 'undefined') {
axis = 'x';
}
curStyle = window.getComputedStyle(el, null);
if (window.WebKitCSSMatrix) {
curTransform = curStyle.transform || curStyle.webkitTransform;
if (curTransform.split(',').length > 6) {
curTransform = curTransform.split(', ').map(function(a){
return a.replace(',','.');
}).join(', ');
}
// Some old versions of Webkit choke when 'none' is passed; pass
// empty string instead in this case
transformMatrix = new WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
}
else {
transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
matrix = transformMatrix.toString().split(',');
}
if (axis === 'x') {
//Latest Chrome and webkits Fix
if (window.WebKitCSSMatrix)
curTransform = transformMatrix.m41;
//Crazy IE10 Matrix
else if (matrix.length === 16)
curTransform = parseFloat(matrix[12]);
//Normal Browsers
else
curTransform = parseFloat(matrix[4]);
}
if (axis === 'y') {
//Latest Chrome and webkits Fix
if (window.WebKitCSSMatrix)
curTransform = transformMatrix.m42;
//Crazy IE10 Matrix
else if (matrix.length === 16)
curTransform = parseFloat(matrix[13]);
//Normal Browsers
else
curTransform = parseFloat(matrix[5]);
}
return curTransform || 0;
};
$.requestAnimationFrame = function (callback) {
if (window.requestAnimationFrame) return window.requestAnimationFrame(callback);
else if (window.webkitRequestAnimationFrame) return window.webkitRequestAnimationFrame(callback);
else if (window.mozRequestAnimationFrame) return window.mozRequestAnimationFrame(callback);
else {
return window.setTimeout(callback, 1000 / 60);
}
};
$.cancelAnimationFrame = function (id) {
if (window.cancelAnimationFrame) return window.cancelAnimationFrame(id);
else if (window.webkitCancelAnimationFrame) return window.webkitCancelAnimationFrame(id);
else if (window.mozCancelAnimationFrame) return window.mozCancelAnimationFrame(id);
else {
return window.clearTimeout(id);
}
};
$.supportTouch = !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
// Remove Diacritics
var defaultDiacriticsRemovalap = [
{base:'A', letters:'\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'},
{base:'AA',letters:'\uA732'},
{base:'AE',letters:'\u00C6\u01FC\u01E2'},
{base:'AO',letters:'\uA734'},
{base:'AU',letters:'\uA736'},
{base:'AV',letters:'\uA738\uA73A'},
{base:'AY',letters:'\uA73C'},
{base:'B', letters:'\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'},
{base:'C', letters:'\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'},
{base:'D', letters:'\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779'},
{base:'DZ',letters:'\u01F1\u01C4'},
{base:'Dz',letters:'\u01F2\u01C5'},
{base:'E', letters:'\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'},
{base:'F', letters:'\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'},
{base:'G', letters:'\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'},
{base:'H', letters:'\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'},
{base:'I', letters:'\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'},
{base:'J', letters:'\u004A\u24BF\uFF2A\u0134\u0248'},
{base:'K', letters:'\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'},
{base:'L', letters:'\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'},
{base:'LJ',letters:'\u01C7'},
{base:'Lj',letters:'\u01C8'},
{base:'M', letters:'\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'},
{base:'N', letters:'\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'},
{base:'NJ',letters:'\u01CA'},
{base:'Nj',letters:'\u01CB'},
{base:'O', letters:'\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'},
{base:'OI',letters:'\u01A2'},
{base:'OO',letters:'\uA74E'},
{base:'OU',letters:'\u0222'},
{base:'OE',letters:'\u008C\u0152'},
{base:'oe',letters:'\u009C\u0153'},
{base:'P', letters:'\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'},
{base:'Q', letters:'\u0051\u24C6\uFF31\uA756\uA758\u024A'},
{base:'R', letters:'\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'},
{base:'S', letters:'\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'},
{base:'T', letters:'\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'},
{base:'TZ',letters:'\uA728'},
{base:'U', letters:'\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'},
{base:'V', letters:'\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'},
{base:'VY',letters:'\uA760'},
{base:'W', letters:'\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'},
{base:'X', letters:'\u0058\u24CD\uFF38\u1E8A\u1E8C'},
{base:'Y', letters:'\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'},
{base:'Z', letters:'\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'},
{base:'a', letters:'\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'},
{base:'aa',letters:'\uA733'},
{base:'ae',letters:'\u00E6\u01FD\u01E3'},
{base:'ao',letters:'\uA735'},
{base:'au',letters:'\uA737'},
{base:'av',letters:'\uA739\uA73B'},
{base:'ay',letters:'\uA73D'},
{base:'b', letters:'\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'},
{base:'c', letters:'\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'},
{base:'d', letters:'\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'},
{base:'dz',letters:'\u01F3\u01C6'},
{base:'e', letters:'\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'},
{base:'f', letters:'\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'},
{base:'g', letters:'\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'},
{base:'h', letters:'\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'},
{base:'hv',letters:'\u0195'},
{base:'i', letters:'\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'},
{base:'j', letters:'\u006A\u24D9\uFF4A\u0135\u01F0\u0249'},
{base:'k', letters:'\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'},
{base:'l', letters:'\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'},
{base:'lj',letters:'\u01C9'},
{base:'m', letters:'\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'},
{base:'n', letters:'\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'},
{base:'nj',letters:'\u01CC'},
{base:'o', letters:'\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'},
{base:'oi',letters:'\u01A3'},
{base:'ou',letters:'\u0223'},
{base:'oo',letters:'\uA74F'},
{base:'p',letters:'\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'},
{base:'q',letters:'\u0071\u24E0\uFF51\u024B\uA757\uA759'},
{base:'r',letters:'\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'},
{base:'s',letters:'\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'},
{base:'t',letters:'\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'},
{base:'tz',letters:'\uA729'},
{base:'u',letters: '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'},
{base:'v',letters:'\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'},
{base:'vy',letters:'\uA761'},
{base:'w',letters:'\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'},
{base:'x',letters:'\u0078\u24E7\uFF58\u1E8B\u1E8D'},
{base:'y',letters:'\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'},
{base:'z',letters:'\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'}
];
var diacriticsMap = {};
for (var i=0; i < defaultDiacriticsRemovalap.length; i++){
var letters = defaultDiacriticsRemovalap[i].letters;
for (var j=0; j < letters.length ; j++){
diacriticsMap[letters[j]] = defaultDiacriticsRemovalap[i].base;
}
}
$.removeDiacritics = function (str) {
return str.replace(/[^\u0000-\u007E]/g, function(a){
return diacriticsMap[a] || a;
});
};
// Link to prototype
$.fn = Dom7.prototype;
// Plugins
$.fn.scrollTo = function (left, top, duration, easing, callback) {
if (arguments.length === 4 && typeof easing === 'function') {
callback = easing;
easing = undefined;
}
return this.each(function () {
var el = this;
var currentTop, currentLeft, maxTop, maxLeft, newTop, newLeft, scrollTop, scrollLeft;
var animateTop = top > 0 || top === 0;
var animateLeft = left > 0 || left === 0;
if (typeof easing === 'undefined') {
easing = 'swing';
}
if (animateTop) {
currentTop = el.scrollTop;
if (!duration) {
el.scrollTop = top;
}
}
if (animateLeft) {
currentLeft = el.scrollLeft;
if (!duration) {
el.scrollLeft = left;
}
}
if (!duration) return;
if (animateTop) {
maxTop = el.scrollHeight - el.offsetHeight;
newTop = Math.max(Math.min(top, maxTop), 0);
}
if (animateLeft) {
maxLeft = el.scrollWidth - el.offsetWidth;
newLeft = Math.max(Math.min(left, maxLeft), 0);
}
var startTime = null;
if (animateTop && newTop === currentTop) animateTop = false;
if (animateLeft && newLeft === currentLeft) animateLeft = false;
function render(time) {
if (time === undefined) {
time = new Date().getTime();
}
if (startTime === null) {
startTime = time;
}
var doneLeft, doneTop, done;
var progress = Math.max(Math.min((time - startTime) / duration, 1), 0);
var easeProgress = easing === 'linear' ? progress : (0.5 - Math.cos( progress * Math.PI ) / 2);
if (animateTop) scrollTop = currentTop + (easeProgress * (newTop - currentTop));
if (animateLeft) scrollLeft = currentLeft + (easeProgress * (newLeft - currentLeft));
if (animateTop && newTop > currentTop && scrollTop >= newTop) {
el.scrollTop = newTop;
done = true;
}
if (animateTop && newTop < currentTop && scrollTop <= newTop) {
el.scrollTop = newTop;
done = true;
}
if (animateLeft && newLeft > currentLeft && scrollLeft >= newLeft) {
el.scrollLeft = newLeft;
done = true;
}
if (animateLeft && newLeft < currentLeft && scrollLeft <= newLeft) {
el.scrollLeft = newLeft;
done = true;
}
if (done) {
if (callback) callback();
return;
}
if (animateTop) el.scrollTop = scrollTop;
if (animateLeft) el.scrollLeft = scrollLeft;
$.requestAnimationFrame(render);
}
$.requestAnimationFrame(render);
});
};
$.fn.scrollTop = function (top, duration, easing, callback) {
if (arguments.length === 3 && typeof easing === 'function') {
callback = easing;
easing = undefined;
}
var dom = this;
if (typeof top === 'undefined') {
if (dom.length > 0) return dom[0].scrollTop;
else return null;
}
return dom.scrollTo(undefined, top, duration, easing, callback);
};
$.fn.scrollLeft = function (left, duration, easing, callback) {
if (arguments.length === 3 && typeof easing === 'function') {
callback = easing;
easing = undefined;
}
var dom = this;
if (typeof left === 'undefined') {
if (dom.length > 0) return dom[0].scrollLeft;
else return null;
}
return dom.scrollTo(left, undefined, duration, easing, callback);
};
return $;
})();
// Export Dom7 to Framework7
Framework7.$ = Dom7;
// Export to local scope
var $ = Dom7;
// Export to Window
window.Dom7 = Dom7;
/*========================
Animate7 Animate Engine
==========================*/
var Animate7 = function (elements, props, params) {
props = props || {};
params = params || {};
var defaults = {
duration: 300,
easing: 'swing', // or 'linear'
/* Callbacks
begin(elements)
complete(elements)
progress(elements, complete, remaining, start, tweenValue)
*/
};
for (var def in defaults) {
if (typeof params[def] === 'undefined') {
params[def] = defaults[def];
}
}
var a = this;
a.params = params;
a.props = props;
a.elements = $(elements);
if (a.elements.length === 0) {
return a;
}
a.easingProgress = function (easing, progress) {
if (easing === 'swing') {
return 0.5 - Math.cos( progress * Math.PI ) / 2;
}
if (typeof easing === 'function') {
return easing(progress);
}
return progress;
};
a.stop = function () {
if (a.frameId) {
$.cancelAnimationFrame(a.frameId);
}
a.animating = false;
a.elements.each(function (index, el) {
delete el.animate7Instance;
});
a.que = [];
};
a.done = function (complete) {
a.animating = false;
a.elements.each(function (index, el) {
delete el.animate7Instance;
});
if (complete) complete(elements);
if (a.que.length > 0) {
var que = a.que.shift();
a.animate(que[0], que[1]);
}
};
a.animating = false;
a.que = [];
a.animate = function (props, params) {
if (a.animating) {
a.que.push([props, params]);
return a;
}
a.params = params;
var _elements = [];
// Define & Cache Initials & Units
a.elements.each(function (index, el) {
var initialFullValue, initialValue, unit, finalValue, finalFullValue;
_elements[index] = {
_container: el
};
for (var prop in props) {
initialFullValue = window.getComputedStyle(el, null).getPropertyValue(prop).replace(',', '.');
initialValue = parseFloat(initialFullValue);
unit = initialFullValue.replace(initialValue, '');
finalValue = props[prop];
finalFullValue = props[prop] + unit;
_elements[index][prop] = {
initialFullValue: initialFullValue,
initialValue: initialValue,
unit: unit,
finalValue: finalValue,
finalFullValue: finalFullValue,
currentValue: initialValue
};
}
});
var startTime = null,
time,
elementsDone = 0,
propsDone = 0,
done,
began = false;
a.animating = true;
function render() {
time = new Date().getTime();
var progress, easeProgress, el;
if (!began) {
began = true;
if (params.begin) params.begin(elements);
}
if (startTime === null) {
startTime = time;
}
if (params.progress) {
params.progress(
a.elements,
Math.max(Math.min((time - startTime) / params.duration, 1), 0),
((startTime + params.duration) - time < 0 ? 0 : (startTime + params.duration) - time),
startTime
);
}
for (var i = 0; i < _elements.length; i++) {
if (done) continue;
el = _elements[i];
if (el.done) continue;
for (var prop in props) {
progress = Math.max(Math.min((time - startTime) / params.duration, 1), 0);
easeProgress = a.easingProgress(params.easing, progress);
el[prop].currentValue = el[prop].initialValue + easeProgress * (el[prop].finalValue - el[prop].initialValue);
if (el[prop].finalValue > el[prop].initialValue && el[prop].currentValue >= el[prop].finalValue || el[prop].finalValue < el[prop].initialValue && el[prop].currentValue <= el[prop].finalValue) {
el._container.style[prop] = el[prop].finalValue + el[prop].unit;
propsDone ++;
if (propsDone === Object.keys(props).length) {
el.done = true;
elementsDone++;
}
if (elementsDone === _elements.length) {
done = true;
}
}
if (done) {
a.done(params.complete);
return a;
}
el._container.style[prop] = el[prop].currentValue + el[prop].unit;
}
}
// Then call
a.frameId = $.requestAnimationFrame(render);
}
a.frameId = $.requestAnimationFrame(render);
return a;
};
var foundInstance;
for (var i = 0; i < a.elements.length; i++) {
if (a.elements[i].animate7Instance) {
foundInstance = a.elements[i].animate7Instance;
}
else a.elements[i].animate7Instance = a;
}
if (foundInstance) {
return foundInstance.animate(props, params);
}
else a.animate(props, params);
return a;
};
window.Animate7 = function (elements, props, params){
return new Animate7(elements, props, params);
};
Dom7.fn.animate = function (props, params) {
new Animate7(this, props, params);
return this;
};
/*===========================
Features Support Detection
===========================*/
Framework7.prototype.support = (function () {
var support = {
touch: !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch),
passiveListener: (function () {
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
}
});
window.addEventListener('testPassiveListener', null, opts);
} catch (e) {}
return supportsPassive;
})()
};
// Export object
return support;
})();
/*===========================
Device/OS Detection
===========================*/
Framework7.prototype.device = (function () {
var device = {};
var ua = navigator.userAgent;
var $ = Dom7;
var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
device.ios = device.android = device.iphone = device.ipad = device.androidChrome = false;
// Android
if (android) {
device.os = 'android';
device.osVersion = android[2];
device.android = true;
device.androidChrome = ua.toLowerCase().indexOf('chrome') >= 0;
}
if (ipad || iphone || ipod) {
device.os = 'ios';
device.ios = true;
}
// iOS
if (iphone && !ipod) {
device.osVersion = iphone[2].replace(/_/g, '.');
device.iphone = true;
}
if (ipad) {
device.osVersion = ipad[2].replace(/_/g, '.');
device.ipad = true;
}
if (ipod) {
device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
device.iphone = true;
}
// iOS 8+ changed UA
if (device.ios && device.osVersion && ua.indexOf('Version/') >= 0) {
if (device.osVersion.split('.')[0] === '10') {
device.osVersion = ua.toLowerCase().split('version/')[1].split(' ')[0];
}
}
// Webview
device.webView = (iphone || ipad || ipod) && ua.match(/.*AppleWebKit(?!.*Safari)/i);
// Minimal UI
if (device.os && device.os === 'ios') {
var osVersionArr = device.osVersion.split('.');
device.minimalUi = !device.webView &&
(ipod || iphone) &&
(osVersionArr[0] * 1 === 7 ? osVersionArr[1] * 1 >= 1 : osVersionArr[0] * 1 > 7) &&
$('meta[name="viewport"]').length > 0 && $('meta[name="viewport"]').attr('content').indexOf('minimal-ui') >= 0;
}
// Check for status bar and fullscreen app mode
var windowWidth = $(window).width();
var windowHeight = $(window).height();
device.statusBar = false;
if (device.webView && (windowWidth * windowHeight === screen.width * screen.height)) {
device.statusBar = true;
}
else {
device.statusBar = false;
}
// Classes
var classNames = [];
// Pixel Ratio
device.pixelRatio = window.devicePixelRatio || 1;
classNames.push('pixel-ratio-' + Math.floor(device.pixelRatio));
if (device.pixelRatio >= 2) {
classNames.push('retina');
}
// OS classes
if (device.os) {
classNames.push(device.os, device.os + '-' + device.osVersion.split('.')[0], device.os + '-' + device.osVersion.replace(/\./g, '-'));
if (device.os === 'ios') {
var major = parseInt(device.osVersion.split('.')[0], 10);
for (var i = major - 1; i >= 6; i--) {
classNames.push('ios-gt-' + i);
}
}
}
// Status bar classes
if (device.statusBar) {
classNames.push('with-statusbar-overlay');
}
else {
$('html').removeClass('with-statusbar-overlay');
}
// Add html classes
if (classNames.length > 0) $('html').addClass(classNames.join(' '));
// Export object
return device;
})();
/*===========================
Plugins prototype
===========================*/
Framework7.prototype.plugins = {};
/*===========================
Template7 Template engine
===========================*/
window.Template7 = (function () {
'use strict';
function isArray(arr) {
return Object.prototype.toString.apply(arr) === '[object Array]';
}
function isObject(obj) {
return obj instanceof Object;
}
function isFunction(func) {
return typeof func === 'function';
}
function _escape(string) {
return typeof window !== 'undefined' && window.escape ? window.escape(string) : string
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
var cache = {};
var quoteSingleRexExp = new RegExp('\'', 'g');
var quoteDoubleRexExp = new RegExp('"', 'g');
function helperToSlices(string) {
var helperParts = string.replace(/[{}#}]/g, '').split(' ');
var slices = [];
var shiftIndex, i, j;
for (i = 0; i < helperParts.length; i++) {
var part = helperParts[i];
var blockQuoteRegExp, openingQuote;
if (i === 0) slices.push(part);
else {
if (part.indexOf('"') === 0 || part.indexOf('\'') === 0) {
blockQuoteRegExp = part.indexOf('"') === 0 ? quoteDoubleRexExp : quoteSingleRexExp;
openingQuote = part.indexOf('"') === 0 ? '"' : '\'';
// Plain String
if (part.match(blockQuoteRegExp).length === 2) {
// One word string
slices.push(part);
}
else {
// Find closed Index
shiftIndex = 0;
for (j = i + 1; j < helperParts.length; j++) {
part += ' ' + helperParts[j];
if (helperParts[j].indexOf(openingQuote) >= 0) {
shiftIndex = j;
slices.push(part);
break;
}
}
if (shiftIndex) i = shiftIndex;
}
}
else {
if (part.indexOf('=') > 0) {
// Hash
var hashParts = part.split('=');
var hashName = hashParts[0];
var hashContent = hashParts[1];
if (hashContent.match(blockQuoteRegExp).length !== 2) {
shiftIndex = 0;
for (j = i + 1; j < helperParts.length; j++) {
hashContent += ' ' + helperParts[j];
if (helperParts[j].indexOf(openingQuote) >= 0) {
shiftIndex = j;
break;
}
}
if (shiftIndex) i = shiftIndex;
}
var hash = [hashName, hashContent.replace(blockQuoteRegExp,'')];
slices.push(hash);
}
else {
// Plain variable
slices.push(part);
}
}
}
}
return slices;
}
function stringToBlocks(string) {
var blocks = [], i, j, k;
if (!string) return [];
var _blocks = string.split(/({{[^{^}]*}})/);
for (i = 0; i < _blocks.length; i++) {
var block = _blocks[i];
if (block === '') continue;
if (block.indexOf('{{') < 0) {
blocks.push({
type: 'plain',
content: block
});
}
else {
if (block.indexOf('{/') >= 0) {
continue;
}
if (block.indexOf('{#') < 0 && block.indexOf(' ') < 0 && block.indexOf('else') < 0) {
// Simple variable
blocks.push({
type: 'variable',
contextName: block.replace(/[{}]/g, '')
});
continue;
}
// Helpers
var helperSlices = helperToSlices(block);
var helperName = helperSlices[0];
var isPartial = helperName === '>';
var helperContext = [];
var helperHash = {};
for (j = 1; j < helperSlices.length; j++) {
var slice = helperSlices[j];
if (isArray(slice)) {
// Hash
helperHash[slice[0]] = slice[1] === 'false' ? false : slice[1];
}
else {
helperContext.push(slice);
}
}
if (block.indexOf('{#') >= 0) {
// Condition/Helper
var helperStartIndex = i;
var helperContent = '';
var elseContent = '';
var toSkip = 0;
var shiftIndex;
var foundClosed = false, foundElse = false, foundClosedElse = false, depth = 0;
for (j = i + 1; j < _blocks.length; j++) {
if (_blocks[j].indexOf('{{#') >= 0) {
depth ++;
}
if (_blocks[j].indexOf('{{/') >= 0) {
depth --;
}
if (_blocks[j].indexOf('{{#' + helperName) >= 0) {
helperContent += _blocks[j];
if (foundElse) elseContent += _blocks[j];
toSkip ++;
}
else if (_blocks[j].indexOf('{{/' + helperName) >= 0) {
if (toSkip > 0) {
toSkip--;
helperContent += _blocks[j];
if (foundElse) elseContent += _blocks[j];
}
else {
shiftIndex = j;
foundClosed = true;
break;
}
}
else if (_blocks[j].indexOf('else') >= 0 && depth === 0) {
foundElse = true;
}
else {
if (!foundElse) helperContent += _blocks[j];
if (foundElse) elseContent += _blocks[j];
}
}
if (foundClosed) {
if (shiftIndex) i = shiftIndex;
blocks.push({
type: 'helper',
helperName: helperName,
contextName: helperContext,
content: helperContent,
inverseContent: elseContent,
hash: helperHash
});
}
}
else if (block.indexOf(' ') > 0) {
if (isPartial) {
helperName = '_partial';
if (helperContext[0]) helperContext[0] = '"' + helperContext[0].replace(/"|'/g, '') + '"';
}
blocks.push({
type: 'helper',
helperName: helperName,
contextName: helperContext,
hash: helperHash
});
}
}
}
return blocks;
}
var Template7 = function (template, options) {
var t = this;
t.template = template;
function getCompileFn(block, depth) {
if (block.content) return compile(block.content, depth);
else return function () {return ''; };
}
function getCompileInverse(block, depth) {
if (block.inverseContent) return compile(block.inverseContent, depth);
else return function () {return ''; };
}
function getCompileVar(name, ctx) {
var variable, parts, levelsUp = 0, initialCtx = ctx;
if (name.indexOf('../') === 0) {
levelsUp = name.split('../').length - 1;
var newDepth = ctx.split('_')[1] - levelsUp;
ctx = 'ctx_' + (newDepth >= 1 ? newDepth : 1);
parts = name.split('../')[levelsUp].split('.');
}
else if (name.indexOf('@global') === 0) {
ctx = 'Template7.global';
parts = name.split('@global.')[1].split('.');
}
else if (name.indexOf('@root') === 0) {
ctx = 'root';
parts = name.split('@root.')[1].split('.');
}
else {
parts = name.split('.');
}
variable = ctx;
for (var i = 0; i < parts.length; i++) {
var part = parts[i];
if (part.indexOf('@') === 0) {
if (i > 0) {
variable += '[(data && data.' + part.replace('@', '') + ')]';
}
else {
variable = '(data && data.' + name.replace('@', '') + ')';
}
}
else {
if (isFinite(part)) {
variable += '[' + part + ']';
}
else {
if (part === 'this' || part.indexOf('this.') >= 0 || part.indexOf('this[') >= 0 || part.indexOf('this(') >= 0) {
variable = part.replace('this', ctx);
}
else {
variable += '.' + part;
}
}
}
}
return variable;
}
function getCompiledArguments(contextArray, ctx) {
var arr = [];
for (var i = 0; i < contextArray.length; i++) {
if (/^['"]/.test(contextArray[i])) arr.push(contextArray[i]);
else if (/^(true|false|\d+)$/.test(contextArray[i])) arr.push(contextArray[i]);
else {
arr.push(getCompileVar(contextArray[i], ctx));
}
}
return arr.join(', ');
}
function compile(template, depth) {
depth = depth || 1;
template = template || t.template;
if (typeof template !== 'string') {
throw new Error('Template7: Template must be a string');
}
var blocks = stringToBlocks(template);
if (blocks.length === 0) {
return function () { return ''; };
}
var ctx = 'ctx_' + depth;
var resultString = '';
if (depth === 1) {
resultString += '(function (' + ctx + ', data, root) {\n';
}
else {
resultString += '(function (' + ctx + ', data) {\n';
}
if (depth === 1) {
resultString += 'function isArray(arr){return Object.prototype.toString.apply(arr) === \'[object Array]\';}\n';
resultString += 'function isFunction(func){return (typeof func === \'function\');}\n';
resultString += 'function c(val, ctx) {if (typeof val !== "undefined" && val !== null) {if (isFunction(val)) {return val.call(ctx);} else return val;} else return "";}\n';
resultString += 'root = root || ctx_1 || {};\n';
}
resultString += 'var r = \'\';\n';
var i, j, context;
for (i = 0; i < blocks.length; i++) {
var block = blocks[i];
// Plain block
if (block.type === 'plain') {
resultString += 'r +=\'' + (block.content).replace(/\r/g, '\\r').replace(/\n/g, '\\n').replace(/'/g, '\\' + '\'') + '\';';
continue;
}
var variable, compiledArguments;
// Variable block
if (block.type === 'variable') {
variable = getCompileVar(block.contextName, ctx);
resultString += 'r += c(' + variable + ', ' + ctx + ');';
}
// Helpers block
if (block.type === 'helper') {
if (block.helperName in t.helpers) {
compiledArguments = getCompiledArguments(block.contextName, ctx);
resultString += 'r += (Template7.helpers.' + block.helperName + ').call(' + ctx + ', ' + (compiledArguments && (compiledArguments + ', ')) +'{hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth + 1) + ', inverse: ' + getCompileInverse(block, depth + 1) + ', root: root});';
}
else {
if (block.contextName.length > 0) {
throw new Error('Template7: Missing helper: "' + block.helperName + '"');
}
else {
variable = getCompileVar(block.helperName, ctx);
resultString += 'if (' + variable + ') {';
resultString += 'if (isArray(' + variable + ')) {';
resultString += 'r += (Template7.helpers.each).call(' + ctx + ', ' + variable + ', {hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: root});';
resultString += '}else {';
resultString += 'r += (Template7.helpers.with).call(' + ctx + ', ' + variable + ', {hash:' + JSON.stringify(block.hash) + ', data: data || {}, fn: ' + getCompileFn(block, depth+1) + ', inverse: ' + getCompileInverse(block, depth+1) + ', root: root});';
resultString += '}}';
}
}
}
}
resultString += '\nreturn r;})';
return eval.call(window, resultString);
}
t.compile = function (template) {
if (!t.compiled) {
t.compiled = compile(template);
}
return t.compiled;
};
};
Template7.prototype = {
options: {},
partials: {},
helpers: {
'_partial' : function (partialName, options) {
var p = Template7.prototype.partials[partialName];
if (!p || (p && !p.template)) return '';
if (!p.compiled) {
p.compiled = new Template7(p.template).compile();
}
var ctx = this;
for (var hashName in options.hash) {
ctx[hashName] = options.hash[hashName];
}
return p.compiled(ctx, options.data, options.root);
},
'escape': function (context, options) {
if (typeof context !== 'string') {
throw new Error('Template7: Passed context to "escape" helper should be a string');
}
return _escape(context);
},
'if': function (context, options) {
if (isFunction(context)) { context = context.call(this); }
if (context) {
return options.fn(this, options.data);
}
else {
return options.inverse(this, options.data);
}
},
'unless': function (context, options) {
if (isFunction(context)) { context = context.call(this); }
if (!context) {
return options.fn(this, options.data);
}
else {
return options.inverse(this, options.data);
}
},
'each': function (context, options) {
var ret = '', i = 0;
if (isFunction(context)) { context = context.call(this); }
if (isArray(context)) {
if (options.hash.reverse) {
context = context.reverse();
}
for (i = 0; i < context.length; i++) {
ret += options.fn(context[i], {first: i === 0, last: i === context.length - 1, index: i});
}
if (options.hash.reverse) {
context = context.reverse();
}
}
else {
for (var key in context) {
i++;
ret += options.fn(context[key], {key: key});
}
}
if (i > 0) return ret;
else return options.inverse(this);
},
'with': function (context, options) {
if (isFunction(context)) { context = context.call(this); }
return options.fn(context);
},
'join': function (context, options) {
if (isFunction(context)) { context = context.call(this); }
return context.join(options.hash.delimiter || options.hash.delimeter);
},
'js': function (expression, options) {
var func;
if (expression.indexOf('return')>=0) {
func = '(function(){'+expression+'})';
}
else {
func = '(function(){return ('+expression+')})';
}
return eval.call(this, func).call(this);
},
'js_compare': function (expression, options) {
var func;
if (expression.indexOf('return')>=0) {
func = '(function(){'+expression+'})';
}
else {
func = '(function(){return ('+expression+')})';
}
var condition = eval.call(this, func).call(this);
if (condition) {
return options.fn(this, options.data);
}
else {
return options.inverse(this, options.data);
}
}
}
};
var t7 = function (template, data) {
if (arguments.length === 2) {
var instance = new Template7(template);
var rendered = instance.compile()(data);
instance = null;
return (rendered);
}
else return new Template7(template);
};
t7.registerHelper = function (name, fn) {
Template7.prototype.helpers[name] = fn;
};
t7.unregisterHelper = function (name) {
Template7.prototype.helpers[name] = undefined;
delete Template7.prototype.helpers[name];
};
t7.registerPartial = function (name, template) {
Template7.prototype.partials[name] = {template: template};
};
t7.unregisterPartial = function (name, template) {
if (Template7.prototype.partials[name]) {
Template7.prototype.partials[name] = undefined;
delete Template7.prototype.partials[name];
}
};
t7.compile = function (template, options) {
var instance = new Template7(template, options);
return instance.compile();
};
t7.options = Template7.prototype.options;
t7.helpers = Template7.prototype.helpers;
t7.partials = Template7.prototype.partials;
return t7;
})();
/*===========================
Swiper
===========================*/
window.Swiper = function (container, params) {
if (!(this instanceof Swiper)) return new Swiper(container, params);
var defaults = {
direction: 'horizontal',
touchEventsTarget: 'container',
initialSlide: 0,
speed: 300,
// autoplay
autoplay: false,
autoplayDisableOnInteraction: true,
autoplayStopOnLast: false,
// To support iOS's swipe-to-go-back gesture (when being used in-app, with UIWebView).
iOSEdgeSwipeDetection: false,
iOSEdgeSwipeThreshold: 20,
// Free mode
freeMode: false,
freeModeMomentum: true,
freeModeMomentumRatio: 1,
freeModeMomentumBounce: true,
freeModeMomentumBounceRatio: 1,
freeModeMomentumVelocityRatio: 1,
freeModeSticky: false,
freeModeMinimumVelocity: 0.02,
// Autoheight
autoHeight: false,
// Set wrapper width
setWrapperSize: false,
// Virtual Translate
virtualTranslate: false,
// Effects
effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow' or 'flip'
coverflow: {
rotate: 50,
stretch: 0,
depth: 100,
modifier: 1,
slideShadows : true
},
flip: {
slideShadows : true,
limitRotation: true
},
cube: {
slideShadows: true,
shadow: true,
shadowOffset: 20,
shadowScale: 0.94
},
fade: {
crossFade: false
},
// Parallax
parallax: false,
// Zoom
zoom: false,
zoomMax: 3,
zoomMin: 1,
zoomToggle: true,
// Scrollbar
scrollbar: null,
scrollbarHide: true,
scrollbarDraggable: false,
scrollbarSnapOnRelease: false,
// Keyboard Mousewheel
keyboardControl: false,
mousewheelControl: false,
mousewheelReleaseOnEdges: false,
mousewheelInvert: false,
mousewheelForceToAxis: false,
mousewheelSensitivity: 1,
mousewheelEventsTarged: 'container',
// Hash Navigation
hashnav: false,
hashnavWatchState: false,
// History
history: false,
// Commong Nav State
replaceState: false,
// Breakpoints
breakpoints: undefined,
// Slides grid
spaceBetween: 0,
slidesPerView: 1,
slidesPerColumn: 1,
slidesPerColumnFill: 'column',
slidesPerGroup: 1,
centeredSlides: false,
slidesOffsetBefore: 0, // in px
slidesOffsetAfter: 0, // in px
// Round length
roundLengths: false,
// Touches
touchRatio: 1,
touchAngle: 45,
simulateTouch: true,
shortSwipes: true,
longSwipes: true,
longSwipesRatio: 0.5,
longSwipesMs: 300,
followFinger: true,
onlyExternal: false,
threshold: 0,
touchMoveStopPropagation: true,
touchReleaseOnEdges: false,
// Unique Navigation Elements
uniqueNavElements: true,
// Pagination
pagination: null,
paginationElement: 'span',
paginationClickable: false,
paginationHide: false,
paginationBulletRender: null,
paginationProgressRender: null,
paginationFractionRender: null,
paginationCustomRender: null,
paginationType: 'bullets', // 'bullets' or 'progress' or 'fraction' or 'custom'
// Resistance
resistance: true,
resistanceRatio: 0.85,
// Next/prev buttons
nextButton: null,
prevButton: null,
// Progress
watchSlidesProgress: false,
watchSlidesVisibility: false,
// Cursor
grabCursor: false,
// Clicks
preventClicks: true,
preventClicksPropagation: true,
slideToClickedSlide: false,
// Lazy Loading
lazyLoading: false,
lazyLoadingInPrevNext: false,
lazyLoadingInPrevNextAmount: 1,
lazyLoadingOnTransitionStart: false,
// Images
preloadImages: true,
updateOnImagesReady: true,
// loop
loop: false,
loopAdditionalSlides: 0,
loopedSlides: null,
// Control
control: undefined,
controlInverse: false,
controlBy: 'slide', //or 'container'
normalizeSlideIndex: true,
// Swiping/no swiping
allowSwipeToPrev: true,
allowSwipeToNext: true,
swipeHandler: null, //'.swipe-handler',
noSwiping: true,
noSwipingClass: 'swiper-no-swiping',
// Passive Listeners
passiveListeners: true,
// NS
containerModifierClass: 'swiper-container-', // NEW
slideClass: 'swiper-slide',
slideActiveClass: 'swiper-slide-active',
slideDuplicateActiveClass: 'swiper-slide-duplicate-active',
slideVisibleClass: 'swiper-slide-visible',
slideDuplicateClass: 'swiper-slide-duplicate',
slideNextClass: 'swiper-slide-next',
slideDuplicateNextClass: 'swiper-slide-duplicate-next',
slidePrevClass: 'swiper-slide-prev',
slideDuplicatePrevClass: 'swiper-slide-duplicate-prev',
wrapperClass: 'swiper-wrapper',
bulletClass: 'swiper-pagination-bullet',
bulletActiveClass: 'swiper-pagination-bullet-active',
buttonDisabledClass: 'swiper-button-disabled',
paginationCurrentClass: 'swiper-pagination-current',
paginationTotalClass: 'swiper-pagination-total',
paginationHiddenClass: 'swiper-pagination-hidden',
paginationProgressbarClass: 'swiper-pagination-progressbar',
paginationClickableClass: 'swiper-pagination-clickable', // NEW
paginationModifierClass: 'swiper-pagination-', // NEW
lazyLoadingClass: 'swiper-lazy',
lazyStatusLoadingClass: 'swiper-lazy-loading',
lazyStatusLoadedClass: 'swiper-lazy-loaded',
lazyPreloaderClass: 'swiper-lazy-preloader',
notificationClass: 'swiper-notification',
preloaderClass: 'preloader',
zoomContainerClass: 'swiper-zoom-container',
// Observer
observer: false,
observeParents: false,
// Accessibility
a11y: false,
prevSlideMessage: 'Previous slide',
nextSlideMessage: 'Next slide',
firstSlideMessage: 'This is the first slide',
lastSlideMessage: 'This is the last slide',
paginationBulletMessage: 'Go to slide {{index}}',
// Callbacks
runCallbacksOnInit: true
/*
Callbacks:
onInit: function (swiper)
onDestroy: function (swiper)
onClick: function (swiper, e)
onTap: function (swiper, e)
onDoubleTap: function (swiper, e)
onSliderMove: function (swiper, e)
onSlideChangeStart: function (swiper)
onSlideChangeEnd: function (swiper)
onTransitionStart: function (swiper)
onTransitionEnd: function (swiper)
onImagesReady: function (swiper)
onProgress: function (swiper, progress)
onTouchStart: function (swiper, e)
onTouchMove: function (swiper, e)
onTouchMoveOpposite: function (swiper, e)
onTouchEnd: function (swiper, e)
onReachBeginning: function (swiper)
onReachEnd: function (swiper)
onSetTransition: function (swiper, duration)
onSetTranslate: function (swiper, translate)
onAutoplayStart: function (swiper)
onAutoplayStop: function (swiper),
onLazyImageLoad: function (swiper, slide, image)
onLazyImageReady: function (swiper, slide, image)
*/
};
var initialVirtualTranslate = params && params.virtualTranslate;
params = params || {};
var originalParams = {};
for (var param in params) {
if (typeof params[param] === 'object' && params[param] !== null && !(params[param].nodeType || params[param] === window || params[param] === document || (typeof Dom7 !== 'undefined' && params[param] instanceof Dom7) || (typeof jQuery !== 'undefined' && params[param] instanceof jQuery))) {
originalParams[param] = {};
for (var deepParam in params[param]) {
originalParams[param][deepParam] = params[param][deepParam];
}
}
else {
originalParams[param] = params[param];
}
}
for (var def in defaults) {
if (typeof params[def] === 'undefined') {
params[def] = defaults[def];
}
else if (typeof params[def] === 'object') {
for (var deepDef in defaults[def]) {
if (typeof params[def][deepDef] === 'undefined') {
params[def][deepDef] = defaults[def][deepDef];
}
}
}
}
// Swiper
var s = this;
// Params
s.params = params;
s.originalParams = originalParams;
// Classname
s.classNames = [];
/*=========================
Dom Library and plugins
===========================*/
if (typeof $ !== 'undefined' && typeof Dom7 !== 'undefined'){
$ = Dom7;
}
if (typeof $ === 'undefined') {
if (typeof Dom7 === 'undefined') {
$ = window.Dom7 || window.Zepto || window.jQuery;
}
else {
$ = Dom7;
}
if (!$) return;
}
// Export it to Swiper instance
s.$ = $;
/*=========================
Breakpoints
===========================*/
s.currentBreakpoint = undefined;
s.getActiveBreakpoint = function () {
//Get breakpoint for window width
if (!s.params.breakpoints) return false;
var breakpoint = false;
var points = [], point;
for ( point in s.params.breakpoints ) {
if (s.params.breakpoints.hasOwnProperty(point)) {
points.push(point);
}
}
points.sort(function (a, b) {
return parseInt(a, 10) > parseInt(b, 10);
});
for (var i = 0; i < points.length; i++) {
point = points[i];
if (point >= window.innerWidth && !breakpoint) {
breakpoint = point;
}
}
return breakpoint || 'max';
};
s.setBreakpoint = function () {
//Set breakpoint for window width and update parameters
var breakpoint = s.getActiveBreakpoint();
if (breakpoint && s.currentBreakpoint !== breakpoint) {
var breakPointsParams = breakpoint in s.params.breakpoints ? s.params.breakpoints[breakpoint] : s.originalParams;
var needsReLoop = s.params.loop && (breakPointsParams.slidesPerView !== s.params.slidesPerView);
for ( var param in breakPointsParams ) {
s.params[param] = breakPointsParams[param];
}
s.currentBreakpoint = breakpoint;
if(needsReLoop && s.destroyLoop) {
s.reLoop(true);
}
}
};
// Set breakpoint on load
if (s.params.breakpoints) {
s.setBreakpoint();
}
/*=========================
Preparation - Define Container, Wrapper and Pagination
===========================*/
s.container = $(container);
if (s.container.length === 0) return;
if (s.container.length > 1) {
var swipers = [];
s.container.each(function () {
var container = this;
swipers.push(new Swiper(this, params));
});
return swipers;
}
// Save instance in container HTML Element and in data
s.container[0].swiper = s;
s.container.data('swiper', s);
s.classNames.push(s.params.containerModifierClass + s.params.direction);
if (s.params.freeMode) {
s.classNames.push(s.params.containerModifierClass + 'free-mode');
}
if (!s.support.flexbox) {
s.classNames.push(s.params.containerModifierClass + 'no-flexbox');
s.params.slidesPerColumn = 1;
}
if (s.params.autoHeight) {
s.classNames.push(s.params.containerModifierClass + 'autoheight');
}
// Enable slides progress when required
if (s.params.parallax || s.params.watchSlidesVisibility) {
s.params.watchSlidesProgress = true;
}
// Max resistance when touchReleaseOnEdges
if (s.params.touchReleaseOnEdges) {
s.params.resistanceRatio = 0;
}
// Coverflow / 3D
if (['cube', 'coverflow', 'flip'].indexOf(s.params.effect) >= 0) {
if (s.support.transforms3d) {
s.params.watchSlidesProgress = true;
s.classNames.push(s.params.containerModifierClass + '3d');
}
else {
s.params.effect = 'slide';
}
}
if (s.params.effect !== 'slide') {
s.classNames.push(s.params.containerModifierClass + s.params.effect);
}
if (s.params.effect === 'cube') {
s.params.resistanceRatio = 0;
s.params.slidesPerView = 1;
s.params.slidesPerColumn = 1;
s.params.slidesPerGroup = 1;
s.params.centeredSlides = false;
s.params.spaceBetween = 0;
s.params.virtualTranslate = true;
s.params.setWrapperSize = false;
}
if (s.params.effect === 'fade' || s.params.effect === 'flip') {
s.params.slidesPerView = 1;
s.params.slidesPerColumn = 1;
s.params.slidesPerGroup = 1;
s.params.watchSlidesProgress = true;
s.params.spaceBetween = 0;
s.params.setWrapperSize = false;
if (typeof initialVirtualTranslate === 'undefined') {
s.params.virtualTranslate = true;
}
}
// Grab Cursor
if (s.params.grabCursor && s.support.touch) {
s.params.grabCursor = false;
}
// Wrapper
s.wrapper = s.container.children('.' + s.params.wrapperClass);
// Pagination
if (s.params.pagination) {
s.paginationContainer = $(s.params.pagination);
if (s.params.uniqueNavElements && typeof s.params.pagination === 'string' && s.paginationContainer.length > 1 && s.container.find(s.params.pagination).length === 1) {
s.paginationContainer = s.container.find(s.params.pagination);
}
if (s.params.paginationType === 'bullets' && s.params.paginationClickable) {
s.paginationContainer.addClass(s.params.paginationModifierClass + 'clickable');
}
else {
s.params.paginationClickable = false;
}
s.paginationContainer.addClass(s.params.paginationModifierClass + s.params.paginationType);
}
// Next/Prev Buttons
if (s.params.nextButton || s.params.prevButton) {
if (s.params.nextButton) {
s.nextButton = $(s.params.nextButton);
if (s.params.uniqueNavElements && typeof s.params.nextButton === 'string' && s.nextButton.length > 1 && s.container.find(s.params.nextButton).length === 1) {
s.nextButton = s.container.find(s.params.nextButton);
}
}
if (s.params.prevButton) {
s.prevButton = $(s.params.prevButton);
if (s.params.uniqueNavElements && typeof s.params.prevButton === 'string' && s.prevButton.length > 1 && s.container.find(s.params.prevButton).length === 1) {
s.prevButton = s.container.find(s.params.prevButton);
}
}
}
// Is Horizontal
s.isHorizontal = function () {
return s.params.direction === 'horizontal';
};
// s.isH = isH;
// RTL
s.rtl = s.isHorizontal() && (s.container[0].dir.toLowerCase() === 'rtl' || s.container.css('direction') === 'rtl');
if (s.rtl) {
s.classNames.push(s.params.containerModifierClass + 'rtl');
}
// Wrong RTL support
if (s.rtl) {
s.wrongRTL = s.wrapper.css('display') === '-webkit-box';
}
// Columns
if (s.params.slidesPerColumn > 1) {
s.classNames.push(s.params.containerModifierClass + 'multirow');
}
// Check for Android
if (s.device.android) {
s.classNames.push(s.params.containerModifierClass + 'android');
}
// Add classes
s.container.addClass(s.classNames.join(' '));
// Translate
s.translate = 0;
// Progress
s.progress = 0;
// Velocity
s.velocity = 0;
/*=========================
Locks, unlocks
===========================*/
s.lockSwipeToNext = function () {
s.params.allowSwipeToNext = false;
if (s.params.allowSwipeToPrev === false && s.params.grabCursor) {
s.unsetGrabCursor();
}
};
s.lockSwipeToPrev = function () {
s.params.allowSwipeToPrev = false;
if (s.params.allowSwipeToNext === false && s.params.grabCursor) {
s.unsetGrabCursor();
}
};
s.lockSwipes = function () {
s.params.allowSwipeToNext = s.params.allowSwipeToPrev = false;
if (s.params.grabCursor) s.unsetGrabCursor();
};
s.unlockSwipeToNext = function () {
s.params.allowSwipeToNext = true;
if (s.params.allowSwipeToPrev === true && s.params.grabCursor) {
s.setGrabCursor();
}
};
s.unlockSwipeToPrev = function () {
s.params.allowSwipeToPrev = true;
if (s.params.allowSwipeToNext === true && s.params.grabCursor) {
s.setGrabCursor();
}
};
s.unlockSwipes = function () {
s.params.allowSwipeToNext = s.params.allowSwipeToPrev = true;
if (s.params.grabCursor) s.setGrabCursor();
};
/*=========================
Round helper
===========================*/
function round(a) {
return Math.floor(a);
}
/*=========================
Set grab cursor
===========================*/
s.setGrabCursor = function(moving) {
s.container[0].style.cursor = 'move';
s.container[0].style.cursor = moving ? '-webkit-grabbing' : '-webkit-grab';
s.container[0].style.cursor = moving ? '-moz-grabbin' : '-moz-grab';
s.container[0].style.cursor = moving ? 'grabbing': 'grab';
};
s.unsetGrabCursor = function () {
s.container[0].style.cursor = '';
};
if (s.params.grabCursor) {
s.setGrabCursor();
}
/*=========================
Update on Images Ready
===========================*/
s.imagesToLoad = [];
s.imagesLoaded = 0;
s.loadImage = function (imgElement, src, srcset, sizes, checkForComplete, callback) {
var image;
function onReady () {
if (callback) callback();
}
if (!imgElement.complete || !checkForComplete) {
if (src) {
image = new window.Image();
image.onload = onReady;
image.onerror = onReady;
if (sizes) {
image.sizes = sizes;
}
if (srcset) {
image.srcset = srcset;
}
if (src) {
image.src = src;
}
} else {
onReady();
}
} else {//image already loaded...
onReady();
}
};
s.preloadImages = function () {
s.imagesToLoad = s.container.find('img');
function _onReady() {
if (typeof s === 'undefined' || s === null) return;
if (s.imagesLoaded !== undefined) s.imagesLoaded++;
if (s.imagesLoaded === s.imagesToLoad.length) {
if (s.params.updateOnImagesReady) s.update();
s.emit('onImagesReady', s);
}
}
for (var i = 0; i < s.imagesToLoad.length; i++) {
s.loadImage(s.imagesToLoad[i], (s.imagesToLoad[i].currentSrc || s.imagesToLoad[i].getAttribute('src')), (s.imagesToLoad[i].srcset || s.imagesToLoad[i].getAttribute('srcset')), s.imagesToLoad[i].sizes || s.imagesToLoad[i].getAttribute('sizes'), true, _onReady);
}
};
/*=========================
Autoplay
===========================*/
s.autoplayTimeoutId = undefined;
s.autoplaying = false;
s.autoplayPaused = false;
function autoplay() {
var autoplayDelay = s.params.autoplay;
var activeSlide = s.slides.eq(s.activeIndex);
if (activeSlide.attr('data-swiper-autoplay')) {
autoplayDelay = activeSlide.attr('data-swiper-autoplay') || s.params.autoplay;
}
s.autoplayTimeoutId = setTimeout(function () {
if (s.params.loop) {
s.fixLoop();
s._slideNext();
s.emit('onAutoplay', s);
}
else {
if (!s.isEnd) {
s._slideNext();
s.emit('onAutoplay', s);
}
else {
if (!params.autoplayStopOnLast) {
s._slideTo(0);
s.emit('onAutoplay', s);
}
else {
s.stopAutoplay();
}
}
}
}, autoplayDelay);
}
s.startAutoplay = function () {
if (typeof s.autoplayTimeoutId !== 'undefined') return false;
if (!s.params.autoplay) return false;
if (s.autoplaying) return false;
s.autoplaying = true;
s.emit('onAutoplayStart', s);
autoplay();
};
s.stopAutoplay = function (internal) {
if (!s.autoplayTimeoutId) return;
if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId);
s.autoplaying = false;
s.autoplayTimeoutId = undefined;
s.emit('onAutoplayStop', s);
};
s.pauseAutoplay = function (speed) {
if (s.autoplayPaused) return;
if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId);
s.autoplayPaused = true;
if (speed === 0) {
s.autoplayPaused = false;
autoplay();
}
else {
s.wrapper.transitionEnd(function () {
if (!s) return;
s.autoplayPaused = false;
if (!s.autoplaying) {
s.stopAutoplay();
}
else {
autoplay();
}
});
}
};
/*=========================
Min/Max Translate
===========================*/
s.minTranslate = function () {
return (-s.snapGrid[0]);
};
s.maxTranslate = function () {
return (-s.snapGrid[s.snapGrid.length - 1]);
};
/*=========================
Slider/slides sizes
===========================*/
s.updateAutoHeight = function () {
var activeSlides = [];
var newHeight = 0;
// Find slides currently in view
if(s.params.slidesPerView !== 'auto' && s.params.slidesPerView > 1) {
for (i = 0; i < Math.ceil(s.params.slidesPerView); i++) {
var index = s.activeIndex + i;
if(index > s.slides.length) break;
activeSlides.push(s.slides.eq(index)[0]);
}
} else {
activeSlides.push(s.slides.eq(s.activeIndex)[0]);
}
// Find new height from heighest slide in view
for (i = 0; i < activeSlides.length; i++) {
if (typeof activeSlides[i] !== 'undefined') {
var height = activeSlides[i].offsetHeight;
newHeight = height > newHeight ? height : newHeight;
}
}
// Update Height
if (newHeight) s.wrapper.css('height', newHeight + 'px');
};
s.updateContainerSize = function () {
var width, height;
if (typeof s.params.width !== 'undefined') {
width = s.params.width;
}
else {
width = s.container[0].clientWidth;
}
if (typeof s.params.height !== 'undefined') {
height = s.params.height;
}
else {
height = s.container[0].clientHeight;
}
if (width === 0 && s.isHorizontal() || height === 0 && !s.isHorizontal()) {
return;
}
//Subtract paddings
width = width - parseInt(s.container.css('padding-left'), 10) - parseInt(s.container.css('padding-right'), 10);
height = height - parseInt(s.container.css('padding-top'), 10) - parseInt(s.container.css('padding-bottom'), 10);
// Store values
s.width = width;
s.height = height;
s.size = s.isHorizontal() ? s.width : s.height;
};
s.updateSlidesSize = function () {
s.slides = s.wrapper.children('.' + s.params.slideClass);
s.snapGrid = [];
s.slidesGrid = [];
s.slidesSizesGrid = [];
var spaceBetween = s.params.spaceBetween,
slidePosition = -s.params.slidesOffsetBefore,
i,
prevSlideSize = 0,
index = 0;
if (typeof s.size === 'undefined') return;
if (typeof spaceBetween === 'string' && spaceBetween.indexOf('%') >= 0) {
spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * s.size;
}
s.virtualSize = -spaceBetween;
// reset margins
if (s.rtl) s.slides.css({marginLeft: '', marginTop: ''});
else s.slides.css({marginRight: '', marginBottom: ''});
var slidesNumberEvenToRows;
if (s.params.slidesPerColumn > 1) {
if (Math.floor(s.slides.length / s.params.slidesPerColumn) === s.slides.length / s.params.slidesPerColumn) {
slidesNumberEvenToRows = s.slides.length;
}
else {
slidesNumberEvenToRows = Math.ceil(s.slides.length / s.params.slidesPerColumn) * s.params.slidesPerColumn;
}
if (s.params.slidesPerView !== 'auto' && s.params.slidesPerColumnFill === 'row') {
slidesNumberEvenToRows = Math.max(slidesNumberEvenToRows, s.params.slidesPerView * s.params.slidesPerColumn);
}
}
// Calc slides
var slideSize;
var slidesPerColumn = s.params.slidesPerColumn;
var slidesPerRow = slidesNumberEvenToRows / slidesPerColumn;
var numFullColumns = slidesPerRow - (s.params.slidesPerColumn * slidesPerRow - s.slides.length);
for (i = 0; i < s.slides.length; i++) {
slideSize = 0;
var slide = s.slides.eq(i);
if (s.params.slidesPerColumn > 1) {
// Set slides order
var newSlideOrderIndex;
var column, row;
if (s.params.slidesPerColumnFill === 'column') {
column = Math.floor(i / slidesPerColumn);
row = i - column * slidesPerColumn;
if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn-1)) {
if (++row >= slidesPerColumn) {
row = 0;
column++;
}
}
newSlideOrderIndex = column + row * slidesNumberEvenToRows / slidesPerColumn;
slide
.css({
'-webkit-box-ordinal-group': newSlideOrderIndex,
'-moz-box-ordinal-group': newSlideOrderIndex,
'-ms-flex-order': newSlideOrderIndex,
'-webkit-order': newSlideOrderIndex,
'order': newSlideOrderIndex
});
}
else {
row = Math.floor(i / slidesPerRow);
column = i - row * slidesPerRow;
}
slide
.css(
'margin-' + (s.isHorizontal() ? 'top' : 'left'),
(row !== 0 && s.params.spaceBetween) && (s.params.spaceBetween + 'px')
)
.attr('data-swiper-column', column)
.attr('data-swiper-row', row);
}
if (slide.css('display') === 'none') continue;
if (s.params.slidesPerView === 'auto') {
slideSize = s.isHorizontal() ? slide.outerWidth(true) : slide.outerHeight(true);
if (s.params.roundLengths) slideSize = round(slideSize);
}
else {
slideSize = (s.size - (s.params.slidesPerView - 1) * spaceBetween) / s.params.slidesPerView;
if (s.params.roundLengths) slideSize = round(slideSize);
if (s.isHorizontal()) {
s.slides[i].style.width = slideSize + 'px';
}
else {
s.slides[i].style.height = slideSize + 'px';
}
}
s.slides[i].swiperSlideSize = slideSize;
s.slidesSizesGrid.push(slideSize);
if (s.params.centeredSlides) {
slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;
if (i === 0) slidePosition = slidePosition - s.size / 2 - spaceBetween;
if (Math.abs(slidePosition) < 1 / 1000) slidePosition = 0;
if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition);
s.slidesGrid.push(slidePosition);
}
else {
if ((index) % s.params.slidesPerGroup === 0) s.snapGrid.push(slidePosition);
s.slidesGrid.push(slidePosition);
slidePosition = slidePosition + slideSize + spaceBetween;
}
s.virtualSize += slideSize + spaceBetween;
prevSlideSize = slideSize;
index ++;
}
s.virtualSize = Math.max(s.virtualSize, s.size) + s.params.slidesOffsetAfter;
var newSlidesGrid;
if (
s.rtl && s.wrongRTL && (s.params.effect === 'slide' || s.params.effect === 'coverflow')) {
s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
}
if (!s.support.flexbox || s.params.setWrapperSize) {
if (s.isHorizontal()) s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
else s.wrapper.css({height: s.virtualSize + s.params.spaceBetween + 'px'});
}
if (s.params.slidesPerColumn > 1) {
s.virtualSize = (slideSize + s.params.spaceBetween) * slidesNumberEvenToRows;
s.virtualSize = Math.ceil(s.virtualSize / s.params.slidesPerColumn) - s.params.spaceBetween;
if (s.isHorizontal()) s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
else s.wrapper.css({height: s.virtualSize + s.params.spaceBetween + 'px'});
if (s.params.centeredSlides) {
newSlidesGrid = [];
for (i = 0; i < s.snapGrid.length; i++) {
if (s.snapGrid[i] < s.virtualSize + s.snapGrid[0]) newSlidesGrid.push(s.snapGrid[i]);
}
s.snapGrid = newSlidesGrid;
}
}
// Remove last grid elements depending on width
if (!s.params.centeredSlides) {
newSlidesGrid = [];
for (i = 0; i < s.snapGrid.length; i++) {
if (s.snapGrid[i] <= s.virtualSize - s.size) {
newSlidesGrid.push(s.snapGrid[i]);
}
}
s.snapGrid = newSlidesGrid;
if (Math.floor(s.virtualSize - s.size) - Math.floor(s.snapGrid[s.snapGrid.length - 1]) > 1) {
s.snapGrid.push(s.virtualSize - s.size);
}
}
if (s.snapGrid.length === 0) s.snapGrid = [0];
if (s.params.spaceBetween !== 0) {
if (s.isHorizontal()) {
if (s.rtl) s.slides.css({marginLeft: spaceBetween + 'px'});
else s.slides.css({marginRight: spaceBetween + 'px'});
}
else s.slides.css({marginBottom: spaceBetween + 'px'});
}
if (s.params.watchSlidesProgress) {
s.updateSlidesOffset();
}
};
s.updateSlidesOffset = function () {
for (var i = 0; i < s.slides.length; i++) {
s.slides[i].swiperSlideOffset = s.isHorizontal() ? s.slides[i].offsetLeft : s.slides[i].offsetTop;
}
};
/*=========================
Slider/slides progress
===========================*/
s.updateSlidesProgress = function (translate) {
if (typeof translate === 'undefined') {
translate = s.translate || 0;
}
if (s.slides.length === 0) return;
if (typeof s.slides[0].swiperSlideOffset === 'undefined') s.updateSlidesOffset();
var offsetCenter = -translate;
if (s.rtl) offsetCenter = translate;
// Visible Slides
s.slides.removeClass(s.params.slideVisibleClass);
for (var i = 0; i < s.slides.length; i++) {
var slide = s.slides[i];
var slideProgress = (offsetCenter + (s.params.centeredSlides ? s.minTranslate() : 0) - slide.swiperSlideOffset) / (slide.swiperSlideSize + s.params.spaceBetween);
if (s.params.watchSlidesVisibility) {
var slideBefore = -(offsetCenter - slide.swiperSlideOffset);
var slideAfter = slideBefore + s.slidesSizesGrid[i];
var isVisible =
(slideBefore >= 0 && slideBefore < s.size) ||
(slideAfter > 0 && slideAfter <= s.size) ||
(slideBefore <= 0 && slideAfter >= s.size);
if (isVisible) {
s.slides.eq(i).addClass(s.params.slideVisibleClass);
}
}
slide.progress = s.rtl ? -slideProgress : slideProgress;
}
};
s.updateProgress = function (translate) {
if (typeof translate === 'undefined') {
translate = s.translate || 0;
}
var translatesDiff = s.maxTranslate() - s.minTranslate();
var wasBeginning = s.isBeginning;
var wasEnd = s.isEnd;
if (translatesDiff === 0) {
s.progress = 0;
s.isBeginning = s.isEnd = true;
}
else {
s.progress = (translate - s.minTranslate()) / (translatesDiff);
s.isBeginning = s.progress <= 0;
s.isEnd = s.progress >= 1;
}
if (s.isBeginning && !wasBeginning) s.emit('onReachBeginning', s);
if (s.isEnd && !wasEnd) s.emit('onReachEnd', s);
if (s.params.watchSlidesProgress) s.updateSlidesProgress(translate);
s.emit('onProgress', s, s.progress);
};
s.updateActiveIndex = function () {
var translate = s.rtl ? s.translate : -s.translate;
var newActiveIndex, i, snapIndex;
for (i = 0; i < s.slidesGrid.length; i ++) {
if (typeof s.slidesGrid[i + 1] !== 'undefined') {
if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1] - (s.slidesGrid[i + 1] - s.slidesGrid[i]) / 2) {
newActiveIndex = i;
}
else if (translate >= s.slidesGrid[i] && translate < s.slidesGrid[i + 1]) {
newActiveIndex = i + 1;
}
}
else {
if (translate >= s.slidesGrid[i]) {
newActiveIndex = i;
}
}
}
// Normalize slideIndex
if(s.params.normalizeSlideIndex){
if (newActiveIndex < 0 || typeof newActiveIndex === 'undefined') newActiveIndex = 0;
}
// for (i = 0; i < s.slidesGrid.length; i++) {
// if (- translate >= s.slidesGrid[i]) {
// newActiveIndex = i;
// }
// }
snapIndex = Math.floor(newActiveIndex / s.params.slidesPerGroup);
if (snapIndex >= s.snapGrid.length) snapIndex = s.snapGrid.length - 1;
if (newActiveIndex === s.activeIndex) {
return;
}
s.snapIndex = snapIndex;
s.previousIndex = s.activeIndex;
s.activeIndex = newActiveIndex;
s.updateClasses();
s.updateRealIndex();
};
s.updateRealIndex = function(){
s.realIndex = s.slides.eq(s.activeIndex).attr('data-swiper-slide-index') || s.activeIndex;
};
/*=========================
Classes
===========================*/
s.updateClasses = function () {
s.slides.removeClass(s.params.slideActiveClass + ' ' + s.params.slideNextClass + ' ' + s.params.slidePrevClass + ' ' + s.params.slideDuplicateActiveClass + ' ' + s.params.slideDuplicateNextClass + ' ' + s.params.slideDuplicatePrevClass);
var activeSlide = s.slides.eq(s.activeIndex);
// Active classes
activeSlide.addClass(s.params.slideActiveClass);
if (params.loop) {
// Duplicate to all looped slides
if (activeSlide.hasClass(s.params.slideDuplicateClass)) {
s.wrapper.children('.' + s.params.slideClass + ':not(.' + s.params.slideDuplicateClass + ')[data-swiper-slide-index="' + s.realIndex + '"]').addClass(s.params.slideDuplicateActiveClass);
}
else {
s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + s.realIndex + '"]').addClass(s.params.slideDuplicateActiveClass);
}
}
// Next Slide
var nextSlide = activeSlide.next('.' + s.params.slideClass).addClass(s.params.slideNextClass);
if (s.params.loop && nextSlide.length === 0) {
nextSlide = s.slides.eq(0);
nextSlide.addClass(s.params.slideNextClass);
}
// Prev Slide
var prevSlide = activeSlide.prev('.' + s.params.slideClass).addClass(s.params.slidePrevClass);
if (s.params.loop && prevSlide.length === 0) {
prevSlide = s.slides.eq(-1);
prevSlide.addClass(s.params.slidePrevClass);
}
if (params.loop) {
// Duplicate to all looped slides
if (nextSlide.hasClass(s.params.slideDuplicateClass)) {
s.wrapper.children('.' + s.params.slideClass + ':not(.' + s.params.slideDuplicateClass + ')[data-swiper-slide-index="' + nextSlide.attr('data-swiper-slide-index') + '"]').addClass(s.params.slideDuplicateNextClass);
}
else {
s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + nextSlide.attr('data-swiper-slide-index') + '"]').addClass(s.params.slideDuplicateNextClass);
}
if (prevSlide.hasClass(s.params.slideDuplicateClass)) {
s.wrapper.children('.' + s.params.slideClass + ':not(.' + s.params.slideDuplicateClass + ')[data-swiper-slide-index="' + prevSlide.attr('data-swiper-slide-index') + '"]').addClass(s.params.slideDuplicatePrevClass);
}
else {
s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + prevSlide.attr('data-swiper-slide-index') + '"]').addClass(s.params.slideDuplicatePrevClass);
}
}
// Pagination
if (s.paginationContainer && s.paginationContainer.length > 0) {
// Current/Total
var current,
total = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length;
if (s.params.loop) {
current = Math.ceil((s.activeIndex - s.loopedSlides)/s.params.slidesPerGroup);
if (current > s.slides.length - 1 - s.loopedSlides * 2) {
current = current - (s.slides.length - s.loopedSlides * 2);
}
if (current > total - 1) current = current - total;
if (current < 0 && s.params.paginationType !== 'bullets') current = total + current;
}
else {
if (typeof s.snapIndex !== 'undefined') {
current = s.snapIndex;
}
else {
current = s.activeIndex || 0;
}
}
// Types
if (s.params.paginationType === 'bullets' && s.bullets && s.bullets.length > 0) {
s.bullets.removeClass(s.params.bulletActiveClass);
if (s.paginationContainer.length > 1) {
s.bullets.each(function () {
if ($(this).index() === current) $(this).addClass(s.params.bulletActiveClass);
});
}
else {
s.bullets.eq(current).addClass(s.params.bulletActiveClass);
}
}
if (s.params.paginationType === 'fraction') {
s.paginationContainer.find('.' + s.params.paginationCurrentClass).text(current + 1);
s.paginationContainer.find('.' + s.params.paginationTotalClass).text(total);
}
if (s.params.paginationType === 'progress') {
var scale = (current + 1) / total,
scaleX = scale,
scaleY = 1;
if (!s.isHorizontal()) {
scaleY = scale;
scaleX = 1;
}
s.paginationContainer.find('.' + s.params.paginationProgressbarClass).transform('translate3d(0,0,0) scaleX(' + scaleX + ') scaleY(' + scaleY + ')').transition(s.params.speed);
}
if (s.params.paginationType === 'custom' && s.params.paginationCustomRender) {
s.paginationContainer.html(s.params.paginationCustomRender(s, current + 1, total));
s.emit('onPaginationRendered', s, s.paginationContainer[0]);
}
}
// Next/active buttons
if (!s.params.loop) {
if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) {
if (s.isBeginning) {
s.prevButton.addClass(s.params.buttonDisabledClass);
if (s.params.a11y && s.a11y) s.a11y.disable(s.prevButton);
}
else {
s.prevButton.removeClass(s.params.buttonDisabledClass);
if (s.params.a11y && s.a11y) s.a11y.enable(s.prevButton);
}
}
if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) {
if (s.isEnd) {
s.nextButton.addClass(s.params.buttonDisabledClass);
if (s.params.a11y && s.a11y) s.a11y.disable(s.nextButton);
}
else {
s.nextButton.removeClass(s.params.buttonDisabledClass);
if (s.params.a11y && s.a11y) s.a11y.enable(s.nextButton);
}
}
}
};
/*=========================
Pagination
===========================*/
s.updatePagination = function () {
if (!s.params.pagination) return;
if (s.paginationContainer && s.paginationContainer.length > 0) {
var paginationHTML = '';
if (s.params.paginationType === 'bullets') {
var numberOfBullets = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length;
for (var i = 0; i < numberOfBullets; i++) {
if (s.params.paginationBulletRender) {
paginationHTML += s.params.paginationBulletRender(s, i, s.params.bulletClass);
}
else {
paginationHTML += '<' + s.params.paginationElement+' class="' + s.params.bulletClass + '"></' + s.params.paginationElement + '>';
}
}
s.paginationContainer.html(paginationHTML);
s.bullets = s.paginationContainer.find('.' + s.params.bulletClass);
if (s.params.paginationClickable && s.params.a11y && s.a11y) {
s.a11y.initPagination();
}
}
if (s.params.paginationType === 'fraction') {
if (s.params.paginationFractionRender) {
paginationHTML = s.params.paginationFractionRender(s, s.params.paginationCurrentClass, s.params.paginationTotalClass);
}
else {
paginationHTML =
'<span class="' + s.params.paginationCurrentClass + '"></span>' +
' / ' +
'<span class="' + s.params.paginationTotalClass+'"></span>';
}
s.paginationContainer.html(paginationHTML);
}
if (s.params.paginationType === 'progress') {
if (s.params.paginationProgressRender) {
paginationHTML = s.params.paginationProgressRender(s, s.params.paginationProgressbarClass);
}
else {
paginationHTML = '<span class="' + s.params.paginationProgressbarClass + '"></span>';
}
s.paginationContainer.html(paginationHTML);
}
if (s.params.paginationType !== 'custom') {
s.emit('onPaginationRendered', s, s.paginationContainer[0]);
}
}
};
/*=========================
Common update method
===========================*/
s.update = function (updateTranslate) {
s.updateContainerSize();
s.updateSlidesSize();
s.updateProgress();
s.updatePagination();
s.updateClasses();
if (s.params.scrollbar && s.scrollbar) {
s.scrollbar.set();
}
function forceSetTranslate() {
var translate = s.rtl ? -s.translate : s.translate;
newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate());
s.setWrapperTranslate(newTranslate);
s.updateActiveIndex();
s.updateClasses();
}
if (updateTranslate) {
var translated, newTranslate;
if (s.controller && s.controller.spline) {
s.controller.spline = undefined;
}
if (s.params.freeMode) {
forceSetTranslate();
if (s.params.autoHeight) {
s.updateAutoHeight();
}
}
else {
if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) {
translated = s.slideTo(s.slides.length - 1, 0, false, true);
}
else {
translated = s.slideTo(s.activeIndex, 0, false, true);
}
if (!translated) {
forceSetTranslate();
}
}
}
else if (s.params.autoHeight) {
s.updateAutoHeight();
}
};
/*=========================
Resize Handler
===========================*/
s.onResize = function (forceUpdatePagination) {
//Breakpoints
if (s.params.breakpoints) {
s.setBreakpoint();
}
// Disable locks on resize
var allowSwipeToPrev = s.params.allowSwipeToPrev;
var allowSwipeToNext = s.params.allowSwipeToNext;
s.params.allowSwipeToPrev = s.params.allowSwipeToNext = true;
s.updateContainerSize();
s.updateSlidesSize();
if (s.params.slidesPerView === 'auto' || s.params.freeMode || forceUpdatePagination) s.updatePagination();
if (s.params.scrollbar && s.scrollbar) {
s.scrollbar.set();
}
if (s.controller && s.controller.spline) {
s.controller.spline = undefined;
}
var slideChangedBySlideTo = false;
if (s.params.freeMode) {
var newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate());
s.setWrapperTranslate(newTranslate);
s.updateActiveIndex();
s.updateClasses();
if (s.params.autoHeight) {
s.updateAutoHeight();
}
}
else {
s.updateClasses();
if ((s.params.slidesPerView === 'auto' || s.params.slidesPerView > 1) && s.isEnd && !s.params.centeredSlides) {
slideChangedBySlideTo = s.slideTo(s.slides.length - 1, 0, false, true);
}
else {
slideChangedBySlideTo = s.slideTo(s.activeIndex, 0, false, true);
}
}
if (s.params.lazyLoading && !slideChangedBySlideTo && s.lazy) {
s.lazy.load();
}
// Return locks after resize
s.params.allowSwipeToPrev = allowSwipeToPrev;
s.params.allowSwipeToNext = allowSwipeToNext;
};
/*=========================
Events
===========================*/
//Define Touch Events
s.touchEventsDesktop = {start: 'mousedown', move: 'mousemove', end: 'mouseup'};
if (window.navigator.pointerEnabled) s.touchEventsDesktop = {start: 'pointerdown', move: 'pointermove', end: 'pointerup'};
else if (window.navigator.msPointerEnabled) s.touchEventsDesktop = {start: 'MSPointerDown', move: 'MSPointerMove', end: 'MSPointerUp'};
s.touchEvents = {
start : s.support.touch || !s.params.simulateTouch ? 'touchstart' : s.touchEventsDesktop.start,
move : s.support.touch || !s.params.simulateTouch ? 'touchmove' : s.touchEventsDesktop.move,
end : s.support.touch || !s.params.simulateTouch ? 'touchend' : s.touchEventsDesktop.end
};
// WP8 Touch Events Fix
if (window.navigator.pointerEnabled || window.navigator.msPointerEnabled) {
(s.params.touchEventsTarget === 'container' ? s.container : s.wrapper).addClass('swiper-wp8-' + s.params.direction);
}
// Attach/detach events
s.initEvents = function (detach) {
var actionDom = detach ? 'off' : 'on';
var action = detach ? 'removeEventListener' : 'addEventListener';
var touchEventsTarget = s.params.touchEventsTarget === 'container' ? s.container[0] : s.wrapper[0];
var target = s.support.touch ? touchEventsTarget : document;
var moveCapture = s.params.nested ? true : false;
//Touch Events
if (s.browser.ie) {
touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false);
target[action](s.touchEvents.move, s.onTouchMove, moveCapture);
target[action](s.touchEvents.end, s.onTouchEnd, false);
}
else {
if (s.support.touch) {
var passiveListener = s.touchEvents.start === 'touchstart' && s.support.passiveListener && s.params.passiveListeners ? {passive: true, capture: false} : false;
touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, passiveListener);
touchEventsTarget[action](s.touchEvents.move, s.onTouchMove, moveCapture);
touchEventsTarget[action](s.touchEvents.end, s.onTouchEnd, passiveListener);
}
if ((params.simulateTouch && !s.device.ios && !s.device.android) || (params.simulateTouch && !s.support.touch && s.device.ios)) {
touchEventsTarget[action]('mousedown', s.onTouchStart, false);
document[action]('mousemove', s.onTouchMove, moveCapture);
document[action]('mouseup', s.onTouchEnd, false);
}
}
window[action]('resize', s.onResize);
// Next, Prev, Index
if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) {
s.nextButton[actionDom]('click', s.onClickNext);
if (s.params.a11y && s.a11y) s.nextButton[actionDom]('keydown', s.a11y.onEnterKey);
}
if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) {
s.prevButton[actionDom]('click', s.onClickPrev);
if (s.params.a11y && s.a11y) s.prevButton[actionDom]('keydown', s.a11y.onEnterKey);
}
if (s.params.pagination && s.params.paginationClickable) {
s.paginationContainer[actionDom]('click', '.' + s.params.bulletClass, s.onClickIndex);
if (s.params.a11y && s.a11y) s.paginationContainer[actionDom]('keydown', '.' + s.params.bulletClass, s.a11y.onEnterKey);
}
// Prevent Links Clicks
if (s.params.preventClicks || s.params.preventClicksPropagation) touchEventsTarget[action]('click', s.preventClicks, true);
};
s.attachEvents = function () {
s.initEvents();
};
s.detachEvents = function () {
s.initEvents(true);
};
/*=========================
Handle Clicks
===========================*/
// Prevent Clicks
s.allowClick = true;
s.preventClicks = function (e) {
if (!s.allowClick) {
if (s.params.preventClicks) e.preventDefault();
if (s.params.preventClicksPropagation && s.animating) {
e.stopPropagation();
e.stopImmediatePropagation();
}
}
};
// Clicks
s.onClickNext = function (e) {
e.preventDefault();
if (s.isEnd && !s.params.loop) return;
s.slideNext();
};
s.onClickPrev = function (e) {
e.preventDefault();
if (s.isBeginning && !s.params.loop) return;
s.slidePrev();
};
s.onClickIndex = function (e) {
e.preventDefault();
var index = $(this).index() * s.params.slidesPerGroup;
if (s.params.loop) index = index + s.loopedSlides;
s.slideTo(index);
};
/*=========================
Handle Touches
===========================*/
function findElementInEvent(e, selector) {
var el = $(e.target);
if (!el.is(selector)) {
if (typeof selector === 'string') {
el = el.parents(selector);
}
else if (selector.nodeType) {
var found;
el.parents().each(function (index, _el) {
if (_el === selector) found = selector;
});
if (!found) return undefined;
else return selector;
}
}
if (el.length === 0) {
return undefined;
}
return el[0];
}
s.updateClickedSlide = function (e) {
var slide = findElementInEvent(e, '.' + s.params.slideClass);
var slideFound = false;
if (slide) {
for (var i = 0; i < s.slides.length; i++) {
if (s.slides[i] === slide) slideFound = true;
}
}
if (slide && slideFound) {
s.clickedSlide = slide;
s.clickedIndex = $(slide).index();
}
else {
s.clickedSlide = undefined;
s.clickedIndex = undefined;
return;
}
if (s.params.slideToClickedSlide && s.clickedIndex !== undefined && s.clickedIndex !== s.activeIndex) {
var slideToIndex = s.clickedIndex,
realIndex,
duplicatedSlides;
if (s.params.loop) {
if (s.animating) return;
realIndex = $(s.clickedSlide).attr('data-swiper-slide-index');
if (s.params.centeredSlides) {
if ((slideToIndex < s.loopedSlides - s.params.slidesPerView/2) || (slideToIndex > s.slides.length - s.loopedSlides + s.params.slidesPerView/2)) {
s.fixLoop();
slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.' + s.params.slideDuplicateClass + ')').eq(0).index();
setTimeout(function () {
s.slideTo(slideToIndex);
}, 0);
}
else {
s.slideTo(slideToIndex);
}
}
else {
if (slideToIndex > s.slides.length - s.params.slidesPerView) {
s.fixLoop();
slideToIndex = s.wrapper.children('.' + s.params.slideClass + '[data-swiper-slide-index="' + realIndex + '"]:not(.' + s.params.slideDuplicateClass + ')').eq(0).index();
setTimeout(function () {
s.slideTo(slideToIndex);
}, 0);
}
else {
s.slideTo(slideToIndex);
}
}
}
else {
s.slideTo(slideToIndex);
}
}
};
var isTouched,
isMoved,
allowTouchCallbacks,
touchStartTime,
isScrolling,
currentTranslate,
startTranslate,
allowThresholdMove,
// Form elements to match
formElements = 'input, select, textarea, button, video',
// Last click time
lastClickTime = Date.now(), clickTimeout,
//Velocities
velocities = [],
allowMomentumBounce;
// Animating Flag
s.animating = false;
// Touches information
s.touches = {
startX: 0,
startY: 0,
currentX: 0,
currentY: 0,
diff: 0
};
// Touch handlers
var isTouchEvent, startMoving;
s.onTouchStart = function (e) {
if (e.originalEvent) e = e.originalEvent;
isTouchEvent = e.type === 'touchstart';
if (!isTouchEvent && 'which' in e && e.which === 3) return;
if (s.params.noSwiping && findElementInEvent(e, '.' + s.params.noSwipingClass)) {
s.allowClick = true;
return;
}
if (s.params.swipeHandler) {
if (!findElementInEvent(e, s.params.swipeHandler)) return;
}
var startX = s.touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
var startY = s.touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
// Do NOT start if iOS edge swipe is detected. Otherwise iOS app (UIWebView) cannot swipe-to-go-back anymore
if(s.device.ios && s.params.iOSEdgeSwipeDetection && startX <= s.params.iOSEdgeSwipeThreshold) {
return;
}
isTouched = true;
isMoved = false;
allowTouchCallbacks = true;
isScrolling = undefined;
startMoving = undefined;
s.touches.startX = startX;
s.touches.startY = startY;
touchStartTime = Date.now();
s.allowClick = true;
s.updateContainerSize();
s.swipeDirection = undefined;
if (s.params.threshold > 0) allowThresholdMove = false;
if (e.type !== 'touchstart') {
var preventDefault = true;
if ($(e.target).is(formElements)) preventDefault = false;
if (document.activeElement && $(document.activeElement).is(formElements)) {
document.activeElement.blur();
}
if (preventDefault) {
e.preventDefault();
}
}
s.emit('onTouchStart', s, e);
};
s.onTouchMove = function (e) {
if (e.originalEvent) e = e.originalEvent;
if (isTouchEvent && e.type === 'mousemove') return;
if (e.preventedByNestedSwiper) {
s.touches.startX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
s.touches.startY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
return;
}
if (s.params.onlyExternal) {
// isMoved = true;
s.allowClick = false;
if (isTouched) {
s.touches.startX = s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
s.touches.startY = s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
touchStartTime = Date.now();
}
return;
}
if (isTouchEvent && s.params.touchReleaseOnEdges && !s.params.loop) {
if (!s.isHorizontal()) {
// Vertical
if (
(s.touches.currentY < s.touches.startY && s.translate <= s.maxTranslate()) ||
(s.touches.currentY > s.touches.startY && s.translate >= s.minTranslate())
) {
return;
}
}
else {
if (
(s.touches.currentX < s.touches.startX && s.translate <= s.maxTranslate()) ||
(s.touches.currentX > s.touches.startX && s.translate >= s.minTranslate())
) {
return;
}
}
}
if (isTouchEvent && document.activeElement) {
if (e.target === document.activeElement && $(e.target).is(formElements)) {
isMoved = true;
s.allowClick = false;
return;
}
}
if (allowTouchCallbacks) {
s.emit('onTouchMove', s, e);
}
if (e.targetTouches && e.targetTouches.length > 1) return;
s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
if (typeof isScrolling === 'undefined') {
var touchAngle;
if (s.isHorizontal() && s.touches.currentY === s.touches.startY || !s.isHorizontal() && s.touches.currentX !== s.touches.startX) {
isScrolling = false;
}
else {
touchAngle = Math.atan2(Math.abs(s.touches.currentY - s.touches.startY), Math.abs(s.touches.currentX - s.touches.startX)) * 180 / Math.PI;
isScrolling = s.isHorizontal() ? touchAngle > s.params.touchAngle : (90 - touchAngle > s.params.touchAngle);
}
}
if (isScrolling) {
s.emit('onTouchMoveOpposite', s, e);
}
if (typeof startMoving === 'undefined' && s.browser.ieTouch) {
if (s.touches.currentX !== s.touches.startX || s.touches.currentY !== s.touches.startY) {
startMoving = true;
}
}
if (!isTouched) return;
if (isScrolling) {
isTouched = false;
return;
}
if (!startMoving && s.browser.ieTouch) {
return;
}
s.allowClick = false;
s.emit('onSliderMove', s, e);
e.preventDefault();
if (s.params.touchMoveStopPropagation && !s.params.nested) {
e.stopPropagation();
}
if (!isMoved) {
if (params.loop) {
s.fixLoop();
}
startTranslate = s.getWrapperTranslate();
s.setWrapperTransition(0);
if (s.animating) {
s.wrapper.trigger('webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd');
}
if (s.params.autoplay && s.autoplaying) {
if (s.params.autoplayDisableOnInteraction) {
s.stopAutoplay();
}
else {
s.pauseAutoplay();
}
}
allowMomentumBounce = false;
//Grab Cursor
if (s.params.grabCursor && (s.params.allowSwipeToNext === true || s.params.allowSwipeToPrev === true)) {
s.setGrabCursor(true);
}
}
isMoved = true;
var diff = s.touches.diff = s.isHorizontal() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY;
diff = diff * s.params.touchRatio;
if (s.rtl) diff = -diff;
s.swipeDirection = diff > 0 ? 'prev' : 'next';
currentTranslate = diff + startTranslate;
var disableParentSwiper = true;
if ((diff > 0 && currentTranslate > s.minTranslate())) {
disableParentSwiper = false;
if (s.params.resistance) currentTranslate = s.minTranslate() - 1 + Math.pow(-s.minTranslate() + startTranslate + diff, s.params.resistanceRatio);
}
else if (diff < 0 && currentTranslate < s.maxTranslate()) {
disableParentSwiper = false;
if (s.params.resistance) currentTranslate = s.maxTranslate() + 1 - Math.pow(s.maxTranslate() - startTranslate - diff, s.params.resistanceRatio);
}
if (disableParentSwiper) {
e.preventedByNestedSwiper = true;
}
// Directions locks
if (!s.params.allowSwipeToNext && s.swipeDirection === 'next' && currentTranslate < startTranslate) {
currentTranslate = startTranslate;
}
if (!s.params.allowSwipeToPrev && s.swipeDirection === 'prev' && currentTranslate > startTranslate) {
currentTranslate = startTranslate;
}
// Threshold
if (s.params.threshold > 0) {
if (Math.abs(diff) > s.params.threshold || allowThresholdMove) {
if (!allowThresholdMove) {
allowThresholdMove = true;
s.touches.startX = s.touches.currentX;
s.touches.startY = s.touches.currentY;
currentTranslate = startTranslate;
s.touches.diff = s.isHorizontal() ? s.touches.currentX - s.touches.startX : s.touches.currentY - s.touches.startY;
return;
}
}
else {
currentTranslate = startTranslate;
return;
}
}
if (!s.params.followFinger) return;
// Update active index in free mode
if (s.params.freeMode || s.params.watchSlidesProgress) {
s.updateActiveIndex();
}
if (s.params.freeMode) {
//Velocity
if (velocities.length === 0) {
velocities.push({
position: s.touches[s.isHorizontal() ? 'startX' : 'startY'],
time: touchStartTime
});
}
velocities.push({
position: s.touches[s.isHorizontal() ? 'currentX' : 'currentY'],
time: (new window.Date()).getTime()
});
}
// Update progress
s.updateProgress(currentTranslate);
// Update translate
s.setWrapperTranslate(currentTranslate);
};
s.onTouchEnd = function (e) {
if (e.originalEvent) e = e.originalEvent;
if (allowTouchCallbacks) {
s.emit('onTouchEnd', s, e);
}
allowTouchCallbacks = false;
if (!isTouched) return;
//Return Grab Cursor
if (s.params.grabCursor && isMoved && isTouched && (s.params.allowSwipeToNext === true || s.params.allowSwipeToPrev === true)) {
s.setGrabCursor(false);
}
// Time diff
var touchEndTime = Date.now();
var timeDiff = touchEndTime - touchStartTime;
// Tap, doubleTap, Click
if (s.allowClick) {
s.updateClickedSlide(e);
s.emit('onTap', s, e);
if (timeDiff < 300 && (touchEndTime - lastClickTime) > 300) {
if (clickTimeout) clearTimeout(clickTimeout);
clickTimeout = setTimeout(function () {
if (!s) return;
if (s.params.paginationHide && s.paginationContainer.length > 0 && !$(e.target).hasClass(s.params.bulletClass)) {
s.paginationContainer.toggleClass(s.params.paginationHiddenClass);
}
s.emit('onClick', s, e);
}, 300);
}
if (timeDiff < 300 && (touchEndTime - lastClickTime) < 300) {
if (clickTimeout) clearTimeout(clickTimeout);
s.emit('onDoubleTap', s, e);
}
}
lastClickTime = Date.now();
setTimeout(function () {
if (s) s.allowClick = true;
}, 0);
if (!isTouched || !isMoved || !s.swipeDirection || s.touches.diff === 0 || currentTranslate === startTranslate) {
isTouched = isMoved = false;
return;
}
isTouched = isMoved = false;
var currentPos;
if (s.params.followFinger) {
currentPos = s.rtl ? s.translate : -s.translate;
}
else {
currentPos = -currentTranslate;
}
if (s.params.freeMode) {
if (currentPos < -s.minTranslate()) {
s.slideTo(s.activeIndex);
return;
}
else if (currentPos > -s.maxTranslate()) {
if (s.slides.length < s.snapGrid.length) {
s.slideTo(s.snapGrid.length - 1);
}
else {
s.slideTo(s.slides.length - 1);
}
return;
}
if (s.params.freeModeMomentum) {
if (velocities.length > 1) {
var lastMoveEvent = velocities.pop(), velocityEvent = velocities.pop();
var distance = lastMoveEvent.position - velocityEvent.position;
var time = lastMoveEvent.time - velocityEvent.time;
s.velocity = distance / time;
s.velocity = s.velocity / 2;
if (Math.abs(s.velocity) < s.params.freeModeMinimumVelocity) {
s.velocity = 0;
}
// this implies that the user stopped moving a finger then released.
// There would be no events with distance zero, so the last event is stale.
if (time > 150 || (new window.Date().getTime() - lastMoveEvent.time) > 300) {
s.velocity = 0;
}
} else {
s.velocity = 0;
}
s.velocity = s.velocity * s.params.freeModeMomentumVelocityRatio;
velocities.length = 0;
var momentumDuration = 1000 * s.params.freeModeMomentumRatio;
var momentumDistance = s.velocity * momentumDuration;
var newPosition = s.translate + momentumDistance;
if (s.rtl) newPosition = - newPosition;
var doBounce = false;
var afterBouncePosition;
var bounceAmount = Math.abs(s.velocity) * 20 * s.params.freeModeMomentumBounceRatio;
if (newPosition < s.maxTranslate()) {
if (s.params.freeModeMomentumBounce) {
if (newPosition + s.maxTranslate() < -bounceAmount) {
newPosition = s.maxTranslate() - bounceAmount;
}
afterBouncePosition = s.maxTranslate();
doBounce = true;
allowMomentumBounce = true;
}
else {
newPosition = s.maxTranslate();
}
}
else if (newPosition > s.minTranslate()) {
if (s.params.freeModeMomentumBounce) {
if (newPosition - s.minTranslate() > bounceAmount) {
newPosition = s.minTranslate() + bounceAmount;
}
afterBouncePosition = s.minTranslate();
doBounce = true;
allowMomentumBounce = true;
}
else {
newPosition = s.minTranslate();
}
}
else if (s.params.freeModeSticky) {
var j = 0,
nextSlide;
for (j = 0; j < s.snapGrid.length; j += 1) {
if (s.snapGrid[j] > -newPosition) {
nextSlide = j;
break;
}
}
if (Math.abs(s.snapGrid[nextSlide] - newPosition) < Math.abs(s.snapGrid[nextSlide - 1] - newPosition) || s.swipeDirection === 'next') {
newPosition = s.snapGrid[nextSlide];
} else {
newPosition = s.snapGrid[nextSlide - 1];
}
if (!s.rtl) newPosition = - newPosition;
}
//Fix duration
if (s.velocity !== 0) {
if (s.rtl) {
momentumDuration = Math.abs((-newPosition - s.translate) / s.velocity);
}
else {
momentumDuration = Math.abs((newPosition - s.translate) / s.velocity);
}
}
else if (s.params.freeModeSticky) {
s.slideReset();
return;
}
if (s.params.freeModeMomentumBounce && doBounce) {
s.updateProgress(afterBouncePosition);
s.setWrapperTransition(momentumDuration);
s.setWrapperTranslate(newPosition);
s.onTransitionStart();
s.animating = true;
s.wrapper.transitionEnd(function () {
if (!s || !allowMomentumBounce) return;
s.emit('onMomentumBounce', s);
s.setWrapperTransition(s.params.speed);
s.setWrapperTranslate(afterBouncePosition);
s.wrapper.transitionEnd(function () {
if (!s) return;
s.onTransitionEnd();
});
});
} else if (s.velocity) {
s.updateProgress(newPosition);
s.setWrapperTransition(momentumDuration);
s.setWrapperTranslate(newPosition);
s.onTransitionStart();
if (!s.animating) {
s.animating = true;
s.wrapper.transitionEnd(function () {
if (!s) return;
s.onTransitionEnd();
});
}
} else {
s.updateProgress(newPosition);
}
s.updateActiveIndex();
}
if (!s.params.freeModeMomentum || timeDiff >= s.params.longSwipesMs) {
s.updateProgress();
s.updateActiveIndex();
}
return;
}
// Find current slide
var i, stopIndex = 0, groupSize = s.slidesSizesGrid[0];
for (i = 0; i < s.slidesGrid.length; i += s.params.slidesPerGroup) {
if (typeof s.slidesGrid[i + s.params.slidesPerGroup] !== 'undefined') {
if (currentPos >= s.slidesGrid[i] && currentPos < s.slidesGrid[i + s.params.slidesPerGroup]) {
stopIndex = i;
groupSize = s.slidesGrid[i + s.params.slidesPerGroup] - s.slidesGrid[i];
}
}
else {
if (currentPos >= s.slidesGrid[i]) {
stopIndex = i;
groupSize = s.slidesGrid[s.slidesGrid.length - 1] - s.slidesGrid[s.slidesGrid.length - 2];
}
}
}
// Find current slide size
var ratio = (currentPos - s.slidesGrid[stopIndex]) / groupSize;
if (timeDiff > s.params.longSwipesMs) {
// Long touches
if (!s.params.longSwipes) {
s.slideTo(s.activeIndex);
return;
}
if (s.swipeDirection === 'next') {
if (ratio >= s.params.longSwipesRatio) s.slideTo(stopIndex + s.params.slidesPerGroup);
else s.slideTo(stopIndex);
}
if (s.swipeDirection === 'prev') {
if (ratio > (1 - s.params.longSwipesRatio)) s.slideTo(stopIndex + s.params.slidesPerGroup);
else s.slideTo(stopIndex);
}
}
else {
// Short swipes
if (!s.params.shortSwipes) {
s.slideTo(s.activeIndex);
return;
}
if (s.swipeDirection === 'next') {
s.slideTo(stopIndex + s.params.slidesPerGroup);
}
if (s.swipeDirection === 'prev') {
s.slideTo(stopIndex);
}
}
};
/*=========================
Transitions
===========================*/
s._slideTo = function (slideIndex, speed) {
return s.slideTo(slideIndex, speed, true, true);
};
s.slideTo = function (slideIndex, speed, runCallbacks, internal) {
if (typeof runCallbacks === 'undefined') runCallbacks = true;
if (typeof slideIndex === 'undefined') slideIndex = 0;
if (slideIndex < 0) slideIndex = 0;
s.snapIndex = Math.floor(slideIndex / s.params.slidesPerGroup);
if (s.snapIndex >= s.snapGrid.length) s.snapIndex = s.snapGrid.length - 1;
var translate = - s.snapGrid[s.snapIndex];
// Stop autoplay
if (s.params.autoplay && s.autoplaying) {
if (internal || !s.params.autoplayDisableOnInteraction) {
s.pauseAutoplay(speed);
}
else {
s.stopAutoplay();
}
}
// Update progress
s.updateProgress(translate);
// Normalize slideIndex
if(s.params.normalizeSlideIndex){
for (var i = 0; i < s.slidesGrid.length; i++) {
if (- Math.floor(translate * 100) >= Math.floor(s.slidesGrid[i] * 100)) {
slideIndex = i;
}
}
}
// Directions locks
if (!s.params.allowSwipeToNext && translate < s.translate && translate < s.minTranslate()) {
return false;
}
if (!s.params.allowSwipeToPrev && translate > s.translate && translate > s.maxTranslate()) {
if ((s.activeIndex || 0) !== slideIndex ) return false;
}
// Update Index
if (typeof speed === 'undefined') speed = s.params.speed;
s.previousIndex = s.activeIndex || 0;
s.activeIndex = slideIndex;
s.updateRealIndex();
if ((s.rtl && -translate === s.translate) || (!s.rtl && translate === s.translate)) {
// Update Height
if (s.params.autoHeight) {
s.updateAutoHeight();
}
s.updateClasses();
if (s.params.effect !== 'slide') {
s.setWrapperTranslate(translate);
}
return false;
}
s.updateClasses();
s.onTransitionStart(runCallbacks);
if (speed === 0 || s.browser.lteIE9) {
s.setWrapperTranslate(translate);
s.setWrapperTransition(0);
s.onTransitionEnd(runCallbacks);
}
else {
s.setWrapperTranslate(translate);
s.setWrapperTransition(speed);
if (!s.animating) {
s.animating = true;
s.wrapper.transitionEnd(function () {
if (!s) return;
s.onTransitionEnd(runCallbacks);
});
}
}
return true;
};
s.onTransitionStart = function (runCallbacks) {
if (typeof runCallbacks === 'undefined') runCallbacks = true;
if (s.params.autoHeight) {
s.updateAutoHeight();
}
if (s.lazy) s.lazy.onTransitionStart();
if (runCallbacks) {
s.emit('onTransitionStart', s);
if (s.activeIndex !== s.previousIndex) {
s.emit('onSlideChangeStart', s);
if (s.activeIndex > s.previousIndex) {
s.emit('onSlideNextStart', s);
}
else {
s.emit('onSlidePrevStart', s);
}
}
}
};
s.onTransitionEnd = function (runCallbacks) {
s.animating = false;
s.setWrapperTransition(0);
if (typeof runCallbacks === 'undefined') runCallbacks = true;
if (s.lazy) s.lazy.onTransitionEnd();
if (runCallbacks) {
s.emit('onTransitionEnd', s);
if (s.activeIndex !== s.previousIndex) {
s.emit('onSlideChangeEnd', s);
if (s.activeIndex > s.previousIndex) {
s.emit('onSlideNextEnd', s);
}
else {
s.emit('onSlidePrevEnd', s);
}
}
}
if (s.params.history && s.history) {
s.history.setHistory(s.params.history, s.activeIndex);
}
if (s.params.hashnav && s.hashnav) {
s.hashnav.setHash();
}
};
s.slideNext = function (runCallbacks, speed, internal) {
if (s.params.loop) {
if (s.animating) return false;
s.fixLoop();
var clientLeft = s.container[0].clientLeft;
return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal);
}
else return s.slideTo(s.activeIndex + s.params.slidesPerGroup, speed, runCallbacks, internal);
};
s._slideNext = function (speed) {
return s.slideNext(true, speed, true);
};
s.slidePrev = function (runCallbacks, speed, internal) {
if (s.params.loop) {
if (s.animating) return false;
s.fixLoop();
var clientLeft = s.container[0].clientLeft;
return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal);
}
else return s.slideTo(s.activeIndex - 1, speed, runCallbacks, internal);
};
s._slidePrev = function (speed) {
return s.slidePrev(true, speed, true);
};
s.slideReset = function (runCallbacks, speed, internal) {
return s.slideTo(s.activeIndex, speed, runCallbacks);
};
s.disableTouchControl = function () {
s.params.onlyExternal = true;
return true;
};
s.enableTouchControl = function () {
s.params.onlyExternal = false;
return true;
};
/*=========================
Translate/transition helpers
===========================*/
s.setWrapperTransition = function (duration, byController) {
s.wrapper.transition(duration);
if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
s.effects[s.params.effect].setTransition(duration);
}
if (s.params.parallax && s.parallax) {
s.parallax.setTransition(duration);
}
if (s.params.scrollbar && s.scrollbar) {
s.scrollbar.setTransition(duration);
}
if (s.params.control && s.controller) {
s.controller.setTransition(duration, byController);
}
s.emit('onSetTransition', s, duration);
};
s.setWrapperTranslate = function (translate, updateActiveIndex, byController) {
var x = 0, y = 0, z = 0;
if (s.isHorizontal()) {
x = s.rtl ? -translate : translate;
}
else {
y = translate;
}
if (s.params.roundLengths) {
x = round(x);
y = round(y);
}
if (!s.params.virtualTranslate) {
if (s.support.transforms3d) s.wrapper.transform('translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)');
else s.wrapper.transform('translate(' + x + 'px, ' + y + 'px)');
}
s.translate = s.isHorizontal() ? x : y;
// Check if we need to update progress
var progress;
var translatesDiff = s.maxTranslate() - s.minTranslate();
if (translatesDiff === 0) {
progress = 0;
}
else {
progress = (translate - s.minTranslate()) / (translatesDiff);
}
if (progress !== s.progress) {
s.updateProgress(translate);
}
if (updateActiveIndex) s.updateActiveIndex();
if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
s.effects[s.params.effect].setTranslate(s.translate);
}
if (s.params.parallax && s.parallax) {
s.parallax.setTranslate(s.translate);
}
if (s.params.scrollbar && s.scrollbar) {
s.scrollbar.setTranslate(s.translate);
}
if (s.params.control && s.controller) {
s.controller.setTranslate(s.translate, byController);
}
s.emit('onSetTranslate', s, s.translate);
};
s.getTranslate = function (el, axis) {
var matrix, curTransform, curStyle, transformMatrix;
// automatic axis detection
if (typeof axis === 'undefined') {
axis = 'x';
}
if (s.params.virtualTranslate) {
return s.rtl ? -s.translate : s.translate;
}
curStyle = window.getComputedStyle(el, null);
if (window.WebKitCSSMatrix) {
curTransform = curStyle.transform || curStyle.webkitTransform;
if (curTransform.split(',').length > 6) {
curTransform = curTransform.split(', ').map(function(a){
return a.replace(',','.');
}).join(', ');
}
// Some old versions of Webkit choke when 'none' is passed; pass
// empty string instead in this case
transformMatrix = new window.WebKitCSSMatrix(curTransform === 'none' ? '' : curTransform);
}
else {
transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,');
matrix = transformMatrix.toString().split(',');
}
if (axis === 'x') {
//Latest Chrome and webkits Fix
if (window.WebKitCSSMatrix)
curTransform = transformMatrix.m41;
//Crazy IE10 Matrix
else if (matrix.length === 16)
curTransform = parseFloat(matrix[12]);
//Normal Browsers
else
curTransform = parseFloat(matrix[4]);
}
if (axis === 'y') {
//Latest Chrome and webkits Fix
if (window.WebKitCSSMatrix)
curTransform = transformMatrix.m42;
//Crazy IE10 Matrix
else if (matrix.length === 16)
curTransform = parseFloat(matrix[13]);
//Normal Browsers
else
curTransform = parseFloat(matrix[5]);
}
if (s.rtl && curTransform) curTransform = -curTransform;
return curTransform || 0;
};
s.getWrapperTranslate = function (axis) {
if (typeof axis === 'undefined') {
axis = s.isHorizontal() ? 'x' : 'y';
}
return s.getTranslate(s.wrapper[0], axis);
};
/*=========================
Observer
===========================*/
s.observers = [];
function initObserver(target, options) {
options = options || {};
// create an observer instance
var ObserverFunc = window.MutationObserver || window.WebkitMutationObserver;
var observer = new ObserverFunc(function (mutations) {
mutations.forEach(function (mutation) {
s.onResize(true);
s.emit('onObserverUpdate', s, mutation);
});
});
observer.observe(target, {
attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
childList: typeof options.childList === 'undefined' ? true : options.childList,
characterData: typeof options.characterData === 'undefined' ? true : options.characterData
});
s.observers.push(observer);
}
s.initObservers = function () {
if (s.params.observeParents) {
var containerParents = s.container.parents();
for (var i = 0; i < containerParents.length; i++) {
initObserver(containerParents[i]);
}
}
// Observe container
initObserver(s.container[0], {childList: false});
// Observe wrapper
initObserver(s.wrapper[0], {attributes: false});
};
s.disconnectObservers = function () {
for (var i = 0; i < s.observers.length; i++) {
s.observers[i].disconnect();
}
s.observers = [];
};
/*=========================
Loop
===========================*/
// Create looped slides
s.createLoop = function () {
// Remove duplicated slides
s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove();
var slides = s.wrapper.children('.' + s.params.slideClass);
if(s.params.slidesPerView === 'auto' && !s.params.loopedSlides) s.params.loopedSlides = slides.length;
s.loopedSlides = parseInt(s.params.loopedSlides || s.params.slidesPerView, 10);
s.loopedSlides = s.loopedSlides + s.params.loopAdditionalSlides;
if (s.loopedSlides > slides.length) {
s.loopedSlides = slides.length;
}
var prependSlides = [], appendSlides = [], i;
slides.each(function (index, el) {
var slide = $(this);
if (index < s.loopedSlides) appendSlides.push(el);
if (index < slides.length && index >= slides.length - s.loopedSlides) prependSlides.push(el);
slide.attr('data-swiper-slide-index', index);
});
for (i = 0; i < appendSlides.length; i++) {
s.wrapper.append($(appendSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
}
for (i = prependSlides.length - 1; i >= 0; i--) {
s.wrapper.prepend($(prependSlides[i].cloneNode(true)).addClass(s.params.slideDuplicateClass));
}
};
s.destroyLoop = function () {
s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove();
s.slides.removeAttr('data-swiper-slide-index');
};
s.reLoop = function (updatePosition) {
var oldIndex = s.activeIndex - s.loopedSlides;
s.destroyLoop();
s.createLoop();
s.updateSlidesSize();
if (updatePosition) {
s.slideTo(oldIndex + s.loopedSlides, 0, false);
}
};
s.fixLoop = function () {
var newIndex;
//Fix For Negative Oversliding
if (s.activeIndex < s.loopedSlides) {
newIndex = s.slides.length - s.loopedSlides * 3 + s.activeIndex;
newIndex = newIndex + s.loopedSlides;
s.slideTo(newIndex, 0, false, true);
}
//Fix For Positive Oversliding
else if ((s.params.slidesPerView === 'auto' && s.activeIndex >= s.loopedSlides * 2) || (s.activeIndex > s.slides.length - s.params.slidesPerView * 2)) {
newIndex = -s.slides.length + s.activeIndex + s.loopedSlides;
newIndex = newIndex + s.loopedSlides;
s.slideTo(newIndex, 0, false, true);
}
};
/*=========================
Append/Prepend/Remove Slides
===========================*/
s.appendSlide = function (slides) {
if (s.params.loop) {
s.destroyLoop();
}
if (typeof slides === 'object' && slides.length) {
for (var i = 0; i < slides.length; i++) {
if (slides[i]) s.wrapper.append(slides[i]);
}
}
else {
s.wrapper.append(slides);
}
if (s.params.loop) {
s.createLoop();
}
if (!(s.params.observer && s.support.observer)) {
s.update(true);
}
};
s.prependSlide = function (slides) {
if (s.params.loop) {
s.destroyLoop();
}
var newActiveIndex = s.activeIndex + 1;
if (typeof slides === 'object' && slides.length) {
for (var i = 0; i < slides.length; i++) {
if (slides[i]) s.wrapper.prepend(slides[i]);
}
newActiveIndex = s.activeIndex + slides.length;
}
else {
s.wrapper.prepend(slides);
}
if (s.params.loop) {
s.createLoop();
}
if (!(s.params.observer && s.support.observer)) {
s.update(true);
}
s.slideTo(newActiveIndex, 0, false);
};
s.removeSlide = function (slidesIndexes) {
if (s.params.loop) {
s.destroyLoop();
s.slides = s.wrapper.children('.' + s.params.slideClass);
}
var newActiveIndex = s.activeIndex,
indexToRemove;
if (typeof slidesIndexes === 'object' && slidesIndexes.length) {
for (var i = 0; i < slidesIndexes.length; i++) {
indexToRemove = slidesIndexes[i];
if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove();
if (indexToRemove < newActiveIndex) newActiveIndex--;
}
newActiveIndex = Math.max(newActiveIndex, 0);
}
else {
indexToRemove = slidesIndexes;
if (s.slides[indexToRemove]) s.slides.eq(indexToRemove).remove();
if (indexToRemove < newActiveIndex) newActiveIndex--;
newActiveIndex = Math.max(newActiveIndex, 0);
}
if (s.params.loop) {
s.createLoop();
}
if (!(s.params.observer && s.support.observer)) {
s.update(true);
}
if (s.params.loop) {
s.slideTo(newActiveIndex + s.loopedSlides, 0, false);
}
else {
s.slideTo(newActiveIndex, 0, false);
}
};
s.removeAllSlides = function () {
var slidesIndexes = [];
for (var i = 0; i < s.slides.length; i++) {
slidesIndexes.push(i);
}
s.removeSlide(slidesIndexes);
};
/*=========================
Effects
===========================*/
s.effects = {
fade: {
setTranslate: function () {
for (var i = 0; i < s.slides.length; i++) {
var slide = s.slides.eq(i);
var offset = slide[0].swiperSlideOffset;
var tx = -offset;
if (!s.params.virtualTranslate) tx = tx - s.translate;
var ty = 0;
if (!s.isHorizontal()) {
ty = tx;
tx = 0;
}
var slideOpacity = s.params.fade.crossFade ?
Math.max(1 - Math.abs(slide[0].progress), 0) :
1 + Math.min(Math.max(slide[0].progress, -1), 0);
slide
.css({
opacity: slideOpacity
})
.transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px)');
}
},
setTransition: function (duration) {
s.slides.transition(duration);
if (s.params.virtualTranslate && duration !== 0) {
var eventTriggered = false;
s.slides.transitionEnd(function () {
if (eventTriggered) return;
if (!s) return;
eventTriggered = true;
s.animating = false;
var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'];
for (var i = 0; i < triggerEvents.length; i++) {
s.wrapper.trigger(triggerEvents[i]);
}
});
}
}
},
flip: {
setTranslate: function () {
for (var i = 0; i < s.slides.length; i++) {
var slide = s.slides.eq(i);
var progress = slide[0].progress;
if (s.params.flip.limitRotation) {
progress = Math.max(Math.min(slide[0].progress, 1), -1);
}
var offset = slide[0].swiperSlideOffset;
var rotate = -180 * progress,
rotateY = rotate,
rotateX = 0,
tx = -offset,
ty = 0;
if (!s.isHorizontal()) {
ty = tx;
tx = 0;
rotateX = -rotateY;
rotateY = 0;
}
else if (s.rtl) {
rotateY = -rotateY;
}
slide[0].style.zIndex = -Math.abs(Math.round(progress)) + s.slides.length;
if (s.params.flip.slideShadows) {
//Set shadows
var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top');
var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom');
if (shadowBefore.length === 0) {
shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>');
slide.append(shadowBefore);
}
if (shadowAfter.length === 0) {
shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>');
slide.append(shadowAfter);
}
if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
}
slide
.transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)');
}
},
setTransition: function (duration) {
s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
if (s.params.virtualTranslate && duration !== 0) {
var eventTriggered = false;
s.slides.eq(s.activeIndex).transitionEnd(function () {
if (eventTriggered) return;
if (!s) return;
if (!$(this).hasClass(s.params.slideActiveClass)) return;
eventTriggered = true;
s.animating = false;
var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'];
for (var i = 0; i < triggerEvents.length; i++) {
s.wrapper.trigger(triggerEvents[i]);
}
});
}
}
},
cube: {
setTranslate: function () {
var wrapperRotate = 0, cubeShadow;
if (s.params.cube.shadow) {
if (s.isHorizontal()) {
cubeShadow = s.wrapper.find('.swiper-cube-shadow');
if (cubeShadow.length === 0) {
cubeShadow = $('<div class="swiper-cube-shadow"></div>');
s.wrapper.append(cubeShadow);
}
cubeShadow.css({height: s.width + 'px'});
}
else {
cubeShadow = s.container.find('.swiper-cube-shadow');
if (cubeShadow.length === 0) {
cubeShadow = $('<div class="swiper-cube-shadow"></div>');
s.container.append(cubeShadow);
}
}
}
for (var i = 0; i < s.slides.length; i++) {
var slide = s.slides.eq(i);
var slideAngle = i * 90;
var round = Math.floor(slideAngle / 360);
if (s.rtl) {
slideAngle = -slideAngle;
round = Math.floor(-slideAngle / 360);
}
var progress = Math.max(Math.min(slide[0].progress, 1), -1);
var tx = 0, ty = 0, tz = 0;
if (i % 4 === 0) {
tx = - round * 4 * s.size;
tz = 0;
}
else if ((i - 1) % 4 === 0) {
tx = 0;
tz = - round * 4 * s.size;
}
else if ((i - 2) % 4 === 0) {
tx = s.size + round * 4 * s.size;
tz = s.size;
}
else if ((i - 3) % 4 === 0) {
tx = - s.size;
tz = 3 * s.size + s.size * 4 * round;
}
if (s.rtl) {
tx = -tx;
}
if (!s.isHorizontal()) {
ty = tx;
tx = 0;
}
var transform = 'rotateX(' + (s.isHorizontal() ? 0 : -slideAngle) + 'deg) rotateY(' + (s.isHorizontal() ? slideAngle : 0) + 'deg) translate3d(' + tx + 'px, ' + ty + 'px, ' + tz + 'px)';
if (progress <= 1 && progress > -1) {
wrapperRotate = i * 90 + progress * 90;
if (s.rtl) wrapperRotate = -i * 90 - progress * 90;
}
slide.transform(transform);
if (s.params.cube.slideShadows) {
//Set shadows
var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top');
var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom');
if (shadowBefore.length === 0) {
shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>');
slide.append(shadowBefore);
}
if (shadowAfter.length === 0) {
shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>');
slide.append(shadowAfter);
}
if (shadowBefore.length) shadowBefore[0].style.opacity = Math.max(-progress, 0);
if (shadowAfter.length) shadowAfter[0].style.opacity = Math.max(progress, 0);
}
}
s.wrapper.css({
'-webkit-transform-origin': '50% 50% -' + (s.size / 2) + 'px',
'-moz-transform-origin': '50% 50% -' + (s.size / 2) + 'px',
'-ms-transform-origin': '50% 50% -' + (s.size / 2) + 'px',
'transform-origin': '50% 50% -' + (s.size / 2) + 'px'
});
if (s.params.cube.shadow) {
if (s.isHorizontal()) {
cubeShadow.transform('translate3d(0px, ' + (s.width / 2 + s.params.cube.shadowOffset) + 'px, ' + (-s.width / 2) + 'px) rotateX(90deg) rotateZ(0deg) scale(' + (s.params.cube.shadowScale) + ')');
}
else {
var shadowAngle = Math.abs(wrapperRotate) - Math.floor(Math.abs(wrapperRotate) / 90) * 90;
var multiplier = 1.5 - (Math.sin(shadowAngle * 2 * Math.PI / 360) / 2 + Math.cos(shadowAngle * 2 * Math.PI / 360) / 2);
var scale1 = s.params.cube.shadowScale,
scale2 = s.params.cube.shadowScale / multiplier,
offset = s.params.cube.shadowOffset;
cubeShadow.transform('scale3d(' + scale1 + ', 1, ' + scale2 + ') translate3d(0px, ' + (s.height / 2 + offset) + 'px, ' + (-s.height / 2 / scale2) + 'px) rotateX(-90deg)');
}
}
var zFactor = (s.isSafari || s.isUiWebView) ? (-s.size / 2) : 0;
s.wrapper.transform('translate3d(0px,0,' + zFactor + 'px) rotateX(' + (s.isHorizontal() ? 0 : wrapperRotate) + 'deg) rotateY(' + (s.isHorizontal() ? -wrapperRotate : 0) + 'deg)');
},
setTransition: function (duration) {
s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
if (s.params.cube.shadow && !s.isHorizontal()) {
s.container.find('.swiper-cube-shadow').transition(duration);
}
}
},
coverflow: {
setTranslate: function () {
var transform = s.translate;
var center = s.isHorizontal() ? -transform + s.width / 2 : -transform + s.height / 2;
var rotate = s.isHorizontal() ? s.params.coverflow.rotate: -s.params.coverflow.rotate;
var translate = s.params.coverflow.depth;
//Each slide offset from center
for (var i = 0, length = s.slides.length; i < length; i++) {
var slide = s.slides.eq(i);
var slideSize = s.slidesSizesGrid[i];
var slideOffset = slide[0].swiperSlideOffset;
var offsetMultiplier = (center - slideOffset - slideSize / 2) / slideSize * s.params.coverflow.modifier;
var rotateY = s.isHorizontal() ? rotate * offsetMultiplier : 0;
var rotateX = s.isHorizontal() ? 0 : rotate * offsetMultiplier;
// var rotateZ = 0
var translateZ = -translate * Math.abs(offsetMultiplier);
var translateY = s.isHorizontal() ? 0 : s.params.coverflow.stretch * (offsetMultiplier);
var translateX = s.isHorizontal() ? s.params.coverflow.stretch * (offsetMultiplier) : 0;
//Fix for ultra small values
if (Math.abs(translateX) < 0.001) translateX = 0;
if (Math.abs(translateY) < 0.001) translateY = 0;
if (Math.abs(translateZ) < 0.001) translateZ = 0;
if (Math.abs(rotateY) < 0.001) rotateY = 0;
if (Math.abs(rotateX) < 0.001) rotateX = 0;
var slideTransform = 'translate3d(' + translateX + 'px,' + translateY + 'px,' + translateZ + 'px) rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)';
slide.transform(slideTransform);
slide[0].style.zIndex = -Math.abs(Math.round(offsetMultiplier)) + 1;
if (s.params.coverflow.slideShadows) {
//Set shadows
var shadowBefore = s.isHorizontal() ? slide.find('.swiper-slide-shadow-left') : slide.find('.swiper-slide-shadow-top');
var shadowAfter = s.isHorizontal() ? slide.find('.swiper-slide-shadow-right') : slide.find('.swiper-slide-shadow-bottom');
if (shadowBefore.length === 0) {
shadowBefore = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'left' : 'top') + '"></div>');
slide.append(shadowBefore);
}
if (shadowAfter.length === 0) {
shadowAfter = $('<div class="swiper-slide-shadow-' + (s.isHorizontal() ? 'right' : 'bottom') + '"></div>');
slide.append(shadowAfter);
}
if (shadowBefore.length) shadowBefore[0].style.opacity = offsetMultiplier > 0 ? offsetMultiplier : 0;
if (shadowAfter.length) shadowAfter[0].style.opacity = (-offsetMultiplier) > 0 ? -offsetMultiplier : 0;
}
}
//Set correct perspective for IE10
if (s.browser.ie) {
var ws = s.wrapper[0].style;
ws.perspectiveOrigin = center + 'px 50%';
}
},
setTransition: function (duration) {
s.slides.transition(duration).find('.swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left').transition(duration);
}
}
};
/*=========================
Images Lazy Loading
===========================*/
s.lazy = {
initialImageLoaded: false,
loadImageInSlide: function (index, loadInDuplicate) {
if (typeof index === 'undefined') return;
if (typeof loadInDuplicate === 'undefined') loadInDuplicate = true;
if (s.slides.length === 0) return;
var slide = s.slides.eq(index);
var img = slide.find('.' + s.params.lazyLoadingClass + ':not(.' + s.params.lazyStatusLoadedClass + '):not(.' + s.params.lazyStatusLoadingClass + ')');
if (slide.hasClass(s.params.lazyLoadingClass) && !slide.hasClass(s.params.lazyStatusLoadedClass) && !slide.hasClass(s.params.lazyStatusLoadingClass)) {
img = img.add(slide[0]);
}
if (img.length === 0) return;
img.each(function () {
var _img = $(this);
_img.addClass(s.params.lazyStatusLoadingClass);
var background = _img.attr('data-background');
var src = _img.attr('data-src'),
srcset = _img.attr('data-srcset'),
sizes = _img.attr('data-sizes');
s.loadImage(_img[0], (src || background), srcset, sizes, false, function () {
if (background) {
_img.css('background-image', 'url("' + background + '")');
_img.removeAttr('data-background');
}
else {
if (srcset) {
_img.attr('srcset', srcset);
_img.removeAttr('data-srcset');
}
if (sizes) {
_img.attr('sizes', sizes);
_img.removeAttr('data-sizes');
}
if (src) {
_img.attr('src', src);
_img.removeAttr('data-src');
}
}
_img.addClass(s.params.lazyStatusLoadedClass).removeClass(s.params.lazyStatusLoadingClass);
slide.find('.' + s.params.lazyPreloaderClass + ', .' + s.params.preloaderClass).remove();
if (s.params.loop && loadInDuplicate) {
var slideOriginalIndex = slide.attr('data-swiper-slide-index');
if (slide.hasClass(s.params.slideDuplicateClass)) {
var originalSlide = s.wrapper.children('[data-swiper-slide-index="' + slideOriginalIndex + '"]:not(.' + s.params.slideDuplicateClass + ')');
s.lazy.loadImageInSlide(originalSlide.index(), false);
}
else {
var duplicatedSlide = s.wrapper.children('.' + s.params.slideDuplicateClass + '[data-swiper-slide-index="' + slideOriginalIndex + '"]');
s.lazy.loadImageInSlide(duplicatedSlide.index(), false);
}
}
s.emit('onLazyImageReady', s, slide[0], _img[0]);
});
s.emit('onLazyImageLoad', s, slide[0], _img[0]);
});
},
load: function () {
var i;
var slidesPerView = s.params.slidesPerView;
if (slidesPerView === 'auto') {
slidesPerView = 0;
}
if (!s.lazy.initialImageLoaded) s.lazy.initialImageLoaded = true;
if (s.params.watchSlidesVisibility) {
s.wrapper.children('.' + s.params.slideVisibleClass).each(function () {
s.lazy.loadImageInSlide($(this).index());
});
}
else {
if (slidesPerView > 1) {
for (i = s.activeIndex; i < s.activeIndex + slidesPerView ; i++) {
if (s.slides[i]) s.lazy.loadImageInSlide(i);
}
}
else {
s.lazy.loadImageInSlide(s.activeIndex);
}
}
if (s.params.lazyLoadingInPrevNext) {
if (slidesPerView > 1 || (s.params.lazyLoadingInPrevNextAmount && s.params.lazyLoadingInPrevNextAmount > 1)) {
var amount = s.params.lazyLoadingInPrevNextAmount;
var spv = slidesPerView;
var maxIndex = Math.min(s.activeIndex + spv + Math.max(amount, spv), s.slides.length);
var minIndex = Math.max(s.activeIndex - Math.max(spv, amount), 0);
// Next Slides
for (i = s.activeIndex + slidesPerView; i < maxIndex; i++) {
if (s.slides[i]) s.lazy.loadImageInSlide(i);
}
// Prev Slides
for (i = minIndex; i < s.activeIndex ; i++) {
if (s.slides[i]) s.lazy.loadImageInSlide(i);
}
}
else {
var nextSlide = s.wrapper.children('.' + s.params.slideNextClass);
if (nextSlide.length > 0) s.lazy.loadImageInSlide(nextSlide.index());
var prevSlide = s.wrapper.children('.' + s.params.slidePrevClass);
if (prevSlide.length > 0) s.lazy.loadImageInSlide(prevSlide.index());
}
}
},
onTransitionStart: function () {
if (s.params.lazyLoading) {
if (s.params.lazyLoadingOnTransitionStart || (!s.params.lazyLoadingOnTransitionStart && !s.lazy.initialImageLoaded)) {
s.lazy.load();
}
}
},
onTransitionEnd: function () {
if (s.params.lazyLoading && !s.params.lazyLoadingOnTransitionStart) {
s.lazy.load();
}
}
};
/*=========================
Scrollbar
===========================*/
s.scrollbar = {
isTouched: false,
setDragPosition: function (e) {
var sb = s.scrollbar;
var x = 0, y = 0;
var translate;
var pointerPosition = s.isHorizontal() ?
((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageX : e.pageX || e.clientX) :
((e.type === 'touchstart' || e.type === 'touchmove') ? e.targetTouches[0].pageY : e.pageY || e.clientY) ;
var position = (pointerPosition) - sb.track.offset()[s.isHorizontal() ? 'left' : 'top'] - sb.dragSize / 2;
var positionMin = -s.minTranslate() * sb.moveDivider;
var positionMax = -s.maxTranslate() * sb.moveDivider;
if (position < positionMin) {
position = positionMin;
}
else if (position > positionMax) {
position = positionMax;
}
position = -position / sb.moveDivider;
s.updateProgress(position);
s.setWrapperTranslate(position, true);
},
dragStart: function (e) {
var sb = s.scrollbar;
sb.isTouched = true;
e.preventDefault();
e.stopPropagation();
sb.setDragPosition(e);
clearTimeout(sb.dragTimeout);
sb.track.transition(0);
if (s.params.scrollbarHide) {
sb.track.css('opacity', 1);
}
s.wrapper.transition(100);
sb.drag.transition(100);
s.emit('onScrollbarDragStart', s);
},
dragMove: function (e) {
var sb = s.scrollbar;
if (!sb.isTouched) return;
if (e.preventDefault) e.preventDefault();
else e.returnValue = false;
sb.setDragPosition(e);
s.wrapper.transition(0);
sb.track.transition(0);
sb.drag.transition(0);
s.emit('onScrollbarDragMove', s);
},
dragEnd: function (e) {
var sb = s.scrollbar;
if (!sb.isTouched) return;
sb.isTouched = false;
if (s.params.scrollbarHide) {
clearTimeout(sb.dragTimeout);
sb.dragTimeout = setTimeout(function () {
sb.track.css('opacity', 0);
sb.track.transition(400);
}, 1000);
}
s.emit('onScrollbarDragEnd', s);
if (s.params.scrollbarSnapOnRelease) {
s.slideReset();
}
},
draggableEvents: (function () {
if ((s.params.simulateTouch === false && !s.support.touch)) return s.touchEventsDesktop;
else return s.touchEvents;
})(),
enableDraggable: function () {
var sb = s.scrollbar;
var target = s.support.touch ? sb.track : document;
$(sb.track).on(sb.draggableEvents.start, sb.dragStart);
$(target).on(sb.draggableEvents.move, sb.dragMove);
$(target).on(sb.draggableEvents.end, sb.dragEnd);
},
disableDraggable: function () {
var sb = s.scrollbar;
var target = s.support.touch ? sb.track : document;
$(sb.track).off(s.draggableEvents.start, sb.dragStart);
$(target).off(s.draggableEvents.move, sb.dragMove);
$(target).off(s.draggableEvents.end, sb.dragEnd);
},
set: function () {
if (!s.params.scrollbar) return;
var sb = s.scrollbar;
sb.track = $(s.params.scrollbar);
if (s.params.uniqueNavElements && typeof s.params.scrollbar === 'string' && sb.track.length > 1 && s.container.find(s.params.scrollbar).length === 1) {
sb.track = s.container.find(s.params.scrollbar);
}
sb.drag = sb.track.find('.swiper-scrollbar-drag');
if (sb.drag.length === 0) {
sb.drag = $('<div class="swiper-scrollbar-drag"></div>');
sb.track.append(sb.drag);
}
sb.drag[0].style.width = '';
sb.drag[0].style.height = '';
sb.trackSize = s.isHorizontal() ? sb.track[0].offsetWidth : sb.track[0].offsetHeight;
sb.divider = s.size / s.virtualSize;
sb.moveDivider = sb.divider * (sb.trackSize / s.size);
sb.dragSize = sb.trackSize * sb.divider;
if (s.isHorizontal()) {
sb.drag[0].style.width = sb.dragSize + 'px';
}
else {
sb.drag[0].style.height = sb.dragSize + 'px';
}
if (sb.divider >= 1) {
sb.track[0].style.display = 'none';
}
else {
sb.track[0].style.display = '';
}
if (s.params.scrollbarHide) {
sb.track[0].style.opacity = 0;
}
},
setTranslate: function () {
if (!s.params.scrollbar) return;
var diff;
var sb = s.scrollbar;
var translate = s.translate || 0;
var newPos;
var newSize = sb.dragSize;
newPos = (sb.trackSize - sb.dragSize) * s.progress;
if (s.rtl && s.isHorizontal()) {
newPos = -newPos;
if (newPos > 0) {
newSize = sb.dragSize - newPos;
newPos = 0;
}
else if (-newPos + sb.dragSize > sb.trackSize) {
newSize = sb.trackSize + newPos;
}
}
else {
if (newPos < 0) {
newSize = sb.dragSize + newPos;
newPos = 0;
}
else if (newPos + sb.dragSize > sb.trackSize) {
newSize = sb.trackSize - newPos;
}
}
if (s.isHorizontal()) {
if (s.support.transforms3d) {
sb.drag.transform('translate3d(' + (newPos) + 'px, 0, 0)');
}
else {
sb.drag.transform('translateX(' + (newPos) + 'px)');
}
sb.drag[0].style.width = newSize + 'px';
}
else {
if (s.support.transforms3d) {
sb.drag.transform('translate3d(0px, ' + (newPos) + 'px, 0)');
}
else {
sb.drag.transform('translateY(' + (newPos) + 'px)');
}
sb.drag[0].style.height = newSize + 'px';
}
if (s.params.scrollbarHide) {
clearTimeout(sb.timeout);
sb.track[0].style.opacity = 1;
sb.timeout = setTimeout(function () {
sb.track[0].style.opacity = 0;
sb.track.transition(400);
}, 1000);
}
},
setTransition: function (duration) {
if (!s.params.scrollbar) return;
s.scrollbar.drag.transition(duration);
}
};
/*=========================
Controller
===========================*/
s.controller = {
LinearSpline: function (x, y) {
this.x = x;
this.y = y;
this.lastIndex = x.length - 1;
// Given an x value (x2), return the expected y2 value:
// (x1,y1) is the known point before given value,
// (x3,y3) is the known point after given value.
var i1, i3;
var l = this.x.length;
this.interpolate = function (x2) {
if (!x2) return 0;
// Get the indexes of x1 and x3 (the array indexes before and after given x2):
i3 = binarySearch(this.x, x2);
i1 = i3 - 1;
// We have our indexes i1 & i3, so we can calculate already:
// y2 := ((x2x1) × (y3y1)) ÷ (x3x1) + y1
return ((x2 - this.x[i1]) * (this.y[i3] - this.y[i1])) / (this.x[i3] - this.x[i1]) + this.y[i1];
};
var binarySearch = (function() {
var maxIndex, minIndex, guess;
return function(array, val) {
minIndex = -1;
maxIndex = array.length;
while (maxIndex - minIndex > 1)
if (array[guess = maxIndex + minIndex >> 1] <= val) {
minIndex = guess;
} else {
maxIndex = guess;
}
return maxIndex;
};
})();
},
//xxx: for now i will just save one spline function to to
getInterpolateFunction: function(c){
if(!s.controller.spline) s.controller.spline = s.params.loop ?
new s.controller.LinearSpline(s.slidesGrid, c.slidesGrid) :
new s.controller.LinearSpline(s.snapGrid, c.snapGrid);
},
setTranslate: function (translate, byController) {
var controlled = s.params.control;
var multiplier, controlledTranslate;
function setControlledTranslate(c) {
// this will create an Interpolate function based on the snapGrids
// x is the Grid of the scrolled scroller and y will be the controlled scroller
// it makes sense to create this only once and recall it for the interpolation
// the function does a lot of value caching for performance
translate = c.rtl && c.params.direction === 'horizontal' ? -s.translate : s.translate;
if (s.params.controlBy === 'slide') {
s.controller.getInterpolateFunction(c);
// i am not sure why the values have to be multiplicated this way, tried to invert the snapGrid
// but it did not work out
controlledTranslate = -s.controller.spline.interpolate(-translate);
}
if(!controlledTranslate || s.params.controlBy === 'container'){
multiplier = (c.maxTranslate() - c.minTranslate()) / (s.maxTranslate() - s.minTranslate());
controlledTranslate = (translate - s.minTranslate()) * multiplier + c.minTranslate();
}
if (s.params.controlInverse) {
controlledTranslate = c.maxTranslate() - controlledTranslate;
}
c.updateProgress(controlledTranslate);
c.setWrapperTranslate(controlledTranslate, false, s);
c.updateActiveIndex();
}
if (s.isArray(controlled)) {
for (var i = 0; i < controlled.length; i++) {
if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
setControlledTranslate(controlled[i]);
}
}
}
else if (controlled instanceof Swiper && byController !== controlled) {
setControlledTranslate(controlled);
}
},
setTransition: function (duration, byController) {
var controlled = s.params.control;
var i;
function setControlledTransition(c) {
c.setWrapperTransition(duration, s);
if (duration !== 0) {
c.onTransitionStart();
c.wrapper.transitionEnd(function(){
if (!controlled) return;
if (c.params.loop && s.params.controlBy === 'slide') {
c.fixLoop();
}
c.onTransitionEnd();
});
}
}
if (s.isArray(controlled)) {
for (i = 0; i < controlled.length; i++) {
if (controlled[i] !== byController && controlled[i] instanceof Swiper) {
setControlledTransition(controlled[i]);
}
}
}
else if (controlled instanceof Swiper && byController !== controlled) {
setControlledTransition(controlled);
}
}
};
/*=========================
Parallax
===========================*/
function setParallaxTransform(el, progress) {
el = $(el);
var p, pX, pY;
var rtlFactor = s.rtl ? -1 : 1;
p = el.attr('data-swiper-parallax') || '0';
pX = el.attr('data-swiper-parallax-x');
pY = el.attr('data-swiper-parallax-y');
if (pX || pY) {
pX = pX || '0';
pY = pY || '0';
}
else {
if (s.isHorizontal()) {
pX = p;
pY = '0';
}
else {
pY = p;
pX = '0';
}
}
if ((pX).indexOf('%') >= 0) {
pX = parseInt(pX, 10) * progress * rtlFactor + '%';
}
else {
pX = pX * progress * rtlFactor + 'px' ;
}
if ((pY).indexOf('%') >= 0) {
pY = parseInt(pY, 10) * progress + '%';
}
else {
pY = pY * progress + 'px' ;
}
el.transform('translate3d(' + pX + ', ' + pY + ',0px)');
}
s.parallax = {
setTranslate: function () {
s.container.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){
setParallaxTransform(this, s.progress);
});
s.slides.each(function () {
var slide = $(this);
slide.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function () {
var progress = Math.min(Math.max(slide[0].progress, -1), 1);
setParallaxTransform(this, progress);
});
});
},
setTransition: function (duration) {
if (typeof duration === 'undefined') duration = s.params.speed;
s.container.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){
var el = $(this);
var parallaxDuration = parseInt(el.attr('data-swiper-parallax-duration'), 10) || duration;
if (duration === 0) parallaxDuration = 0;
el.transition(parallaxDuration);
});
}
};
/*=========================
Zoom
===========================*/
s.zoom = {
// "Global" Props
scale: 1,
currentScale: 1,
isScaling: false,
gesture: {
slide: undefined,
slideWidth: undefined,
slideHeight: undefined,
image: undefined,
imageWrap: undefined,
zoomMax: s.params.zoomMax
},
image: {
isTouched: undefined,
isMoved: undefined,
currentX: undefined,
currentY: undefined,
minX: undefined,
minY: undefined,
maxX: undefined,
maxY: undefined,
width: undefined,
height: undefined,
startX: undefined,
startY: undefined,
touchesStart: {},
touchesCurrent: {}
},
velocity: {
x: undefined,
y: undefined,
prevPositionX: undefined,
prevPositionY: undefined,
prevTime: undefined
},
// Calc Scale From Multi-touches
getDistanceBetweenTouches: function (e) {
if (e.targetTouches.length < 2) return 1;
var x1 = e.targetTouches[0].pageX,
y1 = e.targetTouches[0].pageY,
x2 = e.targetTouches[1].pageX,
y2 = e.targetTouches[1].pageY;
var distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
return distance;
},
// Events
onGestureStart: function (e) {
var z = s.zoom;
if (!s.support.gestures) {
if (e.type !== 'touchstart' || e.type === 'touchstart' && e.targetTouches.length < 2) {
return;
}
z.gesture.scaleStart = z.getDistanceBetweenTouches(e);
}
if (!z.gesture.slide || !z.gesture.slide.length) {
z.gesture.slide = $(this);
if (z.gesture.slide.length === 0) z.gesture.slide = s.slides.eq(s.activeIndex);
z.gesture.image = z.gesture.slide.find('img, svg, canvas');
z.gesture.imageWrap = z.gesture.image.parent('.' + s.params.zoomContainerClass);
z.gesture.zoomMax = z.gesture.imageWrap.attr('data-swiper-zoom') || s.params.zoomMax ;
if (z.gesture.imageWrap.length === 0) {
z.gesture.image = undefined;
return;
}
}
z.gesture.image.transition(0);
z.isScaling = true;
},
onGestureChange: function (e) {
var z = s.zoom;
if (!s.support.gestures) {
if (e.type !== 'touchmove' || e.type === 'touchmove' && e.targetTouches.length < 2) {
return;
}
z.gesture.scaleMove = z.getDistanceBetweenTouches(e);
}
if (!z.gesture.image || z.gesture.image.length === 0) return;
if (s.support.gestures) {
z.scale = e.scale * z.currentScale;
}
else {
z.scale = (z.gesture.scaleMove / z.gesture.scaleStart) * z.currentScale;
}
if (z.scale > z.gesture.zoomMax) {
z.scale = z.gesture.zoomMax - 1 + Math.pow((z.scale - z.gesture.zoomMax + 1), 0.5);
}
if (z.scale < s.params.zoomMin) {
z.scale = s.params.zoomMin + 1 - Math.pow((s.params.zoomMin - z.scale + 1), 0.5);
}
z.gesture.image.transform('translate3d(0,0,0) scale(' + z.scale + ')');
},
onGestureEnd: function (e) {
var z = s.zoom;
if (!s.support.gestures) {
if (e.type !== 'touchend' || e.type === 'touchend' && e.changedTouches.length < 2) {
return;
}
}
if (!z.gesture.image || z.gesture.image.length === 0) return;
z.scale = Math.max(Math.min(z.scale, z.gesture.zoomMax), s.params.zoomMin);
z.gesture.image.transition(s.params.speed).transform('translate3d(0,0,0) scale(' + z.scale + ')');
z.currentScale = z.scale;
z.isScaling = false;
if (z.scale === 1) z.gesture.slide = undefined;
},
onTouchStart: function (s, e) {
var z = s.zoom;
if (!z.gesture.image || z.gesture.image.length === 0) return;
if (z.image.isTouched) return;
if (s.device.os === 'android') e.preventDefault();
z.image.isTouched = true;
z.image.touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
z.image.touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
},
onTouchMove: function (e) {
var z = s.zoom;
if (!z.gesture.image || z.gesture.image.length === 0) return;
s.allowClick = false;
if (!z.image.isTouched || !z.gesture.slide) return;
if (!z.image.isMoved) {
z.image.width = z.gesture.image[0].offsetWidth;
z.image.height = z.gesture.image[0].offsetHeight;
z.image.startX = s.getTranslate(z.gesture.imageWrap[0], 'x') || 0;
z.image.startY = s.getTranslate(z.gesture.imageWrap[0], 'y') || 0;
z.gesture.slideWidth = z.gesture.slide[0].offsetWidth;
z.gesture.slideHeight = z.gesture.slide[0].offsetHeight;
z.gesture.imageWrap.transition(0);
}
// Define if we need image drag
var scaledWidth = z.image.width * z.scale;
var scaledHeight = z.image.height * z.scale;
if (scaledWidth < z.gesture.slideWidth && scaledHeight < z.gesture.slideHeight) return;
z.image.minX = Math.min((z.gesture.slideWidth / 2 - scaledWidth / 2), 0);
z.image.maxX = -z.image.minX;
z.image.minY = Math.min((z.gesture.slideHeight / 2 - scaledHeight / 2), 0);
z.image.maxY = -z.image.minY;
z.image.touchesCurrent.x = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
z.image.touchesCurrent.y = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
if (!z.image.isMoved && !z.isScaling) {
if (s.isHorizontal() &&
(Math.floor(z.image.minX) === Math.floor(z.image.startX) && z.image.touchesCurrent.x < z.image.touchesStart.x) ||
(Math.floor(z.image.maxX) === Math.floor(z.image.startX) && z.image.touchesCurrent.x > z.image.touchesStart.x)
) {
z.image.isTouched = false;
return;
}
else if (!s.isHorizontal() &&
(Math.floor(z.image.minY) === Math.floor(z.image.startY) && z.image.touchesCurrent.y < z.image.touchesStart.y) ||
(Math.floor(z.image.maxY) === Math.floor(z.image.startY) && z.image.touchesCurrent.y > z.image.touchesStart.y)
) {
z.image.isTouched = false;
return;
}
}
e.preventDefault();
e.stopPropagation();
z.image.isMoved = true;
z.image.currentX = z.image.touchesCurrent.x - z.image.touchesStart.x + z.image.startX;
z.image.currentY = z.image.touchesCurrent.y - z.image.touchesStart.y + z.image.startY;
if (z.image.currentX < z.image.minX) {
z.image.currentX = z.image.minX + 1 - Math.pow((z.image.minX - z.image.currentX + 1), 0.8);
}
if (z.image.currentX > z.image.maxX) {
z.image.currentX = z.image.maxX - 1 + Math.pow((z.image.currentX - z.image.maxX + 1), 0.8);
}
if (z.image.currentY < z.image.minY) {
z.image.currentY = z.image.minY + 1 - Math.pow((z.image.minY - z.image.currentY + 1), 0.8);
}
if (z.image.currentY > z.image.maxY) {
z.image.currentY = z.image.maxY - 1 + Math.pow((z.image.currentY - z.image.maxY + 1), 0.8);
}
//Velocity
if (!z.velocity.prevPositionX) z.velocity.prevPositionX = z.image.touchesCurrent.x;
if (!z.velocity.prevPositionY) z.velocity.prevPositionY = z.image.touchesCurrent.y;
if (!z.velocity.prevTime) z.velocity.prevTime = Date.now();
z.velocity.x = (z.image.touchesCurrent.x - z.velocity.prevPositionX) / (Date.now() - z.velocity.prevTime) / 2;
z.velocity.y = (z.image.touchesCurrent.y - z.velocity.prevPositionY) / (Date.now() - z.velocity.prevTime) / 2;
if (Math.abs(z.image.touchesCurrent.x - z.velocity.prevPositionX) < 2) z.velocity.x = 0;
if (Math.abs(z.image.touchesCurrent.y - z.velocity.prevPositionY) < 2) z.velocity.y = 0;
z.velocity.prevPositionX = z.image.touchesCurrent.x;
z.velocity.prevPositionY = z.image.touchesCurrent.y;
z.velocity.prevTime = Date.now();
z.gesture.imageWrap.transform('translate3d(' + z.image.currentX + 'px, ' + z.image.currentY + 'px,0)');
},
onTouchEnd: function (s, e) {
var z = s.zoom;
if (!z.gesture.image || z.gesture.image.length === 0) return;
if (!z.image.isTouched || !z.image.isMoved) {
z.image.isTouched = false;
z.image.isMoved = false;
return;
}
z.image.isTouched = false;
z.image.isMoved = false;
var momentumDurationX = 300;
var momentumDurationY = 300;
var momentumDistanceX = z.velocity.x * momentumDurationX;
var newPositionX = z.image.currentX + momentumDistanceX;
var momentumDistanceY = z.velocity.y * momentumDurationY;
var newPositionY = z.image.currentY + momentumDistanceY;
//Fix duration
if (z.velocity.x !== 0) momentumDurationX = Math.abs((newPositionX - z.image.currentX) / z.velocity.x);
if (z.velocity.y !== 0) momentumDurationY = Math.abs((newPositionY - z.image.currentY) / z.velocity.y);
var momentumDuration = Math.max(momentumDurationX, momentumDurationY);
z.image.currentX = newPositionX;
z.image.currentY = newPositionY;
// Define if we need image drag
var scaledWidth = z.image.width * z.scale;
var scaledHeight = z.image.height * z.scale;
z.image.minX = Math.min((z.gesture.slideWidth / 2 - scaledWidth / 2), 0);
z.image.maxX = -z.image.minX;
z.image.minY = Math.min((z.gesture.slideHeight / 2 - scaledHeight / 2), 0);
z.image.maxY = -z.image.minY;
z.image.currentX = Math.max(Math.min(z.image.currentX, z.image.maxX), z.image.minX);
z.image.currentY = Math.max(Math.min(z.image.currentY, z.image.maxY), z.image.minY);
z.gesture.imageWrap.transition(momentumDuration).transform('translate3d(' + z.image.currentX + 'px, ' + z.image.currentY + 'px,0)');
},
onTransitionEnd: function (s) {
var z = s.zoom;
if (z.gesture.slide && s.previousIndex !== s.activeIndex) {
z.gesture.image.transform('translate3d(0,0,0) scale(1)');
z.gesture.imageWrap.transform('translate3d(0,0,0)');
z.gesture.slide = z.gesture.image = z.gesture.imageWrap = undefined;
z.scale = z.currentScale = 1;
}
},
// Toggle Zoom
toggleZoom: function (s, e) {
var z = s.zoom;
if (!z.gesture.slide) {
z.gesture.slide = s.clickedSlide ? $(s.clickedSlide) : s.slides.eq(s.activeIndex);
z.gesture.image = z.gesture.slide.find('img, svg, canvas');
z.gesture.imageWrap = z.gesture.image.parent('.' + s.params.zoomContainerClass);
}
if (!z.gesture.image || z.gesture.image.length === 0) return;
var touchX, touchY, offsetX, offsetY, diffX, diffY, translateX, translateY, imageWidth, imageHeight, scaledWidth, scaledHeight, translateMinX, translateMinY, translateMaxX, translateMaxY, slideWidth, slideHeight;
if (typeof z.image.touchesStart.x === 'undefined' && e) {
touchX = e.type === 'touchend' ? e.changedTouches[0].pageX : e.pageX;
touchY = e.type === 'touchend' ? e.changedTouches[0].pageY : e.pageY;
}
else {
touchX = z.image.touchesStart.x;
touchY = z.image.touchesStart.y;
}
if (z.scale && z.scale !== 1) {
// Zoom Out
z.scale = z.currentScale = 1;
z.gesture.imageWrap.transition(300).transform('translate3d(0,0,0)');
z.gesture.image.transition(300).transform('translate3d(0,0,0) scale(1)');
z.gesture.slide = undefined;
}
else {
// Zoom In
z.scale = z.currentScale = z.gesture.imageWrap.attr('data-swiper-zoom') || s.params.zoomMax;
if (e) {
slideWidth = z.gesture.slide[0].offsetWidth;
slideHeight = z.gesture.slide[0].offsetHeight;
offsetX = z.gesture.slide.offset().left;
offsetY = z.gesture.slide.offset().top;
diffX = offsetX + slideWidth/2 - touchX;
diffY = offsetY + slideHeight/2 - touchY;
imageWidth = z.gesture.image[0].offsetWidth;
imageHeight = z.gesture.image[0].offsetHeight;
scaledWidth = imageWidth * z.scale;
scaledHeight = imageHeight * z.scale;
translateMinX = Math.min((slideWidth / 2 - scaledWidth / 2), 0);
translateMinY = Math.min((slideHeight / 2 - scaledHeight / 2), 0);
translateMaxX = -translateMinX;
translateMaxY = -translateMinY;
translateX = diffX * z.scale;
translateY = diffY * z.scale;
if (translateX < translateMinX) {
translateX = translateMinX;
}
if (translateX > translateMaxX) {
translateX = translateMaxX;
}
if (translateY < translateMinY) {
translateY = translateMinY;
}
if (translateY > translateMaxY) {
translateY = translateMaxY;
}
}
else {
translateX = 0;
translateY = 0;
}
z.gesture.imageWrap.transition(300).transform('translate3d(' + translateX + 'px, ' + translateY + 'px,0)');
z.gesture.image.transition(300).transform('translate3d(0,0,0) scale(' + z.scale + ')');
}
},
// Attach/Detach Events
attachEvents: function (detach) {
var action = detach ? 'off' : 'on';
if (s.params.zoom) {
var target = s.slides;
var passiveListener = s.touchEvents.start === 'touchstart' && s.support.passiveListener && s.params.passiveListeners ? {passive: true, capture: false} : false;
// Scale image
if (s.support.gestures) {
s.slides[action]('gesturestart', s.zoom.onGestureStart, passiveListener);
s.slides[action]('gesturechange', s.zoom.onGestureChange, passiveListener);
s.slides[action]('gestureend', s.zoom.onGestureEnd, passiveListener);
}
else if (s.touchEvents.start === 'touchstart') {
s.slides[action](s.touchEvents.start, s.zoom.onGestureStart, passiveListener);
s.slides[action](s.touchEvents.move, s.zoom.onGestureChange, passiveListener);
s.slides[action](s.touchEvents.end, s.zoom.onGestureEnd, passiveListener);
}
// Move image
s[action]('touchStart', s.zoom.onTouchStart);
s.slides.each(function (index, slide){
if ($(slide).find('.' + s.params.zoomContainerClass).length > 0) {
$(slide)[action](s.touchEvents.move, s.zoom.onTouchMove);
}
});
s[action]('touchEnd', s.zoom.onTouchEnd);
// Scale Out
s[action]('transitionEnd', s.zoom.onTransitionEnd);
if (s.params.zoomToggle) {
s.on('doubleTap', s.zoom.toggleZoom);
}
}
},
init: function () {
s.zoom.attachEvents();
},
destroy: function () {
s.zoom.attachEvents(true);
}
};
/*=========================
Plugins API. Collect all and init all plugins
===========================*/
s._plugins = [];
for (var plugin in s.plugins) {
var p = s.plugins[plugin](s, s.params[plugin]);
if (p) s._plugins.push(p);
}
// Method to call all plugins event/method
s.callPlugins = function (eventName) {
for (var i = 0; i < s._plugins.length; i++) {
if (eventName in s._plugins[i]) {
s._plugins[i][eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
}
}
};
/*=========================
Events/Callbacks/Plugins Emitter
===========================*/
function normalizeEventName (eventName) {
if (eventName.indexOf('on') !== 0) {
if (eventName[0] !== eventName[0].toUpperCase()) {
eventName = 'on' + eventName[0].toUpperCase() + eventName.substring(1);
}
else {
eventName = 'on' + eventName;
}
}
return eventName;
}
s.emitterEventListeners = {
};
s.emit = function (eventName) {
// Trigger callbacks
if (s.params[eventName]) {
s.params[eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
}
var i;
// Trigger events
if (s.emitterEventListeners[eventName]) {
for (i = 0; i < s.emitterEventListeners[eventName].length; i++) {
s.emitterEventListeners[eventName][i](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
}
}
// Trigger plugins
if (s.callPlugins) s.callPlugins(eventName, arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
};
s.on = function (eventName, handler) {
eventName = normalizeEventName(eventName);
if (!s.emitterEventListeners[eventName]) s.emitterEventListeners[eventName] = [];
s.emitterEventListeners[eventName].push(handler);
return s;
};
s.off = function (eventName, handler) {
var i;
eventName = normalizeEventName(eventName);
if (typeof handler === 'undefined') {
// Remove all handlers for such event
s.emitterEventListeners[eventName] = [];
return s;
}
if (!s.emitterEventListeners[eventName] || s.emitterEventListeners[eventName].length === 0) return;
for (i = 0; i < s.emitterEventListeners[eventName].length; i++) {
if(s.emitterEventListeners[eventName][i] === handler) s.emitterEventListeners[eventName].splice(i, 1);
}
return s;
};
s.once = function (eventName, handler) {
eventName = normalizeEventName(eventName);
var _handler = function () {
handler(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
s.off(eventName, _handler);
};
s.on(eventName, _handler);
return s;
};
// Accessibility tools
s.a11y = {
makeFocusable: function ($el) {
$el.attr('tabIndex', '0');
return $el;
},
addRole: function ($el, role) {
$el.attr('role', role);
return $el;
},
addLabel: function ($el, label) {
$el.attr('aria-label', label);
return $el;
},
disable: function ($el) {
$el.attr('aria-disabled', true);
return $el;
},
enable: function ($el) {
$el.attr('aria-disabled', false);
return $el;
},
onEnterKey: function (event) {
if (event.keyCode !== 13) return;
if ($(event.target).is(s.params.nextButton)) {
s.onClickNext(event);
if (s.isEnd) {
s.a11y.notify(s.params.lastSlideMessage);
}
else {
s.a11y.notify(s.params.nextSlideMessage);
}
}
else if ($(event.target).is(s.params.prevButton)) {
s.onClickPrev(event);
if (s.isBeginning) {
s.a11y.notify(s.params.firstSlideMessage);
}
else {
s.a11y.notify(s.params.prevSlideMessage);
}
}
if ($(event.target).is('.' + s.params.bulletClass)) {
$(event.target)[0].click();
}
},
liveRegion: $('<span class="' + s.params.notificationClass + '" aria-live="assertive" aria-atomic="true"></span>'),
notify: function (message) {
var notification = s.a11y.liveRegion;
if (notification.length === 0) return;
notification.html('');
notification.html(message);
},
init: function () {
// Setup accessibility
if (s.params.nextButton && s.nextButton && s.nextButton.length > 0) {
s.a11y.makeFocusable(s.nextButton);
s.a11y.addRole(s.nextButton, 'button');
s.a11y.addLabel(s.nextButton, s.params.nextSlideMessage);
}
if (s.params.prevButton && s.prevButton && s.prevButton.length > 0) {
s.a11y.makeFocusable(s.prevButton);
s.a11y.addRole(s.prevButton, 'button');
s.a11y.addLabel(s.prevButton, s.params.prevSlideMessage);
}
$(s.container).append(s.a11y.liveRegion);
},
initPagination: function () {
if (s.params.pagination && s.params.paginationClickable && s.bullets && s.bullets.length) {
s.bullets.each(function () {
var bullet = $(this);
s.a11y.makeFocusable(bullet);
s.a11y.addRole(bullet, 'button');
s.a11y.addLabel(bullet, s.params.paginationBulletMessage.replace(/{{index}}/, bullet.index() + 1));
});
}
},
destroy: function () {
if (s.a11y.liveRegion && s.a11y.liveRegion.length > 0) s.a11y.liveRegion.remove();
}
};
/*=========================
Init/Destroy
===========================*/
s.init = function () {
if (s.params.loop) s.createLoop();
s.updateContainerSize();
s.updateSlidesSize();
s.updatePagination();
if (s.params.scrollbar && s.scrollbar) {
s.scrollbar.set();
if (s.params.scrollbarDraggable) {
s.scrollbar.enableDraggable();
}
}
if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
if (!s.params.loop) s.updateProgress();
s.effects[s.params.effect].setTranslate();
}
if (s.params.loop) {
s.slideTo(s.params.initialSlide + s.loopedSlides, 0, s.params.runCallbacksOnInit);
}
else {
s.slideTo(s.params.initialSlide, 0, s.params.runCallbacksOnInit);
if (s.params.initialSlide === 0) {
if (s.parallax && s.params.parallax) s.parallax.setTranslate();
if (s.lazy && s.params.lazyLoading) {
s.lazy.load();
s.lazy.initialImageLoaded = true;
}
}
}
s.attachEvents();
if (s.params.observer && s.support.observer) {
s.initObservers();
}
if (s.params.preloadImages && !s.params.lazyLoading) {
s.preloadImages();
}
if (s.params.zoom && s.zoom) {
s.zoom.init();
}
if (s.params.autoplay) {
s.startAutoplay();
}
if (s.params.keyboardControl) {
if (s.enableKeyboardControl) s.enableKeyboardControl();
}
if (s.params.mousewheelControl) {
if (s.enableMousewheelControl) s.enableMousewheelControl();
}
// Deprecated hashnavReplaceState changed to replaceState for use in hashnav and history
if (s.params.hashnavReplaceState) {
s.params.replaceState = s.params.hashnavReplaceState;
}
if (s.params.history) {
if (s.history) s.history.init();
}
if (s.params.hashnav) {
if (s.hashnav) s.hashnav.init();
}
if (s.params.a11y && s.a11y) s.a11y.init();
s.emit('onInit', s);
};
// Cleanup dynamic styles
s.cleanupStyles = function () {
// Container
s.container.removeClass(s.classNames.join(' ')).removeAttr('style');
// Wrapper
s.wrapper.removeAttr('style');
// Slides
if (s.slides && s.slides.length) {
s.slides
.removeClass([
s.params.slideVisibleClass,
s.params.slideActiveClass,
s.params.slideNextClass,
s.params.slidePrevClass
].join(' '))
.removeAttr('style')
.removeAttr('data-swiper-column')
.removeAttr('data-swiper-row');
}
// Pagination/Bullets
if (s.paginationContainer && s.paginationContainer.length) {
s.paginationContainer.removeClass(s.params.paginationHiddenClass);
}
if (s.bullets && s.bullets.length) {
s.bullets.removeClass(s.params.bulletActiveClass);
}
// Buttons
if (s.params.prevButton) $(s.params.prevButton).removeClass(s.params.buttonDisabledClass);
if (s.params.nextButton) $(s.params.nextButton).removeClass(s.params.buttonDisabledClass);
// Scrollbar
if (s.params.scrollbar && s.scrollbar) {
if (s.scrollbar.track && s.scrollbar.track.length) s.scrollbar.track.removeAttr('style');
if (s.scrollbar.drag && s.scrollbar.drag.length) s.scrollbar.drag.removeAttr('style');
}
};
// Destroy
s.destroy = function (deleteInstance, cleanupStyles) {
// Detach evebts
s.detachEvents();
// Stop autoplay
s.stopAutoplay();
// Disable draggable
if (s.params.scrollbar && s.scrollbar) {
if (s.params.scrollbarDraggable) {
s.scrollbar.disableDraggable();
}
}
// Destroy loop
if (s.params.loop) {
s.destroyLoop();
}
// Cleanup styles
if (cleanupStyles) {
s.cleanupStyles();
}
// Disconnect observer
s.disconnectObservers();
// Destroy zoom
if (s.params.zoom && s.zoom) {
s.zoom.destroy();
}
// Disable keyboard/mousewheel
if (s.params.keyboardControl) {
if (s.disableKeyboardControl) s.disableKeyboardControl();
}
if (s.params.mousewheelControl) {
if (s.disableMousewheelControl) s.disableMousewheelControl();
}
// Disable a11y
if (s.params.a11y && s.a11y) s.a11y.destroy();
// Delete history popstate
if (s.params.history && !s.params.replaceState) {
window.removeEventListener('popstate', s.history.setHistoryPopState);
}
if (s.params.hashnav && s.hashnav) {
s.hashnav.destroy();
}
// Destroy callback
s.emit('onDestroy');
// Delete instance
if (deleteInstance !== false) s = null;
};
s.init();
// Return swiper instance
return s;
};
/*==================================================
Prototype
====================================================*/
Swiper.prototype = {
isSafari: (function () {
var ua = navigator.userAgent.toLowerCase();
return (ua.indexOf('safari') >= 0 && ua.indexOf('chrome') < 0 && ua.indexOf('android') < 0);
})(),
isUiWebView: /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent),
isArray: function (arr) {
return Object.prototype.toString.apply(arr) === '[object Array]';
},
/*==================================================
Browser
====================================================*/
browser: {
ie: window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
ieTouch: (window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints > 1) || (window.navigator.pointerEnabled && window.navigator.maxTouchPoints > 1),
lteIE9: (function() {
// create temporary DIV
var div = document.createElement('div');
// add content to tmp DIV which is wrapped into the IE HTML conditional statement
div.innerHTML = '<!--[if lte IE 9]><i></i><![endif]-->';
// return true / false value based on what will browser render
return div.getElementsByTagName('i').length === 1;
})()
},
/*==================================================
Devices
====================================================*/
device: (function () {
var ua = navigator.userAgent;
var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
return {
ios: ipad || iphone || ipod,
android: android
};
})(),
/*==================================================
Feature Detection
====================================================*/
support: {
touch : (window.Modernizr && Modernizr.touch === true) || (function () {
return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
})(),
transforms3d : (window.Modernizr && Modernizr.csstransforms3d === true) || (function () {
var div = document.createElement('div').style;
return ('webkitPerspective' in div || 'MozPerspective' in div || 'OPerspective' in div || 'MsPerspective' in div || 'perspective' in div);
})(),
flexbox: (function () {
var div = document.createElement('div').style;
var styles = ('alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient').split(' ');
for (var i = 0; i < styles.length; i++) {
if (styles[i] in div) return true;
}
})(),
observer: (function () {
return ('MutationObserver' in window || 'WebkitMutationObserver' in window);
})(),
passiveListener: (function () {
var supportsPassive = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
supportsPassive = true;
}
});
window.addEventListener('testPassiveListener', null, opts);
} catch (e) {}
return supportsPassive;
})(),
gestures: (function () {
return 'ongesturestart' in window;
})()
},
/*==================================================
Plugins
====================================================*/
plugins: {}
};
})();
//# sourceMappingURL=framework7.js.map