framework7rails 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * Licensed under MIT
12
12
  *
13
- * Released on: October 7, 2014
13
+ * Released on: November 2, 2014
14
14
  */
15
15
  (function () {
16
16
 
@@ -24,7 +24,7 @@
24
24
  var app = this;
25
25
 
26
26
  // Version
27
- app.version = '0.9.6';
27
+ app.version = '0.9.8';
28
28
 
29
29
  // Default Parameters
30
30
  app.params = {
@@ -54,19 +54,22 @@
54
54
  swipeBackPage: true,
55
55
  swipeBackPageThreshold: 0,
56
56
  swipeBackPageActiveArea: 30,
57
- swipeBackPageBoxShadow: true,
57
+ swipeBackPageAnimateShadow: true,
58
+ swipeBackPageAnimateOpacity: true,
58
59
  // Ajax
59
60
  ajaxLinks: undefined, // or CSS selector
60
61
  // External Links
61
- externalLinks: ['external'], // array of CSS class selectors and/or rel attributes
62
+ externalLinks: '.external', // CSS selector
62
63
  // Sortable
63
64
  sortable: true,
64
65
  // Scroll toolbars
65
66
  hideNavbarOnPageScroll: false,
66
67
  hideToolbarOnPageScroll: false,
68
+ hideTabbarOnPageScroll: false,
67
69
  showBarsOnPageScrollEnd: true,
68
70
  // Swipeout
69
71
  swipeout: true,
72
+ swipeoutActionsNoFold: false,
70
73
  swipeoutNoFollow: false,
71
74
  // Smart Select Back link template
72
75
  smartSelectBackTemplate: '<div class="left sliding"><a href="#" class="back link"><i class="icon icon-back"></i><span>{{backText}}</span></a></div>',
@@ -107,7 +110,7 @@
107
110
  animatePages: true,
108
111
  // Template7
109
112
  templates: {},
110
- templatesData: {},
113
+ template7Data: {},
111
114
  template7Pages: false,
112
115
  precompileTemplates: false,
113
116
  // Auto init
@@ -157,10 +160,12 @@
157
160
  dynamicNavbar: false,
158
161
  domCache: false,
159
162
  linksView: undefined,
163
+ reloadPages: false,
160
164
  uniqueHistory: app.params.uniqueHistory,
161
165
  uniqueHistoryIgnoreGetParameters: app.params.uniqueHistoryIgnoreGetParameters,
162
166
  swipeBackPage: app.params.swipeBackPage,
163
- swipeBackPageBoxShadow: app.params.swipeBackPageBoxShadow,
167
+ swipeBackPageAnimateShadow: app.params.swipeBackPageAnimateShadow,
168
+ swipeBackPageAnimateOpacity: app.params.swipeBackPageAnimateOpacity,
164
169
  swipeBackPageActiveArea: app.params.swipeBackPageActiveArea,
165
170
  swipeBackPageThreshold: app.params.swipeBackPageThreshold,
166
171
  animatePages: app.params.animatePages,
@@ -382,10 +387,10 @@
382
387
  }
383
388
 
384
389
  activePage.transform('translate3d(' + activePageTranslate + 'px,0,0)');
385
- if (view.params.swipeBackPageBoxShadow && app.device.os !== 'android') activePage[0].style.boxShadow = '0px 0px 12px rgba(0,0,0,' + (0.5 - 0.5 * percentage) + ')';
390
+ if (view.params.swipeBackPageAnimateShadow && app.device.os !== 'android') activePage[0].style.boxShadow = '0px 0px 12px rgba(0,0,0,' + (0.5 - 0.5 * percentage) + ')';
386
391
 
387
392
  previousPage.transform('translate3d(' + previousPageTranslate + 'px,0,0)');
388
- previousPage[0].style.opacity = 0.9 + 0.1 * percentage;
393
+ if (view.params.swipeBackPageAnimateOpacity) previousPage[0].style.opacity = 0.9 + 0.1 * percentage;
389
394
 
390
395
  // Dynamic Navbars Animation
391
396
  if (dynamicNavbar) {
@@ -618,16 +623,16 @@
618
623
 
619
624
  // Bars methods
620
625
  view.hideNavbar = function () {
621
- return app.hideNavbar(container);
626
+ return app.hideNavbar(container.find('.navbar'));
622
627
  };
623
628
  view.showNavbar = function () {
624
- return app.showNavbar(container);
629
+ return app.showNavbar(container.find('.navbar'));
625
630
  };
626
631
  view.hideToolbar = function () {
627
- return app.hideToolbar(container);
632
+ return app.hideToolbar(container.find('.toolbar'));
628
633
  };
629
634
  view.showToolbar = function () {
630
- return app.showToolbar(container);
635
+ return app.showToolbar(container.find('.toolbar'));
631
636
  };
632
637
 
633
638
  // Push State on load
@@ -775,25 +780,25 @@
775
780
 
776
781
  });
777
782
  };
