framework7rails 4.0.2 → 4.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b9b7a7fd470ab9769641b68c1977f07f703c0484
4
- data.tar.gz: 66a9615febdd34ef52c7173ea6303338e002eca9
3
+ metadata.gz: fee198e7099e742267f3012165cf4afa062fb53f
4
+ data.tar.gz: 3f8c0419b21a7e887ad66a4e721e533fdc0a3ce2
5
5
  SHA512:
6
- metadata.gz: 4db1887cd6d259e615445af22c04b4f1e85365af7fbc0d10cc68d3bc22509bc0158228b59e886e015b4f5bdb8d07110fe9633c2f7db46f069bd2483d3e3fb09e
7
- data.tar.gz: c73a2e62823a6eda9f67c9a026590961ad0203db6ab629d6381c1973a392c4c33f12a28b215bff9cc6c1f69d3e5c372c2e196fe63f6b1040e297f8c907fe7492
6
+ metadata.gz: a1688adc6cd475130eba1ca9034ae7337d87edc88a4637c659604b10f515e5b044d232a1d3f74b966e7c1a58133b96eb8bc44b9c354f3535ef05a05b4680b4f6
7
+ data.tar.gz: 0ae382593370beea6b94a84482bf1739bd095095c669f21d96f7422c8468ffaf593ddd6611089d07bf9df463ae2024e7316de4fe506960c18e0c2065cf75ae98
@@ -1,4 +1,4 @@
1
1
  module Framework7rails
2
- # framework7 version 1.0.2
3
- VERSION = "4.0.2"
2
+ # framework7 version 1.0.5
3
+ VERSION = "4.0.5"
4
4
  end
@@ -3,7 +3,7 @@
3
3
  if ARGV[0]
4
4
  VERSION_FRAMEWORK7 = ARGV[0]
5
5
  else
6
- VERSION_FRAMEWORK7 = "1.0.2"
6
+ VERSION_FRAMEWORK7 = "1.0.5"
7
7
  end
8
8
 
9
9
  puts "Updating Framework Version #{VERSION_FRAMEWORK7}"
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Framework7 1.0.2
2
+ * Framework7 1.0.5
3
3
  * Full Featured Mobile HTML Framework For Building iOS Apps
4
4
  *
5
5
  * http://www.idangero.us/framework7
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * Licensed under MIT
12
12
  *
13
- * Released on: February 22, 2015
13
+ * Released on: March 28, 2015
14
14
  */
15
15
  (function () {
16
16
 
@@ -24,7 +24,7 @@
24
24
  var app = this;
25
25
 
26
26
  // Version
27
- app.version = '1.0.2';
27
+ app.version = '1.0.5';
28
28
 
29
29
  // Default Parameters
30
30
  app.params = {
@@ -47,6 +47,10 @@
47
47
  fastClicks: true,
48
48
  fastClicksDistanceThreshold: 0,
49
49
  fastClicksDelayBetweenClicks: 50,
50
+ // Tap Hold
51
+ tapHold: false,
52
+ tapHoldDelay: 750,
53
+ tapHoldPreventClicks: true,
50
54
  // Active State
51
55
  activeState: true,
52
56
  activeStateElements: 'a, button, label, span',
@@ -202,6 +206,9 @@
202
206
  var container = $(selector);
203
207
  view.container = container[0];
204
208
 
209
+ // Is main
210
+ view.main = container.hasClass(app.params.viewMainClass);
211
+
205
212
  // Content cache
206
213
  view.contentCache = {};
207
214
 
@@ -239,7 +246,7 @@
239
246
  var viewURL = docLocation;
240
247
  var pushStateSeparator = app.params.pushStateSeparator;
241
248
  var pushStateRoot = app.params.pushStateRoot;
242
- if (app.params.pushState) {
249
+ if (app.params.pushState && view.main) {
243
250
  if (pushStateRoot) {
244
251
  viewURL = pushStateRoot;
245
252
  }
@@ -282,9 +289,6 @@
282
289
  view.history.push(view.url);
283
290
  }
284
291
 
285
- // Is main
286
- view.main = container.hasClass(app.params.viewMainClass);
287
-
288
292
  // Touch events
289
293
  var isTouched = false,
290
294
  isMoved = false,
@@ -374,6 +378,11 @@
374
378
  previousNavBackIcon = previousNavbar.find('.left.sliding .back .icon');
375
379
  }
376
380
  }
381
+
382
+ // Close/Hide Any Picker
383
+ if ($('.picker-modal.modal-in').length > 0) {
384
+ app.closeModal($('.picker-modal.modal-in'));
385
+ }
377
386
  }
378
387
  e.f7PreventPanelSwipe = true;
379
388
  isMoved = true;
@@ -518,8 +527,8 @@
518
527
  view.url = url;
519
528
 
520
529
  // Page before animation callback
521
- app.pageBackCallbacks('before', view, {pageContainer: activePage[0], url: url, position: 'center', newPage: previousPage, oldPage: activePage, swipeBack: true});
522
- app.pageAnimCallbacks('before', view, {pageContainer: previousPage[0], url: url, position: 'left', newPage: previousPage, oldPage: activePage, swipeBack: true});
530
+ app.pageBackCallback('before', view, {pageContainer: activePage[0], url: url, position: 'center', newPage: previousPage, oldPage: activePage, swipeBack: true});
531
+ app.pageAnimCallback('before', view, {pageContainer: previousPage[0], url: url, position: 'left', newPage: previousPage, oldPage: activePage, swipeBack: true});
523
532
  }
524
533
 
