framework7-rails 0.6.8

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