framework7-rails 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ac8e985ee5be7ecab0fa90179dd2d64d996c8fcb
4
+ data.tar.gz: 60e7fc36991900ddbd5bbfe9a7267d7870698691
5
+ SHA512:
6
+ metadata.gz: 9f63d0b48d8b2785104923d0c5dc421044491dc7d5eaa977767cb76b3c253fbc370a7c6521ead8fec30e1b3bf2f6072084a5eb15d470ff78777a2cbe9f905b7c
7
+ data.tar.gz: 21536ff6294db422bf888512dedb1e916f764ded745f3a34b2ee9af3afef0d9ca01ee8483e27bac8526d45a1996d6af08da0c5f3fb74090f9d0a62755a8b4d1d
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in framework7-rails.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 TWSS
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,53 @@
1
+ # Framework7::Rails
2
+
3
+ Brings the excellent [Framework7](https://github.com/nolimits4web/framework7/) into the Rails 3.1+ Asset Pipeline.
4
+
5
+ The gem version number ``x.y.z`` is kept in sync with the version of Framework7 being supported.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'framework7-rails'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or, install it yourself as:
18
+
19
+ $ gem install framework7-rails
20
+
21
+ ## Usage
22
+
23
+ ### Development/Debugging
24
+
25
+ In your application.js file, add the line:
26
+
27
+ //= require framework7
28
+
29
+ In your application.css file, add the line:
30
+
31
+ *= require framework7
32
+
33
+ ### Production
34
+
35
+ In your application.js file, add the line:
36
+
37
+ //= require framework7.min
38
+
39
+ In your application.css file, add the line:
40
+
41
+ *= require framework7.min
42
+
43
+ ## Future Improvements
44
+
45
+ Currently, the gem only brings in the assets. But it is the intention to add layout/view generators and helpers.
46
+
47
+ ## Contributing
48
+
49
+ 1. Fork it ( http://github.com/twss/framework7-rails/fork )
50
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
51
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
52
+ 4. Push to the branch (`git push origin my-new-feature`)
53
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'framework7/rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "framework7-rails"
8
+ spec.version = Framework7::Rails::VERSION
9
+ spec.authors = ["Terry Wilson"]
10
+ spec.email = ["terry.wilson@twss.co.uk"]
11
+ spec.summary = %q{Framework7 for Rails 3.1+ Asset Pipeline.}
12
+ spec.description = %q{Adds support for Framework7 to the Asset Pipeline.}
13
+ spec.homepage = "https://github.com/twss/framework7-rails"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake", "~> 0"
23
+ end
@@ -0,0 +1,8 @@
1
+ require "framework7/rails/version"
2
+
3
+ module Framework7
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Framework7
2
+ module Rails
3
+ VERSION = "0.6.8"
4
+ end
5
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,2429 @@
1
+ /*
2
+ * Framework7 0.6.8
3
+ * Full Featured HTML Framework For Building iOS7 Apps
4
+ *
5
+ * http://www.idangero.us/framework7
6
+ *
7
+ * Copyright 2014, Vladimir Kharlampidi
8
+ * The iDangero.us
9
+ * http://www.idangero.us/
10
+ *
11
+ * Licensed under MIT
12
+ *
13
+ * Released on: April 6, 2014
14
+ */
15
+ (function () {
16
+
17
+ 'use strict';
18
+ /*===========================
19
+ Framework 7
20
+ ===========================*/
21
+ window.Framework7 = function (params) {
22
+
23
+ // App
24
+ var app = this;
25
+
26
+ // Anim Frame
27
+ app._animFrame = function (callback) {
28
+ if (window.requestAnimationFrame) return window.requestAnimationFrame(callback);
29
+ else if (window.webkitRequestAnimationFrame) return window.webkitRequestAnimationFrame(callback);
30
+ else if (window.mozRequestAnimationFrame) return window.mozRequestAnimationFrame(callback);
31
+ else {
32
+ return window.setTimeout(callback, 1000 / 60);
33
+ }
34
+ };
35
+
36
+ // Default Parameters
37
+ app.params = {
38
+ cache: true,
39
+ cacheDuration: 1000 * 60 * 10, // Ten minutes
40
+ preloadPreviousPage: true,
41
+ // Swipe Back
42
+ swipeBackPage: true,
43
+ swipeBackPageThreshold: 0,
44
+ swipeBackPageActiveArea: 30,
45
+ swipeBackPageBoxShadow: true,
46
+ // Ajax
47
+ ajaxLinks: false, // or CSS selector
48
+ // Pull To Refresh
49
+ pullToRefresh: true,
50
+ // Swipeout
51
+ swipeout: true,
52
+ swipeoutNoFollow: false,
53
+ // Panels
54
+ panelsCloseByOutside: true,
55
+ panelsVisibleZIndex: 6000,
56
+ panelsAnimationDuration: 400,
57
+ // Modals
58
+ modalTemplate: '<div class="modal {{noButtons}}">' +
59
+ '<div class="modal-inner">' +
60
+ '{{if title}}<div class="modal-title">{{title}}</div>{{/if title}}' +
61
+ '<div class="modal-text">{{text}}</div>' +
62
+ '{{afterText}}' +
63
+ '</div>' +
64
+ '<div class="modal-buttons">{{buttons}}</div>' +
65
+ '</div>',
66
+ modalActionsTemplate: '<div class="actions-modal">{{buttons}}</div>',
67
+ modalButtonOk: 'OK',
68
+ modalButtonCancel: 'Cancel',
69
+ modalTitle: 'Framework7',
70
+ modalCloseByOutside: false,
71
+ modalActionsCloseByOutside: true,
72
+ modalPopupCloseByOutside: true,
73
+ modalPreloaderTitle: 'Loading... ',
74
+ // Auto init
75
+ init: true
76
+ };
77
+
78
+ // Extend defaults with parameters
79
+ for (var param in params) {
80
+ app.params[param] = params[param];
81
+ }
82
+
83
+ // Expose DOM lib
84
+ app.$ = $;
85
+
86
+ // Touch events
87
+ app.touchEvents = {
88
+ start: $.supportTouch ? 'touchstart' : 'mousedown',
89
+ move: $.supportTouch ? 'touchmove' : 'mousemove',
90
+ end: $.supportTouch ? 'touchend' : 'mouseup'
91
+ };
92
+
93
+ /*======================================================
94
+ ************ Views ************
95
+ ======================================================*/
96
+ app.views = [];
97
+ app.addView = function (viewSelector, viewParams) {
98
+ if (!viewSelector) return;
99
+ var container = $(viewSelector)[0];
100
+ var view = {
101
+ container: container,
102
+ selector: viewSelector,
103
+ params: viewParams || {},
104
+ history: [],
105
+ contentCache: {},
106
+ url: '',
107
+ pagesContainer: $('.pages', container)[0],
108
+ main: $(container).hasClass('view-main'),
109
+ loadContent: function (content) {
110
+ app.loadContent(view, content);
111
+ },
112
+ loadPage: function (url) {
113
+ app.loadPage(view, url);
114
+ },
115
+ goBack: function (url) {
116
+ app.goBack(view, url);
117
+ },
118
+ hideNavbar: function () {
119
+ app.hideNavbar(container);
120
+ },
121
+ showNavbar: function () {
122
+ app.showNavbar(container);
123
+ },
124
+ hideToolbar: function () {
125
+ app.hideToolbar(container);
126
+ },
127
+ showToolbar: function () {
128
+ app.showToolbar(container);
129
+ }
130
+ };
131
+ // Store to history main view's url
132
+ if (view.main) {
133
+ view.url = document.location.href;
134
+ view.history.push(view.url);
135
+ }
136
+ // Store View in element for easy access
137
+ container.f7View = view;
138
+
139
+ // Add view to app
140
+ app.views.push(view);
141
+
142
+ // Init View's events
143
+ app.initViewEvents(view);
144
+
145
+ // Return view object
146
+ return view;
147
+ };
148
+
149
+ // Live Events on view links
150
+ app.initViewEvents = function (view) {
151
+ if (!app.params.swipeBackPage) return;
152
+ // Swipe Back to previous page
153
+ var viewContainer = $(view.container),
154
+ isTouched = false,
155
+ isMoved = false,
156
+ touchesStart = {},
157
+ isScrolling,
158
+ activePage,
159
+ previousPage,
160
+ viewContainerWidth,
161
+ touchesDiff,
162
+ allowViewTouchMove = true,
163
+ touchStartTime,
164
+ activeNavbar,
165
+ previousNavbar,
166
+ activeNavElements,
167
+ previousNavElements,
168
+ i,
169
+ dynamicNavbar,
170
+ el;
171
+
172
+ function handleTouchStart(e, target) {
173
+ if (!allowViewTouchMove || !app.params.swipeBackPage || isTouched || app.swipeoutOpenedEl) return;
174
+ isMoved = false;
175
+ isTouched = true;
176
+ isScrolling = undefined;
177
+ touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
178
+ touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
179
+ touchStartTime = (new Date()).getTime();
180
+ dynamicNavbar = view.params.dynamicNavbar && viewContainer.find('.navbar-inner').length > 1;
181
+ }
182
+
183
+ function handleTouchMove(e, target) {
184
+ if (!isTouched) return;
185
+ var pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
186
+ var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
187
+ if (typeof isScrolling === 'undefined') {
188
+ isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
189
+ }
190
+ if (isScrolling) {
191
+ isTouched = false;
192
+ return;
193
+ }
194
+
195
+ if (!isMoved) {
196
+ var cancel = false;
197
+ // Calc values during first move fired
198
+ viewContainerWidth = viewContainer.width();
199
+ activePage = $(target || e.target).is('.page') ? $(target || e.target) : $(target || e.target).parents('.page');
200
+ previousPage = viewContainer.find('.page-on-left:not(.cached)');
201
+ if (touchesStart.x - viewContainer.offset().left > app.params.swipeBackPageActiveArea) cancel = true;
202
+ if (previousPage.length === 0 || activePage.length === 0) cancel = true;
203
+ if (cancel) {
204
+ isTouched = false;
205
+ return;
206
+ }
207
+ if (dynamicNavbar) {
208
+ activeNavbar = viewContainer.find('.navbar-on-center:not(.cached)');
209
+ previousNavbar = viewContainer.find('.navbar-on-left:not(.cached)');
210
+ activeNavElements = activeNavbar.find('.left, .center, .right');
211
+ previousNavElements = previousNavbar.find('.left, .center, .right');
212
+ }
213
+ }
214
+ isMoved = true;
215
+
216
+ e.preventDefault();
217
+ touchesDiff = pageX - touchesStart.x - app.params.swipeBackPageThreshold;
218
+ if (touchesDiff < 0) touchesDiff = 0;
219
+ var percentage = touchesDiff / viewContainerWidth;
220
+
221
+ // Transform pages
222
+ activePage.transform('translate3d(' + touchesDiff + 'px,0,0)');
223
+ if (app.params.swipeBackPageBoxShadow && app.device.os !== 'android') activePage[0].style.boxShadow = '0px 0px 12px rgba(0,0,0,' + (0.5 - 0.5 * percentage) + ')';
224
+
225
+ var pageTranslate = (touchesDiff / 5 - viewContainerWidth / 5);
226
+ if (app.device.pixelRatio === 1) pageTranslate = Math.round(pageTranslate);
227
+
228
+ previousPage.transform('translate3d(' + pageTranslate + 'px,0,0)');
229
+ previousPage[0].style.opacity = 0.9 + 0.1 * percentage;
230
+
231
+ // Dynamic Navbars Animation
232
+ if (dynamicNavbar) {
233
+ for (i = 0; i < activeNavElements.length; i++) {
234
+ el = $(activeNavElements[i]);
235
+ el[0].style.opacity = (1 - percentage * 1.3);
236
+ if (el[0].className.indexOf('sliding') >= 0) {
237
+ var activeNavTranslate = percentage * el[0].f7NavbarRightOffset;
238
+ if (app.device.pixelRatio === 1) activeNavTranslate = Math.round(activeNavTranslate);
239
+ el.transform('translate3d(' + activeNavTranslate + 'px,0,0)');
240
+ }
241
+ }
242
+ for (i = 0; i < previousNavElements.length; i++) {
243
+ el = $(previousNavElements[i]);
244
+ el[0].style.opacity = percentage * 1.3 - 0.3;
245
+ if (el[0].className.indexOf('sliding') >= 0) {
246
+ var previousNavTranslate = el[0].f7NavbarLeftOffset * (1 - percentage);
247
+ if (app.device.pixelRatio === 1) previousNavTranslate = Math.round(previousNavTranslate);
248
+ el.transform('translate3d(' + previousNavTranslate + 'px,0,0)');
249
+ }
250
+ }
251
+ }
252
+
253
+ }
254
+ function handleTouchEnd(e, target) {
255
+ if (!isTouched || !isMoved) {
256
+ isTouched = false;
257
+ isMoved = false;
258
+ return;
259
+ }
260
+ isTouched = false;
261
+ isMoved = false;
262
+ var timeDiff = (new Date()).getTime() - touchStartTime;
263
+ var pageChanged = false;
264
+ // Swipe back to previous page
265
+ if (
266
+ timeDiff < 300 && touchesDiff > 10 ||
267
+ timeDiff >= 300 && touchesDiff > viewContainerWidth / 2
268
+ ) {
269
+ activePage.removeClass('page-on-center').addClass('page-on-right');
270
+ previousPage.removeClass('page-on-left').addClass('page-on-center');
271
+ if (dynamicNavbar) {
272
+ activeNavbar.removeClass('navbar-on-center').addClass('navbar-on-right');
273
+ previousNavbar.removeClass('navbar-on-left').addClass('navbar-on-center');
274
+ }
275
+ pageChanged = true;
276
+ }
277
+ // Reset custom styles
278
+ // Add transitioning class for transition-duration
279
+ $([activePage[0], previousPage[0]]).transform('').css({opacity: '', boxShadow: ''}).addClass('page-transitioning');
280
+ if (dynamicNavbar) {
281
+ activeNavElements.css({opacity: ''})
282
+ .each(function () {
283
+ var translate = pageChanged ? this.f7NavbarRightOffset : 0;
284
+ $(this).transform('translate3d(' + translate + 'px,0,0)');
285
+ }).addClass('page-transitioning');
286
+
287
+ previousNavElements.transform('').css({opacity: ''}).each(function () {
288
+ var translate = pageChanged ? 0 : this.f7NavbarLeftOffset;
289
+ $(this).transform('translate3d(' + translate + 'px,0,0)');
290
+ }).addClass('page-transitioning');
291
+ }
292
+ allowViewTouchMove = false;
293
+ app.allowPageChange = false;
294
+
295
+ if (pageChanged) {
296
+ // Update View's URL
297
+ var url = view.history[view.history.length - 2];
298
+ view.url = url;
299
+
300
+ // Page before animation callback
301
+ app.pageAnimCallbacks('before', view, {pageContainer: previousPage[0], url: url, position: 'left', newPage: previousPage, oldPage: activePage});
302
+ }
303
+
304
+ activePage.transitionEnd(function () {
305
+ $([activePage[0], previousPage[0]]).removeClass('page-transitioning');
306
+ if (dynamicNavbar) {
307
+ activeNavElements.removeClass('page-transitioning');
308
+ activeNavElements.transform('').css({opacity: ''});
309
+ previousNavElements.removeClass('page-transitioning');
310
+ previousNavElements.transform('').css({opacity: ''});
311
+ }
312
+ allowViewTouchMove = true;
313
+ app.allowPageChange = true;
314
+ if (pageChanged) app.afterGoBack(view, activePage, previousPage);
315
+ });
316
+ }
317
+
318
+ viewContainer.on(app.touchEvents.start, handleTouchStart);
319
+ viewContainer.on(app.touchEvents.move, handleTouchMove);
320
+ viewContainer.on(app.touchEvents.end, handleTouchEnd);
321
+
322
+ view.attachSubEvents = function (page, el) {
323
+ $(el).on(app.touchEvents.start, function (e) {
324
+ return handleTouchStart.apply(page, [e, page]);
325
+ });
326
+ $(el).on(app.touchEvents.move, function (e) {
327
+ return handleTouchMove.apply(page, [e, page]);
328
+ });
329
+ $(el).on(app.touchEvents.end, function (e, page) {
330
+ return handleTouchEnd.apply(page, [e, page]);
331
+ });
332
+ };
333
+ };
334
+ /*======================================================
335
+ ************ Navbars && Toolbars ************
336
+ ======================================================*/
337
+ app.sizeNavbars = function (viewContainer) {
338
+ var navbarInner = viewContainer ? $(viewContainer).find('.navbar .navbar-inner:not(.cached)') : $('.navbar .navbar-inner:not(.cached)');
339
+ navbarInner.each(function () {
340
+ var tt = $(this),
341
+ left = tt.find('.left'),
342
+ right = tt.find('.right'),
343
+ center = tt.find('.center'),
344
+ noLeft = left.length === 0,
345
+ noRight = right.length === 0,
346
+ leftWidth = noLeft ? 0 : left.outerWidth(true),
347
+ rightWidth = noRight ? 0 : right.outerWidth(true),
348
+ centerWidth = center.outerWidth(true),
349
+ navbarWidth = tt.width(),
350
+ currLeft, diff;
351
+
352
+ if (noRight) {
353
+ currLeft = navbarWidth - centerWidth;
354
+ }
355
+ if (noLeft) {
356
+ currLeft = 0;
357
+ }
358
+ if (!noLeft && !noRight) {
359
+ currLeft = (navbarWidth - rightWidth - centerWidth + leftWidth) / 2;
360
+ }
361
+ var requiredLeft = (navbarWidth - centerWidth) / 2;
362
+ if (navbarWidth - leftWidth - rightWidth > centerWidth) {
363
+ if (requiredLeft < leftWidth) {
364
+ requiredLeft = leftWidth;
365
+ }
366
+ if (requiredLeft + centerWidth > navbarWidth - rightWidth) {
367
+ requiredLeft = navbarWidth - rightWidth - centerWidth;
368
+ }
369
+ diff = requiredLeft - currLeft;
370
+ }
371
+ else {
372
+ diff = 0;
373
+ }
374
+ center.css({left: diff + 'px'});
375
+ if (center.hasClass('sliding')) {
376
+ center[0].f7NavbarLeftOffset = -(currLeft + diff);
377
+ center[0].f7NavbarRightOffset = navbarWidth - currLeft - diff - centerWidth;
378
+ }
379
+ if (!noLeft && left.hasClass('sliding')) {
380
+ left[0].f7NavbarLeftOffset = -leftWidth;
381
+ left[0].f7NavbarRightOffset = (navbarWidth - left.outerWidth()) / 2;
382
+ }
383
+ if (!noRight && right.hasClass('sliding')) {
384
+ right[0].f7NavbarLeftOffset = -(navbarWidth - right.outerWidth()) / 2;
385
+ right[0].f7NavbarRightOffset = rightWidth;
386
+ }
387
+
388
+ });
389
+ };
390
+ app.hideNavbar = function (viewContainer) {
391
+ $(viewContainer).addClass('hidden-navbar');
392
+ return true;
393
+ };
394
+ app.showNavbar = function (viewContainer) {
395
+ var vc = $(viewContainer);
396
+ vc.addClass('hiding-navbar').removeClass('hidden-navbar').find('.navbar').transitionEnd(function () {
397
+ vc.removeClass('hiding-navbar');
398
+ });
399
+ return true;
400
+ };
401
+ app.hideToolbar = function (viewContainer) {
402
+ $(viewContainer).addClass('hidden-toolbar');
403
+ return true;
404
+ };
405
+ app.showToolbar = function (viewContainer) {
406
+ var vc = $(viewContainer);
407
+ vc.addClass('hiding-toolbar').removeClass('hidden-toolbar').find('.toolbar').transitionEnd(function () {
408
+ vc.removeClass('hiding-toolbar');
409
+ });
410
+ };
411
+ /*======================================================
412
+ ************ XHR ************
413
+ ======================================================*/
414
+ // XHR Caching
415
+ app.cache = [];
416
+ app.removeFromCache = function (url) {
417
+ var index = false;
418
+ for (var i = 0; i < app.cache.length; i++) {
419
+ if (app.cache[i].url === url) index = i;
420
+ }
421
+ if (index !== false) app.cache.splice(index, 1);
422
+ };
423
+
424
+ // XHR
425
+ app.xhr = false;
426
+ app.get = function (url, callback) {
427
+ if (app.params.cache) {
428
+ // Check is the url cached
429
+ for (var i = 0; i < app.cache.length; i++) {
430
+ if (app.cache[i].url === url) {
431
+ // Check expiration
432
+ if ((new Date()).getTime() - app.cache[i].time < app.params.cacheDuration) {
433
+ // Load from cache
434
+ callback(app.cache[i].data);
435
+ return false;
436
+ }
437
+ }
438
+ }
439
+ }
440
+ var xhr = new XMLHttpRequest();
441
+ xhr.open('GET', url, true);
442
+ xhr.onload = function (e) {
443
+ if (app.params.onAjaxComplete) {
444
+ app.params.onAjaxComplete(xhr);
445
+ $(document).trigger('ajaxComplete', {xhr: xhr});
446
+ }
447
+ if (callback) {
448
+ if (this.status === 200 || this.status === 0) {
449
+ callback(this.responseText, false);
450
+ if (app.params.cache) {
451
+ app.removeFromCache(url);
452
+ app.cache.push({
453
+ url: url,
454
+ time: (new Date()).getTime(),
455
+ data: this.responseText
456
+ });
457
+ }
458
+ }
459
+ else {
460
+ callback(this.responseText, true);
461
+ }
462
+ }
463
+ };
464
+ if (app.params.onAjaxStart) {
465
+ app.params.onAjaxStart(xhr);
466
+ $(document).trigger('ajaxStart', {xhr: xhr});
467
+ }
468
+ app.xhr = xhr;
469
+ xhr.send();
470
+ return xhr;
471
+ };
472
+ /*======================================================
473
+ ************ Pages ************
474
+ ======================================================*/
475
+ // On Page Init Callback
476
+ app.pageInitCallback = function (view, pageContainer, url, position) {
477
+ if (pageContainer.f7PageInitialized) return;
478
+ pageContainer.f7PageInitialized = true;
479
+ // Page Data
480
+ var pageData = {
481
+ container: pageContainer,
482
+ url: url,
483
+ query: $.parseUrlQuery(url || ''),
484
+ name: $(pageContainer).attr('data-page'),
485
+ view: view,
486
+ from: position
487
+ };
488
+ // Before Init Callback
489
+ if (app.params.onPageBeforeInit) {
490
+ app.params.onPageBeforeInit(pageData);
491
+ }
492
+ if (view.params.onPageBeforeInit) {
493
+ view.params.onPageBeforeInit(pageData);
494
+ }
495
+ $(document).trigger('pageBeforeInit', {page: pageData});
496
+ app.initPage(pageContainer);
497
+ // Init Callback
498
+ if (app.params.onPageInit) {
499
+ app.params.onPageInit(pageData);
500
+ }
501
+ if (view.params.onPageInit) {
502
+ view.params.onPageInit(pageData);
503
+ }
504
+ $(document).trigger('pageInit', {page: pageData});
505
+ };
506
+ app.pageAnimCallbacks = function (callback, view, params) {
507
+ // Page Data
508
+ var pageData = {
509
+ container: params.pageContainer,
510
+ url: params.url,
511
+ query: $.parseUrlQuery(params.url || ''),
512
+ name: $(params.pageContainer).attr('data-page'),
513
+ view: view,
514
+ from: params.position
515
+ };
516
+ var oldPage = params.oldPage,
517
+ newPage = params.newPage;
518
+
519
+ if (callback === 'after') {
520
+ if (app.params.onPageAfterAnimation) {
521
+ app.params.onPageAfterAnimation(pageData);
522
+ }
523
+ if (view.params.onPageAfterAnimation) {
524
+ view.params.onPageAfterAnimation(pageData);
525
+ }
526
+ $(document).trigger('pageAfterAnimation', {page: pageData});
527
+
528
+ }
529
+ if (callback === 'before') {
530
+ // Hide/show navbar dynamically
531
+ if (newPage.hasClass('no-navbar') && !oldPage.hasClass('no-navbar')) {
532
+ view.hideNavbar();
533
+ }
534
+ if (!newPage.hasClass('no-navbar') && oldPage.hasClass('no-navbar')) {
535
+ view.showNavbar();
536
+ }
537
+ // Hide/show navbar toolbar
538
+ if (newPage.hasClass('no-toolbar') && !oldPage.hasClass('no-toolbar')) {
539
+ view.hideToolbar();
540
+ }
541
+ if (!newPage.hasClass('no-toolbar') && oldPage.hasClass('no-toolbar')) {
542
+ view.showToolbar();
543
+ }
544
+ // Callbacks
545
+ if (app.params.onPageBeforeAnimation) {
546
+ app.params.onPageBeforeAnimation(pageData);
547
+ }
548
+ if (view.params.onPageBeforeAnimation) {
549
+ view.params.onPageBeforeAnimation(pageData);
550
+ }
551
+ $(document).trigger('pageBeforeAnimation', {page: pageData});
552
+ }
553
+ };
554
+ // Init Page Events and Manipulations
555
+ app.initPage = function (pageContainer) {
556
+ // Size navbars on page load
557
+ if (app.sizeNavbars) app.sizeNavbars($(pageContainer).parents('.view')[0]);
558
+ // Init messages
559
+ if (app.initMessages) app.initMessages(pageContainer);
560
+ };
561
+ // Load Page
562
+ app.allowPageChange = true;
563
+ app._tempDomElement = document.createElement('div');
564
+
565
+ function _load(view, url, content) {
566
+ var viewContainer = $(view.container),
567
+ newPage, oldPage, pagesInView, i, oldNavbarInner, newNavbarInner, navbar, dynamicNavbar;
568
+
569
+ // Parse DOM to find new page
570
+ if (url || (typeof content === 'string')) {
571
+ app._tempDomElement.innerHTML = content;
572
+ } else {
573
+ if ('length' in content && content.length > 1) {
574
+ app._tempDomElement = document.createElement('div');
575
+ for (var ci = 0; ci < content.length; ci++) {
576
+ $(app._tempDomElement).append(content[ci]);
577
+ }
578
+ } else {
579
+ app._tempDomElement.innerHTML = '';
580
+ $(app._tempDomElement).append(content);
581
+ }
582
+ }
583
+
584
+ if (view.params.subEvents) {
585
+ $(app._tempDomElement).find('.page').each(function () {
586
+ var page = this;
587
+ $(page).find('iframe').on('load', function () {
588
+ view.attachSubEvents(page, this.contentWindow.document);
589
+ });
590
+ });
591
+ }
592
+
593
+ newPage = $('.page', app._tempDomElement);
594
+ if (newPage.length > 1) {
595
+ newPage = $(app._tempDomElement).find('.view-main .page');
596
+ }
597
+
598
+ // If pages not found or there are still more than one, exit
599
+ if (newPage.length === 0 || newPage.length > 1) {
600
+ app.allowPageChange = true;
601
+ return;
602
+ }
603
+ newPage.addClass('page-on-right');
604
+
605
+ // Find old page (should be the last one) and remove older pages
606
+ pagesInView = viewContainer.find('.page:not(.cached)');
607
+ if (pagesInView.length > 1) {
608
+ for (i = 0; i < pagesInView.length - 2; i++) {
609
+ if (!view.params.domCache)
610
+ $(pagesInView[i]).remove();
611
+ else
612
+ $(pagesInView[i]).addClass('cached');
613
+ }
614
+ if (!view.params.domCache)
615
+ $(pagesInView[i]).remove();
616
+ else
617
+ $(pagesInView[i]).addClass('cached');
618
+ }
619
+
620
+ oldPage = viewContainer.find('.page:not(.cached)');
621
+
622
+ // Dynamic navbar
623
+ if (view.params.dynamicNavbar) {
624
+ dynamicNavbar = true;
625
+ // Find navbar
626
+ newNavbarInner = $('.navbar-inner', app._tempDomElement);
627
+ if (newNavbarInner.length > 1) {
628
+ newNavbarInner = $('.view-main .navbar-inner', app._tempDomElement);
629
+ }
630
+ if (newNavbarInner.length === 0 || newNavbarInner > 1) {
631
+ dynamicNavbar = false;
632
+ }
633
+ navbar = viewContainer.find('.navbar');
634
+ oldNavbarInner = navbar.find('.navbar-inner:not(.cached)');
635
+ if (oldNavbarInner.length > 0) {
636
+ for (i = 0; i < oldNavbarInner.length - 1; i++) {
637
+ if (!view.params.domCache)
638
+ $(oldNavbarInner[i]).remove();
639
+ else
640
+ $(oldNavbarInner[i]).addClass('cached');
641
+ }
642
+ if (newNavbarInner.length === 0 && oldNavbarInner.length === 1) {
643
+ if (!view.params.domCache)
644
+ $(oldNavbarInner[0]).remove();
645
+ else
646
+ $(oldNavbarInner[0]).addClass('cached');
647
+ }
648
+ oldNavbarInner = navbar.find('.navbar-inner:not(.cached)');
649
+ }
650
+ }
651
+ if (dynamicNavbar) {
652
+ newNavbarInner.addClass('navbar-on-right');
653
+ navbar.append(newNavbarInner[0]);
654
+ }
655
+
656
+ // save content areas into view's cache
657
+ if (!url) {
658
+ url = '#content-' + view.history.length;
659
+
660
+ if (!view.params.domCache) {
661
+ if (view.history.length === 1) {
662
+ view.contentCache[view.history[0]] = { nav: oldNavbarInner, page: oldPage };
663
+ }
664
+ view.contentCache[url] = { nav: newNavbarInner, page: newPage };
665
+ }
666
+ }
667
+
668
+ // Update View history
669
+ view.url = url;
670
+ view.history.push(url);
671
+
672
+ // Append Old Page and add classes for animation
673
+ $(view.pagesContainer).append(newPage[0]);
674
+
675
+ // Page Init Events
676
+ app.pageInitCallback(view, newPage[0], url, 'right');
677
+
678
+ if (dynamicNavbar) {
679
+ newNavbarInner.find('.sliding').each(function () {
680
+ $(this).transform('translate3d(' + (this.f7NavbarRightOffset) + 'px,0,0)');
681
+ });
682
+ }
683
+ // Force reLayout
684
+ var clientLeft = newPage[0].clientLeft;
685
+
686
+ // Before Anim Callback
687
+ app.pageAnimCallbacks('before', view, {pageContainer: newPage[0], url: url, position: 'left', oldPage: oldPage, newPage: newPage});
688
+
689
+ newPage.addClass('page-from-right-to-center');
690
+ oldPage.addClass('page-from-center-to-left').removeClass('page-on-center');
691
+
692
+ // Dynamic navbar animation
693
+ if (dynamicNavbar) {
694
+ newNavbarInner.removeClass('navbar-on-right').addClass('navbar-from-right-to-center');
695
+ newNavbarInner.find('.sliding').each(function () {
696
+ $(this).transform('translate3d(0px,0,0)');
697
+ });
698
+ oldNavbarInner.removeClass('navbar-on-center').addClass('navbar-from-center-to-left');
699
+ oldNavbarInner.find('.sliding').each(function () {
700
+ $(this).transform('translate3d(' + (this.f7NavbarLeftOffset) + 'px,0,0)');
701
+ });
702
+ }
703
+
704
+ newPage.animationEnd(function (e) {
705
+ app.allowPageChange = true;
706
+ newPage.toggleClass('page-from-right-to-center page-on-center page-on-right');
707
+ oldPage.toggleClass('page-from-center-to-left page-on-left');
708
+ if (dynamicNavbar) {
709
+ newNavbarInner.toggleClass('navbar-from-right-to-center navbar-on-center');
710
+ oldNavbarInner.toggleClass('navbar-from-center-to-left navbar-on-left');
711
+ }
712
+ app.pageAnimCallbacks('after', view, {pageContainer: newPage[0], url: url, position: 'right', oldPage: oldPage, newPage: newPage});
713
+ });
714
+ }
715
+ app.loadContent = function (view, content) {
716
+ if (!app.allowPageChange) return false;
717
+ app.allowPageChange = false;
718
+ if (app.xhr) {
719
+ app.xhr.abort();
720
+ app.xhr = false;
721
+ }
722
+
723
+ _load(view, null, content);
724
+
725
+ app.allowPageChange = true;
726
+ };
727
+ app.loadPage = function (view, url) {
728
+ if (!app.allowPageChange) return false;
729
+ if (view.url === url) return false;
730
+ app.allowPageChange = false;
731
+ if (app.xhr) {
732
+ app.xhr.abort();
733
+ app.xhr = false;
734
+ }
735
+ app.get(url, function (data, error) {
736
+ if (error) {
737
+ app.allowPageChange = true;
738
+ return;
739
+ }
740
+
741
+ _load(view, url, data);
742
+
743
+ });
744
+ };
745
+ app.goBack = function (view, url, preloadOnly) {
746
+ if (!app.allowPageChange) return false;
747
+ app.allowPageChange = false;
748
+ if (app.xhr) {
749
+ app.xhr.abort();
750
+ app.xhr = false;
751
+ }
752
+
753
+ var viewContainer = $(view.container),
754
+ pagesInView = viewContainer.find('.page'),
755
+ oldPage, newPage, oldNavbarInner, newNavbarInner, navbar, dynamicNavbar;
756
+
757
+ function _preload() {
758
+ newPage = $('.page', app._tempDomElement);
759
+ if (newPage.length > 1) {
760
+ newPage = $(app._tempDomElement).find('.view-main .page');
761
+ }
762
+
763
+ // If pages not found or there are still more than one, exit
764
+ if (newPage.length === 0 || newPage.length > 1) {
765
+ app.allowPageChange = true;
766
+ return;
767
+ }
768
+ newPage.addClass('page-on-left');
769
+
770
+ // Find old page (should be the only one)
771
+ oldPage = $(viewContainer.find('.page')[0]);
772
+
773
+ // Dynamic navbar
774
+ if (view.params.dynamicNavbar) {
775
+ dynamicNavbar = true;
776
+ // Find navbar
777
+ newNavbarInner = $('.navbar-inner', app._tempDomElement);
778
+ if (newNavbarInner.length > 1) {
779
+ newNavbarInner = $('.view-main .navbar-inner', app._tempDomElement);
780
+ }
781
+ if (newNavbarInner.length === 0 || newNavbarInner > 1) {
782
+ dynamicNavbar = false;
783
+ }
784
+
785
+ }
786
+
787
+ if (dynamicNavbar) {
788
+ navbar = viewContainer.find('.navbar');
789
+ oldNavbarInner = navbar.find('.navbar-inner');
790
+ newNavbarInner.addClass(oldNavbarInner.length > 0 ? 'navbar-on-left' : 'navbar-on-center');
791
+ if (oldNavbarInner.length > 1) {
792
+ $(oldNavbarInner[0]).remove();
793
+ oldNavbarInner = navbar.find('.navbar-inner');
794
+ }
795
+ navbar.prepend(newNavbarInner[0]);
796
+ }
797
+ // Prepend new Page and add classes for animation
798
+ $(view.pagesContainer).prepend(newPage[0]);
799
+
800
+ // Page Init Events
801
+ app.pageInitCallback(view, newPage[0], url, 'left');
802
+
803
+ if (dynamicNavbar && newNavbarInner.hasClass('navbar-on-left')) {
804
+ newNavbarInner.find('.sliding').each(function () {
805
+ $(this).transform('translate3d(' + (this.f7NavbarLeftOffset) + 'px,0,0)');
806
+ });
807
+ }
808
+
809
+ // Exit if we need only to preload page
810
+ if (preloadOnly) {
811
+ newPage.addClass('page-on-left');
812
+ app.allowPageChange = true;
813
+ return;
814
+ }
815
+
816
+ // Update View's URL
817
+ view.url = url;
818
+
819
+ // Force reLayout
820
+ var clientLeft = newPage[0].clientLeft;
821
+
822
+ // Before Anim Callback
823
+ app.pageAnimCallbacks('before', view, {pageContainer: newPage[0], url: url, position: 'left', oldPage: oldPage, newPage: newPage});
824
+
825
+ newPage.addClass('page-from-left-to-center');
826
+ oldPage.removeClass('page-on-center').addClass('page-from-center-to-right');
827
+
828
+ // Dynamic navbar animation
829
+ if (dynamicNavbar) {
830
+ newNavbarInner.removeClass('navbar-on-left').addClass('navbar-from-left-to-center');
831
+ newNavbarInner.find('.sliding').each(function () {
832
+ $(this).transform('translate3d(0px,0,0)');
833
+ });
834
+ oldNavbarInner.removeClass('navbar-on-center').addClass('navbar-from-center-to-right');
835
+ oldNavbarInner.find('.sliding').each(function () {
836
+ $(this).transform('translate3d(' + (this.f7NavbarRightOffset) + 'px,0,0)');
837
+ });
838
+ }
839
+
840
+ newPage.animationEnd(function () {
841
+ app.afterGoBack(view, oldPage[0], newPage[0]);
842
+ app.pageAnimCallbacks('after', view, {pageContainer: newPage[0], url: url, position: 'left', oldPage: oldPage, newPage: newPage});
843
+ });
844
+ }
845
+
846
+ if (pagesInView.length > 1) {
847
+ // Exit if only preloadOnly
848
+ if (preloadOnly) {
849
+ app.allowPageChange = true;
850
+ return;
851
+ }
852
+ // Update View's URL
853
+ view.url = view.history[view.history.length - 2];
854
+
855
+ // Define old and new pages
856
+ newPage = $(pagesInView[pagesInView.length - 2]);
857
+ oldPage = $(pagesInView[pagesInView.length - 1]);
858
+
859
+ // Dynamic navbar
860
+ if (view.params.dynamicNavbar) {
861
+ dynamicNavbar = true;
862
+ // Find navbar
863
+ var inners = viewContainer.find('.navbar-inner:not(.cached)');
864
+ newNavbarInner = $(inners[0]);
865
+ oldNavbarInner = $(inners[1]);
866
+ }
867
+
868
+ // Page before animation callback
869
+ app.pageAnimCallbacks('before', view, {pageContainer: newPage[0], url: url, position: 'left', oldPage: oldPage, newPage: newPage});
870
+
871
+ // Add classes for animation
872
+ newPage.removeClass('page-on-left').addClass('page-from-left-to-center');
873
+ oldPage.removeClass('page-on-center').addClass('page-from-center-to-right');
874
+
875
+ // Dynamic navbar animation
876
+ if (dynamicNavbar) {
877
+ newNavbarInner.removeClass('navbar-on-left').addClass('navbar-from-left-to-center');
878
+ newNavbarInner.find('.sliding').each(function () {
879
+ $(this).transform('translate3d(0px,0,0)');
880
+ });
881
+
882
+ oldNavbarInner.removeClass('navbar-on-center').addClass('navbar-from-center-to-right');
883
+ oldNavbarInner.find('.sliding').each(function () {
884
+ $(this).transform('translate3d(' + (this.f7NavbarRightOffset) + 'px,0,0)');
885
+ });
886
+ }
887
+
888
+ newPage.animationEnd(function () {
889
+ app.afterGoBack(view, oldPage[0], newPage[0]);
890
+ app.pageAnimCallbacks('after', view, {pageContainer: newPage[0], url: url, position: 'left', oldPage: oldPage, newPage: newPage});
891
+ });
892
+ }
893
+ else {
894
+ if (url && url.indexOf('#') === 0) url = undefined;
895
+ if (view.history.length > 1) {
896
+ url = view.history[view.history.length - 2];
897
+ }
898
+ if (!url) {
899
+ app.allowPageChange = true;
900
+ return;
901
+ }
902
+
903
+ // Check current url is in cache?
904
+ if (!view.params.domCache && (url in view.contentCache)) {
905
+ var _cache = view.contentCache[url];
906
+
907
+ app._tempDomElement = document.createElement('div');
908
+ $(app._tempDomElement).append(_cache.nav[0]).append(_cache.page[0]);
909
+ _preload();
910
+ return;
911
+ }
912
+
913
+ app.get(url, function (data, error) {
914
+ if (error) {
915
+ app.allowPageChange = true;
916
+ return;
917
+ }
918
+ // Parse DOM to find new page
919
+ app._tempDomElement.innerHTML = data;
920
+
921
+ _preload();
922
+ });
923
+ }
924
+ };
925
+ app.afterGoBack = function (view, oldPage, newPage) {
926
+ // Remove old page and set classes on new one
927
+ oldPage = $(oldPage);
928
+ newPage = $(newPage);
929
+ oldPage.remove();
930
+ newPage.removeClass('page-from-left-to-center page-on-left').addClass('page-on-center');
931
+ app.allowPageChange = true;
932
+ // Updated dynamic navbar
933
+ if (view.params.dynamicNavbar) {
934
+ var inners = $(view.container).find('.navbar-inner:not(.cached)');
935
+ var oldNavbar = $(inners[1]).remove();
936
+ var newNavbar = $(inners[0]).removeClass('navbar-on-left navbar-from-left-to-center').addClass('navbar-on-center');
937
+
938
+ if (app.params.preloadPreviousPage && view.params.domCache) {
939
+ var cachedNavs = $(view.container).find('.navbar-inner.cached');
940
+ $(cachedNavs[cachedNavs.length - 1]).removeClass('cached');
941
+ }
942
+ }
943
+ // Update View's History
944
+ view.history.pop();
945
+ // Check current page is content based only
946
+ if (!view.params.domCache && view.url && view.url.indexOf('#content-') > -1 && (view.url in view.contentCache)) {
947
+ view.contentCache[view.url] = null;
948
+ delete view.contentCache[view.url];
949
+ }
950
+ // Preload previous page
951
+ if (app.params.preloadPreviousPage) {
952
+ if (view.params.domCache) {
953
+ var cachedPages = $(view.container).find('.page.cached');
954
+ $(cachedPages[cachedPages.length - 1]).removeClass('cached');
955
+ }
956
+ app.goBack(view, false, true);
957
+ }
958
+ };
959
+ /*======================================================
960
+ ************ Modals ************
961
+ ======================================================*/
962
+ var _modalTemplateTempDiv = document.createElement('div');
963
+ app.modal = function (params) {
964
+ params = params || {};
965
+ /* @params example
966
+ {
967
+ title: 'Modal title',
968
+ text: 'Modal text',
969
+ afterText: 'Custom content after text',
970
+ buttons: [{
971
+ text:'Cancel',
972
+ bold: true,
973
+ onClick: function (){},
974
+ close:false
975
+ }]
976
+ }
977
+ */
978
+ var buttonsHTML = '';
979
+ if (params.buttons && params.buttons.length > 0) {
980
+ for (var i = 0; i < params.buttons.length; i++) {
981
+ buttonsHTML += '<span class="modal-button' + (params.buttons[i].bold ? ' modal-button-bold' : '') + '">' + params.buttons[i].text + '</span>';
982
+ }
983
+ }
984
+ var modalTemplate = app.params.modalTemplate;
985
+ if (!params.title) {
986
+ modalTemplate = modalTemplate.split('{{if title}}')[0] + modalTemplate.split('{{/if title}}')[1];
987
+ }
988
+ else {
989
+ modalTemplate = modalTemplate.replace(/{{if\ title}}/g, '').replace(/{{\/if\ title}}/g, '');
990
+ }
991
+ var modalHTML = modalTemplate
992
+ .replace(/{{title}}/g, params.title || '')
993
+ .replace(/{{text}}/g, params.text || '')
994
+ .replace(/{{afterText}}/g, params.afterText || '')
995
+ .replace(/{{buttons}}/g, buttonsHTML)
996
+ .replace(/{{noButtons}}/g, !params.buttons || params.buttons.length === 0 ? 'modal-no-buttons' : '');
997
+ _modalTemplateTempDiv.innerHTML = modalHTML;
998
+
999
+ var modal = $(_modalTemplateTempDiv).children();
1000
+
1001
+ $('body').append(modal[0]);
1002
+
1003
+ // Add events on buttons
1004
+ modal.find('.modal-button').each(function (index, el) {
1005
+ $(el).tap(function (e) {
1006
+ if (params.buttons[index].close !== false) app.closeModal(modal);
1007
+ if (params.buttons[index].onClick) params.buttons[index].onClick(modal, e);
1008
+ });
1009
+ });
1010
+ app.openModal(modal);
1011
+ return modal[0];
1012
+ };
1013
+ app.alert = function (text, title) {
1014
+ return app.modal({
1015
+ text: text || '',
1016
+ title: title || app.params.modalTitle,
1017
+ buttons: [ {text: app.params.modalButtonOk, bold: true} ]
1018
+ });
1019
+ };
1020
+ app.confirm = function (text, callbackOk, callbackCancel) {
1021
+ return app.modal({
1022
+ text: text || '',
1023
+ title: app.params.modalTitle || '',
1024
+ buttons: [
1025
+ {text: app.params.modalButtonCancel, onClick: callbackCancel},
1026
+ {text: app.params.modalButtonOk, bold: true, onClick: callbackOk}
1027
+ ]
1028
+ });
1029
+ };
1030
+ app.prompt = function (text, callbackOk, callbackCancel) {
1031
+ return app.modal({
1032
+ text: text || '',
1033
+ title: app.params.modalTitle || '',
1034
+ afterText: '<input type="text" class="modal-prompt-input">',
1035
+ buttons: [
1036
+ {text: app.params.modalButtonCancel, onClick: function (modal) {
1037
+ if (callbackCancel) callbackCancel($(modal).find('.modal-prompt-input').val());
1038
+ }},
1039
+ {text: app.params.modalButtonOk, bold: true, onClick: function (modal) {
1040
+ if (callbackOk) callbackOk($(modal).find('.modal-prompt-input').val());
1041
+ }}
1042
+ ]
1043
+ });
1044
+ };
1045
+ app.showPreloader = function (title) {
1046
+ return app.modal({
1047
+ title: title || app.params.modalPreloaderTitle,
1048
+ text: '<div class="preloader"></div>'
1049
+ });
1050
+ };
1051
+ app.hidePreloader = function () {
1052
+ app.closeModal();
1053
+ };
1054
+ app.showIndicator = function () {
1055
+ $('body').append('<div class="preloader-indicator-overlay"></div><div class="preloader-indicator-modal"><span class="preloader preloader-white"></span></div>');
1056
+ };
1057
+ app.hideIndicator = function () {
1058
+ $('.preloader-indicator-overlay, .preloader-indicator-modal').remove();
1059
+ };
1060
+ // Action Sheet
1061
+ app.actions = function (params) {
1062
+ params = params || [];
1063
+ /*Example of @params
1064
+ [
1065
+ [
1066
+ {
1067
+ text: 'Button 1',
1068
+ red: false,
1069
+ bold: false,
1070
+ onClick: function () { ... },
1071
+ label: false // or true
1072
+ },
1073
+ {
1074
+ text: '<a href="#" class="open-panel">Open panel</a>',
1075
+ red: false,
1076
+ bold: false,
1077
+ onClick: function () { ... }
1078
+ label: false // or true
1079
+ }
1080
+ ... more buttons in this group
1081
+ ],
1082
+ ... more groups
1083
+ ]
1084
+ */
1085
+ if (params.length > 0 && !$.isArray(params[0])) {
1086
+ params = [params];
1087
+ }
1088
+
1089
+ var actionsTemplate = app.params.modalActionsTemplate;
1090
+ var buttonsHTML = '';
1091
+ for (var i = 0; i < params.length; i++) {
1092
+ for (var j = 0; j < params[i].length; j++) {
1093
+ if (j === 0) buttonsHTML += '<div class="actions-modal-group">';
1094
+ var button = params[i][j];
1095
+ var buttonClass = button.label ? 'actions-modal-label' : 'actions-modal-button';
1096
+ if (button.bold) buttonClass += ' actions-modal-button-bold';
1097
+ if (button.red) buttonClass += ' actions-modal-button-red';
1098
+ buttonsHTML += '<span class="' + buttonClass + '">' + button.text + '</span>';
1099
+ if (j === params[i].length - 1) buttonsHTML += '</div>';
1100
+ }
1101
+ }
1102
+ var modalHTML = actionsTemplate.replace(/{{buttons}}/g, buttonsHTML);
1103
+
1104
+ _modalTemplateTempDiv.innerHTML = modalHTML;
1105
+ var modal = $(_modalTemplateTempDiv).children();
1106
+ $('body').append(modal[0]);
1107
+
1108
+ var groups = modal.find('.actions-modal-group');
1109
+ groups.each(function (index, el) {
1110
+ var groupIndex = index;
1111
+ $(el).children().each(function (index, el) {
1112
+ var buttonIndex = index;
1113
+ var buttonParams = params[groupIndex][buttonIndex];
1114
+ if ($(el).hasClass('actions-modal-button')) {
1115
+ $(el).tap(function (e) {
1116
+ if (buttonParams.close !== false) app.closeModal(modal);
1117
+ if (buttonParams.onClick) buttonParams.onClick(modal, e);
1118
+ });
1119
+ }
1120
+ });
1121
+ });
1122
+ app.openModal(modal);
1123
+ return modal[0];
1124
+ };
1125
+ app.popover = function (modal, target) {
1126
+ modal = $(modal);
1127
+ target = $(target);
1128
+ if (modal.length === 0 || target.length === 0) return false;
1129
+
1130
+ modal.show();
1131
+
1132
+ function sizePopover() {
1133
+ modal.css({left: '', top: ''});
1134
+ var modalWidth = modal.width();
1135
+ var modalHeight = modal.height(); // 13 - height of angle
1136
+ var modalAngle = modal.find('.popover-angle');
1137
+ var modalAngleSize = modalAngle.width() / 2;
1138
+ modalAngle.removeClass('on-left on-right on-top on-bottom').css({left: '', top: ''});
1139
+
1140
+ var targetWidth = target.outerWidth();
1141
+ var targetHeight = target.outerHeight();
1142
+ var targetOffset = target.offset();
1143
+ var targetParentPage = target.parents('.page');
1144
+ if (targetParentPage.length > 0) {
1145
+ targetOffset.top = targetOffset.top - targetParentPage[0].scrollTop;
1146
+ }
1147
+
1148
+ var windowHeight = $(window).height();
1149
+ var windowWidth = $(window).width();
1150
+
1151
+ var modalTop = 0;
1152
+ var modalLeft = 0;
1153
+ var diff = 0;
1154
+ // Top Position
1155
+ var modalPosition = 'top';
1156
+
1157
+ if ((modalHeight + modalAngleSize) < targetOffset.top) {
1158
+ // On top
1159
+ modalTop = targetOffset.top - modalHeight - modalAngleSize;
1160
+ }
1161
+ else if ((modalHeight + modalAngleSize) < windowHeight - targetOffset.top - targetHeight) {
1162
+ // On bottom
1163
+ modalPosition = 'bottom';
1164
+ modalTop = targetOffset.top + targetHeight + modalAngleSize;
1165
+ }
1166
+ else {
1167
+ // On middle
1168
+ modalPosition = 'middle';
1169
+ modalTop = targetHeight / 2 + targetOffset.top - modalHeight / 2;
1170
+ diff = modalTop;
1171
+ if (modalTop < 0) {
1172
+ modalTop = 5;
1173
+ }
1174
+ else if (modalTop + modalHeight > windowHeight) {
1175
+ modalTop = windowHeight - modalHeight - 5;
1176
+ }
1177
+ diff = diff - modalTop;
1178
+ }
1179
+ // Horizontal Position
1180
+ if (modalPosition === 'top' || modalPosition === 'bottom') {
1181
+ modalLeft = targetWidth / 2 + targetOffset.left - modalWidth / 2;
1182
+ diff = modalLeft;
1183
+ if (modalLeft < 5) modalLeft = 5;
1184
+ if (modalLeft + modalWidth > windowWidth) modalLeft = windowWidth - modalWidth - 5;
1185
+ if (modalPosition === 'top') modalAngle.addClass('on-bottom');
1186
+ if (modalPosition === 'bottom') modalAngle.addClass('on-top');
1187
+ diff = diff - modalLeft;
1188
+ modalAngle.css({left: (modalWidth / 2 - modalAngleSize + diff) + 'px'});
1189
+ }
1190
+ else if (modalPosition === 'middle') {
1191
+ modalLeft = targetOffset.left - modalWidth - modalAngleSize;
1192
+ modalAngle.addClass('on-right');
1193
+ if (modalLeft < 5) {
1194
+ modalLeft = targetOffset.left + targetWidth + modalAngleSize;
1195
+ modalAngle.removeClass('on-right').addClass('on-left');
1196
+ }
1197
+ if (modalLeft + modalWidth > windowWidth) {
1198
+ modalLeft = windowWidth - modalWidth - 5;
1199
+ modalAngle.removeClass('on-right').addClass('on-left');
1200
+ }
1201
+ modalAngle.css({top: (modalHeight / 2 - modalAngleSize + diff) + 'px'});
1202
+ }
1203
+
1204
+ // Apply Styles
1205
+ modal.css({top: modalTop + 'px', left: modalLeft + 'px'});
1206
+ }
1207
+ sizePopover();
1208
+
1209
+ $(window).on('resize', sizePopover);
1210
+ modal.on('close', function () {
1211
+ $(window).off('resize', sizePopover);
1212
+ });
1213
+
1214
+ app.openModal(modal);
1215
+ return modal[0];
1216
+ };
1217
+ app.popup = function (modal) {
1218
+ modal = $(modal);
1219
+ if (modal.length === 0) return false;
1220
+ modal.show();
1221
+ if (modal.find('.view').length > 0) {
1222
+ app.sizeNavbars(modal.find('.view')[0]);
1223
+ }
1224
+ app.openModal(modal);
1225
+ return modal[0];
1226
+ };
1227
+ app.openModal = function (modal) {
1228
+ modal = $(modal);
1229
+ if ($('.modal-overlay').length === 0) {
1230
+ var overlay = document.createElement('div');
1231
+ overlay.className = 'modal-overlay';
1232
+ $('body').append(overlay);
1233
+ }
1234
+ var isPopover = modal.hasClass('popover');
1235
+ var isPopup = modal.hasClass('popup');
1236
+ if (!isPopover && !isPopup) modal.css({marginTop: -modal.outerHeight() / 2 + 'px'});
1237
+
1238
+ //Make sure that styles are applied, trigger relayout;
1239
+ var clientLeft = modal[0].clientLeft;
1240
+
1241
+ // Trugger open event
1242
+ modal.trigger('open');
1243
+
1244
+ // Classes for transition in
1245
+ $('.modal-overlay').addClass('modal-overlay-visible');
1246
+ $(modal).addClass('modal-in');
1247
+ return true;
1248
+ };
1249
+ app.closeModal = function (modal) {
1250
+ modal = $(modal || '.modal-in');
1251
+ $('.modal-overlay').removeClass('modal-overlay-visible');
1252
+ modal.trigger('close');
1253
+ var isPopover = modal.hasClass('popover');
1254
+ var isPopup = modal.hasClass('popup');
1255
+ if (!isPopover) {
1256
+ modal.removeClass('modal-in').addClass('modal-out').transitionEnd(function (e) {
1257
+ modal.trigger('closed');
1258
+ if (!isPopup) modal.remove();
1259
+ if (isPopup) modal.removeClass('modal-out').hide();
1260
+ });
1261
+ }
1262
+ else {
1263
+ modal.removeClass('modal-in modal-out').trigger('closed').hide();
1264
+ }
1265
+ return true;
1266
+ };
1267
+ /*======================================================
1268
+ ************ Panels ************
1269
+ ======================================================*/
1270
+ app.allowPanelOpen = true;
1271
+ app.openPanel = function (panelPosition) {
1272
+ // @panelPosition - string with panel position "left", "right", "top"
1273
+ if (!app.allowPanelOpen) return false;
1274
+ var panel = $('.panel-' + panelPosition);
1275
+ if (panel.length === 0 || panel.hasClass('active')) return false;
1276
+ app.closePanel(); // Close if some panel is opened
1277
+ app.allowPanelOpen = false;
1278
+ var effect = panel.hasClass('panel-reveal') ? 'reveal' : 'cover';
1279
+ panel.css({display: 'block'}).addClass('active');
1280
+ panel.trigger('open');
1281
+
1282
+ // Trigger reLayout
1283
+ var clientLeft = panel[0].clientLeft;
1284
+
1285
+ // Transition End;
1286
+ var transitionEndTarget = effect === 'reveal' ? $('.views') : panel;
1287
+ var openedTriggered = false;
1288
+ transitionEndTarget.transitionEnd(function (e) {
1289
+ if ($(e.target).is(transitionEndTarget)) {
1290
+ if (!openedTriggered) panel.trigger('opened');
1291
+ }
1292
+ app.allowPanelOpen = true;
1293
+ });
1294
+ setTimeout(function () {
1295
+ if (!openedTriggered) panel.trigger('opened');
1296
+ }, app.params.panelsAnimationDuration);
1297
+
1298
+ $('body').addClass('with-panel-' + panelPosition + '-' + effect);
1299
+ return true;
1300
+ };
1301
+ app.closePanel = function () {
1302
+ var activePanel = $('.panel.active');
1303
+ if (activePanel.length === 0) return false;
1304
+ var effect = activePanel.hasClass('panel-reveal') ? 'reveal' : 'cover';
1305
+ var panelPosition = activePanel.hasClass('panel-left') ? 'left' : 'right';
1306
+ activePanel.removeClass('active');
1307
+ var transitionEndTarget = effect === 'reveal' ? $('.views') : activePanel;
1308
+ activePanel.trigger('close');
1309
+ transitionEndTarget.transitionEnd(function () {
1310
+ activePanel.css({display: ''});
1311
+ activePanel.trigger('closed');
1312
+ $('body').removeClass('panel-closing');
1313
+ });
1314
+ $('body').addClass('panel-closing').removeClass('with-panel-' + panelPosition + '-' + effect);
1315
+ };
1316
+ /*======================================================
1317
+ ************ Messages ************
1318
+ ======================================================*/
1319
+ app.initMessages = function (pageContainer) {
1320
+ var page = $(pageContainer);
1321
+ var messages = page.find('.messages');
1322
+ if (messages.length === 0) return;
1323
+ var pageContent = page.find('.page-content');
1324
+ pageContent[0].scrollTop = messages.height() - pageContent.height();
1325
+ app.updateMessagesAngles(messages);
1326
+ };
1327
+ app.addMessage = function (props) {
1328
+ props = props || {};
1329
+ /*
1330
+ {
1331
+ text : 'Message text',
1332
+ day : 'Mon',
1333
+ time : '14:42',
1334
+ type : 'sent' // or 'received'
1335
+ }
1336
+ */
1337
+ props.type = props.type || 'sent';
1338
+ if (!props.text || props.length === 0) return false;
1339
+ var messagesContent = $('.messages-content');
1340
+ if (messagesContent.length === 0) return false;
1341
+ var messages = messagesContent.find('.messages');
1342
+
1343
+ var html = '';
1344
+ if (props.day) {
1345
+ html += '<div class="messages-date">' + props.day + (props.time ? ',' : '') + (props.time ? ' <span>' + props.time + '</span>' : '') + '</div>';
1346
+ }
1347
+ var isPic = props.text.indexOf('<img') >= 0;
1348
+ var messageClass = 'message' + ' message-' + props.type + (isPic ? ' message-pic' : '') + ' message-appear';
1349
+ html += '<div class="' + messageClass + '">' + props.text + '</div>';
1350
+ messages.append(html);
1351
+ app.updateMessagesAngles(messages);
1352
+ app.scrollMessagesContainer(messagesContent);
1353
+ };
1354
+ app.updateMessagesAngles = function (messages) {
1355
+ messages.find('.message-sent').each(function () {
1356
+ var message = $(this);
1357
+ if (!message.next().hasClass('message-sent')) {
1358
+ message.addClass('message-last');
1359
+ }
1360
+ else message.removeClass('message-last');
1361
+ });
1362
+ messages.find('.message-received').each(function () {
1363
+ var message = $(this);
1364
+ if (!message.next().hasClass('message-received')) {
1365
+ message.addClass('message-last');
1366
+ }
1367
+ else message.removeClass('message-last');
1368
+ });
1369
+ };
1370
+ app.scrollMessagesContainer = function (messagesContent) {
1371
+ messagesContent = $(messagesContent || '.messages-content');
1372
+ if (messagesContent.length === 0) return;
1373
+ var messages = messagesContent.find('.messages');
1374
+ var currentScroll = messagesContent[0].scrollTop;
1375
+ var newScroll = messages.height() - messagesContent.height();
1376
+ var step = (newScroll - currentScroll) / 12;
1377
+ function animScroll() {
1378
+ if (messagesContent[0].scrollTop < newScroll) {
1379
+ messagesContent[0].scrollTop = messagesContent[0].scrollTop + Math.floor(step);
1380
+ app._animFrame(animScroll);
1381
+ }
1382
+ else {
1383
+ messagesContent[0].scrollTop = newScroll;
1384
+ }
1385
+ }
1386
+ app._animFrame(animScroll);
1387
+ };
1388
+ /*===============================================================================
1389
+ ************ Swipeout Actions (Swipe to delete) ************
1390
+ ===============================================================================*/
1391
+ app.swipeoutOpenedEl = undefined;
1392
+ app.allowSwipeout = true;
1393
+ app.initSwipeout = function () {
1394
+ var isTouched, isMoved, isScrolling, touchesStart = {}, touchStartTime, touchesDiff, swipeOutEl, swipeOutContent, swipeOutActions, swipeOutActionsWidth, translate, opened;
1395
+ $(document).on(app.touchEvents.start, function (e) {
1396
+ if (app.swipeoutOpenedEl) {
1397
+ var target = $(e.target);
1398
+ if (!(
1399
+ app.swipeoutOpenedEl.is(target[0]) ||
1400
+ target.parents('.swipeout').is(app.swipeoutOpenedEl) ||
1401
+ target.hasClass('modal-in') ||
1402
+ target.parents('.modal-in').length > 0 ||
1403
+ target.hasClass('modal-overlay')
1404
+ )) {
1405
+ app.swipeoutClose(app.swipeoutOpenedEl);
1406
+ }
1407
+ }
1408
+ });
1409
+
1410
+
1411
+ function handleTouchStart(e) {
1412
+ if (!app.allowSwipeout) return;
1413
+ isMoved = false;
1414
+ isTouched = true;
1415
+ isScrolling = undefined;
1416
+ touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
1417
+ touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
1418
+ touchStartTime = (new Date()).getTime();
1419
+
1420
+ }
1421
+ function handleTouchMove(e) {
1422
+ if (!isTouched) return;
1423
+ var pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
1424
+ var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
1425
+ if (typeof isScrolling === 'undefined') {
1426
+ isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
1427
+ }
1428
+ if (isScrolling) {
1429
+ isTouched = false;
1430
+ return;
1431
+ }
1432
+
1433
+ if (!isMoved) {
1434
+ /*jshint validthis:true */
1435
+ swipeOutEl = $(this);
1436
+ swipeOutContent = swipeOutEl.find('.swipeout-content');
1437
+ swipeOutActions = swipeOutEl.find('.swipeout-actions-inner');
1438
+ swipeOutActionsWidth = swipeOutActions.width();
1439
+ opened = swipeOutEl.hasClass('swipeout-opened');
1440
+ swipeOutEl.removeClass('transitioning');
1441
+ }
1442
+ isMoved = true;
1443
+
1444
+ e.preventDefault();
1445
+ touchesDiff = pageX - touchesStart.x;
1446
+ translate = touchesDiff - (opened ? swipeOutActionsWidth : 0);
1447
+
1448
+ if (translate > 0) translate = 0;
1449
+ if (translate < -swipeOutActionsWidth) {
1450
+ translate = -swipeOutActionsWidth - Math.pow(-translate - swipeOutActionsWidth, 0.8);
1451
+ }
1452
+
1453
+ if (app.params.swipeoutNoFollow) {
1454
+ if (touchesDiff < 0 && !opened) {
1455
+ app.swipeoutOpen(swipeOutEl);
1456
+ isTouched = false;
1457
+ isMoved = false;
1458
+ return;
1459
+ }
1460
+ if (touchesDiff > 0 && opened) {
1461
+ app.swipeoutClose(swipeOutEl);
1462
+ isTouched = false;
1463
+ isMoved = false;
1464
+ return;
1465
+ }
1466
+ }
1467
+ else swipeOutContent.transform('translate3d(' + translate + 'px,0,0)');
1468
+
1469
+ }
1470
+ function handleTouchEnd(e) {
1471
+ if (!isTouched || !isMoved) {
1472
+ isTouched = false;
1473
+ isMoved = false;
1474
+ return;
1475
+ }
1476
+ isTouched = false;
1477
+ isMoved = false;
1478
+ var timeDiff = (new Date()).getTime() - touchStartTime;
1479
+ if (!(translate === 0 || translate === -swipeOutActionsWidth)) app.allowSwipeout = false;
1480
+
1481
+ var action;
1482
+ if (opened) {
1483
+ if (
1484
+ timeDiff < 300 && translate > -(swipeOutActionsWidth - 10) ||
1485
+ timeDiff >= 300 && translate > -swipeOutActionsWidth / 2
1486
+ ) {
1487
+ action = 'close';
1488
+ }
1489
+ else {
1490
+ action = 'open';
1491
+ }
1492
+ }
1493
+ else {
1494
+ if (
1495
+ timeDiff < 300 && translate < -10 ||
1496
+ timeDiff >= 300 && translate < -swipeOutActionsWidth / 2
1497
+ ) {
1498
+ action = 'open';
1499
+ }
1500
+ else {
1501
+ action = 'close';
1502
+ }
1503
+ }
1504
+ if (action === 'open') {
1505
+ app.swipeoutOpenedEl = swipeOutEl;
1506
+ swipeOutEl.trigger('open');
1507
+ swipeOutEl.addClass('swipeout-opened transitioning');
1508
+ swipeOutContent.transform('translate3d(' + -swipeOutActionsWidth + 'px,0,0)');
1509
+ }
1510
+ else {
1511
+ swipeOutEl.trigger('close');
1512
+ app.swipeoutOpenedEl = undefined;
1513
+ swipeOutEl.addClass('transitioning').removeClass('swipeout-opened');
1514
+ swipeOutContent.transform('translate3d(' + 0 + 'px,0,0)');
1515
+ }
1516
+ swipeOutContent.transitionEnd(function () {
1517
+ app.allowSwipeout = true;
1518
+ swipeOutEl.trigger(action === 'open' ? 'opened' : 'closed');
1519
+ });
1520
+ }
1521
+ $(document).on(app.touchEvents.start, '.list-block li.swipeout', handleTouchStart);
1522
+ $(document).on(app.touchEvents.move, '.list-block li.swipeout', handleTouchMove);
1523
+ $(document).on(app.touchEvents.end, '.list-block li.swipeout', handleTouchEnd);
1524
+ };
1525
+ app.swipeoutOpen = function (el) {
1526
+ el = $(el);
1527
+ if (!el.hasClass('swipeout')) return;
1528
+ if (el.length === 0) return;
1529
+ if (el.length > 1) el = $(el[0]);
1530
+ el.trigger('open').addClass('transitioning swipeout-opened');
1531
+ var swipeOutActions = el.find('.swipeout-actions-inner');
1532
+ el.find('.swipeout-content').transform('translate3d(-' + swipeOutActions.width() + 'px,0,0)').transitionEnd(function () {
1533
+ el.trigger('opened');
1534
+ });
1535
+ app.swipeoutOpenedEl = el;
1536
+ };
1537
+ app.swipeoutClose = function (el) {
1538
+ el = $(el);
1539
+ if (el.length === 0) return;
1540
+ app.allowSwipeout = false;
1541
+ el.trigger('close');
1542
+ el.removeClass('swipeout-opened')
1543
+ .addClass('transitioning')
1544
+ .find('.swipeout-content')
1545
+ .transform('translate3d(' + 0 + 'px,0,0)')
1546
+ .transitionEnd(function () {
1547
+ el.trigger('closed');
1548
+ app.allowSwipeout = true;
1549
+ });
1550
+
1551
+ if (app.swipeoutOpenedEl[0] === el[0]) app.swipeoutOpenedEl = undefined;
1552
+ };
1553
+ app.swipeoutDelete = function (el) {
1554
+ el = $(el);
1555
+ if (el.length === 0) return;
1556
+ if (el.length > 1) el = $(el[0]);
1557
+ app.swipeoutOpenedEl = undefined;
1558
+ el.trigger('delete');
1559
+ el.css({height: el.outerHeight() + 'px'});
1560
+ var clientLeft = el[0].clientLeft;
1561
+ el.css({height: 0 + 'px'}).addClass('deleting transitioning').transitionEnd(function () {
1562
+ el.trigger('deleted');
1563
+ el.remove();
1564
+ });
1565
+ el.find('.swipeout-content').transform('translate3d(-100%,0,0)');
1566
+ };
1567
+ /*======================================================
1568
+ ************ Pull To Refresh ************
1569
+ ======================================================*/
1570
+ app.initPullToRefresh = function () {
1571
+ var isTouched, isMoved, touchesStart = {}, isScrolling, touchesDiff, touchStartTime, container, refresh = false, useTranslate = false, startTranslate = 0;
1572
+ function handleTouchStart(e) {
1573
+ if (isTouched) return;
1574
+ isMoved = false;
1575
+ isTouched = true;
1576
+ isScrolling = undefined;
1577
+ touchesStart.x = e.type === 'touchstart' ? e.targetTouches[0].pageX : e.pageX;
1578
+ touchesStart.y = e.type === 'touchstart' ? e.targetTouches[0].pageY : e.pageY;
1579
+ touchStartTime = (new Date()).getTime();
1580
+ }
1581
+
1582
+ function handleTouchMove(e) {
1583
+ if (!isTouched) return;
1584
+ var pageX = e.type === 'touchmove' ? e.targetTouches[0].pageX : e.pageX;
1585
+ var pageY = e.type === 'touchmove' ? e.targetTouches[0].pageY : e.pageY;
1586
+ if (typeof isScrolling === 'undefined') {
1587
+ isScrolling = !!(isScrolling || Math.abs(pageY - touchesStart.y) > Math.abs(pageX - touchesStart.x));
1588
+ }
1589
+ if (!isScrolling) {
1590
+ isTouched = false;
1591
+ return;
1592
+ }
1593
+ if (!isMoved) {
1594
+ /*jshint validthis:true */
1595
+ container = $(this);
1596
+ container.removeClass('transitioning');
1597
+ startTranslate = container.hasClass('refreshing') ? 44 : 0;
1598
+ if (container[0].scrollHeight === container[0].offsetHeight || app.device.os !== 'ios') {
1599
+ useTranslate = true;
1600
+ }
1601
+ else {
1602
+ useTranslate = false;
1603
+ }
1604
+ }
1605
+ isMoved = true;
1606
+ touchesDiff = pageY - touchesStart.y;
1607
+ if (touchesDiff > 0 && container[0].scrollTop <= 0 || container[0].scrollTop < 0) {
1608
+ if (useTranslate) {
1609
+ e.preventDefault();
1610
+ container.transform('translate3d(0,' + (Math.pow(touchesDiff, 0.85) + startTranslate) + 'px,0)');
1611
+ }
1612
+ if ((useTranslate && Math.pow(touchesDiff, 0.85) > 44) || (!useTranslate && touchesDiff >= 88)) {
1613
+ refresh = true;
1614
+ container.addClass('pull-up');
1615
+ }
1616
+ else {
1617
+ refresh = false;
1618
+ container.removeClass('pull-up');
1619
+ }
1620
+ }
1621
+ else {
1622
+ container.removeClass('pull-up');
1623
+ refresh = false;
1624
+ return;
1625
+ }
1626
+ }
1627
+ function handleTouchEnd(e) {
1628
+ if (!isTouched || !isMoved) {
1629
+ isTouched = false;
1630
+ isMoved = false;
1631
+ return;
1632
+ }
1633
+ container.addClass('transitioning');
1634
+ container.transform('');
1635
+ if (refresh) {
1636
+ container.addClass('refreshing');
1637
+ container.trigger('refresh', {
1638
+ done: function () {
1639
+ app.pullToRefreshDone(container);
1640
+ }
1641
+ });
1642
+ }
1643
+ isTouched = false;
1644
+ isMoved = false;
1645
+ }
1646
+ $(document).on(app.touchEvents.start, '.pull-to-refresh-content', handleTouchStart);
1647
+ $(document).on(app.touchEvents.move, '.pull-to-refresh-content', handleTouchMove);
1648
+ $(document).on(app.touchEvents.end, '.pull-to-refresh-content', handleTouchEnd);
1649
+ };
1650
+
1651
+ app.pullToRefreshDone = function (container) {
1652
+ container = $(container);
1653
+ if (container.length === 0) container = $('.pull-to-refresh-content.refreshing');
1654
+ container.removeClass('refreshing').addClass('transitioning');
1655
+ container.transitionEnd(function () {
1656
+ container.removeClass('transitioning pull-up');
1657
+ });
1658
+ };
1659
+ /*===============================================================================
1660
+ ************ Handle clicks and make them fast (on tap); ************
1661
+ ===============================================================================*/
1662
+ app.initClickEvents = function () {
1663
+ function handleTap(e) {
1664
+ /*jshint validthis:true */
1665
+ var clicked = $(this);
1666
+ var url = clicked.attr('href');
1667
+ // External
1668
+ if (clicked.hasClass('external')) {
1669
+ return;
1670
+ }
1671
+ // Open Panel
1672
+ if (clicked.hasClass('open-panel')) {
1673
+ if ($('.panel').length === 1) {
1674
+ if ($('.panel').hasClass('panel-left')) app.openPanel('left');
1675
+ else app.openPanel('right');
1676
+ }
1677
+ else {
1678
+ if (clicked.attr('data-panel') === 'right') app.openPanel('right');
1679
+ else app.openPanel('left');
1680
+ }
1681
+ }
1682
+ // Close Panel
1683
+ if (clicked.hasClass('close-panel')) {
1684
+ app.closePanel();
1685
+ }
1686
+
1687
+ if (clicked.hasClass('panel-overlay') && app.params.panelsCloseByOutside) {
1688
+ app.closePanel();
1689
+ }
1690
+ // Popover
1691
+ if (clicked.hasClass('open-popover')) {
1692
+ var popover;
1693
+ if (clicked.attr('data-popover')) {
1694
+ popover = clicked.attr('data-popover');
1695
+ }
1696
+ else popover = '.popover';
1697
+ app.popover(popover, clicked);
1698
+ }
1699
+ // Popup
1700
+ var popup;
1701
+ if (clicked.hasClass('open-popup')) {
1702
+ if (clicked.attr('data-popup')) {
1703
+ popup = clicked.attr('data-popup');
1704
+ }
1705
+ else popup = '.popup';
1706
+ app.popup(popup);
1707
+ }
1708
+ if (clicked.hasClass('close-popup')) {
1709
+ app.closeModal('.popup.modal-in');
1710
+ }
1711
+ // Close Modal
1712
+ if (clicked.hasClass('modal-overlay')) {
1713
+ if ($('.modal.modal-in').length > 0 && app.params.modalCloseByOutside)
1714
+ app.closeModal();
1715
+ if ($('.actions-modal.modal-in').length > 0 && app.params.modalActionsCloseByOutside)
1716
+ app.closeModal();
1717
+ if ($('.popup.modal-in').length > 0 && app.params.modalPopupCloseByOutside)
1718
+ app.closeModal();
1719
+ if ($('.popover.modal-in').length > 0) app.closeModal('.popover.modal-in');
1720
+ }
1721
+ // Radios/checkboxes
1722
+ if (clicked.hasClass('label-checkbox') || clicked.hasClass('label-radio')) {
1723
+ var input = clicked.find('input');
1724
+ if (input.attr('type') === 'checkbox') {
1725
+ if (input[0].checked === true) input[0].checked = false;
1726
+ else input[0].checked = true;
1727
+ }
1728
+ if (input.attr('type') === 'radio') {
1729
+ clicked.find('input')[0].checked = true;
1730
+ }
1731
+ input.trigger('change');
1732
+ return;
1733
+ }
1734
+ if ($.supportTouch) {
1735
+ if (clicked.parent().hasClass('label-switch')) {
1736
+ clicked[0].checked = !clicked[0].checked;
1737
+ clicked.trigger('change');
1738
+ }
1739
+ }
1740
+
1741
+ // Tabs
1742
+ if (clicked.hasClass('tab-link')) {
1743
+ var newTab = $(clicked.attr('href'));
1744
+ var oldTab = newTab.parent().find('.tab.active').removeClass('active');
1745
+ newTab.addClass('active');
1746
+ var clickedParent = clicked.parent();
1747
+ if (clickedParent.hasClass('buttons-row') || clicked.parents('.tabbar').length > 0) {
1748
+ clickedParent.find('.active').removeClass('active');
1749
+ clicked.addClass('active');
1750
+ }
1751
+ }
1752
+ // Swipeout Delete
1753
+ if (clicked.hasClass('swipeout-delete')) {
1754
+ if (clicked.attr('data-confirm')) {
1755
+ var modal = app.confirm(clicked.attr('data-confirm'), function () {
1756
+ app.swipeoutDelete(clicked.parents('.swipeout'));
1757
+ });
1758
+ }
1759
+ else {
1760
+ app.swipeoutDelete(clicked.parents('.swipeout'));
1761
+ }
1762
+
1763
+ }
1764
+ // Load Page
1765
+ if (app.params.ajaxLinks && !clicked.is(app.params.ajaxLinks)) {
1766
+ return;
1767
+ }
1768
+ var validUrl = url && url.length > 0 && url.indexOf('#') !== 0;
1769
+ if (validUrl || clicked.hasClass('back')) {
1770
+ var view;
1771
+ if (clicked.attr('data-view')) {
1772
+ view = $(clicked.attr('data-view'))[0].f7View;
1773
+ }
1774
+ else {
1775
+ view = clicked.parents('.view')[0] && clicked.parents('.view')[0].f7View;
1776
+ }
1777
+ if (!view) {
1778
+ for (var i = 0; i < app.views.length; i++) {
1779
+ if (app.views[i].main) view = app.views[i];
1780
+ }
1781
+ }
1782
+ if (!view) return;
1783
+ if (clicked.hasClass('back')) view.goBack(clicked.attr('href'));
1784
+ else view.loadPage(clicked.attr('href'));
1785
+ }
1786
+ }
1787
+ $(document).tap('a, .open-panel, .close-panel, .panel-overlay, .modal-overlay, .swipeout-delete, .close-popup, .open-popup, .open-popover, .label-checkbox, .label-radio, .label-switch, .label-switch input', handleTap);
1788
+
1789
+ //Disable clicks
1790
+ function handleClick(e) {
1791
+ /*jshint validthis:true */
1792
+ if (!$(this).hasClass('external')) e.preventDefault();
1793
+ }
1794
+ $(document).on('click', 'a, .label-checkbox, .label-radio', handleClick);
1795
+ };
1796
+ /*======================================================
1797
+ ************ App Resize Actions ************
1798
+ ======================================================*/
1799
+ app.initResize = function () {
1800
+ $(window).on('resize', app.resize);
1801
+ $(window).on('orientationchange', app.orientationchange);
1802
+ };
1803
+ app.resize = function () {
1804
+ if (app.sizeNavbars) app.sizeNavbars();
1805
+ };
1806
+ app.orientationchange = function () {
1807
+ if (app.device && app.device.minimalUi) {
1808
+ if (window.orientation === 90 || window.orientation === -90) document.body.scrollTop = 0;
1809
+ }
1810
+ };
1811
+ /*===========================
1812
+ Device/OS Detection
1813
+ ===========================*/
1814
+ app.getDeviceInfo = function () {
1815
+ var device = {};
1816
+ var ua = navigator.userAgent;
1817
+
1818
+ var android = ua.match(/(Android);?[\s\/]+([\d.]+)?/);
1819
+ var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
1820
+ var ipod = ua.match(/(iPod)(.*OS\s([\d_]+))?/);
1821
+ var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
1822
+
1823
+ // Android
1824
+ if (android) {
1825
+ device.os = 'android';
1826
+ device.osVersion = android[2];
1827
+ }
1828
+ if (ipad || iphone || ipod) {
1829
+ device.os = 'ios';
1830
+ }
1831
+ // iOS
1832
+ if (iphone && !ipod) device.osVersion = iphone[2].replace(/_/g, '.');
1833
+ if (ipad) device.osVersion = ipad[2].replace(/_/g, '.');
1834
+ if (ipod) device.osVersion = ipod[3] ? ipod[3].replace(/_/g, '.') : null;
1835
+
1836
+ // Webview
1837
+ device.webview = (iphone || ipad || ipod) && ua.match(/.*AppleWebKit(?!.*Safari)/i);
1838
+
1839
+ // Minimal UI
1840
+ if (device.os && device.os === 'ios') {
1841
+ var osVersionArr = device.osVersion.split('.');
1842
+ device.minimalUi = !device.webview &&
1843
+ (ipod || iphone) &&
1844
+ (osVersionArr[0] * 1 === 7 ? osVersionArr[1] * 1 >= 1 : osVersionArr[0] * 1 > 7) &&
1845
+ $('meta[name="viewport"]').length > 0 && $('meta[name="viewport"]').attr('content').indexOf('minimal-ui') >= 0;
1846
+ }
1847
+
1848
+ // Check for status bar and fullscreen app mode
1849
+ var windowWidth = $(window).width();
1850
+ var windowHeight = $(window).height();
1851
+ device.statusBar = false;
1852
+ if (
1853
+ device.webview &&
1854
+ // iPhone 5
1855
+ (windowWidth === 320 && windowHeight === 568) ||
1856
+ (windowWidth === 568 && windowHeight === 320) ||
1857
+ // iPhone 4
1858
+ (windowWidth === 320 && windowHeight === 480) ||
1859
+ (windowWidth === 480 && windowHeight === 320) ||
1860
+ // iPad
1861
+ (windowWidth === 768 && windowHeight === 1024) ||
1862
+ (windowWidth === 1024 && windowHeight === 768)
1863
+ ) {
1864
+ device.statusBar = true;
1865
+ }
1866
+ else {
1867
+ device.statusBar = false;
1868
+ }
1869
+
1870
+ // Pixel Ratio
1871
+ device.pixelRatio = window.devicePixelRatio || 1;
1872
+
1873
+ // Add html classes
1874
+ if (device.os) {
1875
+ var className = device.os +
1876
+ ' ' +
1877
+ device.os + '-' + device.osVersion.replace(/\./g, '-') +
1878
+ ' ' +
1879
+ device.os + '-' + device.osVersion.split('.')[0];
1880
+ $('html').addClass(className);
1881
+ }
1882
+ if (device.statusBar) {
1883
+ $('html').addClass('with-statusbar-overlay');
1884
+ }
1885
+ else {
1886
+ $('html').removeClass('with-statusbar-overlay');
1887
+ }
1888
+
1889
+ // Export to app
1890
+ app.device = device;
1891
+ };
1892
+ /*======================================================
1893
+ ************ App Init ************
1894
+ ======================================================*/
1895
+ app.init = function () {
1896
+ if (app.getDeviceInfo) app.getDeviceInfo();
1897
+ // Init Click events
1898
+ if (app.initClickEvents) app.initClickEvents();
1899
+ // Init Swipeouts events
1900
+ if (app.initSwipeout && app.params.swipeout) app.initSwipeout();
1901
+ // Init Pull To Refresh
1902
+ if (app.initPullToRefresh && app.params.pullToRefresh) app.initPullToRefresh();
1903
+ // Init each page callbacks
1904
+ $('.page').each(function () {
1905
+ app.initPage(this);
1906
+ });
1907
+ // Init resize events
1908
+ if (app.initResize) app.initResize();
1909
+
1910
+ // App Init callback
1911
+ if (app.params.onAppInit) app.params.onAppInit();
1912
+ };
1913
+ if (app.params.init) app.init();
1914
+ //Return instance
1915
+ return app;
1916
+ };
1917
+
1918
+ /*===========================
1919
+ jQuery-like DOM library
1920
+ ===========================*/
1921
+ var Dom7 = function (arr) {
1922
+ var _this = this, i = 0;
1923
+ // Create array-like object
1924
+ for (i = 0; i < arr.length; i++) {
1925
+ _this[i] = arr[i];
1926
+ }
1927
+ _this.length = arr.length;
1928
+ // Return collection with methods
1929
+ return this;
1930
+ };
1931
+ Dom7.prototype = {
1932
+ // Classes and attriutes
1933
+ addClass: function (className) {
1934
+ var classes = className.split(' ');
1935
+ for (var i = 0; i < classes.length; i++) {
1936
+ for (var j = 0; j < this.length; j++) {
1937
+ this[j].classList.add(classes[i]);
1938
+ }
1939
+ }
1940
+ return this;
1941
+ },
1942
+ removeClass: function (className) {
1943
+ var classes = className.split(' ');
1944
+ for (var i = 0; i < classes.length; i++) {
1945
+ for (var j = 0; j < this.length; j++) {
1946
+ this[j].classList.remove(classes[i]);
1947
+ }
1948
+ }
1949
+ return this;
1950
+ },
1951
+ hasClass: function (className) {
1952
+ if (!this[0]) return false;
1953
+ else return this[0].className.indexOf(className) >= 0;
1954
+ },
1955
+ toggleClass: function (className) {
1956
+ var classes = className.split(' ');
1957
+ for (var i = 0; i < classes.length; i++) {
1958
+ for (var j = 0; j < this.length; j++) {
1959
+ this[j].classList.toggle(classes[i]);
1960
+ }
1961
+ }
1962
+ return this;
1963
+ },
1964
+ attr: function (attr, value) {
1965
+ if (typeof value === 'undefined') {
1966
+ return this[0].getAttribute(attr);
1967
+ }
1968
+ else {
1969
+ for (var i = 0; i < this.length; i++) {
1970
+ this[i].setAttribute(attr, value);
1971
+ }
1972
+ return this;
1973
+ }
1974
+ },
1975
+ val: function (value) {
1976
+ if (typeof value === 'undefined') {
1977
+ if (this[0]) return this[0].value;
1978
+ else return null;
1979
+ }
1980
+ else {
1981
+ for (var i = 0; i < this.length; i++) {
1982
+ this[i].value = value;
1983
+ }
1984
+ return this;
1985
+ }
1986
+ },
1987
+ // Transforms
1988
+ transform : function (transform) {
1989
+ for (var i = 0; i < this.length; i++) {
1990
+ var elStyle = this[i].style;
1991
+ elStyle.webkitTransform = elStyle.MsTransform = elStyle.msTransform = elStyle.MozTransform = elStyle.OTransform = elStyle.transform = transform;
1992
+ }
1993
+ return this;
1994
+ },
1995
+ transition: function (duration) {
1996
+ for (var i = 0; i < this.length; i++) {
1997
+ var elStyle = this[i].style;
1998
+ elStyle.webkitTransitionDuration = elStyle.MsTransitionDuration = elStyle.msTransitionDuration = elStyle.MozTransitionDuration = elStyle.OTransitionDuration = elStyle.transitionDuration = duration + 'ms';
1999
+ }
2000
+ return this;
2001
+ },
2002
+ //Events
2003
+ on: function (eventName, targetSelector, listener) {
2004
+ function handleLiveEvent(e) {
2005
+ var target = e.target;
2006
+ if ($(target).is(targetSelector)) listener.call(target, e);
2007
+ else {
2008
+ var parents = $(target).parents();
2009
+ for (var k = 0; k < parents.length; k++) {
2010
+ if ($(parents[k]).is(targetSelector)) listener.call(parents[k], e);
2011
+ }
2012
+ }
2013
+ }
2014
+ var events = eventName.split(' ');
2015
+ var i, j;
2016
+ for (i = 0; i < this.length; i++) {
2017
+ if (arguments.length === 2 || targetSelector === false) {
2018
+ // Usual events
2019
+ if (arguments.length === 2) listener = arguments[1];
2020
+ for (j = 0; j < events.length; j++) {
2021
+ this[i].addEventListener(events[j], listener, false);
2022
+ }
2023
+ }
2024
+ else {
2025
+ //Live events
2026
+ for (j = 0; j < events.length; j++) {
2027
+ this[i].addEventListener(events[j], handleLiveEvent, false);
2028
+ }
2029
+ }
2030
+ }
2031
+
2032
+ return this;
2033
+ },
2034
+ tap: function (targetSelector, listener) {
2035
+ var dom = this;
2036
+ var isTouched, isMoved, touchesStart = {}, touchStartTime, deltaX, deltaY;
2037
+ if (arguments.length === 1) {
2038
+ listener = arguments[0];
2039
+ targetSelector = false;
2040
+ }
2041
+ function handleTouchStart(e) {
2042
+ isTouched = true;
2043
+ isMoved = false;
2044
+ }
2045
+ function handleTouchMove(e) {
2046
+ if (!isTouched || isMoved) return;
2047
+ isMoved = true;
2048
+ }
2049
+ function handleTouchEnd(e) {
2050
+ e.preventDefault(); // - to prevent Safari's Ghost click
2051
+ if (isTouched && !isMoved) {
2052
+ /*jshint validthis:true */
2053
+ listener.call(this, e);
2054
+ }
2055
+ isTouched = isMoved = false;
2056
+ }
2057
+ if ($.supportTouch) {
2058
+ dom.on('touchstart', targetSelector, handleTouchStart);
2059
+ dom.on('touchmove', targetSelector, handleTouchMove);
2060
+ dom.on('touchend', targetSelector, handleTouchEnd);
2061
+ }
2062
+ else {
2063
+ dom.on('click', targetSelector, listener);
2064
+ }
2065
+ },
2066
+ off: function (event, listener) {
2067
+ for (var i = 0; i < this.length; i++) {
2068
+ this[i].removeEventListener(event, listener, false);
2069
+ }
2070
+ return this;
2071
+ },
2072
+ trigger: function (eventName, eventData) {
2073
+ for (var i = 0; i < this.length; i++) {
2074
+ var evt;
2075
+ try {
2076
+ evt = new CustomEvent(eventName, {detail: eventData, bubbles: true, cancelable: true});
2077
+ }
2078
+ catch (e) {
2079
+ evt = document.createEvent('Event');
2080
+ evt.initEvent(eventName, true, true);
2081
+ evt.detail = eventData;
2082
+ }
2083
+ this[i].dispatchEvent(evt);
2084
+ }
2085
+ return this;
2086
+ },
2087
+ transitionEnd: function (callback) {
2088
+ var events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'],
2089
+ i, j, dom = this;
2090
+ function fireCallBack(e) {
2091
+ /*jshint validthis:true */
2092
+ callback.call(this, e);
2093
+ for (i = 0; i < events.length; i++) {
2094
+ dom.off(events[i], fireCallBack);
2095
+ }
2096
+ }
2097
+ if (callback) {
2098
+ for (i = 0; i < events.length; i++) {
2099
+ dom.on(events[i], fireCallBack);
2100
+ }
2101
+ }
2102
+ return this;
2103
+ },
2104
+ animationEnd: function (callback) {
2105
+ var events = ['webkitAnimationEnd', 'OAnimationEnd', 'MSAnimationEnd', 'animationend'],
2106
+ i, j, dom = this;
2107
+ function fireCallBack(e) {
2108
+ callback(e);
2109
+ for (i = 0; i < events.length; i++) {
2110
+ dom.off(events[i], fireCallBack);
2111
+ }
2112
+ }
2113
+ if (callback) {
2114
+ for (i = 0; i < events.length; i++) {
2115
+ dom.on(events[i], fireCallBack);
2116
+ }
2117
+ }
2118
+ return this;
2119
+ },
2120
+ // Sizing/Styles
2121
+ width: function () {
2122
+ if (this[0] === window) {
2123
+ return window.innerWidth;
2124
+ }
2125
+ else {
2126
+ if (this.length > 0) {
2127
+ return parseFloat(this.css('width')) - parseFloat(this.css('padding-left')) - parseFloat(this.css('padding-right'));
2128
+ }
2129
+ else {
2130
+ return null;
2131
+ }
2132
+ }
2133
+
2134
+ },
2135
+ outerWidth: function (margins) {
2136
+ if (this.length > 0) {
2137
+ if (margins)
2138
+ return this[0].offsetWidth + parseFloat(this.css('margin-right')) + parseFloat(this.css('margin-left'));
2139
+ else
2140
+ return this[0].offsetWidth;
2141
+ }
2142
+ else return null;
2143
+ },
2144
+ height: function () {
2145
+ if (this[0] === window) {
2146
+ return window.innerHeight;
2147
+ }
2148
+ else {
2149
+ if (this.length > 0) {
2150
+ return this[0].offsetHeight - parseFloat(this.css('padding-top')) - parseFloat(this.css('padding-bottom'));
2151
+ }
2152
+ else {
2153
+ return null;
2154
+ }
2155
+ }
2156
+
2157
+ },
2158
+ outerHeight: function (margins) {
2159
+ if (this.length > 0) {
2160
+ if (margins)
2161
+ return this[0].offsetHeight + parseFloat(this.css('margin-top')) + parseFloat(this.css('margin-bottom'));
2162
+ else
2163
+ return this[0].offsetHeight;
2164
+ }
2165
+ else return null;
2166
+ },
2167
+ offset: function () {
2168
+ if (this.length > 0) {
2169
+ var el = this[0];
2170
+ var box = el.getBoundingClientRect();
2171
+ var body = document.body;
2172
+ var clientTop = el.clientTop || body.clientTop || 0;
2173
+ var clientLeft = el.clientLeft || body.clientLeft || 0;
2174
+ var scrollTop = window.pageYOffset || el.scrollTop;
2175
+ var scrollLeft = window.pageXOffset || el.scrollLeft;
2176
+ return {
2177
+ top: box.top + scrollTop - clientTop,
2178
+ left: box.left + scrollLeft - clientLeft
2179
+ };
2180
+ }
2181
+ else {
2182
+ return null;
2183
+ }
2184
+ },
2185
+ hide: function () {
2186
+ for (var i = 0; i < this.length; i++) {
2187
+ this[i].style.display = 'none';
2188
+ }
2189
+ return this;
2190
+ },
2191
+ show: function () {
2192
+ for (var i = 0; i < this.length; i++) {
2193
+ this[i].style.display = 'block';
2194
+ }
2195
+ return this;
2196
+ },
2197
+ css: function (props) {
2198
+ if (typeof props === 'string') {
2199
+ if (this[0]) return window.getComputedStyle(this[0], null).getPropertyValue(props);
2200
+ }
2201
+ else {
2202
+ for (var i = 0; i < this.length; i++) {
2203
+ for (var prop in props) {
2204
+ this[i].style[prop] = props[prop];
2205
+ }
2206
+ }
2207
+ return this;
2208
+ }
2209
+
2210
+ },
2211
+
2212
+ //Dom manipulation
2213
+ each: function (callback) {
2214
+ for (var i = 0; i < this.length; i++) {
2215
+ callback.call(this[i], i, this[i]);
2216
+ }
2217
+ return this;
2218
+ },
2219
+ html: function (html) {
2220
+ if (typeof html === 'undefined') {
2221
+ return this[0].innerHTML;
2222
+ }
2223
+ else {
2224
+ for (var i = 0; i < this.length; i++) {
2225
+ this[i].innerHTML = html;
2226
+ }
2227
+ return this;
2228
+ }
2229
+ },
2230
+ text: function (text) {
2231
+ if (typeof text === 'undefined') {
2232
+ if (this[0]) {
2233
+ return this[0].textContent.trim();
2234
+ }
2235
+ else return null;
2236
+ }
2237
+ else {
2238
+ for (var i = 0; i < this.length; i++) {
2239
+ this[0].textContent = text;
2240
+ }
2241
+ }
2242
+ },
2243
+ is: function (selector) {
2244
+ var compareWith;
2245
+ if (typeof selector === 'string') compareWith = document.querySelectorAll(selector);
2246
+ else if (selector.nodeType) compareWith = [selector];
2247
+ else compareWith = selector;
2248
+ for (var i = 0; i < compareWith.length; i++) {
2249
+ if (compareWith[i] === this[0]) return true;
2250
+ }
2251
+ return false;
2252
+ },
2253
+ indexOf: function (el) {
2254
+ for (var i = 0; i < this.length; i++) {
2255
+ if (this[i] === el) return i;
2256
+ }
2257
+ },
2258
+ append: function (newChild) {
2259
+ for (var i = 0; i < this.length; i++) {
2260
+ if (typeof newChild === 'string') {
2261
+ var tempDiv = document.createElement('div');
2262
+ tempDiv.innerHTML = newChild;
2263
+ while (tempDiv.firstChild) {
2264
+ this[i].appendChild(tempDiv.firstChild);
2265
+ }
2266
+ }
2267
+ else {
2268
+ this[i].appendChild(newChild);
2269
+ }
2270
+ }
2271
+ return this;
2272
+ },
2273
+ prepend: function (newChild) {
2274
+ for (var i = 0; i < this.length; i++) {
2275
+ if (typeof newChild === 'string') {
2276
+ var tempDiv = document.createElement('div');
2277
+ tempDiv.innerHTML = newChild;
2278
+ for (var j = tempDiv.childNodes.length - 1; j >= 0; j--) {
2279
+ this[i].insertBefore(tempDiv.childNodes[j], this[i].childNodes[0]);
2280
+ }
2281
+ }
2282
+ else {
2283
+ this[i].insertBefore(newChild, this[i].childNodes[0]);
2284
+ }
2285
+ }
2286
+ return this;
2287
+ },
2288
+ insertBefore: function (selector) {
2289
+ var before = $(selector);
2290
+ for (var i = 0; i < this.length; i++) {
2291
+ if (before.length === 1) {
2292
+ before[0].parentNode.insertBefore(this[i], before[0]);
2293
+ }
2294
+ else if (before.length > 1) {
2295
+ for (var j = 0; j < before.length; j++) {
2296
+ before[j].parentNode.insertBefore(this[i].cloneNode(true), before[j]);
2297
+ }
2298
+ }
2299
+ }
2300
+ },
2301
+ next: function () {
2302
+ if (this.length > 0) {
2303
+ if (this[0].nextElementSibling) return new Dom7([this[0].nextElementSibling]);
2304
+ else return new Dom7([]);
2305
+ }
2306
+ else return new Dom7([]);
2307
+ },
2308
+ prev: function () {
2309
+ if (this.length > 0) {
2310
+ if (this[0].previousElementSibling) return new Dom7([this[0].previousElementSibling]);
2311
+ else return new Dom7([]);
2312
+ }
2313
+ else return new Dom7([]);
2314
+ },
2315
+ parent: function (selector) {
2316
+ var parents = [];
2317
+ for (var i = 0; i < this.length; i++) {
2318
+ if (selector) {
2319
+ if ($(this[i].parentNode).is(selector)) parents.push(this[i].parentNode);
2320
+ }
2321
+ else {
2322
+ parents.push(this[i].parentNode);
2323
+ }
2324
+ }
2325
+ return $($.unique(parents));
2326
+ },
2327
+ parents: function (selector) {
2328
+ var parents = [];
2329
+ for (var i = 0; i < this.length; i++) {
2330
+ var parent = this[i].parentNode;
2331
+ while (parent) {
2332
+ if (selector) {
2333
+ if ($(parent).is(selector)) parents.push(parent);
2334
+ }
2335
+ else {
2336
+ parents.push(parent);
2337
+ }
2338
+ parent = parent.parentNode;
2339
+ }
2340
+ }
2341
+ return $($.unique(parents));
2342
+ },
2343
+ find : function (selector) {
2344
+ var foundElements = [];
2345
+ for (var i = 0; i < this.length; i++) {
2346
+ var found = this[i].querySelectorAll(selector);
2347
+ for (var j = 0; j < found.length; j++) {
2348
+ foundElements.push(found[j]);
2349
+ }
2350
+ }
2351
+ return new Dom7(foundElements);
2352
+ },
2353
+ children: function (selector) {
2354
+ var children = [];
2355
+ for (var i = 0; i < this.length; i++) {
2356
+ var childNodes = this[i].childNodes;
2357
+
2358
+ for (var j = 0; j < childNodes.length; j++) {
2359
+ if (!selector) {
2360
+ if (childNodes[j].nodeType === 1) children.push(childNodes[j]);
2361
+ }
2362
+ else {
2363
+ if (childNodes[j].nodeType === 1 && $(childNodes[j]).is(selector)) children.push(childNodes[j]);
2364
+ }
2365
+ }
2366
+ }
2367
+ return new Dom7($.unique(children));
2368
+ },
2369
+ remove: function () {
2370
+ for (var i = 0; i < this.length; i++) {
2371
+ if (this[i].parentNode) this[i].parentNode.removeChild(this[i]);
2372
+ }
2373
+ return this;
2374
+ },
2375
+
2376
+ };
2377
+ var $ = function (selector, context) {
2378
+ var arr = [], i = 0;
2379
+ if (selector) {
2380
+ // String
2381
+ if (typeof selector === 'string') {
2382
+ var els = (context || document).querySelectorAll(selector);
2383
+ for (i = 0; i < els.length; i++) {
2384
+ arr.push(els[i]);
2385
+ }
2386
+ }
2387
+ // Node/element
2388
+ else if (selector.nodeType || selector === window || selector === document) {
2389
+ arr.push(selector);
2390
+ }
2391
+ //Array of elements or instance of Dom
2392
+ else if (selector.length > 0 && selector[0].nodeType) {
2393
+ for (i = 0; i < selector.length; i++) {
2394
+ arr.push(selector[i]);
2395
+ }
2396
+ }
2397
+ }
2398
+ return new Dom7(arr);
2399
+ };
2400
+ // Utilites
2401
+ $.parseUrlQuery = function (url) {
2402
+ var query = {}, i, params, param;
2403
+ if (url.indexOf('?') >= 0) url = url.split('?')[1];
2404
+ params = url.split('&');
2405
+ for (i = 0; i < params.length; i++) {
2406
+ param = params[i].split('=');
2407
+ query[param[0]] = param[1];
2408
+ }
2409
+ return query;
2410
+ };
2411
+ $.isArray = function (arr) {
2412
+ if (Object.prototype.toString.apply(arr) === '[object Array]') return true;
2413
+ else return false;
2414
+ };
2415
+ $.unique = function (arr) {
2416
+ var unique = [];
2417
+ for (var i = 0; i < arr.length; i++) {
2418
+ if (unique.indexOf(arr[i]) === -1) unique.push(arr[i]);
2419
+ }
2420
+ return unique;
2421
+ };
2422
+ $.trim = function (str) {
2423
+ return str.trim();
2424
+ };
2425
+ $.supportTouch = (function () {
2426
+ return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch);
2427
+ })();
2428
+ $.fn = Dom7.prototype;
2429
+ })();