778
- app.hideNavbar = function (viewContainer) {
779
- $(viewContainer).addClass('hidden-navbar');
783
+ app.hideNavbar = function (navbarContainer) {
784
+ $(navbarContainer).addClass('navbar-hidden');
780
785
  return true;
781
786
  };
782
- app.showNavbar = function (viewContainer) {
783
- var vc = $(viewContainer);
784
- vc.addClass('hiding-navbar').removeClass('hidden-navbar').find('.navbar').transitionEnd(function () {
785
- vc.removeClass('hiding-navbar');
787
+ app.showNavbar = function (navbarContainer) {
788
+ var navbar = $(navbarContainer);
789
+ navbar.addClass('navbar-hiding').removeClass('navbar-hidden').transitionEnd(function () {
790
+ navbar.removeClass('navbar-hiding');
786
791
  });
787
792
  return true;
788
793
  };
789
- app.hideToolbar = function (viewContainer) {
790
- $(viewContainer).addClass('hidden-toolbar');
794
+ app.hideToolbar = function (toolbarContainer) {
795
+ $(toolbarContainer).addClass('toolbar-hidden');
791
796
  return true;
792
797
  };
793
- app.showToolbar = function (viewContainer) {
794
- var vc = $(viewContainer);
795
- vc.addClass('hiding-toolbar').removeClass('hidden-toolbar').find('.toolbar').transitionEnd(function () {
796
- vc.removeClass('hiding-toolbar');
798
+ app.showToolbar = function (toolbarContainer) {
799
+ var toolbar = $(toolbarContainer);
800
+ toolbar.addClass('toolbar-hiding').removeClass('toolbar-hidden').transitionEnd(function () {
801
+ toolbar.removeClass('toolbar-hiding');
797
802
  });
798
803
  };
799
804
 
@@ -810,6 +815,8 @@
810
815
  var clear = searchbar.find('.searchbar-clear');
811
816
  var cancel = searchbar.find('.searchbar-cancel');
812
817
  var searchList = $(searchbar.attr('data-search-list'));
818
+ var isVirtualList = searchList.hasClass('virtual-list');
819
+ var virtualList;
813
820
  var searchIn = searchbar.attr('data-search-in');
814
821
  var searchBy = searchbar.attr('data-search-by');
815
822
  var found = searchbar.attr('data-searchbar-found');
@@ -830,18 +837,17 @@
830
837
  }
831
838
 
832
839
  // Cancel button
833
- var cancelWidth, cancelMarginProp = app.rtl ? 'margin-left' : 'margin-right';
840
+ var cancelMarginProp = app.rtl ? 'margin-left' : 'margin-right';
834
841
  if (cancel.length > 0) {
835
- cancelWidth = cancel.width();
836
-
837
- cancel.css(cancelMarginProp, - cancelWidth + 'px');
842
+ cancel.css(cancelMarginProp, -cancel[0].offsetWidth + 'px');
838
843
  }
844
+
839
845
 
840
846
  // Handlers
841
847
  function disableSearchbar() {
842
848
  input.val('').trigger('change');
843
849
  searchbar.removeClass('searchbar-active searchbar-not-empty');
844
- if (cancel.length > 0) cancel.css(cancelMarginProp, - cancelWidth + 'px');
850
+ if (cancel.length > 0) cancel.css(cancelMarginProp, -cancel[0].offsetWidth + 'px');
845
851
 
846
852
  if (searchList) searchbarOverlay.removeClass('searchbar-overlay-active');
847
853
  if (app.device.ios) {
@@ -877,7 +883,7 @@
877
883
 
878
884
  // Clear
879
885
  function clearSearchbar() {
880
- input.val('').trigger('change');
886
+ input.val('').trigger('change').focus();
881
887
  searchList.trigger('clearSearch');
882
888
  }
883
889
 
@@ -893,7 +899,7 @@
893
899
  searchbar.addClass('searchbar-not-empty');
894
900
  if (searchList && searchbar.hasClass('searchbar-active')) searchbarOverlay.removeClass('searchbar-overlay-active');
895
901
  }
896
- if (searchList.length > 0 && searchIn) search(value);
902
+ if (searchList.length > 0 && (searchIn || isVirtualList)) search(value);
897
903
  }, 0);
898
904
  }
899
905
 
@@ -922,57 +928,75 @@
922
928
  // Search
923
929
  function search(query) {
924
930
  var values = query.trim().toLowerCase().split(' ');
925
- searchList.find('li').removeClass('hidden-by-searchbar');
926
931
  var foundItems = [];
927
- searchList.find('li').each(function (index, el) {
928
- el = $(el);
929
- var compareWithEl = el.find(searchIn);
930
- if (compareWithEl.length === 0) return;
931
- var compareWith;
932
- compareWith = compareWithEl.text().trim().toLowerCase();
933
- var wordsMatch = 0;
934
- for (var i = 0; i < values.length; i++) {
935
- if (compareWith.indexOf(values[i]) >= 0) wordsMatch++;
936
- }
937
- if (wordsMatch !== values.length) {
938
- el.addClass('hidden-by-searchbar');
932
+ if (isVirtualList) {
933
+ virtualList = searchList[0].f7VirtualList;
934
+ if (query.trim() === '') {
935
+ virtualList.resetFilter();
936
+ notFound.hide();
937
+ found.show();
938
+ return;
939
939
  }
940
- else {
941
- foundItems.push(el[0]);
940
+ if (virtualList.params.searchAll) {
941
+ foundItems = virtualList.params.searchAll(query, virtualList.items) || [];
942
942
  }
943
- });
944
-
945
- if (app.params.searchbarHideDividers) {
946
- searchList.find('.item-divider, .list-group-title').each(function () {
947
- var title = $(this);
948
- var nextElements = title.nextAll('li');
949
- var hide = true;
950
- for (var i = 0; i < nextElements.length; i++) {
951
- var nextEl = $(nextElements[i]);
952
- if (nextEl.hasClass('list-group-title') || nextEl.hasClass('item-divider')) break;
953
- if (!nextEl.hasClass('hidden-by-searchbar')) {
954
- hide = false;
943
+ else if (virtualList.params.searchByItem) {
944
+ for (var i = 0; i < virtualList.items.length; i++) {
945
+ if(virtualList.params.searchByItem(query, i, virtualList.params.items[i])) {
946
+ foundItems.push(i);
955
947
  }
956
948
  }
957
- if (hide) title.addClass('hidden-by-searchbar');
958
- else title.removeClass('hidden-by-searchbar');
959
- });
949
+ }
960
950
  }
961
- if (app.params.searchbarHideGroups) {
962
- searchList.find('.list-group').each(function () {
963
- var group = $(this);
964
- var notHidden = group.find('li:not(.hidden-by-searchbar)');
965
- if (notHidden.length === 0) {
966
- group.addClass('hidden-by-searchbar');
951
+ else {
952
+ searchList.find('li').removeClass('hidden-by-searchbar').each(function (index, el) {
953
+ el = $(el);
954
+ var compareWithEl = el.find(searchIn);
955
+ if (compareWithEl.length === 0) return;
956
+ var compareWith;
957
+ compareWith = compareWithEl.text().trim().toLowerCase();
958
+ var wordsMatch = 0;
959
+ for (var i = 0; i < values.length; i++) {
960
+ if (compareWith.indexOf(values[i]) >= 0) wordsMatch++;
961
+ }
962
+ if (wordsMatch !== values.length) {
963
+ el.addClass('hidden-by-searchbar');
967
964
  }
968
965
  else {
969
- group.removeClass('hidden-by-searchbar');
966
+ foundItems.push(el[0]);
970
967
  }
971
968
  });
972
- }
973
969
 
970
+ if (app.params.searchbarHideDividers) {
971
+ searchList.find('.item-divider, .list-group-title').each(function () {
972
+ var title = $(this);
973
+ var nextElements = title.nextAll('li');
974
+ var hide = true;
975
+ for (var i = 0; i < nextElements.length; i++) {
976
+ var nextEl = $(nextElements[i]);
977
+ if (nextEl.hasClass('list-group-title') || nextEl.hasClass('item-divider')) break;
978
+ if (!nextEl.hasClass('hidden-by-searchbar')) {
979
+ hide = false;
980
+ }
981
+ }
982
+ if (hide) title.addClass('hidden-by-searchbar');
983
+ else title.removeClass('hidden-by-searchbar');
984
+ });
985
+ }
986
+ if (app.params.searchbarHideGroups) {
987
+ searchList.find('.list-group').each(function () {
988
+ var group = $(this);
989
+ var notHidden = group.find('li:not(.hidden-by-searchbar)');
990
+ if (notHidden.length === 0) {
991
+ group.addClass('hidden-by-searchbar');
992
+ }
993
+ else {
994
+ group.removeClass('hidden-by-searchbar');
995
+ }
996
+ });
997
+ }
998
+ }
974
999
  searchList.trigger('search', {query: query, foundItems: foundItems});
975
-
976
1000
  if (foundItems.length === 0) {
977
1001
  notFound.show();
978
1002
  found.hide();
@@ -981,6 +1005,9 @@
981
1005
  notFound.hide();
982
1006
  found.show();
983
1007
  }
1008
+ if (isVirtualList) {
1009
+ virtualList.filterItems(foundItems);
1010
+ }
984
1011
  }
985
1012
 
986
1013
  // Destroy on page remove
@@ -1228,18 +1255,20 @@
1228
1255
  };
1229
1256
 
1230
1257
  // On Page Init Callback
1231
- app.pageInitCallback = function (view, pageContainer, url, position, navbarInnerContainer) {
1258
+ app.pageInitCallback = function (view, params) {
1259
+ var pageContainer = params.pageContainer;
1232
1260
  if (pageContainer.f7PageInitialized && !view.params.domCache) return;
1233
1261
 
1234
1262
  // Page Data
1235
1263
  var pageData = {
1236
1264
  container: pageContainer,
1237
- url: url,
1238
- query: $.parseUrlQuery(url || ''),
1265
+ url: params.url,
1266
+ query: $.parseUrlQuery(params.url || ''),
1239
1267
  name: $(pageContainer).attr('data-page'),
1240
1268
  view: view,
1241
- from: position,
1242
- navbarInnerContainer: navbarInnerContainer
1269
+ from: params.position,
1270
+ context: params.context,
1271
+ navbarInnerContainer: params.navbarInnerContainer
1243
1272
  };
1244
1273
 
1245
1274
  if (pageContainer.f7PageInitialized && view.params.domCache) {
@@ -1282,6 +1311,8 @@
1282
1311
  container: pageContainer,
1283
1312
  name: $(pageContainer).attr('data-page'),
1284
1313
  view: view,
1314
+ url: pageContainer.f7PageData && pageContainer.f7PageData.url,
1315
+ query: pageContainer.f7PageData && pageContainer.f7PageData.query,
1285
1316
  from: position
1286
1317
  };
1287
1318
  // Before Init Callback
@@ -1301,6 +1332,7 @@
1301
1332
  query: pageContainer.f7PageData && pageContainer.f7PageData.query,
1302
1333
  view: view,
1303
1334
  from: params.position,
1335
+ context: params.context,
1304
1336
  swipeBack: params.swipeBack
1305
1337
  };
1306
1338
 
@@ -1327,6 +1359,7 @@
1327
1359
  name: $(params.pageContainer).attr('data-page'),
1328
1360
  view: view,
1329
1361
  from: params.position,
1362
+ context: params.context,
1330
1363
  swipeBack: params.swipeBack
1331
1364
  };
1332
1365
  var oldPage = params.oldPage,
@@ -1363,6 +1396,19 @@
1363
1396
  if (!newPage.hasClass('no-toolbar') && (oldPage.hasClass('no-toolbar') || oldPage.hasClass('no-toolbar-by-scroll'))) {
1364
1397
  view.showToolbar();
1365
1398
  }
1399
+ // Hide/show tabbar
1400
+ var tabBar;
1401
+ if (newPage.hasClass('no-tabbar') && !oldPage.hasClass('no-tabbar')) {
1402
+ tabBar = $(view.container).find('.tabbar');
1403
+ if (tabBar.length === 0) tabBar = $(view.container).parents('.' + app.params.viewsClass).find('.tabbar');
1404
+ app.hideToolbar(tabBar);
1405
+ }
1406
+ if (!newPage.hasClass('no-tabbar') && (oldPage.hasClass('no-tabbar') || oldPage.hasClass('no-tabbar-by-scroll'))) {
1407
+ tabBar = $(view.container).find('.tabbar');
1408
+ if (tabBar.length === 0) tabBar = $(view.container).parents('.' + app.params.viewsClass).find('.tabbar');
1409
+ app.showToolbar(tabBar);
1410
+ }
1411
+
1366
1412
  oldPage.removeClass('no-navbar-by-scroll no-toolbar-by-scroll');
1367
1413
  // Callbacks
1368
1414
  app.pluginHook('pageBeforeAnimation', pageData);
@@ -1556,10 +1602,10 @@
1556
1602
  var t7_ctx, t7_template;
1557
1603
  if (typeof content === 'string') {
1558
1604
  if (url) {
1559
- if (app.templatesCache[url]) t7_template = t7.templatesCache[url];
1605
+ if (app.template7Cache[url]) t7_template = t7.cache[url];
1560
1606
  else {
1561
1607
  t7_template = t7.compile(content);
1562
- t7.templatesCache[url] = t7_template;
1608
+ t7.cache[url] = t7_template;
1563
1609
  }
1564
1610
  }
1565
1611
  else t7_template = t7.compile(content);
@@ -1600,7 +1646,7 @@
1600
1646
  }
1601
1647
  if (!t7_ctx) t7_ctx = {};
1602
1648
  }
1603
-
1649
+
1604
1650
  if (t7_template && t7_ctx) {
1605
1651
  if (typeof t7_ctx === 'function') t7_ctx = t7_ctx();
1606
1652
  if (url) {
@@ -1614,7 +1660,7 @@
1614
1660
  t7_rendered_content = t7_template(t7_ctx);
1615
1661
  }
1616
1662
 
1617
- return t7_rendered_content;
1663
+ return {content: t7_rendered_content, context: t7_ctx};
1618
1664
  }
1619
1665
  };
1620
1666
 
@@ -1624,7 +1670,7 @@
1624
1670
 
1625
1671
  var url = options.url,
1626
1672
  content = options.content, //initial content
1627
- t7_rendered_content = options.content, // will be rendered using Template7
1673
+ t7_rendered = {content: options.content},
1628
1674
  template = options.template, // Template 7 compiled template
1629
1675
  pageName = options.pageName,
1630
1676
  viewContainer = $(view.container),
@@ -1641,9 +1687,9 @@
1641
1687
 
1642
1688
  // Render with Template7
1643
1689
  if (app.params.template7Pages && typeof content === 'string' || template) {
1644
- t7_rendered_content = app.router.template7Render(view, options);
1645
- if (t7_rendered_content && !content) {
1646
- content = t7_rendered_content;
1690
+ t7_rendered = app.router.template7Render(view, options);
1691
+ if (t7_rendered.content && !content) {
1692
+ content = t7_rendered.content;
1647
1693
  }
1648
1694
  }
1649
1695
 
@@ -1652,7 +1698,7 @@
1652
1698
  // Parse DOM
1653
1699
  if (!pageName) {
1654
1700
  if (url || (typeof content === 'string')) {
1655
- app.router.temporaryDom.innerHTML = t7_rendered_content;
1701
+ app.router.temporaryDom.innerHTML = t7_rendered.content;
1656
1702
  } else {
1657
1703
  if ('length' in content && content.length > 1) {
1658
1704
  for (var ci = 0; ci < content.length; ci++) {
@@ -1850,7 +1896,13 @@
1850
1896
  }
1851
1897
 
1852
1898
  // Page Init Events
1853
- app.pageInitCallback(view, newPage[0], url, options.reload ? reloadPosition : 'right', dynamicNavbar ? newNavbarInner[0] : undefined);
1899
+ app.pageInitCallback(view, {
1900
+ pageContainer: newPage[0],
1901
+ url: url,
1902
+ position: options.reload ? reloadPosition : 'right',
1903
+ navbarInnerContainer: dynamicNavbar ? newNavbarInner[0] : undefined,
1904
+ context: t7_rendered.context
1905
+ });
1854
1906
 
1855
1907
  // Navbar init event
1856
1908
  if (dynamicNavbar) {
@@ -1870,7 +1922,7 @@
1870
1922
  var clientLeft = newPage[0].clientLeft;
1871
1923
 
1872
1924
  // Before Anim Callback
1873
- app.pageAnimCallbacks('before', view, {pageContainer: newPage[0], url: url, position: 'right', oldPage: oldPage, newPage: newPage});
1925
+ app.pageAnimCallbacks('before', view, {pageContainer: newPage[0], url: url, position: 'right', oldPage: oldPage, newPage: newPage, context: t7_rendered.context});
1874
1926
 
1875
1927
  function afterAnimation() {
1876
1928
  view.allowPageChange = true;
@@ -1880,7 +1932,7 @@
1880
1932
  newNavbarInner.removeClass('navbar-from-right-to-center navbar-on-right').addClass('navbar-on-center');
1881
1933
  oldNavbarInner.removeClass('navbar-from-center-to-left navbar-on-center').addClass('navbar-on-left');
1882
1934
  }
1883
- app.pageAnimCallbacks('after', view, {pageContainer: newPage[0], url: url, position: 'right', oldPage: oldPage, newPage: newPage});
1935
+ app.pageAnimCallbacks('after', view, {pageContainer: newPage[0], url: url, position: 'right', oldPage: oldPage, newPage: newPage, context: t7_rendered.context});
1884
1936
  if (app.params.pushState) app.pushStateClearQueue();
1885
1937
  if (!(view.params.swipeBackPage || view.params.preloadPreviousPage)) {
1886
1938
  if (view.params.domCache) {
@@ -1921,10 +1973,12 @@
1921
1973
  };
1922
1974
 
1923
1975
  app.router.load = function (view, options) {
1976
+ options = options || {};
1924
1977
  var url = options.url;
1925
1978
  var content = options.content;
1926
1979
  var pageName = options.pageName;
1927
1980
  var template = options.template;
1981
+ if (view.params.reloadPages === true) options.reload = true;
1928
1982
 
1929
1983
  if (!view.allowPageChange) return false;
1930
1984
  if (url && view.url === url && !options.reload) return false;
@@ -1965,7 +2019,7 @@
1965
2019
  options = options || {};
1966
2020
  var url = options.url,
1967
2021
  content = options.content,
1968
- t7_rendered_content = options.content, // will be rendered using Template7
2022
+ t7_rendered = {content: options.content}, // will be rendered using Template7
1969
2023
  template = options.template, // Template 7 compiled template
1970
2024
  animatePages = options.animatePages,
1971
2025
  preloadOnly = options.preloadOnly,
@@ -1985,9 +2039,9 @@
1985
2039
 
1986
2040
  // Render with Template7
1987
2041
  if (app.params.template7Pages && typeof content === 'string' || template) {
1988
- t7_rendered_content = app.router.template7Render(view, options);
1989
- if (t7_rendered_content && !content) {
1990
- content = t7_rendered_content;
2042
+ t7_rendered = app.router.template7Render(view, options);
2043
+ if (t7_rendered.content && !content) {
2044
+ content = t7_rendered.content;
1991
2045
  }
1992
2046
  }
1993
2047
 
@@ -2001,14 +2055,14 @@
2001
2055
 
2002
2056
  // Animation
2003
2057
  function afterAnimation() {
2004
- app.pageBackCallbacks('after', view, {pageContainer: oldPage[0], url: url, position: 'center', oldPage: oldPage, newPage: newPage});
2005
- app.pageAnimCallbacks('after', view, {pageContainer: newPage[0], url: url, position: 'left', oldPage: oldPage, newPage: newPage});
2058
+ app.pageBackCallbacks('after', view, {pageContainer: oldPage[0], url: url, position: 'center', oldPage: oldPage, newPage: newPage, context: t7_rendered.context});
2059
+ app.pageAnimCallbacks('after', view, {pageContainer: newPage[0], url: url, position: 'left', oldPage: oldPage, newPage: newPage, context: t7_rendered.context});
2006
2060
  app.router.afterBack(view, oldPage[0], newPage[0]);
2007
2061
  }
2008
2062
  function animateBack() {
2009
2063
  // Page before animation callback
2010
- app.pageBackCallbacks('before', view, {pageContainer: oldPage[0], url: url, position: 'center', oldPage: oldPage, newPage: newPage});
2011
- app.pageAnimCallbacks('before', view, {pageContainer: newPage[0], url: url, position: 'left', oldPage: oldPage, newPage: newPage});
2064
+ app.pageBackCallbacks('before', view, {pageContainer: oldPage[0], url: url, position: 'center', oldPage: oldPage, newPage: newPage, context: t7_rendered.context});
2065
+ app.pageAnimCallbacks('before', view, {pageContainer: newPage[0], url: url, position: 'left', oldPage: oldPage, newPage: newPage, context: t7_rendered.context});
2012
2066
 
2013
2067
  if (animatePages) {
2014
2068
  // Set pages before animation
@@ -2035,7 +2089,7 @@
2035
2089
  app.router.temporaryDom.innerHTML = '';
2036
2090
  // Parse DOM
2037
2091
  if (url || (typeof content === 'string')) {
2038
- app.router.temporaryDom.innerHTML = t7_rendered_content;
2092
+ app.router.temporaryDom.innerHTML = t7_rendered.content;
2039
2093
  } else {
2040
2094
  if ('length' in content && content.length > 1) {
2041
2095
  for (var ci = 0; ci < content.length; ci++) {
@@ -2058,7 +2112,7 @@
2058
2112
  view.allowPageChange = true;
2059
2113
  return;
2060
2114
  }
2061
- if (view.params.dynamicNavbar) {
2115
+ if (view.params.dynamicNavbar && typeof dynamicNavbar === 'undefined') {
2062
2116
  if (!newNavbarInner || newNavbarInner.length === 0) {
2063
2117
  dynamicNavbar = false;
2064
2118
  }
@@ -2105,8 +2159,9 @@
2105
2159
 
2106
2160
  oldPage = $(pagesInView[pagesInView.length - 1]);
2107
2161
 
2108
- if (dynamicNavbar) {
2162
+ if (dynamicNavbar && !oldNavbarInner) {
2109
2163
  oldNavbarInner = $(navbarInners[navbarInners.length - 1]);
2164
+ if (oldNavbarInner.length === 0 || newNavbarInner[0] === oldNavbarInner[0]) dynamicNavbar = false;
2110
2165
  }
2111
2166
 
2112
2167
  if (dynamicNavbar) {
@@ -2117,7 +2172,13 @@
2117
2172
  if (manipulateDom) newPage.insertBefore(oldPage);
2118
2173
 
2119
2174
  // Page Init Events
2120
- app.pageInitCallback(view, newPage[0], url, 'left', dynamicNavbar ? newNavbarInner[0] : undefined);
2175
+ app.pageInitCallback(view, {
2176
+ pageContainer: newPage[0],
2177
+ url: url,
2178
+ position: 'left',
2179
+ navbarInnerContainer: dynamicNavbar ? newNavbarInner[0] : undefined,
2180
+ context: t7_rendered.context
2181
+ });
2121
2182
  if (dynamicNavbar) {
2122
2183
  app.navbarInitCallback(view, newPage[0], navbar[0], newNavbarInner[0], url, 'right');
2123
2184
  }
@@ -2163,6 +2224,9 @@
2163
2224
  navbarInners = viewContainer.find('.navbar-inner:not(.cached)');
2164
2225
  newNavbarInner = $(navbarInners[0]);
2165
2226
  oldNavbarInner = $(navbarInners[1]);
2227
+ if (newNavbarInner.length === 0 || oldNavbarInner.length === 0 || oldNavbarInner[0] === newNavbarInner[0]) {
2228
+ dynamicNavbar = false;
2229
+ }
2166
2230
  }
2167
2231
  manipulateDom = false;
2168
2232
  setPages();
@@ -2367,7 +2431,6 @@
2367
2431
  var preloadUrl = view.history[view.history.length - 2];
2368
2432
  var previousPage;
2369
2433
  var previousNavbar;
2370
-
2371
2434
  if (preloadUrl && view.pagesCache[preloadUrl]) {
2372
2435
  // Load by page name
2373
2436
  previousPage = $(view.container).find('.page[data-page="' + view.pagesCache[preloadUrl] + '"]');
@@ -2376,6 +2439,7 @@
2376
2439
  previousNavbar = $(view.container).find('.navbar-inner[data-page="' + view.pagesCache[preloadUrl] + '"]');
2377
2440
  previousNavbar.insertBefore(newNavbar);
2378
2441
  }
2442
+ if(!previousNavbar || previousNavbar.length === 0) previousNavbar = newNavbar.prev('.navbar-inner.cached');
2379
2443
  }
2380
2444
  else {
2381
2445
  // Just load previous page
@@ -2584,7 +2648,7 @@
2584
2648
  '{{#if label}}' +
2585
2649
  '<li class="actions-popover-label {{#if color}}color-{{color}}{{/if}} {{#if bold}}actions-popover-bold{{/if}}">{{text}}</li>' +
2586
2650
  '{{else}}' +
2587
- '<li><a href="#" class="item-link list-button {{#if color}}color-{{color}}{{/if}} {{#if bold}}actions-popover-bold{{/if}}">{{text}}</a></li>' +
2651
+ '<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>' +
2588
2652
  '{{/if}}' +
2589
2653
  '{{/each}}' +
2590
2654
  '</ul>' +
@@ -2614,6 +2678,7 @@
2614
2678
  var buttonClass = button.label ? 'actions-modal-label' : 'actions-modal-button';
2615
2679
  if (button.bold) buttonClass += ' actions-modal-button-bold';
2616
2680
  if (button.color) buttonClass += ' color-' + button.color;
2681
+ if (button.bg) buttonClass += ' bg-' + button.bg;
2617
2682
  buttonsHTML += '<span class="' + buttonClass + '">' + button.text + '</span>';
2618
2683
  if (j === params[i].length - 1) buttonsHTML += '</div>';
2619
2684
  }
@@ -2674,6 +2739,7 @@
2674
2739
  var modalHeight = modal.height(); // 13 - height of angle
2675
2740
  var modalAngle = modal.find('.popover-angle');
2676
2741
  var modalAngleSize = modalAngle.width() / 2;
2742
+ var modalAngleLeft, modalAngleTop;
2677
2743
  modalAngle.removeClass('on-left on-right on-top on-bottom').css({left: '', top: ''});
2678
2744
 
2679
2745
  var targetWidth = target.outerWidth();
@@ -2724,7 +2790,9 @@
2724
2790
  if (modalPosition === 'top') modalAngle.addClass('on-bottom');
2725
2791
  if (modalPosition === 'bottom') modalAngle.addClass('on-top');
2726
2792
  diff = diff - modalLeft;
2727
- modalAngle.css({left: (modalWidth / 2 - modalAngleSize + diff) + 'px'});
2793
+ modalAngleLeft = (modalWidth / 2 - modalAngleSize + diff);
2794
+ modalAngleLeft = Math.max(Math.min(modalAngleLeft, modalWidth - modalAngleSize * 2 - 6), 6);
2795
+ modalAngle.css({left: modalAngleLeft + 'px'});
2728
2796
  }
2729
2797
  else if (modalPosition === 'middle') {
2730
2798
  modalLeft = targetOffset.left - modalWidth - modalAngleSize;
@@ -2737,7 +2805,9 @@
2737
2805
  modalLeft = windowWidth - modalWidth - 5;
2738
2806
  modalAngle.removeClass('on-right').addClass('on-left');
2739
2807
  }
2740
- modalAngle.css({top: (modalHeight / 2 - modalAngleSize + diff) + 'px'});
2808
+ modalAngleTop = (modalHeight / 2 - modalAngleSize + diff);
2809
+ modalAngleTop = Math.max(Math.min(modalAngleTop, modalHeight - modalAngleSize * 2 - 6), 6);
2810
+ modalAngle.css({top: modalAngleTop + 'px'});
2741
2811
  }
2742
2812
 
2743
2813
  // Apply Styles
@@ -3193,6 +3263,7 @@
3193
3263
  (props.name ? '<div class="message-name">' + props.name + '</div>' : '') +
3194
3264
  '<div class="message-text">' + props.text + '</div>' +
3195
3265
  (props.avatar ? '<div class="message-avatar" style="background-image:url(' + props.avatar + ')"></div>' : '') +
3266
+ (props.label ? '<div class="message-label">' + props.label + '</div>' : '') +
3196
3267
  '</div>';
3197
3268
  if (newOnTop) messages.prepend(html);
3198
3269
  else messages.append(html);
@@ -3266,7 +3337,7 @@
3266
3337
  app.swipeoutOpenedEl = undefined;
3267
3338
  app.allowSwipeout = true;
3268
3339
  app.initSwipeout = function (swipeoutEl) {
3269
- var isTouched, isMoved, isScrolling, touchesStart = {}, touchStartTime, touchesDiff, swipeOutEl, swipeOutContent, actionsRight, actionsLeft, actionsLeftWidth, actionsRightWidth, translate, opened, openedActions, buttonsLeft, buttonsRight, direction, overswipeLeftButton, overswipeRightButton, overswipeLeft, overswipeRight;
3340
+ var isTouched, isMoved, isScrolling, touchesStart = {}, touchStartTime, touchesDiff, swipeOutEl, swipeOutContent, actionsRight, actionsLeft, actionsLeftWidth, actionsRightWidth, translate, opened, openedActions, buttonsLeft, buttonsRight, direction, overswipeLeftButton, overswipeRightButton, overswipeLeft, overswipeRight, noFoldLeft, noFoldRight;
3270
3341
  $(document).on(app.touchEvents.start, function (e) {
3271
3342
  if (app.swipeoutOpenedEl) {
3272
3343
  var target = $(e.target);
@@ -3281,7 +3352,6 @@
3281
3352
  }
3282
3353
  }
3283
3354
  });
3284
-
3285
3355
 
3286
3356
  function handleTouchStart(e) {
3287
3357
  if (!app.allowSwipeout) return;
@@ -3312,6 +3382,8 @@
3312
3382
  actionsRight = swipeOutEl.find('.swipeout-actions-right');
3313
3383
  actionsLeft = swipeOutEl.find('.swipeout-actions-left');
3314
3384
  actionsLeftWidth = actionsRightWidth = buttonsLeft = buttonsRight = overswipeRightButton = overswipeLeftButton = null;
3385
+ noFoldLeft = actionsLeft.hasClass('swipeout-actions-no-fold') || app.params.swipeoutActionsNoFold;
3386
+ noFoldRight = actionsRight.hasClass('swipeout-actions-no-fold') || app.params.swipeoutActionsNoFold;
3315
3387
  if (actionsLeft.length > 0) {
3316
3388
  actionsLeftWidth = actionsLeft.width();
3317
3389
  buttonsLeft = actionsLeft.children('a');
@@ -3393,7 +3465,6 @@
3393
3465
  if (overswipeRightButton.length > 0) {
3394
3466
  overswipeRight = true;
3395
3467
  }
3396
-
3397
3468
  }
3398
3469
  for (i = 0; i < buttonsRight.length; i++) {
3399
3470
  if (typeof buttonsRight[i]._buttonOffset === 'undefined') {
@@ -3425,7 +3496,10 @@
3425
3496
  if (overswipeLeftButton.length > 0 && $button.hasClass('swipeout-overswipe')) {
3426
3497
  $button.css({left: (overswipeLeft ? buttonOffset : 0) + 'px'});
3427
3498
  }
3428
- $button.css('z-index', buttonsLeft.length - i).transform('translate3d(' + (translate + buttonOffset * (1 - Math.min(progress, 1))) + 'px,0,0)');
3499
+ if (buttonsLeft.length > 1) {
3500
+ $button.css('z-index', buttonsLeft.length - i);
3501
+ }
3502
+ $button.transform('translate3d(' + (translate + buttonOffset * (1 - Math.min(progress, 1))) + 'px,0,0)');
3429
3503
  }
3430
3504
  }
3431
3505
  swipeOutContent.transform('translate3d(' + translate + 'px,0,0)');
@@ -3436,11 +3510,13 @@
3436
3510
  isMoved = false;
3437
3511
  return;
3438
3512
  }
3513
+
3439
3514
  isTouched = false;
3440
3515
  isMoved = false;
3441
3516
  var timeDiff = (new Date()).getTime() - touchStartTime;
3442
- var action, actionsWidth, actions, buttons, i;
3517
+ var action, actionsWidth, actions, buttons, i, noFold;
3443
3518
 
3519
+ noFold = direction === 'to-left' ? noFoldRight : noFoldLeft;
3444
3520
  actions = direction === 'to-left' ? actionsRight : actionsLeft;
3445
3521
  actionsWidth = direction === 'to-left' ? actionsRightWidth : actionsLeftWidth;
3446
3522
 
@@ -3542,6 +3618,7 @@
3542
3618
  }
3543
3619
  var swipeOutActions = el.find('.swipeout-actions-' + dir);
3544
3620
  if (swipeOutActions.length === 0) return;
3621
+ var noFold = swipeOutActions.hasClass('swipeout-actions-no-fold') || app.params.swipeoutActionsNoFold;
3545
3622
  el.trigger('open').addClass('swipeout-opened').removeClass('transitioning');
3546
3623
  swipeOutActions.addClass('swipeout-actions-opened');
3547
3624
  var buttons = swipeOutActions.children('a');
@@ -3559,10 +3636,9 @@
3559
3636
  }
3560
3637
  var clientLeft = buttons[1].clientLeft;
3561
3638
  }
3562
-
3563
3639
  el.addClass('transitioning');
3564
3640
  for (i = 0; i < buttons.length; i++) {
3565
- $(buttons[i]).transform('translate3d(' + (translate) + 'px,0,0');
3641
+ $(buttons[i]).transform('translate3d(' + (translate) + 'px,0,0)');
3566
3642
  }
3567
3643
  el.find('.swipeout-content').transform('translate3d(' + translate + 'px,0,0)').transitionEnd(function () {
3568
3644
  el.trigger('opened');
@@ -3575,12 +3651,12 @@
3575
3651
  if (!el.hasClass('swipeout-opened')) return;
3576
3652
  var dir = el.find('.swipeout-actions-opened').hasClass('swipeout-actions-right') ? 'right' : 'left';
3577
3653
  var swipeOutActions = el.find('.swipeout-actions-opened').removeClass('swipeout-actions-opened');
3654
+ var noFold = swipeOutActions.hasClass('swipeout-actions-no-fold') || app.params.swipeoutActionsNoFold;
3578
3655
  var buttons = swipeOutActions.children('a');
3579
3656
  var swipeOutActionsWidth = swipeOutActions.width();
3580
3657
  app.allowSwipeout = false;
3581
3658
  el.trigger('close');
3582
3659
  el.removeClass('swipeout-opened').addClass('transitioning');
3583
-
3584
3660
  el.find('.swipeout-content').transform('translate3d(' + 0 + 'px,0,0)').transitionEnd(function () {
3585
3661
  el.trigger('closed');
3586
3662
  buttons.transform('');
@@ -3607,7 +3683,14 @@
3607
3683
  var clientLeft = el[0].clientLeft;
3608
3684
  el.css({height: 0 + 'px'}).addClass('deleting transitioning').transitionEnd(function () {
3609
3685
  el.trigger('deleted');
3610
- el.remove();
3686
+ if (el.parents('.virtual-list').length > 0) {
3687
+ var virtualList = el.parents('.virtual-list')[0].f7VirtualList;
3688
+ var virtualIndex = el[0].f7VirtualListIndex;
3689
+ if (virtualList && typeof virtualIndex !== 'undefined') virtualList.deleteItem(virtualIndex);
3690
+ }
3691
+ else {
3692
+ el.remove();
3693
+ }
3611
3694
  });
3612
3695
  var translate = '-100%';
3613
3696
  el.find('.swipeout-content').transform('translate3d(' + translate + ',0,0)');
@@ -3643,7 +3726,7 @@
3643
3726
  return sortableContainer;
3644
3727
  };
3645
3728
  app.initSortable = function () {
3646
- var isTouched, isMoved, touchStartY, touchesDiff, sortingEl, sortingItems, minTop, maxTop, insertAfter, insertBefore, sortableContainer;
3729
+ var isTouched, isMoved, touchStartY, touchesDiff, sortingEl, sortingElHeight, sortingItems, minTop, maxTop, insertAfter, insertBefore, sortableContainer;
3647
3730
 
3648
3731
  function handleTouchStart(e) {
3649
3732
  isMoved = false;
@@ -3665,7 +3748,7 @@
3665
3748
  sortableContainer.addClass('sortable-sorting');
3666
3749
  minTop = sortingEl[0].offsetTop;
3667
3750
  maxTop = sortingEl.parent().height() - sortingEl[0].offsetTop - sortingEl.height();
3668
-
3751
+ sortingElHeight = sortingEl[0].offsetHeight;
3669
3752
  }
3670
3753
  isMoved = true;
3671
3754
 
@@ -3687,12 +3770,12 @@
3687
3770
  var sortingElOffset = sortingEl[0].offsetTop + translate;
3688
3771
 
3689
3772
  if ((sortingElOffset >= currentElOffset - currentElHeight / 2) && sortingEl.index() < currentEl.index()) {
3690
- currentEl.transform('translate3d(0,-100%,0)');
3773
+ currentEl.transform('translate3d(0, '+(-sortingElHeight)+'px,0)');
3691
3774
  insertAfter = currentEl;
3692
3775
  insertBefore = undefined;
3693
3776
  }
3694
3777
  else if ((sortingElOffset <= currentElOffset + currentElHeight / 2) && sortingEl.index() > currentEl.index()) {
3695
- $(this).transform('translate3d(0,100%,0)');
3778
+ currentEl.transform('translate3d(0, '+(sortingElHeight)+'px,0)');
3696
3779
  insertAfter = undefined;
3697
3780
  if (!insertBefore) insertBefore = currentEl;
3698
3781
  }
@@ -3712,6 +3795,7 @@
3712
3795
  sortingItems.transform('');
3713
3796
  sortingEl.removeClass('sorting');
3714
3797
  sortableContainer.removeClass('sortable-sorting');
3798
+ var virtualList, oldIndex, newIndex;
3715
3799
  if (insertAfter) {
3716
3800
  sortingEl.insertAfter(insertAfter);
3717
3801
  sortingEl.trigger('sort');
@@ -3720,6 +3804,12 @@
3720
3804
  sortingEl.insertBefore(insertBefore);
3721
3805
  sortingEl.trigger('sort');
3722
3806
  }
3807
+ if ((insertAfter || insertBefore) && sortableContainer.hasClass('virtual-list')) {
3808
+ virtualList = sortableContainer[0].f7VirtualList;
3809
+ oldIndex = sortingEl[0].f7VirtualListIndex;
3810
+ newIndex = insertBefore ? insertBefore[0].f7VirtualListIndex : insertAfter[0].f7VirtualListIndex;
3811
+ if (virtualList) virtualList.moveItem(oldIndex, newIndex);
3812
+ }
3723
3813
  insertAfter = insertBefore = undefined;
3724
3814
  isTouched = false;
3725
3815
  isMoved = false;
@@ -3809,6 +3899,8 @@
3809
3899
  var backText = smartSelect.attr('data-back-text') || app.params.smartSelectBackText;
3810
3900
  var closeText = smartSelect.attr('data-popup-close-text') || smartSelect.attr('data-back-text') || app.params.smartSelectPopupCloseText ;
3811
3901
  var backOnSelect = smartSelect.attr('data-back-onselect') ? (smartSelect.attr('data-back-onselect') === 'true' ? true : false) : app.params.smartSelectBackOnSelect;
3902
+ var formTheme = smartSelect.attr('data-form-theme') || app.params.smartSelectFormTheme;
3903
+ var navbarTheme = smartSelect.attr('data-navbar-theme') || app.params.smartSelectNavbarTheme;
3812
3904
 
3813
3905
  // Generate dynamic page layout
3814
3906
  var id = (new Date()).getTime();
@@ -3843,7 +3935,7 @@
3843
3935
  // Navbar HTML
3844
3936
  var navbarLeftTemplate = openIn === 'popup' ? app.params.smartSelectPopupCloseTemplate.replace(/{{closeText}}/g, closeText) : app.params.smartSelectBackTemplate.replace(/{{backText}}/g, backText);
3845
3937
  var navbarHTML =
3846
- '<div class="navbar">' +
3938
+ '<div class="navbar ' + (navbarTheme ? 'theme-' + navbarTheme : '') + '">' +
3847
3939
  ' <div class="navbar-inner">' +
3848
3940
  navbarLeftTemplate +
3849
3941
  ' <div class="center sliding">' + pageTitle + '</div>' +
@@ -3906,7 +3998,7 @@
3906
3998
  (useSearchbar ? searchbarHTML : '') +
3907
3999
  ' <div class="page-content">' +
3908
4000
  (navbarLayout === 'static' ? navbarHTML : '') +
3909
- ' <div class="list-block smart-select-list-' + id + '">' +
4001
+ ' <div class="list-block smart-select-list-' + id + ' ' + (formTheme ? 'theme-' + formTheme : '') + '">' +
3910
4002
  ' <ul>' +
3911
4003
  inputsHTML +
3912
4004
  ' </ul>' +
@@ -3915,6 +4007,9 @@
3915
4007
  ' </div>' +
3916
4008
  '</div>';
3917
4009
 
4010
+ // Define popup
4011
+ var popup;
4012
+
3918
4013
  // Event Listeners on new page
3919
4014
  function handleInputs(container) {
3920
4015
  $(container).find('input[name="' + inputName + '"]').on('change', function () {
@@ -3941,7 +4036,8 @@
3941
4036
  $select.trigger('change');
3942
4037
  smartSelect.find('.item-after').text(optionText.join(', '));
3943
4038
  if (backOnSelect && inputType === 'radio') {
3944
- view.router.back();
4039
+ if (openIn === 'popup') app.closeModal(popup);
4040
+ else view.router.back();
3945
4041
  }
3946
4042
  });
3947
4043
  }
@@ -3956,7 +4052,7 @@
3956
4052
 
3957
4053
  // Load content
3958
4054
  if (openIn === 'popup') {
3959
- var popup = app.popup('<div class="popup smart-select-popup smart-select-popup-' + inputName + '">' +
4055
+ popup = app.popup('<div class="popup smart-select-popup smart-select-popup-' + inputName + '">' +
3960
4056
  '<div class="view navbar-fixed">' +
3961
4057
  pageHTML +
3962
4058
  '</div>' +
@@ -3966,6 +4062,428 @@
3966
4062
  else view.router.load({content: pageHTML});
3967
4063
  };
3968
4064
 
4065
+ /*===============================================================================
4066
+ ************ Virtual List ************
4067
+ ===============================================================================*/
4068
+ var VirtualList = function (listBlock, params) {
4069
+ var defaults = {
4070
+ cols: 1,
4071
+ height: 44,
4072
+ cache: true
4073
+ };
4074
+ params = params || {};
4075
+ for (var def in defaults) {
4076
+ if (typeof params[def] === 'undefined') {
4077
+ params[def] = defaults[def];
4078
+ }
4079
+ }
4080
+
4081
+ // Preparation
4082
+ var vl = this;
4083
+ vl.listBlock = $(listBlock);
4084
+ vl.params = params;
4085
+ vl.items = params.items;
4086
+ if (params.template) {
4087
+ if (typeof params.template === 'string') vl.template = t7.compile(params.template);
4088
+ else if (typeof params.template === 'function') vl.template = params.template;
4089
+ }
4090
+ vl.pageContent = vl.listBlock.parents('.page-content');
4091
+
4092
+ // Bad scroll
4093
+ var updatableScroll;
4094
+ if (typeof vl.params.updatableScroll !== 'undefined') {
4095
+ updatableScroll = vl.params.updatableScroll;
4096
+ }
4097
+ else {
4098
+ updatableScroll = true;
4099
+ if (app.device.ios && app.device.osVersion.split('.')[0] < 8) {
4100
+ updatableScroll = false;
4101
+ }
4102
+ }
4103
+
4104
+ // Append <ul>
4105
+ vl.ul = vl.listBlock.children('ul');
4106
+ if (vl.ul.length === 0) {
4107
+ vl.listBlock.append('<ul></ul>');
4108
+ vl.ul = vl.listBlock.children('ul');
4109
+ }
4110
+
4111
+ // DOM cached items
4112
+ vl.domCache = {};
4113
+ vl.displayDomCache = {};
4114
+
4115
+ // Temporary DOM Element
4116
+ vl.tempDomElement = document.createElement('ul');
4117
+
4118
+ // Last repain position
4119
+ vl.lastRepaintY = null;
4120
+
4121
+ // Fragment
4122
+ vl.fragment = document.createDocumentFragment();
4123
+
4124
+ // Filter
4125
+ vl.filterItems = function (indexes, resetScrollTop) {
4126
+ vl.filteredItems = [];
4127
+ var firstIndex = indexes[0];
4128
+ var lastIndex = indexes[indexes.length - 1];
4129
+ for (var i = 0; i < indexes.length; i++) {
4130
+ vl.filteredItems.push(vl.items[indexes[i]]);
4131
+ }
4132
+ if (typeof resetScrollTop === 'undefined') resetScrollTop = true;
4133
+ if (resetScrollTop) {
4134
+ vl.pageContent[0].scrollTop = 0;
4135
+ }
4136
+ vl.update();
4137
+ };
4138
+ vl.resetFilter = function () {
4139
+ vl.filteredItems = null;
4140
+ delete vl.filteredItems;
4141
+ vl.update();
4142
+ };
4143
+
4144
+ var pageHeight, rowsPerScreen, rowsBefore, rowsAfter, rowsToRender, maxBufferHeight = 0, listHeight;
4145
+ var dynamicHeight = typeof vl.params.height === 'function';
4146
+
4147
+ // Set list size
4148
+ vl.setListSize = function () {
4149
+ var items = vl.filteredItems || vl.items;
4150
+ pageHeight = vl.pageContent[0].offsetHeight;
4151
+ if (dynamicHeight) {
4152
+ listHeight = 0;
4153
+ vl.heights = [];
4154
+ for (var i = 0; i < items.length; i++) {
4155
+ var itemHeight = vl.params.height(items[i]);
4156
+ listHeight += itemHeight;
4157
+ vl.heights.push(itemHeight);
4158
+ }
4159
+ }
4160
+ else {
4161
+ listHeight = items.length * vl.params.height;
4162
+ rowsPerScreen = Math.ceil(pageHeight / vl.params.height);
4163
+ rowsBefore = vl.params.rowsBefore || rowsPerScreen * 2;
4164
+ rowsAfter = vl.params.rowsAfter || rowsPerScreen;
4165
+ rowsToRender = (rowsPerScreen + rowsBefore + rowsAfter);
4166
+ maxBufferHeight = rowsBefore / 2 * vl.params.height;
4167
+ }
4168
+
4169
+ if (updatableScroll) {
4170
+ vl.ul.css({height: listHeight + 'px'});
4171
+ }
4172
+ };
4173
+
4174
+ // Render items
4175
+ vl.render = function (force) {
4176
+ if (force) vl.lastRepaintY = null;
4177
+ var scrollTop = vl.pageContent[0].scrollTop;
4178
+ if (vl.lastRepaintY === null || Math.abs(scrollTop - vl.lastRepaintY) > maxBufferHeight || (!updatableScroll && (scrollTop + pageHeight >= vl.pageContent[0].scrollHeight))) {
4179
+ vl.lastRepaintY = scrollTop;
4180
+ }
4181
+ else {
4182
+ return;
4183
+ }
4184
+ var items = vl.filteredItems || vl.items,
4185
+ fromIndex, toIndex, heightBeforeFirstItem = 0, heightBeforeLastItem = 0;
4186
+ if (dynamicHeight) {
4187
+ var itemTop = 0, j, itemHeight;
4188
+ maxBufferHeight = pageHeight;
4189
+ for (j = 0; j < vl.heights.length; j++) {
4190
+ itemHeight = vl.heights[j];
4191
+ if (typeof fromIndex === 'undefined') {
4192
+ if (itemTop + itemHeight >= scrollTop - pageHeight * 2) fromIndex = j;
4193
+ else heightBeforeFirstItem += itemHeight;
4194
+ }
4195
+
4196
+ if (typeof toIndex === 'undefined') {
4197
+ if (itemTop + itemHeight >= scrollTop + pageHeight * 2 || j === vl.heights.length - 1) toIndex = j + 1;
4198
+ heightBeforeLastItem += itemHeight;
4199
+ }
4200
+ itemTop += itemHeight;
4201
+ }
4202
+ toIndex = Math.min(toIndex, items.length);
4203
+ }
4204
+ else {
4205
+ fromIndex = (parseInt(scrollTop / vl.params.height) - rowsBefore) * vl.params.cols;
4206
+ if (fromIndex < 0) {
4207
+ fromIndex = 0;
4208
+ }
4209
+ toIndex = Math.min(fromIndex + rowsToRender * vl.params.cols, items.length);
4210
+ }
4211
+
4212
+ var topPosition;
4213
+ vl.reachEnd = false;
4214
+ for (var i = fromIndex; i < toIndex; i++) {
4215
+ var item, index;
4216
+ // Define real item index
4217
+ index = vl.items.indexOf(items[i]);
4218
+
4219
+ if (i === fromIndex) vl.currentFromIndex = index;
4220
+ if (i === toIndex - 1) vl.currentToIndex = index;
4221
+ if (index === vl.items.length - 1) vl.reachEnd = true;
4222
+
4223
+ // Find items
4224
+ if (vl.domCache[index]) {
4225
+ item = vl.domCache[index];
4226
+ }
4227
+ else {
4228
+ if (vl.template) {
4229
+ vl.tempDomElement.innerHTML = vl.template(items[i], {index: index});
4230
+ }
4231
+ else if (vl.params.renderItem) {
4232
+ vl.tempDomElement.innerHTML = vl.params.renderItem(index, items[i]);
4233
+ }
4234
+ else {
4235
+ vl.tempDomElement.innerHTML = items[i];
4236
+ }
4237
+ item = vl.tempDomElement.childNodes[0];
4238
+ if (vl.params.cache) vl.domCache[index] = item;
4239
+ }
4240
+ item.f7VirtualListIndex = index;
4241
+
4242
+ // Set item top position
4243
+ if (i === fromIndex) {
4244
+ if (dynamicHeight) {
4245
+ topPosition = heightBeforeFirstItem;
4246
+ }
4247
+ else {
4248
+ topPosition = (i * vl.params.height / vl.params.cols);
4249
+ }
4250
+ }
4251
+ item.style.top = topPosition + 'px';
4252
+
4253
+ // Before item insert
4254
+ if (vl.params.onItemBeforeInsert) vl.params.onItemBeforeInsert(vl, item);
4255
+
4256
+ // Append item to fragment
4257
+ vl.fragment.appendChild(item);
4258
+
4259
+ // Update list height with not updatable scroll
4260
+ if (!updatableScroll) {
4261
+ if (dynamicHeight) {
4262
+ vl.ul[0].style.height = heightBeforeLastItem + 'px';
4263
+ }
4264
+ else {
4265
+ vl.ul[0].style.height = (i + 1) * vl.params.height + 'px';
4266
+ }
4267
+ }
4268
+ }
4269
+
4270
+ // Update list html
4271
+ if (vl.params.onBeforeClear) vl.params.onBeforeClear(vl, vl.fragment);
4272
+ vl.ul[0].innerHTML = '';
4273
+
4274
+ if (vl.params.onItemsBeforeInsert) vl.params.onItemsBeforeInsert(vl, vl.fragment);
4275
+ vl.ul[0].appendChild(vl.fragment);
4276
+ if (vl.params.onItemsAfterInsert) vl.params.onFragmentAfterInsert(vl, vl.fragment);
4277
+ };
4278
+
4279
+ // Handle scroll event
4280
+ vl.handleScroll = function (e) {
4281
+ vl.render();
4282
+ };
4283
+ // Handle resize event
4284
+ vl.handleResize = function (e) {
4285
+ vl.setListSize();
4286
+ vl.render(true);
4287
+ };
4288
+
4289
+ vl.attachEvents = function (detach) {
4290
+ var action = detach ? 'off' : 'on';
4291
+ vl.pageContent[action]('scroll', vl.handleScroll);
4292
+ $(window)[action]('resize', vl.handleResize);
4293
+ };
4294
+
4295
+ // Init Virtual List
4296
+ vl.init = function () {
4297
+ vl.attachEvents();
4298
+ vl.setListSize();
4299
+ vl.render();
4300
+ };
4301
+
4302
+ // Append
4303
+ vl.appendItems = function (items) {
4304
+ for (var i = 0; i < items.length; i++) {
4305
+ vl.items.push(items[i]);
4306
+ }
4307
+ vl.update();
4308
+ };
4309
+ vl.appendItem = function (item) {
4310
+ vl.appendItems([item]);
4311
+ };
4312
+ // Replace
4313
+ vl.replaceAllItems = function (items) {
4314
+ vl.items = items;
4315
+ delete vl.filteredItems;
4316
+ vl.domCache = {};
4317
+ vl.update();
4318
+ };
4319
+ vl.replaceItem = function (index, item) {
4320
+ vl.items[index] = item;
4321
+ if (vl.params.cache) delete vl.domCache[index];
4322
+ vl.update();
4323
+ };
4324
+ // Prepend
4325
+ vl.prependItems = function (items) {
4326
+ for (var i = items.length - 1; i >= 0; i--) {
4327
+ vl.items.unshift(items[i]);
4328
+ }
4329
+ if (vl.params.cache) {
4330
+ var newCache = {};
4331
+ for (var cached in vl.domCache) {
4332
+ newCache[parseInt(cached, 10) + items.length] = vl.domCache[cached];
4333
+ }
4334
+ vl.domCache = newCache;
4335
+ }
4336
+ vl.update();
4337
+ };
4338
+ vl.prependItem = function (item) {
4339
+ vl.prependItems([item]);
4340
+ };
4341
+
4342
+ // Move
4343
+ vl.moveItem = function (oldIndex, newIndex) {
4344
+ if (oldIndex === newIndex) return;
4345
+ // remove item from array
4346
+ var item = vl.items.splice(oldIndex, 1)[0];
4347
+ if (newIndex >= vl.items.length) {
4348
+ // Add item to the end
4349
+ vl.items.push(item);
4350
+ newIndex = vl.items.length - 1;
4351
+ }
4352
+ else {
4353
+ // Add item to new index
4354
+ vl.items.splice(newIndex, 0, item);
4355
+ }
4356
+ // Update cache
4357
+ if (vl.params.cache) {
4358
+ var newCache = {};
4359
+ for (var cached in vl.domCache) {
4360
+ var cachedIndex = parseInt(cached, 10);
4361
+ var leftIndex = oldIndex < newIndex ? oldIndex : newIndex;
4362
+ var rightIndex = oldIndex < newIndex ? newIndex : oldIndex;
4363
+ var indexShift = oldIndex < newIndex ? -1 : 1;
4364
+ if (cachedIndex < leftIndex || cachedIndex > rightIndex) newCache[cachedIndex] = vl.domCache[cachedIndex];
4365
+ if (cachedIndex === leftIndex) newCache[rightIndex] = vl.domCache[cachedIndex];
4366
+ if (cachedIndex > leftIndex && cachedIndex <= rightIndex) newCache[cachedIndex + indexShift] = vl.domCache[cachedIndex];
4367
+ }
4368
+ vl.domCache = newCache;
4369
+ }
4370
+ vl.update();
4371
+ };
4372
+ // Insert before
4373
+ vl.insertItemBefore = function (index, item) {
4374
+ if (index === 0) {
4375
+ vl.prependItem(item);
4376
+ return;
4377
+ }
4378
+ if (index >= vl.items.length) {
4379
+ vl.appendItem(item);
4380
+ return;
4381
+ }
4382
+ vl.items.splice(index, 0, item);
4383
+ // Update cache
4384
+ if (vl.params.cache) {
4385
+ var newCache = {};
4386
+ for (var cached in vl.domCache) {
4387
+ var cachedIndex = parseInt(cached, 10);
4388
+ if (cachedIndex >= index) {
4389
+ newCache[cachedIndex + 1] = vl.domCache[cachedIndex];
4390
+ }
4391
+ }
4392
+ vl.domCache = newCache;
4393
+ }
4394
+ vl.update();
4395
+ };
4396
+ // Delete
4397
+ vl.deleteItems = function (indexes) {
4398
+ var prevIndex, indexShift = 0;
4399
+ for (var i = 0; i < indexes.length; i++) {
4400
+ var index = indexes[i];
4401
+ if (typeof prevIndex !== 'undefined') {
4402
+ if (index > prevIndex) {
4403
+ indexShift = -i;
4404
+ }
4405
+ }
4406
+ index = index + indexShift;
4407
+ prevIndex = indexes[i];
4408
+ // Delete item
4409
+ var deletedItem = vl.items.splice(index, 1)[0];
4410
+
4411
+ // Delete from filtered
4412
+ if (vl.filteredItems && vl.filteredItems.indexOf(deletedItem) >= 0) {
4413
+ vl.filteredItems.splice(vl.filteredItems.indexOf(deletedItem), 1);
4414
+ }
4415
+ // Update cache
4416
+ if (vl.params.cache) {
4417
+ var newCache = {};
4418
+ for (var cached in vl.domCache) {
4419
+ var cachedIndex = parseInt(cached, 10);
4420
+ if (cachedIndex === index) {
4421
+ delete vl.domCache[index];
4422
+ }
4423
+ else if (parseInt(cached, 10) > index) {
4424
+ newCache[cachedIndex - 1] = vl.domCache[cached];
4425
+ }
4426
+ else {
4427
+ newCache[cachedIndex] = vl.domCache[cached];
4428
+ }
4429
+ }
4430
+ vl.domCache = newCache;
4431
+ }
4432
+ }
4433
+ vl.update();
4434
+ };
4435
+ vl.deleteAllItems = function () {
4436
+ vl.items = [];
4437
+ delete vl.filteredItems;
4438
+ if (vl.params.cache) vl.domCache = {};
4439
+ vl.update();
4440
+ };
4441
+ vl.deleteItem = function (index) {
4442
+ vl.deleteItems([index]);
4443
+ };
4444
+
4445
+ // Clear cache
4446
+ vl.clearCache = function () {
4447
+ vl.domCache = {};
4448
+ };
4449
+
4450
+ // Update Virtual List
4451
+ vl.update = function () {
4452
+ vl.setListSize();
4453
+ vl.render(true);
4454
+ };
4455
+
4456
+ // Destroy
4457
+ vl.destroy = function () {
4458
+ vl.attachEvents(true);
4459
+ delete vl.items;
4460
+ delete vl.domCache;
4461
+ };
4462
+
4463
+ // Init Virtual List
4464
+ vl.init();
4465
+
4466
+ // Store vl in container
4467
+ vl.listBlock[0].f7VirtualList = vl;
4468
+ return vl;
4469
+ };
4470
+
4471
+ // App Method
4472
+ app.virtualList = function (listBlock, params) {
4473
+ return new VirtualList(listBlock, params);
4474
+ };
4475
+
4476
+ app.reinitVirtualList = function (pageContainer) {
4477
+ var page = $(pageContainer);
4478
+ var vlists = page.find('.virtual-list');
4479
+ if (vlists.length === 0) return;
4480
+ for (var i = 0; i < vlists.length; i++) {
4481
+ var vlistInstance = vlistInstance[0].f7VirtualList;
4482
+ if (vlistInstance) {
4483
+ vlistInstance.update();
4484
+ }
4485
+ }
4486
+ };
3969
4487
  /*======================================================
3970
4488
  ************ Pull To Refresh ************
3971
4489
  ======================================================*/
@@ -4135,18 +4653,24 @@
4135
4653
  =============================================================================== */
4136
4654
  function handleInfiniteScroll() {
4137
4655
  /*jshint validthis:true */
4138
- var inf = this;
4139
- var scrollTop = inf.scrollTop;
4140
- var scrollHeight = inf.scrollHeight;
4141
- var height = inf.offsetHeight;
4142
- var distance = inf.getAttribute('data-distance');
4656
+ var inf = $(this);
4657
+ var scrollTop = inf[0].scrollTop;
4658
+ var scrollHeight = inf[0].scrollHeight;
4659
+ var height = inf[0].offsetHeight;
4660
+ var distance = inf[0].getAttribute('data-distance');
4661
+ var virtualListContainer = inf.find('.virtual-list');
4662
+ var virtualList;
4143
4663
  if (!distance) distance = 50;
4144
4664
  if (typeof distance === 'string' && distance.indexOf('%') >= 0) {
4145
4665
  distance = parseInt(distance, 10) / 100 * height;
4146
4666
  }
4147
4667
  if (distance > height) distance = height;
4148
4668
  if (scrollTop + height >= scrollHeight - distance) {
4149
- $(inf).trigger('infinite');
4669
+ if (virtualListContainer.length > 0) {
4670
+ virtualList = virtualListContainer[0].f7VirtualList;
4671
+ if (virtualList && !virtualList.reachEnd) return;
4672
+ }
4673
+ inf.trigger('infinite');
4150
4674
  }
4151
4675
  }
4152
4676
  app.attachInfiniteScroll = function (infiniteContent) {
@@ -4176,29 +4700,44 @@
4176
4700
  if (scrollContent.length === 0) return;
4177
4701
  var hideNavbar = app.params.hideNavbarOnPageScroll || scrollContent.hasClass('hide-navbar-on-scroll') || scrollContent.hasClass('hide-bars-on-scroll');
4178
4702
  var hideToolbar = app.params.hideToolbarOnPageScroll || scrollContent.hasClass('hide-toolbar-on-scroll') || scrollContent.hasClass('hide-bars-on-scroll');
4179
- if (!(hideNavbar || hideToolbar)) return;
4703
+ var hideTabbar = app.params.hideTabbarOnPageScroll || scrollContent.hasClass('hide-tabbar-on-scroll');
4704
+
4705
+ if (!(hideNavbar || hideToolbar || hideTabbar)) return;
4180
4706
 
4181
4707
  var viewContainer = scrollContent.parents('.' + app.params.viewClass);
4182
4708
  if (viewContainer.length === 0) return;
4183
4709
 
4184
- var hasNavbar = viewContainer.find('.navbar').length > 0;
4185
- var hasToolbar = viewContainer.find('.toolbar').length > 0;
4710
+ var navbar = viewContainer.find('.navbar'),
4711
+ toolbar = viewContainer.find('.toolbar'),
4712
+ tabbar;
4713
+ if (hideTabbar) {
4714
+ tabbar = viewContainer.find('.tabbar');
4715
+ if (tabbar.length === 0) tabbar = viewContainer.parents('.' + app.params.viewsClass).find('.tabbar');
4716
+ }
4717
+
4718
+ var hasNavbar = navbar.length > 0,
4719
+ hasToolbar = toolbar.length > 0,
4720
+ hasTabbar = tabbar && tabbar.length > 0;
4186
4721
 
4187
4722
  var previousScroll, currentScroll;
4188
4723
  previousScroll = currentScroll = scrollContent[0].scrollTop;
4189
4724
 
4190
- var scrollHeight, offsetHeight, reachEnd, action, navbarHidden, toolbarHidden;
4725
+ var scrollHeight, offsetHeight, reachEnd, action, navbarHidden, toolbarHidden, tabbarHidden;
4191
4726
 
4192
- var toolbarHeight = (hasToolbar && hideToolbar) ? viewContainer.find('.toolbar')[0].offsetHeight : 0;
4727
+ var toolbarHeight = (hasToolbar && hideToolbar) ? toolbar[0].offsetHeight : 0;
4728
+ var tabbarHeight = (hasTabbar && hideTabbar) ? tabbar[0].offsetHeight : 0;
4729
+ var bottomBarHeight = tabbarHeight || toolbarHeight;
4193
4730
 
4194
4731
  function handleScroll(e) {
4195
4732
  if (pageContainer.hasClass('page-on-left')) return;
4196
4733
  currentScroll = scrollContent[0].scrollTop;
4197
4734
  scrollHeight = scrollContent[0].scrollHeight;
4198
4735
  offsetHeight = scrollContent[0].offsetHeight;
4199
- reachEnd = app.params.showBarsOnPageScrollEnd && (currentScroll + offsetHeight >= scrollHeight - toolbarHeight);
4200
- navbarHidden = viewContainer.hasClass('hidden-navbar');
4201
- toolbarHidden = viewContainer.hasClass('hidden-toolbar');
4736
+ reachEnd = app.params.showBarsOnPageScrollEnd && (currentScroll + offsetHeight >= scrollHeight - bottomBarHeight);
4737
+ navbarHidden = navbar.hasClass('navbar-hidden');
4738
+ toolbarHidden = toolbar.hasClass('toolbar-hidden');
4739
+ tabbarHidden = tabbar && tabbar.hasClass('toolbar-hidden');
4740
+
4202
4741
 
4203
4742
  if (previousScroll > currentScroll || reachEnd) {
4204
4743
  action = 'show';
@@ -4214,27 +4753,37 @@
4214
4753
 
4215
4754
  if (action === 'show') {
4216
4755
  if (hasNavbar && hideNavbar && navbarHidden) {
4217
- app.showNavbar(viewContainer);
4756
+ app.showNavbar(navbar);
4218
4757
  pageContainer.removeClass('no-navbar-by-scroll');
4219
4758
  navbarHidden = false;
4220
4759
  }
4221
4760
  if (hasToolbar && hideToolbar && toolbarHidden) {
4222
- app.showToolbar(viewContainer);
4761
+ app.showToolbar(toolbar);
4223
4762
  pageContainer.removeClass('no-toolbar-by-scroll');
4224
4763
  toolbarHidden = false;
4225
4764
  }
4765
+ if (hasTabbar && hideTabbar && tabbarHidden) {
4766
+ app.showToolbar(tabbar);
4767
+ pageContainer.removeClass('no-tabbar-by-scroll');
4768
+ tabbarHidden = false;
4769
+ }
4226
4770
  }
4227
4771
  else {
4228
4772
  if (hasNavbar && hideNavbar && !navbarHidden) {
4229
- app.hideNavbar(viewContainer);
4773
+ app.hideNavbar(navbar);
4230
4774
  pageContainer.addClass('no-navbar-by-scroll');
4231
4775
  navbarHidden = true;
4232
4776
  }
4233
4777
  if (hasToolbar && hideToolbar && !toolbarHidden) {
4234
- app.hideToolbar(viewContainer);
4778
+ app.hideToolbar(toolbar);
4235
4779
  pageContainer.addClass('no-toolbar-by-scroll');
4236
4780
  toolbarHidden = true;
4237
4781
  }
4782
+ if (hasTabbar && hideTabbar && !tabbarHidden) {
4783
+ app.hideToolbar(tabbar);
4784
+ pageContainer.addClass('no-tabbar-by-scroll');
4785
+ tabbarHidden = true;
4786
+ }
4238
4787
  }
4239
4788
 
4240
4789
  previousScroll = currentScroll;
@@ -4709,16 +5258,7 @@
4709
5258
  }
4710
5259
  // Check if link is external
4711
5260
  if (isLink) {
4712
- /*jshint shadow:true */
4713
- for (var i = 0; i < app.params.externalLinks.length; i++) {
4714
- if (clicked.hasClass(app.params.externalLinks[i])) {
4715
- return;
4716
- }
4717
-
4718
- if (clicked[0].rel === app.params.externalLinks[i]) {
4719
- return;
4720
- }
4721
- }
5261
+ if (clicked.is(app.params.externalLinks)) return;
4722
5262
  }
4723
5263
 
4724
5264
  // Smart Select
@@ -4861,7 +5401,8 @@
4861
5401
  else {
4862
5402
  view = clicked.parents('.' + app.params.viewClass)[0] && clicked.parents('.' + app.params.viewClass)[0].f7View;
4863
5403
  if (view && view.params.linksView) {
4864
- view = $(view.params.linksView)[0].f7View;
5404
+ if (typeof view.params.linksView === 'string') view = $(view.params.linksView)[0].f7View;
5405
+ else if (view.params.linksView instanceof View) view = view.params.linksView;
4865
5406
  }
4866
5407
  }
4867
5408
  if (!view) {
@@ -5398,8 +5939,17 @@
5398
5939
  }
5399
5940
  }
5400
5941
  };
5942
+
5943
+ function isFormElement(el) {
5944
+ var nn = el.nodeName.toLowerCase();
5945
+ if (nn === 'input' || nn === 'textarea' || nn === 'select') return true;
5946
+ return false;
5947
+ }
5948
+ s.touchedTarget = null;
5949
+ var hasFocused, hasBlured;
5401
5950
  s.onTouchStart = function (e) {
5402
5951
  if (s.params.onlyExternal) return;
5952
+ s.touchedTarget = e.target;
5403
5953
  isTouched = true;
5404
5954
  isMoved = false;
5405
5955
  isScrolling = undefined;
@@ -5409,7 +5959,11 @@
5409
5959
  s.allowClick = true;
5410
5960
  s.updateSize();
5411
5961
  if (s.params.onTouchStart) s.params.onTouchStart(s, e);
5412
- if (e.type === 'mousedown') e.preventDefault();
5962
+ hasFocused = hasBlured = false;
5963
+ if (e.type === 'mousedown') {
5964
+ if (!isFormElement(e.target)) e.preventDefault();
5965
+ }
5966
+
5413
5967
  };
5414
5968
  s.onTouchMove = function (e) {
5415
5969
  if (s.params.onTouchMove) s.params.onTouchMove(s, e);
@@ -5468,12 +6022,17 @@
5468
6022
  if (s.params.onTouchEnd) s.params.onTouchEnd(s, e);
5469
6023
  var touchEndTime = Date.now();
5470
6024
  var timeDiff = touchEndTime - touchStartTime;
6025
+ if (isFormElement(s.touchedTarget)) hasFocused = true;
6026
+ if (document.activeElement && document.activeElement !== s.touchedTarget && isFormElement(document.activeElement)) {
6027
+ document.activeElement.blur();
6028
+ hasBlured = true;
6029
+ }
5471
6030
  if (s.allowClick) {
5472
6031
  if (timeDiff < 300 && (touchEndTime - lastClickTime) > 300) {
5473
6032
  if (clickTimeout) clearTimeout(clickTimeout);
5474
6033
  clickTimeout = setTimeout(function () {
5475
6034
  if (!s) return;
5476
- if (s.params.paginationHide && s.paginationContainer) {
6035
+ if (s.params.paginationHide && s.paginationContainer && !hasBlured && !hasFocused) {
5477
6036
  s.paginationContainer.toggleClass('slider-pagination-hidden');
5478
6037
  }
5479
6038
  if (s.params.onClick) s.params.onClick(s, e);
@@ -5667,9 +6226,14 @@
5667
6226
  s.wrapper.transitionEnd(function () {
5668
6227
  s.startAutoplay();
5669
6228
  });
5670
- var index = s.activeSlideIndex + 1;
5671
- if (index > s.slides.length - s.params.slidesPerView) index = 0;
5672
- s.slideTo(index);
6229
+ if (s.params.loop) {
6230
+ s.slideNext();
6231
+ }
6232
+ else {
6233
+ var index = s.activeSlideIndex + 1;
6234
+ if (index > s.slides.length - s.params.slidesPerView) index = 0;
6235
+ s.slideTo(index);
6236
+ }
5673
6237
  }, s.params.autoplay);
5674
6238
  };
5675
6239
  s.stopAutoplay = function () {
@@ -6575,11 +7139,11 @@
6575
7139
  if (!window.Template7) return;
6576
7140
  Template7.templates = Template7.templates || app.params.templates || {};
6577
7141
  Template7.data = Template7.data || app.params.template7Data || {};
6578
- Template7.templatesCache = {};
7142
+ Template7.template7Cache = {};
6579
7143
 
6580
7144
  app.templates = Template7.templates;
6581
7145
  app.template7Data = Template7.data;
6582
- app.templatesCache = Template7.templatesCache;
7146
+ app.template7Cache = Template7.cache;
6583
7147
 
6584
7148
  // Precompile templates on app init
6585
7149
  if (!app.params.precompileTemplates) return;
@@ -6655,7 +7219,7 @@
6655
7219
  if (viewContainer) {
6656
7220
  viewContainer.attr('data-page', pageContainer.attr('data-page') || undefined);
6657
7221
  }
6658
- app.pageInitCallback(view, this, url, 'center');
7222
+ app.pageInitCallback(view, {pageContainer: this, url: url, position: 'center'});
6659
7223
  });
6660
7224
 
6661
7225
  // Init resize events