525
534
  activePage.transitionEnd(function () {
@@ -533,10 +542,10 @@
533
542
  allowViewTouchMove = true;
534
543
  view.allowPageChange = true;
535
544
  if (pageChanged) {
536
- if (app.params.pushState) history.back();
545
+ if (app.params.pushState && view.main) history.back();
537
546
  // Page after animation callback
538
- app.pageBackCallbacks('after', view, {pageContainer: activePage[0], url: url, position: 'center', newPage: previousPage, oldPage: activePage, swipeBack: true});
539
- app.pageAnimCallbacks('after', view, {pageContainer: previousPage[0], url: url, position: 'left', newPage: previousPage, oldPage: activePage, swipeBack: true});
547
+ app.pageBackCallback('after', view, {pageContainer: activePage[0], url: url, position: 'center', newPage: previousPage, oldPage: activePage, swipeBack: true});
548
+ app.pageAnimCallback('after', view, {pageContainer: previousPage[0], url: url, position: 'left', newPage: previousPage, oldPage: activePage, swipeBack: true});
540
549
  app.router.afterBack(view, activePage, previousPage);
541
550
  }
542
551
  if (pageShadow && pageShadow.length > 0) pageShadow.remove();
@@ -698,35 +707,118 @@
698
707
  return new View(selector, params);
699
708
  };
700
709
 
710
+ app.getCurrentView = function (index) {
711
+ var popoverView = $('.popover.modal-in .view');
712
+ var popupView = $('.popup.modal-in .view');
713
+ var panelView = $('.panel.active .view');
714
+ var appViews = $('.views');
715
+ // Find active view as tab
716
+ var appView = appViews.children('.view');
717
+ // Propably in tabs or split view
718
+ if (appView.length > 1) {
719
+ if (appView.hasClass('tab')) {
720
+ // Tabs
721
+ appView = appViews.children('.view.active');
722
+ }
723
+ else {
724
+ // Split View, leave appView intact
725
+ }
726
+ }
727
+ if (popoverView.length > 0 && popoverView[0].f7View) return popoverView[0].f7View;
728
+ if (popupView.length > 0 && popupView[0].f7View) return popupView[0].f7View;
729
+ if (panelView.length > 0 && panelView[0].f7View) return panelView[0].f7View;
730
+ if (appView.length > 0) {
731
+ if (appView.length === 1 && appView[0].f7View) return appView[0].f7View;
732
+ if (appView.length > 1) {
733
+ var currentViews = [];
734
+ for (var i = 0; i < appView.length; i++) {
735
+ if (appView[i].f7View) currentViews.push(appView[i].f7View);
736
+ }
737
+ if (currentViews.length > 0 && typeof index !== 'undefined') return currentViews[index];
738
+ if (currentViews.length > 1) return currentViews;
739
+ if (currentViews.length === 1) return currentViews[0];
740
+ return undefined;
741
+ }
742
+ }
743
+ return undefined;
744
+ };
745
+
701
746
 
702
747
  /*======================================================
703
748
  ************ Navbars && Toolbars ************
704
749
  ======================================================*/
705
750
  // On Navbar Init Callback
706
- app.navbarInitCallback = function (view, pageContainer, navbar, navbarInnerContainer, url, position) {
707
- var _navbar = {
708
- container: navbar,
751
+ app.navbarInitCallback = function (view, pageContainer, navbarContainer, navbarInnerContainer) {
752
+ if (!navbarContainer && navbarInnerContainer) navbarContainer = $(navbarInnerContainer).parent('.navbar')[0];
753
+ var navbarData = {
754
+ container: navbarContainer,
709
755
  innerContainer: navbarInnerContainer
710
756
  };
711
- var _page = {
712
- url: url,
713
- query: $.parseUrlQuery(url || ''),
714
- container: pageContainer,
715
- name: $(pageContainer).attr('data-page'),
716
- view: view,
717
- from: position
718
- };
757
+ var pageData = pageContainer && pageContainer.f7PageData;
758
+
719
759
  var eventData = {
720
- navbar: _navbar,
721
- page: _page
760
+ page: pageData,
761
+ navbar: navbarData
722
762
  };
723
763
 
724
- // Plugin hook
725
- app.pluginHook('navbarInit', _navbar, _page);
726
-
727
- // Navbar Init Callback
764
+ if (navbarInnerContainer.f7NavbarInitialized) {
765
+ // Reinit Navbar
766
+ app.reinitNavbar(navbarContainer, navbarInnerContainer);
767
+
768
+ // Plugin hook
769
+ app.pluginHook('navbarReinit', pageData);
770
+
771
+ // Event
772
+ $(pageData.container).trigger('navbarReinit', eventData);
773
+ return;
774
+ }
775
+ navbarInnerContainer.f7NavbarInitialized = true;
776
+
777
+ // Before Init
778
+ app.pluginHook('navbarBeforeInit', navbarData, pageData);
779
+ $(navbarInnerContainer).trigger('navbarBeforeInit', eventData);
780
+
781
+ // Initialize Navbar
782
+ app.initNavbar(navbarContainer, navbarInnerContainer);
783
+
784
+ // On init
785
+ app.pluginHook('navbarInit', navbarData, pageData);
728
786
  $(navbarInnerContainer).trigger('navbarInit', eventData);
729
787
  };
788
+ // Navbar Remove Callback
789
+ app.navbarRemoveCallback = function (view, pageContainer, navbarContainer, navbarInnerContainer) {
790
+ if (!navbarContainer && navbarInnerContainer) navbarContainer = $(navbarInnerContainer).parent('.navbar')[0];
791
+ var navbarData = {
792
+ container: navbarContainer,
793
+ innerContainer: navbarInnerContainer
794
+ };
795
+ var pageData = pageContainer.f7PageData;
796
+
797
+ var eventData = {
798
+ page: pageData,
799
+ navbar: navbarData
800
+ };
801
+ app.pluginHook('navbarBeforeRemove', navbarData, pageData);
802
+ $(navbarInnerContainer).trigger('navbarBeforeRemove', eventData);
803
+ };
804
+ app.initNavbar = function (navbarContainer, navbarInnerContainer) {
805
+ // Init Subnavbar Searchbar
806
+ app.initSearchbar(navbarInnerContainer);
807
+ };
808
+ app.reinitNavbar = function (navbarContainer, navbarInnerContainer) {
809
+ // Re init navbar methods
810
+ };
811
+ app.initNavbarWithCallback = function (navbarContainer) {
812
+ navbarContainer = $(navbarContainer);
813
+ var viewContainer = navbarContainer.parents('.' + app.params.viewClass);
814
+ if (viewContainer.length === 0) return;
815
+ var view = viewContainer[0].f7View || undefined;
816
+ navbarContainer.find('.navbar-inner').each(function () {
817
+ app.navbarInitCallback(view, undefined, navbarContainer[0], this);
818
+ });
819
+ };
820
+
821
+ // Size Navbars
730
822
  app.sizeNavbars = function (viewContainer) {
731
823
  var navbarInner = viewContainer ? $(viewContainer).find('.navbar .navbar-inner:not(.cached)') : $('.navbar .navbar-inner:not(.cached)');
732
824
  navbarInner.each(function () {
@@ -809,6 +901,8 @@
809
901
 
810
902
  });
811
903
  };
904
+
905
+ // Hide/Show Navbars/Toolbars
812
906
  app.hideNavbar = function (navbarContainer) {
813
907
  $(navbarContainer).addClass('navbar-hidden');
814
908
  return true;
@@ -835,140 +929,182 @@
835
929
  /*======================================================
836
930
  ************ Searchbar ************
837
931
  ======================================================*/
838
- app.initSearchbar = function (pageContainer) {
839
- pageContainer = $(pageContainer);
840
- var searchbar = pageContainer.hasClass('searchbar') ? pageContainer : pageContainer.find('.searchbar');
841
- if (searchbar.length === 0) return;
842
- if (!pageContainer.hasClass('page')) pageContainer = searchbar.parents('.page').eq(0);
843
- var searchbarOverlay = pageContainer.hasClass('page') ? pageContainer.find('.searchbar-overlay') : $('.searchbar-overlay');
844
- var input = searchbar.find('input[type="search"]');
845
- var clear = searchbar.find('.searchbar-clear');
846
- var cancel = searchbar.find('.searchbar-cancel');
847
- var searchList = $(searchbar.attr('data-search-list'));
848
- var isVirtualList = searchList.hasClass('virtual-list');
849
- var virtualList;
850
- var searchIn = searchbar.attr('data-search-in');
851
- var searchBy = searchbar.attr('data-search-by');
852
- var found = searchbar.attr('data-searchbar-found');
853
- if (!found) {
854
- found = pageContainer.find('.searchbar-found');
855
- if (found.length === 0) found = $('.searchbar-found');
932
+ var Searchbar = function (container, params) {
933
+ var defaults = {
934
+ input: null,
935
+ clearButton: null,
936
+ cancelButton: null,
937
+ searchList: null,
938
+ searchIn: '.item-title',
939
+ searchBy: '',
940
+ found: null,
941
+ notFound: null,
942
+ overlay: null,
943
+ ignore: '.searchbar-ignore',
944
+ customSearch: false
945
+ };
946
+ params = params || {};
947
+ for (var def in defaults) {
948
+ if (typeof params[def] === 'undefined' || params[def] === null) {
949
+ params[def] = defaults[def];
950
+ }
951
+ }
952
+
953
+ // Instance
954
+ var s = this;
955
+
956
+ // Params
957
+ s.params = params;
958
+
959
+ // Container
960
+ container = $(container);
961
+ s.container = container;
962
+
963
+ // Active
964
+ s.active = false;
965
+
966
+ // Input
967
+ s.input = s.params.input ? $(s.params.input) : s.container.find('input[type="search"]');
968
+ s.clearButton = s.params.clearButton ? $(s.params.clearButton) : s.container.find('.searchbar-clear');
969
+ s.cancelButton = s.params.cancelButton ? $(s.params.cancelButton) : s.container.find('.searchbar-cancel');
970
+
971
+ // Search List
972
+ s.searchList = $(s.params.searchList);
973
+ s.ul = s.searchList.children('ul');
974
+
975
+ // Is Virtual List
976
+ s.isVirtualList = s.searchList.hasClass('virtual-list');
977
+
978
+ // Is In Page
979
+ s.pageContainer = s.container.parents('.page').eq(0);
980
+
981
+ // Overlay
982
+ if (!s.params.overlay) {
983
+ s.overlay = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-overlay') : $('.searchbar-overlay');
984
+ }
985
+ else {
986
+ s.overlay = $(s.params.overlay);
987
+ }
988
+ // Found and not found
989
+ if (!s.params.found) {
990
+ s.found = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-found') : $('.searchbar-found');
856
991
  }
857
992
  else {
858
- found = $(found);
993
+ s.found = $(s.params.found);
859
994
  }
860
- var notFound = searchbar.attr('data-searchbar-not-found');
861
- if (!notFound) {
862
- notFound = pageContainer.find('.searchbar-not-found');
863
- if (notFound.length === 0) notFound = $('.searchbar-not-found');
995
+ if (!s.params.notFound) {
996
+ s.notFound = s.pageContainer.length > 0 ? s.pageContainer.find('.searchbar-not-found') : $('.searchbar-not-found');
864
997
  }
865
998
  else {
866
- notFound = $(notFound);
999
+ s.notFound = $(s.params.notFound);
867
1000
  }
868
1001
 
869
1002
  // Cancel button
870
1003
  var cancelMarginProp = app.rtl ? 'margin-left' : 'margin-right';
871
- if (cancel.length > 0) {
872
- cancel.show();
873
- cancel.css(cancelMarginProp, -cancel[0].offsetWidth + 'px');
1004
+ if (s.cancelButton.length > 0) {
1005
+ s.cancelButton.transition(0).show();
1006
+ s.cancelButton.css(cancelMarginProp, -s.cancelButton[0].offsetWidth + 'px');
1007
+ setTimeout(function () {
1008
+ s.cancelButton.transition('');
1009
+ }, 0);
874
1010
  }
875
-
876
1011
 
877
- // Handlers
878
- function disableSearchbar() {
879
- input.val('').trigger('change');
880
- searchbar.removeClass('searchbar-active searchbar-not-empty');
881
- if (cancel.length > 0) cancel.css(cancelMarginProp, -cancel[0].offsetWidth + 'px');
882
-
883
- if (searchList) searchbarOverlay.removeClass('searchbar-overlay-active');
1012
+ s.triggerEvent = function (eventName, eventData) {
1013
+ s.container.trigger(eventName, eventData);
1014
+ if (s.searchList.length > 0) s.searchList.trigger(eventName, eventData);
1015
+ };
1016
+
1017
+ // Enable/disalbe
1018
+ s.enable = function () {
1019
+ function _enable() {
1020
+ if (s.searchList.length && !s.container.hasClass('searchbar-active')) s.overlay.addClass('searchbar-overlay-active');
1021
+ s.container.addClass('searchbar-active');
1022
+ if (s.cancelButton.length > 0) s.cancelButton.css(cancelMarginProp, '0px');
1023
+ s.triggerEvent('enableSearch');
1024
+ s.active = true;
1025
+ }
884
1026
  if (app.device.ios) {
885
1027
  setTimeout(function () {
886
- input.blur();
887
- searchList.trigger('disableSearch');
1028
+ _enable();
888
1029
  }, 400);
889
1030
  }
890
1031
  else {
891
- input.blur();
892
- searchList.trigger('disableSearch');
1032
+ _enable();
893
1033
  }
894
- }
1034
+ };
895
1035
 
896
- // Activate
897
- function enableSearchbar() {
1036
+ s.disable = function () {
1037
+ s.input.val('').trigger('change');
1038
+ s.container.removeClass('searchbar-active searchbar-not-empty');
1039
+ if (s.cancelButton.length > 0) s.cancelButton.css(cancelMarginProp, -s.cancelButton[0].offsetWidth + 'px');
1040
+
1041
+ if (s.searchList.length) s.overlay.removeClass('searchbar-overlay-active');
1042
+ function _disable() {
1043
+ s.input.blur();
1044
+ s.triggerEvent('disableSearch');
1045
+ s.active = false;
1046
+ }
898
1047
  if (app.device.ios) {
899
1048
  setTimeout(function () {
900
- if (searchList && !searchbar.hasClass('searchbar-active')) searchbarOverlay.addClass('searchbar-overlay-active');
901
- searchbar.addClass('searchbar-active');
902
- if (cancel.length > 0) cancel.css(cancelMarginProp, '0px');
903
- searchList.trigger('enableSearch');
904
-
1049
+ _disable();
905
1050
  }, 400);
906
1051
  }
907
1052
  else {
908
- if (searchList && !searchbar.hasClass('searchbar-active')) searchbarOverlay.addClass('searchbar-overlay-active');
909
- searchbar.addClass('searchbar-active');
910
- if (cancel.length > 0) cancel.css(cancelMarginProp, '0px');
911
- searchList.trigger('enableSearch');
1053
+ _disable();
912
1054
  }
913
- }
1055
+ };
914
1056
 
915
1057
  // Clear
916
- function clearSearchbar() {
917
- input.val('').trigger('change').focus();
918
- searchList.trigger('clearSearch');
919
- }
1058
+ s.clear = function () {
1059
+ s.input.val('').trigger('change').focus();
1060
+ s.triggerEvent('clearSearch');
1061
+ };
920
1062
 
921
- // Change
922
- function searchValue() {
1063
+ // Search
1064
+ s.handleInput = function () {
923
1065
  setTimeout(function () {
924
- var value = input.val().trim();
925
- if (value.length === 0) {
926
- searchbar.removeClass('searchbar-not-empty');
927
- if (searchList && searchbar.hasClass('searchbar-active')) searchbarOverlay.addClass('searchbar-overlay-active');
928
- }
929
- else {
930
- searchbar.addClass('searchbar-not-empty');
931
- if (searchList && searchbar.hasClass('searchbar-active')) searchbarOverlay.removeClass('searchbar-overlay-active');
932
- }
933
- if (searchList.length > 0 && (searchIn || isVirtualList)) search(value);
1066
+ var value = s.input.val().trim();
1067
+ if (s.searchList.length > 0 && (s.params.searchIn || s.isVirtualList)) s.search(value, true);
934
1068
  }, 0);
935
- }
936
-
937
- //Prevent submit
938
- function preventSubmit(e) {
939
- e.preventDefault();
940
- }
941
-
942
- function attachEvents(destroy) {
943
- var method = destroy ? 'off' : 'on';
944
- searchbar[method]('submit', preventSubmit);
945
- cancel[method]('click', disableSearchbar);
946
- searchbarOverlay[method]('click', disableSearchbar);
947
- input[method]('focus', enableSearchbar);
948
- input[method]('change keydown keypress keyup', searchValue);
949
- clear[method]('click', clearSearchbar);
950
- }
951
- function detachEvents() {
952
- attachEvents(true);
953
- }
954
- searchbar[0].f7DestroySearchbar = detachEvents;
955
-
956
- // Attach events
957
- attachEvents();
1069
+ };
958
1070
 
959
- // Search
960
1071
  var previousQuery;
961
- function search(query) {
1072
+ var virtualList;
1073
+ s.search = function (query, internal) {
962
1074
  if (query.trim() === previousQuery) return;
963
1075
  previousQuery = query.trim();
1076
+
1077
+ if (!internal) {
1078
+ if (!s.active) {
1079
+ s.enable();
1080
+ }
1081
+ if (!internal) {
1082
+ s.input.val(query);
1083
+ }
1084
+ }
1085
+ // Add active/inactive classes on overlay
1086
+ if (query.length === 0) {
1087
+ s.container.removeClass('searchbar-not-empty');
1088
+ if (s.searchList.length && s.container.hasClass('searchbar-active')) s.overlay.addClass('searchbar-overlay-active');
1089
+ }
1090
+ else {
1091
+ s.container.addClass('searchbar-not-empty');
1092
+ if (s.searchList.length && s.container.hasClass('searchbar-active')) s.overlay.removeClass('searchbar-overlay-active');
1093
+ }
1094
+
1095
+ if (s.params.externalSearch) {
1096
+ s.triggerEvent('search', {query: query});
1097
+ return;
1098
+ }
1099
+
964
1100
  var values = query.trim().toLowerCase().split(' ');
965
1101
  var foundItems = [];
966
- if (isVirtualList) {
967
- virtualList = searchList[0].f7VirtualList;
1102
+ if (s.isVirtualList) {
1103
+ virtualList = s.searchList[0].f7VirtualList;
968
1104
  if (query.trim() === '') {
969
1105
  virtualList.resetFilter();
970
- notFound.hide();
971
- found.show();
1106
+ s.notFound.hide();
1107
+ s.found.show();
972
1108
  return;
973
1109
  }
974
1110
  if (virtualList.params.searchAll) {
@@ -983,18 +1119,21 @@
983
1119
  }
984
1120
  }
985
1121
  else {
986
- searchIn = searchbar.attr('data-search-in');
987
- searchList.find('li').removeClass('hidden-by-searchbar').each(function (index, el) {
1122
+ if (s.ul.length === 0) {
1123
+ s.ul = s.searchList.children('ul');
1124
+ }
1125
+ s.ul.children('li').removeClass('hidden-by-searchbar').each(function (index, el) {
988
1126
  el = $(el);
989
- var compareWithEl = el.find(searchIn);
990
- if (compareWithEl.length === 0) return;
991
- var compareWith;
992
- compareWith = compareWithEl.text().trim().toLowerCase();
1127
+ var compareWithText = [];
1128
+ el.find(s.params.searchIn).each(function () {
1129
+ compareWithText.push($(this).text().trim().toLowerCase());
1130
+ });
1131
+ compareWithText = compareWithText.join(' ');
993
1132
  var wordsMatch = 0;
994
1133
  for (var i = 0; i < values.length; i++) {
995
- if (compareWith.indexOf(values[i]) >= 0) wordsMatch++;
1134
+ if (compareWithText.indexOf(values[i]) >= 0) wordsMatch++;
996
1135
  }
997
- if (wordsMatch !== values.length) {
1136
+ if (wordsMatch !== values.length && !(s.params.ignore && el.is(s.params.ignore))) {
998
1137
  el.addClass('hidden-by-searchbar');
999
1138
  }
1000
1139
  else {
@@ -1003,7 +1142,7 @@
1003
1142
  });
1004
1143
 
1005
1144
  if (app.params.searchbarHideDividers) {
1006
- searchList.find('.item-divider, .list-group-title').each(function () {
1145
+ s.searchList.find('.item-divider, .list-group-title').each(function () {
1007
1146
  var title = $(this);
1008
1147
  var nextElements = title.nextAll('li');
1009
1148
  var hide = true;
@@ -1014,15 +1153,17 @@
1014
1153
  hide = false;
1015
1154
  }
1016
1155
  }
1017
- if (hide) title.addClass('hidden-by-searchbar');
1156
+ var ignore = s.params.ignore && title.is(s.params.ignore);
1157
+ if (hide && !ignore) title.addClass('hidden-by-searchbar');
1018
1158
  else title.removeClass('hidden-by-searchbar');
1019
1159
  });
1020
1160
  }
1021
1161
  if (app.params.searchbarHideGroups) {
1022
- searchList.find('.list-group').each(function () {
1162
+ s.searchList.find('.list-group').each(function () {
1023
1163
  var group = $(this);
1164
+ var ignore = s.params.ignore && group.is(s.params.ignore);
1024
1165
  var notHidden = group.find('li:not(.hidden-by-searchbar)');
1025
- if (notHidden.length === 0) {
1166
+ if (notHidden.length === 0 && !ignore) {
1026
1167
  group.addClass('hidden-by-searchbar');
1027
1168
  }
1028
1169
  else {
@@ -1031,126 +1172,213 @@
1031
1172
  });
1032
1173
  }
1033
1174
  }
1034
- searchList.trigger('search', {query: query, foundItems: foundItems});
1175
+ s.triggerEvent('search', {query: query, foundItems: foundItems});
1035
1176
  if (foundItems.length === 0) {
1036
- notFound.show();
1037
- found.hide();
1177
+ s.notFound.show();
1178
+ s.found.hide();
1038
1179
  }
1039
1180
  else {
1040
- notFound.hide();
1041
- found.show();
1181
+ s.notFound.hide();
1182
+ s.found.show();
1042
1183
  }
1043
- if (isVirtualList) {
1184
+ if (s.isVirtualList) {
1044
1185
  virtualList.filterItems(foundItems);
1045
1186
  }
1046
- }
1187
+ };
1047
1188
 
1048
- // Destroy on page remove
1049
- function pageBeforeRemove() {
1050
- detachEvents();
1051
- pageContainer.off('pageBeforeRemove', pageBeforeRemove);
1052
- }
1053
- if (pageContainer.hasClass('page')) {
1054
- pageContainer.on('pageBeforeRemove', pageBeforeRemove);
1189
+ // Events
1190
+ function preventSubmit(e) {
1191
+ e.preventDefault();
1055
1192
  }
1056
-
1193
+
1194
+ s.attachEvents = function (destroy) {
1195
+ var method = destroy ? 'off' : 'on';
1196
+ s.container[method]('submit', preventSubmit);
1197
+ s.cancelButton[method]('click', s.disable);
1198
+ s.overlay[method]('click', s.disable);
1199
+ s.input[method]('focus', s.enable);
1200
+ s.input[method]('change keydown keypress keyup', s.handleInput);
1201
+ s.clearButton[method]('click', s.clear);
1202
+ };
1203
+ s.detachEvents = function() {
1204
+ s.attachEvents(true);
1205
+ };
1206
+
1207
+ // Init Destroy
1208
+ s.init = function () {
1209
+ s.attachEvents();
1210
+ };
1211
+ s.destroy = function () {
1212
+ s.detachEvents();
1213
+ s = null;
1214
+ };
1215
+
1216
+ // Init
1217
+ s.init();
1218
+
1219
+ s.container[0].f7Searchbar = s;
1220
+ return s;
1221
+
1057
1222
  };
1058
- app.destroySearchbar = function (pageContainer) {
1059
- pageContainer = $(pageContainer);
1060
- var searchbar = pageContainer.hasClass('searchbar') ? pageContainer : pageContainer.find('.searchbar');
1061
- if (searchbar.length === 0) return;
1062
- if (searchbar[0].f7DestroySearchbar) searchbar[0].f7DestroySearchbar();
1223
+ app.searchbar = function (container, params) {
1224
+ return new Searchbar(container, params);
1063
1225
  };
1226
+ app.initSearchbar = function (container) {
1227
+ container = $(container);
1228
+ var searchbar = container.hasClass('searchbar') ? container : container.find('.searchbar');
1229
+ if (searchbar.length === 0) return;
1230
+ if (!searchbar.hasClass('searchbar-init')) return;
1064
1231
 
1232
+ var sb = app.searchbar(searchbar, searchbar.dataset());
1233
+
1234
+ function onBeforeRemove() {
1235
+ sb.destroy();
1236
+ }
1237
+ if (container.hasClass('page')) {
1238
+ container.once('pageBeforeRemove', onBeforeRemove);
1239
+ }
1240
+ else if (container.hasClass('navbar-inner')) {
1241
+ container.once('navbarBeforeRemove', onBeforeRemove);
1242
+ }
1243
+ };
1065
1244
 
1066
1245
  /*======================================================
1067
1246
  ************ Messagebar ************
1068
1247
  ======================================================*/
1069
- app.initMessagebar = function (pageContainer) {
1070
- pageContainer = $(pageContainer);
1071
- var messagebar = pageContainer.hasClass('messagebar') ? pageContainer : pageContainer.find('.messagebar');
1072
- if (messagebar.length === 0) return;
1073
- var textarea = messagebar.find('textarea');
1074
- var pageContent = messagebar.parents('.page').find('.page-content');
1075
- var pageContentInitialPadding = parseInt(pageContent.css('padding-bottom'));
1076
- var initialBarHeight = messagebar[0].offsetHeight;
1077
- var initialAreaHeight = textarea[0].offsetHeight;
1078
-
1079
- //Prevent submit
1080
- function preventSubmit(e) {
1081
- e.preventDefault();
1248
+ var Messagebar = function (container, params) {
1249
+ var defaults = {
1250
+ textarea: null,
1251
+ maxHeight: null,
1252
+ };
1253
+ params = params || {};
1254
+ for (var def in defaults) {
1255
+ if (typeof params[def] === 'undefined' || params[def] === null) {
1256
+ params[def] = defaults[def];
1257
+ }
1082
1258
  }
1259
+
1260
+ // Instance
1261
+ var m = this;
1262
+
1263
+ // Params
1264
+ m.params = params;
1265
+
1266
+ // Container
1267
+ m.container = $(container);
1268
+ if (m.container.length === 0) return;
1269
+
1270
+ // Textarea
1271
+ m.textarea = m.params.textarea ? $(m.params.textarea) : m.container.find('textarea');
1272
+
1273
+ // Is In Page
1274
+ m.pageContainer = m.container.parents('.page').eq(0);
1275
+ m.pageContent = m.pageContainer.find('.page-content');
1276
+
1277
+ // Initial Sizes
1278
+ m.pageContentPadding = parseInt(m.pageContent.css('padding-bottom'));
1279
+ m.initialBarHeight = m.container[0].offsetHeight;
1280
+ m.initialAreaHeight = m.textarea[0].offsetHeight;
1281
+
1083
1282
 
1084
1283
  // Resize textarea
1085
- function sizeTextarea() {
1284
+ m.sizeTextarea = function () {
1086
1285
  // Reset
1087
- textarea.css({'height': ''});
1286
+ m.textarea.css({'height': ''});
1088
1287
 
1089
- var height = textarea[0].offsetHeight;
1090
- var diff = height - textarea[0].clientHeight;
1091
- var scrollHeight = textarea[0].scrollHeight;
1092
- var addExtra = parseInt((messagebar.attr('data-keyboard-height') || 0), 10);
1288
+ var height = m.textarea[0].offsetHeight;
1289
+ var diff = height - m.textarea[0].clientHeight;
1290
+ var scrollHeight = m.textarea[0].scrollHeight;
1291
+
1093
1292
  // Update
1094
1293
  if (scrollHeight + diff > height) {
1095
1294
  var newAreaHeight = scrollHeight + diff;
1096
- var newBarHeight = initialBarHeight + (newAreaHeight - initialAreaHeight);
1097
- var maxBarHeight = messagebar.attr('data-max-height') || messagebar.parents('.view')[0].offsetHeight - 88;
1295
+ var newBarHeight = m.initialBarHeight + (newAreaHeight - m.initialAreaHeight);
1296
+ var maxBarHeight = m.params.maxHeight || m.container.parents('.view')[0].offsetHeight - 88;
1098
1297
  if (newBarHeight > maxBarHeight) {
1099
1298
  newBarHeight = parseInt(maxBarHeight, 10);
1100
- newAreaHeight = newBarHeight - initialBarHeight + initialAreaHeight;
1299
+ newAreaHeight = newBarHeight - m.initialBarHeight + m.initialAreaHeight;
1101
1300
  }
1102
- textarea.css('height', newAreaHeight + 'px');
1103
- messagebar.css('height', newBarHeight + 'px');
1104
- if (pageContent.length > 0) {
1105
- pageContent.css('padding-bottom', newBarHeight + addExtra + 'px');
1106
- pageContent.scrollTop(pageContent[0].scrollHeight - pageContent[0].offsetHeight);
1301
+ m.textarea.css('height', newAreaHeight + 'px');
1302
+ m.container.css('height', newBarHeight + 'px');
1303
+ if (m.pageContent.length > 0) {
1304
+ m.pageContent.css('padding-bottom', newBarHeight + 'px');
1305
+ m.pageContent.scrollTop(m.pageContent[0].scrollHeight - m.pageContent[0].offsetHeight);
1107
1306
  }
1108
1307
  }
1109
1308
  else {
1110
- if (pageContent.length > 0) {
1111
- messagebar.css({'height': ''});
1112
- pageContent.css({'padding-bottom': addExtra ? pageContentInitialPadding + addExtra + 'px' : ''});
1309
+ if (m.pageContent.length > 0) {
1310
+ m.container.css({'height': '', 'bottom': ''});
1311
+ m.pageContent.css({'padding-bottom': ''});
1113
1312
  }
1114
1313
  }
1115
- }
1116
- var to;
1117
- function handleKey(e) {
1118
- clearTimeout(to);
1119
- to = setTimeout(function () {
1120
- sizeTextarea();
1314
+ };
1315
+
1316
+ // Clear
1317
+ m.clear = function () {
1318
+ m.textarea.val('').trigger('change');
1319
+ };
1320
+ m.value = function (value) {
1321
+ if (typeof value === 'undefined') return m.textarea.val();
1322
+ else m.textarea.val(value).trigger('change');
1323
+ };
1324
+
1325
+ // Handle textarea
1326
+ m.textareaTimeout = undefined;
1327
+ m.handleTextarea = function (e) {
1328
+ clearTimeout(m.textareaTimeout);
1329
+ m.textareaTimeout = setTimeout(function () {
1330
+ m.sizeTextarea();
1121
1331
  }, 0);
1122
-
1332
+ };
1333
+
1334
+ //Events
1335
+ function preventSubmit(e) {
1336
+ e.preventDefault();
1123
1337
  }
1124
1338
 
1125
- function attachEvents(destroy) {
1339
+ m.attachEvents = function (destroy) {
1126
1340
  var method = destroy ? 'off' : 'on';
1127
- messagebar[method]('submit', preventSubmit);
1128
- textarea[method]('change keydown keypress keyup paste cut', handleKey);
1129
- }
1130
- function detachEvents() {
1131
- attachEvents(true);
1132
- }
1341
+ m.container[method]('submit', preventSubmit);
1342
+ m.textarea[method]('change keydown keypress keyup paste cut', m.handleTextarea);
1343
+ };
1344
+ m.detachEvents = function () {
1345
+ m.attachEvents(true);
1346
+ };
1133
1347
 
1134
- messagebar[0].f7DestroyMessagebar = detachEvents;
1348
+ // Init Destroy
1349
+ m.init = function () {
1350
+ m.attachEvents();
1351
+ };
1352
+ m.destroy = function () {
1353
+ m.detachEvents();
1354
+ m = null;
1355
+ };
1135
1356
 
1136
- // Attach events
1137
- attachEvents();
1357
+ // Init
1358
+ m.init();
1359
+
1360
+ m.container[0].f7Messagebar = m;
1361
+ return m;
1362
+ };
1363
+ app.messagebar = function (container, params) {
1364
+ return new Messagebar(container, params);
1365
+ };
1366
+ app.initPageMessagebar = function (pageContainer) {
1367
+ pageContainer = $(pageContainer);
1368
+ var messagebar = pageContainer.hasClass('messagebar') ? pageContainer : pageContainer.find('.messagebar');
1369
+ if (messagebar.length === 0) return;
1370
+ if (!messagebar.hasClass('messagebar-init')) return;
1371
+ var mb = app.messagebar(messagebar, messagebar.dataset());
1138
1372
 
1139
1373
  // Destroy on page remove
1140
1374
  function pageBeforeRemove() {
1141
- detachEvents();
1375
+ mb.destroy();
1142
1376
  pageContainer.off('pageBeforeRemove', pageBeforeRemove);
1143
1377
  }
1144
1378
  if (pageContainer.hasClass('page')) {
1145
1379
  pageContainer.on('pageBeforeRemove', pageBeforeRemove);
1146
1380
  }
1147
1381
  };
1148
- app.destroyMessagebar = function (pageContainer) {
1149
- pageContainer = $(pageContainer);
1150
- var messagebar = pageContainer.hasClass('messagebar') ? pageContainer : pageContainer.find('.messagebar');
1151
- if (messagebar.length === 0) return;
1152
- if (messagebar[0].f7DestroyMessagebar) messagebar[0].f7DestroyMessagebar();
1153
- };
1154
1382
 
1155
1383
  /*======================================================
1156
1384
  ************ XHR ************
@@ -1192,7 +1420,7 @@
1192
1420
  method: 'GET',
1193
1421
  beforeSend: app.params.onAjaxStart,
1194
1422
  complete: function (xhr) {
1195
- if (xhr.status === 200 || xhr.status === 0) {
1423
+ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0) {
1196
1424
  if (app.params.cache && !ignoreCache) {
1197
1425
  app.removeFromCache(_url);
1198
1426
  app.cache.push({
@@ -1310,6 +1538,9 @@
1310
1538
  navbarInnerContainer: params.navbarInnerContainer,
1311
1539
  fromPage: params.fromPage
1312
1540
  };
1541
+ if (params.fromPage && !params.fromPage.navbarInnerContainer && params.oldNavbarInnerContainer) {
1542
+ params.fromPage.navbarInnerContainer = params.oldNavbarInnerContainer;
1543
+ }
1313
1544
 
1314
1545
  if (pageContainer.f7PageInitialized && view.params.domCache) {
1315
1546
  // Reinit Page
@@ -1365,7 +1596,7 @@
1365
1596
  app.triggerPageCallbacks('beforeRemove', pageData.name, pageData);
1366
1597
  $(pageData.container).trigger('pageBeforeRemove', {page: pageData});
1367
1598
  };
1368
- app.pageBackCallbacks = function (callback, view, params) {
1599
+ app.pageBackCallback = function (callback, view, params) {
1369
1600
  // Page Data
1370
1601
  var pageContainer = params.pageContainer;
1371
1602
  var pageContext;
@@ -1397,7 +1628,7 @@
1397
1628
  $(pageData.container).trigger('pageBack', {page: pageData});
1398
1629
  }
1399
1630
  };
1400
- app.pageAnimCallbacks = function (callback, view, params) {
1631
+ app.pageAnimCallback = function (callback, view, params) {
1401
1632
  var pageContainer = params.pageContainer;
1402
1633
  var pageContext;
1403
1634
  if (pageContainer.f7PageData) pageContext = pageContainer.f7PageData.context;
@@ -1476,14 +1707,13 @@
1476
1707
  // Size navbars on page load
1477
1708
  if (app.sizeNavbars) app.sizeNavbars(pageContainer.parents('.' + app.params.viewClass)[0]);
1478
1709
  // Init messages
1479
- if (app.initMessages) app.initMessages(pageContainer);
1710
+ if (app.initPageMessages) app.initPageMessages(pageContainer);
1480
1711
  // Init forms storage
1481
1712
  if (app.initFormsStorage) app.initFormsStorage(pageContainer);
1482
1713
  // Init smart select
1483
1714
  if (app.initSmartSelects) app.initSmartSelects(pageContainer);
1484
1715
  // Init slider
1485
- if (app.initSlider) app.initSlider(pageContainer);
1486
- if (app.initSwiper) app.initSwiper(pageContainer);
1716
+ if (app.initPageSwiper) app.initPageSwiper(pageContainer);
1487
1717
  // Init pull to refres
1488
1718
  if (app.initPullToRefresh) app.initPullToRefresh(pageContainer);
1489
1719
  // Init infinite scroll
@@ -1491,7 +1721,7 @@
1491
1721
  // Init searchbar
1492
1722
  if (app.initSearchbar) app.initSearchbar(pageContainer);
1493
1723
  // Init message bar
1494
- if (app.initMessagebar) app.initMessagebar(pageContainer);
1724
+ if (app.initPageMessagebar) app.initPageMessagebar(pageContainer);
1495
1725
  // Init scroll toolbars
1496
1726
  if (app.initScrollToolbars) app.initScrollToolbars(pageContainer);
1497
1727
  // Init scroll toolbars
@@ -1502,8 +1732,7 @@
1502
1732
  // Size navbars on page reinit
1503
1733
  if (app.sizeNavbars) app.sizeNavbars(pageContainer.parents('.' + app.params.viewClass)[0]);
1504
1734
  // Reinit slider
1505
- if (app.reinitSlider) app.reinitSlider(pageContainer);
1506
- if (app.reinitSwiper) app.reinitSwiper(pageContainer);
1735
+ if (app.reinitPageSwiper) app.reinitPageSwiper(pageContainer);
1507
1736
  // Reinit lazy load
1508
1737
  if (app.reinitLazyLoad) app.reinitLazyLoad(pageContainer);
1509
1738
  };
@@ -1511,10 +1740,10 @@
1511
1740
  pageContainer = $(pageContainer);
1512
1741
  var viewContainer = pageContainer.parents('.' + app.params.viewClass);
1513
1742
  if (viewContainer.length === 0) return;
1514
- var view = viewContainer[0].f7View || false;
1515
- var url = view && view.url ? view.url : false;
1516
- if (viewContainer) {
1517
- viewContainer.attr('data-page', pageContainer.attr('data-page') || undefined);
1743
+ var view = viewContainer[0].f7View || undefined;
1744
+ var url = view && view.url ? view.url : undefined;
1745
+ if (viewContainer && pageContainer.attr('data-page')) {
1746
+ viewContainer.attr('data-page', pageContainer.attr('data-page'));
1518
1747
  }
1519
1748
  app.pageInitCallback(view, {pageContainer: pageContainer[0], url: url, position: 'center'});
1520
1749
  };
@@ -1641,22 +1870,39 @@
1641
1870
  }
1642
1871
  },
1643
1872
 
1644
- preprocess: function(content, url, next) {
1873
+ preprocess: function(view, content, url, next) {
1645
1874
  // Plugin hook
1646
- app.pluginHook('routerPreprocess', content, url, next);
1875
+ app.pluginHook('routerPreprocess', view, content, url, next);
1647
1876
 
1648
1877
  // Preprocess by plugin
1649
1878
  content = app.pluginProcess('preprocess', content);
1650
1879
 
1651
- if (app.params.preprocess) {
1652
- content = app.params.preprocess(content, url, next);
1880
+ if (view && view.params && view.params.preprocess) {
1881
+ content = view.params.preprocess(content, url, next);
1882
+ console.log(content);
1653
1883
  if (typeof content !== 'undefined') {
1654
1884
  next(content);
1655
1885
  }
1656
- } else {
1886
+ }
1887
+ else if (app.params.preprocess) {
1888
+ content = app.params.preprocess(content, url, next);
1889
+ if (typeof content !== 'undefined') {
1890
+ next(content);
1891
+ }
1892
+ }
1893
+ else {
1657
1894
  next(content);
1658
1895
  }
1659
1896
  },
1897
+ preroute: function(view, options) {
1898
+ app.pluginHook('routerPreroute', view, options);
1899
+ if ((app.params.preroute && app.params.preroute(view, options) === false) || (view && view.params.preroute && view.params.preroute(view, options) === false)) {
1900
+ return true;
1901
+ }
1902
+ else {
1903
+ return false;
1904
+ }
1905
+ },
1660
1906
 
1661
1907
  template7Render: function (view, options) {
1662
1908
  var url = options.url,
@@ -1851,14 +2097,18 @@
1851
2097
 
1852
2098
  if (oldNavbarInner.length > 0) {
1853
2099
  for (i = 0; i < oldNavbarInner.length - 1; i++) {
1854
- if (!view.params.domCache)
2100
+ if (!view.params.domCache) {
2101
+ app.navbarRemoveCallback(view, pagesInView[i], navbar[0], oldNavbarInner[i]);
1855
2102
  $(oldNavbarInner[i]).remove();
2103
+ }
1856
2104
  else
1857
2105
  $(oldNavbarInner[i]).addClass('cached');
1858
2106
  }
1859
2107
  if (!newNavbarInner && oldNavbarInner.length === 1) {
1860
- if (!view.params.domCache)
2108
+ if (!view.params.domCache) {
2109
+ app.navbarRemoveCallback(view, pagesInView[0], navbar[0], oldNavbarInner[0]);
1861
2110
  $(oldNavbarInner[0]).remove();
2111
+ }
1862
2112
  else
1863
2113
  $(oldNavbarInner[0]).addClass('cached');
1864
2114
  }
@@ -1958,6 +2208,7 @@
1958
2208
  }
1959
2209
  else {
1960
2210
  app.pageRemoveCallback(view, oldPage[0], reloadPosition);
2211
+ if (dynamicNavbar) app.navbarRemoveCallback(view, oldPage[0], navbar[0], oldNavbarInner[0]);
1961
2212
  oldPage.remove();
1962
2213
  if (dynamicNavbar) oldNavbarInner.remove();
1963
2214
  }
@@ -1968,7 +2219,8 @@
1968
2219
  pageContainer: newPage[0],
1969
2220
  url: url,
1970
2221
  position: options.reload ? reloadPosition : 'right',
1971
- navbarInnerContainer: dynamicNavbar ? newNavbarInner[0] : undefined,
2222
+ navbarInnerContainer: dynamicNavbar ? newNavbarInner && newNavbarInner[0] : undefined,
2223
+ oldNavbarInnerContainer: dynamicNavbar ? oldNavbarInner && oldNavbarInner[0] : undefined,
1972
2224
  context: t7_rendered.context,
1973
2225
  query: options.query,
1974
2226
  fromPage: oldPage && oldPage.length && oldPage[0].f7PageData
@@ -1992,7 +2244,7 @@
1992
2244
  var clientLeft = newPage[0].clientLeft;
1993
2245
 
1994
2246
  // Before Anim Callback
1995
- app.pageAnimCallbacks('before', view, {
2247
+ app.pageAnimCallback('before', view, {
1996
2248
  pageContainer: newPage[0],
1997
2249
  url: url,
1998
2250
  position: 'right',
@@ -2004,13 +2256,13 @@
2004
2256
 
2005
2257
  function afterAnimation() {
2006
2258
  view.allowPageChange = true;
2007
- newPage.removeClass('page-from-right-to-center page-on-right').addClass('page-on-center');
2008
- oldPage.removeClass('page-from-center-to-left page-on-center').addClass('page-on-left');
2259
+ newPage.removeClass('page-from-right-to-center page-on-right page-on-left').addClass('page-on-center');
2260
+ oldPage.removeClass('page-from-center-to-left page-on-center page-on-right').addClass('page-on-left');
2009
2261
  if (dynamicNavbar) {
2010
2262
  newNavbarInner.removeClass('navbar-from-right-to-center navbar-on-left navbar-on-right').addClass('navbar-on-center');
2011
- oldNavbarInner.removeClass('navbar-from-center-to-left navbar-on-center').addClass('navbar-on-left');
2263
+ oldNavbarInner.removeClass('navbar-from-center-to-left navbar-on-center navbar-on-right').addClass('navbar-on-left');
2012
2264
  }
2013
- app.pageAnimCallbacks('after', view, {
2265
+ app.pageAnimCallback('after', view, {
2014
2266
  pageContainer: newPage[0],
2015
2267
  url: url,
2016
2268
  position: 'right',
@@ -2019,7 +2271,7 @@
2019
2271
  query: options.query,
2020
2272
  fromPage: oldPage && oldPage.length && oldPage[0].f7PageData
2021
2273
  });
2022
- if (app.params.pushState) app.pushStateClearQueue();
2274
+ if (app.params.pushState && view.main) app.pushStateClearQueue();
2023
2275
  if (!(view.params.swipeBackPage || view.params.preloadPreviousPage)) {
2024
2276
  if (view.params.domCache) {
2025
2277
  oldPage.addClass('cached');
@@ -2028,6 +2280,7 @@
2028
2280
  else {
2029
2281
  if (!(url.indexOf('#') === 0 && newPage.attr('data-page').indexOf('smart-select-') === 0)) {
2030
2282
  app.pageRemoveCallback(view, oldPage[0], 'left');
2283
+ if (dynamicNavbar) app.navbarRemoveCallback(view, oldPage[0], navbar[0], oldNavbarInner[0]);
2031
2284
  oldPage.remove();
2032
2285
  if (dynamicNavbar) oldNavbarInner.remove();
2033
2286
  }
@@ -2052,13 +2305,16 @@
2052
2305
  });
2053
2306
  }
2054
2307
  else {
2055
- newNavbarInner.find('.sliding, .sliding .back .icon').transform('');
2308
+ if (dynamicNavbar) newNavbarInner.find('.sliding, .sliding .back .icon').transform('');
2056
2309
  afterAnimation();
2057
2310
  }
2058
2311
 
2059
2312
  };
2060
2313
 
2061
2314
  app.router.load = function (view, options) {
2315
+ if (app.router.preroute(view, options)) {
2316
+ return false;
2317
+ }
2062
2318
  options = options || {};
2063
2319
  var url = options.url;
2064
2320
  var content = options.content;
@@ -2080,7 +2336,7 @@
2080
2336
  app.xhr = false;
2081
2337
  }
2082
2338
  function proceed(content) {
2083
- app.router.preprocess(content, url, function (content) {
2339
+ app.router.preprocess(view, content, url, function (content) {
2084
2340
  options.content = content;
2085
2341
  app.router._load(view, options);
2086
2342
  });
@@ -2138,7 +2394,7 @@
2138
2394
  }
2139
2395
 
2140
2396
  // Push state
2141
- if (app.params.pushState) {
2397
+ if (app.params.pushState && view.main) {
2142
2398
  if (typeof pushState === 'undefined') pushState = true;
2143
2399
  if (!preloadOnly && history.state && pushState) {
2144
2400
  history.back();
@@ -2147,14 +2403,14 @@
2147
2403
 
2148
2404
  // Animation
2149
2405
  function afterAnimation() {
2150
- app.pageBackCallbacks('after', view, {
2406
+ app.pageBackCallback('after', view, {
2151
2407
  pageContainer: oldPage[0],
2152
2408
  url: url,
2153
2409
  position: 'center',
2154
2410
  oldPage: oldPage,
2155
2411
  newPage: newPage,
2156
2412
  });
2157
- app.pageAnimCallbacks('after', view, {
2413
+ app.pageAnimCallback('after', view, {
2158
2414
  pageContainer: newPage[0],
2159
2415
  url: url,
2160
2416
  position: 'left',
@@ -2167,14 +2423,14 @@
2167
2423
  }
2168
2424
  function animateBack() {
2169
2425
  // Page before animation callback
2170
- app.pageBackCallbacks('before', view, {
2426
+ app.pageBackCallback('before', view, {
2171
2427
  pageContainer: oldPage[0],
2172
2428
  url: url,
2173
2429
  position: 'center',
2174
2430
  oldPage: oldPage,
2175
2431
  newPage: newPage,
2176
2432
  });
2177
- app.pageAnimCallbacks('before', view, {
2433
+ app.pageAnimCallback('before', view, {
2178
2434
  pageContainer: newPage[0],
2179
2435
  url: url,
2180
2436
  position: 'left',
@@ -2200,7 +2456,7 @@
2200
2456
  });
2201
2457
  }
2202
2458
  else {
2203
- newNavbarInner.find('.sliding, .sliding .back .icon').transform('');
2459
+ if (dynamicNavbar) newNavbarInner.find('.sliding, .sliding .back .icon').transform('');
2204
2460
  afterAnimation();
2205
2461
  }
2206
2462
  }
@@ -2316,6 +2572,7 @@
2316
2572
  url: url,
2317
2573
  position: 'left',
2318
2574
  navbarInnerContainer: dynamicNavbar ? newNavbarInner[0] : undefined,
2575
+ oldNavbarInnerContainer: dynamicNavbar ? oldNavbarInner && oldNavbarInner[0] : undefined,
2319
2576
  context: t7_rendered.context,
2320
2577
  query: options.query,
2321
2578
  fromPage: oldPage && oldPage.length && oldPage[0].f7PageData,
@@ -2436,6 +2693,9 @@
2436
2693
 
2437
2694
  };
2438
2695
  app.router.back = function (view, options) {
2696
+ if (app.router.preroute(view, options)) {
2697
+ return false;
2698
+ }
2439
2699
  options = options || {};
2440
2700
  var url = options.url;
2441
2701
  var content = options.content;
@@ -2456,7 +2716,7 @@
2456
2716
  var pagesInView = $(view.pagesContainer).find('.page:not(.cached)');
2457
2717
 
2458
2718
  function proceed(content) {
2459
- app.router.preprocess(content, url, function (content) {
2719
+ app.router.preprocess(view, content, url, function (content) {
2460
2720
  options.content = content;
2461
2721
  app.router._back(view, options);
2462
2722
  });
@@ -2548,6 +2808,7 @@
2548
2808
  oldNavbar.removeClass('navbar-from-center-to-right').addClass('cached');
2549
2809
  }
2550
2810
  else {
2811
+ app.navbarRemoveCallback(view, oldPage[0], undefined, oldNavbar[0]);
2551
2812
  oldNavbar.remove();
2552
2813
  }
2553
2814
  newNavbar = $(inners[0]).removeClass('navbar-on-left navbar-from-left-to-center').addClass('navbar-on-center');
@@ -2572,7 +2833,7 @@
2572
2833
  delete view.contentCache[previousURL];
2573
2834
  }
2574
2835
 
2575
- if (app.params.pushState) app.pushStateClearQueue();
2836
+ if (app.params.pushState && view.main) app.pushStateClearQueue();
2576
2837
 
2577
2838
  // Preload previous page
2578
2839
  if (view.params.preloadPreviousPage) {
@@ -2796,7 +3057,7 @@
2796
3057
  }
2797
3058
  var modalHTML;
2798
3059
  if (toPopover) {
2799
- var actionsPopoverTemplate =
3060
+ var actionsToPopoverTemplate = app.params.modalActionsToPopoverTemplate ||
2800
3061
  '<div class="popover actions-popover">' +
2801
3062
  '<div class="popover-inner">' +
2802
3063
  '{{#each this}}' +
@@ -2806,7 +3067,7 @@
2806
3067
  '{{#if label}}' +
2807
3068
  '<li class="actions-popover-label {{#if color}}color-{{color}}{{/if}} {{#if bold}}actions-popover-bold{{/if}}">{{text}}</li>' +
2808
3069
  '{{else}}' +
2809
- '<li><a href="#" class="item-link list-button {{#if color}}color-{{color}}{{/if}} {{#if bg}}bg-{{bg}}{{/if}} {{#if bold}}actions-popover-bold{{/if}}">{{text}}</a></li>' +
3070
+ '<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>' +
2810
3071
  '{{/if}}' +
2811
3072
  '{{/each}}' +
2812
3073
  '</ul>' +
@@ -2814,10 +3075,10 @@
2814
3075
  '{{/each}}' +
2815
3076
  '</div>' +
2816
3077
  '</div>';
2817
- if (!app._compiledTemplates.actionsPopover) {
2818
- app._compiledTemplates.actionsPopover = t7.compile(actionsPopoverTemplate);
3078
+ if (!app._compiledTemplates.actionsToPopover) {
3079
+ app._compiledTemplates.actionsToPopover = t7.compile(actionsToPopoverTemplate);
2819
3080
  }
2820
- var popoverHTML = app._compiledTemplates.actionsPopover(params);
3081
+ var popoverHTML = app._compiledTemplates.actionsToPopover(params);
2821
3082
  modal = $(app.popover(popoverHTML, target, true));
2822
3083
  groupSelector = '.list-block ul';
2823
3084
  buttonSelector = '.list-button';
@@ -2837,6 +3098,7 @@
2837
3098
  if (button.bold) buttonClass += ' actions-modal-button-bold';
2838
3099
  if (button.color) buttonClass += ' color-' + button.color;
2839
3100
  if (button.bg) buttonClass += ' bg-' + button.bg;
3101
+ if (button.disabled) buttonClass += ' disabled';
2840
3102
  buttonsHTML += '<span class="' + buttonClass + '">' + button.text + '</span>';
2841
3103
  if (j === params[i].length - 1) buttonsHTML += '</div>';
2842
3104
  }
@@ -3516,14 +3778,11 @@
3516
3778
  }
3517
3779
  }
3518
3780
 
3519
- if (!app.params.imagesLazyLoadSequential) {
3520
- onLoad();
3521
- return;
3522
- }
3523
-
3524
- if (imageIsLoading) {
3525
- if (imagesSequence.indexOf(el[0]) < 0) imagesSequence.push(el[0]);
3526
- return;
3781
+ if (app.params.imagesLazyLoadSequential) {
3782
+ if (imageIsLoading) {
3783
+ if (imagesSequence.indexOf(el[0]) < 0) imagesSequence.push(el[0]);
3784
+ return;
3785
+ }
3527
3786
  }
3528
3787
 
3529
3788
  // Loading flag
@@ -3599,106 +3858,202 @@
3599
3858
  /*======================================================
3600
3859
  ************ Messages ************
3601
3860
  ======================================================*/
3602
- app.initMessages = function (pageContainer) {
3603
- var page = $(pageContainer);
3604
- var messages = page.find('.messages');
3605
- if (messages.length === 0) return;
3606
- var pageContent = page.find('.page-content');
3607
- if (messages.hasClass('messages-auto-layout')) app.updateMessagesLayout(messages);
3608
- if (!messages.hasClass('new-messages-first')) pageContent[0].scrollTop = pageContent[0].scrollHeight - pageContent[0].offsetHeight;
3609
- };
3610
- app.addMessage = function (props, messagesContent, addToTop) {
3611
- props = props || {};
3612
- props.type = props.type || 'sent';
3613
- if (!props.text || props.length === 0) return false;
3614
- messagesContent = $(messagesContent || '.messages-content');
3615
- if (messagesContent.length === 0) return false;
3616
- var messages = messagesContent.find('.messages');
3617
- var newOnTop = messages.hasClass('new-messages-first');
3618
-
3619
- if (typeof addToTop === 'undefined') {
3620
- addToTop = newOnTop ? true : false;
3621
- }
3622
- var method = addToTop ? 'prepend' : 'append';
3623
-
3624
- var html = '';
3625
- if (props.day) {
3626
- html += '<div class="messages-date">' + props.day + (props.time ? ',' : '') + (props.time ? ' <span>' + props.time + '</span>' : '') + '</div>';
3627
- }
3628
- var isPic = props.text.indexOf('<img') >= 0 ? 'message-pic' : '';
3629
- var withAvatar = props.avatar ? 'message-with-avatar' : '';
3630
- var messageClass = 'message' + ' message-' + props.type + ' ' + isPic + ' ' + withAvatar + ' message-appear-from-' + (method === 'append' ? 'bottom' : 'top');
3631
- html += '<div class="' + messageClass + '">' +
3632
- (props.name ? '<div class="message-name">' + props.name + '</div>' : '') +
3633
- '<div class="message-text">' + props.text + '</div>' +
3634
- (props.avatar ? '<div class="message-avatar" style="background-image:url(' + props.avatar + ')"></div>' : '') +
3635
- (props.label ? '<div class="message-label">' + props.label + '</div>' : '') +
3636
- '</div>';
3637
- messages[method](html);
3638
- if (messages.hasClass('messages-auto-layout')) app.updateMessagesLayout(messages);
3639
- if ((method === 'append' && !newOnTop) || (method === 'prepend' && newOnTop)) {
3640
- app.scrollMessagesContainer(messagesContent);
3641
- }
3642
- };
3643
- app.updateMessagesLayout = function (messages) {
3644
- messages.find('.message').each(function () {
3645
- var message = $(this);
3646
- if (message.find('.message-text img').length > 0) message.addClass('message-pic');
3647
- if (message.find('.message-avatar').length > 0) message.addClass('message-with-avatar');
3648
- });
3649
- messages.find('.message-sent').each(function () {
3650
- var message = $(this);
3651
- var next = message.next('.message-sent');
3652
- var prev = message.prev('.message-sent');
3653
- if (next.length === 0) {
3654
- message.addClass('message-last message-with-tail');
3655
- }
3656
- else message.removeClass('message-last message-with-tail');
3657
-
3658
- if (prev.length === 0) {
3659
- message.addClass('message-first');
3660
- }
3661
- else message.removeClass('message-first');
3662
- // Search for changed names
3663
- if (prev.length > 0 && prev.find('.message-name').length > 0 && message.find('.message-name').length > 0) {
3664
- if (prev.find('.message-name').text() !== message.find('.message-name').text()) {
3665
- prev.addClass('message-last message-with-tail');
3666
- message.addClass('message-first');
3667
- }
3668
- }
3669
- });
3670
- messages.find('.message-received').each(function () {
3671
- var message = $(this);
3672
- var next = message.next('.message-received');
3673
- var prev = message.prev('.message-received');
3674
- if (next.length === 0) {
3675
- message.addClass('message-last message-with-tail');
3861
+ var Messages = function (container, params) {
3862
+ var defaults = {
3863
+ autoLayout: true,
3864
+ newMessagesFirst: false,
3865
+ messageTemplate:
3866
+ '{{#if day}}' +
3867
+ '<div class="messages-date">{{day}} {{#if time}}, <span>{{time}}</span>{{/if}}</div>' +
3868
+ '{{/if}}' +
3869
+ '<div class="message message-{{type}} {{#if hasImage}}message-pic{{/if}} {{#if avatar}}message-with-avatar{{/if}} {{#if position}}message-appear-from-{{position}}{{/if}}">' +
3870
+ '{{#if name}}<div class="message-name">{{name}}</div>{{/if}}' +
3871
+ '<div class="message-text">{{text}}</div>' +
3872
+ '{{#if avatar}}<div class="message-avatar" style="background-image:url({{avatar}})"></div>{{/if}}' +
3873
+ '{{#if label}}<div class="message-label">{{label}}</div>{{/if}}' +
3874
+ '</div>'
3875
+ };
3876
+ params = params || {};
3877
+ for (var def in defaults) {
3878
+ if (typeof params[def] === 'undefined' || params[def] === null) {
3879
+ params[def] = defaults[def];
3676
3880
  }
3677
- else message.removeClass('message-last message-with-tail');
3881
+ }
3678
3882
 
3679
- if (prev.length === 0) {
3680
- message.addClass('message-first');
3681
- }
3682
- else message.removeClass('message-first');
3883
+ // Instance
3884
+ var m = this;
3683
3885
 
3684
- // Search for changed names
3685
- if (prev.length > 0 && prev.find('.message-name').length > 0 && message.find('.message-name').length > 0) {
3686
- if (prev.find('.message-name').text() !== message.find('.message-name').text()) {
3687
- prev.addClass('message-last message-with-tail');
3688
- message.addClass('message-first');
3689
- }
3690
- }
3691
- });
3886
+ // Params
3887
+ m.params = params;
3888
+
3889
+ // Container
3890
+ m.container = $(container);
3891
+ if (m.container.length === 0) return;
3892
+
3893
+ // Autolayout
3894
+ if (m.params.autoLayout) m.container.addClass('messages-auto-layout');
3895
+
3896
+ // Is In Page
3897
+ m.pageContainer = m.container.parents('.page').eq(0);
3898
+ m.pageContent = m.pageContainer.find('.page-content');
3899
+
3900
+ // Compiled template
3901
+ m.template = Template7.compile(m.params.messageTemplate);
3902
+
3903
+ // Auto Layout
3904
+ m.layout = function () {
3905
+ if (!m.container.hasClass('messages-auto-layout')) m.container.addClass('messages-auto-layout');
3906
+ m.container.find('.message').each(function () {
3907
+ var message = $(this);
3908
+ if (message.find('.message-text img').length > 0) message.addClass('message-pic');
3909
+ if (message.find('.message-avatar').length > 0) message.addClass('message-with-avatar');
3910
+ });
3911
+ m.container.find('.message').each(function () {
3912
+ var message = $(this);
3913
+ var isSent = message.hasClass('message-sent');
3914
+ var next = message.next('.message-' + (isSent ? 'sent' : 'received'));
3915
+ var prev = message.prev('.message-' + (isSent ? 'sent' : 'received'));
3916
+ if (next.length === 0) {
3917
+ message.addClass('message-last message-with-tail');
3918
+ }
3919
+ else message.removeClass('message-last message-with-tail');
3920
+
3921
+ if (prev.length === 0) {
3922
+ message.addClass('message-first');
3923
+ }
3924
+ else message.removeClass('message-first');
3925
+
3926
+ if (prev.length > 0 && prev.find('.message-name').length > 0 && message.find('.message-name').length > 0) {
3927
+ if (prev.find('.message-name').text() !== message.find('.message-name').text()) {
3928
+ prev.addClass('message-last message-with-tail');
3929
+ message.addClass('message-first');
3930
+ }
3931
+ }
3932
+ });
3933
+
3934
+ };
3935
+
3936
+ // Add Message
3937
+ m.appendMessage = function (props, animate) {
3938
+ return m.addMessage(props, 'append', animate);
3939
+ };
3940
+ m.prependMessage = function (props, animate) {
3941
+ return m.addMessage(props, 'prepend', animate);
3942
+ };
3943
+ m.addMessage = function (props, method, animate) {
3944
+ return m.addMessages([props], method, animate);
3945
+ };
3946
+ m.addMessages = function (newMessages, method, animate) {
3947
+ if (typeof animate === 'undefined') {
3948
+ animate = true;
3949
+ }
3950
+ if (typeof method === 'undefined') {
3951
+ method = m.params.newMessagesFirst ? 'prepend' : 'append';
3952
+ }
3953
+ var newMessagesHTML = '', i;
3954
+ for (i = 0; i < newMessages.length; i++) {
3955
+ var props = newMessages[i] || {};
3956
+ props.type = props.type || 'sent';
3957
+ if (!props.text) continue;
3958
+ props.hasImage = props.text.indexOf('<img') >= 0;
3959
+ if (animate) props.position = method === 'append' ? 'bottom' : 'top';
3960
+
3961
+ newMessagesHTML += m.template(props);
3962
+ }
3963
+ m.container[method](newMessagesHTML);
3964
+
3965
+ if (m.params.autoLayout) m.layout();
3966
+ if ((method === 'append' && !m.params.newMessagesFirst) || (method === 'prepend' && m.params.newMessagesFirst)) {
3967
+ m.scrollMessages(animate ? undefined : 0);
3968
+ }
3969
+ var messages = m.container.find('.message');
3970
+ if (newMessages.length === 1) {
3971
+ return method === 'append' ? messages[messages.length - 1] : messages[0];
3972
+ }
3973
+ else {
3974
+ var messagesToReturn = [];
3975
+ if (method === 'append') {
3976
+ for (i = messages.length - newMessages.length; i < messages.length; i++) {
3977
+ messagesToReturn.push(messages[i]);
3978
+ }
3979
+ }
3980
+ else {
3981
+ for (i = 0; i < newMessages.length; i++) {
3982
+ messagesToReturn.push(messages[i]);
3983
+ }
3984
+ }
3985
+ return messagesToReturn;
3986
+ }
3987
+
3988
+ };
3989
+ m.removeMessage = function (message) {
3990
+ message = $(message);
3991
+ if (message.length === 0) {
3992
+ return false;
3993
+ }
3994
+ else {
3995
+ message.remove();
3996
+ if (m.params.autoLayout) m.layout();
3997
+ return true;
3998
+ }
3999
+ };
4000
+ m.removeMessages = function (messages) {
4001
+ m.removeMessage(messages);
4002
+ };
4003
+ m.clean = function () {
4004
+ m.container.html('');
4005
+ };
4006
+
4007
+ // Scroll
4008
+ m.scrollMessages = function (duration) {
4009
+ if (typeof duration === 'undefined') duration = 400;
4010
+ var currentScroll = m.pageContent[0].scrollTop;
4011
+ var newScroll = m.params.newMessagesFirst ? 0 : m.pageContent[0].scrollHeight - m.pageContent[0].offsetHeight;
4012
+ if (newScroll === currentScroll) return;
4013
+ m.pageContent.scrollTop(newScroll, duration);
4014
+ };
4015
+
4016
+ // Init Destroy
4017
+ m.init = function () {
4018
+ if (m.params.messages) {
4019
+ m.addMessages(m.params.messages, undefined, false);
4020
+ }
4021
+ else {
4022
+ if (m.params.autoLayout) m.layout();
4023
+ m.scrollMessages(0);
4024
+ }
4025
+
4026
+ };
4027
+ m.destroy = function () {
4028
+ m = null;
4029
+ };
4030
+
4031
+ // Init
4032
+ m.init();
4033
+
4034
+ m.container[0].f7Messages = m;
4035
+ return m;
4036
+ };
4037
+ app.messages = function (container, params) {
4038
+ return new Messages (container, params);
3692
4039
  };
3693
- app.scrollMessagesContainer = function (messagesContent) {
3694
- messagesContent = $(messagesContent || '.messages-content');
3695
- if (messagesContent.length === 0) return;
3696
- var messages = messagesContent.find('.messages');
3697
- var newOnTop = messages.hasClass('new-messages-first');
3698
- var currentScroll = messagesContent[0].scrollTop;
3699
- var newScroll = newOnTop ? 0 : messagesContent[0].scrollHeight - messagesContent[0].offsetHeight;
3700
- if (newScroll === currentScroll) return;
3701
- messagesContent.scrollTop(newScroll, 400);
4040
+ app.initPageMessages = function (pageContainer) {
4041
+ pageContainer = $(pageContainer);
4042
+ var messages = pageContainer.find('.messages');
4043
+ if (messages.length === 0) return;
4044
+ if (!messages.hasClass('messages-init')) {
4045
+ return;
4046
+ }
4047
+ var m = app.messages(messages, messages.dataset());
4048
+
4049
+ // Destroy on page remove
4050
+ function pageBeforeRemove() {
4051
+ m.destroy();
4052
+ pageContainer.off('pageBeforeRemove', pageBeforeRemove);
4053
+ }
4054
+ if (pageContainer.hasClass('page')) {
4055
+ pageContainer.on('pageBeforeRemove', pageBeforeRemove);
4056
+ }
3702
4057
  };
3703
4058
 
3704
4059
 
@@ -4034,12 +4389,18 @@
4034
4389
  app.allowSwipeout = false;
4035
4390
  el.trigger('close');
4036
4391
  el.removeClass('swipeout-opened').addClass('transitioning');
4037
- el.find('.swipeout-content').transform('translate3d(' + 0 + 'px,0,0)').transitionEnd(function () {
4392
+
4393
+ var closeTO;
4394
+ function onSwipeoutClose() {
4038
4395
  app.allowSwipeout = true;
4039
4396
  buttons.transform('');
4040
4397
  el.trigger('closed');
4041
4398
  if (callback) callback.call(el[0]);
4042
- });
4399
+ if (closeTO) clearTimeout(closeTO);
4400
+ }
4401
+ el.find('.swipeout-content').transform('translate3d(' + 0 + 'px,0,0)').transitionEnd(onSwipeoutClose);
4402
+ closeTO = setTimeout(onSwipeoutClose, 500);
4403
+
4043
4404
  for (var i = 0; i < buttons.length; i++) {
4044
4405
  if (dir === 'right') {
4045
4406
  $(buttons[i]).transform('translate3d(' + (-buttons[i].offsetLeft) + 'px,0,0)');
@@ -4213,8 +4574,13 @@
4213
4574
  app.initSmartSelects = function (pageContainer) {
4214
4575
  var page = $(pageContainer);
4215
4576
  if (page.length === 0) return;
4216
-
4217
- var selects = page.find('.smart-select');
4577
+ var selects;
4578
+ if (page.is('.smart-select')) {
4579
+ selects = page;
4580
+ }
4581
+ else {
4582
+ selects = page.find('.smart-select');
4583
+ }
4218
4584
  if (selects.length === 0) return;
4219
4585
 
4220
4586
  selects.each(function () {
@@ -4249,7 +4615,23 @@
4249
4615
  });
4250
4616
 
4251
4617
  };
4252
- app.smartSelectOpen = function (smartSelect) {
4618
+ app.smartSelectAddOption = function (select, option, index) {
4619
+ select = $(select);
4620
+ var smartSelect = select.parents('.smart-select');
4621
+ if (typeof index === 'undefined') {
4622
+ select.append(option);
4623
+ }
4624
+ else {
4625
+ $(option).insertBefore(select.find('option').eq(index));
4626
+ }
4627
+ app.initSmartSelects(smartSelect);
4628
+ var selectName = smartSelect.find('select').attr('name');
4629
+ var opened = $('.page.smart-select-page[data-select-name="' + selectName + '"]').length > 0;
4630
+ if (opened) {
4631
+ app.smartSelectOpen(smartSelect, true);
4632
+ }
4633
+ };
4634
+ app.smartSelectOpen = function (smartSelect, reLayout) {
4253
4635
  smartSelect = $(smartSelect);
4254
4636
  if (smartSelect.length === 0) return;
4255
4637
 
@@ -4263,18 +4645,20 @@
4263
4645
  var openIn = smartSelect.attr('data-open-in');
4264
4646
  if (!openIn) openIn = app.params.smartSelectInPopup ? 'popup' : 'page';
4265
4647
 
4266
- var pageTitle = smartSelect.attr('data-page-title') || smartSelect.find('.item-title').text();
4267
- var backText = smartSelect.attr('data-back-text') || app.params.smartSelectBackText;
4268
- var closeText = smartSelect.attr('data-popup-close-text') || smartSelect.attr('data-back-text') || app.params.smartSelectPopupCloseText ;
4269
- var backOnSelect = smartSelect.attr('data-back-onselect') ? (smartSelect.attr('data-back-onselect') === 'true' ? true : false) : app.params.smartSelectBackOnSelect;
4270
- var formTheme = smartSelect.attr('data-form-theme') || app.params.smartSelectFormTheme;
4271
- var navbarTheme = smartSelect.attr('data-navbar-theme') || app.params.smartSelectNavbarTheme;
4272
- var virtualList = smartSelect.attr('data-virtual-list') === 'true';
4273
- var virtualListItemHeight = smartSelect.attr('data-virtual-list-height');
4648
+ var smartSelectData = smartSelect.dataset();
4649
+ var pageTitle = smartSelectData.pageTitle || smartSelect.find('.item-title').text();
4650
+ var backText = smartSelectData.backText || app.params.smartSelectBackText;
4651
+ var closeText = smartSelectData.popupCloseText || smartSelectData.backText || app.params.smartSelectPopupCloseText ;
4652
+ var backOnSelect = smartSelectData.backOnSelect !== undefined ? smartSelectData.backOnSelect : app.params.smartSelectBackOnSelect;
4653
+ var formTheme = smartSelectData.formTheme || app.params.smartSelectFormTheme;
4654
+ var navbarTheme = smartSelectData.navbarTheme || app.params.smartSelectNavbarTheme;
4655
+ var virtualList = smartSelectData.virtualList;
4656
+ var virtualListHeight = smartSelectData.virtualListHeight;
4274
4657
 
4275
4658
  // Collect all options/values
4276
4659
  var select = smartSelect.find('select')[0];
4277
4660
  var $select = $(select);
4661
+ var $selectData = $select.dataset();
4278
4662
  if (select.disabled || smartSelect.hasClass('disabled') || $select.hasClass('disabled')) {
4279
4663
  return;
4280
4664
  }
@@ -4282,13 +4666,17 @@
4282
4666
  var id = (new Date()).getTime();
4283
4667
  var inputType = select.multiple ? 'checkbox' : 'radio';
4284
4668
  var inputName = inputType + '-' + id;
4285
- var option, optionHasMedia, optionImage, optionIcon, optionGroup, optionGroupLabel, optionPreviousGroup, optionShowGroupLabel, previousGroup;
4669
+ var selectName = select.name;
4670
+ var option, optionHasMedia, optionImage, optionIcon, optionGroup, optionGroupLabel, optionPreviousGroup, optionShowGroupLabel, previousGroup, optionColor, optionClassName, optionData;
4286
4671
  for (var i = 0; i < select.length; i++) {
4287
4672
  option = $(select[i]);
4288
4673
  if (option[0].disabled) continue;
4289
- optionImage = option.attr('data-option-image') || $select.attr('data-option-image');
4290
- optionIcon = option.attr('data-option-icon') || $select.attr('data-option-icon');
4674
+ optionData = option.dataset();
4675
+ optionImage = optionData.optionImage || $selectData.optionImage;
4676
+ optionIcon = optionData.optionIcon || $selectData.optionIcon;
4291
4677
  optionHasMedia = optionImage || optionIcon || inputType === 'checkbox';
4678
+ optionColor = optionData.optionColor;
4679
+ optionClassName = optionData.optionClass;
4292
4680
  optionGroup = option.parent('optgroup')[0];
4293
4681
  optionGroupLabel = optionGroup && optionGroup.label;
4294
4682
  optionShowGroupLabel = false;
@@ -4307,6 +4695,8 @@
4307
4695
  showGroupLabel: optionShowGroupLabel,
4308
4696
  image: optionImage,
4309
4697
  icon: optionIcon,
4698
+ color: optionColor,
4699
+ className: optionClassName,
4310
4700
  disabled: option[0].disabled,
4311
4701
  inputType: inputType,
4312
4702
  id: id,
@@ -4324,7 +4714,7 @@
4324
4714
  '{{#if showGroupLabel}}' +
4325
4715
  '<li class="item-divider">{{groupLabel}}</li>' +
4326
4716
  '{{/if}}' +
4327
- '<li>' +
4717
+ '<li{{#if className}} class="{{className}}"{{/if}}>' +
4328
4718
  '<label class="label-{{inputType}} item-content">' +
4329
4719
  '<input type="{{inputType}}" name="{{inputName}}" value="{{value}}" {{#if selected}}checked{{/if}}>' +
4330
4720
  '{{#if hasMedia}}' +
@@ -4335,7 +4725,7 @@
4335
4725
  '</div>' +
4336
4726
  '{{/if}}' +
4337
4727
  '<div class="item-inner">' +
4338
- '<div class="item-title">{{text}}</div>' +
4728
+ '<div class="item-title{{#if color}} color-{{color}}{{/if}}">{{text}}</div>' +
4339
4729
  '</div>' +
4340
4730
  '</label>' +
4341
4731
  '</li>'
@@ -4398,7 +4788,7 @@
4398
4788
  searchbarCancel = smartSelect.data('searchbar-cancel') || 'Cancel';
4399
4789
  }
4400
4790
 
4401
- var searchbarHTML = '<form class="searchbar" data-search-list=".smart-select-list-' + id + '" data-search-in=".item-title">' +
4791
+ var searchbarHTML = '<form class="searchbar searchbar-init" data-search-list=".smart-select-list-' + id + '" data-search-in=".item-title">' +
4402
4792
  '<div class="searchbar-input">' +
4403
4793
  '<input type="search" placeholder="' + searchbarPlaceholder + '">' +
4404
4794
  '<a href="#" class="searchbar-clear"></a>' +
@@ -4410,7 +4800,7 @@
4410
4800
  var pageHTML =
4411
4801
  (navbarLayout === 'through' ? navbarHTML : '') +
4412
4802
  '<div class="pages">' +
4413
- ' <div data-page="' + pageName + '" class="page smart-select-page ' + noNavbar + ' ' + noToolbar + '">' +
4803
+ ' <div data-page="' + pageName + '" data-select-name="' + selectName + '" class="page smart-select-page ' + noNavbar + ' ' + noToolbar + '">' +
4414
4804
  (navbarLayout === 'fixed' ? navbarHTML : '') +
4415
4805
  (useSearchbar ? searchbarHTML : '') +
4416
4806
  ' <div class="page-content">' +
@@ -4433,9 +4823,9 @@
4433
4823
  var virtualListInstance = app.virtualList($(container).find('.virtual-list'), {
4434
4824
  items: values,
4435
4825
  template: smartSelectItemTemplate,
4436
- height: virtualListItemHeight || undefined,
4826
+ height: virtualListHeight || undefined,
4437
4827
  searchByItem: function (query, index, item) {
4438
- if (item.text.toLowerCase().indexOf(query.trim()) >=0 ) return true;
4828
+ if (item.text.toLowerCase().indexOf(query.trim().toLowerCase()) >=0 ) return true;
4439
4829
  return false;
4440
4830
  }
4441
4831
  });
@@ -4475,26 +4865,33 @@
4475
4865
  function pageInit(e) {
4476
4866
  var page = e.detail.page;
4477
4867
  if (page.name === pageName) {
4478
- $(document).off('pageInit', pageInit);
4479
4868
  handleInputs(page.container);
4480
4869
  }
4481
4870
  }
4482
-
4483
- // Load content
4484
4871
  if (openIn === 'popup') {
4485
- popup = app.popup(
4872
+ if (reLayout) {
4873
+ popup = $('.popup.smart-select-popup .view');
4874
+ popup.html(pageHTML);
4875
+ }
4876
+ else {
4877
+ popup = app.popup(
4486
4878
  '<div class="popup smart-select-popup smart-select-popup-' + inputName + '">' +
4487
4879
  '<div class="view navbar-fixed">' +
4488
4880
  pageHTML +
4489
4881
  '</div>' +
4490
4882
  '</div>'
4491
4883
  );
4492
- app.initPage($(popup).find('.page'));
4884
+ popup = $(popup);
4885
+ }
4886
+ app.initPage(popup.find('.page'));
4493
4887
  handleInputs(popup);
4494
4888
  }
4495
4889
  else {
4496
- $(document).on('pageInit', pageInit);
4497
- view.router.load({content: pageHTML});
4890
+ $(document).once('pageInit', '.smart-select-page', pageInit);
4891
+ view.router.load({
4892
+ content: pageHTML,
4893
+ reload: reLayout ? true : undefined
4894
+ });
4498
4895
  }
4499
4896
  };
4500
4897
 
@@ -4719,7 +5116,7 @@
4719
5116
 
4720
5117
  if (vl.params.onItemsBeforeInsert) vl.params.onItemsBeforeInsert(vl, vl.fragment);
4721
5118
  vl.ul[0].appendChild(vl.fragment);
4722
- if (vl.params.onItemsAfterInsert) vl.params.onFragmentAfterInsert(vl, vl.fragment);
5119
+ if (vl.params.onItemsAfterInsert) vl.params.onItemsAfterInsert(vl, vl.fragment);
4723
5120
 
4724
5121
  if (typeof forceScrollTop !== 'undefined' && force) {
4725
5122
  vl.pageContent.scrollTop(forceScrollTop, 0);
@@ -4945,7 +5342,7 @@
4945
5342
  var vlists = page.find('.virtual-list');
4946
5343
  if (vlists.length === 0) return;
4947
5344
  for (var i = 0; i < vlists.length; i++) {
4948
- var vlistInstance = vlistInstance[0].f7VirtualList;
5345
+ var vlistInstance = vlists[i].f7VirtualList;
4949
5346
  if (vlistInstance) {
4950
5347
  vlistInstance.update();
4951
5348
  }
@@ -5446,9 +5843,13 @@
5446
5843
  if (app.params.activeState) {
5447
5844
  $('html').addClass('watch-active-state');
5448
5845
  }
5846
+ if (app.device.ios && app.device.webView) {
5847
+ // Strange hack required for iOS 8 webview to work on inputs
5848
+ window.addEventListener('touchstart', function () {});
5849
+ }
5449
5850
 
5450
- var touchStartX, touchStartY, touchStartTime, targetElement, trackClick, activeSelection, scrollParent, lastClickTime, isMoved;
5451
- var activableElement, activeTimeout, needsFastClick;
5851
+ var touchStartX, touchStartY, touchStartTime, targetElement, trackClick, activeSelection, scrollParent, lastClickTime, isMoved, tapHoldFired, tapHoldTimeout;
5852
+ var activableElement, activeTimeout, needsFastClick, needsFastClickTimeOut;
5452
5853
 
5453
5854
  function findActivableElement(e) {
5454
5855
  var target = $(e.target);
@@ -5485,9 +5886,13 @@
5485
5886
  function removeActive(el) {
5486
5887
  activableElement.removeClass('active-state');
5487
5888
  }
5488
-
5889
+ function isFormElement(el) {
5890
+ var nodes = ('input select textarea label').split(' ');
5891
+ if (el.nodeName && nodes.indexOf(el.nodeName.toLowerCase()) >= 0) return true;
5892
+ return false;
5893
+ }
5489
5894
  function androidNeedsBlur(el) {
5490
- var noBlur = ('button checkbox file image radio submit input textarea').split(' ');
5895
+ var noBlur = ('button input textarea select').split(' ');
5491
5896
  if (document.activeElement && el !== document.activeElement && document.activeElement !== document.body) {
5492
5897
  if (noBlur.indexOf(el.nodeName.toLowerCase()) >= 0) {
5493
5898
  return false;
@@ -5554,9 +5959,19 @@
5554
5959
  // Touch Handlers
5555
5960
  function handleTouchStart(e) {
5556
5961
  isMoved = false;
5962
+ tapHoldFired = false;
5557
5963
  if (e.targetTouches.length > 1) {
5558
5964
  return true;
5559
5965
  }
5966
+ if (app.params.tapHold) {
5967
+ if (tapHoldTimeout) clearTimeout(tapHoldTimeout);
5968
+ tapHoldTimeout = setTimeout(function () {
5969
+ tapHoldFired = true;
5970
+ e.preventDefault();
5971
+ $(e.target).trigger('taphold');
5972
+ }, app.params.tapHoldDelay);
5973
+ }
5974
+ if (needsFastClickTimeOut) clearTimeout(needsFastClickTimeOut);
5560
5975
  needsFastClick = targetNeedsFastClick(e.target);
5561
5976
 
5562
5977
  if (!needsFastClick) {
@@ -5629,15 +6044,18 @@
5629
6044
  trackClick = false;
5630
6045
  targetElement = null;
5631
6046
  isMoved = true;
5632
- }
5633
-
5634
- if (app.params.activeState) {
5635
- clearTimeout(activeTimeout);
5636
- removeActive();
6047
+ if (app.params.tapHold) {
6048
+ clearTimeout(tapHoldTimeout);
6049
+ }
6050
+ if (app.params.activeState) {
6051
+ clearTimeout(activeTimeout);
6052
+ removeActive();
6053
+ }
5637
6054
  }
5638
6055
  }
5639
6056
  function handleTouchEnd(e) {
5640
6057
  clearTimeout(activeTimeout);
6058
+ clearTimeout(tapHoldTimeout);
5641
6059
 
5642
6060
  if (!trackClick) {
5643
6061
  if (!activeSelection && needsFastClick) {
@@ -5709,18 +6127,20 @@
5709
6127
 
5710
6128
  function handleClick(e) {
5711
6129
  var allowClick = false;
6130
+
5712
6131
  if (trackClick) {
5713
6132
  targetElement = null;
5714
6133
  trackClick = false;
5715
6134
  return true;
5716
6135
  }
5717
-
5718
6136
  if (e.target.type === 'submit' && e.detail === 0) {
5719
6137
  return true;
5720
6138
  }
5721
- // if (!targetElement) {
5722
- // allowClick = true;
5723
- // }
6139
+ if (!targetElement) {
6140
+ if (!isFormElement(e.target)) {
6141
+ allowClick = true;
6142
+ }
6143
+ }
5724
6144
  if (!needsFastClick) {
5725
6145
  allowClick = true;
5726
6146
  }
@@ -5733,6 +6153,9 @@
5733
6153
  if (!e.cancelable) {
5734
6154
  allowClick = true;
5735
6155
  }
6156
+ if (app.params.tapHold && app.params.tapHoldPreventClicks && tapHoldFired) {
6157
+ allowClick = false;
6158
+ }
5736
6159
  if (!allowClick) {
5737
6160
  e.stopImmediatePropagation();
5738
6161
  e.stopPropagation();
@@ -5746,6 +6169,16 @@
5746
6169
  }
5747
6170
  targetElement = null;
5748
6171
  }
6172
+ needsFastClickTimeOut = setTimeout(function () {
6173
+ needsFastClick = false;
6174
+ }, (app.device.ios || app.device.androidChrome ? 100 : 400));
6175
+
6176
+ if (app.params.tapHold) {
6177
+ tapHoldTimeout = setTimeout(function () {
6178
+ tapHoldFired = false;
6179
+ }, (app.device.ios || app.device.androidChrome ? 100 : 400));
6180
+ }
6181
+
5749
6182
  return allowClick;
5750
6183
  }
5751
6184
  if (app.support.touch) {
@@ -5834,13 +6267,7 @@
5834
6267
  var clicked = $(this);
5835
6268
  var url = clicked.attr('href');
5836
6269
  var isLink = clicked[0].nodeName.toLowerCase() === 'a';
5837
-
5838
- // Str to boolean for data attributes
5839
- function toBoolean(str) {
5840
- if (str === 'false') return false;
5841
- if (str === 'true') return true;
5842
- return undefined;
5843
- }
6270
+
5844
6271
  // Check if link is external
5845
6272
  if (isLink) {
5846
6273
  if (clicked.is(app.params.externalLinks)) {
@@ -5852,6 +6279,9 @@
5852
6279
  }
5853
6280
  }
5854
6281
 
6282
+ // Collect Clicked data- attributes
6283
+ var clickedData = clicked.dataset();
6284
+
5855
6285
  // Smart Select
5856
6286
  if (clicked.hasClass('smart-select')) {
5857
6287
  if (app.smartSelectOpen) app.smartSelectOpen(clicked);
@@ -5864,7 +6294,7 @@
5864
6294
  else app.openPanel('right');
5865
6295
  }
5866
6296
  else {
5867
- if (clicked.attr('data-panel') === 'right') app.openPanel('right');
6297
+ if (clickedData.panel === 'right') app.openPanel('right');
5868
6298
  else app.openPanel('left');
5869
6299
  }
5870
6300
  }
@@ -5879,8 +6309,8 @@
5879
6309
  // Popover
5880
6310
  if (clicked.hasClass('open-popover')) {
5881
6311
  var popover;
5882
- if (clicked.attr('data-popover')) {
5883
- popover = clicked.attr('data-popover');
6312
+ if (clickedData.popover) {
6313
+ popover = clickedData.popover;
5884
6314
  }
5885
6315
  else popover = '.popover';
5886
6316
  app.popover(popover, clicked);
@@ -5891,15 +6321,15 @@
5891
6321
  // Popup
5892
6322
  var popup;
5893
6323
  if (clicked.hasClass('open-popup')) {
5894
- if (clicked.attr('data-popup')) {
5895
- popup = clicked.attr('data-popup');
6324
+ if (clickedData.popup) {
6325
+ popup = clickedData.popup;
5896
6326
  }
5897
6327
  else popup = '.popup';
5898
6328
  app.popup(popup);
5899
6329
  }
5900
6330
  if (clicked.hasClass('close-popup')) {
5901
- if (clicked.attr('data-popup')) {
5902
- popup = clicked.attr('data-popup');
6331
+ if (clickedData.popup) {
6332
+ popup = clickedData.popup;
5903
6333
  }
5904
6334
  else popup = '.popup.modal-in';
5905
6335
  app.closeModal(popup);
@@ -5907,8 +6337,8 @@
5907
6337
  // Login Screen
5908
6338
  var loginScreen;
5909
6339
  if (clicked.hasClass('open-login-screen')) {
5910
- if (clicked.attr('data-login-screen')) {
5911
- loginScreen = clicked.attr('data-login-screen');
6340
+ if (clickedData.loginScreen) {
6341
+ loginScreen = clickedData.loginScreen;
5912
6342
  }
5913
6343
  else loginScreen = '.login-screen';
5914
6344
  app.loginScreen(loginScreen);
@@ -5945,8 +6375,8 @@
5945
6375
  }
5946
6376
  if (clicked.hasClass('open-picker')) {
5947
6377
  var pickerToOpen;
5948
- if (clicked.attr('data-picker')) {
5949
- pickerToOpen = clicked.attr('data-picker');
6378
+ if (clickedData.picker) {
6379
+ pickerToOpen = clickedData.picker;
5950
6380
  }
5951
6381
  else pickerToOpen = '.picker-modal';
5952
6382
  app.pickerModal(pickerToOpen, clicked);
@@ -5956,7 +6386,7 @@
5956
6386
  var isTabLink;
5957
6387
  if (clicked.hasClass('tab-link')) {
5958
6388
  isTabLink = true;
5959
- app.showTab(clicked.attr('data-tab') || clicked.attr('href'), clicked);
6389
+ app.showTab(clickedData.tab || clicked.attr('href'), clicked);
5960
6390
  }
5961
6391
  // Swipeout Close
5962
6392
  if (clicked.hasClass('swipeout-close')) {
@@ -5964,9 +6394,9 @@
5964
6394
  }
5965
6395
  // Swipeout Delete
5966
6396
  if (clicked.hasClass('swipeout-delete')) {
5967
- if (clicked.attr('data-confirm')) {
5968
- var text = clicked.attr('data-confirm');
5969
- var title = clicked.attr('data-confirm-title');
6397
+ if (clickedData.confirm) {
6398
+ var text = clickedData.confirm;
6399
+ var title = clickedData.confirmTitle;
5970
6400
  if (title) {
5971
6401
  app.confirm(text, title, function () {
5972
6402
  app.swipeoutDelete(clicked.parents('.swipeout'));
@@ -5985,13 +6415,13 @@
5985
6415
  }
5986
6416
  // Sortable
5987
6417
  if (clicked.hasClass('toggle-sortable')) {
5988
- app.sortableToggle(clicked.data('sortable'));
6418
+ app.sortableToggle(clickedData.sortable);
5989
6419
  }
5990
6420
  if (clicked.hasClass('open-sortable')) {
5991
- app.sortableOpen(clicked.data('sortable'));
6421
+ app.sortableOpen(clickedData.sortable);
5992
6422
  }
5993
6423
  if (clicked.hasClass('close-sortable')) {
5994
- app.sortableClose(clicked.data('sortable'));
6424
+ app.sortableClose(clickedData.sortable);
5995
6425
  }
5996
6426
  // Accordion
5997
6427
  if (clicked.hasClass('accordion-item-toggle') || (clicked.hasClass('item-link') && clicked.parent().hasClass('accordion-item'))) {
@@ -6010,11 +6440,11 @@
6010
6440
  }
6011
6441
 
6012
6442
  var validUrl = url && url.length > 0 && url !== '#' && !isTabLink;
6013
- var template = clicked.attr('data-template');
6443
+ var template = clickedData.template;
6014
6444
  if (validUrl || clicked.hasClass('back') || template) {
6015
6445
  var view;
6016
- if (clicked.attr('data-view')) {
6017
- view = $(clicked.attr('data-view'))[0].f7View;
6446
+ if (clickedData.view) {
6447
+ view = $(clickedData.view)[0].f7View;
6018
6448
  }
6019
6449
  else {
6020
6450
  view = clicked.parents('.' + app.params.viewClass)[0] && clicked.parents('.' + app.params.viewClass)[0].f7View;
@@ -6044,8 +6474,8 @@
6044
6474
  }
6045
6475
 
6046
6476
  var animatePages;
6047
- if (clicked.attr('data-animatePages')) {
6048
- animatePages = toBoolean(clicked.attr('data-animatePages'));
6477
+ if (typeof clickedData.animatePages !== 'undefined') {
6478
+ animatePages = clickedData.animatePages;
6049
6479
  }
6050
6480
  else {
6051
6481
  if (clicked.hasClass('with-animation')) animatePages = true;
@@ -6054,17 +6484,17 @@
6054
6484
 
6055
6485
  var options = {
6056
6486
  animatePages: animatePages,
6057
- ignoreCache: toBoolean(clicked.attr('data-ignoreCache')),
6058
- force: toBoolean(clicked.attr('data-force')),
6059
- reload: toBoolean(clicked.attr('data-reload')),
6060
- reloadPrevious: toBoolean(clicked.attr('data-reloadPrevious')),
6487
+ ignoreCache: clickedData.ignoreCache,
6488
+ force: clickedData.force,
6489
+ reload: clickedData.reload,
6490
+ reloadPrevious: clickedData.reloadPrevious,
6061
6491
  pageName: pageName,
6062
6492
  url: url
6063
6493
  };
6064
6494
 
6065
6495
  if (app.params.template7Pages) {
6066
- options.contextName = clicked.attr('data-contextName');
6067
- var context = clicked.attr('data-context');
6496
+ options.contextName = clickedData.contextName;
6497
+ var context = clickedData.context;
6068
6498
  if (context) {
6069
6499
  options.context = JSON.parse(context);
6070
6500
  }
@@ -6087,7 +6517,7 @@
6087
6517
  e.preventDefault();
6088
6518
  }
6089
6519
  if (app.support.touch) {
6090
- $(document).on('touchstart', '.panel-overlay, .modal-overlay, .preloader-indicator-overlay, .popup-overlay, .searchbar-overlay', preventScrolling);
6520
+ $(document).on((app.params.fastClicks ? 'touchstart' : 'touchmove'), '.panel-overlay, .modal-overlay, .preloader-indicator-overlay, .popup-overlay, .searchbar-overlay', preventScrolling);
6091
6521
  }
6092
6522
  };
6093
6523
 
@@ -6436,7 +6866,7 @@
6436
6866
  app.swiper = function (container, params) {
6437
6867
  return new Swiper(container, params);
6438
6868
  };
6439
- app.initSwiper = function (pageContainer) {
6869
+ app.initPageSwiper = function (pageContainer) {
6440
6870
  var page = $(pageContainer);
6441
6871
  var swipers = page.find('.swiper-init');
6442
6872
  if (swipers.length === 0) return;
@@ -6454,40 +6884,20 @@
6454
6884
  params = JSON.parse(swiper.data('swiper'));
6455
6885
  }
6456
6886
  else {
6457
- params = {
6458
- initialSlide: parseInt(swiper.data('initialSlide'), 10) || undefined,
6459
- spaceBetween: parseInt(swiper.data('spaceBetween'), 10) || undefined,
6460
- speed: parseInt(swiper.data('speed'), 10) || undefined,
6461
- slidesPerView: swiper.data('slidesPerView') || undefined,
6462
- slidesPerColumn: parseInt(swiper.data('slidesPerColumn'), 10) || undefined,
6463
- centeredSlides: swiper.data('centeredSlides') && (swiper.data('centeredSlides') === 'true' ? true : false),
6464
- direction: swiper.data('direction'),
6465
- pagination: swiper.data('pagination'),
6466
- paginationHide: swiper.data('paginationHide') && (swiper.data('paginationHide') === 'true' ? true : false),
6467
- paginationClickable: swiper.data('paginationClickable') && (swiper.data('paginationClickable') === 'true' ? true : false),
6468
- scrollbar: swiper.data('scrollbar'),
6469
- scrollbarHide: swiper.data('scrollbarHide') && (swiper.data('scrollbarHide') === 'true' ? true : false),
6470
- loop: swiper.data('loop') && (swiper.data('loop') === 'true' ? true : false),
6471
- effect: swiper.data('effect') || 'slide',
6472
- freeMode: swiper.data('freeMode') && (swiper.data('freeMode') === 'true' ? true : false),
6473
- onlyExternal: swiper.data('onlyExternal') && (swiper.data('onlyExternal') === 'true' ? true : false),
6474
- nextButton: swiper.data('nextButton'),
6475
- prevButton: swiper.data('prevButton'),
6476
- autoplay: swiper.data('autoplay')
6477
- };
6887
+ params = swiper.dataset();
6478
6888
  }
6479
6889
  var _slider = app.swiper(swiper[0], params);
6480
6890
  destroySwiperOnRemove(_slider);
6481
6891
  }
6482
6892
  };
6483
- app.reinitSwiper = function (pageContainer) {
6893
+ app.reinitPageSwiper = function (pageContainer) {
6484
6894
  var page = $(pageContainer);
6485
6895
  var sliders = page.find('.swiper-init');
6486
6896
  if (sliders.length === 0) return;
6487
6897
  for (var i = 0; i < sliders.length; i++) {
6488
6898
  var sliderInstance = sliders[0].swiper;
6489
6899
  if (sliderInstance) {
6490
- sliderInstance.onResize();
6900
+ sliderInstance.update(true);
6491
6901
  }
6492
6902
  }
6493
6903
  };
@@ -6519,7 +6929,20 @@
6519
6929
  loop: false,
6520
6930
  lazyLoading: false,
6521
6931
  lazyLoadingInPrevNext: false,
6522
- lazyLoadingOnTransitionStart: false
6932
+ lazyLoadingOnTransitionStart: false,
6933
+ /*
6934
+ Callbacks:
6935
+ onLazyImageLoad(pb, slide, img)
6936
+ onLazyImageReady(pb, slide, img)
6937
+ onOpen(pb)
6938
+ onClose(pb)
6939
+ onSlideChangeStart(swiper)
6940
+ onSlideChangeEnd(swiper)
6941
+ onTap(swiper, e)
6942
+ onClick(swiper, e)
6943
+ onDoubleTap(swiper, e)
6944
+ onSwipeToClose(pb)
6945
+ */
6523
6946
  };
6524
6947
 
6525
6948
  params = params || {};
@@ -6567,7 +6990,7 @@
6567
6990
 
6568
6991
  var photoTemplate = !pb.params.lazyLoading ?
6569
6992
  (pb.params.photoTemplate || '<div class="photo-browser-slide swiper-slide"><span class="photo-browser-zoom-container"><img src="{{url}}"></span></div>') :
6570
- (pb.params.photoLazyTemplate || '<div class="photo-browser-slide photo-browser-slide-lazy swiper-slide"><div class="preloader' + (pb.params.theme === 'dark' ? ' preloader-white' : '') + '"></div><span class="photo-browser-zoom-container"><img data-src="{{url}}"></span></div>');
6993
+ (pb.params.photoLazyTemplate || '<div class="photo-browser-slide photo-browser-slide-lazy swiper-slide"><div class="preloader' + (pb.params.theme === 'dark' ? ' preloader-white' : '') + '"></div><span class="photo-browser-zoom-container"><img data-src="{{url}}" class="swiper-lazy"></span></div>');
6571
6994
 
6572
6995
  var captionsTheme = pb.params.captionsTheme || pb.params.theme;
6573
6996
  var captionsTemplate = pb.params.captionsTemplate || '<div class="photo-browser-captions photo-browser-captions-' + captionsTheme + '">{{captions}}</div>';
@@ -6633,7 +7056,7 @@
6633
7056
  }
6634
7057
  pb.opened = true;
6635
7058
  pb.openIndex = index;
6636
- pb.initialLazyLoaded = false;
7059
+ // pb.initialLazyLoaded = false;
6637
7060
  if (pb.params.type === 'standalone') {
6638
7061
  $('body').append(htmlTemplate);
6639
7062
  }
@@ -6693,45 +7116,6 @@
6693
7116
  $(document).off('pageBeforeRemove', pb.onPageBeforeRemove);
6694
7117
  };
6695
7118
 
6696
- pb.loadImageInSlide = function (swiper, index) {
6697
- if (!swiper || typeof index === 'undefined') return;
6698
- if (swiper.slides.length === 0) return;
6699
-
6700
- var slide = swiper.slides.eq(index);
6701
- if (!slide.hasClass('photo-browser-slide-lazy')) return;
6702
-
6703
- var img = slide.find('img');
6704
- if (img.length === 0) return;
6705
-
6706
- var image = new Image();
6707
- var src = img.attr('data-src');
6708
-
6709
- image.onload = function () {
6710
- img.attr('src', src);
6711
- img.removeAttr('data-src');
6712
- slide.removeClass('photo-browser-slide-lazy').find('.preloader').remove();
6713
- if (pb.params.onImageLoaded) {
6714
- pb.params.onImageLoaded(pb, slide[0], img[0]);
6715
- }
6716
- };
6717
- image.src = src;
6718
-
6719
- if (pb.params.onImageLoad) {
6720
- pb.params.onImageLoad(pb, slide[0], img[0]);
6721
- }
6722
- };
6723
-
6724
- pb.lazyLoading = function (swiper, activeIndex) {
6725
- pb.loadImageInSlide(swiper, activeIndex);
6726
- if (pb.params.lazyLoadingInPrevNext) {
6727
- var nextSlide = swiper.wrapper.find('.swiper-slide-next.photo-browser-slide-lazy');
6728
- if (nextSlide.length > 0) pb.loadImageInSlide(swiper, nextSlide.index());
6729
-
6730
- var prevSlide = swiper.wrapper.find('.swiper-slide-prev.photo-browser-slide-lazy');
6731
- if (prevSlide.length > 0) pb.loadImageInSlide(swiper, prevSlide.index());
6732
- }
6733
- };
6734
-
6735
7119
  pb.onSliderTransitionStart = function (swiper) {
6736
7120
  pb.activeIndex = swiper.activeIndex;
6737
7121
 
@@ -6762,13 +7146,6 @@
6762
7146
  pb.captionsContainer.find('[data-caption-index="' + captionIndex + '"]').addClass('photo-browser-caption-active');
6763
7147
  }
6764
7148
 
6765
- // Lazy loading
6766
- if (pb.params.lazyLoading){
6767
- if (pb.params.lazyLoadingOnTransitionStart || (!pb.params.lazyLoadingOnTransitionStart && !pb.initialLazyLoaded)) {
6768
- pb.initialLazyLoaded = true;
6769
- pb.lazyLoading(swiper, pb.activeIndex);
6770
- }
6771
- }
6772
7149
 
6773
7150
  // Stop Video
6774
7151
  var previousSlideVideo = swiper.slides.eq(swiper.previousIndex).find('video');
@@ -6779,9 +7156,6 @@
6779
7156
  if (pb.params.onSlideChangeStart) pb.params.onSlideChangeStart(swiper);
6780
7157
  };
6781
7158
  pb.onSliderTransitionEnd = function (swiper) {
6782
- if (pb.params.lazyLoading && !pb.params.lazyLoadingOnTransitionStart) {
6783
- pb.lazyLoading(swiper, pb.activeIndex);
6784
- }
6785
7159
  // Reset zoom
6786
7160
  if (pb.params.zoom && gestureSlide && swiper.previousIndex !== swiper.activeIndex) {
6787
7161
  gestureImg.transform('translate3d(0,0,0) scale(1)');
@@ -6817,6 +7191,10 @@
6817
7191
  spaceBetween: pb.params.spaceBetween,
6818
7192
  speed: pb.params.speed,
6819
7193
  loop: pb.params.loop,
7194
+ lazyLoading: pb.params.lazyLoading,
7195
+ lazyLoadingInPrevNext: pb.params.lazyLoadingInPrevNext,
7196
+ lazyLoadingOnTransitionStart: pb.params.lazyLoadingOnTransitionStart,
7197
+ preloadImages: pb.params.lazyLoading ? false : true,
6820
7198
  onTap: function (swiper, e) {
6821
7199
  if (pb.params.onTap) pb.params.onTap(swiper, e);
6822
7200
  },
@@ -6833,6 +7211,13 @@
6833
7211
  },
6834
7212
  onTransitionEnd: function (swiper) {
6835
7213
  pb.onSliderTransitionEnd(swiper);
7214
+ },
7215
+ onLazyImageLoad: function (swiper, slide, img) {
7216
+ if (pb.params.onLazyImageLoad) pb.params.onLazyImageLoad(pb, slide, img);
7217
+ },
7218
+ onLazyImageReady: function (swiper, slide, img) {
7219
+ $(slide).removeClass('photo-browser-slide-lazy');
7220
+ if (pb.params.onLazyImageReady) pb.params.onLazyImageReady(pb, slide, img);
6836
7221
  }
6837
7222
  };
6838
7223
 
@@ -7141,6 +7526,7 @@
7141
7526
  scrollToInput: true,
7142
7527
  inputReadOnly: true,
7143
7528
  convertToPopover: true,
7529
+ onlyInPopover: false,
7144
7530
  toolbar: true,
7145
7531
  toolbarCloseText: 'Done',
7146
7532
  toolbarTemplate:
@@ -7172,13 +7558,16 @@
7172
7558
  // Should be converted to popover
7173
7559
  function isPopover() {
7174
7560
  var toPopover = false;
7175
- if (!p.params.convertToPopover) return toPopover;
7561
+ if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
7176
7562
  if (!p.inline && p.params.input) {
7177
- if (app.device.ios) {
7178
- toPopover = app.device.ipad ? true : false;
7179
- }
7563
+ if (p.params.onlyInPopover) toPopover = true;
7180
7564
  else {
7181
- if ($(window).width() >= 768) toPopover = true;
7565
+ if (app.device.ios) {
7566
+ toPopover = app.device.ipad ? true : false;
7567
+ }
7568
+ else {
7569
+ if ($(window).width() >= 768) toPopover = true;
7570
+ }
7182
7571
  }
7183
7572
  }
7184
7573
  return toPopover;
@@ -7234,6 +7623,7 @@
7234
7623
  var i, j;
7235
7624
  var wrapperHeight, itemHeight, itemsHeight, minTranslate, maxTranslate;
7236
7625
  col.replaceValues = function (values, displayValues) {
7626
+ col.destroyEvents();
7237
7627
  col.values = values;
7238
7628
  col.displayValues = displayValues;
7239
7629
  var newItemsHTML = p.columnHTML(col, true);
@@ -7241,6 +7631,7 @@
7241
7631
  col.items = col.wrapper.find('.picker-item');
7242
7632
  col.calcSize();
7243
7633
  col.setValue(col.values[0], 0, true);
7634
+ col.initEvents();
7244
7635
  };
7245
7636
  col.calcSize = function () {
7246
7637
  if (p.params.rotateEffect) {
@@ -7480,18 +7871,23 @@
7480
7871
  col.setValue(value);
7481
7872
  }
7482
7873
 
7483
- col.container.on(app.touchEvents.start, handleTouchStart);
7484
- col.container.on(app.touchEvents.move, handleTouchMove);
7485
- col.container.on(app.touchEvents.end, handleTouchEnd);
7486
- col.items.on('click', handleClick);
7874
+ col.initEvents = function (detach) {
7875
+ var method = detach ? 'off' : 'on';
7876
+ col.container[method](app.touchEvents.start, handleTouchStart);
7877
+ col.container[method](app.touchEvents.move, handleTouchMove);
7878
+ col.container[method](app.touchEvents.end, handleTouchEnd);
7879
+ col.items[method]('click', handleClick);
7880
+ };
7881
+ col.destroyEvents = function () {
7882
+ col.initEvents(true);
7883
+ };
7487
7884
 
7488
7885
  col.container[0].f7DestroyPickerCol = function () {
7489
- col.container.off(app.touchEvents.start, handleTouchStart);
7490
- col.container.off(app.touchEvents.move, handleTouchMove);
7491
- col.container.off(app.touchEvents.end, handleTouchEnd);
7492
- col.items.off('click', handleClick);
7886
+ col.destroyEvents();
7493
7887
  };
7494
7888
 
7889
+ col.initEvents();
7890
+
7495
7891
  };
7496
7892
  p.destroyPickerCol = function (colContainer) {
7497
7893
  colContainer = $(colContainer);
@@ -7744,6 +8140,7 @@
7744
8140
  scrollToInput: true,
7745
8141
  inputReadOnly: true,
7746
8142
  convertToPopover: true,
8143
+ onlyInPopover: false,
7747
8144
  toolbar: true,
7748
8145
  toolbarCloseText: 'Done',
7749
8146
  toolbarTemplate:
@@ -7788,13 +8185,16 @@
7788
8185
  // Should be converted to popover
7789
8186
  function isPopover() {
7790
8187
  var toPopover = false;
7791
- if (!p.params.convertToPopover) return toPopover;
8188
+ if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
7792
8189
  if (!p.inline && p.params.input) {
7793
- if (app.device.ios) {
7794
- toPopover = app.device.ipad ? true : false;
7795
- }
8190
+ if (p.params.onlyInPopover) toPopover = true;
7796
8191
  else {
7797
- if ($(window).width() >= 768) toPopover = true;
8192
+ if (app.device.ios) {
8193
+ toPopover = app.device.ipad ? true : false;
8194
+ }
8195
+ else {
8196
+ if ($(window).width() >= 768) toPopover = true;
8197
+ }
7798
8198
  }
7799
8199
  }
7800
8200
  return toPopover;
@@ -8267,7 +8667,13 @@
8267
8667
  transition = '';
8268
8668
  if (!p.params.animate) transition = 0;
8269
8669
  }
8270
- var targetDate = new Date(year, month).getTime();
8670
+ var targetDate;
8671
+ if (year < p.currentYear) {
8672
+ targetDate = new Date(year, month + 1, -1).getTime();
8673
+ }
8674
+ else {
8675
+ targetDate = new Date(year, month).getTime();
8676
+ }
8271
8677
  if (p.params.maxDate && targetDate > new Date(p.params.maxDate).getTime()) {
8272
8678
  return false;
8273
8679
  }
@@ -8275,7 +8681,7 @@
8275
8681
  return false;
8276
8682
  }
8277
8683
  var currentDate = new Date(p.currentYear, p.currentMonth).getTime();
8278
- var dir;
8684
+ var dir = targetDate > currentDate ? 'next' : 'prev';
8279
8685
  var newMonthHTML = p.monthHTML(new Date(year, month));
8280
8686
  p.monthsTranslate = p.monthsTranslate || 0;
8281
8687
  var prevTranslate = p.monthsTranslate;
@@ -8284,7 +8690,6 @@
8284
8690
  if (targetDate > currentDate) {
8285
8691
  // To next
8286
8692
  p.monthsTranslate --;
8287
- dir = 'next';
8288
8693
  if (!p.animating) p.months.eq(p.months.length - 1).remove();
8289
8694
  p.wrapper.append(newMonthHTML);
8290
8695
  p.months = p.wrapper.find('.picker-calendar-month');
@@ -8294,7 +8699,6 @@
8294
8699
  else {
8295
8700
  // To prev
8296
8701
  p.monthsTranslate ++;
8297
- dir = 'prev';
8298
8702
  if (!p.animating) p.months.eq(0).remove();
8299
8703
  p.wrapper.prepend(newMonthHTML);
8300
8704
  p.months = p.wrapper.find('.picker-calendar-month');
@@ -8735,6 +9139,11 @@
8735
9139
  $('.page:not(.cached)').each(function () {
8736
9140
  app.initPageWithCallback(this);
8737
9141
  });
9142
+
9143
+ // Init each navbar callbacks
9144
+ $('.navbar:not(.cached)').each(function () {
9145
+ app.initNavbarWithCallback(this);
9146
+ });
8738
9147
 
8739
9148
  // Init resize events
8740
9149
  if (app.initResize) app.initResize();
@@ -8895,6 +9304,7 @@
8895
9304
  for (var i = 0; i < this.length; i++) {
8896
9305
  this[i].removeAttribute(attr);
8897
9306
  }
9307
+ return this;
8898
9308
  },
8899
9309
  prop: function (props, value) {
8900
9310
  if (arguments.length === 1 && typeof props === 'string') {
@@ -8940,6 +9350,32 @@
8940
9350
  return this;
8941
9351
  }
8942
9352
  },
9353
+ dataset: function () {
9354
+ var el = this[0];
9355
+ if (el) {
9356
+ var dataset = {};
9357
+ if (el.dataset) {
9358
+ for (var dataKey in el.dataset) {
9359
+ dataset[dataKey] = el.dataset[dataKey];
9360
+ }
9361
+ }
9362
+ else {
9363
+ for (var i = 0; i < el.attributes.length; i++) {
9364
+ var attr = el.attributes[i];
9365
+ if (attr.name.indexOf('data-') >= 0) {
9366
+ dataset[$.toCamelCase(attr.name.split('data-')[1])] = attr.value;
9367
+ }
9368
+ }
9369
+ }
9370
+ for (var key in dataset) {
9371
+ if (dataset[key] === 'false') dataset[key] = false;
9372
+ else if (dataset[key] === 'true') dataset[key] = true;
9373
+ else if (parseFloat(dataset[key]) === dataset[key] * 1) dataset[key] = dataset[key] * 1;
9374
+ }
9375
+ return dataset;
9376
+ }
9377
+ else return undefined;
9378
+ },
8943
9379
  val: function (value) {
8944
9380
  if (typeof value === 'undefined') {
8945
9381
  if (this[0]) return this[0].value;
@@ -9193,7 +9629,7 @@
9193
9629
  }
9194
9630
  return this;
9195
9631
  },
9196
-
9632
+
9197
9633
  //Dom manipulation
9198
9634
  each: function (callback) {
9199
9635
  for (var i = 0; i < this.length; i++) {
@@ -9226,7 +9662,7 @@
9226
9662
  }
9227
9663
  },
9228
9664
  is: function (selector) {
9229
- if (!this[0]) return false;
9665
+ if (!this[0] || typeof selector === 'undefined') return false;
9230
9666
  var compareWith, i;
9231
9667
  if (typeof selector === 'string') {
9232
9668
  var el = this[0];
@@ -9257,7 +9693,7 @@
9257
9693
  }
9258
9694
  return false;
9259
9695
  }
9260
-
9696
+
9261
9697
  },
9262
9698
  indexOf: function (el) {
9263
9699
  for (var i = 0; i < this.length; i++) {
@@ -9522,9 +9958,9 @@
9522
9958
  var globalAjaxOptions = {};
9523
9959
  $.ajaxSetup = function (options) {
9524
9960
  if (options.type) options.method = options.type;
9525
- for (var option in options) {
9526
- globalAjaxOptions[option] = options[option];
9527
- }
9961
+ $.each(options, function (optionName, optionValue) {
9962
+ globalAjaxOptions[optionName] = optionValue;
9963
+ });
9528
9964
  };
9529
9965
 
9530
9966
  // Ajax
@@ -9547,13 +9983,15 @@
9547
9983
  };
9548
9984
  var callbacks = ['beforeSend', 'error', 'complete', 'success', 'statusCode'];
9549
9985
 
9986
+
9550
9987
  //For jQuery guys
9551
9988
  if (options.type) options.method = options.type;
9552
9989
 
9553
9990
  // Merge global and defaults
9554
- for (var globalOption in globalAjaxOptions) {
9555
- if (callbacks.indexOf(globalOption) < 0) defaults[globalOption] = globalAjaxOptions[globalOption];
9556
- }
9991
+ $.each(globalAjaxOptions, function (globalOptionName, globalOptionValue) {
9992
+ if (callbacks.indexOf(globalOptionName) < 0) defaults[globalOptionName] = globalOptionValue;
9993
+ });
9994
+
9557
9995
  // Function to run XHR callbacks and events
9558
9996
  function fireAjaxCallback (eventName, eventData, callbackName) {
9559
9997
  var a = arguments;
@@ -9567,14 +10005,17 @@
9567
10005
  }
9568
10006
 
9569
10007
  // Merge options and defaults
9570
- for (var prop in defaults) {
9571
- if (!(prop in options)) options[prop] = defaults[prop];
9572
- }
10008
+ $.each(defaults, function (prop, defaultValue) {
10009
+ if (!(prop in options)) options[prop] = defaultValue;
10010
+ });
9573
10011
 
9574
10012
  // Default URL
9575
10013
  if (!options.url) {
9576
10014
  options.url = window.location.toString();
9577
10015
  }
10016
+ // Parameters Prefix
10017
+ var paramsPrefix = options.url.indexOf('?') >= 0 ? '&' : '?';
10018
+
9578
10019
  // UC method
9579
10020
  var _method = options.method.toUpperCase();
9580
10021
  // Data to modify GET URL
@@ -9589,21 +10030,18 @@
9589
10030
  // Should be key=value object
9590
10031
  stringData = $.serializeObject(options.data);
9591
10032
  }
9592
- if (options.url.indexOf('?') >= 0) options.url += '&' + stringData;
9593
- else options.url += '?' + stringData;
10033
+ options.url += paramsPrefix + stringData;
9594
10034
  }
9595
10035
  // JSONP
9596
10036
  if (options.dataType === 'json' && options.url.indexOf('callback=') >= 0) {
9597
-
10037
+
9598
10038
  var callbackName = 'f7jsonp_' + Date.now() + (_jsonpRequests++);
9599
- var requestUrl, abortTimeout;
10039
+ var abortTimeout;
9600
10040
  var callbackSplit = options.url.split('callback=');
10041
+ var requestUrl = callbackSplit[0] + 'callback=' + callbackName;
9601
10042
  if (callbackSplit[1].indexOf('&') >= 0) {
9602
10043
  var addVars = callbackSplit[1].split('&').filter(function (el) { return el.indexOf('=') > 0; }).join('&');
9603
- requestUrl = callbackSplit[0] + 'callback=' + callbackName + (addVars.length > 0 ? '&' + addVars : '');
9604
- }
9605
- else {
9606
- requestUrl = callbackSplit[0] + 'callback=' + callbackName;
10044
+ if (addVars.length > 0) requestUrl += '&' + addVars;
9607
10045
  }
9608
10046
 
9609
10047
  // Create script
@@ -9639,12 +10077,7 @@
9639
10077
  // Cache for GET/HEAD requests
9640
10078
  if (_method === 'GET' || _method === 'HEAD') {
9641
10079
  if (options.cache === false) {
9642
- if (options.url.indexOf('?') >= 0) {
9643
- options.url += ('&_nocache=' + Date.now());
9644
- }
9645
- else {
9646
- options.url += ('?_nocache=' + Date.now());
9647
- }
10080
+ options.url += (paramsPrefix + '_nocache=' + Date.now());
9648
10081
  }
9649
10082
  }
9650
10083
 
@@ -9659,7 +10092,7 @@
9659
10092
 
9660
10093
  // Create POST Data
9661
10094
  var postData = null;
9662
-
10095
+
9663
10096
  if ((_method === 'POST' || _method === 'PUT') && options.data) {
9664
10097
  if (options.processData) {
9665
10098
  var postDataInstances = [ArrayBuffer, Blob, Document, FormData];
@@ -9696,14 +10129,14 @@
9696
10129
  else {
9697
10130
  postData = options.data;
9698
10131
  }
9699
-
10132
+
9700
10133
  }
9701
10134
 
9702
10135
  // Additional headers
9703
10136
  if (options.headers) {
9704
- for (var header in options.headers) {
9705
- xhr.setRequestHeader(header, options.headers[header]);
9706
- }
10137
+ $.each(options.headers, function (headerName, headerCallback) {
10138
+ xhr.setRequestHeader(headerName, headerCallback);
10139
+ });
9707
10140
  }
9708
10141
 
9709
10142
  // Check for crossDomain
@@ -9716,23 +10149,23 @@
9716
10149
  }
9717
10150
 
9718
10151
  if (options.xhrFields) {
9719
- for (var field in options.xhrFields) {
9720
- xhr[field] = options.xhrFields[field];
9721
- }
10152
+ $.each(options.xhrFields, function (fieldName, fieldValue) {
10153
+ xhr[fieldName] = fieldValue;
10154
+ });
9722
10155
  }
9723
10156
 
9724
10157
  var xhrTimeout;
9725
10158
  // Handle XHR
9726
10159
  xhr.onload = function (e) {
9727
10160
  if (xhrTimeout) clearTimeout(xhrTimeout);
9728
- if (xhr.status === 200 || xhr.status === 0) {
9729
- var isSuccess, responseData;
10161
+ if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0) {
10162
+ var responseData;
9730
10163
  if (options.dataType === 'json') {
9731
10164
  try {
9732
10165
  responseData = JSON.parse(xhr.responseText);
9733
10166
  fireAjaxCallback('ajaxSuccess', {xhr: xhr}, 'success', responseData, xhr.status, xhr);
9734
10167
  }
9735
- catch (e) {
10168
+ catch (err) {
9736
10169
  fireAjaxCallback('ajaxError', {xhr: xhr, parseerror: true}, 'error', xhr, 'parseerror');
9737
10170
  }
9738
10171
  }
@@ -9749,7 +10182,7 @@
9749
10182
  }
9750
10183
  fireAjaxCallback('ajaxComplete', {xhr: xhr}, 'complete', xhr, xhr.status);
9751
10184
  };
9752
-
10185
+
9753
10186
  xhr.onerror = function (e) {
9754
10187
  if (xhrTimeout) clearTimeout(xhrTimeout);
9755
10188
  fireAjaxCallback('ajaxError', {xhr: xhr}, 'error', xhr, xhr.status);
@@ -9793,6 +10226,7 @@
9793
10226
  createMethod(methods[i]);
9794
10227
  }
9795
10228
  })();
10229
+
9796
10230
 
9797
10231
  // DOM Library Utilites
9798
10232
  $.parseUrlQuery = function (url) {
@@ -9810,6 +10244,25 @@
9810
10244
  if (Object.prototype.toString.apply(arr) === '[object Array]') return true;
9811
10245
  else return false;
9812
10246
  };
10247
+ $.each = function (obj, callback) {
10248
+ if (typeof obj !== 'object') return;
10249
+ if (!callback) return;
10250
+ var i, prop;
10251
+ if ($.isArray(obj) || obj instanceof Dom7) {
10252
+ // Array
10253
+ for (i = 0; i < obj.length; i++) {
10254
+ callback(i, obj[i]);
10255
+ }
10256
+ }
10257
+ else {
10258
+ // Object
10259
+ for (prop in obj) {
10260
+ if (obj.hasOwnProperty(prop)) {
10261
+ callback(prop, obj[prop]);
10262
+ }
10263
+ }
10264
+ }
10265
+ };
9813
10266
  $.unique = function (arr) {
9814
10267
  var unique = [];
9815
10268
  for (var i = 0; i < arr.length; i++) {
@@ -9817,9 +10270,6 @@
9817
10270
  }
9818
10271
  return unique;
9819
10272
  };
9820
- $.trim = function (str) {
9821
- return str.trim();
9822
- };
9823
10273
  $.serializeObject = function (obj) {
9824
10274
  if (typeof obj === 'string') return obj;
9825
10275
  var resultArray = [];
@@ -9840,7 +10290,14 @@
9840
10290
 
9841
10291
  return resultArray.join(separator);
9842
10292
  };
9843
-
10293
+ $.toCamelCase = function (string) {
10294
+ return string.toLowerCase().replace(/-(.)/g, function(match, group1) {
10295
+ return group1.toUpperCase();
10296
+ });
10297
+ };
10298
+ $.dataset = function (el) {
10299
+ return $(el).dataset();
10300
+ };
9844
10301
  $.getTranslate = function (el, axis) {
9845
10302
  var matrix, curTransform, curStyle, transformMatrix;
9846
10303
 
@@ -9908,7 +10365,11 @@
9908
10365
  $.fn = Dom7.prototype;
9909
10366
 
9910
10367
  // Plugins
9911
- $.fn.scrollTo = function (left, top, duration, easing) {
10368
+ $.fn.scrollTo = function (left, top, duration, easing, callback) {
10369
+ if (arguments.length === 4 && typeof easing === 'function') {
10370
+ callback = easing;
10371
+ easing = undefined;
10372
+ }
9912
10373
  return this.each(function () {
9913
10374
  var el = this;
9914
10375
  var currentTop, currentLeft, maxTop, maxLeft, newTop, newLeft, scrollTop, scrollLeft;
@@ -9971,7 +10432,10 @@
9971
10432
  done = true;
9972
10433
  }
9973
10434
 
9974
- if (done) return;
10435
+ if (done) {
10436
+ if (callback) callback();
10437
+ return;
10438
+ }
9975
10439
  if (animateTop) el.scrollTop = scrollTop;
9976
10440
  if (animateLeft) el.scrollLeft = scrollLeft;
9977
10441
  $.requestAnimationFrame(render);
@@ -9979,21 +10443,29 @@
9979
10443
  $.requestAnimationFrame(render);
9980
10444
  });
9981
10445
  };
9982
- $.fn.scrollTop = function (top, duration, easing) {
10446
+ $.fn.scrollTop = function (top, duration, easing, callback) {
10447
+ if (arguments.length === 3 && typeof easing === 'function') {
10448
+ callback = easing;
10449
+ easing = undefined;
10450
+ }
9983
10451
  var dom = this;
9984
10452
  if (typeof top === 'undefined') {
9985
10453
  if (dom.length > 0) return dom[0].scrollTop;
9986
10454
  else return null;
9987
10455
  }
9988
- return dom.scrollTo(undefined, top, duration, easing);
10456
+ return dom.scrollTo(undefined, top, duration, easing, callback);
9989
10457
  };
9990
- $.fn.scrollLeft = function (left, duration, easing) {
10458
+ $.fn.scrollLeft = function (left, duration, easing, callback) {
10459
+ if (arguments.length === 3 && typeof easing === 'function') {
10460
+ callback = easing;
10461
+ easing = undefined;
10462
+ }
9991
10463
  var dom = this;
9992
10464
  if (typeof left === 'undefined') {
9993
10465
  if (dom.length > 0) return dom[0].scrollLeft;
9994
10466
  else return null;
9995
10467
  }
9996
- return dom.scrollTo(left, undefined, duration, easing);
10468
+ return dom.scrollTo(left, undefined, duration, easing, callback);
9997
10469
  };
9998
10470
 
9999
10471
  return $;
@@ -10324,28 +10796,50 @@
10324
10796
  else return function () {return ''; };
10325
10797
  }
10326
10798
  function getCompileVar(name, ctx) {
10327
- var parents, variable, context;
10328
- if (name.indexOf('@global') >= 0) {
10329
- variable = '(Template7.global && Template7.global.' + (name.split('@global.')[1]) + ')';
10799
+ var variable, parts, levelsUp = 0, initialCtx = ctx;
10800
+ if (name.indexOf('../') === 0) {
10801
+ levelsUp = name.split('../').length - 1;
10802
+ var newDepth = ctx.split('_')[1] - levelsUp;
10803
+ ctx = 'ctx_' + (newDepth >= 1 ? newDepth : 1);
10804
+ parts = name.split('../')[levelsUp].split('.');
10805
+ }
10806
+ else if (name.indexOf('@global') === 0) {
10807
+ ctx = 'Template7.global';
10808
+ parts = name.split('@global.')[1].split('.');
10330
10809
  }
10331
- else if (name.indexOf('@') >= 0) {
10332
- variable = '(data && data.' + name.replace('@', '') + ')';
10810
+ else if (name.indexOf('@root') === 0) {
10811
+ ctx = 'ctx_1';
10812
+ parts = name.split('@root.')[1].split('.');
10333
10813
  }
10334
10814
  else {
10335
- if (name.indexOf('.') > 0) {
10336
- if (name.indexOf('this') === 0) variable = name.replace('this', ctx);
10337
- else variable = ctx + '.' + name;
10338
- }
10339
- else if (name.indexOf('../') === 0) {
10340
- var levelUp = name.split('../').length - 1;
10341
- var newName = name.split('../')[name.split('../').length - 1];
10342
- var newDepth = ctx.split('_')[1] - levelUp;
10343
- variable = 'ctx_' + (newDepth >= 1 ? newDepth : 1) + '.' + newName;
10815
+ parts = name.split('.');
10816
+ }
10817
+ variable = ctx;
10818
+ for (var i = 0; i < parts.length; i++) {
10819
+ var part = parts[i];
10820
+ if (part.indexOf('@') === 0) {
10821
+ if (i > 0) {
10822
+ variable += '[(data && data.' + part.replace('@', '') + ')]';
10823
+ }
10824
+ else {
10825
+ variable = '(data && data.' + name.replace('@', '') + ')';
10826
+ }
10344
10827
  }
10345
10828
  else {
10346
- variable = name === 'this' ? ctx : ctx + '.' + name;
10829
+ if (isFinite(part)) {
10830
+ variable += '[' + part + ']';
10831
+ }
10832
+ else {
10833
+ if (part.indexOf('this') === 0) {
10834
+ variable = part.replace('this', ctx);
10835
+ }
10836
+ else {
10837
+ variable += '.' + part;
10838
+ }
10839
+ }
10347
10840
  }
10348
10841
  }
10842
+
10349
10843
  return variable;
10350
10844
  }
10351
10845
  function getCompiledArguments(contextArray, ctx) {
@@ -10365,7 +10859,6 @@
10365
10859
  throw new Error('Template7: Template must be a string');
10366
10860
  }
10367
10861
  var blocks = stringToBlocks(template);
10368
-
10369
10862
  if (blocks.length === 0) {
10370
10863
  return function () { return ''; };
10371
10864
  }
@@ -10395,7 +10888,7 @@
10395
10888
  if (block.type === 'helper') {
10396
10889
  if (block.helperName in t.helpers) {
10397
10890
  compiledArguments = getCompiledArguments(block.contextName, ctx);
10398
- 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) + '});';
10891
+ 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: ctx_1});';
10399
10892
  }
10400
10893
  else {
10401
10894
  if (block.contextName.length > 0) {
@@ -10405,9 +10898,9 @@
10405
10898
  variable = getCompileVar(block.helperName, ctx);
10406
10899
  resultString += 'if (' + variable + ') {';
10407
10900
  resultString += 'if (isArray(' + variable + ')) {';
10408
- 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) + '});';
10901
+ 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: ctx_1});';
10409
10902
  resultString += '}else {';
10410
- 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) + '});';
10903
+ 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: ctx_1});';
10411
10904
  resultString += '}}';
10412
10905
  }
10413
10906
  }
@@ -10474,6 +10967,32 @@
10474
10967
  'join': function (context, options) {
10475
10968
  if (isFunction(context)) { context = context.call(this); }
10476
10969
  return context.join(options.hash.delimiter || options.hash.delimeter);
10970
+ },
10971
+ 'js': function (expression, options) {
10972
+ var func;
10973
+ if (expression.indexOf('return')>=0) {
10974
+ func = '(function(){'+expression+'})';
10975
+ }
10976
+ else {
10977
+ func = '(function(){return ('+expression+')})';
10978
+ }
10979
+ return eval.call(this, func).call(this);
10980
+ },
10981
+ 'js_compare': function (expression, options) {
10982
+ var func;
10983
+ if (expression.indexOf('return')>=0) {
10984
+ func = '(function(){'+expression+'})';
10985
+ }
10986
+ else {
10987
+ func = '(function(){return ('+expression+')})';
10988
+ }
10989
+ var condition = eval.call(this, func).call(this);
10990
+ if (condition) {
10991
+ return options.fn(this, options.data);
10992
+ }
10993
+ else {
10994
+ return options.inverse(this, options.data);
10995
+ }
10477
10996
  }
10478
10997
  }
10479
10998
  };
@@ -10508,6 +11027,7 @@
10508
11027
  Swiper
10509
11028
  ===========================*/
10510
11029
  window.Swiper = function (container, params) {
11030
+ if (!(this instanceof Swiper)) return new Swiper(container, params);
10511
11031
  var defaults = {
10512
11032
  direction: 'horizontal',
10513
11033
  touchEventsTarget: 'container',
@@ -10522,6 +11042,10 @@
10522
11042
  freeModeMomentumRatio: 1,
10523
11043
  freeModeMomentumBounce: true,
10524
11044
  freeModeMomentumBounceRatio: 1,
11045
+ // Set wrapper width
11046
+ setWrapperSize: false,
11047
+ // Virtual Translate
11048
+ virtualTranslate: false,
10525
11049
  // Effects
10526
11050
  effect: 'slide', // 'slide' or 'fade' or 'cube' or 'coverflow'
10527
11051
  coverflow: {
@@ -10537,6 +11061,11 @@
10537
11061
  shadowOffset: 20,
10538
11062
  shadowScale: 0.94
10539
11063
  },
11064
+ fade: {
11065
+ crossFade: false
11066
+ },
11067
+ // Parallax
11068
+ parallax: false,
10540
11069
  // Scrollbar
10541
11070
  scrollbar: null,
10542
11071
  scrollbarHide: true,
@@ -10569,6 +11098,7 @@
10569
11098
  pagination: null,
10570
11099
  paginationClickable: false,
10571
11100
  paginationHide: false,
11101
+ paginationBulletRender: null,
10572
11102
  // Resistance
10573
11103
  resistance: true,
10574
11104
  resistanceRatio: 0.85,
@@ -10577,15 +11107,19 @@
10577
11107
  prevButton: null,
10578
11108
  // Progress
10579
11109
  watchSlidesProgress: false,
10580
- watchVisibility: false,
11110
+ watchSlidesVisibility: false,
10581
11111
  // Cursor
10582
11112
  grabCursor: false,
10583
11113
  // Clicks
10584
11114
  preventClicks: true,
10585
11115
  preventClicksPropagation: true,
10586
- releaseFormElements: true,
10587
11116
  slideToClickedSlide: false,
11117
+ // Lazy Loading
11118
+ lazyLoading: false,
11119
+ lazyLoadingInPrevNext: false,
11120
+ lazyLoadingOnTransitionStart: false,
10588
11121
  // Images
11122
+ preloadImages: true,
10589
11123
  updateOnImagesReady: true,
10590
11124
  // loop
10591
11125
  loop: false,
@@ -10615,32 +11149,45 @@
10615
11149
  // Observer
10616
11150
  observer: false,
10617
11151
  observeParents: false,
11152
+ // Accessibility
11153
+ a11y: false,
11154
+ prevSlideMessage: 'Previous slide',
11155
+ nextSlideMessage: 'Next slide',
11156
+ firstSlideMessage: 'This is the first slide',
11157
+ lastSlideMessage: 'This is the last slide',
10618
11158
  // Callbacks
10619
- runCallbacksOnInit: true
11159
+ runCallbacksOnInit: true,
10620
11160
  /*
10621
11161
  Callbacks:
10622
11162
  onInit: function (swiper)
10623
11163
  onDestroy: function (swiper)
10624
- onClick: function (swiper, e)
10625
- onTap: function (swiper, e)
10626
- onDoubleTap: function (swiper, e)
10627
- onSliderMove: function (swiper, e)
10628
- onSlideChangeStart: function (swiper)
10629
- onSlideChangeEnd: function (swiper)
10630
- onTransitionStart: function (swiper)
10631
- onTransitionEnd: function (swiper)
10632
- onImagesReady: function (swiper)
10633
- onProgress: function (swiper, progress)
10634
- onTouchStart: function (swiper, e)
10635
- onTouchMove: function (swiper, e)
10636
- onTouchMoveOpposite: function (swiper, e)
10637
- onTouchEnd: function (swiper, e)
10638
- onReachBeginning: function (swiper)
10639
- onReachEnd: function (swiper)
10640
- onSetTransition: function (swiper, duration)
10641
- onSetTranslate: function (swiper, translate)
11164
+ onClick: function (swiper, e)
11165
+ onTap: function (swiper, e)
11166
+ onDoubleTap: function (swiper, e)
11167
+ onSliderMove: function (swiper, e)
11168
+ onSlideChangeStart: function (swiper)
11169
+ onSlideChangeEnd: function (swiper)
11170
+ onTransitionStart: function (swiper)
11171
+ onTransitionEnd: function (swiper)
11172
+ onImagesReady: function (swiper)
11173
+ onProgress: function (swiper, progress)
11174
+ onTouchStart: function (swiper, e)
11175
+ onTouchMove: function (swiper, e)
11176
+ onTouchMoveOpposite: function (swiper, e)
11177
+ onTouchEnd: function (swiper, e)
11178
+ onReachBeginning: function (swiper)
11179
+ onReachEnd: function (swiper)
11180
+ onSetTransition: function (swiper, duration)
11181
+ onSetTranslate: function (swiper, translate)
11182
+ onAutoplayStart: function (swiper)
11183
+ onAutoplayStop: function (swiper),
11184
+ onLazyImageLoad: function (swiper, slide, image)
11185
+ onLazyImageReady: function (swiper, slide, image)
10642
11186
  */
11187
+
10643
11188
  };
11189
+ var initalVirtualTranslate = params && params.virtualTranslate;
11190
+
10644
11191
  params = params || {};
10645
11192
  for (var def in defaults) {
10646
11193
  if (typeof params[def] === 'undefined') {
@@ -10660,6 +11207,9 @@
10660
11207
 
10661
11208
  // Params
10662
11209
  s.params = params;
11210
+
11211
+ // Classname
11212
+ s.classNames = [];
10663
11213
  /*=========================
10664
11214
  Dom Library and plugins
10665
11215
  ===========================*/
@@ -10672,6 +11222,8 @@
10672
11222
  }
10673
11223
  if (!$) return;
10674
11224
 
11225
+ // Export it to Swiper instance
11226
+ s.$ = $;
10675
11227
  /*=========================
10676
11228
  Preparation - Define Container, Wrapper and Pagination
10677
11229
  ===========================*/
@@ -10688,24 +11240,31 @@
10688
11240
  s.container[0].swiper = s;
10689
11241
  s.container.data('swiper', s);
10690
11242
 
10691
- s.container.addClass('swiper-container-' + s.params.direction);
11243
+ s.classNames.push('swiper-container-' + s.params.direction);
10692
11244
 
10693
11245
  if (s.params.freeMode) {
10694
- s.container.addClass('swiper-container-free-mode');
11246
+ s.classNames.push('swiper-container-free-mode');
11247
+ }
11248
+ if (!s.support.flexbox) {
11249
+ s.classNames.push('swiper-container-no-flexbox');
11250
+ s.params.slidesPerColumn = 1;
11251
+ }
11252
+ // Enable slides progress when required
11253
+ if (s.params.parallax || s.params.watchSlidesVisibility) {
11254
+ s.params.watchSlidesProgress = true;
10695
11255
  }
10696
-
10697
11256
  // Coverflow / 3D
10698
11257
  if (['cube', 'coverflow'].indexOf(s.params.effect) >= 0) {
10699
11258
  if (s.support.transforms3d) {
10700
11259
  s.params.watchSlidesProgress = true;
10701
- s.container.addClass('swiper-container-3d');
11260
+ s.classNames.push('swiper-container-3d');
10702
11261
  }
10703
11262
  else {
10704
11263
  s.params.effect = 'slide';
10705
11264
  }
10706
11265
  }
10707
11266
  if (s.params.effect !== 'slide') {
10708
- s.container.addClass('swiper-container-' + s.params.effect);
11267
+ s.classNames.push('swiper-container-' + s.params.effect);
10709
11268
  }
10710
11269
  if (s.params.effect === 'cube') {
10711
11270
  s.params.resistanceRatio = 0;
@@ -10714,10 +11273,18 @@
10714
11273
  s.params.slidesPerGroup = 1;
10715
11274
  s.params.centeredSlides = false;
10716
11275
  s.params.spaceBetween = 0;
11276
+ s.params.virtualTranslate = true;
11277
+ s.params.setWrapperSize = false;
10717
11278
  }
10718
11279
  if (s.params.effect === 'fade') {
11280
+ s.params.slidesPerView = 1;
11281
+ s.params.slidesPerColumn = 1;
11282
+ s.params.slidesPerGroup = 1;
10719
11283
  s.params.watchSlidesProgress = true;
10720
11284
  s.params.spaceBetween = 0;
11285
+ if (typeof initalVirtualTranslate === 'undefined') {
11286
+ s.params.virtualTranslate = true;
11287
+ }
10721
11288
  }
10722
11289
 
10723
11290
  // Grab Cursor
@@ -10743,16 +11310,32 @@
10743
11310
 
10744
11311
  // RTL
10745
11312
  s.rtl = isH() && (s.container[0].dir.toLowerCase() === 'rtl' || s.container.css('direction') === 'rtl');
10746
- if (s.rtl) s.container.addClass('swiper-container-rtl');
11313
+ if (s.rtl) {
11314
+ s.classNames.push('swiper-container-rtl');
11315
+ }
11316
+
10747
11317
  // Wrong RTL support
10748
11318
  if (s.rtl) {
10749
11319
  s.wrongRTL = s.wrapper.css('display') === '-webkit-box';
10750
11320
  }
10751
11321
 
10752
- // Translate
10753
- s.translate = 0;
10754
-
10755
- // Progress
11322
+ // Columns
11323
+ if (s.params.slidesPerColumn > 1) {
11324
+ s.classNames.push('swiper-container-multirow');
11325
+ }
11326
+
11327
+ // Check for Android
11328
+ if (s.device.android) {
11329
+ s.classNames.push('swiper-container-android');
11330
+ }
11331
+
11332
+ // Add classes
11333
+ s.container.addClass(s.classNames.join(' '));
11334
+
11335
+ // Translate
11336
+ s.translate = 0;
11337
+
11338
+ // Progress
10756
11339
  s.progress = 0;
10757
11340
 
10758
11341
  // Velocity
@@ -10778,11 +11361,6 @@
10778
11361
  s.params.allowSwipeToNext = s.params.allowSwipeToPrev = true;
10779
11362
  };
10780
11363
 
10781
- // Columns
10782
- if (s.params.slidesPerColumn > 1) {
10783
- s.container.addClass('swiper-container-multirow');
10784
- }
10785
-
10786
11364
 
10787
11365
  /*=========================
10788
11366
  Set grab cursor
@@ -10799,19 +11377,12 @@
10799
11377
  s.imagesToLoad = [];
10800
11378
  s.imagesLoaded = 0;
10801
11379
 
10802
- function loadImage(img) {
10803
- var image, src;
10804
- var onReady = function () {
10805
- if (typeof s === 'undefined' || s === null) return;
10806
- if (s.imagesLoaded !== undefined) s.imagesLoaded++;
10807
- if (s.imagesLoaded === s.imagesToLoad.length) {
10808
- s.update();
10809
- if (s.params.onImagesReady) s.params.onImagesReady(s);
10810
- }
10811
- };
10812
-
10813
- if (!img.complete) {
10814
- src = (img.currentSrc || img.getAttribute('src'));
11380
+ s.loadImage = function (imgElement, src, checkForComplete, callback) {
11381
+ var image;
11382
+ function onReady () {
11383
+ if (callback) callback();
11384
+ }
11385
+ if (!imgElement.complete || !checkForComplete) {
10815
11386
  if (src) {
10816
11387
  image = new Image();
10817
11388
  image.onload = onReady;
@@ -10824,12 +11395,19 @@
10824
11395
  } else {//image already loaded...
10825
11396
  onReady();
10826
11397
  }
10827
- }
11398
+ };
10828
11399
  s.preloadImages = function () {
10829
11400
  s.imagesToLoad = s.container.find('img');
10830
-
11401
+ function _onReady() {
11402
+ if (typeof s === 'undefined' || s === null) return;
11403
+ if (s.imagesLoaded !== undefined) s.imagesLoaded++;
11404
+ if (s.imagesLoaded === s.imagesToLoad.length) {
11405
+ if (s.params.updateOnImagesReady) s.update();
11406
+ s.emit('onImagesReady', s);
11407
+ }
11408
+ }
10831
11409
  for (var i = 0; i < s.imagesToLoad.length; i++) {
10832
- loadImage(s.imagesToLoad[i]);
11410
+ s.loadImage(s.imagesToLoad[i], (s.imagesToLoad[i].currentSrc || s.imagesToLoad[i].getAttribute('src')), true, _onReady);
10833
11411
  }
10834
11412
  };
10835
11413
 
@@ -10862,10 +11440,10 @@
10862
11440
  }
10863
11441
  s.startAutoplay = function () {
10864
11442
  if (typeof s.autoplayTimeoutId !== 'undefined') return false;
10865
- if (!s.params.autoplay) return;
10866
- if (s.autoplaying) return;
11443
+ if (!s.params.autoplay) return false;
11444
+ if (s.autoplaying) return false;
10867
11445
  s.autoplaying = true;
10868
- if (s.params.onAutoplayStart) s.params.onAutoplayStart(s);
11446
+ s.emit('onAutoplayStart', s);
10869
11447
  autoplay();
10870
11448
  };
10871
11449
  s.stopAutoplay = function (internal) {
@@ -10873,7 +11451,7 @@
10873
11451
  if (s.autoplayTimeoutId) clearTimeout(s.autoplayTimeoutId);
10874
11452
  s.autoplaying = false;
10875
11453
  s.autoplayTimeoutId = undefined;
10876
- if (s.params.onAutoplayStop) s.params.onAutoplayStop(s);
11454
+ s.emit('onAutoplayStop', s);
10877
11455
  };
10878
11456
  s.pauseAutoplay = function (speed) {
10879
11457
  if (s.autoplayPaused) return;
@@ -10886,7 +11464,12 @@
10886
11464
  else {
10887
11465
  s.wrapper.transitionEnd(function () {
10888
11466
  s.autoplayPaused = false;
10889
- autoplay();
11467
+ if (!s.autoplaying) {
11468
+ s.stopAutoplay();
11469
+ }
11470
+ else {
11471
+ autoplay();
11472
+ }
10890
11473
  });
10891
11474
  }
10892
11475
  };
@@ -10913,7 +11496,7 @@
10913
11496
  s.snapGrid = [];
10914
11497
  s.slidesGrid = [];
10915
11498
  s.slidesSizesGrid = [];
10916
-
11499
+
10917
11500
  var spaceBetween = s.params.spaceBetween,
10918
11501
  slidePosition = 0,
10919
11502
  i,
@@ -10923,7 +11506,7 @@
10923
11506
  spaceBetween = parseFloat(spaceBetween.replace('%', '')) / 100 * s.size;
10924
11507
  }
10925
11508
 
10926
- s.virtualWidth = -spaceBetween;
11509
+ s.virtualSize = -spaceBetween;
10927
11510
  // reset margins
10928
11511
  if (s.rtl) s.slides.css({marginLeft: '', marginTop: ''});
10929
11512
  else s.slides.css({marginRight: '', marginBottom: ''});
@@ -10966,7 +11549,7 @@
10966
11549
  slidesPerRow = slidesNumberEvenToRows / slidesPerColumn;
10967
11550
  row = Math.floor(i / slidesPerRow);
10968
11551
  column = i - row * slidesPerRow;
10969
-
11552
+
10970
11553
  }
10971
11554
  slide
10972
11555
  .css({
@@ -10974,7 +11557,7 @@
10974
11557
  })
10975
11558
  .attr('data-swiper-column', column)
10976
11559
  .attr('data-swiper-row', row);
10977
-
11560
+
10978
11561
  }
10979
11562
  if (slide.css('display') === 'none') continue;
10980
11563
  if (s.params.slidesPerView === 'auto') {
@@ -10991,8 +11574,8 @@
10991
11574
  }
10992
11575
  s.slides[i].swiperSlideSize = slideSize;
10993
11576
  s.slidesSizesGrid.push(slideSize);
10994
-
10995
-
11577
+
11578
+
10996
11579
  if (s.params.centeredSlides) {
10997
11580
  slidePosition = slidePosition + slideSize / 2 + prevSlideSize / 2 + spaceBetween;
10998
11581
  if (i === 0) slidePosition = slidePosition - s.size / 2 - spaceBetween;
@@ -11006,28 +11589,33 @@
11006
11589
  slidePosition = slidePosition + slideSize + spaceBetween;
11007
11590
  }
11008
11591
 
11009
- s.virtualWidth += slideSize + spaceBetween;
11592
+ s.virtualSize += slideSize + spaceBetween;
11010
11593
 
11011
11594
  prevSlideSize = slideSize;
11012
11595
 
11013
11596
  index ++;
11014
11597
  }
11015
- s.virtualWidth = Math.max(s.virtualWidth, s.size);
11598
+ s.virtualSize = Math.max(s.virtualSize, s.size);
11016
11599
 
11017
11600
  var newSlidesGrid;
11018
11601
 
11019
- if (s.rtl && s.wrongRTL && (s.params.effect === 'slide' || s.params.effect === 'coverflow')) {
11020
- s.wrapper.css({width: s.virtualWidth + s.params.spaceBetween + 'px'});
11602
+ if (
11603
+ s.rtl && s.wrongRTL && (s.params.effect === 'slide' || s.params.effect === 'coverflow')) {
11604
+ s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
11605
+ }
11606
+ if (!s.support.flexbox || s.params.setWrapperSize) {
11607
+ if (isH()) s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
11608
+ else s.wrapper.css({height: s.virtualSize + s.params.spaceBetween + 'px'});
11021
11609
  }
11022
11610
 
11023
11611
  if (s.params.slidesPerColumn > 1) {
11024
- s.virtualWidth = (slideSize + s.params.spaceBetween) * slidesNumberEvenToRows;
11025
- s.virtualWidth = Math.ceil(s.virtualWidth / s.params.slidesPerColumn) - s.params.spaceBetween;
11026
- s.wrapper.css({width: s.virtualWidth + s.params.spaceBetween + 'px'});
11612
+ s.virtualSize = (slideSize + s.params.spaceBetween) * slidesNumberEvenToRows;
11613
+ s.virtualSize = Math.ceil(s.virtualSize / s.params.slidesPerColumn) - s.params.spaceBetween;
11614
+ s.wrapper.css({width: s.virtualSize + s.params.spaceBetween + 'px'});
11027
11615
  if (s.params.centeredSlides) {
11028
11616
  newSlidesGrid = [];
11029
11617
  for (i = 0; i < s.snapGrid.length; i++) {
11030
- if (s.snapGrid[i] < s.virtualWidth + s.snapGrid[0]) newSlidesGrid.push(s.snapGrid[i]);
11618
+ if (s.snapGrid[i] < s.virtualSize + s.snapGrid[0]) newSlidesGrid.push(s.snapGrid[i]);
11031
11619
  }
11032
11620
  s.snapGrid = newSlidesGrid;
11033
11621
  }
@@ -11037,17 +11625,17 @@
11037
11625
  if (!s.params.centeredSlides) {
11038
11626
  newSlidesGrid = [];
11039
11627
  for (i = 0; i < s.snapGrid.length; i++) {
11040
- if (s.snapGrid[i] <= s.virtualWidth - s.size) {
11628
+ if (s.snapGrid[i] <= s.virtualSize - s.size) {
11041
11629
  newSlidesGrid.push(s.snapGrid[i]);
11042
11630
  }
11043
11631
  }
11044
11632
  s.snapGrid = newSlidesGrid;
11045
- if (Math.floor(s.virtualWidth - s.size) > Math.floor(s.snapGrid[s.snapGrid.length - 1])) {
11046
- s.snapGrid.push(s.virtualWidth - s.size);
11633
+ if (Math.floor(s.virtualSize - s.size) > Math.floor(s.snapGrid[s.snapGrid.length - 1])) {
11634
+ s.snapGrid.push(s.virtualSize - s.size);
11047
11635
  }
11048
11636
  }
11049
11637
  if (s.snapGrid.length === 0) s.snapGrid = [0];
11050
-
11638
+
11051
11639
  if (s.params.spaceBetween !== 0) {
11052
11640
  if (isH()) {
11053
11641
  if (s.rtl) s.slides.css({marginLeft: spaceBetween + 'px'});
@@ -11087,7 +11675,7 @@
11087
11675
  var slide = s.slides[i];
11088
11676
  var slideCenterOffset = (s.params.centeredSlides === true) ? slide.swiperSlideSize / 2 : 0;
11089
11677
  var slideProgress = (offsetCenter - slide.swiperSlideOffset - slideCenterOffset) / (slide.swiperSlideSize + s.params.spaceBetween);
11090
- if (s.params.watchVisibility) {
11678
+ if (s.params.watchSlidesVisibility) {
11091
11679
  var slideBefore = -(offsetCenter - slide.swiperSlideOffset - slideCenterOffset);
11092
11680
  var slideAfter = slideBefore + s.slidesSizesGrid[i];
11093
11681
  var isVisible =
@@ -11105,19 +11693,21 @@
11105
11693
  if (typeof translate === 'undefined') {
11106
11694
  translate = s.translate || 0;
11107
11695
  }
11108
- s.progress = (translate - s.minTranslate()) / (s.maxTranslate() - s.minTranslate());
11109
- s.isBeginning = s.isEnd = false;
11110
-
11111
- if (s.progress <= 0) {
11112
- s.isBeginning = true;
11113
- if (s.params.onReachBeginning) s.params.onReachBeginning(s);
11696
+ var translatesDiff = s.maxTranslate() - s.minTranslate();
11697
+ if (translatesDiff === 0) {
11698
+ s.progress = 0;
11699
+ s.isBeginning = s.isEnd = true;
11114
11700
  }
11115
- if (s.progress >= 1) {
11116
- s.isEnd = true;
11117
- if (s.params.onReachEnd) s.params.onReachEnd(s);
11701
+ else {
11702
+ s.progress = (translate - s.minTranslate()) / (translatesDiff);
11703
+ s.isBeginning = s.progress <= 0;
11704
+ s.isEnd = s.progress >= 1;
11118
11705
  }
11706
+ if (s.isBeginning) s.emit('onReachBeginning', s);
11707
+ if (s.isEnd) s.emit('onReachEnd', s);
11708
+
11119
11709
  if (s.params.watchSlidesProgress) s.updateSlidesProgress(translate);
11120
- if (s.params.onProgress) s.params.onProgress(s, s.progress);
11710
+ s.emit('onProgress', s, s.progress);
11121
11711
  };
11122
11712
  s.updateActiveIndex = function () {
11123
11713
  var translate = s.rtl ? s.translate : -s.translate;
@@ -11172,10 +11762,11 @@
11172
11762
  s.bullets.removeClass(s.params.bulletActiveClass);
11173
11763
  var bulletIndex;
11174
11764
  if (s.params.loop) {
11175
- bulletIndex = s.activeIndex - s.loopedSlides;
11765
+ bulletIndex = Math.ceil(s.activeIndex - s.loopedSlides)/s.params.slidesPerGroup;
11176
11766
  if (bulletIndex > s.slides.length - 1 - s.loopedSlides * 2) {
11177
11767
  bulletIndex = bulletIndex - (s.slides.length - s.loopedSlides * 2);
11178
11768
  }
11769
+ if (bulletIndex > s.bullets.length - 1) bulletIndex = bulletIndex - s.bullets.length;
11179
11770
  }
11180
11771
  else {
11181
11772
  if (typeof s.snapIndex !== 'undefined') {
@@ -11185,18 +11776,37 @@
11185
11776
  bulletIndex = s.activeIndex || 0;
11186
11777
  }
11187
11778
  }
11188
- s.bullets.eq(bulletIndex).addClass(s.params.bulletActiveClass);
11779
+ if (s.paginationContainer.length > 1) {
11780
+ s.bullets.each(function () {
11781
+ if ($(this).index() === bulletIndex) $(this).addClass(s.params.bulletActiveClass);
11782
+ });
11783
+ }
11784
+ else {
11785
+ s.bullets.eq(bulletIndex).addClass(s.params.bulletActiveClass);
11786
+ }
11189
11787
  }
11190
11788
 
11191
11789
  // Next/active buttons
11192
11790
  if (!s.params.loop) {
11193
11791
  if (s.params.prevButton) {
11194
- if (s.isBeginning) $(s.params.prevButton).addClass(s.params.buttonDisabledClass);
11195
- else $(s.params.prevButton).removeClass(s.params.buttonDisabledClass);
11792
+ if (s.isBeginning) {
11793
+ $(s.params.prevButton).addClass(s.params.buttonDisabledClass);
11794
+ if (s.params.a11y && s.a11y) s.a11y.disable($(s.params.prevButton));
11795
+ }
11796
+ else {
11797
+ $(s.params.prevButton).removeClass(s.params.buttonDisabledClass);
11798
+ if (s.params.a11y && s.a11y) s.a11y.enable($(s.params.prevButton));
11799
+ }
11196
11800
  }
11197
11801
  if (s.params.nextButton) {
11198
- if (s.isEnd) $(s.params.nextButton).addClass(s.params.buttonDisabledClass);
11199
- else $(s.params.nextButton).removeClass(s.params.buttonDisabledClass);
11802
+ if (s.isEnd) {
11803
+ $(s.params.nextButton).addClass(s.params.buttonDisabledClass);
11804
+ if (s.params.a11y && s.a11y) s.a11y.disable($(s.params.nextButton));
11805
+ }
11806
+ else {
11807
+ $(s.params.nextButton).removeClass(s.params.buttonDisabledClass);
11808
+ if (s.params.a11y && s.a11y) s.a11y.enable($(s.params.nextButton));
11809
+ }
11200
11810
  }
11201
11811
  }
11202
11812
  };
@@ -11208,9 +11818,14 @@
11208
11818
  if (!s.params.pagination) return;
11209
11819
  if (s.paginationContainer && s.paginationContainer.length > 0) {
11210
11820
  var bulletsHTML = '';
11211
- var numberOfBullets = s.params.loop ? s.slides.length - s.loopedSlides * 2 : s.snapGrid.length;
11821
+ var numberOfBullets = s.params.loop ? Math.ceil((s.slides.length - s.loopedSlides * 2) / s.params.slidesPerGroup) : s.snapGrid.length;
11212
11822
  for (var i = 0; i < numberOfBullets; i++) {
11213
- bulletsHTML += '<span class="' + s.params.bulletClass + '"></span>';
11823
+ if (s.params.paginationBulletRender) {
11824
+ bulletsHTML += s.params.paginationBulletRender(i, s.params.bulletClass);
11825
+ }
11826
+ else {
11827
+ bulletsHTML += '<span class="' + s.params.bulletClass + '"></span>';
11828
+ }
11214
11829
  }
11215
11830
  s.paginationContainer.html(bulletsHTML);
11216
11831
  s.bullets = s.paginationContainer.find('.' + s.params.bulletClass);
@@ -11228,19 +11843,29 @@
11228
11843
  if (s.params.scrollbar && s.scrollbar) {
11229
11844
  s.scrollbar.set();
11230
11845
  }
11846
+ function forceSetTranslate() {
11847
+ newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate());
11848
+ s.setWrapperTranslate(newTranslate);
11849
+ s.updateActiveIndex();
11850
+ s.updateClasses();
11851
+ }
11231
11852
  if (updateTranslate) {
11232
11853
  var translated, newTranslate;
11233
- if (s.isEnd) {
11234
- translated = s.slideTo(s.slides.length - 1, 0, false, true);
11854
+ if (s.params.freeMode) {
11855
+ forceSetTranslate();
11235
11856
  }
11236
11857
  else {
11237
- translated = s.slideTo(s.activeIndex, 0, false, true);
11238
- }
11239
- if (!translated) {
11240
- newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate());
11241
- s.setWrapperTranslate(newTranslate);
11858
+ if (s.params.slidesPerView === 'auto' && s.isEnd && !s.params.centeredSlides) {
11859
+ translated = s.slideTo(s.slides.length - 1, 0, false, true);
11860
+ }
11861
+ else {
11862
+ translated = s.slideTo(s.activeIndex, 0, false, true);
11863
+ }
11864
+ if (!translated) {
11865
+ forceSetTranslate();
11866
+ }
11242
11867
  }
11243
-
11868
+
11244
11869
  }
11245
11870
  };
11246
11871
 
@@ -11251,17 +11876,26 @@
11251
11876
  s.updateContainerSize();
11252
11877
  s.updateSlidesSize();
11253
11878
  s.updateProgress();
11254
- s.updateClasses();
11255
- if (s.params.slidesPerView === 'auto') s.updatePagination();
11879
+ if (s.params.slidesPerView === 'auto' || s.params.freeMode) s.updatePagination();
11256
11880
  if (s.params.scrollbar && s.scrollbar) {
11257
11881
  s.scrollbar.set();
11258
11882
  }
11259
- if (s.isEnd) {
11260
- s.slideTo(s.slides.length - 1, 0, false, true);
11883
+ if (s.params.freeMode) {
11884
+ var newTranslate = Math.min(Math.max(s.translate, s.maxTranslate()), s.minTranslate());
11885
+ s.setWrapperTranslate(newTranslate);
11886
+ s.updateActiveIndex();
11887
+ s.updateClasses();
11261
11888
  }
11262
11889
  else {
11263
- s.slideTo(s.activeIndex, 0, false, true);
11890
+ s.updateClasses();
11891
+ if (s.params.slidesPerView === 'auto' && s.isEnd && !s.params.centeredSlides) {
11892
+ s.slideTo(s.slides.length - 1, 0, false, true);
11893
+ }
11894
+ else {
11895
+ s.slideTo(s.activeIndex, 0, false, true);
11896
+ }
11264
11897
  }
11898
+
11265
11899
  };
11266
11900
 
11267
11901
  /*=========================
@@ -11272,48 +11906,68 @@
11272
11906
  var desktopEvents = ['mousedown', 'mousemove', 'mouseup'];
11273
11907
  if (window.navigator.pointerEnabled) desktopEvents = ['pointerdown', 'pointermove', 'pointerup'];
11274
11908
  else if (window.navigator.msPointerEnabled) desktopEvents = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp'];
11275
-
11276
11909
  s.touchEvents = {
11277
11910
  start : s.support.touch || !s.params.simulateTouch ? 'touchstart' : desktopEvents[0],
11278
11911
  move : s.support.touch || !s.params.simulateTouch ? 'touchmove' : desktopEvents[1],
11279
11912
  end : s.support.touch || !s.params.simulateTouch ? 'touchend' : desktopEvents[2]
11280
11913
  };
11281
11914
 
11915
+
11282
11916
  // WP8 Touch Events Fix
11283
11917
  if (window.navigator.pointerEnabled || window.navigator.msPointerEnabled) {
11284
11918
  (s.params.touchEventsTarget === 'container' ? s.container : s.wrapper).addClass('swiper-wp8-' + s.params.direction);
11285
11919
  }
11286
11920
 
11287
11921
  // Attach/detach events
11288
- s.events = function (detach) {
11922
+ s.initEvents = function (detach) {
11289
11923
  var actionDom = detach ? 'off' : 'on';
11290
- var actionVanilla = detach ? 'removeEventListener' : 'addEventListener';
11291
- var touchEventsTarget = s.params.touchEventsTarget === 'container' ? s.container : s.wrapper;
11292
- var target = s.support.touch ? touchEventsTarget : $(document);
11924
+ var action = detach ? 'removeEventListener' : 'addEventListener';
11925
+ var touchEventsTarget = s.params.touchEventsTarget === 'container' ? s.container[0] : s.wrapper[0];
11926
+ var target = s.support.touch ? touchEventsTarget : document;
11293
11927
 
11294
11928
  var moveCapture = s.params.nested ? true : false;
11295
11929
 
11296
- // Touch events
11297
- touchEventsTarget[0][actionVanilla](s.touchEvents.start, s.onTouchStart, false);
11298
- target[0][actionVanilla](s.touchEvents.move, s.onTouchMove, moveCapture);
11299
- target[0][actionVanilla](s.touchEvents.end, s.onTouchEnd, false);
11300
- window[actionVanilla]('resize', s.onResize);
11930
+ //Touch Events
11931
+ if (s.browser.ie) {
11932
+ touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false);
11933
+ target[action](s.touchEvents.move, s.onTouchMove, moveCapture);
11934
+ target[action](s.touchEvents.end, s.onTouchEnd, false);
11935
+ }
11936
+ else {
11937
+ if (s.support.touch) {
11938
+ touchEventsTarget[action](s.touchEvents.start, s.onTouchStart, false);
11939
+ touchEventsTarget[action](s.touchEvents.move, s.onTouchMove, moveCapture);
11940
+ touchEventsTarget[action](s.touchEvents.end, s.onTouchEnd, false);
11941
+ }
11942
+ if (params.simulateTouch && !s.device.ios && !s.device.android) {
11943
+ touchEventsTarget[action]('mousedown', s.onTouchStart, false);
11944
+ target[action]('mousemove', s.onTouchMove, moveCapture);
11945
+ target[action]('mouseup', s.onTouchEnd, false);
11946
+ }
11947
+ }
11948
+ window[action]('resize', s.onResize);
11301
11949
 
11302
11950
  // Next, Prev, Index
11303
- if (s.params.nextButton) $(s.params.nextButton)[actionDom]('click', s.onClickNext);
11304
- if (s.params.prevButton) $(s.params.prevButton)[actionDom]('click', s.onClickPrev);
11951
+ if (s.params.nextButton) {
11952
+ $(s.params.nextButton)[actionDom]('click', s.onClickNext);
11953
+ if (s.params.a11y && s.a11y) $(s.params.nextButton)[actionDom]('keydown', s.a11y.onEnterKey);
11954
+ }
11955
+ if (s.params.prevButton) {
11956
+ $(s.params.prevButton)[actionDom]('click', s.onClickPrev);
11957
+ if (s.params.a11y && s.a11y) $(s.params.prevButton)[actionDom]('keydown', s.a11y.onEnterKey);
11958
+ }
11305
11959
  if (s.params.pagination && s.params.paginationClickable) {
11306
11960
  $(s.paginationContainer)[actionDom]('click', '.' + s.params.bulletClass, s.onClickIndex);
11307
11961
  }
11308
11962
 
11309
11963
  // Prevent Links Clicks
11310
- if (s.params.preventClicks || s.params.preventClicksPropagation) touchEventsTarget[0][actionVanilla]('click', s.preventClicks, true);
11964
+ if (s.params.preventClicks || s.params.preventClicksPropagation) touchEventsTarget[action]('click', s.preventClicks, true);
11311
11965
  };
11312
11966
  s.attachEvents = function (detach) {
11313
- s.events();
11967
+ s.initEvents();
11314
11968
  };
11315
11969
  s.detachEvents = function () {
11316
- s.events(true);
11970
+ s.initEvents(true);
11317
11971
  };
11318
11972
 
11319
11973
  /*=========================
@@ -11410,19 +12064,19 @@
11410
12064
  }
11411
12065
  };
11412
12066
 
11413
- var isTouched,
11414
- isMoved,
11415
- touchStartTime,
11416
- isScrolling,
11417
- currentTranslate,
11418
- startTranslate,
12067
+ var isTouched,
12068
+ isMoved,
12069
+ touchStartTime,
12070
+ isScrolling,
12071
+ currentTranslate,
12072
+ startTranslate,
11419
12073
  allowThresholdMove,
11420
12074
  // Form elements to match
11421
12075
  formElements = 'input, select, textarea, button',
11422
12076
  // Last click time
11423
12077
  lastClickTime = Date.now(), clickTimeout,
11424
12078
  //Velocities
11425
- velocities = [],
12079
+ velocities = [],
11426
12080
  allowMomentumBounce;
11427
12081
 
11428
12082
  // Animating Flag
@@ -11438,16 +12092,22 @@
11438
12092
  };
11439
12093
 
11440
12094
  // Touch handlers
12095
+ var isTouchEvent, startMoving;
11441
12096
  s.onTouchStart = function (e) {
11442
12097
  if (e.originalEvent) e = e.originalEvent;
11443
- if (e.type === 'mousedown' && 'which' in e && e.which === 3) return;
11444
- if (s.params.noSwiping && findElementInEvent(e, '.' + s.params.noSwipingClass)) return;
12098
+ isTouchEvent = e.type === 'touchstart';
12099
+ if (!isTouchEvent && 'which' in e && e.which === 3) return;
12100
+ if (s.params.noSwiping && findElementInEvent(e, '.' + s.params.noSwipingClass)) {
12101
+ s.allowClick = true;
12102
+ return;
12103
+ }
11445
12104
  if (s.params.swipeHandler) {
11446
12105
  if (!findElementInEvent(e, s.params.swipeHandler)) return;
11447
12106
  }
11448
12107
  isTouched = true;
11449
12108
  isMoved = false;
11450
12109
  isScrolling = undefined;
12110
+ startMoving = undefined;
11451
12111
  s.touches.startX = s.touches.currentX = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
11452
12112
  s.touches.startY = s.touches.currentY = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
11453
12113
  touchStartTime = Date.now();
@@ -11458,44 +12118,62 @@
11458
12118
  if (e.type !== 'touchstart') {
11459
12119
  var preventDefault = true;
11460
12120
  if ($(e.target).is(formElements)) preventDefault = false;
11461
- if (document.activeElement && $(document.activeElement).is(formElements)) document.activeElement.blur();
12121
+ if (document.activeElement && $(document.activeElement).is(formElements)) {
12122
+ document.activeElement.blur();
12123
+ }
11462
12124
  if (preventDefault) {
11463
12125
  e.preventDefault();
11464
12126
  }
11465
12127
  }
11466
- if (s.params.onTouchStart) s.params.onTouchStart(s, e);
12128
+ s.emit('onTouchStart', s, e);
11467
12129
  };
11468
12130
 
11469
12131
  s.onTouchMove = function (e) {
11470
12132
  if (e.originalEvent) e = e.originalEvent;
12133
+ if (isTouchEvent && e.type === 'mousemove') return;
11471
12134
  if (e.preventedByNestedSwiper) return;
11472
12135
  if (s.params.onlyExternal) {
11473
12136
  isMoved = true;
11474
12137
  s.allowClick = false;
11475
12138
  return;
11476
12139
  }
11477
- if (s.params.onTouchMove) s.params.onTouchMove(s, e);
11478
- s.allowClick = false;
12140
+ if (isTouchEvent && document.activeElement) {
12141
+ if (e.target === document.activeElement && $(e.target).is(formElements)) {
12142
+ isMoved = true;
12143
+ s.allowClick = false;
12144
+ return;
12145
+ }
12146
+ }
12147
+
12148
+ s.emit('onTouchMove', s, e);
12149
+
11479
12150
  if (e.targetTouches && e.targetTouches.length > 1) return;
11480
-
12151
+
11481
12152
  s.touches.currentX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
11482
12153
  s.touches.currentY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
11483
12154
 
11484
12155
  if (typeof isScrolling === 'undefined') {
11485
12156
  var touchAngle = Math.atan2(Math.abs(s.touches.currentY - s.touches.startY), Math.abs(s.touches.currentX - s.touches.startX)) * 180 / Math.PI;
11486
12157
  isScrolling = isH() ? touchAngle > s.params.touchAngle : (90 - touchAngle > s.params.touchAngle);
11487
- // isScrolling = !!(isScrolling || Math.abs(touchesCurrent.y - touchesStart.y) > Math.abs(touchesCurrent.x - touchesStart.x));
11488
12158
  }
11489
- if (isScrolling && s.params.onTouchMoveOpposite) {
11490
- s.params.onTouchMoveOpposite(s, e);
12159
+ if (isScrolling) {
12160
+ s.emit('onTouchMoveOpposite', s, e);
12161
+ }
12162
+ if (typeof startMoving === 'undefined' && s.browser.ieTouch) {
12163
+ if (s.touches.currentX !== s.touches.startX || s.touches.currentY !== s.touches.startY) {
12164
+ startMoving = true;
12165
+ }
11491
12166
  }
11492
12167
  if (!isTouched) return;
11493
12168
  if (isScrolling) {
11494
12169
  isTouched = false;
11495
12170
  return;
11496
12171
  }
11497
- if (s.params.onSliderMove) s.params.onSliderMove(s, e);
11498
-
12172
+ if (!startMoving && s.browser.ieTouch) {
12173
+ return;
12174
+ }
12175
+ s.allowClick = false;
12176
+ s.emit('onSliderMove', s, e);
11499
12177
  e.preventDefault();
11500
12178
  if (s.params.touchMoveStopPropagation && !s.params.nested) {
11501
12179
  e.stopPropagation();
@@ -11505,7 +12183,7 @@
11505
12183
  if (params.loop) {
11506
12184
  s.fixLoop();
11507
12185
  }
11508
- startTranslate = s.params.effect === 'cube' ? ((s.rtl ? -s.translate: s.translate) || 0) : s.getWrapperTranslate();
12186
+ startTranslate = s.getWrapperTranslate();
11509
12187
  s.setWrapperTransition(0);
11510
12188
  if (s.animating) {
11511
12189
  s.wrapper.trigger('webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd');
@@ -11546,7 +12224,7 @@
11546
12224
  disableParentSwiper = false;
11547
12225
  if (s.params.resistance) currentTranslate = s.maxTranslate() + 1 - Math.pow(s.maxTranslate() - startTranslate - diff, s.params.resistanceRatio);
11548
12226
  }
11549
-
12227
+
11550
12228
  if (disableParentSwiper) {
11551
12229
  e.preventedByNestedSwiper = true;
11552
12230
  }
@@ -11558,7 +12236,7 @@
11558
12236
  if (!s.params.allowSwipeToPrev && s.swipeDirection === 'prev' && currentTranslate > startTranslate) {
11559
12237
  currentTranslate = startTranslate;
11560
12238
  }
11561
-
12239
+
11562
12240
  if (!s.params.followFinger) return;
11563
12241
 
11564
12242
  // Threshold
@@ -11602,9 +12280,8 @@
11602
12280
  };
11603
12281
  s.onTouchEnd = function (e) {
11604
12282
  if (e.originalEvent) e = e.originalEvent;
11605
- if (s.params.onTouchEnd) s.params.onTouchEnd(s, e);
12283
+ s.emit('onTouchEnd', s, e);
11606
12284
  if (!isTouched) return;
11607
-
11608
12285
  //Return Grab Cursor
11609
12286
  if (s.params.grabCursor && isMoved && isTouched) {
11610
12287
  s.container[0].style.cursor = 'move';
@@ -11620,7 +12297,7 @@
11620
12297
  // Tap, doubleTap, Click
11621
12298
  if (s.allowClick) {
11622
12299
  s.updateClickedSlide(e);
11623
- if (s.params.onTap) s.params.onTap(s, e);
12300
+ s.emit('onTap', s, e);
11624
12301
  if (timeDiff < 300 && (touchEndTime - lastClickTime) > 300) {
11625
12302
  if (clickTimeout) clearTimeout(clickTimeout);
11626
12303
  clickTimeout = setTimeout(function () {
@@ -11628,15 +12305,13 @@
11628
12305
  if (s.params.paginationHide && s.paginationContainer.length > 0 && !$(e.target).hasClass(s.params.bulletClass)) {
11629
12306
  s.paginationContainer.toggleClass(s.params.paginationHiddenClass);
11630
12307
  }
11631
- if (s.params.onClick) s.params.onClick(s, e);
12308
+ s.emit('onClick', s, e);
11632
12309
  }, 300);
11633
-
12310
+
11634
12311
  }
11635
12312
  if (timeDiff < 300 && (touchEndTime - lastClickTime) < 300) {
11636
12313
  if (clickTimeout) clearTimeout(clickTimeout);
11637
- if (s.params.onDoubleTap) {
11638
- s.params.onDoubleTap(s, e);
11639
- }
12314
+ s.emit('onDoubleTap', s, e);
11640
12315
  }
11641
12316
  }
11642
12317
 
@@ -11667,7 +12342,7 @@
11667
12342
  s.slideTo(s.slides.length - 1);
11668
12343
  return;
11669
12344
  }
11670
-
12345
+
11671
12346
  if (s.params.freeModeMomentum) {
11672
12347
  if (velocities.length > 1) {
11673
12348
  var lastMoveEvent = velocities.pop(), velocityEvent = velocities.pop();
@@ -11735,24 +12410,24 @@
11735
12410
 
11736
12411
  if (s.params.freeModeMomentumBounce && doBounce) {
11737
12412
  s.updateProgress(afterBouncePosition);
11738
- s.setWrapperTranslate(newPosition);
11739
12413
  s.setWrapperTransition(momentumDuration);
12414
+ s.setWrapperTranslate(newPosition);
11740
12415
  s.onTransitionStart();
11741
12416
  s.animating = true;
11742
12417
  s.wrapper.transitionEnd(function () {
11743
12418
  if (!allowMomentumBounce) return;
11744
- if (s.params.onMomentumBounce) s.params.onMomentumBounce(s);
12419
+ s.emit('onMomentumBounce', s);
11745
12420
 
11746
- s.setWrapperTranslate(afterBouncePosition);
11747
12421
  s.setWrapperTransition(s.params.speed);
12422
+ s.setWrapperTranslate(afterBouncePosition);
11748
12423
  s.wrapper.transitionEnd(function () {
11749
12424
  s.onTransitionEnd();
11750
12425
  });
11751
12426
  });
11752
12427
  } else if (s.velocity) {
11753
12428
  s.updateProgress(newPosition);
11754
- s.setWrapperTranslate(newPosition);
11755
12429
  s.setWrapperTransition(momentumDuration);
12430
+ s.setWrapperTranslate(newPosition);
11756
12431
  s.onTransitionStart();
11757
12432
  if (!s.animating) {
11758
12433
  s.animating = true;
@@ -11760,11 +12435,11 @@
11760
12435
  s.onTransitionEnd();
11761
12436
  });
11762
12437
  }
11763
-
12438
+
11764
12439
  } else {
11765
12440
  s.updateProgress(newPosition);
11766
12441
  }
11767
-
12442
+
11768
12443
  s.updateActiveIndex();
11769
12444
  }
11770
12445
  if (!s.params.freeModeMomentum || timeDiff >= s.params.longSwipesMs) {
@@ -11793,7 +12468,7 @@
11793
12468
 
11794
12469
  // Find current slide size
11795
12470
  var ratio = (currentPos - s.slidesGrid[stopIndex]) / groupSize;
11796
-
12471
+
11797
12472
  if (timeDiff > s.params.longSwipesMs) {
11798
12473
  // Long touches
11799
12474
  if (!s.params.longSwipes) {
@@ -11837,7 +12512,7 @@
11837
12512
  if (slideIndex < 0) slideIndex = 0;
11838
12513
  s.snapIndex = Math.floor(slideIndex / s.params.slidesPerGroup);
11839
12514
  if (s.snapIndex >= s.snapGrid.length) s.snapIndex = s.snapGrid.length - 1;
11840
-
12515
+
11841
12516
  var translate = - s.snapGrid[s.snapIndex];
11842
12517
 
11843
12518
  // Stop autoplay
@@ -11863,17 +12538,17 @@
11863
12538
  if (typeof speed === 'undefined') speed = s.params.speed;
11864
12539
  s.previousIndex = s.activeIndex || 0;
11865
12540
  s.activeIndex = slideIndex;
11866
-
12541
+
11867
12542
  if (translate === s.translate) {
11868
12543
  s.updateClasses();
11869
12544
  return false;
11870
12545
  }
11871
- if (runCallbacks) s.onTransitionStart();
12546
+ s.onTransitionStart(runCallbacks);
11872
12547
  var translateX = isH() ? translate : 0, translateY = isH() ? 0 : translate;
11873
12548
  if (speed === 0) {
11874
12549
  s.setWrapperTransition(0);
11875
12550
  s.setWrapperTranslate(translate);
11876
- if (runCallbacks) s.onTransitionEnd();
12551
+ s.onTransitionEnd(runCallbacks);
11877
12552
  }
11878
12553
  else {
11879
12554
  s.setWrapperTransition(speed);
@@ -11881,24 +12556,40 @@
11881
12556
  if (!s.animating) {
11882
12557
  s.animating = true;
11883
12558
  s.wrapper.transitionEnd(function () {
11884
- if (runCallbacks) s.onTransitionEnd();
12559
+ s.onTransitionEnd(runCallbacks);
11885
12560
  });
11886
12561
  }
11887
-
12562
+
11888
12563
  }
11889
12564
  s.updateClasses();
11890
12565
  return true;
11891
12566
  };
11892
12567
 
11893
- s.onTransitionStart = function () {
11894
- if (s.params.onTransitionStart) s.params.onTransitionStart(s);
11895
- if (s.params.onSlideChangeStart && s.activeIndex !== s.previousIndex) s.params.onSlideChangeStart(s);
12568
+ s.onTransitionStart = function (runCallbacks) {
12569
+ if (typeof runCallbacks === 'undefined') runCallbacks = true;
12570
+ if (s.lazy) s.lazy.onTransitionStart();
12571
+ if (runCallbacks) {
12572
+ s.emit('onTransitionStart', s);
12573
+ if (s.activeIndex !== s.previousIndex) {
12574
+ s.emit('onSlideChangeStart', s);
12575
+ }
12576
+ }
11896
12577
  };
11897
- s.onTransitionEnd = function () {
12578
+ s.onTransitionEnd = function (runCallbacks) {
11898
12579
  s.animating = false;
11899
12580
  s.setWrapperTransition(0);
11900
- if (s.params.onTransitionEnd) s.params.onTransitionEnd(s);
11901
- if (s.params.onSlideChangeEnd && s.activeIndex !== s.previousIndex) s.params.onSlideChangeEnd(s);
12581
+ if (typeof runCallbacks === 'undefined') runCallbacks = true;
12582
+ if (s.lazy) s.lazy.onTransitionEnd();
12583
+ if (runCallbacks) {
12584
+ s.emit('onTransitionEnd', s);
12585
+ if (s.activeIndex !== s.previousIndex) {
12586
+ s.emit('onSlideChangeEnd', s);
12587
+ }
12588
+ }
12589
+ if (s.params.hashnav && s.hashnav) {
12590
+ s.hashnav.setHash();
12591
+ }
12592
+
11902
12593
  };
11903
12594
  s.slideNext = function (runCallbacks, speed, internal) {
11904
12595
  if (s.params.loop) {
@@ -11933,16 +12624,19 @@
11933
12624
  ===========================*/
11934
12625
  s.setWrapperTransition = function (duration, byController) {
11935
12626
  s.wrapper.transition(duration);
11936
- if (s.params.onSetTransition) s.params.onSetTransition(s, duration);
11937
12627
  if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
11938
12628
  s.effects[s.params.effect].setTransition(duration);
11939
12629
  }
12630
+ if (s.params.parallax && s.parallax) {
12631
+ s.parallax.setTransition(duration);
12632
+ }
11940
12633
  if (s.params.scrollbar && s.scrollbar) {
11941
12634
  s.scrollbar.setTransition(duration);
11942
12635
  }
11943
12636
  if (s.params.control && s.controller) {
11944
12637
  s.controller.setTransition(duration, byController);
11945
12638
  }
12639
+ s.emit('onSetTransition', s, duration);
11946
12640
  };
11947
12641
  s.setWrapperTranslate = function (translate, updateActiveIndex, byController) {
11948
12642
  var x = 0, y = 0, z = 0;
@@ -11952,24 +12646,27 @@
11952
12646
  else {
11953
12647
  y = translate;
11954
12648
  }
11955
-
11956
- if (s.support.transforms3d) s.wrapper.transform('translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)');
11957
- else s.wrapper.transform('translate(' + x + 'px, ' + y + 'px)');
12649
+ if (!s.params.virtualTranslate) {
12650
+ if (s.support.transforms3d) s.wrapper.transform('translate3d(' + x + 'px, ' + y + 'px, ' + z + 'px)');
12651
+ else s.wrapper.transform('translate(' + x + 'px, ' + y + 'px)');
12652
+ }
12653
+
11958
12654
  s.translate = isH() ? x : y;
12655
+
11959
12656
  if (updateActiveIndex) s.updateActiveIndex();
11960
12657
  if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
11961
12658
  s.effects[s.params.effect].setTranslate(s.translate);
11962
12659
  }
12660
+ if (s.params.parallax && s.parallax) {
12661
+ s.parallax.setTranslate(s.translate);
12662
+ }
11963
12663
  if (s.params.scrollbar && s.scrollbar) {
11964
12664
  s.scrollbar.setTranslate(s.translate);
11965
12665
  }
11966
12666
  if (s.params.control && s.controller) {
11967
12667
  s.controller.setTranslate(s.translate, byController);
11968
12668
  }
11969
- if (s.params.hashnav && s.hashnav) {
11970
- s.hashnav.setHash();
11971
- }
11972
- if (s.params.onSetTranslate) s.params.onSetTranslate(s, s.translate);
12669
+ s.emit('onSetTranslate', s, s.translate);
11973
12670
  };
11974
12671
 
11975
12672
  s.getTranslate = function (el, axis) {
@@ -11980,6 +12677,10 @@
11980
12677
  axis = 'x';
11981
12678
  }
11982
12679
 
12680
+ if (s.params.virtualTranslate) {
12681
+ return s.rtl ? -s.translate : s.translate;
12682
+ }
12683
+
11983
12684
  curStyle = window.getComputedStyle(el, null);
11984
12685
  if (window.WebKitCSSMatrix) {
11985
12686
  // Some old versions of Webkit choke when 'none' is passed; pass
@@ -12034,9 +12735,10 @@
12034
12735
  var observer = new ObserverFunc(function (mutations) {
12035
12736
  mutations.forEach(function (mutation) {
12036
12737
  s.onResize();
12738
+ s.emit('onObserverUpdate', s, mutation);
12037
12739
  });
12038
12740
  });
12039
-
12741
+
12040
12742
  observer.observe(target, {
12041
12743
  attributes: typeof options.attributes === 'undefined' ? true : options.attributes,
12042
12744
  childList: typeof options.childList === 'undefined' ? true : options.childList,
@@ -12096,6 +12798,7 @@
12096
12798
  };
12097
12799
  s.destroyLoop = function () {
12098
12800
  s.wrapper.children('.' + s.params.slideClass + '.' + s.params.slideDuplicateClass).remove();
12801
+ s.slides.removeAttr('data-swiper-slide-index');
12099
12802
  };
12100
12803
  s.fixLoop = function () {
12101
12804
  var newIndex;
@@ -12196,19 +12899,27 @@
12196
12899
  ===========================*/
12197
12900
  s.effects = {
12198
12901
  fade: {
12902
+ fadeIndex: null,
12199
12903
  setTranslate: function () {
12200
12904
  for (var i = 0; i < s.slides.length; i++) {
12201
12905
  var slide = s.slides.eq(i);
12202
12906
  var offset = slide[0].swiperSlideOffset;
12203
- var tx = -offset - s.translate;
12907
+ var tx = -offset;
12908
+ if (!s.params.virtualTranslate) tx = tx - s.translate;
12204
12909
  var ty = 0;
12205
12910
  if (!isH()) {
12206
12911
  ty = tx;
12207
12912
  tx = 0;
12208
12913
  }
12914
+ var slideOpacity = s.params.fade.crossFade ?
12915
+ Math.max(1 - Math.abs(slide[0].progress), 0) :
12916
+ 1 + Math.min(Math.max(slide[0].progress, -1), 0);
12917
+ if (slideOpacity > 0 && slideOpacity < 1) {
12918
+ s.effects.fade.fadeIndex = i;
12919
+ }
12209
12920
  slide
12210
12921
  .css({
12211
- opacity: 1 + Math.min(Math.max(slide[0].progress, -1), 0)
12922
+ opacity: slideOpacity
12212
12923
  })
12213
12924
  .transform('translate3d(' + tx + 'px, ' + ty + 'px, 0px)');
12214
12925
 
@@ -12216,6 +12927,15 @@
12216
12927
  },
12217
12928
  setTransition: function (duration) {
12218
12929
  s.slides.transition(duration);
12930
+ if (s.params.virtualTranslate && duration !== 0) {
12931
+ var fadeIndex = s.effects.fade.fadeIndex !== null ? s.effects.fade.fadeIndex : s.activeIndex;
12932
+ s.slides.eq(fadeIndex).transitionEnd(function () {
12933
+ var triggerEvents = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'];
12934
+ for (var i = 0; i < triggerEvents.length; i++) {
12935
+ s.wrapper.trigger(triggerEvents[i]);
12936
+ }
12937
+ });
12938
+ }
12219
12939
  }
12220
12940
  },
12221
12941
  cube: {
@@ -12376,8 +13096,8 @@
12376
13096
  }
12377
13097
 
12378
13098
  //Set correct perspective for IE10
12379
- if (window.navigator.pointerEnabled || window.navigator.msPointerEnabled) {
12380
- var ws = s.wrapper.style;
13099
+ if (s.browser.ie) {
13100
+ var ws = s.wrapper[0].style;
12381
13101
  ws.perspectiveOrigin = center + 'px 50%';
12382
13102
  }
12383
13103
  },
@@ -12387,6 +13107,78 @@
12387
13107
  }
12388
13108
  };
12389
13109
 
13110
+ /*=========================
13111
+ Images Lazy Loading
13112
+ ===========================*/
13113
+ s.lazy = {
13114
+ initialImageLoaded: false,
13115
+ loadImageInSlide: function (index) {
13116
+ if (typeof index === 'undefined') return;
13117
+ if (s.slides.length === 0) return;
13118
+
13119
+ var slide = s.slides.eq(index);
13120
+ var img = slide.find('img.swiper-lazy:not(.swiper-lazy-loaded):not(.swiper-lazy-loading)');
13121
+ if (img.length === 0) return;
13122
+
13123
+ img.each(function () {
13124
+ var _img = $(this);
13125
+ _img.addClass('swiper-lazy-loading');
13126
+
13127
+ var src = _img.attr('data-src');
13128
+
13129
+ s.loadImage(_img[0], src, false, function () {
13130
+ _img.attr('src', src);
13131
+ _img.removeAttr('data-src');
13132
+ _img.addClass('swiper-lazy-loaded').removeClass('swiper-lazy-loading');
13133
+ slide.find('.swiper-lazy-preloader, .preloader').remove();
13134
+
13135
+ s.emit('onLazyImageReady', s, slide[0], _img[0]);
13136
+ });
13137
+
13138
+ s.emit('onLazyImageLoad', s, slide[0], _img[0]);
13139
+ });
13140
+
13141
+ },
13142
+ load: function () {
13143
+ if (s.params.watchSlidesVisibility) {
13144
+ s.wrapper.children('.' + s.params.slideVisibleClass).each(function () {
13145
+ s.lazy.loadImageInSlide($(this).index());
13146
+ });
13147
+ }
13148
+ else {
13149
+ if (s.params.slidesPerView > 1) {
13150
+ for (var i = s.activeIndex; i < s.activeIndex + s.params.slidesPerView ; i++) {
13151
+ if (s.slides[i]) s.lazy.loadImageInSlide(i);
13152
+ }
13153
+ }
13154
+ else {
13155
+ s.lazy.loadImageInSlide(s.activeIndex);
13156
+ }
13157
+ }
13158
+ if (s.params.lazyLoadingInPrevNext) {
13159
+ var nextSlide = s.wrapper.children('.' + s.params.slideNextClass);
13160
+ if (nextSlide.length > 0) s.lazy.loadImageInSlide(nextSlide.index());
13161
+
13162
+ var prevSlide = s.wrapper.children('.' + s.params.slidePrevClass);
13163
+ if (prevSlide.length > 0) s.lazy.loadImageInSlide(prevSlide.index());
13164
+ }
13165
+ },
13166
+ onTransitionStart: function () {
13167
+ if (s.params.lazyLoading) {
13168
+ if (s.params.lazyLoadingOnTransitionStart || (!s.params.lazyLoadingOnTransitionStart && !s.lazy.initialImageLoaded)) {
13169
+ s.lazy.initialImageLoaded = true;
13170
+ s.lazy.load();
13171
+ }
13172
+ }
13173
+ },
13174
+ onTransitionEnd: function () {
13175
+ if (s.params.lazyLoading && !s.params.lazyLoadingOnTransitionStart) {
13176
+ s.lazy.load();
13177
+ }
13178
+ }
13179
+ };
13180
+
13181
+
12390
13182
  /*=========================
12391
13183
  Scrollbar
12392
13184
  ===========================*/
@@ -12404,7 +13196,7 @@
12404
13196
  sb.drag[0].style.height = '';
12405
13197
  sb.trackSize = isH() ? sb.track[0].offsetWidth : sb.track[0].offsetHeight;
12406
13198
 
12407
- sb.divider = s.size / s.virtualWidth;
13199
+ sb.divider = s.size / s.virtualSize;
12408
13200
  sb.moveDivider = sb.divider * (sb.trackSize / s.size);
12409
13201
  sb.dragSize = sb.trackSize * sb.divider;
12410
13202
 
@@ -12454,11 +13246,21 @@
12454
13246
  }
12455
13247
  }
12456
13248
  if (isH()) {
12457
- sb.drag.transform('translate3d(' + (newPos) + 'px, 0, 0)');
13249
+ if (s.support.transforms3d) {
13250
+ sb.drag.transform('translate3d(' + (newPos) + 'px, 0, 0)');
13251
+ }
13252
+ else {
13253
+ sb.drag.transform('translateX(' + (newPos) + 'px)');
13254
+ }
12458
13255
  sb.drag[0].style.width = newSize + 'px';
12459
13256
  }
12460
13257
  else {
12461
- sb.drag.transform('translate3d(0px, ' + (newPos) + 'px, 0)');
13258
+ if (s.support.transforms3d) {
13259
+ sb.drag.transform('translate3d(0px, ' + (newPos) + 'px, 0)');
13260
+ }
13261
+ else {
13262
+ sb.drag.transform('translateY(' + (newPos) + 'px)');
13263
+ }
12462
13264
  sb.drag[0].style.height = newSize + 'px';
12463
13265
  }
12464
13266
  if (s.params.scrollbarHide) {
@@ -12525,6 +13327,228 @@
12525
13327
  }
12526
13328
  };
12527
13329
 
13330
+ /*=========================
13331
+ Parallax
13332
+ ===========================*/
13333
+ function setParallaxTransform(el, progress) {
13334
+ el = $(el);
13335
+ var p, pX, pY;
13336
+
13337
+ p = el.attr('data-swiper-parallax') || '0';
13338
+ pX = el.attr('data-swiper-parallax-x');
13339
+ pY = el.attr('data-swiper-parallax-y');
13340
+ if (pX || pY) {
13341
+ pX = pX || '0';
13342
+ pY = pY || '0';
13343
+ }
13344
+ else {
13345
+ if (isH()) {
13346
+ pX = p;
13347
+ pY = '0';
13348
+ }
13349
+ else {
13350
+ pY = p;
13351
+ pX = '0';
13352
+ }
13353
+ }
13354
+ if ((pX).indexOf('%') >= 0) {
13355
+ pX = parseInt(pX, 10) * progress + '%';
13356
+ }
13357
+ else {
13358
+ pX = pX * progress + 'px' ;
13359
+ }
13360
+ if ((pY).indexOf('%') >= 0) {
13361
+ pY = parseInt(pY, 10) * progress + '%';
13362
+ }
13363
+ else {
13364
+ pY = pY * progress + 'px' ;
13365
+ }
13366
+ el.transform('translate3d(' + pX + ', ' + pY + ',0px)');
13367
+ }
13368
+ s.parallax = {
13369
+ setTranslate: function () {
13370
+ s.container.children('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){
13371
+ setParallaxTransform(this, s.progress);
13372
+
13373
+ });
13374
+ s.slides.each(function () {
13375
+ var slide = $(this);
13376
+ slide.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function () {
13377
+ var progress = Math.min(Math.max(slide[0].progress, -1), 1);
13378
+ setParallaxTransform(this, progress);
13379
+ });
13380
+ });
13381
+ },
13382
+ setTransition: function (duration) {
13383
+ if (typeof duration === 'undefined') duration = s.params.speed;
13384
+ s.container.find('[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]').each(function(){
13385
+ var el = $(this);
13386
+ var parallaxDuration = parseInt(el.attr('data-swiper-parallax-duration'), 10) || duration;
13387
+ if (duration === 0) parallaxDuration = 0;
13388
+ el.transition(parallaxDuration);
13389
+ });
13390
+ }
13391
+ };
13392
+
13393
+
13394
+ /*=========================
13395
+ Plugins API. Collect all and init all plugins
13396
+ ===========================*/
13397
+ s._plugins = [];
13398
+ for (var plugin in s.plugins) {
13399
+ var p = s.plugins[plugin](s, s.params[plugin]);
13400
+ if (p) s._plugins.push(p);
13401
+ }
13402
+ // Method to call all plugins event/method
13403
+ s.callPlugins = function (eventName) {
13404
+ for (var i = 0; i < s._plugins.length; i++) {
13405
+ if (eventName in s._plugins[i]) {
13406
+ s._plugins[i][eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
13407
+ }
13408
+ }
13409
+ };
13410
+
13411
+ /*=========================
13412
+ Events/Callbacks/Plugins Emitter
13413
+ ===========================*/
13414
+ function normalizeEventName (eventName) {
13415
+ if (eventName.indexOf('on') !== 0) {
13416
+ if (eventName[0] !== eventName[0].toUpperCase()) {
13417
+ eventName = 'on' + eventName[0].toUpperCase() + eventName.substring(1);
13418
+ }
13419
+ else {
13420
+ eventName = 'on' + eventName;
13421
+ }
13422
+ }
13423
+ return eventName;
13424
+ }
13425
+ s.emitterEventListeners = {
13426
+
13427
+ };
13428
+ s.emit = function (eventName) {
13429
+ // Trigger callbacks
13430
+ if (s.params[eventName]) {
13431
+ s.params[eventName](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
13432
+ }
13433
+ var i;
13434
+ // Trigger events
13435
+ if (s.emitterEventListeners[eventName]) {
13436
+ for (i = 0; i < s.emitterEventListeners[eventName].length; i++) {
13437
+ s.emitterEventListeners[eventName][i](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
13438
+ }
13439
+ }
13440
+ // Trigger plugins
13441
+ if (s.callPlugins) s.callPlugins(eventName, arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
13442
+ };
13443
+ s.on = function (eventName, handler) {
13444
+ eventName = normalizeEventName(eventName);
13445
+ if (!s.emitterEventListeners[eventName]) s.emitterEventListeners[eventName] = [];
13446
+ s.emitterEventListeners[eventName].push(handler);
13447
+ return s;
13448
+ };
13449
+ s.off = function (eventName, handler) {
13450
+ var i;
13451
+ eventName = normalizeEventName(eventName);
13452
+ if (typeof handler === 'undefined') {
13453
+ // Remove all handlers for such event
13454
+ s.emitterEventListeners[eventName] = [];
13455
+ return s;
13456
+ }
13457
+ if (!s.emitterEventListeners[eventName] || s.emitterEventListeners[eventName].length === 0) return;
13458
+ for (i = 0; i < s.emitterEventListeners[eventName].length; i++) {
13459
+ if(s.emitterEventListeners[eventName][i] === handler) s.emitterEventListeners[eventName].splice(i, 1);
13460
+ }
13461
+ return s;
13462
+ };
13463
+ s.once = function (eventName, handler) {
13464
+ eventName = normalizeEventName(eventName);
13465
+ var _handler = function () {
13466
+ handler(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
13467
+ s.off(eventName, _handler);
13468
+ };
13469
+ s.on(eventName, _handler);
13470
+ return s;
13471
+ };
13472
+
13473
+ // Accessibility tools
13474
+ s.a11y = {
13475
+ makeFocusable: function ($el) {
13476
+ $el[0].tabIndex = '0';
13477
+ return $el;
13478
+ },
13479
+ addRole: function ($el, role) {
13480
+ $el.attr('role', role);
13481
+ return $el;
13482
+ },
13483
+
13484
+ addLabel: function ($el, label) {
13485
+ $el.attr('aria-label', label);
13486
+ return $el;
13487
+ },
13488
+
13489
+ disable: function ($el) {
13490
+ $el.attr('aria-disabled', true);
13491
+ return $el;
13492
+ },
13493
+
13494
+ enable: function ($el) {
13495
+ $el.attr('aria-disabled', false);
13496
+ return $el;
13497
+ },
13498
+
13499
+ onEnterKey: function (event) {
13500
+ if (event.keyCode !== 13) return;
13501
+ if ($(event.target).is(s.params.nextButton)) {
13502
+ s.onClickNext(event);
13503
+ if (s.isEnd) {
13504
+ s.a11y.notify(s.params.lastSlideMsg);
13505
+ }
13506
+ else {
13507
+ s.a11y.notify(s.params.nextSlideMsg);
13508
+ }
13509
+ }
13510
+ else if ($(event.target).is(s.params.prevButton)) {
13511
+ s.onClickPrev(event);
13512
+ if (s.isBeginning) {
13513
+ s.a11y.notify(s.params.firstSlideMsg);
13514
+ }
13515
+ else {
13516
+ s.a11y.notify(s.params.prevSlideMsg);
13517
+ }
13518
+ }
13519
+ },
13520
+
13521
+ liveRegion: $('<span class="swiper-notification" aria-live="assertive" aria-atomic="true"></span>'),
13522
+
13523
+ notify: function (message) {
13524
+ var notification = s.a11y.liveRegion;
13525
+ if (notification.length === 0) return;
13526
+ notification.html('');
13527
+ notification.html(message);
13528
+ },
13529
+ init: function () {
13530
+ // Setup accessibility
13531
+ if (s.params.nextButton) {
13532
+ var nextButton = $(s.params.nextButton);
13533
+ s.a11y.makeFocusable(nextButton);
13534
+ s.a11y.addRole(nextButton, 'button');
13535
+ s.a11y.addLabel(nextButton, s.params.nextSlideMsg);
13536
+ }
13537
+ if (s.params.prevButton) {
13538
+ var prevButton = $(s.params.prevButton);
13539
+ s.a11y.makeFocusable(prevButton);
13540
+ s.a11y.addRole(prevButton, 'button');
13541
+ s.a11y.addLabel(prevButton, s.params.prevSlideMsg);
13542
+ }
13543
+
13544
+ $(s.container).append(s.a11y.liveRegion);
13545
+ },
13546
+ destroy: function () {
13547
+ if (s.a11y.liveRegion && s.a11y.liveRegion.length > 0) s.a11y.liveRegion.remove();
13548
+ }
13549
+ };
13550
+
13551
+
12528
13552
  /*=========================
12529
13553
  Init/Destroy
12530
13554
  ===========================*/
@@ -12545,12 +13569,16 @@
12545
13569
  }
12546
13570
  else {
12547
13571
  s.slideTo(s.params.initialSlide, 0, s.params.runCallbacksOnInit);
13572
+ if (s.params.initialSlide === 0) {
13573
+ if (s.parallax && s.params.parallax) s.parallax.setTranslate();
13574
+ if (s.lazy && s.params.lazyLoading) s.lazy.load();
13575
+ }
12548
13576
  }
12549
13577
  s.attachEvents();
12550
13578
  if (s.params.observer && s.support.observer) {
12551
13579
  s.initObservers();
12552
13580
  }
12553
- if (s.params.updateOnImagesReady) {
13581
+ if (s.params.preloadImages && !s.params.lazyLoading) {
12554
13582
  s.preloadImages();
12555
13583
  }
12556
13584
  if (s.params.autoplay) {
@@ -12565,26 +13593,84 @@
12565
13593
  if (s.params.hashnav) {
12566
13594
  if (s.hashnav) s.hashnav.init();
12567
13595
  }
12568
- if (s.params.onInit) s.params.onInit(s);
13596
+ if (s.params.a11y && s.a11y) s.a11y.init();
13597
+ s.emit('onInit', s);
13598
+ };
13599
+
13600
+ // Cleanup dynamic styles
13601
+ s.cleanupStyles = function () {
13602
+ // Container
13603
+ s.container.removeClass(s.classNames.join(' ')).removeAttr('style');
13604
+
13605
+ // Wrapper
13606
+ s.wrapper.removeAttr('style');
13607
+
13608
+ // Slides
13609
+ if (s.slides && s.slides.length) {
13610
+ s.slides
13611
+ .removeClass([
13612
+ s.params.slideVisibleClass,
13613
+ s.params.slideActiveClass,
13614
+ s.params.slideNextClass,
13615
+ s.params.slidePrevClass
13616
+ ].join(' '))
13617
+ .removeAttr('style')
13618
+ .removeAttr('data-swiper-column')
13619
+ .removeAttr('data-swiper-row');
13620
+ }
13621
+
13622
+ // Pagination/Bullets
13623
+ if (s.paginationContainer && s.paginationContainer.length) {
13624
+ s.paginationContainer.removeClass(s.params.paginationHiddenClass);
13625
+ }
13626
+ if (s.bullets && s.bullets.length) {
13627
+ s.bullets.removeClass(s.params.bulletActiveClass);
13628
+ }
13629
+
13630
+ // Buttons
13631
+ if (s.params.prevButton) $(s.params.prevButton).removeClass(s.params.buttonDisabledClass);
13632
+ if (s.params.nextButton) $(s.params.nextButton).removeClass(s.params.buttonDisabledClass);
13633
+
13634
+ // Scrollbar
13635
+ if (s.params.scrollbar && s.scrollbar) {
13636
+ if (s.scrollbar.track && s.scrollbar.track.length) s.scrollbar.track.removeAttr('style');
13637
+ if (s.scrollbar.drag && s.scrollbar.drag.length) s.scrollbar.drag.removeAttr('style');
13638
+ }
12569
13639
  };
12570
13640
 
12571
13641
  // Destroy
12572
- s.destroy = function (deleteInstance) {
13642
+ s.destroy = function (deleteInstance, cleanupStyles) {
13643
+ // Detach evebts
12573
13644
  s.detachEvents();
13645
+ // Stop autoplay
13646
+ s.stopAutoplay();
13647
+ // Destroy loop
13648
+ if (s.params.loop) {
13649
+ s.destroyLoop();
13650
+ }
13651
+ // Cleanup styles
13652
+ if (cleanupStyles) {
13653
+ s.cleanupStyles();
13654
+ }
13655
+ // Disconnect observer
12574
13656
  s.disconnectObservers();
13657
+ // Disable keyboard/mousewheel
12575
13658
  if (s.params.keyboardControl) {
12576
13659
  if (s.disableKeyboardControl) s.disableKeyboardControl();
12577
13660
  }
12578
13661
  if (s.params.mousewheelControl) {
12579
13662
  if (s.disableMousewheelControl) s.disableMousewheelControl();
12580
13663
  }
12581
- if (s.params.onDestroy) s.params.onDestroy();
13664
+ // Disable a11y
13665
+ if (s.params.a11y && s.a11y) s.a11y.destroy();
13666
+ // Destroy callback
13667
+ s.emit('onDestroy');
13668
+ // Delete instance
12582
13669
  if (deleteInstance !== false) s = null;
12583
13670
  };
12584
13671
 
12585
13672
  s.init();
12586
13673
 
12587
-
12588
13674
 
12589
13675
 
12590
13676
  // Return swiper instance
@@ -12604,6 +13690,27 @@
12604
13690
  return Object.prototype.toString.apply(arr) === '[object Array]';
12605
13691
  },
12606
13692
  /*==================================================
13693
+ Browser
13694
+ ====================================================*/
13695
+ browser: {
13696
+ ie: window.navigator.pointerEnabled || window.navigator.msPointerEnabled,
13697
+ ieTouch: (window.navigator.msPointerEnabled && window.navigator.msMaxTouchPoints > 1) || (window.navigator.pointerEnabled && window.navigator.maxTouchPoints > 1),
13698
+ },
13699
+ /*==================================================
13700
+ Devices
13701
+ ====================================================*/
13702
+ device: (function () {
13703
+ var ua = navigator.userAgent;
13704
+ var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
13705
+ var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
13706
+ var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
13707
+ var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
13708
+ return {
13709
+ ios: ipad || iphone || ipad,
13710
+ android: android
13711
+ };
13712
+ })(),
13713
+ /*==================================================
12607
13714
  Feature Detection
12608
13715
  ====================================================*/
12609
13716
  support: {
@@ -12618,7 +13725,7 @@
12618
13725
 
12619
13726
  flexbox: (function () {
12620
13727
  var div = document.createElement('div').style;
12621
- var styles = ('WebkitBox msFlexbox MsFlexbox WebkitFlex MozBox flex').split(' ');
13728
+ var styles = ('alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient').split(' ');
12622
13729
  for (var i = 0; i < styles.length; i++) {
12623
13730
  if (styles[i] in div) return true;
12624
13731
  }
@@ -12628,7 +13735,12 @@
12628
13735
  return ('MutationObserver' in window || 'WebkitMutationObserver' in window);
12629
13736
  })()
12630
13737
  },
13738
+ /*==================================================
13739
+ Plugins
13740
+ ====================================================*/
13741
+ plugins: {}
12631
13742
  };
13743
+
12632
13744
 
12633
13745
  })();
12634
13746