framework7rails 4.0.2 → 4.0.5

Sign up to get free protection for your applications and to get access to all the features.
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