45 files changed, 5012 insertions, 797 deletions
diff --git a/frontend/gamma/js/Clipperz/Async.js b/frontend/gamma/js/Clipperz/Async.js index 97d8ecf..f7a9517 100644 --- a/frontend/gamma/js/Clipperz/Async.js +++ b/frontend/gamma/js/Clipperz/Async.js | |||
diff --git a/frontend/gamma/js/Clipperz/Base.js b/frontend/gamma/js/Clipperz/Base.js index 76b2c3f..9d399d9 100644 --- a/frontend/gamma/js/Clipperz/Base.js +++ b/frontend/gamma/js/Clipperz/Base.js | |||
@@ -77,6 +77,11 @@ MochiKit.Base.update(Clipperz.Base, { | |||
77 | return MochiKit.Base.compose(function(aResult) { return -aResult; }, aComparator); | 77 | return MochiKit.Base.compose(function(aResult) { return -aResult; }, aComparator); |
78 | }, | 78 | }, |
79 | 79 | ||
80 | 'caseInsensitiveKeyComparator': function (aKey) { | ||
81 | return function (a, b) { | ||
82 | return MochiKit.Base.compare(a[aKey].toLowerCase(), b[aKey].toLowerCase()); | ||
83 | } | ||
84 | }, | ||
80 | //------------------------------------------------------------------------- | 85 | //------------------------------------------------------------------------- |
81 | /* | 86 | /* |
82 | 'dependsOn': function(module, deps) { | 87 | 'dependsOn': function(module, deps) { |
diff --git a/frontend/gamma/js/Clipperz/PM/Connection.js b/frontend/gamma/js/Clipperz/PM/Connection.js index b4e8aaa..a05a310 100644 --- a/frontend/gamma/js/Clipperz/PM/Connection.js +++ b/frontend/gamma/js/Clipperz/PM/Connection.js | |||
@@ -41,6 +41,7 @@ Clipperz.PM.Connection = function (args) { | |||
41 | this._clipperz_pm_crypto_version = null; | 41 | this._clipperz_pm_crypto_version = null; |
42 | this._connectionId = null; | 42 | this._connectionId = null; |
43 | this._sharedSecret = null; | 43 | this._sharedSecret = null; |
44 | this._serverLockValue = null; | ||
44 | 45 | ||
45 | return this; | 46 | return this; |
46 | } | 47 | } |
@@ -146,6 +147,16 @@ MochiKit.Logging.logError("### Connection.defaultErrorHandler: " + anErrorString | |||
146 | this._connectionId = aValue; | 147 | this._connectionId = aValue; |
147 | }, | 148 | }, |
148 | 149 | ||
150 | //------------------------------------------------------------------------- | ||
151 | |||
152 | 'serverLockValue': function () { | ||
153 | return this._serverLockValue; | ||
154 | }, | ||
155 | |||
156 | 'setServerLockValue': function (aValue) { | ||
157 | this._serverLockValue = aValue; | ||
158 | }, | ||
159 | |||
149 | //========================================================================= | 160 | //========================================================================= |
150 | /* | 161 | /* |
151 | //TODO: ????? | 162 | //TODO: ????? |
@@ -320,13 +331,12 @@ Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz. | |||
320 | ], {trace:false}) | 331 | ], {trace:false}) |
321 | }, | 332 | }, |
322 | 333 | ||
323 | 'login': function(/*anUsername, aPassphrase*/) { | 334 | 'login': function(isReconnecting) { |
324 | vardeferredResult; | 335 | vardeferredResult; |
325 | var cryptoVersion; | 336 | var cryptoVersion; |
326 | var srpConnection; | 337 | var srpConnection; |
327 | 338 | ||
328 | cryptoVersion = this.clipperz_pm_crypto_version(); | 339 | cryptoVersion = this.clipperz_pm_crypto_version(); |
329 | |||
330 | deferredResult = new Clipperz.Async.Deferred("Connection.login", {trace:false}); | 340 | deferredResult = new Clipperz.Async.Deferred("Connection.login", {trace:false}); |
331 | deferredResult.addCallback(this.getCredentialsFunction()); | 341 | deferredResult.addCallback(this.getCredentialsFunction()); |
332 | deferredResult.addMethod(this, 'normalizedCredentials'); | 342 | deferredResult.addMethod(this, 'normalizedCredentials'); |
@@ -399,6 +409,13 @@ Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz. | |||
399 | // if (this.oneTimePassword() != null) { | 409 | // if (this.oneTimePassword() != null) { |
400 | /// ?? result = this.user().oneTimePasswordManager().archiveOneTimePassword(this.oneTimePassword())); | 410 | /// ?? result = this.user().oneTimePasswordManager().archiveOneTimePassword(this.oneTimePassword())); |
401 | // } | 411 | // } |
412 | |||
413 | if ((isReconnecting == true) && (this.serverLockValue() != someParameters['lock'])) { | ||
414 | throw Clipperz.PM.Connection.exception.StaleData; | ||
415 | } else { | ||
416 | this.setServerLockValue(someParameters['lock']); | ||
417 | } | ||
418 | |||
402 | return someParameters; | 419 | return someParameters; |
403 | }, this)); | 420 | }, this)); |
404 | // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_loggedIn'); | 421 | // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_loggedIn'); |
@@ -429,12 +446,19 @@ Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz. | |||
429 | 446 | ||
430 | 'message': function(aMessageName, someParameters) { | 447 | 'message': function(aMessageName, someParameters) { |
431 | var args; | 448 | var args; |
449 | var parameters; | ||
450 | |||
451 | parameters = someParameters || {}; | ||
452 | if (typeof(parameters['user']) != 'undefined') { | ||
453 | parameters['user']['lock'] = this.serverLockValue(); | ||
454 | } | ||
432 | 455 | ||
433 | //console.log(">>> Connection.message", aMessageName, someParameters); | 456 | //console.log(">>> Connection.message", aMessageName, someParameters); |
434 | args = { | 457 | args = { |
435 | message: aMessageName, | 458 | message: aMessageName, |
436 | srpSharedSecret: this.sharedSecret(), | 459 | srpSharedSecret: this.sharedSecret(), |
437 | parameters: (someParameters || {}) | 460 | // parameters: (someParameters || {}) |
461 | parameters: parameters | ||
438 | } | 462 | } |
439 | 463 | ||
440 | return this.sendMessage(args); | 464 | return this.sendMessage(args); |
@@ -449,8 +473,7 @@ Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz. | |||
449 | deferredResult.addMethod(this.proxy(), 'message', someArguments); | 473 | deferredResult.addMethod(this.proxy(), 'message', someArguments); |
450 | deferredResult.addCallback(MochiKit.Base.bind(function(res) { | 474 | deferredResult.addCallback(MochiKit.Base.bind(function(res) { |
451 | if (typeof(res['lock']) != 'undefined') { | 475 | if (typeof(res['lock']) != 'undefined') { |
452 | //TODO: ????? | 476 | this.setServerLockValue(res['lock']); |
453 | // ?? this.user().setLock(res['lock']); | ||
454 | } | 477 | } |
455 | return res; | 478 | return res; |
456 | }, this)); | 479 | }, this)); |
@@ -587,6 +610,7 @@ Clipperz.PM.Connection.SRP['1.1'].prototype = MochiKit.Base.update(new Clipperz. | |||
587 | 610 | ||
588 | Clipperz.PM.Connection.exception = { | 611 | Clipperz.PM.Connection.exception = { |
589 | WrongChecksum: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.InvalidValue"), | 612 | WrongChecksum: new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.InvalidValue"), |
613 | StaleData: new MochiKit.Base.NamedError("Stale data"), | ||
590 | UnexpectedRequest:new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.UnexpectedRequest") | 614 | UnexpectedRequest:new MochiKit.Base.NamedError("Clipperz.ByteArray.exception.UnexpectedRequest") |
591 | }; | 615 | }; |
592 | 616 | ||
diff --git a/frontend/gamma/js/Clipperz/PM/DataModel/User.js b/frontend/gamma/js/Clipperz/PM/DataModel/User.js index 72d4006..646ce21 100644 --- a/frontend/gamma/js/Clipperz/PM/DataModel/User.js +++ b/frontend/gamma/js/Clipperz/PM/DataModel/User.js | |||
@@ -44,7 +44,7 @@ Clipperz.PM.DataModel.User = function (args) { | |||
44 | this._connectionVersion = 'current'; | 44 | this._connectionVersion = 'current'; |
45 | 45 | ||
46 | this._serverData = null; | 46 | this._serverData = null; |
47 | this._serverLockValue = null; | 47 | //this._serverLockValue = null; |
48 | this._transientState = null; | 48 | this._transientState = null; |
49 | 49 | ||
50 | this._deferredLocks = { | 50 | this._deferredLocks = { |
@@ -93,7 +93,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | |||
93 | }, | 93 | }, |
94 | 94 | ||
95 | //------------------------------------------------------------------------- | 95 | //------------------------------------------------------------------------- |
96 | 96 | /* | |
97 | 'serverLockValue': function () { | 97 | 'serverLockValue': function () { |
98 | return this._serverLockValue; | 98 | return this._serverLockValue; |
99 | }, | 99 | }, |
@@ -101,7 +101,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | |||
101 | 'setServerLockValue': function (aValue) { | 101 | 'setServerLockValue': function (aValue) { |
102 | this._serverLockValue = aValue; | 102 | this._serverLockValue = aValue; |
103 | }, | 103 | }, |
104 | 104 | */ | |
105 | //------------------------------------------------------------------------- | 105 | //------------------------------------------------------------------------- |
106 | 106 | ||
107 | 'transientState': function () { | 107 | 'transientState': function () { |
@@ -220,8 +220,8 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | |||
220 | deferredResult.addMethod(this, 'prepareRemoteDataWithKey'); | 220 | deferredResult.addMethod(this, 'prepareRemoteDataWithKey'); |
221 | deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); | 221 | deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); |
222 | deferredResult.addMethod(this.connection(), 'register'); | 222 | deferredResult.addMethod(this.connection(), 'register'); |
223 | deferredResult.addCallback(MochiKit.Base.itemgetter('lock')); | 223 | // deferredResult.addCallback(MochiKit.Base.itemgetter('lock')); |
224 | deferredResult.addMethod(this, 'setServerLockValue'); | 224 | // deferredResult.addMethod(this, 'setServerLockValue'); |
225 | deferredResult.addCallbackPass(MochiKit.Signal.signal,Clipperz.Signal.NotificationCenter, 'userSuccessfullyRegistered'); | 225 | deferredResult.addCallbackPass(MochiKit.Signal.signal,Clipperz.Signal.NotificationCenter, 'userSuccessfullyRegistered'); |
226 | 226 | ||
227 | // deferredResult.addErrback (MochiKit.Base.method(this, 'handleRegistrationFailure')); | 227 | // deferredResult.addErrback (MochiKit.Base.method(this, 'handleRegistrationFailure')); |
@@ -247,7 +247,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | |||
247 | MochiKit.Base.method(this.data(), 'setValue', 'passphrase') | 247 | MochiKit.Base.method(this.data(), 'setValue', 'passphrase') |
248 | ], [])); | 248 | ], [])); |
249 | deferredResult.addErrback(MochiKit.Base.method(this, 'getPassphrase')); | 249 | deferredResult.addErrback(MochiKit.Base.method(this, 'getPassphrase')); |
250 | deferredResult.addMethod(this.connection(), 'login'); | 250 | deferredResult.addMethod(this.connection(), 'login', false); |
251 | deferredResult.addCallbackPass(MochiKit.Signal.signal,Clipperz.Signal.NotificationCenter, 'userSuccessfullyLoggedIn'); | 251 | deferredResult.addCallbackPass(MochiKit.Signal.signal,Clipperz.Signal.NotificationCenter, 'userSuccessfullyLoggedIn'); |
252 | deferredResult.addErrback (MochiKit.Base.method(this, 'handleConnectionFallback')); | 252 | deferredResult.addErrback (MochiKit.Base.method(this, 'handleConnectionFallback')); |
253 | 253 | ||
@@ -329,7 +329,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | |||
329 | var oneTimePasswords; | 329 | var oneTimePasswords; |
330 | 330 | ||
331 | //console.log(">>> ***************** user.unpackServerData", someServerData); | 331 | //console.log(">>> ***************** user.unpackServerData", someServerData); |
332 | this.setServerLockValue(someServerData['lock']); | 332 | // this.setServerLockValue(someServerData['lock']); |
333 | 333 | ||
334 | headerVersion = this.headerFormatVersion(someServerData['header']); | 334 | headerVersion = this.headerFormatVersion(someServerData['header']); |
335 | 335 | ||
@@ -662,8 +662,8 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | |||
662 | MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'commitTransientState'), | 662 | MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'commitTransientState'), |
663 | 663 | ||
664 | MochiKit.Base.method(this, 'transientState'), | 664 | MochiKit.Base.method(this, 'transientState'), |
665 | MochiKit.Base.itemgetter('lock'), | 665 | // MochiKit.Base.itemgetter('lock'), |
666 | MochiKit.Base.method(this, 'setServerLockValue'), | 666 | // MochiKit.Base.method(this, 'setServerLockValue'), |
667 | MochiKit.Base.method(this, 'resetTransientState', true) | 667 | MochiKit.Base.method(this, 'resetTransientState', true) |
668 | ], {trace:false}); | 668 | ], {trace:false}); |
669 | }, | 669 | }, |
@@ -740,7 +740,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | |||
740 | return aResult; | 740 | return aResult; |
741 | }, this), result); | 741 | }, this), result); |
742 | deferredResult.addCallback(Clipperz.Async.setItem, result, 'version', Clipperz.PM.Crypto.encryptingFunctions.currentVersion); | 742 | deferredResult.addCallback(Clipperz.Async.setItem, result, 'version', Clipperz.PM.Crypto.encryptingFunctions.currentVersion); |
743 | deferredResult.addCallback(Clipperz.Async.setItem, result, 'lock', this.serverLockValue()); | 743 | // deferredResult.addCallback(Clipperz.Async.setItem, result, 'lock', this.serverLockValue()); |
744 | deferredResult.callback(); | 744 | deferredResult.callback(); |
745 | 745 | ||
746 | return deferredResult; | 746 | return deferredResult; |
diff --git a/frontend/gamma/js/Clipperz/PM/PIN.js b/frontend/gamma/js/Clipperz/PM/PIN.js new file mode 100644 index 0000000..bc932b2 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/PIN.js | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2011 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz Community Edition. | ||
6 | Clipperz Community Edition is an online password manager. | ||
7 | For further information about its features and functionalities please | ||
8 | refer to http://www.clipperz.com. | ||
9 | |||
10 | * Clipperz Community Edition is free software: you can redistribute | ||
11 | it and/or modify it under the terms of the GNU Affero General Public | ||
12 | License as published by the Free Software Foundation, either version | ||
13 | 3 of the License, or (at your option) any later version. | ||
14 | |||
15 | * Clipperz Community Edition is distributed in the hope that it will | ||
16 | be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
17 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | See the GNU Affero General Public License for more details. | ||
19 | |||
20 | * You should have received a copy of the GNU Affero General Public | ||
21 | License along with Clipperz Community Edition. If not, see | ||
22 | <http://www.gnu.org/licenses/>. | ||
23 | |||
24 | */ | ||
25 | |||
26 | if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||
27 | if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } | ||
28 | if (typeof(Clipperz.PM.PIN) == 'undefined') { Clipperz.PM.PIN = {}; } | ||
29 | |||
30 | MochiKit.Base.update(Clipperz.PM.PIN, { | ||
31 | |||
32 | //------------------------------------------------------------------------- | ||
33 | |||
34 | '__repr__': function () { | ||
35 | return "[" + this.NAME + " " + this.VERSION + "]"; | ||
36 | }, | ||
37 | |||
38 | //------------------------------------------------------------------------- | ||
39 | |||
40 | 'toString': function () { | ||
41 | return this.__repr__(); | ||
42 | }, | ||
43 | |||
44 | 'CREDENTIALS': 'CLIPPERZ.CREDENTIALS', | ||
45 | 'FAILURE_COUNT': 'CLIPPERZ.FAILED_LOGIN_COUNT', | ||
46 | 'ALLOWED_RETRY': 3, | ||
47 | |||
48 | //------------------------------------------------------------------------- | ||
49 | |||
50 | 'isSet': function () { | ||
51 | return (this.storedCredentials() != null); | ||
52 | }, | ||
53 | |||
54 | 'storedCredentials': function () { | ||
55 | return localStorage[this.CREDENTIALS]; | ||
56 | }, | ||
57 | |||
58 | //------------------------------------------------------------------------- | ||
59 | |||
60 | 'recordFailedAttempt': function () { | ||
61 | varfailureCount; | ||
62 | varresult; | ||
63 | |||
64 | failureCount = localStorage[this.FAILURE_COUNT]; | ||
65 | |||
66 | if (failureCount == null) { | ||
67 | failureCount = 0 | ||
68 | } | ||
69 | |||
70 | failureCount ++; | ||
71 | |||
72 | if (failureCount < this.ALLOWED_RETRY) { | ||
73 | localStorage[this.FAILURE_COUNT] = failureCount; | ||
74 | result = failureCount; | ||
75 | } else { | ||
76 | this.removeLocalCredentials(); | ||
77 | result = -1; | ||
78 | } | ||
79 | |||
80 | return result; | ||
81 | }, | ||
82 | |||
83 | 'resetFailedAttemptCount': function () { | ||
84 | localStorage.removeItem(this.FAILURE_COUNT); | ||
85 | }, | ||
86 | |||
87 | 'failureCount': function () { | ||
88 | return localStorage[this.FAILURE_COUNT]; | ||
89 | }, | ||
90 | |||
91 | //------------------------------------------------------------------------- | ||
92 | |||
93 | 'deriveKeyFromPin': function (aPIN) { | ||
94 | return Clipperz.Crypto.SHA.sha256(new Clipperz.ByteArray(aPIN)); | ||
95 | }, | ||
96 | |||
97 | 'credentialsWithPIN': function (aPIN) { | ||
98 | varbyteArrayValue; | ||
99 | var decryptedValue; | ||
100 | varresult; | ||
101 | |||
102 | byteArrayValue = (new Clipperz.ByteArray()).appendBase64String(localStorage[this.CREDENTIALS]); | ||
103 | decryptedValue = Clipperz.Crypto.AES.decrypt(this.deriveKeyFromPin(aPIN), byteArrayValue).asString(); | ||
104 | try { | ||
105 | result = Clipperz.Base.evalJSON(decryptedValue); | ||
106 | } catch (error) { | ||
107 | result = {'username':'fakeusername', 'passphrase':'fakepassphrase'}; | ||
108 | } | ||
109 | |||
110 | return result; | ||
111 | }, | ||
112 | |||
113 | 'setCredentialsWithPIN': function (aPIN, someCredentials) { | ||
114 | varencodedValue; | ||
115 | varbyteArrayValue; | ||
116 | var encryptedValue; | ||
117 | |||
118 | encodedValue = Clipperz.Base.serializeJSON(someCredentials); | ||
119 | byteArrayValue = new Clipperz.ByteArray(encodedValue); | ||
120 | encryptedValue = Clipperz.Crypto.AES.encrypt(this.deriveKeyFromPin(aPIN), byteArrayValue).toBase64String(); | ||
121 | |||
122 | localStorage[this.CREDENTIALS] = encryptedValue; | ||
123 | }, | ||
124 | |||
125 | 'removeLocalCredentials': function () { | ||
126 | localStorage.removeItem(this.CREDENTIALS); | ||
127 | localStorage.removeItem(this.FAILURE_COUNT); | ||
128 | }, | ||
129 | |||
130 | //------------------------------------------------------------------------- | ||
131 | __syntaxFix__: "syntax fix" | ||
132 | |||
133 | }); | ||
134 | |||
diff --git a/frontend/gamma/js/Clipperz/PM/Proxy/Proxy.OfflineCache.js b/frontend/gamma/js/Clipperz/PM/Proxy/Proxy.OfflineCache.js new file mode 100644 index 0000000..803c590 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/Proxy/Proxy.OfflineCache.js | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2011 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz Community Edition. | ||
6 | Clipperz Community Edition is an online password manager. | ||
7 | For further information about its features and functionalities please | ||
8 | refer to http://www.clipperz.com. | ||
9 | |||
10 | * Clipperz Community Edition is free software: you can redistribute | ||
11 | it and/or modify it under the terms of the GNU Affero General Public | ||
12 | License as published by the Free Software Foundation, either version | ||
13 | 3 of the License, or (at your option) any later version. | ||
14 | |||
15 | * Clipperz Community Edition is distributed in the hope that it will | ||
16 | be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
17 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | See the GNU Affero General Public License for more details. | ||
19 | |||
20 | * You should have received a copy of the GNU Affero General Public | ||
21 | License along with Clipperz Community Edition. If not, see | ||
22 | <http://www.gnu.org/licenses/>. | ||
23 | |||
24 | */ | ||
25 | |||
26 | if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||
27 | if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } | ||
28 | |||
29 | //============================================================================= | ||
30 | |||
31 | Clipperz.PM.Proxy.OfflineCache = function(args) { | ||
32 | args = args || {}; | ||
33 | |||
34 | Clipperz.PM.Proxy.Offline.superclass.constructor.call(this, args); | ||
35 | |||
36 | //this._dataStore = args.dataStore || new Clipperz.PM.Proxy.Offline.DataStore(args); | ||
37 | |||
38 | return this; | ||
39 | } | ||
40 | |||
41 | Clipperz.Base.extend(Clipperz.PM.Proxy.OfflineCache, Clipperz.PM.Proxy, { | ||
42 | |||
43 | 'toString': function () { | ||
44 | return "Clipperz.PM.Proxy.OfflineCache"; | ||
45 | }, | ||
46 | |||
47 | //------------------------------------------------------------------------- | ||
48 | |||
49 | //'dataStore': function () { | ||
50 | // return this._dataStore; | ||
51 | //}, | ||
52 | |||
53 | //------------------------------------------------------------------------- | ||
54 | |||
55 | 'sendMessage': function(aFunctionName, someParameters) { | ||
56 | throw Clipperz.Base.exception.MethodNotImplementedYet; | ||
57 | // return this.dataStore().processMessage(aFunctionName, someParameters); | ||
58 | }, | ||
59 | |||
60 | //------------------------------------------------------------------------- | ||
61 | |||
62 | __syntaxFix__: "syntax fix" | ||
63 | |||
64 | }); | ||
65 | |||
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Common/Components/BaseComponent.js b/frontend/gamma/js/Clipperz/PM/UI/Common/Components/BaseComponent.js index 2a03fdf..b9d7adf 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Common/Components/BaseComponent.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Common/Components/BaseComponent.js | |||
@@ -406,6 +406,10 @@ Clipperz.Base.extend(Clipperz.PM.UI.Common.Components.BaseComponent, /*Ext.Compo | |||
406 | return result; | 406 | return result; |
407 | }, | 407 | }, |
408 | 408 | ||
409 | 'getAnchor': function (aValue) { | ||
410 | return '#' + this.getId(aValue); | ||
411 | }, | ||
412 | |||
409 | //------------------------------------------------------------------------- | 413 | //------------------------------------------------------------------------- |
410 | 414 | ||
411 | 'getElement': function(aValue) { | 415 | 'getElement': function(aValue) { |
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Common/Components/Button.js b/frontend/gamma/js/Clipperz/PM/UI/Common/Components/Button.js index 716d851..1010c9d 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Common/Components/Button.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Common/Components/Button.js | |||
@@ -62,7 +62,8 @@ Clipperz.Base.extend(Clipperz.PM.UI.Common.Components.Button, Clipperz.PM.UI.Com | |||
62 | //------------------------------------------------------------------------- | 62 | //------------------------------------------------------------------------- |
63 | 63 | ||
64 | 'renderSelf': function () { | 64 | 'renderSelf': function () { |
65 | this.append(this.element(), {tag:'div', id:this.getId('wrapper'), cls:'button_wrapper', children:[ | 65 | /* |
66 | this.append(this.element(), {tag:'div', id:this.getId('button'), cls:'button_wrapper', children:[ | ||
66 | {tag:'div', id:this.getId('bodyWrapper'), cls:'button_bodyWrapper', children:[ | 67 | {tag:'div', id:this.getId('bodyWrapper'), cls:'button_bodyWrapper', children:[ |
67 | {tag:'div', id:this.getId('body'), cls:'button_body', children:[ | 68 | {tag:'div', id:this.getId('body'), cls:'button_body', children:[ |
68 | {tag:'span', html:this.text()} | 69 | {tag:'span', html:this.text()} |
@@ -70,32 +71,39 @@ Clipperz.Base.extend(Clipperz.PM.UI.Common.Components.Button, Clipperz.PM.UI.Com | |||
70 | {tag:'div', id:this.getId('footer'), cls:'button_footer'} | 71 | {tag:'div', id:this.getId('footer'), cls:'button_footer'} |
71 | ]} | 72 | ]} |
72 | ]}); | 73 | ]}); |
74 | */ | ||
75 | /* | ||
76 | this.append(this.element(), {tag:'div', id:this.getId('button'), cls:'button', children:[ | ||
77 | {tag:'span', html:this.text()} | ||
78 | ]}); | ||
79 | */ | ||
80 | this.append(this.element(), {tag:'a', id:this.getId('button'), cls:'button', html:this.text()}); | ||
73 | 81 | ||
74 | if (this.isDefault()) { | 82 | if (this.isDefault()) { |
75 | MochiKit.DOM.addElementClass(this.getId('wrapper'), 'default'); | 83 | MochiKit.DOM.addElementClass(this.getId('button'), 'default'); |
76 | } | 84 | } |
77 | 85 | ||
78 | MochiKit.Signal.connect(this.getId('wrapper'), 'onmouseenter',this, 'handleOnMouseEnter'); | 86 | // MochiKit.Signal.connect(this.getId('button'), 'onmouseenter',this, 'handleOnMouseEnter'); |
79 | MochiKit.Signal.connect(this.getId('wrapper'), 'onmouseleave',this, 'handleOnMouseLeave'); | 87 | // MochiKit.Signal.connect(this.getId('button'), 'onmouseleave',this, 'handleOnMouseLeave'); |
80 | MochiKit.Signal.connect(this.getId('wrapper'), 'onmousedown',this, 'handleOnMouseDown'); | 88 | // MochiKit.Signal.connect(this.getId('button'), 'onmousedown',this, 'handleOnMouseDown'); |
81 | MochiKit.Signal.connect(this.getId('wrapper'), 'onclick', this, 'handleOnClick'); | 89 | MochiKit.Signal.connect(this.getId('button'), 'onclick', this, 'handleOnClick'); |
82 | }, | 90 | }, |
83 | 91 | ||
84 | //------------------------------------------------------------------------- | 92 | //------------------------------------------------------------------------- |
85 | 93 | /* | |
86 | 'handleOnMouseEnter': function (anEvent) { | 94 | 'handleOnMouseEnter': function (anEvent) { |
87 | MochiKit.DOM.addElementClass(this.getId('wrapper'), 'hover'); | 95 | MochiKit.DOM.addElementClass(this.getId('button'), 'hover'); |
88 | }, | 96 | }, |
89 | 97 | ||
90 | 'handleOnMouseLeave': function (anEvent) { | 98 | 'handleOnMouseLeave': function (anEvent) { |
91 | MochiKit.DOM.removeElementClass(this.getId('wrapper'), 'hover'); | 99 | MochiKit.DOM.removeElementClass(this.getId('button'), 'hover'); |
92 | MochiKit.DOM.removeElementClass(this.getId('wrapper'), 'clicked'); | 100 | MochiKit.DOM.removeElementClass(this.getId('button'), 'clicked'); |
93 | }, | 101 | }, |
94 | 102 | ||
95 | 'handleOnMouseDown': function (anEvent) { | 103 | 'handleOnMouseDown': function (anEvent) { |
96 | MochiKit.DOM.addElementClass(this.getId('wrapper'), 'clicked'); | 104 | MochiKit.DOM.addElementClass(this.getId('button'), 'clicked'); |
97 | }, | 105 | }, |
98 | 106 | */ | |
99 | 'handleOnClick': function (anEvent) { | 107 | 'handleOnClick': function (anEvent) { |
100 | MochiKit.Signal.signal(this, 'onclick', anEvent); | 108 | MochiKit.Signal.signal(this, 'onclick', anEvent); |
101 | }, | 109 | }, |
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Common/Components/SimpleMessagePanel.js b/frontend/gamma/js/Clipperz/PM/UI/Common/Components/SimpleMessagePanel.js index 1992154..1d816a9 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Common/Components/SimpleMessagePanel.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Common/Components/SimpleMessagePanel.js | |||
@@ -98,14 +98,29 @@ Clipperz.Base.extend(Clipperz.PM.UI.Common.Components.SimpleMessagePanel, Clippe | |||
98 | }, | 98 | }, |
99 | 99 | ||
100 | 'setType': function (aValue) { | 100 | 'setType': function (aValue) { |
101 | if (this.getElement('icon') != null) { | 101 | // if (this.getElement('icon') != null) { |
102 | MochiKit.DOM.removeElementClass(this.getId('icon'), this._type); | 102 | // MochiKit.DOM.removeElementClass(this.getId('icon'), this._type); |
103 | MochiKit.DOM.addElementClass(this.getId('icon'), aValue); | 103 | // MochiKit.DOM.addElementClass(this.getId('icon'), aValue); |
104 | } | 104 | // } |
105 | 105 | ||
106 | this._type = aValue; | 106 | this._type = aValue; |
107 | }, | 107 | }, |
108 | 108 | ||
109 | 'icon': function () { | ||
110 | var type = this.type(); | ||
111 | var result; | ||
112 | |||
113 | if (type == 'ALERT') { | ||
114 | result = '!'; | ||
115 | } else if (type == 'INFO') { | ||
116 | result = 'i'; | ||
117 | } else if (type == 'ERROR') { | ||
118 | result = '!'; | ||
119 | } | ||
120 | |||
121 | return result; | ||
122 | }, | ||
123 | |||
109 | //------------------------------------------------------------------------- | 124 | //------------------------------------------------------------------------- |
110 | 125 | ||
111 | 'buttons': function () { | 126 | 'buttons': function () { |
@@ -132,17 +147,20 @@ Clipperz.Base.extend(Clipperz.PM.UI.Common.Components.SimpleMessagePanel, Clippe | |||
132 | 147 | ||
133 | 'renderSelf': function() { | 148 | 'renderSelf': function() { |
134 | this.append(this.element(), {tag:'div', cls:'SimpleMessagePanel', id:this.getId('panel'), children: [ | 149 | this.append(this.element(), {tag:'div', cls:'SimpleMessagePanel', id:this.getId('panel'), children: [ |
135 | {tag:'div', cls:'header', children:[]}, | 150 | // {tag:'div', cls:'header', children:[]}, |
136 | {tag:'div', cls:'body', children:[ | 151 | {tag:'div', cls:'body', children:[ |
137 | {tag:'div', id:this.getId('icon'),cls:'img ' + this.type(), children:[{tag:'div'}]}, | 152 | // {tag:'div', id:this.getId('icon'),cls:'img ' + this.type(), children:[{tag:'div'}]}, |
153 | {tag:'div', /*id:this.getId('icon'),*/cls:'img ' + this.type(), children:[{tag:'canvas', id:this.getId('icon')}]}, | ||
138 | {tag:'h3', id:this.getId('title'),html:this.title()}, | 154 | {tag:'h3', id:this.getId('title'),html:this.title()}, |
139 | {tag:'p', id:this.getId('text'),html:this.text()}, | 155 | {tag:'p', id:this.getId('text'),html:this.text()}, |
140 | {tag:'div', id:this.getId('container')}, | 156 | {tag:'div', id:this.getId('container')}, |
141 | {tag:'div', id:this.getId('buttonArea'), cls:'buttonArea', children:[]} | 157 | {tag:'div', id:this.getId('buttonArea'), cls:'buttonArea', children:[]} |
142 | ]}, | 158 | ]} |
143 | {tag:'div', cls:'footer', children:[]} | 159 | // {tag:'div', cls:'footer', children:[]} |
144 | ]}); | 160 | ]}); |
145 | 161 | ||
162 | Clipperz.PM.UI.Canvas.marks[this.icon()](this.getElement('icon'), "#ffffff"); | ||
163 | |||
146 | MochiKit.Signal.connect(this.getId('panel'), 'onkeydown', this, 'keyDownHandler'); | 164 | MochiKit.Signal.connect(this.getId('panel'), 'onkeydown', this, 'keyDownHandler'); |
147 | 165 | ||
148 | this.renderButtons(); | 166 | this.renderButtons(); |
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardDetail.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardDetail.js new file mode 100644 index 0000000..32dfa63 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardDetail.js | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2011 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz Community Edition. | ||
6 | Clipperz Community Edition is an online password manager. | ||
7 | For further information about its features and functionalities please | ||
8 | refer to http://www.clipperz.com. | ||
9 | |||
10 | * Clipperz Community Edition is free software: you can redistribute | ||
11 | it and/or modify it under the terms of the GNU Affero General Public | ||
12 | License as published by the Free Software Foundation, either version | ||
13 | 3 of the License, or (at your option) any later version. | ||
14 | |||
15 | * Clipperz Community Edition is distributed in the hope that it will | ||
16 | be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
17 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | See the GNU Affero General Public License for more details. | ||
19 | |||
20 | * You should have received a copy of the GNU Affero General Public | ||
21 | License along with Clipperz Community Edition. If not, see | ||
22 | <http://www.gnu.org/licenses/>. | ||
23 | |||
24 | */ | ||
25 | |||
26 | Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components'); | ||
27 | |||
28 | Clipperz.PM.UI.Mobile.Components.CardDetail = function(args) { | ||
29 | args = args || {}; | ||
30 | |||
31 | Clipperz.PM.UI.Mobile.Components.CardDetail.superclass.constructor.apply(this, arguments); | ||
32 | |||
33 | //this._cardReference = null; | ||
34 | |||
35 | return this; | ||
36 | } | ||
37 | |||
38 | //============================================================================= | ||
39 | |||
40 | Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.CardDetail, Clipperz.PM.UI.Common.Components.BaseComponent, { | ||
41 | |||
42 | //------------------------------------------------------------------------- | ||
43 | |||
44 | 'toString': function () { | ||
45 | return "Clipperz.PM.UI.Mobile.Components.CardDetail component"; | ||
46 | }, | ||
47 | |||
48 | //------------------------------------------------------------------------- | ||
49 | /* | ||
50 | 'cardReference': function () { | ||
51 | return this._cardReference; | ||
52 | }, | ||
53 | |||
54 | 'setCardReference': function (aValue) { | ||
55 | this._cardReference = aValue; | ||
56 | }, | ||
57 | */ | ||
58 | //------------------------------------------------------------------------- | ||
59 | |||
60 | 'renderSelf': function () { | ||
61 | console.log("CardDetail.renderSelf"); | ||
62 | this.append(this.element(), {tag:'div', cls:'cardDetail', children:[ | ||
63 | {tag:'div', cls:'toolbar', children:[ | ||
64 | {tag:'a', href:'#', cls:'back', html:"List"}, | ||
65 | {tag:'h1', id:this.getId('cardTitle'), html:"…"} | ||
66 | ]}, | ||
67 | {tag:'div', cls:'scroll', id:this.getId('cardDetails'), children:[ | ||
68 | ]} | ||
69 | ]}); | ||
70 | }, | ||
71 | /* | ||
72 | 'renderSelf': function() { | ||
73 | this.append(this.element(), [ | ||
74 | {tag:'div', cls:'cardDetail', id:this.getId('cardDetail'), children:[ | ||
75 | {tag:'div', id:this.getId('progressBar')} //, | ||
76 | ]} | ||
77 | ]); | ||
78 | |||
79 | this.addComponent(new Clipperz.PM.UI.Common.Components.ProgressBar({'element':this.getElement('progressBar')})); | ||
80 | MochiKit.Signal.signal(Clipperz.PM.UI.Common.Controllers.ProgressBarController.defaultController, 'updateProgress', 0); | ||
81 | }, | ||
82 | */ | ||
83 | |||
84 | 'setTitle': function (aValue) { | ||
85 | this.getElement('cardTitle').innerHTML = aValue; | ||
86 | }, | ||
87 | |||
88 | 'fieldListElement': function () { | ||
89 | varresult; | ||
90 | |||
91 | result = this.getElement('fieldList'); | ||
92 | if (result == null) { | ||
93 | result = this.append(this.getElement('cardDetails'), {tag:'ul', cls:'rounded', id:this.getId('fieldList')}); | ||
94 | } | ||
95 | |||
96 | return result; | ||
97 | }, | ||
98 | |||
99 | 'renderFieldValues': function (someFieldValues) { | ||
100 | varfieldClass; | ||
101 | |||
102 | if ((someFieldValues['actionType'] != 'NONE') || (someFieldValues['label'] != '') && (someFieldValues['value'] != '')) { | ||
103 | if (someFieldValues['isHidden'] == true) { | ||
104 | fieldClass = 'password'; | ||
105 | } else { | ||
106 | fieldClass = ''; | ||
107 | } | ||
108 | |||
109 | this.append(this.fieldListElement(), {tag:'li', cls:'cardField', children:[ | ||
110 | {tag:'a', href:'#', cls:fieldClass, html:someFieldValues['value'], children:[ | ||
111 | {tag:'small', cls:'label', html:someFieldValues['label']} | ||
112 | ]} | ||
113 | ]}) | ||
114 | } | ||
115 | }, | ||
116 | |||
117 | 'addField': function (aField) { | ||
118 | var deferredResult; | ||
119 | varfieldValues; | ||
120 | |||
121 | fieldValues = {}; | ||
122 | deferredResult = new Clipperz.Async.Deferred("CardDetail.addField", {trace:false}); | ||
123 | deferredResult.addMethod(aField, 'label'); | ||
124 | deferredResult.addCallback(function (aValue) { fieldValues['label'] = aValue; }); | ||
125 | deferredResult.addMethod(aField, 'value'); | ||
126 | deferredResult.addCallback(function (aValue) { fieldValues['value'] = aValue; }); | ||
127 | deferredResult.addMethod(aField, 'actionType'); | ||
128 | deferredResult.addCallback(function (aValue) { fieldValues['actionType'] = aValue; }); | ||
129 | deferredResult.addMethod(aField, 'isHidden'); | ||
130 | deferredResult.addCallback(function (aValue) { fieldValues['isHidden'] = aValue; }); | ||
131 | deferredResult.addMethod(this, 'renderFieldValues', fieldValues); | ||
132 | deferredResult.callback(); | ||
133 | |||
134 | return deferredResult; | ||
135 | }, | ||
136 | |||
137 | //------------------------------------------------------------------------- | ||
138 | |||
139 | 'directLoginElement': function () { | ||
140 | varresult; | ||
141 | |||
142 | result = this.getElement('directLoginList'); | ||
143 | if (result == null) { | ||
144 | this.append(this.getElement('cardDetails'), {tag:'h2', html:"Direct login"}); | ||
145 | result = this.append(this.getElement('cardDetails'), {tag:'ul', cls:'rounded', id:this.getId('directLoginList')}); | ||
146 | } | ||
147 | |||
148 | return result; | ||
149 | }, | ||
150 | |||
151 | 'addDirectLogin': function (aDirectLogin) { | ||
152 | this.append(this.directLoginElement(), {tag:'li', cls:'directLogin forward', children:[ | ||
153 | {tag:'a', href:'#', html:"direct login", children:[ | ||
154 | {tag:'small', cls:'favicon', children:[{tag:'img', cls:'favicon', src:'http://www.clipperz.com/favicon.ico'}]} | ||
155 | ]} | ||
156 | ]}) | ||
157 | |||
158 | console.log("ADD DIRECT LOGIN", aDirectLogin); | ||
159 | }, | ||
160 | |||
161 | //========================================================================= | ||
162 | |||
163 | 'showCard': function (aCard) { | ||
164 | var deferredResult; | ||
165 | |||
166 | // this.render(); | ||
167 | |||
168 | console.log("CardDetail.showCard", aCard); | ||
169 | deferredResult = new Clipperz.Async.Deferred("CardDetail.showCard", {trace:false}); | ||
170 | deferredResult.addMethod(aCard, 'label'); | ||
171 | deferredResult.addMethod(this, 'setTitle'); | ||
172 | |||
173 | deferredResult.addMethod(aCard, 'fields'); | ||
174 | deferredResult.addCallback(MochiKit.Base.values); | ||
175 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'addField')); | ||
176 | |||
177 | deferredResult.addMethod(aCard, 'directLogins'); | ||
178 | deferredResult.addCallback(MochiKit.Base.values); | ||
179 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'addDirectLogin')); | ||
180 | |||
181 | |||
182 | deferredResult.callback(); | ||
183 | |||
184 | return deferredResult; | ||
185 | // return Clipperz.Async.callbacks("CardDialogController.updateComponentState", [ | ||
186 | // MochiKit.Base.method(this.record(), 'hasPendingChanges'), | ||
187 | // MochiKit.Base.method(this.cardDialogComponent(), 'setShouldEnableSaving'), | ||
188 | // | ||
189 | // MochiKit.Base.method(this.record(), 'label'), | ||
190 | // MochiKit.Base.method(this.cardDialogComponent(), 'setTitle'), | ||
191 | // MochiKit.Base.method(this.record(), 'notes'), | ||
192 | // MochiKit.Base.method(this.cardDialogComponent(), 'setNotes'), | ||
193 | // | ||
194 | // MochiKit.Base.method(this.record(), 'fields'), | ||
195 | // MochiKit.Base.values, | ||
196 | // MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'addCardDialogComponentWithField')), | ||
197 | // | ||
198 | // MochiKit.Base.method(this.record(), 'directLogins'), | ||
199 | // MochiKit.Base.values, | ||
200 | // MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.method(this, 'addCardDialogComponentWithDirectLogin')), | ||
201 | // | ||
202 | // MochiKit.Base.method(this.cardDialogComponent(), 'resetNewFieldInputs'), | ||
203 | // MochiKit.Base.noop | ||
204 | // ], {trace:false}); | ||
205 | |||
206 | }, | ||
207 | |||
208 | //========================================================================= | ||
209 | |||
210 | 'showCardDetails': function (someData) { | ||
211 | this.element().innerHTML = ''; | ||
212 | this.append(this.element(), [ | ||
213 | {tag:'fieldset', id:this.getId('fields'), children:MochiKit.Base.map(function (aFieldData) { | ||
214 | return {tag:'div', cls:'row', children:[ | ||
215 | {tag:'label', html:aFieldData['label']}, | ||
216 | // {tag:'span', cls:('fieldValue ' + (aFieldData['isHidden']? 'password' : 'text')), html:aFieldData['value']} | ||
217 | {tag:'div', cls:('fieldValue ' + (aFieldData['isHidden']? 'password' : 'text')), children:[ | ||
218 | {tag:'div', children:[{tag:'p', html:aFieldData['value']}]} | ||
219 | ]} | ||
220 | // {tag:'input', type:'text', cls:('fieldValue ' + (aFieldData['isHidden']? 'password' : 'text')), value:aFieldData['value'], disabled:true} | ||
221 | |||
222 | ]} | ||
223 | }, someData['fields'])} | ||
224 | ]); | ||
225 | |||
226 | MochiKit.Iter.forEach(MochiKit.Selector.findChildElements(this.element(), ['span.password']), MochiKit.Base.bind(function (aPasswordElement) { | ||
227 | MochiKit.Signal.connect(aPasswordElement, 'onclick', function (anEvent) { alert(MochiKit.DOM.scrapeText(anEvent.src())); }) | ||
228 | }, this)); | ||
229 | |||
230 | if (someData['directLogins'].length > 0) { | ||
231 | this.append(this.element(), [ | ||
232 | {tag:'h2', html:"Direct logins"}, | ||
233 | {tag:'fieldset', id:this.getId('directLogins'), children:MochiKit.Base.map(function (aDirectLoginData) { | ||
234 | return {tag:'div', cls:'row', id:('directLogin_' + aDirectLoginData['_reference']), children:[ | ||
235 | {tag:'img', cls:'favicon', src:aDirectLoginData['favicon']}, | ||
236 | // {tag:'input', cls:'directLogin', disabled:'disabled', type:'text', name:aDirectLoginData['label'], value:aDirectLoginData['label']} | ||
237 | {tag:'span', cls:'directLogin', html:aDirectLoginData['label']} | ||
238 | ]} | ||
239 | }, someData['directLogins'])} | ||
240 | ]); | ||
241 | |||
242 | MochiKit.Base.map(MochiKit.Base.bind(function (aRowNode) { | ||
243 | MochiKit.Signal.connect(aRowNode, 'onclick', this, 'directLoginClickHandler'); | ||
244 | }, this), | ||
245 | MochiKit.Selector.findChildElements(this.getElement('directLogins'), ['div.row']) | ||
246 | ) | ||
247 | }; | ||
248 | |||
249 | if (someData['notes'] != '') { | ||
250 | this.append(this.element(), [ | ||
251 | {tag:'h2', html:"Notes"}, | ||
252 | {tag:'fieldset', id:this.getId('fieldset'), children:[ | ||
253 | {tag:'div', cls:'row notes', children:[ | ||
254 | {tag:'span', html:someData['notes']} | ||
255 | ]} | ||
256 | ]} | ||
257 | ]); | ||
258 | }; | ||
259 | |||
260 | return true; | ||
261 | }, | ||
262 | |||
263 | //------------------------------------------------------------------------- | ||
264 | /* | ||
265 | 'toggleClickHandler': function (anEvent) { | ||
266 | varnextState; | ||
267 | varfieldValue; | ||
268 | |||
269 | //console.log("TOGGLE"); | ||
270 | anEvent.preventDefault; | ||
271 | fieldValue = MochiKit.Selector.findChildElements(anEvent.src().parentNode.parentNode, ['span.password'])[0]; | ||
272 | |||
273 | nextState = (MochiKit.DOM.getNodeAttribute(anEvent.src(), 'toggled') != 'true'); | ||
274 | if (nextState) { | ||
275 | MochiKit.DOM.removeElementClass(fieldValue, 'clear'); | ||
276 | } else { | ||
277 | MochiKit.DOM.addElementClass(fieldValue, 'clear'); | ||
278 | } | ||
279 | |||
280 | MochiKit.DOM.setNodeAttribute(anEvent.src(), 'toggled', nextState); | ||
281 | }, | ||
282 | * / | ||
283 | //========================================================================= | ||
284 | /* | ||
285 | 'directLoginClickHandler': function (anEvent) { | ||
286 | anEvent.preventDefault(); | ||
287 | |||
288 | if (/(directLogin_)/.test(anEvent.src().id)) { | ||
289 | var directLoginReference; | ||
290 | |||
291 | directLoginReference = anEvent.src().id.match(/(directLogin_)(.*)/)[2]; | ||
292 | MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'selectedDirectLogin', {cardReference:this.cardReference(), directLoginReference:directLoginReference}); | ||
293 | } | ||
294 | }, | ||
295 | */ | ||
296 | //========================================================================= | ||
297 | |||
298 | __syntaxFix__: "syntax fix" | ||
299 | }); | ||
diff --git a/frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/CardList.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardList.js index c3f2701..a4aa212 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/CardList.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardList.js | |||
@@ -23,12 +23,12 @@ refer to http://www.clipperz.com. | |||
23 | 23 | ||
24 | */ | 24 | */ |
25 | 25 | ||
26 | Clipperz.Base.module('Clipperz.PM.UI.iPhone.Components'); | 26 | Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components'); |
27 | 27 | ||
28 | Clipperz.PM.UI.iPhone.Components.CardList = function(args) { | 28 | Clipperz.PM.UI.Mobile.Components.CardList = function(args) { |
29 | args = args || {}; | 29 | args = args || {}; |
30 | 30 | ||
31 | Clipperz.PM.UI.iPhone.Components.CardList.superclass.constructor.apply(this, arguments); | 31 | Clipperz.PM.UI.Mobile.Components.CardList.superclass.constructor.apply(this, arguments); |
32 | 32 | ||
33 | this._cardDetail = null; | 33 | this._cardDetail = null; |
34 | 34 | ||
@@ -37,44 +37,97 @@ Clipperz.PM.UI.iPhone.Components.CardList = function(args) { | |||
37 | 37 | ||
38 | //============================================================================= | 38 | //============================================================================= |
39 | 39 | ||
40 | Clipperz.Base.extend(Clipperz.PM.UI.iPhone.Components.CardList, Clipperz.PM.UI.Common.Components.BaseComponent, { | 40 | Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.CardList, Clipperz.PM.UI.Common.Components.BaseComponent, { |
41 | 41 | ||
42 | //------------------------------------------------------------------------- | 42 | //------------------------------------------------------------------------- |
43 | 43 | ||
44 | 'toString': function () { | 44 | 'toString': function () { |
45 | return "Clipperz.PM.UI.iPhone.Components.CardList component"; | 45 | return "Clipperz.PM.UI.Mobile.Components.CardList component"; |
46 | }, | 46 | }, |
47 | 47 | ||
48 | //------------------------------------------------------------------------- | 48 | //------------------------------------------------------------------------- |
49 | 49 | ||
50 | 'renderSelf': function(/*aContainer, aPosition*/) { | 50 | 'renderSelf': function () { |
51 | this.append(this.element(), [ | 51 | this.append(this.element(), {tag:'div', cls:'cardList', children:[ |
52 | {tag:'div', cls:'toolbar', id:'toolbar', children:[ | 52 | {tag:'div', cls:'toolbar', children:[ |
53 | {tag:'h1', id:'pageTitle', html:"cards"}, | 53 | {tag:'h1', html:"clipperz"}, |
54 | {tag:'a', id:'backButton', cls:'button', href:'#', html:"cards"} | 54 | // {tag:'input', name:'search', type:'search', autocomplete:'off', placeholder:"search", id:this.getId('search')}, |
55 | {tag:'a', href:'#', id:'settings', cls:'button', html:"*"} | ||
55 | ]}, | 56 | ]}, |
56 | {tag:'div', cls:'cardList', id:this.getId('cardList'), children:[ | 57 | {tag:'div', cls:'scroll', id:this.getId('listBox'), children:[ |
57 | {tag:'form', title:'search', cls:'panel cardListSearchForm', id:this.getId('cardListSearchForm'), children:[ | 58 | {tag:'ul', cls:'rounded', id:this.getId('list'), children:[ |
58 | {tag:'input', type:'search', name:'search', value:"", placeholder:"search", id:this.getId('searchField')} | 59 | {tag:'li', html:'loading'} |
59 | ]}, | 60 | ]} |
60 | {tag:'ul', cls:'panel cardListPanel', id:this.getId('cardListPanel'), children:[]} | 61 | ]} |
61 | ]}, | 62 | ]}); |
62 | {tag:'div', cls:'panel cardDetailPanel', id:this.getId('cardDetail')} | 63 | |
63 | ]); | 64 | MochiKit.Signal.connect(this.getElement('list'), 'onclick', this, 'cardSelectionHandler'); |
65 | MochiKit.Signal.connect(this.getElement('list'), 'ontouchstart',this, 'cardSelectionHandler'); | ||
66 | // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onsubmit', this,'searchHandler'); | ||
67 | // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeydown', this,'searchHandler'); | ||
68 | // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeyup', this,'searchHandler'); | ||
69 | |||
70 | // MochiKit.Signal.connect(this.getElement('cardListPanel'), 'onclick', this,'cardListClickHandler'); | ||
71 | // MochiKit.Signal.connect('backButton', 'onclick', this,'backButtonClickHandler'); | ||
72 | |||
73 | // MochiKit.Style.hideElement('backButton'); | ||
74 | // MochiKit.Style.hideElement(this.getElement('cardDetail')); | ||
75 | }, | ||
64 | 76 | ||
65 | MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onsubmit', this,'searchHandler'); | 77 | 'showCards': function (someCards) { |
66 | MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeydown', this,'searchHandler'); | 78 | varcardListElement; |
67 | MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeyup', this,'searchHandler'); | 79 | if (this.isFullyRendered() == false) { |
80 | this.render(); | ||
81 | }; | ||
82 | |||
83 | cardListElement = this.getElement('list') | ||
84 | |||
85 | cardInfo = { | ||
86 | '_rowObject': MochiKit.Async.succeed, | ||
87 | '_reference': MochiKit.Base.methodcaller('reference'), | ||
88 | '_searchableContent':MochiKit.Base.methodcaller('searchableContent'), | ||
89 | 'label': MochiKit.Base.methodcaller('label'), | ||
90 | 'favicon': MochiKit.Base.methodcaller('favicon') | ||
91 | }; | ||
92 | |||
93 | //console.log("someCards", someCards); | ||
94 | deferredResult = new Clipperz.Async.Deferred("CardList.showCards", {trace:false}); | ||
95 | deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("CardList.value - collectResults", cardInfo, {trace:false})); | ||
96 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
97 | deferredResult.addCallback(MochiKit.Base.methodcaller('sort', Clipperz.Base.caseInsensitiveKeyComparator('label'))); | ||
98 | deferredResult.addCallbackPass(MochiKit.DOM.replaceChildNodes, cardListElement); | ||
99 | // deferredResult.addCallbackPass(MochiKit.DOM.removeElementClass, cardListElement, 'loading'); | ||
100 | deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'appendCardToList', cardListElement)); | ||
101 | deferredResult.callback(someCards); | ||
102 | }, | ||
68 | 103 | ||
69 | MochiKit.Signal.connect(this.getElement('cardListPanel'), 'onclick', this,'cardListClickHandler'); | 104 | 'appendCardToList': function (aCardListElement, aCardInfo) { |
70 | MochiKit.Signal.connect('backButton', 'onclick', this,'backButtonClickHandler'); | 105 | //console.log("appendCardToList", aCardInfo); |
106 | this.append(aCardListElement, {tag:'li', cls:'cardListItem arrow', cardreference:aCardInfo['_reference'], children:[ | ||
107 | {tag:'a', href:'#', html:aCardInfo['label'], children:[ | ||
108 | {tag:'small', cls:'favicon', children:[{tag:'img', cls:'favicon', src:aCardInfo['favicon']}]} | ||
109 | ]} | ||
110 | ]}); | ||
111 | }, | ||
112 | |||
113 | 'cardSelectionHandler': function (anEvent) { | ||
114 | var listElement; | ||
115 | varcardReference; | ||
71 | 116 | ||
72 | MochiKit.Style.hideElement('backButton'); | 117 | anEvent.preventDefault(); |
73 | MochiKit.Style.hideElement(this.getElement('cardDetail')); | 118 | |
119 | listElement = anEvent.target(); | ||
120 | if (MochiKit.DOM.getNodeAttribute(listElement, 'cardreference') == null) { | ||
121 | listElement = MochiKit.DOM.getFirstParentByTagAndClassName(anEvent.target(), tagName='li', className='cardListItem'); | ||
122 | } | ||
123 | cardReference = MochiKit.DOM.getNodeAttribute(listElement, 'cardreference'); | ||
124 | console.log("###", listElement, cardReference); | ||
125 | //TODO: Notify card with reference MochiKit.DOM.getNodeAttribute(listElement, 'cardreference') has been selected | ||
126 | MochiKit.Signal.signal(this, 'selectedCard', cardReference); | ||
74 | }, | 127 | }, |
75 | 128 | ||
76 | //------------------------------------------------------------------------- | 129 | //------------------------------------------------------------------------- |
77 | 130 | /* | |
78 | 'searchHandler': function (anEvent) { | 131 | 'searchHandler': function (anEvent) { |
79 | if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ENTER')) { //RETURN | 132 | if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ENTER')) { //RETURN |
80 | anEvent.preventDefault(); | 133 | anEvent.preventDefault(); |
@@ -127,7 +180,7 @@ Clipperz.Base.extend(Clipperz.PM.UI.iPhone.Components.CardList, Clipperz.PM.UI.C | |||
127 | 180 | ||
128 | 'cardDetail': function (someData) { | 181 | 'cardDetail': function (someData) { |
129 | if (this._cardDetail == null) { | 182 | if (this._cardDetail == null) { |
130 | this._cardDetail = new Clipperz.PM.UI.iPhone.Components.CardDetail({element:this.getElement('cardDetail')}); | 183 | this._cardDetail = new Clipperz.PM.UI.Mobile.Components.CardDetail({element:this.getElement('cardDetail')}); |
131 | } | 184 | } |
132 | 185 | ||
133 | return this._cardDetail; | 186 | return this._cardDetail; |
@@ -195,7 +248,7 @@ Clipperz.Base.extend(Clipperz.PM.UI.iPhone.Components.CardList, Clipperz.PM.UI.C | |||
195 | ], {duration:1, afterFinish:MochiKit.Base.method(this, 'removeCardDetail')}) | 248 | ], {duration:1, afterFinish:MochiKit.Base.method(this, 'removeCardDetail')}) |
196 | 249 | ||
197 | }, | 250 | }, |
198 | 251 | */ | |
199 | //========================================================================= | 252 | //========================================================================= |
200 | __syntaxFix__: "syntax fix" | 253 | __syntaxFix__: "syntax fix" |
201 | }); | 254 | }); |
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/LoginForm.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/LoginForm.js new file mode 100644 index 0000000..eafcdbc --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/LoginForm.js | |||
@@ -0,0 +1,356 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2011 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz Community Edition. | ||
6 | Clipperz Community Edition is an online password manager. | ||
7 | For further information about its features and functionalities please | ||
8 | refer to http://www.clipperz.com. | ||
9 | |||
10 | * Clipperz Community Edition is free software: you can redistribute | ||
11 | it and/or modify it under the terms of the GNU Affero General Public | ||
12 | License as published by the Free Software Foundation, either version | ||
13 | 3 of the License, or (at your option) any later version. | ||
14 | |||
15 | * Clipperz Community Edition is distributed in the hope that it will | ||
16 | be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
17 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | See the GNU Affero General Public License for more details. | ||
19 | |||
20 | * You should have received a copy of the GNU Affero General Public | ||
21 | License along with Clipperz Community Edition. If not, see | ||
22 | <http://www.gnu.org/licenses/>. | ||
23 | |||
24 | */ | ||
25 | |||
26 | Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components'); | ||
27 | |||
28 | Clipperz.PM.UI.Mobile.Components.LoginForm = function(args) { | ||
29 | args = args || {}; | ||
30 | |||
31 | this._pin = ''; | ||
32 | |||
33 | this._message = null; | ||
34 | this._steps = 0; | ||
35 | this._actualSteps = 0; | ||
36 | |||
37 | this._callback = null; | ||
38 | this._errorCallback = null; | ||
39 | |||
40 | this._mode = 'CREDENTIALS'; | ||
41 | |||
42 | Clipperz.PM.UI.Mobile.Components.LoginForm.superclass.constructor.apply(this, arguments); | ||
43 | |||
44 | return this; | ||
45 | } | ||
46 | |||
47 | //============================================================================= | ||
48 | |||
49 | Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.LoginForm, Clipperz.PM.UI.Common.Components.BaseComponent, { | ||
50 | |||
51 | //------------------------------------------------------------------------- | ||
52 | |||
53 | 'toString': function () { | ||
54 | return "Clipperz.PM.UI.Mobile.Components.LoginForm component"; | ||
55 | }, | ||
56 | |||
57 | //------------------------------------------------------------------------- | ||
58 | |||
59 | 'callback': function () { | ||
60 | return this._callback; | ||
61 | }, | ||
62 | |||
63 | 'errorCallback': function () { | ||
64 | return this._errorCallback; | ||
65 | }, | ||
66 | |||
67 | //------------------------------------------------------------------------- | ||
68 | |||
69 | 'mode': function () { | ||
70 | return this._mode; | ||
71 | }, | ||
72 | |||
73 | 'setMode': function (aValue) { | ||
74 | this._mode = aValue; | ||
75 | }, | ||
76 | |||
77 | //.......................................................................... | ||
78 | |||
79 | 'pin': function () { | ||
80 | return this._pin; | ||
81 | }, | ||
82 | |||
83 | 'setPin': function (aValue) { | ||
84 | this._pin = aValue; | ||
85 | }, | ||
86 | |||
87 | //.......................................................................... | ||
88 | |||
89 | 'username': function () { | ||
90 | return this._username; | ||
91 | }, | ||
92 | |||
93 | 'setUsername': function (aValue) { | ||
94 | this._username = aValue; | ||
95 | }, | ||
96 | |||
97 | //.......................................................................... | ||
98 | |||
99 | 'passphrase': function () { | ||
100 | return this._passphrase; | ||
101 | }, | ||
102 | |||
103 | 'setPassphrase': function (aValue) { | ||
104 | this._passphrase = aValue; | ||
105 | }, | ||
106 | |||
107 | //------------------------------------------------------------------------- | ||
108 | |||
109 | 'message': function () { | ||
110 | return this._message; | ||
111 | }, | ||
112 | |||
113 | '_setMessage': function (aValue) { | ||
114 | this._message = aValue; | ||
115 | |||
116 | if (aValue == null) { | ||
117 | MochiKit.Style.hideElement(this.getElement('credentialsMessage')); | ||
118 | } else { | ||
119 | this.getElement('message').innerHTML = aValue; | ||
120 | MochiKit.Style.showElement(this.getElement('credentialsMessage')); | ||
121 | } | ||
122 | }, | ||
123 | |||
124 | 'setMessage': function (aValue) { | ||
125 | this._setMessage(aValue); | ||
126 | MochiKit.DOM.removeElementClass(this.getElement('credentialsMessage'), 'error'); | ||
127 | }, | ||
128 | |||
129 | 'setErrorMessage': function (aValue) { | ||
130 | this._setMessage(aValue); | ||
131 | MochiKit.DOM.addElementClass(this.getElement('credentialsMessage'), 'error'); | ||
132 | }, | ||
133 | |||
134 | //------------------------------------------------------------------------- | ||
135 | |||
136 | 'setCallbacks': function (args) { | ||
137 | this._callback = args['callback']; | ||
138 | this._errorCallback = args['errorCallback']; | ||
139 | }, | ||
140 | |||
141 | 'showErrors': function (args) { | ||
142 | //console.log("LoginForm.showErrors", args); | ||
143 | if (args['previousFailedAttempt'] == 'LOGIN') { | ||
144 | this.setErrorMessage("Wrong credentials"); | ||
145 | } else if (args['previousFailedAttempt'] == 'PIN') { | ||
146 | if (args['failedAttempts'] == -1) { | ||
147 | this.setErrorMessage("Wrong PIN - Resetted"); | ||
148 | } else { | ||
149 | this.setErrorMessage("Wrong PIN"); | ||
150 | } | ||
151 | } else { | ||
152 | this.setMessage(null); | ||
153 | } | ||
154 | }, | ||
155 | |||
156 | 'updateWithArgs': function (args) { | ||
157 | this.renderIfNeeded(); | ||
158 | this.setCallbacks(args); | ||
159 | this.showErrors(args); | ||
160 | this.updateRendering(); | ||
161 | }, | ||
162 | |||
163 | 'showPinLogin': function (args) { | ||
164 | this.setPin(''); | ||
165 | this.setMode('PIN'); | ||
166 | this.updateWithArgs(args); | ||
167 | |||
168 | // $(this.getAnchor('PIN')).focus(); | ||
169 | this.getElement('PIN').focus(); | ||
170 | }, | ||
171 | |||
172 | 'showCredentialsLogin': function (args) { | ||
173 | this.setMode('CREDENTIALS'); | ||
174 | this.updateWithArgs(args); | ||
175 | |||
176 | if (this.getElement('usernameField').value.length == 0) { | ||
177 | // $(this.getAnchor('usernameField')).focus(); | ||
178 | this.getElement('usernameField').focus(); | ||
179 | } else { | ||
180 | // $(this.getAnchor('passphraseField')).focus(); | ||
181 | this.getElement('passphraseField').focus(); | ||
182 | this.getElement('passphraseField').select(); | ||
183 | } | ||
184 | }, | ||
185 | |||
186 | //------------------------------------------------------------------------- | ||
187 | |||
188 | 'renderIfNeeded': function () { | ||
189 | if (this.isFullyRendered() == false) { | ||
190 | this.render(); | ||
191 | }; | ||
192 | this.updateRendering(); | ||
193 | }, | ||
194 | |||
195 | 'updateRendering': function () { | ||
196 | MochiKit.Style.showElement(this.getElement('credentialsBody')); | ||
197 | MochiKit.Style.hideElement(this.getElement('validating')); | ||
198 | |||
199 | // this.hideAllPanes(); | ||
200 | MochiKit.Base.map(function (aNode) { MochiKit.Style.hideElement(aNode); }, MochiKit.Selector.findDocElements('div.credentialsBody > div')); | ||
201 | if (this.mode() == 'CREDENTIALS') { | ||
202 | selectedPanel = this.getElement('credentials') | ||
203 | } else if (this.mode() == 'PIN') { | ||
204 | selectedPanel = this.getElement('pin') | ||
205 | // this.updatePinDisplay(); | ||
206 | } else { | ||
207 | throw 'Unhandled login form mode'; | ||
208 | } | ||
209 | MochiKit.Style.showElement(selectedPanel); | ||
210 | |||
211 | MochiKit.Style.hideElement(this.getElement('validating')); | ||
212 | }, | ||
213 | |||
214 | 'renderSelf': function() { | ||
215 | var selectedPanel; | ||
216 | this.append(this.element(), {tag:'div', id:'login', children:[ | ||
217 | {tag:'div', cls:'toolbar', children:[ | ||
218 | {tag:'h1', html:"clipperz"} | ||
219 | ]}, | ||
220 | {tag:'div', cls:'scroll', children:[ | ||
221 | //================================================================== | ||
222 | {tag:'div', cls:'credentialsMessage', id:this.getId('credentialsMessage'), children:[ | ||
223 | {tag:'h1', cls:'message', id:this.getId('message'), html:"Message"} | ||
224 | ]}, | ||
225 | //================================================================== | ||
226 | {tag:'div', cls:'credentialsBody', id:this.getId('credentialsBody'), children:[ | ||
227 | //-------------------------------------------------------------- | ||
228 | {tag:'div', cls:'pin', id:this.getId('pin'), children:[ | ||
229 | {tag:'form', cls:'scroll', id:this.getId('pinForm'), children:[ | ||
230 | {tag:'ul', cls:'edit rounded', children:[ | ||
231 | {tag:'li', children:[{tag:'input', type:'number', name:'PIN', placeholder:"PIN", id:this.getId('PIN') }]}, | ||
232 | ]}, | ||
233 | {tag:'a', href:'#', cls:'greenButton', id:this.getId('pinSubmitButton'), html:"Login"} | ||
234 | ]} | ||
235 | ]}, | ||
236 | //-------------------------------------------------------------- | ||
237 | {tag:'div', cls:'credentials', id:this.getId('credentials'), children:[ | ||
238 | {tag:'form', cls:'scroll', id:this.getId('credentialsForm'), children:[ | ||
239 | {tag:'ul', cls:'edit rounded', children:[ | ||
240 | {tag:'li', children:[{tag:'input', type:'email', name:'name', /*value:'joe',*/ placeholder:"username", id:this.getId('usernameField') }]}, | ||
241 | {tag:'li', children:[{tag:'input', type:'password', name:'passphrase', /*value:'clipperz',*/placeholder:"passphrase", id:this.getId('passphraseField') }]} | ||
242 | ]}, | ||
243 | {tag:'a', href:'#', cls:'greenButton', id:this.getId('credentialsSubmitButton'), html:"Login"} | ||
244 | // {tag:'input', type:'submit', cls:'greenButton', id:this.getId('credentialsSubmitButton'), value:"Login"} | ||
245 | |||
246 | ]} | ||
247 | ]}, | ||
248 | //-------------------------------------------------------------- | ||
249 | ]}, | ||
250 | //================================================================== | ||
251 | {tag:'div', cls:'validating', id:this.getId('validating'), children:[ | ||
252 | {tag:'div', cls:'loading', children:[ | ||
253 | {tag:'div', cls:'spinner', children:[ | ||
254 | {tag:'div', cls:'bar01'}, | ||
255 | {tag:'div', cls:'bar02'}, | ||
256 | {tag:'div', cls:'bar03'}, | ||
257 | {tag:'div', cls:'bar04'}, | ||
258 | {tag:'div', cls:'bar05'}, | ||
259 | {tag:'div', cls:'bar06'}, | ||
260 | {tag:'div', cls:'bar07'}, | ||
261 | {tag:'div', cls:'bar08'}, | ||
262 | {tag:'div', cls:'bar09'}, | ||
263 | {tag:'div', cls:'bar10'}, | ||
264 | {tag:'div', cls:'bar11'}, | ||
265 | {tag:'div', cls:'bar12'} | ||
266 | ]} | ||
267 | ]}, | ||
268 | {tag:'div', id:this.getId('loadingMessage')}, | ||
269 | {tag:'a', href:'#', cls:'grayButton', id:this.getId('loginCancelButton'), html:"Cancel"} | ||
270 | ]} | ||
271 | //================================================================== | ||
272 | ]} | ||
273 | ]}); | ||
274 | |||
275 | MochiKit.Signal.connect(this.getElement('credentialsForm'), 'onsubmit', this, 'submitCredentialsHandler'); | ||
276 | MochiKit.Signal.connect(this.getElement('credentialsSubmitButton'), 'onclick', this, 'submitCredentialsHandler'); | ||
277 | |||
278 | MochiKit.Signal.connect(this.getElement('pinForm'), 'onsubmit', this, 'submitPinHandler'); | ||
279 | MochiKit.Signal.connect(this.getElement('pinSubmitButton'), 'onclick', this, 'submitPinHandler'); | ||
280 | |||
281 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'initProgress', this, 'initProgressHandle'); | ||
282 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'updateProgress',this, 'updateProgressHandle'); | ||
283 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'advanceProgress',this, 'advanceProgressHandle'); | ||
284 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'progressDone', this, 'progressDoneHandle'); | ||
285 | }, | ||
286 | |||
287 | //------------------------------------------------------------------------- | ||
288 | |||
289 | 'submitPinHandler': function (anEvent) { | ||
290 | varpin; | ||
291 | |||
292 | this.setMessage(null); | ||
293 | pin = this.getElement('PIN').value; | ||
294 | // $(this.getAnchor('PIN')).blur(); | ||
295 | this.getElement('PIN').blur(); | ||
296 | |||
297 | credentials = Clipperz.PM.PIN.credentialsWithPIN(pin); | ||
298 | this.loginWithCredentials(credentials); | ||
299 | }, | ||
300 | |||
301 | 'submitCredentialsHandler': function (anEvent) { | ||
302 | //console.log("submitCredentialsHandler"); | ||
303 | varcredentials; | ||
304 | |||
305 | this.setMessage(null); | ||
306 | |||
307 | credentials = {}; | ||
308 | credentials['username'] = this.getElement('usernameField').value; | ||
309 | credentials['passphrase'] = this.getElement('passphraseField').value; | ||
310 | // $(this.getAnchor('passphraseField')).blur(); | ||
311 | this.getElement('passphraseField').blur(); | ||
312 | |||
313 | this.loginWithCredentials(credentials); | ||
314 | }, | ||
315 | |||
316 | //------------------------------------------------------------------------- | ||
317 | |||
318 | 'loginWithCredentials': function (someCredentials) { | ||
319 | varargs; | ||
320 | |||
321 | args = {}; | ||
322 | args['credentials'] = someCredentials; | ||
323 | args['errorCallback'] = this.errorCallback(); | ||
324 | |||
325 | MochiKit.Style.hideElement(this.getElement('credentialsBody')); | ||
326 | MochiKit.Style.showElement(this.getElement('validating')); | ||
327 | |||
328 | MochiKit.Async.callLater(0.1, this.callback(), args); | ||
329 | }, | ||
330 | |||
331 | //------------------------------------------------------------------------- | ||
332 | |||
333 | 'initProgressHandle': function (anEvent) { | ||
334 | //console.log("** initProgressHandle", anEvent); | ||
335 | this._steps = anEvent['steps']; | ||
336 | this._actualSteps = 0; | ||
337 | }, | ||
338 | |||
339 | 'updateProgressHandle': function (anEvent) { | ||
340 | //console.log("** updateProgressHandle", anEvent); | ||
341 | this._steps += anEvent['extraSteps']; | ||
342 | }, | ||
343 | |||
344 | 'advanceProgressHandle': function (anEvent) { | ||
345 | //console.log("** advanceProgressHandle", anEvent); | ||
346 | this._actualSteps ++; | ||
347 | //console.log("STEPS: " + this._actualSteps + "/" + this._steps); | ||
348 | }, | ||
349 | |||
350 | 'progressDoneHandle': function (anEvent) { | ||
351 | //console.log("** progressDoneHandle", anEvent); | ||
352 | }, | ||
353 | |||
354 | //------------------------------------------------------------------------- | ||
355 | __syntaxFix__: "syntax fix" | ||
356 | }); | ||
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js new file mode 100644 index 0000000..12a61f7 --- a/dev/null +++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js | |||
@@ -0,0 +1,393 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2011 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz Community Edition. | ||
6 | Clipperz Community Edition is an online password manager. | ||
7 | For further information about its features and functionalities please | ||
8 | refer to http://www.clipperz.com. | ||
9 | |||
10 | * Clipperz Community Edition is free software: you can redistribute | ||
11 | it and/or modify it under the terms of the GNU Affero General Public | ||
12 | License as published by the Free Software Foundation, either version | ||
13 | 3 of the License, or (at your option) any later version. | ||
14 | |||
15 | * Clipperz Community Edition is distributed in the hope that it will | ||
16 | be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
17 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | See the GNU Affero General Public License for more details. | ||
19 | |||
20 | * You should have received a copy of the GNU Affero General Public | ||
21 | License along with Clipperz Community Edition. If not, see | ||
22 | <http://www.gnu.org/licenses/>. | ||
23 | |||
24 | */ | ||
25 | |||
26 | Clipperz.Base.module('Clipperz.PM.UI.Mobile.Controllers'); | ||
27 | |||
28 | Clipperz.PM.UI.Mobile.Controllers.MainController = function() { | ||
29 | this._jQTouch = null; | ||
30 | this._user = null; | ||
31 | this._proxy = null; | ||
32 | this._loginForm = null; | ||
33 | this._cardList = null; | ||
34 | this._cardDetail= null; | ||
35 | |||
36 | return this; | ||
37 | } | ||
38 | |||
39 | MochiKit.Base.update(Clipperz.PM.UI.Mobile.Controllers.MainController.prototype, { | ||
40 | |||
41 | 'toString': function () { | ||
42 | return "Clipperz.PM.UI.Mobile.Controllers.MainController"; | ||
43 | }, | ||
44 | |||
45 | //------------------------------------------------------------------------- | ||
46 | |||
47 | 'user': function () { | ||
48 | return this._user; | ||
49 | }, | ||
50 | |||
51 | 'setUser': function (aValue) { | ||
52 | this._user = aValue; | ||
53 | }, | ||
54 | |||
55 | //------------------------------------------------------------------------- | ||
56 | |||
57 | 'jQTouch': function () { | ||
58 | return this._jQTouch; | ||
59 | }, | ||
60 | |||
61 | 'setJQTouch': function (aValue) { | ||
62 | this._jQTouch = aValue; | ||
63 | }, | ||
64 | |||
65 | //========================================================================= | ||
66 | |||
67 | 'run': function () { | ||
68 | console.log("MainController.run"); | ||
69 | |||
70 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'doLogin', MochiKit.Base.method(this, 'doLogin')); | ||
71 | Clipperz.DOM.Helper.overwrite(MochiKit.DOM.currentDocument().body, {tag:'div', id:'jqt', children:[ | ||
72 | {tag:'div', id:'loginForm'}, | ||
73 | {tag:'div', id:'cardList'}, | ||
74 | {tag:'div', id:'cardDetail'}, | ||
75 | {tag:'div', id:'preferences'} | ||
76 | ]}); | ||
77 | |||
78 | this.showLoginForm(); | ||
79 | |||
80 | this.initjQTouch(); | ||
81 | |||
82 | |||
83 | // this.showAddToHomeScreenBaloon(); | ||
84 | // this.selectInitialProxy(); | ||
85 | }, | ||
86 | |||
87 | 'initjQTouch': function () { | ||
88 | var jqt; | ||
89 | |||
90 | jqt = new $.jQTouch({ | ||
91 | icon: 'data:image/png;charset=utf-8;base64,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', | ||
92 | // icon4: 'jqtouch4.png', | ||
93 | // startupScreen: null, //Pass a string path to a 320px x 460px startup screen for full screen apps. | ||
94 | statusBar: 'black-translucent', //Styles the status bar when running as a fullscreen app. Other options are `default`, `black`, and `black-translucent`. | ||
95 | // addGlossToIcon: true, //Set to 'false' to prevent automatic glossy button effect on icon. | ||
96 | preloadImages: false, //Pass an array of image paths to load them before page loads. Ex: `['images/link_over.png', 'images/link_select.png']` | ||
97 | fixedViewport: true, //Removes the user's ability to scale the page. Ensures the site behaves more like an application. | ||
98 | // fullScreen: true, //The website will become a fullscreen application when saved to a user's home screen. Set to `false` to disable. | ||
99 | // fullScreenClass: 'fullscreen' //Adds a class to the `<body>` when running in full-screen mode, to allow for easy detection and styling. Set to `false` to disable. | ||
100 | // themeSelectionSelector: '#jqt #themes ul', //??? | ||
101 | |||
102 | // useAnimations: true, //Set to `false` to disable all animations. | ||
103 | // useFastTouch: true, //Removes ~350ms onClick delay when tapping a link (use in conjunction with the .tap() event) **Experimental** | ||
104 | // useTouchScroll: true, //Adds support for iOS5 scrolling. Set to false to disable. **Experimental** | ||
105 | |||
106 | cacheGetRequests: false, //Automatically caches GET requests, so subsequent taps reference the pre-loaded views. (default: true) | ||
107 | |||
108 | // backSelector: '.back, .cancel, .goback', //A CSS selector for back links/buttons. When clicked, the page history goes back one, automatically reversing whichever entrance animation was used. | ||
109 | |||
110 | // cubeSelector: '.cube', //Link selector for a cube animation. | ||
111 | // dissolveSelector: '.dissolve', //Link selector for a dissolve animation. | ||
112 | // fadeSelector: '.fade', //Link selector for a fade animation. | ||
113 | // flipSelector: '.flip', //Link selector for a 3d flip animation. | ||
114 | formSelector: null, //Sets which forms are automatically submitted via Ajax. (default: 'form') | ||
115 | // popSelector: '.pop', //Link selector for a pop animation. (default: '.pop') | ||
116 | // slideSelector: 'body > * > ul li a', //Link selector for the default slide-left transition. By default applies to all links within an unordered list. Accepts any jQuery-capable selector `'li > a, a:not(.dontslide)'`, etc. (default: 'body > * > ul li a') | ||
117 | // slideupSelector: '.slideup', //Link selector for a slide up animation. (default: '.slideup') | ||
118 | // submitSelector: '.submit', //Selector which, when clicked, will submit its parent form (and close keyboard if open). (default: '.submit') | ||
119 | // swapSelector: '.swap', //Link selector for 3d swap animation. (default: '.swap') | ||
120 | // touchSelector: 'a, .touch', //Selector for items which are automatically given expanded touch events. This makes ordinary links more responsive and provides trigger events like `swipe` (default: 'a, .touch') | ||
121 | |||
122 | debug: false | ||
123 | }); | ||
124 | |||
125 | this.setJQTouch(jqt); | ||
126 | }, | ||
127 | |||
128 | //========================================================================= | ||
129 | |||
130 | 'showAddToHomeScreenBaloon': function () { | ||
131 | console.log(">>> showAddToHomeScreenBaloon"); | ||
132 | }, | ||
133 | |||
134 | //------------------------------------------------------------------------- | ||
135 | |||
136 | 'selectInitialProxy': function () { | ||
137 | //console.log(">>> selectInitialProxy"); | ||
138 | if (this.isOnline()) { | ||
139 | //console.log("--- selectInitialProxy: using default proxy"); | ||
140 | this._proxy = Clipperz.PM.Proxy.defaultProxy; | ||
141 | } else { | ||
142 | if (this.hasLocalData()) { | ||
143 | //console.log("--- selectInitialProxy: using local cache proxy"); | ||
144 | this._proxy = new Clipperz.PM.Proxy.OfflineCache({'shouldPayTolls':false}); | ||
145 | } else { | ||
146 | this.showOfflineError(); | ||
147 | } | ||
148 | } | ||
149 | }, | ||
150 | |||
151 | //------------------------------------------------------------------------- | ||
152 | |||
153 | 'showLoginForm': function (args) { | ||
154 | args = args || {}; | ||
155 | |||
156 | args['callback'] = MochiKit.Base.method(this, 'doLogin'); | ||
157 | |||
158 | if (Clipperz.PM.PIN.isSet()) { | ||
159 | args['errorCallback'] = MochiKit.Base.method(this, 'handleFailedPinLogin'); | ||
160 | this.loginForm().showPinLogin(args); | ||
161 | } else { | ||
162 | args['errorCallback'] = MochiKit.Base.method(this, 'handleFailedCredentialsLogin'); | ||
163 | this.loginForm().showCredentialsLogin(args); | ||
164 | } | ||
165 | }, | ||
166 | |||
167 | //......................................................................... | ||
168 | |||
169 | 'handleFailedCredentialsLogin': function () { | ||
170 | console.log("LOGIN FAILED"); | ||
171 | this.showLoginForm({'previousFailedAttempt':'LOGIN'}); | ||
172 | }, | ||
173 | |||
174 | //......................................................................... | ||
175 | |||
176 | 'handleFailedPinLogin': function () { | ||
177 | varfailedAttempts; | ||
178 | varstatus; | ||
179 | |||
180 | failedAttempts = Clipperz.PM.PIN.recordFailedAttempt(); | ||
181 | this.showLoginForm({'previousFailedAttempt':'PIN', 'failedAttempts': failedAttempts}); | ||
182 | }, | ||
183 | |||
184 | //------------------------------------------------------------------------- | ||
185 | |||
186 | 'doLogin': function (someArgs) { | ||
187 | var deferredResult; | ||
188 | var credentials; | ||
189 | var errorCallback; | ||
190 | var user; | ||
191 | var getPassphraseDelegate; | ||
192 | |||
193 | //console.log(">>> MainController.doLogin", someArgs); | ||
194 | credentials = someArgs['credentials']; | ||
195 | errorCallback = someArgs['errorCallback'] || MochiKit.Base.noop; | ||
196 | |||
197 | getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase); | ||
198 | user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate}); | ||
199 | |||
200 | deferredResult = new Clipperz.Async.Deferred('MainController.doLogin', {trace:false}); | ||
201 | deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress', {'steps':4}); | ||
202 | deferredResult.addCallback(MochiKit.Async.wait, 0.1); | ||
203 | deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection'); | ||
204 | deferredResult.addMethod(user, 'login'); | ||
205 | deferredResult.addCallbacks( | ||
206 | MochiKit.Base.method(this, 'processSuccessfulLogin', user), | ||
207 | errorCallback | ||
208 | ); | ||
209 | deferredResult.callback(); | ||
210 | |||
211 | return deferredResult; | ||
212 | }, | ||
213 | |||
214 | //.......................................................................... | ||
215 | |||
216 | 'processSuccessfulLogin': function (aUser) { | ||
217 | var deferredResult; | ||
218 | |||
219 | deferredResult = new Clipperz.Async.Deferred('MainController.processSuccessfulLogin', {trace:false}); | ||
220 | deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount'); | ||
221 | // deferredResult.addMethod(this, 'removeLoginForm'); | ||
222 | deferredResult.addMethod(this, 'setUser', aUser); | ||
223 | deferredResult.addMethod(this, 'setupApplication'); | ||
224 | deferredResult.addMethod(this, 'runApplication'); | ||
225 | deferredResult.callback(); | ||
226 | |||
227 | return deferredResult; | ||
228 | }, | ||
229 | |||
230 | //------------------------------------------------------------------------- | ||
231 | |||
232 | 'setupApplication': function () { | ||
233 | vardeferredResult; | ||
234 | |||
235 | console.log(">>> setupApplication"); | ||
236 | deferredResult = new Clipperz.Async.Deferred("MainController.setupApplication", {trace:false}); | ||
237 | deferredResult.addMethod(this, 'welcomeFirstTimeUser'); | ||
238 | deferredResult.addMethod(this, 'showPaymentReminder'); | ||
239 | deferredResult.addMethod(this, 'copyDataLocally'); | ||
240 | deferredResult.callback(arguments); | ||
241 | |||
242 | return deferredResult; | ||
243 | }, | ||
244 | |||
245 | |||
246 | //.......................................................................... | ||
247 | |||
248 | 'isFirstTimeUser': function () { | ||
249 | return false; | ||
250 | }, | ||
251 | |||
252 | 'welcomeFirstTimeUser': function () { | ||
253 | vardeferredResult; | ||
254 | |||
255 | deferredResult = new Clipperz.Async.Deferred('MainController.welcomeFirstTimeUser', {trace:false}); | ||
256 | |||
257 | if (this.isFirstTimeUser()) { | ||
258 | deferredResult.addCallback(function () { console.log("--> welcome"); }); | ||
259 | } | ||
260 | deferredResult.callback(); | ||
261 | |||
262 | return deferredResult; | ||
263 | }, | ||
264 | |||
265 | //.......................................................................... | ||
266 | |||
267 | 'shouldShowPaymentReminder': function () { | ||
268 | return true; | ||
269 | }, | ||
270 | |||
271 | 'showPaymentReminder': function () { | ||
272 | vardeferredResult; | ||
273 | |||
274 | deferredResult = new Clipperz.Async.Deferred('MainController.showPaymentReminder', {trace:false}); | ||
275 | |||
276 | if (this.shouldShowPaymentReminder()) { | ||
277 | deferredResult.addCallback(function () { console.log("--> payment reminder"); }); | ||
278 | } | ||
279 | deferredResult.callback(); | ||
280 | |||
281 | return deferredResult; | ||
282 | }, | ||
283 | |||
284 | //.......................................................................... | ||
285 | |||
286 | 'canCopyDataLocally': function () { | ||
287 | return false; | ||
288 | }, | ||
289 | |||
290 | 'copyDataLocally': function () { | ||
291 | vardeferredResult; | ||
292 | |||
293 | deferredResult = new Clipperz.Async.Deferred('MainController.copyDataLocally', {trace:false}); | ||
294 | |||
295 | if (this.canCopyDataLocally()) { | ||
296 | deferredResult.addCallback(function () { console.log("--> copy data locally"); }); | ||
297 | } | ||
298 | deferredResult.callback(); | ||
299 | |||
300 | return deferredResult; | ||
301 | |||
302 | }, | ||
303 | |||
304 | //------------------------------------------------------------------------- | ||
305 | |||
306 | 'runApplication': function () { | ||
307 | var deferredResult; | ||
308 | |||
309 | //console.log(">>> runApplication"); | ||
310 | deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:true}); | ||
311 | deferredResult.addMethod(this.user(), 'getRecords'); | ||
312 | deferredResult.addMethod(this, 'showCards'); | ||
313 | deferredResult.callback(); | ||
314 | |||
315 | return deferredResult; | ||
316 | }, | ||
317 | |||
318 | //========================================================================= | ||
319 | |||
320 | 'showOfflineError': function (anException) { | ||
321 | alert("Error: " + anException); | ||
322 | throw anException; | ||
323 | }, | ||
324 | |||
325 | //========================================================================= | ||
326 | |||
327 | 'isOnline': function() { | ||
328 | return navigator.onLine; | ||
329 | }, | ||
330 | |||
331 | 'hasLocalData': function() { | ||
332 | return false; | ||
333 | }, | ||
334 | |||
335 | //========================================================================= | ||
336 | |||
337 | 'loginForm': function() { | ||
338 | if (this._loginForm == null) { | ||
339 | this._loginForm = new Clipperz.PM.UI.Mobile.Components.LoginForm({element:MochiKit.DOM.getElement('loginForm')}); | ||
340 | } | ||
341 | |||
342 | return this._loginForm; | ||
343 | }, | ||
344 | |||
345 | 'removeLoginForm': function () { | ||
346 | if (this._loginForm != null) { | ||
347 | this._loginForm.remove(); | ||
348 | this._loginForm = null; | ||
349 | } | ||
350 | }, | ||
351 | |||
352 | //------------------------------------------------------------------------- | ||
353 | |||
354 | 'cardList': function () { | ||
355 | if (this._cardList == null) { | ||
356 | this._cardList = new Clipperz.PM.UI.Mobile.Components.CardList({element:MochiKit.DOM.getElement('cardList')}); | ||
357 | MochiKit.Signal.connect(this._cardList, 'selectedCard', this, 'selectCardHandler'); | ||
358 | } | ||
359 | |||
360 | return this._cardList; | ||
361 | }, | ||
362 | |||
363 | 'showCards': function (someCards) { | ||
364 | this.cardList().showCards(someCards); | ||
365 | this.jQTouch().goTo('#cardList', 'slideleft'); | ||
366 | }, | ||
367 | |||
368 | //------------------------------------------------------------------------- | ||
369 | |||
370 | 'cardDetail': function () { | ||
371 | if (this._cardDetail == null) { | ||
372 | this._cardDetail = new Clipperz.PM.UI.Mobile.Components.CardDetail({element:MochiKit.DOM.getElement('cardDetail')}); | ||
373 | } | ||
374 | |||
375 | return this._cardDetail; | ||
376 | }, | ||
377 | |||
378 | 'selectCardHandler': function (aCardReference) { | ||
379 | var deferredResult; | ||
380 | |||
381 | deferredResult = new Clipperz.Async.Deferred("MainController.selectCardHandler", {trace:true}); | ||
382 | deferredResult.addMethod(this.cardDetail(), 'render'); | ||
383 | deferredResult.addMethod(this.jQTouch(), 'goTo', '#cardDetail', 'slideleft'); | ||
384 | deferredResult.addMethod(this.user(), 'getRecord', aCardReference); | ||
385 | deferredResult.addMethod(this.cardDetail(), 'showCard'); | ||
386 | deferredResult.callback(); | ||
387 | |||
388 | return deferredResult; | ||
389 | }, | ||
390 | |||
391 | //========================================================================= | ||
392 | __syntaxFix__: "syntax fix" | ||
393 | }); | ||
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/AccountPanel.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/AccountPanel.js index ee6d7a3..d6b0574 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/AccountPanel.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/AccountPanel.js | |||
@@ -41,6 +41,10 @@ Clipperz.PM.UI.Web.Components.AccountPanel = function(args) { | |||
41 | tab:'passphraseTab', | 41 | tab:'passphraseTab', |
42 | panel:'passphrasePanel' | 42 | panel:'passphrasePanel' |
43 | }, | 43 | }, |
44 | 'OTP': { | ||
45 | tab:'OTPTab', | ||
46 | panel:'OTPPanel' | ||
47 | }, | ||
44 | 'PREFERENCES': { | 48 | 'PREFERENCES': { |
45 | tab:'preferencesTab', | 49 | tab:'preferencesTab', |
46 | panel:'preferencesPanel' | 50 | panel:'preferencesPanel' |
@@ -74,6 +78,7 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.AccountPanel, Clipperz.PM.UI. | |||
74 | {tag:'ul', children:[ | 78 | {tag:'ul', children:[ |
75 | // {tag:'li', id:this.getId('accountTab'), children:[{tag:'a', href:'#', html:'Account'}], cls:'first'}, | 79 | // {tag:'li', id:this.getId('accountTab'), children:[{tag:'a', href:'#', html:'Account'}], cls:'first'}, |
76 | {tag:'li', id:this.getId('passphraseTab'), children:[{tag:'a', href:'#', html:'Passphrase'}], cls:'first'}, | 80 | {tag:'li', id:this.getId('passphraseTab'), children:[{tag:'a', href:'#', html:'Passphrase'}], cls:'first'}, |
81 | {tag:'li', id:this.getId('OTPTab'), children:[{tag:'a', href:'#', html:'One Time Passwords'}]}, | ||
77 | {tag:'li', id:this.getId('preferencesTab'), children:[{tag:'a', href:'#', html:'Preferences'}]}, | 82 | {tag:'li', id:this.getId('preferencesTab'), children:[{tag:'a', href:'#', html:'Preferences'}]}, |
78 | {tag:'li', id:this.getId('loginHistoryTab'),children:[{tag:'a', href:'#', html:'Login history'}]} | 83 | {tag:'li', id:this.getId('loginHistoryTab'),children:[{tag:'a', href:'#', html:'Login history'}]} |
79 | ]} | 84 | ]} |
@@ -117,16 +122,16 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.AccountPanel, Clipperz.PM.UI. | |||
117 | {tag:'div', cls:'clear'}, | 122 | {tag:'div', cls:'clear'}, |
118 | {tag:'div', cls:'confirmButton', id:this.getId('confirmationButton'), children:[ | 123 | {tag:'div', cls:'confirmButton', id:this.getId('confirmationButton'), children:[ |
119 | {tag:'span', html:"change passphrase"} | 124 | {tag:'span', html:"change passphrase"} |
125 | ]} | ||
120 | ]}, | 126 | ]}, |
121 | 127 | {tag:'li', id:this.getId('OTPPanel'), children:[ | |
122 | {tag:'h3', cls:'manageOTP', html:"Manage One-Time Passphrases"}, | 128 | // {tag:'h3', html:"Manage One-Time Passphrases"} |
123 | {} | ||
124 | ]}, | 129 | ]}, |
125 | {tag:'li', id:this.getId('preferencesPanel'), children:[ | 130 | {tag:'li', id:this.getId('preferencesPanel'), children:[ |
126 | {tag:'h3', html:"-- Preferences --"} | 131 | // {tag:'h3', html:"-- Preferences --"} |
127 | ]}, | 132 | ]}, |
128 | {tag:'li', id:this.getId('loginHistoryPanel'), children:[ | 133 | {tag:'li', id:this.getId('loginHistoryPanel'), children:[ |
129 | {tag:'h3', html:"-- Login History --"} | 134 | // {tag:'h3', html:"-- Login History --"} |
130 | ]} | 135 | ]} |
131 | ]} | 136 | ]} |
132 | ]} | 137 | ]} |
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/DataPanel.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/DataPanel.js index d2f1045..462d864 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/DataPanel.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/DataPanel.js | |||
@@ -82,16 +82,18 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.DataPanel, Clipperz.PM.UI.Com | |||
82 | {tag:'div', cls:'subPanelContent', children:[ | 82 | {tag:'div', cls:'subPanelContent', children:[ |
83 | {tag:'ul', children:[ | 83 | {tag:'ul', children:[ |
84 | {tag:'li', id:this.getId('offlineCopyPanel'),children:[ | 84 | {tag:'li', id:this.getId('offlineCopyPanel'),children:[ |
85 | {tag:'h3', html:"Offline copy"} | 85 | // {tag:'h3', html:"Offline copy"}, |
86 | {tag:'p', html:"With just one click you can dump all your encrypted data from Clipperz servers to your hard disk and create a read-only offline version of Clipperz to be used when you are not connected to the Internet."}, | ||
87 | {tag:'a', id:this.getId('offlineCopyDownloadLink'), href:'#', html:"Download", cls:'downloadOfflineCopy'} | ||
86 | ]}, | 88 | ]}, |
87 | {tag:'li', id:this.getId('sharingPanel'),children:[ | 89 | {tag:'li', id:this.getId('sharingPanel'),children:[ |
88 | {tag:'h3', html:"Sharing"} | 90 | // {tag:'h3', html:"Sharing"} |
89 | ]}, | 91 | ]}, |
90 | {tag:'li', id:this.getId('importPanel'), children:[ | 92 | {tag:'li', id:this.getId('importPanel'), children:[ |
91 | {tag:'h3', html:"Import"} | 93 | // {tag:'h3', html:"Import"} |
92 | ]}, | 94 | ]}, |
93 | {tag:'li', id:this.getId('exportPanel'), children:[ | 95 | {tag:'li', id:this.getId('exportPanel'), children:[ |
94 | {tag:'h3', html:"Export"} | 96 | // {tag:'h3', html:"Export"} |
95 | ]} | 97 | ]} |
96 | ]} | 98 | ]} |
97 | ]} | 99 | ]} |
@@ -101,6 +103,12 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.DataPanel, Clipperz.PM.UI.Com | |||
101 | ]); | 103 | ]); |
102 | 104 | ||
103 | this.tabPanelController().setup({selected:this.initiallySelectedTab()}); | 105 | this.tabPanelController().setup({selected:this.initiallySelectedTab()}); |
106 | MochiKit.Signal.connect(this.getId('offlineCopyDownloadLink'), 'onclick', this, 'downloadOfflineCopy'); | ||
107 | }, | ||
108 | |||
109 | 'downloadOfflineCopy': function (anEvent) { | ||
110 | anEvent.preventDefault(); | ||
111 | MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'downloadOfflineCopy', anEvent.src()); | ||
104 | }, | 112 | }, |
105 | 113 | ||
106 | //------------------------------------------------------------------------- | 114 | //------------------------------------------------------------------------- |
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/LoginProgress.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/LoginProgress.js index 5d082b5..26506e7 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/LoginProgress.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/LoginProgress.js | |||
@@ -82,9 +82,10 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.LoginProgress, Clipperz.PM.UI | |||
82 | ]}, | 82 | ]}, |
83 | {tag:'div', cls:'footer', children:[ | 83 | {tag:'div', cls:'footer', children:[ |
84 | {tag:'div', cls:'buttonArea', id:this.getId('buttonArea'), children:[ | 84 | {tag:'div', cls:'buttonArea', id:this.getId('buttonArea'), children:[ |
85 | {tag:'div', cls:'button', id:this.getId('button'), children:[ | 85 | // {tag:'div', cls:'button', id:this.getId('button'), children:[ |
86 | {tag:'a', href:'#', id:this.getId('buttonLink'), html:"cancel"} | 86 | // {tag:'a', href:'#', id:this.getId('buttonLink'), html:"cancel"} |
87 | ]} | 87 | // ]} |
88 | {tag:'a', cls:'button', id:this.getId('button'), html:"cancel"} | ||
88 | ]} | 89 | ]} |
89 | ]} | 90 | ]} |
90 | ]}); | 91 | ]}); |
@@ -95,7 +96,8 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.LoginProgress, Clipperz.PM.UI | |||
95 | this.addComponent(new Clipperz.PM.UI.Common.Components.ProgressBar({'element':this.getElement('progressBar')})); | 96 | this.addComponent(new Clipperz.PM.UI.Common.Components.ProgressBar({'element':this.getElement('progressBar')})); |
96 | MochiKit.Style.hideElement(this.getElement('errorBox')); | 97 | MochiKit.Style.hideElement(this.getElement('errorBox')); |
97 | 98 | ||
98 | MochiKit.Signal.connect(this.getId('buttonLink'), 'onclick', this, 'cancelEventHandler'); | 99 | // MochiKit.Signal.connect(this.getId('buttonLink'), 'onclick', this, 'cancelEventHandler'); |
100 | MochiKit.Signal.connect(this.getId('button'), 'onclick', this, 'cancelEventHandler'); | ||
99 | }, | 101 | }, |
100 | 102 | ||
101 | //------------------------------------------------------------------------- | 103 | //------------------------------------------------------------------------- |
@@ -121,7 +123,9 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.LoginProgress, Clipperz.PM.UI | |||
121 | //------------------------------------------------------------------------- | 123 | //------------------------------------------------------------------------- |
122 | 124 | ||
123 | 'showErrorMessage': function() { | 125 | 'showErrorMessage': function() { |
124 | this.getElement('buttonLink').innerHTML = "close"; | 126 | // this.getElement('buttonLink').innerHTML = "close"; |
127 | this.getElement('button').innerHTML = "close"; | ||
128 | MochiKit.DOM.addElementClass(this.getElement('button'), 'default'); | ||
125 | 129 | ||
126 | MochiKit.Style.hideElement(this.getElement('progressBar')); | 130 | MochiKit.Style.hideElement(this.getElement('progressBar')); |
127 | 131 | ||
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/PageFooter.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/PageFooter.js index a25c8f5..dcf506f 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/PageFooter.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/PageFooter.js | |||
@@ -49,12 +49,11 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.PageFooter, Clipperz.PM.UI.Co | |||
49 | this.append(this.element(), [ | 49 | this.append(this.element(), [ |
50 | {tag:'div', cls:'footerWrapper', children:[ | 50 | {tag:'div', cls:'footerWrapper', children:[ |
51 | {tag:'div', cls:'footerContent', children:[ | 51 | {tag:'div', cls:'footerContent', children:[ |
52 | // {tag:'div', cls:'footerStarIcon'}, | ||
53 | {tag:'canvas', id:this.getId('footerStarIcon'), cls:'footerStarIcon'}, | 52 | {tag:'canvas', id:this.getId('footerStarIcon'), cls:'footerStarIcon'}, |
54 | {tag:'span', cls:'copyright', html:'Copyright © 2009-2012 Clipperz Srl'}, | 53 | {tag:'span', cls:'copyright', html:'Copyright © 2009-2013 Clipperz Srl'}, |
55 | {tag:'a', href:'http://www.clipperz.com/terms_of_service',target:'_blank', html:'terms of service'}, | 54 | {tag:'a', href:'http://www.clipperz.com/terms_of_service',target:'_blank', html:'terms of service'}, |
56 | {tag:'a', href:'http://www.clipperz.com/privacy_policy',target:'_blank', html:'privacy policy'}, | 55 | {tag:'a', href:'http://www.clipperz.com/privacy_policy',target:'_blank', html:'privacy policy'}, |
57 | {tag:'span', cls:'applicationVersion', html:'application version: [1992]'} | 56 | {tag:'div', cls:'applicationVersion', htmlString:'application version: <a href="https://github.com/clipperz/password-manager/tree/' + Clipperz_version + '" target="github">' + Clipperz_version + '</a>'} |
58 | ]} | 57 | ]} |
59 | ]} | 58 | ]} |
60 | ]); | 59 | ]); |
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/ToolsPanel.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/ToolsPanel.js index 3ee6189..0fa369f 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Components/ToolsPanel.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Components/ToolsPanel.js | |||
@@ -82,16 +82,16 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.ToolsPanel, Clipperz.PM.UI.Co | |||
82 | {tag:'div', cls:'subPanelContent', children:[ | 82 | {tag:'div', cls:'subPanelContent', children:[ |
83 | {tag:'ul', children:[ | 83 | {tag:'ul', children:[ |
84 | {tag:'li', id:this.getId('passwordGeneratorPanel'),children:[ | 84 | {tag:'li', id:this.getId('passwordGeneratorPanel'),children:[ |
85 | {tag:'h3', html:"Password generator"} | 85 | // {tag:'h3', html:"Password generator"} |
86 | ]}, | 86 | ]}, |
87 | {tag:'li', id:this.getId('bookmarkletPanel'),children:[ | 87 | {tag:'li', id:this.getId('bookmarkletPanel'),children:[ |
88 | {tag:'h3', html:"Bookmarklet"} | 88 | // {tag:'h3', html:"Bookmarklet"} |
89 | ]}, | 89 | ]}, |
90 | {tag:'li', id:this.getId('compactEditionPanel'), children:[ | 90 | {tag:'li', id:this.getId('compactEditionPanel'), children:[ |
91 | {tag:'h3', html:"Compact edition"} | 91 | // {tag:'h3', html:"Compact edition"} |
92 | ]}, | 92 | ]}, |
93 | {tag:'li', id:this.getId('httpAuthPanel'), children:[ | 93 | {tag:'li', id:this.getId('httpAuthPanel'), children:[ |
94 | {tag:'h3', html:"HTTP Auth"} | 94 | // {tag:'h3', html:"HTTP Auth"} |
95 | ]} | 95 | ]} |
96 | ]} | 96 | ]} |
97 | ]} | 97 | ]} |
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js index 9a0e744..1ab2e69 100644 --- a/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js +++ b/frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js | |||
@@ -235,6 +235,8 @@ MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.AppController.prototype, { | |||
235 | MochiKit.Signal.connect(this.tabSidePanel(), 'addCard', this, 'handleAddCard'); | 235 | MochiKit.Signal.connect(this.tabSidePanel(), 'addCard', this, 'handleAddCard'); |
236 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'addCard', this, 'handleAddCard'); | 236 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'addCard', this, 'handleAddCard'); |
237 | 237 | ||
238 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'downloadOfflineCopy',this, 'handleDownloadOfflineCopy'); | ||
239 | |||
238 | deferredResult = new Clipperz.Async.Deferred("AppController.run", {trace:false}); | 240 | deferredResult = new Clipperz.Async.Deferred("AppController.run", {trace:false}); |
239 | 241 | ||
240 | deferredResult.addMethod(this.cardsController(), 'run', {slot:this.appPage().slotNamed('cardGrid'), user:user}); | 242 | deferredResult.addMethod(this.cardsController(), 'run', {slot:this.appPage().slotNamed('cardGrid'), user:user}); |
@@ -321,6 +323,29 @@ MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.AppController.prototype, { | |||
321 | ], {trace:false}); | 323 | ], {trace:false}); |
322 | }, | 324 | }, |
323 | 325 | ||
326 | 'handleDownloadOfflineCopy': function (anEvent) { | ||
327 | console.log("AppController.handleDownloadOfflineCopy"); | ||
328 | var downloadHref; | ||
329 | |||
330 | downloadHref = window.location.href.replace(/\/[^\/]*$/,'') + Clipperz_dumpUrl; | ||
331 | |||
332 | if (Clipperz_IEisBroken == true) { | ||
333 | window.open(downloadHref, ""); | ||
334 | } else { | ||
335 | vardeferredResult; | ||
336 | var newWindow; | ||
337 | |||
338 | newWindow = window.open("", ""); | ||
339 | |||
340 | deferredResult = new Clipperz.Async.Deferred("AppController.handleDownloadOfflineCopy", {trace:true}); | ||
341 | deferredResult.addCallback(MochiKit.Base.method(this.user().connection(), 'message'), 'echo', {'echo':"echo"}); | ||
342 | deferredResult.addCallback(function(aWindow) { | ||
343 | aWindow.location.href = downloadHref; | ||
344 | }, newWindow); | ||
345 | deferredResult.callback(); | ||
346 | } | ||
347 | }, | ||
348 | |||
324 | //============================================================================= | 349 | //============================================================================= |
325 | __syntaxFix__: "syntax fix" | 350 | __syntaxFix__: "syntax fix" |
326 | }); | 351 | }); |
diff --git a/frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/CardDetail.js b/frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/CardDetail.js deleted file mode 100644 index 5380aa1..0000000 --- a/frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/CardDetail.js +++ b/dev/null | |||
@@ -1,163 +0,0 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2011 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz Community Edition. | ||
6 | Clipperz Community Edition is an online password manager. | ||
7 | For further information about its features and functionalities please | ||
8 | refer to http://www.clipperz.com. | ||
9 | |||
10 | * Clipperz Community Edition is free software: you can redistribute | ||
11 | it and/or modify it under the terms of the GNU Affero General Public | ||
12 | License as published by the Free Software Foundation, either version | ||
13 | 3 of the License, or (at your option) any later version. | ||
14 | |||
15 | * Clipperz Community Edition is distributed in the hope that it will | ||
16 | be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
17 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | See the GNU Affero General Public License for more details. | ||
19 | |||
20 | * You should have received a copy of the GNU Affero General Public | ||
21 | License along with Clipperz Community Edition. If not, see | ||
22 | <http://www.gnu.org/licenses/>. | ||
23 | |||
24 | */ | ||
25 | |||
26 | Clipperz.Base.module('Clipperz.PM.UI.iPhone.Components'); | ||
27 | |||
28 | Clipperz.PM.UI.iPhone.Components.CardDetail = function(args) { | ||
29 | args = args || {}; | ||
30 | |||
31 | Clipperz.PM.UI.iPhone.Components.CardDetail.superclass.constructor.apply(this, arguments); | ||
32 | |||
33 | this._cardReference = null; | ||
34 | |||
35 | return this; | ||
36 | } | ||
37 | |||
38 | //============================================================================= | ||
39 | |||
40 | Clipperz.Base.extend(Clipperz.PM.UI.iPhone.Components.CardDetail, Clipperz.PM.UI.Common.Components.BaseComponent, { | ||
41 | |||
42 | //------------------------------------------------------------------------- | ||
43 | |||
44 | 'toString': function () { | ||
45 | return "Clipperz.PM.UI.iPhone.Components.CardDetail component"; | ||
46 | }, | ||
47 | |||
48 | //------------------------------------------------------------------------- | ||
49 | |||
50 | 'cardReference': function () { | ||
51 | return this._cardReference; | ||
52 | }, | ||
53 | |||
54 | 'setCardReference': function (aValue) { | ||
55 | this._cardReference = aValue; | ||
56 | }, | ||
57 | |||
58 | //------------------------------------------------------------------------- | ||
59 | |||
60 | 'renderSelf': function(/*aContainer, aPosition*/) { | ||
61 | this.append(this.element(), [ | ||
62 | {tag:'div', cls:'cardDetail', id:this.getId('cardDetail'), children:[ | ||
63 | {tag:'div', id:this.getId('progressBar')} //, | ||
64 | // {tag:'h1', cls:'loading', html:"loading"} | ||
65 | ]} | ||
66 | ]); | ||
67 | |||
68 | this.addComponent(new Clipperz.PM.UI.Common.Components.ProgressBar({'element':this.getElement('progressBar')})); | ||
69 | MochiKit.Signal.signal(Clipperz.PM.UI.Common.Controllers.ProgressBarController.defaultController, 'updateProgress', 0); | ||
70 | }, | ||
71 | |||
72 | //========================================================================= | ||
73 | |||
74 | 'showCardDetails': function (someData) { | ||
75 | this.element().innerHTML = ''; | ||
76 | this.append(this.element(), [ | ||
77 | {tag:'fieldset', id:this.getId('fields'), children:MochiKit.Base.map(function (aFieldData) { | ||
78 | return {tag:'div', cls:'row', children:[ | ||
79 | {tag:'label', html:aFieldData['label']}, | ||
80 | // {tag:'span', cls:('fieldValue ' + (aFieldData['isHidden']? 'password' : 'text')), html:aFieldData['value']} | ||
81 | {tag:'div', cls:('fieldValue ' + (aFieldData['isHidden']? 'password' : 'text')), children:[ | ||
82 | {tag:'div', children:[{tag:'p', html:aFieldData['value']}]} | ||
83 | ]} | ||
84 | // {tag:'input', type:'text', cls:('fieldValue ' + (aFieldData['isHidden']? 'password' : 'text')), value:aFieldData['value'], disabled:true} | ||
85 | |||
86 | ]} | ||
87 | }, someData['fields'])} | ||
88 | ]); | ||
89 | |||
90 | MochiKit.Iter.forEach(MochiKit.Selector.findChildElements(this.element(), ['span.password']), MochiKit.Base.bind(function (aPasswordElement) { | ||
91 | MochiKit.Signal.connect(aPasswordElement, 'onclick', function (anEvent) { alert(MochiKit.DOM.scrapeText(anEvent.src())); }) | ||
92 | }, this)); | ||
93 | |||
94 | if (someData['directLogins'].length > 0) { | ||
95 | this.append(this.element(), [ | ||
96 | {tag:'h2', html:"Direct logins"}, | ||
97 | {tag:'fieldset', id:this.getId('directLogins'), children:MochiKit.Base.map(function (aDirectLoginData) { | ||
98 | return {tag:'div', cls:'row', id:('directLogin_' + aDirectLoginData['_reference']), children:[ | ||
99 | {tag:'img', cls:'favicon', src:aDirectLoginData['favicon']}, | ||
100 | // {tag:'input', cls:'directLogin', disabled:'disabled', type:'text', name:aDirectLoginData['label'], value:aDirectLoginData['label']} | ||
101 | {tag:'span', cls:'directLogin', html:aDirectLoginData['label']} | ||
102 | ]} | ||
103 | }, someData['directLogins'])} | ||
104 | ]); | ||
105 | |||
106 | MochiKit.Base.map(MochiKit.Base.bind(function (aRowNode) { | ||
107 | MochiKit.Signal.connect(aRowNode, 'onclick', this, 'directLoginClickHandler'); | ||
108 | }, this), | ||
109 | MochiKit.Selector.findChildElements(this.getElement('directLogins'), ['div.row']) | ||
110 | ) | ||
111 | }; | ||
112 | |||
113 | if (someData['notes'] != '') { | ||
114 | this.append(this.element(), [ | ||
115 | {tag:'h2', html:"Notes"}, | ||
116 | {tag:'fieldset', id:this.getId('fieldset'), children:[ | ||
117 | {tag:'div', cls:'row notes', children:[ | ||
118 | {tag:'span', html:someData['notes']} | ||
119 | ]} | ||
120 | ]} | ||
121 | ]); | ||
122 | }; | ||
123 | |||
124 | return true; | ||
125 | }, | ||
126 | |||
127 | //------------------------------------------------------------------------- | ||
128 | /* | ||
129 | 'toggleClickHandler': function (anEvent) { | ||
130 | varnextState; | ||
131 | varfieldValue; | ||
132 | |||
133 | //console.log("TOGGLE"); | ||
134 | anEvent.preventDefault; | ||
135 | fieldValue = MochiKit.Selector.findChildElements(anEvent.src().parentNode.parentNode, ['span.password'])[0]; | ||
136 | |||
137 | nextState = (MochiKit.DOM.getNodeAttribute(anEvent.src(), 'toggled') != 'true'); | ||
138 | if (nextState) { | ||
139 | MochiKit.DOM.removeElementClass(fieldValue, 'clear'); | ||
140 | } else { | ||
141 | MochiKit.DOM.addElementClass(fieldValue, 'clear'); | ||
142 | } | ||
143 | |||
144 | MochiKit.DOM.setNodeAttribute(anEvent.src(), 'toggled', nextState); | ||
145 | }, | ||
146 | */ | ||
147 | //========================================================================= | ||
148 | |||
149 | 'directLoginClickHandler': function (anEvent) { | ||
150 | anEvent.preventDefault(); | ||
151 | |||
152 | if (/(directLogin_)/.test(anEvent.src().id)) { | ||
153 | var directLoginReference; | ||
154 | |||
155 | directLoginReference = anEvent.src().id.match(/(directLogin_)(.*)/)[2]; | ||
156 | MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'selectedDirectLogin', {cardReference:this.cardReference(), directLoginReference:directLoginReference}); | ||
157 | } | ||
158 | }, | ||
159 | |||
160 | //========================================================================= | ||
161 | |||
162 | __syntaxFix__: "syntax fix" | ||
163 | }); | ||
diff --git a/frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/LoginForm.js b/frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/LoginForm.js deleted file mode 100644 index 5341878..0000000 --- a/frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/LoginForm.js +++ b/dev/null | |||
@@ -1,178 +0,0 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2011 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz Community Edition. | ||
6 | Clipperz Community Edition is an online password manager. | ||
7 | For further information about its features and functionalities please | ||
8 | refer to http://www.clipperz.com. | ||
9 | |||
10 | * Clipperz Community Edition is free software: you can redistribute | ||
11 | it and/or modify it under the terms of the GNU Affero General Public | ||
12 | License as published by the Free Software Foundation, either version | ||
13 | 3 of the License, or (at your option) any later version. | ||
14 | |||
15 | * Clipperz Community Edition is distributed in the hope that it will | ||
16 | be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
17 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | See the GNU Affero General Public License for more details. | ||
19 | |||
20 | * You should have received a copy of the GNU Affero General Public | ||
21 | License along with Clipperz Community Edition. If not, see | ||
22 | <http://www.gnu.org/licenses/>. | ||
23 | |||
24 | */ | ||
25 | |||
26 | Clipperz.Base.module('Clipperz.PM.UI.iPhone.Components'); | ||
27 | |||
28 | Clipperz.PM.UI.iPhone.Components.LoginForm = function(args) { | ||
29 | args = args || {}; | ||
30 | |||
31 | Clipperz.PM.UI.iPhone.Components.LoginForm.superclass.constructor.apply(this, arguments); | ||
32 | |||
33 | return this; | ||
34 | } | ||
35 | |||
36 | //============================================================================= | ||
37 | |||
38 | Clipperz.Base.extend(Clipperz.PM.UI.iPhone.Components.LoginForm, Clipperz.PM.UI.Common.Components.BaseComponent, { | ||
39 | |||
40 | //------------------------------------------------------------------------- | ||
41 | |||
42 | 'toString': function () { | ||
43 | return "Clipperz.PM.UI.iPhone.Components.LoginForm component"; | ||
44 | }, | ||
45 | |||
46 | //------------------------------------------------------------------------- | ||
47 | |||
48 | 'focusOnUsername': function () { | ||
49 | this.getElement('username').focus(); | ||
50 | }, | ||
51 | |||
52 | //------------------------------------------------------------------------- | ||
53 | |||
54 | 'username': function () { | ||
55 | return this.getElement('username').value; | ||
56 | }, | ||
57 | |||
58 | 'passphrase': function () { | ||
59 | return this.getElement('passphrase').value; | ||
60 | }, | ||
61 | |||
62 | //------------------------------------------------------------------------- | ||
63 | |||
64 | 'renderSelf': function(/*aContainer, aPosition*/) { | ||
65 | this.append(this.element(), [ | ||
66 | {tag:'div', cls:'toolbar iPhoneClipperzToolbar', children:[ | ||
67 | {tag:'h1', id:'pageTitle', html:'Clipperz'}, | ||
68 | {tag:'a', id:'backButton', cls:'button', href:'#', html:"back"} | ||
69 | ]}, | ||
70 | {tag:'form', title:'Theaters', cls:'panel toolbarlessPanel loginForm', id:this.getId('loginFormPanel'), children:[ | ||
71 | {tag:'fieldset', id:this.getId('fieldset'), children:[ | ||
72 | {tag:'div', cls:'row', children:[ | ||
73 | {tag:'label', html:"username"}, | ||
74 | {tag:'input', type:'text', name:'username', value:"", autocorrect:'off', autocapitalize:'off', id:this.getId('username')} | ||
75 | ]}, | ||
76 | {tag:'div', cls:'row', children:[ | ||
77 | {tag:'label', html:"passphrase"}, | ||
78 | {tag:'input', type:'password', name:'passphrase', value:"", id:this.getId('passphrase')} | ||
79 | ]} | ||
80 | ]}, | ||
81 | {tag:'a', cls:'whiteButton', type:'submit', href:'#', html:"Login", id:this.getId('submit')} | ||
82 | ]}, | ||
83 | {tag:'div', cls:'panel toolbarlessPanel loginProgressPanel', id:this.getId('loginProgressPanel'), children:[ | ||
84 | {tag:'div', id:this.getId('progressBar')} //, | ||
85 | // {tag:'a', cls:'whiteButton', type:'submit', href:'#', html:"Cancel", id:this.getId('cancel')} | ||
86 | ]}, | ||
87 | {tag:'div', cls:'panel loginErrorPanel', id:this.getId('loginErrorPanel'), children:[ | ||
88 | {tag:'div', cls:'errorMessage', id:this.getId('errorMessageBox'), children:[ | ||
89 | {tag:'h2', id:this.getId('errorMessage'), html:"Login failed"} | ||
90 | ]} | ||
91 | ]} | ||
92 | ]); | ||
93 | |||
94 | MochiKit.Signal.connect(this.getElement('submit'), 'onclick',this, 'submitHandler'); | ||
95 | MochiKit.Signal.connect(this.getElement('loginFormPanel'), 'onsubmit',this, 'submitHandler'); | ||
96 | |||
97 | // MochiKit.Signal.connect(this.getElement('cancel'), 'onclick',this, 'cancelHandler'); | ||
98 | MochiKit.Signal.connect('backButton', 'onclick',this, 'backHandler'); | ||
99 | |||
100 | this.addComponent(new Clipperz.PM.UI.Common.Components.ProgressBar({'element':this.getElement('progressBar')})); | ||
101 | |||
102 | // MochiKit.Style.hideElement(this.getElement('errorMessage')); | ||
103 | |||
104 | this.showLoginForm(); | ||
105 | // MochiKit.Async.callLater(0.2, MochiKit.Base.method(this, 'focusOnUsername')); | ||
106 | }, | ||
107 | |||
108 | //------------------------------------------------------------------------- | ||
109 | |||
110 | 'showLoginForm': function () { | ||
111 | MochiKit.Style.showElement(this.getElement('loginFormPanel')); | ||
112 | MochiKit.Style.hideElement(this.getElement('loginProgressPanel')); | ||
113 | MochiKit.Style.hideElement(this.getElement('loginErrorPanel')); | ||
114 | MochiKit.Style.hideElement('backButton'); | ||
115 | }, | ||
116 | |||
117 | 'slideInLoginForm': function () { | ||
118 | varoffset; | ||
119 | |||
120 | offset = ((MochiKit.DOM.getNodeAttribute(MochiKit.DOM.currentDocument().body, 'orientation') == 'portrait') ? 320 : 480); | ||
121 | |||
122 | MochiKit.Style.showElement(this.getElement('loginFormPanel')); | ||
123 | MochiKit.Style.setElementPosition(this.getElement('loginFormPanel'), {x:-offset, y:0}); | ||
124 | |||
125 | new MochiKit.Visual.Sequence([ | ||
126 | new MochiKit.Visual.Parallel([ | ||
127 | new MochiKit.Visual.Move(this.getElement('loginErrorPanel'), {x:offset, y:0, mode:'relative',transition:MochiKit.Visual.Transitions.linear, sync:true}), | ||
128 | new MochiKit.Visual.Move(this.getElement('loginFormPanel'), {x:0, y:0, mode:'absolute',transition:MochiKit.Visual.Transitions.linear, sync:true}), | ||
129 | MochiKit.Visual.fade ('backButton', { transition:MochiKit.Visual.Transitions.linear, sync:true}) | ||
130 | ], {duration:0.5, sync:true}), | ||
131 | MochiKit.Visual.fade(this.getElement('loginErrorPanel'), {duration:0, sync:true}) | ||
132 | ], {}) | ||
133 | }, | ||
134 | |||
135 | 'showLoginProgress': function () { | ||
136 | MochiKit.Style.hideElement(this.getElement('loginFormPanel')); | ||
137 | MochiKit.Style.showElement(this.getElement('loginProgressPanel')); | ||
138 | }, | ||
139 | |||
140 | 'showLoginError': function (anError) { | ||
141 | this.getElement('errorMessage').innerHTML = "Login error"; | ||
142 | |||
143 | MochiKit.Style.showElement('backButton'); | ||
144 | MochiKit.Style.hideElement(this.getElement('loginProgressPanel')); | ||
145 | MochiKit.Style.showElement(this.getElement('loginErrorPanel')); | ||
146 | MochiKit.Style.setElementPosition(this.getElement('loginErrorPanel'), {x:0, y:45}); | ||
147 | }, | ||
148 | |||
149 | //------------------------------------------------------------------------- | ||
150 | /* | ||
151 | 'disableCancelButton': function () { | ||
152 | MochiKit.DOM.hideElement(this.getElement('cancel')); | ||
153 | }, | ||
154 | */ | ||
155 | //------------------------------------------------------------------------- | ||
156 | |||
157 | 'submitHandler': function (anEvent) { | ||
158 | anEvent.preventDefault(); | ||
159 | |||
160 | MochiKit.Signal.signal(this, 'doLogin', {'username':this.username(), 'passphrase':this.passphrase()}); | ||
161 | }, | ||
162 | |||
163 | 'cancelHandler': function (anEvent) { | ||
164 | anEvent.preventDefault(); | ||
165 | |||
166 | //console.log("CANCEL"); | ||
167 | }, | ||
168 | |||
169 | 'backHandler': function (anEvent) { | ||
170 | anEvent.preventDefault(); | ||
171 | |||
172 | this.slideInLoginForm(); | ||
173 | }, | ||
174 | |||
175 | //------------------------------------------------------------------------- | ||
176 | |||
177 | __syntaxFix__: "syntax fix" | ||
178 | }); | ||
diff --git a/frontend/gamma/js/Clipperz/PM/UI/iPhone/Controllers/MainController.js b/frontend/gamma/js/Clipperz/PM/UI/iPhone/Controllers/MainController.js deleted file mode 100644 index 3fcaae1..0000000 --- a/frontend/gamma/js/Clipperz/PM/UI/iPhone/Controllers/MainController.js +++ b/dev/null | |||
@@ -1,369 +0,0 @@ | |||
1 | /* | ||
2 | |||
3 | Copyright 2008-2011 Clipperz Srl | ||
4 | |||
5 | This file is part of Clipperz Community Edition. | ||
6 | Clipperz Community Edition is an online password manager. | ||
7 | For further information about its features and functionalities please | ||
8 | refer to http://www.clipperz.com. | ||
9 | |||
10 | * Clipperz Community Edition is free software: you can redistribute | ||
11 | it and/or modify it under the terms of the GNU Affero General Public | ||
12 | License as published by the Free Software Foundation, either version | ||
13 | 3 of the License, or (at your option) any later version. | ||
14 | |||
15 | * Clipperz Community Edition is distributed in the hope that it will | ||
16 | be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
17 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
18 | See the GNU Affero General Public License for more details. | ||
19 | |||
20 | * You should have received a copy of the GNU Affero General Public | ||
21 | License along with Clipperz Community Edition. If not, see | ||
22 | <http://www.gnu.org/licenses/>. | ||
23 | |||
24 | */ | ||
25 | |||
26 | Clipperz.Base.module('Clipperz.PM.UI.iPhone.Controllers'); | ||
27 | |||
28 | //Some parts of this controller have been derived from the iUI library. | ||
29 | |||
30 | Clipperz.PM.UI.iPhone.Controllers.MainController = function() { | ||
31 | this._loginForm = null; | ||
32 | this._cardList = null; | ||
33 | this._cachedValues =null; | ||
34 | this._user = null; | ||
35 | |||
36 | if (typeof window.onorientationchange == 'object') { | ||
37 | MochiKit.Signal.connect(window, 'onorientationchange', this, 'orientationChangeHandler'); | ||
38 | MochiKit.Async.callLater(0, MochiKit.Base.method(this, 'orientationChangeHandler')); | ||
39 | } else { | ||
40 | this.setOrientation('portrait'); | ||
41 | // this.setOrientation('landscape'); | ||
42 | } | ||
43 | |||
44 | this.addMetaTag('viewport', 'width=devicewidth; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;'); | ||
45 | this.addMetaTag('apple-mobile-web-app-capable', 'yes'); | ||
46 | this.addMetaTag('apple-mobile-web-app-status-bar-style', 'black'); | ||
47 | |||
48 | this.addLinkTag('apple-touch-icon', 'data:image/png;charset=utf-8;base64,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'); | ||
49 | //this.addLinkTag('apple-touch-startup-image', 'default.png'); | ||
50 | |||
51 | // if (!window.navigator.standalone)// not running as an installed app | ||
52 | |||
53 | MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'selectedDirectLogin', this, 'selectedDirectLoginHandler'); | ||
54 | |||
55 | MochiKit.DOM.addElementClass(document.body, 'iPhone'); | ||
56 | return this; | ||
57 | } | ||
58 | |||
59 | MochiKit.Base.update(Clipperz.PM.UI.iPhone.Controllers.MainController.prototype, { | ||
60 | |||
61 | 'toString': function () { | ||
62 | return "Clipperz.PM.UI.iPhone.Controllers.MainController"; | ||
63 | }, | ||
64 | |||
65 | //========================================================================= | ||
66 | |||
67 | 'user': function () { | ||
68 | return this._user; | ||
69 | }, | ||
70 | |||
71 | 'setUser': function (aValue) { | ||
72 | this._user = aValue; | ||
73 | }, | ||
74 | |||
75 | //========================================================================= | ||
76 | |||
77 | 'loginForm': function() { | ||
78 | if (this._loginForm == null) { | ||
79 | MochiKit.DOM.removeElement('mainDiv'); | ||
80 | this._loginForm = new Clipperz.PM.UI.iPhone.Components.LoginForm({element:MochiKit.DOM.currentDocument().body}); | ||
81 | MochiKit.Signal.connect(this._loginForm, 'doLogin', this, 'doLoginHandler') | ||
82 | } | ||
83 | |||
84 | return this._loginForm; | ||
85 | }, | ||
86 | |||
87 | 'removeLoginForm': function () { | ||
88 | if (this._loginForm != null) { | ||
89 | this._loginForm.remove(); | ||
90 | this._loginForm = null; | ||
91 | } | ||
92 | }, | ||
93 | |||
94 | //----------------------------------------------------------------------------- | ||
95 | |||
96 | 'cardList': function () { | ||
97 | if (this._cardList == null) { | ||
98 | this._cardList = new Clipperz.PM.UI.iPhone.Components.CardList({element:MochiKit.DOM.currentDocument().body}); | ||
99 | MochiKit.Signal.connect(this._cardList, 'searchEvent',this, 'searchEventHandler') | ||
100 | MochiKit.Signal.connect(this._cardList, 'selectedCard',this, 'selecetedCardHandler') | ||
101 | } | ||
102 | |||
103 | return this._cardList; | ||
104 | }, | ||
105 | |||
106 | //========================================================================= | ||
107 | |||
108 | 'currentWidth': function () { | ||
109 | return this._currentWidth; | ||
110 | }, | ||
111 | |||
112 | 'setCurrentWidth': function (aValue) { | ||
113 | this._currentWidth = aValue; | ||
114 | }, | ||
115 | |||
116 | //========================================================================= | ||
117 | |||
118 | 'orientationChangeHandler': function () { | ||
119 | switch(window.orientation) { | ||
120 | case 0: | ||
121 | this.setOrientation('portrait'); | ||
122 | break; | ||
123 | case 90: | ||
124 | case -90: | ||
125 | this.setOrientation('landscape'); | ||
126 | break; | ||
127 | } | ||
128 | }, | ||
129 | |||
130 | //------------------------------------------------------------------------- | ||
131 | |||
132 | 'setOrientation': function (anOrientation) { | ||
133 | document.body.setAttribute('orientation', anOrientation); | ||
134 | setTimeout(scrollTo, 100, 0, 1); | ||
135 | }, | ||
136 | |||
137 | //------------------------------------------------------------------------- | ||
138 | |||
139 | 'slidePages': function (fromPage, toPage, backwards) { | ||
140 | var axis; | ||
141 | var slideDone; | ||
142 | |||
143 | slideDone = function () { | ||
144 | // console.log("slideDone"); | ||
145 | if (!hasClass(toPage, "dialog")) { | ||
146 | fromPage.removeAttribute("selected"); | ||
147 | } | ||
148 | checkTimer = setInterval(checkOrientAndLocation, 300); | ||
149 | setTimeout(updatePage, 0, toPage, fromPage); | ||
150 | fromPage.removeEventListener('webkitTransitionEnd', slideDone, false); | ||
151 | } | ||
152 | |||
153 | axis = (backwards ? fromPage : toPage).getAttribute("axis"); | ||
154 | |||
155 | clearInterval(checkTimer); | ||
156 | |||
157 | if (canDoSlideAnim() && axis != 'y') { | ||
158 | slide2(fromPage, toPage, backwards, slideDone); | ||
159 | } else { | ||
160 | slide1(fromPage, toPage, backwards, axis, slideDone); | ||
161 | } | ||
162 | }, | ||
163 | |||
164 | //------------------------------------------------------------------------- | ||
165 | |||
166 | 'getCachedValues': function () { | ||
167 | var deferredResult; | ||
168 | |||
169 | if (this._cachedObjects != null) { | ||
170 | deferredResult = MochiKit.Async.succeed(this._cachedObjects); | ||
171 | } else { | ||
172 | deferredResult = new Clipperz.Async.Deferred("MainController.getCachedValues", {trace:false}); | ||
173 | deferredResult.addMethod(this.user(), 'getRecords'); | ||
174 | deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("MainController.getCachedValues - collectResults", { | ||
175 | '_rowObject': MochiKit.Async.succeed, | ||
176 | '_reference': MochiKit.Base.methodcaller('reference'), | ||
177 | 'label': MochiKit.Base.methodcaller('label'), | ||
178 | 'favicon': MochiKit.Base.methodcaller('favicon'), | ||
179 | '_searchableContent':MochiKit.Base.methodcaller('searchableContent') | ||
180 | }, {trace:false})); | ||
181 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
182 | deferredResult.addCallback(MochiKit.Base.bind(function (someRows) { | ||
183 | this._cachedObjects = someRows; | ||
184 | return this._cachedObjects; | ||
185 | }, this)); | ||
186 | deferredResult.callback(); | ||
187 | } | ||
188 | |||
189 | return deferredResult; | ||
190 | }, | ||
191 | //========================================================================= | ||
192 | |||
193 | 'run': function(shouldShowRegistrationForm) { | ||
194 | this.loginForm().render(); | ||
195 | MochiKit.Async.callLater(1, MochiKit.Base.method(this.loginForm(), 'focusOnUsername')); | ||
196 | }, | ||
197 | |||
198 | //========================================================================= | ||
199 | |||
200 | 'doLoginHandler': function (someArgs) { | ||
201 | var deferredResult; | ||
202 | varparameters; | ||
203 | varshouldUseOTP; | ||
204 | // var loginProgress; | ||
205 | varuser; | ||
206 | var getPassphraseDelegate; | ||
207 | |||
208 | parameters = someArgs; | ||
209 | shouldUseOTP = (typeof(parameters.passphrase) == 'undefined'); | ||
210 | |||
211 | getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, parameters.passphrase); | ||
212 | user = new Clipperz.PM.DataModel.User({'username':parameters.username, 'getPassphraseFunction':getPassphraseDelegate}); | ||
213 | |||
214 | deferredResult = new Clipperz.Async.Deferred("MainController.doLogin", {trace:false}); | ||
215 | deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress', {'steps':4}); | ||
216 | deferredResult.addMethod(this.loginForm(), 'showLoginProgress'); | ||
217 | deferredResult.addCallback(MochiKit.Async.wait, 0.1); | ||
218 | deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection'); | ||
219 | deferredResult.addMethod(user, 'login'); | ||
220 | deferredResult.addMethod(this, 'setUser', user); | ||
221 | deferredResult.addMethod(user, 'getRecords'); | ||
222 | deferredResult.addMethod(this, 'removeLoginForm'); | ||
223 | deferredResult.addMethod(this.cardList(), 'render'); | ||
224 | deferredResult.addMethod(this, 'displaySelectedRecords', ''); | ||
225 | deferredResult.addErrback(MochiKit.Base.method(this.loginForm(), 'showLoginError')); | ||
226 | deferredResult.callback(); | ||
227 | |||
228 | return deferredResult; | ||
229 | }, | ||
230 | |||
231 | //========================================================================= | ||
232 | |||
233 | 'searchEventHandler': function (aValue) { | ||
234 | //console.log("searching for ... " + aValue); | ||
235 | return this.displaySelectedRecords(aValue); | ||
236 | }, | ||
237 | |||
238 | //========================================================================= | ||
239 | |||
240 | '_displaySelectedRows': function (aFilter, someRows) { | ||
241 | var result; | ||
242 | |||
243 | result = someRows; | ||
244 | |||
245 | if (aFilter != null) { | ||
246 | var filter; | ||
247 | varfilterRegExp; | ||
248 | |||
249 | filter = aFilter.replace(/[^A-Za-z0-9]/g, "\\$&"); | ||
250 | filterRegExp = new RegExp(filter, "i"); | ||
251 | result = MochiKit.Base.filter(function (aCachedResult) { return filterRegExp.test(aCachedResult['_searchableContent'])}, result); | ||
252 | } | ||
253 | |||
254 | |||
255 | result.sort(MochiKit.Base.partial(function (aKey, aComparator, aObject, bObject) { | ||
256 | return aComparator(aObject[aKey], bObject[aKey]); | ||
257 | }, 'label', Clipperz.Base.caseInsensitiveCompare)); | ||
258 | |||
259 | this.cardList().update(result); | ||
260 | }, | ||
261 | |||
262 | //------------------------------------------------------------------------- | ||
263 | |||
264 | 'displaySelectedRecords': function (aFilter) { | ||
265 | return Clipperz.Async.callbacks("MainController.displaySelectedrows", [ | ||
266 | MochiKit.Base.method(this, 'getCachedValues'), | ||
267 | MochiKit.Base.method(this, '_displaySelectedRows', aFilter) | ||
268 | ], {trace:false}); | ||
269 | }, | ||
270 | |||
271 | //========================================================================= | ||
272 | |||
273 | 'selecetedCardHandler': function (aRecordReference) { | ||
274 | vardeferredResult; | ||
275 | varrecordData; | ||
276 | |||
277 | recordData = {}; | ||
278 | //console.log("Showing detail for card with reference", aRecordReference); | ||
279 | deferredResult = new Clipperz.Async.Deferred("MainController.selectedCardHandler", {trace:false}); | ||
280 | deferredResult.addMethod(this.user(), 'getRecord', aRecordReference); | ||
281 | deferredResult.collectResults({ | ||
282 | '_reference':MochiKit.Base.methodcaller('reference'), | ||
283 | 'title': MochiKit.Base.methodcaller('label'), | ||
284 | 'favicon': MochiKit.Base.methodcaller('favicon') | ||
285 | }); | ||
286 | deferredResult.addCallback(function (someData) { | ||
287 | MochiKit.Base.update(recordData, someData); | ||
288 | }) | ||
289 | deferredResult.addMethod(this.cardList(), 'showCard', recordData); | ||
290 | |||
291 | deferredResult.addMethod(this.user(), 'getRecord', aRecordReference); | ||
292 | deferredResult.addMethodcaller('notes'); | ||
293 | deferredResult.addCallback(function (someNotes) { | ||
294 | recordData['notes'] = someNotes; | ||
295 | }) | ||
296 | |||
297 | deferredResult.addMethod(this.user(), 'getRecord', aRecordReference); | ||
298 | deferredResult.addMethodcaller('getCurrentRecordVersion'); | ||
299 | deferredResult.addMethodcaller('fields'); | ||
300 | deferredResult.addCallback(MochiKit.Base.values); | ||
301 | deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("MainController.selectedCardHandler - fields", { | ||
302 | 'label':MochiKit.Base.methodcaller('label'), | ||
303 | 'value':MochiKit.Base.methodcaller('value'), | ||
304 | 'isHidden':MochiKit.Base.methodcaller('isHidden') | ||
305 | }, {trace:false})); | ||
306 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
307 | deferredResult.addCallback(function (someData) { | ||
308 | recordData['fields'] = someData; | ||
309 | }); | ||
310 | |||
311 | deferredResult.addMethod(this.user(), 'getRecord', aRecordReference); | ||
312 | deferredResult.addMethodcaller('directLogins'); | ||
313 | deferredResult.addCallback(MochiKit.Base.values); | ||
314 | deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("MainController.selectedCardHandler - directLogins", { | ||
315 | 'label': MochiKit.Base.methodcaller('label'), | ||
316 | 'favicon': MochiKit.Base.methodcaller('favicon'), | ||
317 | '_reference':MochiKit.Base.methodcaller('reference') | ||
318 | }, {trace:false})); | ||
319 | deferredResult.addCallback(Clipperz.Async.collectAll); | ||
320 | deferredResult.addCallback(function (someData) { | ||
321 | recordData['directLogins'] = someData; | ||
322 | }); | ||
323 | |||
324 | deferredResult.addMethod(this.cardList(), 'showCardDetails', recordData); | ||
325 | deferredResult.callback(); | ||
326 | |||
327 | return deferredResult; | ||
328 | }, | ||
329 | |||
330 | //========================================================================= | ||
331 | |||
332 | 'selectedDirectLoginHandler': function (someData) { | ||
333 | vardeferredResult; | ||
334 | |||
335 | //console.log("<<< signal - directLogin"); | ||
336 | deferredResult = new Clipperz.Async.Deferred("MainController.selectedDirectLoginHandler", {trace:false}); | ||
337 | deferredResult.addMethod(this.user(), 'getRecord', someData['cardReference']); | ||
338 | deferredResult.addMethodcaller('directLogins'); | ||
339 | deferredResult.addCallback(MochiKit.Base.itemgetter(someData['directLoginReference'])); | ||
340 | // deferredResult.addMethodcaller('runDirectLogin'); | ||
341 | deferredResult.addCallback(Clipperz.PM.UI.Common.Controllers.DirectLoginRunner.openDirectLogin); | ||
342 | deferredResult.callback(); | ||
343 | |||
344 | return deferredResult; | ||
345 | }, | ||
346 | |||
347 | //========================================================================= | ||
348 | |||
349 | 'addMetaTag': function (aName, aContent) { | ||
350 | varmetaTag; | ||
351 | |||
352 | metaTag = document.createElement('meta'); | ||
353 | metaTag.name = aName; | ||
354 | metaTag.content = aContent; | ||
355 | document.getElementsByTagName('head')[0].appendChild(metaTag); | ||
356 | }, | ||
357 | |||
358 | 'addLinkTag': function (aRel, anHref) { | ||
359 | var linkTag; | ||
360 | |||
361 | linkTag = document.createElement('link'); | ||
362 | linkTag.rel = aRel; | ||
363 | linkTag.href = anHref; | ||
364 | document.getElementsByTagName('head')[0].appendChild(linkTag); | ||
365 | }, | ||
366 | |||
367 | //========================================================================= | ||
368 | __syntaxFix__: "syntax fix" | ||
369 | }); \ No newline at end of file | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.actionsheet.js b/frontend/gamma/js/JQTouch/extensions/jqt.actionsheet.js new file mode 100644 index 0000000..2a5f8d1 --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.actionsheet.js | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
12 | |||
13 | (c) 2012 by jQTouch project members. | ||
14 | See LICENSE.txt for license. | ||
15 | |||
16 | Author: Thomas Yip | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | |||
21 | _/ _/_/ _/_/_/_/_/ _/ | ||
22 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
23 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
24 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
25 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
26 | _/ | ||
27 | _/ | ||
28 | |||
29 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
30 | |||
31 | (c) 2012 by jQTouch project members. | ||
32 | See LICENSE.txt for license. | ||
33 | |||
34 | Author: Thomas Yip | ||
35 | */ | ||
36 | |||
37 | (function($) { | ||
38 | var src = $("head script").last().attr("src") || ''; | ||
39 | var scriptpath = src.split('?')[0].split('/').slice(0, -1).join('/')+'/'; | ||
40 | var csspath = scriptpath + 'jqt.actionsheet.css'; | ||
41 | var link = $('<link href="' + csspath + '" rel="stylesheet">'); | ||
42 | $('head').append($(link)); | ||
43 | |||
44 | function hide(callback) { | ||
45 | var $target = $(this); | ||
46 | var data = $(this).data('actionsheet'); | ||
47 | var $source = data.source; | ||
48 | |||
49 | var timeout; | ||
50 | |||
51 | function cleanup() { | ||
52 | clearTimeout(timeout); | ||
53 | |||
54 | $source.removeClass('transition'); | ||
55 | $target.removeClass('inmotion transition'); | ||
56 | !callback || callback.apply(this, arguments); | ||
57 | }; | ||
58 | timeout = setTimeout(cleanup, 500); | ||
59 | |||
60 | if (data.shown) { | ||
61 | $(this).data('actionsheet', {}); | ||
62 | $target.one('webkitTransitionEnd', cleanup); | ||
63 | |||
64 | $source.addClass('transition'); | ||
65 | $target.removeClass('current').addClass('inmotion transition'); | ||
66 | $('#jqt').removeClass('actionopened'); | ||
67 | } | ||
68 | return $target; | ||
69 | } | ||
70 | |||
71 | function show(callback) { | ||
72 | var $target = $(this); | ||
73 | var data = $(this).data('actionsheet') || {}; | ||
74 | if (!data.shown) { | ||
75 | var $source = $('#jqt .current:not(.actionsheet)'); | ||
76 | |||
77 | $target.one('webkitTransitionEnd', function() { | ||
78 | $source.removeClass('transition'); | ||
79 | $target.removeClass('inmotion transition'); | ||
80 | !callback || callback.apply(this, arguments); | ||
81 | }); | ||
82 | |||
83 | data.shown = true; | ||
84 | data.source = $source; | ||
85 | $(this).data('actionsheet', data); | ||
86 | |||
87 | $source.addClass('transition'); | ||
88 | $target.addClass('inmotion transition'); | ||
89 | $('#jqt').addClass('actionopened'); | ||
90 | setTimeout(function() { | ||
91 | $target.addClass('current'); | ||
92 | }, 50); | ||
93 | } | ||
94 | return $target; | ||
95 | } | ||
96 | |||
97 | var methods = { | ||
98 | init: function(options) { | ||
99 | $(this).addClass('actionsheet'); | ||
100 | $(this).data({shown: false}); | ||
101 | }, | ||
102 | show: show, | ||
103 | hide: hide | ||
104 | }; | ||
105 | |||
106 | $.fn.actionsheet = function(method) { | ||
107 | if (methods[method]) { | ||
108 | if ($(this).is('.actionsheet')) { | ||
109 | return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); | ||
110 | } else { | ||
111 | var msg = 'Target is not a `actionsheet`. Action `' + method + '` is ignored.'; | ||
112 | console.warn(msg); | ||
113 | } | ||
114 | } else if ( typeof method === 'object' || ! method ) { | ||
115 | return methods.init.apply(this, arguments); | ||
116 | } else { | ||
117 | $.error( 'Method ' + method + ' does not exist on jQuery.tooltip' ); | ||
118 | } | ||
119 | }; | ||
120 | |||
121 | if ($.jQTouch) { | ||
122 | $.jQTouch.addTapHandler({ | ||
123 | name: 'open-actionsheet', | ||
124 | isSupported: function(e, params) { | ||
125 | return params.$el.is('.action'); | ||
126 | }, | ||
127 | fn: function(e, params) { | ||
128 | params.$el.removeClass('active'); | ||
129 | |||
130 | var $target = $(params.hash); | ||
131 | $target.actionsheet('show'); | ||
132 | |||
133 | return false; | ||
134 | } | ||
135 | }); | ||
136 | $.jQTouch.addTapHandler({ | ||
137 | name: 'follow-actionlink', | ||
138 | isSupported: function(e, params) { | ||
139 | if ($('#jqt').hasClass('actionopened')) { | ||
140 | return params.$el.is('.actionsheet a'); | ||
141 | } | ||
142 | return false; | ||
143 | }, | ||
144 | fn: function(e, params) { | ||
145 | params.$el.removeClass('active'); | ||
146 | |||
147 | var $target = params.$el.closest('.actionsheet'); | ||
148 | $target.actionsheet('hide', function() { | ||
149 | if (!params.$el.is('.dismiss')) { | ||
150 | params.$el.trigger('tap'); | ||
151 | } | ||
152 | }); | ||
153 | return false; | ||
154 | } | ||
155 | }); | ||
156 | } else { | ||
157 | console.error('Extension `jqt.actionsheet` failed to load. jQT not found'); | ||
158 | } | ||
159 | })($); | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.autotitles.js b/frontend/gamma/js/JQTouch/extensions/jqt.autotitles.js new file mode 100644 index 0000000..94f3d9b --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.autotitles.js | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Created by David Kaneda <http://www.davidkaneda.com> | ||
12 | Maintained by Thomas Yip <http://beedesk.com/> | ||
13 | Sponsored by Sencha Labs <http://www.sencha.com/> | ||
14 | Special thanks to Jonathan Stark <http://www.jonathanstark.com/> | ||
15 | |||
16 | Documentation and issue tracking on GitHub <http://github.com/senchalabs/jQTouch/> | ||
17 | |||
18 | (c) 2009-2011 Sencha Labs | ||
19 | jQTouch may be freely distributed under the MIT license. | ||
20 | |||
21 | */ | ||
22 | |||
23 | (function($) { | ||
24 | if ($.jQTouch) | ||
25 | { | ||
26 | $.jQTouch.addExtension(function AutoTitles(jQT){ | ||
27 | |||
28 | var titleSelector='.toolbar h1'; | ||
29 | |||
30 | $(function(){ | ||
31 | $('#jqt').bind('pageAnimationStart', function(e, data){ | ||
32 | if (data.direction === 'in'){ | ||
33 | var $title = $(titleSelector, $(e.target)); | ||
34 | var $ref = $(e.target).data('referrer'); | ||
35 | if ($title.length && $ref && $title.text() === ''){ | ||
36 | $title.html($ref.text()); | ||
37 | } | ||
38 | } | ||
39 | }); | ||
40 | }); | ||
41 | |||
42 | function setTitleSelector(ts){ | ||
43 | titleSelector=ts; | ||
44 | } | ||
45 | |||
46 | return { | ||
47 | setTitleSelector: setTitleSelector | ||
48 | }; | ||
49 | |||
50 | }); | ||
51 | } | ||
52 | })($); | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.floaty.js b/frontend/gamma/js/JQTouch/extensions/jqt.floaty.js new file mode 100644 index 0000000..c7e4485 --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.floaty.js | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Created by David Kaneda <http://www.davidkaneda.com> | ||
12 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
13 | |||
14 | Special thanks to Jonathan Stark <http://jonathanstark.com/> | ||
15 | and pinch/zoom <http://www.pinchzoom.com/> | ||
16 | |||
17 | (c) 2009 by jQTouch project members. | ||
18 | See LICENSE.txt for license. | ||
19 | |||
20 | */ | ||
21 | |||
22 | (function($) { | ||
23 | if ($.jQTouch) | ||
24 | { | ||
25 | $.jQTouch.addExtension(function Floaty(jQT){ | ||
26 | |||
27 | $.fn.makeFloaty = function(options){ | ||
28 | var defaults = { | ||
29 | align: 'top', | ||
30 | spacing: 20, | ||
31 | time: '.3s' | ||
32 | }; | ||
33 | |||
34 | var settings = $.extend({}, defaults, options); | ||
35 | |||
36 | settings.align = (settings.align == 'top') ? 'top' : 'bottom'; | ||
37 | |||
38 | return this.each(function(){ | ||
39 | var $el = $(this); | ||
40 | |||
41 | $el.css({ | ||
42 | '-webkit-transition': 'top ' + settings.time + ' ease-in-out', | ||
43 | 'display': 'block', | ||
44 | 'min-height': '0 !important' | ||
45 | }).data('settings', settings); | ||
46 | |||
47 | $(document).scroll(function(){ | ||
48 | if ($el.data('floatyVisible') === 'true') | ||
49 | { | ||
50 | $el.scrollFloaty(); | ||
51 | } | ||
52 | }); | ||
53 | $el.scrollFloaty(); | ||
54 | }); | ||
55 | }; | ||
56 | |||
57 | $.fn.scrollFloaty = function(){ | ||
58 | |||
59 | |||
60 | return this.each(function(){ | ||
61 | var $el = $(this); | ||
62 | var settings = $el.data('settings'); // Settings not being set as object w/Zepto | ||
63 | var wHeight = $('html').attr('clientHeight'); // WRONG | ||
64 | |||
65 | var newY = window.pageYOffset + | ||
66 | ((settings.align == 'top') ? | ||
67 | settings.spacing : wHeight - settings.spacing - $el.get(0).offsetHeight); | ||
68 | |||
69 | $el.css('top', newY).data('floatyVisible', true); | ||
70 | }); | ||
71 | }; | ||
72 | |||
73 | $.fn.hideFloaty = function(){ | ||
74 | return this.each(function(){ | ||
75 | var $el = $(this); | ||
76 | var oh = $el.get(0).offsetHeight; | ||
77 | |||
78 | $el.css('top', -oh-10).data('floatyVisible', false); | ||
79 | }); | ||
80 | }; | ||
81 | |||
82 | $.fn.toggleFloaty = function(){ | ||
83 | return this.each(function(){ | ||
84 | var $el = $(this); | ||
85 | if ($el.data('floatyVisible') === 'true'){ | ||
86 | $el.hideFloaty(); | ||
87 | } | ||
88 | else | ||
89 | { | ||
90 | $el.scrollFloaty(); | ||
91 | } | ||
92 | }); | ||
93 | }; | ||
94 | }); | ||
95 | } | ||
96 | })($); \ No newline at end of file | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.location.js b/frontend/gamma/js/JQTouch/extensions/jqt.location.js new file mode 100644 index 0000000..9d53a1a --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.location.js | |||
@@ -0,0 +1,51 @@ | |||
1 | (function($) { | ||
2 | if ($.jQTouch) | ||
3 | { | ||
4 | $.jQTouch.addExtension(function Location(){ | ||
5 | |||
6 | var latitude, longitude, callback, callback2; | ||
7 | |||
8 | function updateLocation(fn, fn2) { | ||
9 | if (navigator.geolocation) | ||
10 | { | ||
11 | callback = fn; | ||
12 | callback2 = fn2; | ||
13 | navigator.geolocation.getCurrentPosition(savePosition, failResponse); | ||
14 | return true; | ||
15 | } else { | ||
16 | console.log('Device not capable of geo-location.'); | ||
17 | fn(false); | ||
18 | return false; | ||
19 | } | ||
20 | } | ||
21 | function failResponse(error){ | ||
22 | if (callback2) { | ||
23 | callback2(error); | ||
24 | } | ||
25 | } | ||
26 | function savePosition(position) { | ||
27 | latitude = position.coords.latitude; | ||
28 | longitude = position.coords.longitude; | ||
29 | if (callback) { | ||
30 | callback(getLocation()); | ||
31 | } | ||
32 | } | ||
33 | function getLocation() { | ||
34 | if (latitude && longitude) { | ||
35 | return { | ||
36 | latitude: latitude, | ||
37 | longitude: longitude | ||
38 | }; | ||
39 | |||
40 | } else { | ||
41 | console.log('No location available. Try calling updateLocation() first.'); | ||
42 | return false; | ||
43 | } | ||
44 | } | ||
45 | return { | ||
46 | updateLocation: updateLocation, | ||
47 | getLocation: getLocation | ||
48 | }; | ||
49 | }); | ||
50 | } | ||
51 | })($); \ No newline at end of file | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.menusheet.js b/frontend/gamma/js/JQTouch/extensions/jqt.menusheet.js new file mode 100644 index 0000000..8d21aca --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.menusheet.js | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
12 | |||
13 | (c) 2012 by jQTouch project members. | ||
14 | See LICENSE.txt for license. | ||
15 | |||
16 | Author: Thomas Yip | ||
17 | */ | ||
18 | |||
19 | (function($) { | ||
20 | var src = $("head script").last().attr("src") || ''; | ||
21 | var scriptpath = src.split('?')[0].split('/').slice(0, -1).join('/')+'/'; | ||
22 | var csspath = scriptpath + 'jqt.menusheet.css'; | ||
23 | var link = $('<link href="' + csspath + '" rel="stylesheet">'); | ||
24 | $('head').append($(link)); | ||
25 | |||
26 | function hide(callback) { | ||
27 | var $target = $(this); | ||
28 | var data = $(this).data('menusheet'); | ||
29 | if (data.shown) { | ||
30 | $(this).data('menusheet', {}); | ||
31 | var $source = data.source; | ||
32 | $source.unbind('touchstart mousedown', data.closehandler); | ||
33 | $source.one('webkitTransitionEnd', function() { | ||
34 | $source.removeClass('inmotion transition in'); | ||
35 | $target.removeClass('inmotion out'); | ||
36 | !callback || callback.apply(this, arguments); | ||
37 | }); | ||
38 | |||
39 | $source.addClass('inmotion transition in'); | ||
40 | $target.addClass('inmotion out').removeClass('current'); | ||
41 | $('#jqt').removeClass('menuopened'); | ||
42 | } | ||
43 | return $target; | ||
44 | } | ||
45 | |||
46 | function show(callback) { | ||
47 | var $target = $(this); | ||
48 | var data = $(this).data('menusheet') || {}; | ||
49 | if (!data.shown) { | ||
50 | var $source = $('#jqt .current:not(.menusheet)'); | ||
51 | var closehandler = function() { | ||
52 | $target.menusheet('hide'); | ||
53 | return false; | ||
54 | }; | ||
55 | |||
56 | $source.one('webkitTransitionEnd', function() { | ||
57 | $source.one('touchstart mousedown', closehandler); | ||
58 | $source.removeClass('inmotion transition out'); | ||
59 | $target.removeClass('inmotion in'); | ||
60 | !callback || callback.apply(this, arguments); | ||
61 | }); | ||
62 | |||
63 | data.shown = true; | ||
64 | data.closehandler = closehandler; | ||
65 | data.source = $source; | ||
66 | $(this).data('menusheet', data); | ||
67 | |||
68 | $source.addClass('inmotion transition out'); | ||
69 | $target.addClass('current in'); | ||
70 | $('#jqt').addClass('menuopened'); | ||
71 | } | ||
72 | return $target; | ||
73 | } | ||
74 | |||
75 | var methods = { | ||
76 | init: function(options) { | ||
77 | $(this).addClass('menusheet'); | ||
78 | $(this).data({shown: false}); | ||
79 | }, | ||
80 | show: show, | ||
81 | hide: hide | ||
82 | }; | ||
83 | |||
84 | $.fn.menusheet = function(method) { | ||
85 | if (methods[method]) { | ||
86 | if ($(this).is('.menusheet')) { | ||
87 | return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); | ||
88 | } else { | ||
89 | var msg = 'Target is not a `menusheet`. Action `' + method + '` is ignored.'; | ||
90 | console.warn(msg); | ||
91 | } | ||
92 | } else if ( typeof method === 'object' || ! method ) { | ||
93 | return methods.init.apply(this, arguments); | ||
94 | } else { | ||
95 | $.error( 'Method ' + method + ' does not exist on jQuery.tooltip' ); | ||
96 | } | ||
97 | }; | ||
98 | |||
99 | if ($.jQTouch) { | ||
100 | $.jQTouch.addTapHandler({ | ||
101 | name: 'open-menusheet', | ||
102 | isSupported: function(e, params) { | ||
103 | return params.$el.is('.menu'); | ||
104 | }, | ||
105 | fn: function(e, params) { | ||
106 | params.$el.removeClass('active'); | ||
107 | |||
108 | var $target = $(params.hash); | ||
109 | $target.menusheet('show'); | ||
110 | |||
111 | return false; | ||
112 | } | ||
113 | }); | ||
114 | $.jQTouch.addTapHandler({ | ||
115 | name: 'follow-menulink', | ||
116 | isSupported: function(e, params) { | ||
117 | if ($('#jqt').hasClass('menuopened')) { | ||
118 | return params.$el.is('.menusheet a'); | ||
119 | } | ||
120 | return false; | ||
121 | }, | ||
122 | fn: function(e, params) { | ||
123 | params.$el.removeClass('active'); | ||
124 | |||
125 | var $target = params.$el.closest('.menusheet'); | ||
126 | $target.menusheet('hide', function() { | ||
127 | if (!params.$el.is('.dismiss')) { | ||
128 | params.$el.trigger('tap'); | ||
129 | } | ||
130 | }); | ||
131 | return false; | ||
132 | } | ||
133 | }); | ||
134 | } else { | ||
135 | console.error('Extension `jqt.menusheet` failed to load. jQT not found'); | ||
136 | } | ||
137 | })($); | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.offline.js b/frontend/gamma/js/JQTouch/extensions/jqt.offline.js new file mode 100644 index 0000000..b333a16 --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.offline.js | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Created by David Kaneda <http://www.davidkaneda.com> | ||
12 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
13 | |||
14 | Special thanks to Jonathan Stark <http://jonathanstark.com/> | ||
15 | |||
16 | Lots of this code is specifically derived from Jonathan's book, | ||
17 | "Building iPhone Apps with HTML, CSS, and JavaScript" | ||
18 | |||
19 | (c) 2009 by jQTouch project members. | ||
20 | See LICENSE.txt for license. | ||
21 | |||
22 | */ | ||
23 | |||
24 | (function($) { | ||
25 | if ($.jQTouch) | ||
26 | { | ||
27 | $.jQTouch.addExtension(function Offline(){ | ||
28 | |||
29 | // Convenience array of status values | ||
30 | var cacheStatusValues = []; | ||
31 | cacheStatusValues[0] = 'uncached'; | ||
32 | cacheStatusValues[1] = 'idle'; | ||
33 | cacheStatusValues[2] = 'checking'; | ||
34 | cacheStatusValues[3] = 'downloading'; | ||
35 | cacheStatusValues[4] = 'updateready'; | ||
36 | cacheStatusValues[5] = 'obsolete'; | ||
37 | |||
38 | // Listeners for all possible events | ||
39 | var cache = window.applicationCache; | ||
40 | cache.addEventListener('cached', logEvent, false); | ||
41 | cache.addEventListener('checking', logEvent, false); | ||
42 | cache.addEventListener('downloading', logEvent, false); | ||
43 | cache.addEventListener('error', logEvent, false); | ||
44 | cache.addEventListener('noupdate', logEvent, false); | ||
45 | cache.addEventListener('obsolete', logEvent, false); | ||
46 | cache.addEventListener('progress', logEvent, false); | ||
47 | cache.addEventListener('updateready', logEvent, false); | ||
48 | |||
49 | // Log every event to the console | ||
50 | function logEvent(e) { | ||
51 | var online, status, type, message; | ||
52 | online = (isOnline()) ? 'yes' : 'no'; | ||
53 | status = cacheStatusValues[cache.status]; | ||
54 | type = e.type; | ||
55 | message = 'online: ' + online; | ||
56 | message+= ', event: ' + type; | ||
57 | message+= ', status: ' + status; | ||
58 | if (type == 'error' && navigator.onLine) { | ||
59 | message+= ' There was an unknown error, check your Cache Manifest.'; | ||
60 | } | ||
61 | console.log(message); | ||
62 | } | ||
63 | |||
64 | function isOnline() { | ||
65 | return navigator.onLine; | ||
66 | } | ||
67 | |||
68 | if (!$('html').attr('manifest')) { | ||
69 | console.log('No Cache Manifest listed on the <html> tag.') | ||
70 | } | ||
71 | |||
72 | // Swap in newly download files when update is ready | ||
73 | cache.addEventListener('updateready', function(e){ | ||
74 | // Don't perform "swap" if this is the first cache | ||
75 | if (cacheStatusValues[cache.status] != 'idle') { | ||
76 | cache.swapCache(); | ||
77 | console.log('Swapped/updated the Cache Manifest.'); | ||
78 | } | ||
79 | } | ||
80 | , false); | ||
81 | |||
82 | // These two functions check for updates to the manifest file | ||
83 | function checkForUpdates(){ | ||
84 | cache.update(); | ||
85 | } | ||
86 | function autoCheckForUpdates(){ | ||
87 | setInterval(function(){cache.update()}, 10000); | ||
88 | } | ||
89 | |||
90 | return { | ||
91 | isOnline: isOnline, | ||
92 | checkForUpdates: checkForUpdates, | ||
93 | autoCheckForUpdates: autoCheckForUpdates | ||
94 | } | ||
95 | }); | ||
96 | } | ||
97 | })(jQuery); \ No newline at end of file | ||
diff --git a/frontend/gamma/js/JQTouch/extensions/jqt.themeswitcher.js b/frontend/gamma/js/JQTouch/extensions/jqt.themeswitcher.js new file mode 100755 index 0000000..ef3a75d --- a/dev/null +++ b/frontend/gamma/js/JQTouch/extensions/jqt.themeswitcher.js | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Documentation and issue tracking on Google Code <http://code.google.com/p/jqtouch/> | ||
12 | |||
13 | (c) 2011 by jQTouch project members. | ||
14 | See LICENSE.txt for license. | ||
15 | |||
16 | */ | ||
17 | |||
18 | (function($) { | ||
19 | if ($.jQTouch) { | ||
20 | |||
21 | var scriptpath = $("script").last().attr("src").split('?')[0].split('/').slice(0, -1).join('/')+'/'; | ||
22 | |||
23 | $.jQTouch.addExtension(function ThemeSwitcher(jQT) { | ||
24 | |||
25 | var current, | ||
26 | link, | ||
27 | titles = {}, | ||
28 | defaults = { | ||
29 | themeStyleSelector: 'link[rel="stylesheet"][title]', | ||
30 | themeIncluded: [ | ||
31 | {title: 'jQTouch', href: scriptpath + '../themes/css/jqtouch.css'}, | ||
32 | {title: 'Apple', href: scriptpath + '../themes/css/apple.css'}, | ||
33 | {title: 'Vanilla', href: scriptpath + '../themes/css/vanilla.css'} | ||
34 | |||
35 | ] | ||
36 | }, | ||
37 | options = $.extend({}, defaults, jQT.settings); | ||
38 | |||
39 | function setStyleState(item, title) { | ||
40 | var $item = $(item); | ||
41 | |||
42 | if ($item.attr('title') === title) { | ||
43 | item.disabled = false; // workaround for Firefox on Zepto | ||
44 | $item.removeAttr('disabled'); | ||
45 | } else { | ||
46 | item.disabled = true; // workaround for Firefox on Zepto | ||
47 | $item.attr('disabled', true); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | function initializeStyleState(item, title) { | ||
52 | // and, workaround for WebKit by initializing the 'disabled' attribute | ||
53 | if (!current) { | ||
54 | current = title; | ||
55 | } | ||
56 | setStyleState(item, current); | ||
57 | } | ||
58 | |||
59 | // public | ||
60 | function switchStyle(title) { | ||
61 | current = title; | ||
62 | $(options.themeStyleSelector).each(function(i, item) { | ||
63 | setStyleState(item, title); | ||
64 | }); | ||
65 | } | ||
66 | |||
67 | // collect title names, from <head> | ||
68 | $(options.themeStyleSelector).each(function(i, item) { | ||
69 | var $item = $(item); | ||
70 | var title = $item.attr('title'); | ||
71 | |||
72 | titles[title] = true; | ||
73 | |||
74 | initializeStyleState(item, title); | ||
75 | }); | ||
76 | |||
77 | // add included theme | ||
78 | for (var i=0; i < options.themeIncluded.length; i++) { | ||
79 | var hash = options.themeIncluded[i]; | ||
80 | if (!(hash.title in titles)) { | ||
81 | link = $('<link title="' + hash.title + '" href="' + hash.href + '" rel="stylesheet">'); | ||
82 | $('head').append($(link)); | ||
83 | |||
84 | titles[hash.title] = true; | ||
85 | |||
86 | initializeStyleState(link, hash.title); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | if (options.themeSelectionSelector) { | ||
91 | // create UI items | ||
92 | for (var title in titles) { | ||
93 | var $item = $('<li><a href="#" data-title="' + title + '">' + title + '</a></li>'); | ||
94 | $(options.themeSelectionSelector).append($item); | ||
95 | } | ||
96 | |||
97 | // bind to UI items | ||
98 | $(options.themeSelectionSelector).delegate('* > a', 'tap', function(e) { | ||
99 | e.preventDefault(); | ||
100 | e.stopPropagation(); | ||
101 | |||
102 | var $a = $(this).closest('a'); | ||
103 | $a.removeClass('active'); | ||
104 | switchStyle($a.attr('data-title')); | ||
105 | |||
106 | // poor-man simulation of radio button behaviour | ||
107 | $(options.themeSelectionSelector).find('a').removeClass('selected'); | ||
108 | $a.addClass('selected'); | ||
109 | }); | ||
110 | |||
111 | // poor-man simulation of radio button behaviour | ||
112 | $(options.themeSelectionSelector).closest('#jqt > *').bind('pageAnimationEnd', function(e, data){ | ||
113 | if (data.direction === 'in') { | ||
114 | $(options.themeSelectionSelector).find('a[data-title="' + current + '"]').addClass('selected'); | ||
115 | } | ||
116 | }); | ||
117 | } | ||
118 | |||
119 | return {switchStyle: switchStyle}; | ||
120 | |||
121 | }); | ||
122 | } | ||
123 | })($); | ||
diff --git a/frontend/gamma/js/JQTouch/jqtouch.js b/frontend/gamma/js/JQTouch/jqtouch.js new file mode 100644 index 0000000..bdc6d2e --- a/dev/null +++ b/frontend/gamma/js/JQTouch/jqtouch.js | |||
@@ -0,0 +1,889 @@ | |||
1 | /* | ||
2 | |||
3 | _/ _/_/ _/_/_/_/_/ _/ | ||
4 | _/ _/ _/ _/_/ _/ _/ _/_/_/ _/_/_/ | ||
5 | _/ _/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
6 | _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ | ||
7 | _/ _/_/ _/ _/ _/_/ _/_/_/ _/_/_/ _/ _/ | ||
8 | _/ | ||
9 | _/ | ||
10 | |||
11 | Created by David Kaneda <http://www.davidkaneda.com> | ||
12 | Maintained by Thomas Yip <http://beedesk.com/> | ||
13 | Sponsored by Sencha Labs <http://www.sencha.com/> | ||
14 | Special thanks to Jonathan Stark <http://www.jonathanstark.com/> | ||
15 | |||
16 | Documentation and issue tracking on GitHub <http://github.com/senchalabs/jQTouch/> | ||
17 | |||
18 | (c) 2009-2011 Sencha Labs | ||
19 | jQTouch may be freely distributed under the MIT license. | ||
20 | |||
21 | */ | ||
22 | (function() { | ||
23 | |||
24 | var fx; | ||
25 | if ('Zepto' in window) { | ||
26 | fx = window.Zepto; | ||
27 | fx.fn.prop = fx.fn.attr; | ||
28 | |||
29 | Event.prototype.isDefaultPrevented = function() { | ||
30 | return this.defaultPrevented; | ||
31 | }; | ||
32 | } else if ('jQuery' in window) { | ||
33 | fx = window.jQuery; | ||
34 | |||
35 | // trick to get Zepto/touch.js to work for jQuery | ||
36 | window.Zepto = $; | ||
37 | } else { | ||
38 | throw('Either Zepto or jQuery is required but neither can be found.'); | ||
39 | } | ||
40 | |||
41 | $.jQTouch = function(options) { | ||
42 | // Initialize internal jQT variables | ||
43 | var $ = fx, | ||
44 | $body, | ||
45 | $head=$('head'), | ||
46 | history=[], | ||
47 | newPageCount=0, | ||
48 | jQTSettings={}, | ||
49 | $currentPage='', | ||
50 | orientation='portrait', | ||
51 | touchSelectors=[], | ||
52 | publicObj={}, | ||
53 | tapBuffer=100, // High click delay = ~350, quickest animation (slide) = 250 | ||
54 | extensions=$.jQTouch.prototype.extensions, | ||
55 | extTapHandlers=$.jQTouch.prototype.tapHandlers, | ||
56 | tapHandlers=[], | ||
57 | animations=[], | ||
58 | hairExtensions='', | ||
59 | defaults = { | ||
60 | addGlossToIcon: true, | ||
61 | backSelector: '.back, .cancel, .goback', | ||
62 | cacheGetRequests: true, | ||
63 | debug: true, | ||
64 | defaultAnimation: 'slideleft', | ||
65 | fixedViewport: true, | ||
66 | formSelector: 'form', | ||
67 | fullScreen: true, | ||
68 | fullScreenClass: 'fullscreen', | ||
69 | icon: null, | ||
70 | icon4: null, // available in iOS 4.2 and later. | ||
71 | preloadImages: false, | ||
72 | startupScreen: null, | ||
73 | statusBar: 'default', // other options: black-translucent, black | ||
74 | submitSelector: '.submit', | ||
75 | touchSelector: 'a, .touch', | ||
76 | trackScrollPositions: true, | ||
77 | useAnimations: true, | ||
78 | useFastTouch: true, | ||
79 | useTouchScroll: true, | ||
80 | animations: [ // highest to lowest priority | ||
81 | {name:'cubeleft', selector:'.cubeleft, .cube', is3d: true}, | ||
82 | {name:'cuberight', selector:'.cuberight', is3d: true}, | ||
83 | {name:'dissolve', selector:'.dissolve'}, | ||
84 | {name:'fade', selector:'.fade'}, | ||
85 | {name:'flipleft', selector:'.flipleft, .flip', is3d: true}, | ||
86 | {name:'flipright', selector:'.flipright', is3d: true}, | ||
87 | {name:'pop', selector:'.pop', is3d: true}, | ||
88 | {name:'swapleft', selector:'.swap', is3d: true}, | ||
89 | {name:'slidedown', selector:'.slidedown'}, | ||
90 | {name:'slideright', selector:'.slideright'}, | ||
91 | {name:'slideup', selector:'.slideup'}, | ||
92 | {name:'slideleft', selector:'.slideleft, .slide, #jqt > * > ul li a'} | ||
93 | ] | ||
94 | }; // end defaults | ||
95 | |||
96 | function warn(message) { | ||
97 | if (window.console !== undefined && jQTSettings.debug === true) { | ||
98 | console.warn(message); | ||
99 | } | ||
100 | } | ||
101 | function addAnimation(animation) { | ||
102 | if (typeof(animation.selector) === 'string' && typeof(animation.name) === 'string') { | ||
103 | animations.push(animation); | ||
104 | } | ||
105 | } | ||
106 | function addTapHandler(tapHandler) { | ||
107 | if (typeof(tapHandler.name) === 'string' | ||
108 | && typeof(tapHandler.isSupported) === 'function' | ||
109 | && typeof(tapHandler.fn) === 'function') { | ||
110 | |||
111 | tapHandlers.push(tapHandler); | ||
112 | } | ||
113 | } | ||
114 | function addPageToHistory(page, animation) { | ||
115 | history.unshift({ | ||
116 | page: page, | ||
117 | animation: animation, | ||
118 | hash: '#' + page.attr('id'), | ||
119 | id: page.attr('id') | ||
120 | }); | ||
121 | } | ||
122 | |||
123 | // Unfortunately, we can not assume the "tap" event | ||
124 | // is being used for links, forms, etc. | ||
125 | function clickHandler(e) { | ||
126 | // Figure out whether to prevent default | ||
127 | var $el = $(e.target); | ||
128 | |||
129 | // Find the nearest tappable ancestor | ||
130 | if (!$el.is(touchSelectors.join(', '))) { | ||
131 | $el = $(e.target).closest(touchSelectors.join(', ')); | ||
132 | } | ||
133 | |||
134 | // Prevent default if we found an internal link (relative or absolute) | ||
135 | if ($el && $el.attr('href') && !$el.isExternalLink()) { | ||
136 | warn('Need to prevent default click behavior'); | ||
137 | e.preventDefault(); | ||
138 | } else { | ||
139 | warn('No need to prevent default click behavior'); | ||
140 | } | ||
141 | |||
142 | // Trigger a tap event if touchstart is not on the job | ||
143 | if ($.support.touch) { | ||
144 | warn('Not converting click to a tap event because touch handler is on the job'); | ||
145 | } else { | ||
146 | warn('Converting click event to a tap event because touch handlers are not present or off'); | ||
147 | $(e.target).trigger('tap', e); | ||
148 | } | ||
149 | |||
150 | } | ||
151 | function doNavigation(fromPage, toPage, animation, goingBack) { | ||
152 | |||
153 | goingBack = goingBack ? goingBack : false; | ||
154 | |||
155 | // Error check for target page | ||
156 | if (toPage === undefined || toPage.length === 0) { | ||
157 | $.fn.unselect(); | ||
158 | warn('Target element is missing.'); | ||
159 | return false; | ||
160 | } | ||
161 | |||
162 | // Error check for fromPage===toPage | ||
163 | if (toPage.hasClass('current')) { | ||
164 | $.fn.unselect(); | ||
165 | warn('You are already on the page you are trying to navigate to.'); | ||
166 | return false; | ||
167 | } | ||
168 | |||
169 | // Collapse the keyboard | ||
170 | $(':focus').trigger('blur'); | ||
171 | |||
172 | fromPage.trigger('pageAnimationStart', { direction: 'out', back: goingBack }); | ||
173 | toPage.trigger('pageAnimationStart', { direction: 'in', back: goingBack }); | ||
174 | |||
175 | if ($.support.animationEvents && animation && jQTSettings.useAnimations) { | ||
176 | // Fail over to 2d animation if need be | ||
177 | if (!$.support.transform3d && animation.is3d) { | ||
178 | warn('Did not detect support for 3d animations, falling back to ' + jQTSettings.defaultAnimation); | ||
179 | animation.name = jQTSettings.defaultAnimation; | ||
180 | } | ||
181 | |||
182 | // Reverse animation if need be | ||
183 | var finalAnimationName = animation.name, | ||
184 | is3d = animation.is3d ? 'animating3d' : ''; | ||
185 | |||
186 | if (goingBack) { | ||
187 | finalAnimationName = finalAnimationName.replace(/left|right|up|down|in|out/, reverseAnimation ); | ||
188 | } | ||
189 | |||
190 | warn('finalAnimationName is ' + finalAnimationName); | ||
191 | |||
192 | // Bind internal "cleanup" callback | ||
193 | fromPage.bind('webkitAnimationEnd', navigationEndHandler); | ||
194 | |||
195 | // Trigger animations | ||
196 | $body.addClass('animating ' + is3d); | ||
197 | |||
198 | var lastScroll = window.pageYOffset; | ||
199 | |||
200 | // Position the incoming page so toolbar is at top of viewport regardless of scroll position on from page | ||
201 | if (jQTSettings.trackScrollPositions === true) { | ||
202 | toPage.css('top', window.pageYOffset - (toPage.data('lastScroll') || 0)); | ||
203 | } | ||
204 | |||
205 | toPage.addClass(finalAnimationName + ' in current'); | ||
206 | fromPage.removeClass('current').addClass(finalAnimationName + ' out inmotion'); | ||
207 | |||
208 | if (jQTSettings.trackScrollPositions === true) { | ||
209 | fromPage.data('lastScroll', lastScroll); | ||
210 | $('.scroll', fromPage).each(function(){ | ||
211 | $(this).data('lastScroll', this.scrollTop); | ||
212 | }); | ||
213 | } | ||
214 | } else { | ||
215 | toPage.addClass('current in'); | ||
216 | fromPage.removeClass('current'); | ||
217 | navigationEndHandler(); | ||
218 | } | ||
219 | |||
220 | // Housekeeping | ||
221 | $currentPage = toPage; | ||
222 | if (goingBack) { | ||
223 | history.shift(); | ||
224 | } else { | ||
225 | addPageToHistory($currentPage, animation); | ||
226 | } | ||
227 | setHash($currentPage.attr('id')); | ||
228 | |||
229 | // Private navigationEnd callback | ||
230 | function navigationEndHandler(event) { | ||
231 | var bufferTime = tapBuffer; | ||
232 | |||
233 | if ($.support.animationEvents && animation && jQTSettings.useAnimations) { | ||
234 | fromPage.unbind('webkitAnimationEnd', navigationEndHandler); | ||
235 | fromPage.removeClass(finalAnimationName + ' out inmotion'); | ||
236 | if (finalAnimationName) { | ||
237 | toPage.removeClass(finalAnimationName); | ||
238 | } | ||
239 | $body.removeClass('animating animating3d'); | ||
240 | if (jQTSettings.trackScrollPositions === true) { | ||
241 | toPage.css('top', -toPage.data('lastScroll')); | ||
242 | |||
243 | // Have to make sure the scroll/style resets | ||
244 | // are outside the flow of this function. | ||
245 | setTimeout(function(){ | ||
246 | toPage.css('top', 0); | ||
247 | window.scroll(0, toPage.data('lastScroll')); | ||
248 | $('.scroll', toPage).each(function(){ | ||
249 | this.scrollTop = - $(this).data('lastScroll'); | ||
250 | }); | ||
251 | }, 0); | ||
252 | } | ||
253 | } else { | ||
254 | fromPage.removeClass(finalAnimationName + ' out inmotion'); | ||
255 | if (finalAnimationName) { | ||
256 | toPage.removeClass(finalAnimationName); | ||
257 | } | ||
258 | bufferTime += 260; | ||
259 | } | ||
260 | |||
261 | // In class is intentionally delayed, as it is our ghost click hack | ||
262 | setTimeout(function(){ | ||
263 | toPage.removeClass('in'); | ||
264 | window.scroll(0,0); | ||
265 | }, bufferTime); | ||
266 | |||
267 | fromPage.unselect(); | ||
268 | |||
269 | // Trigger custom events | ||
270 | toPage.trigger('pageAnimationEnd', { | ||
271 | direction:'in', animation: animation, back: goingBack | ||
272 | }); | ||
273 | fromPage.trigger('pageAnimationEnd', { | ||
274 | direction:'out', animation: animation, back: goingBack | ||
275 | }); | ||
276 | } | ||
277 | |||
278 | return true; | ||
279 | } | ||
280 | function reverseAnimation(animation) { | ||
281 | var opposites={ | ||
282 | 'up' : 'down', | ||
283 | 'down' : 'up', | ||
284 | 'left' : 'right', | ||
285 | 'right' : 'left', | ||
286 | 'in' : 'out', | ||
287 | 'out' : 'in' | ||
288 | }; | ||
289 | |||
290 | return opposites[animation] || animation; | ||
291 | } | ||
292 | function getOrientation() { | ||
293 | return orientation; | ||
294 | } | ||
295 | function goBack() { | ||
296 | |||
297 | // Error checking | ||
298 | if (history.length < 1 ) { | ||
299 | warn('History is empty.'); | ||
300 | } | ||
301 | |||
302 | if (history.length === 1 ) { | ||
303 | warn('You are on the first panel.'); | ||
304 | window.history.go(-1); | ||
305 | } | ||
306 | |||
307 | var from = history[0], | ||
308 | to = history[1]; | ||
309 | |||
310 | if (doNavigation(from.page, to.page, from.animation, true)) { | ||
311 | return publicObj; | ||
312 | } else { | ||
313 | warn('Could not go back.'); | ||
314 | return false; | ||
315 | } | ||
316 | |||
317 | } | ||
318 | function goTo(toPage, animation) { | ||
319 | |||
320 | var fromPage = history[0].page; | ||
321 | |||
322 | if (typeof animation === 'string') { | ||
323 | for (var i=0, max=animations.length; i < max; i++) { | ||
324 | if (animations[i].name === animation) { | ||
325 | animation = animations[i]; | ||
326 | break; | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | |||
331 | if (typeof toPage === 'string') { | ||
332 | var nextPage = $(toPage); | ||
333 | |||
334 | if (nextPage.length < 1) { | ||
335 | showPageByHref(toPage, { | ||
336 | animation: animation | ||
337 | }); | ||
338 | return; | ||
339 | } else { | ||
340 | toPage = nextPage; | ||
341 | } | ||
342 | } | ||
343 | if (doNavigation(fromPage, toPage, animation)) { | ||
344 | return publicObj; | ||
345 | } else { | ||
346 | warn('Could not animate pages.'); | ||
347 | return false; | ||
348 | } | ||
349 | } | ||
350 | function hashChangeHandler(e) { | ||
351 | if (location.hash === history[0].hash) { | ||
352 | warn('We are on the right panel'); | ||
353 | return true; | ||
354 | } else if (location.hash === '') { | ||
355 | goBack(); | ||
356 | return true; | ||
357 | } else { | ||
358 | if( (history[1] && location.hash === history[1].hash) ) { | ||
359 | goBack(); | ||
360 | return true; | ||
361 | } else { | ||
362 | // Lastly, just try going to the ID... | ||
363 | warn('Could not find ID in history, just forwarding to DOM element.'); | ||
364 | goTo($(location.hash), jQTSettings.defaultAnimation); | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | function init(options) { | ||
369 | jQTSettings = $.extend({}, defaults, options); | ||
370 | |||
371 | // Preload images | ||
372 | if (jQTSettings.preloadImages) { | ||
373 | for (var i = jQTSettings.preloadImages.length - 1; i >= 0; i--) { | ||
374 | (new Image()).src = jQTSettings.preloadImages[i]; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | // Set appropriate icon (retina display available in iOS 4.2 and later.) | ||
379 | var precomposed = (jQTSettings.addGlossToIcon) ? '' : '-precomposed'; | ||
380 | if (jQTSettings.icon) { | ||
381 | hairExtensions += '<link rel="apple-touch-icon' + precomposed + '" href="' + jQTSettings.icon + '" />'; | ||
382 | } | ||
383 | if (jQTSettings.icon4) { | ||
384 | hairExtensions += '<link rel="apple-touch-icon' + precomposed + '" sizes="114x114" href="' + jQTSettings.icon4 + '" />'; | ||
385 | } | ||
386 | // Set startup screen | ||
387 | if (jQTSettings.startupScreen) { | ||
388 | hairExtensions += '<link rel="apple-touch-startup-image" href="' + jQTSettings.startupScreen + '" />'; | ||
389 | } | ||
390 | |||
391 | // Set viewport | ||
392 | if (jQTSettings.fixedViewport) { | ||
393 | hairExtensions += '<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>'; | ||
394 | } | ||
395 | |||
396 | // Set full-screen | ||
397 | if (jQTSettings.fullScreen) { | ||
398 | hairExtensions += '<meta name="apple-mobile-web-app-capable" content="yes" />'; | ||
399 | if (jQTSettings.statusBar) { | ||
400 | hairExtensions += '<meta name="apple-mobile-web-app-status-bar-style" content="' + jQTSettings.statusBar + '" />'; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | // Attach hair extensions | ||
405 | if (hairExtensions) { | ||
406 | $head.prepend(hairExtensions); | ||
407 | } | ||
408 | } | ||
409 | |||
410 | function getAnimation(el) { | ||
411 | var animation; | ||
412 | |||
413 | for (var i=0, max=animations.length; i < max; i++) { | ||
414 | if (el.is(animations[i].selector)) { | ||
415 | animation = animations[i]; | ||
416 | break; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | if (!animation) { | ||
421 | warn('Animation could not be found. Using ' + jQTSettings.defaultAnimation + '.'); | ||
422 | animation = jQTSettings.defaultAnimation; | ||
423 | } | ||
424 | return animation; | ||
425 | } | ||
426 | |||
427 | function insertPages(nodes, animation) { | ||
428 | |||
429 | var targetPage = null; | ||
430 | |||
431 | // Call dom.createElement element directly instead of relying on $(nodes), | ||
432 | // to work around: https://github.com/madrobby/zepto/issues/312 | ||
433 | var div = document.createElement('div'); | ||
434 | div.innerHTML = nodes; | ||
435 | |||
436 | $(div).children().each(function(index, node) { | ||
437 | var $node = $(this); | ||
438 | if (!$node.attr('id')) { | ||
439 | $node.attr('id', 'page-' + (++newPageCount)); | ||
440 | } | ||
441 | |||
442 | // Remove any existing instance | ||
443 | $('#' + $node.attr('id')).remove(); | ||
444 | |||
445 | $body.append($node); | ||
446 | $body.trigger('pageInserted', {page: $node}); | ||
447 | |||
448 | if ($node.hasClass('current') || !targetPage) { | ||
449 | targetPage = $node; | ||
450 | } | ||
451 | }); | ||
452 | if (targetPage !== null) { | ||
453 | goTo(targetPage, animation); | ||
454 | return targetPage; | ||
455 | } else { | ||
456 | return false; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | function orientationChangeHandler() { | ||
461 | $body.css('minHeight', 1000); | ||
462 | scrollTo(0,0); | ||
463 | var bodyHeight = window.innerHeight; | ||
464 | $body.css('minHeight', bodyHeight); | ||
465 | |||
466 | orientation = Math.abs(window.orientation) == 90 ? 'landscape' : 'portrait'; | ||
467 | $body.removeClass('portrait landscape').addClass(orientation).trigger('turn', {orientation: orientation}); | ||
468 | } | ||
469 | function setHash(hash) { | ||
470 | // Sanitize | ||
471 | location.hash = '#' + hash.replace(/^#/, ''); | ||
472 | } | ||
473 | function showPageByHref(href, options) { | ||
474 | |||
475 | var defaults = { | ||
476 | data: null, | ||
477 | method: 'GET', | ||
478 | animation: null, | ||
479 | callback: null, | ||
480 | $referrer: null | ||
481 | }; | ||
482 | |||
483 | var settings = $.extend({}, defaults, options); | ||
484 | |||
485 | if (href != '#') { | ||
486 | $.ajax({ | ||
487 | url: href, | ||
488 | data: settings.data, | ||
489 | type: settings.method, | ||
490 | success: function (data) { | ||
491 | var firstPage = insertPages(data, settings.animation); | ||
492 | if (firstPage) { | ||
493 | if (settings.method == 'GET' && jQTSettings.cacheGetRequests === true && settings.$referrer) { | ||
494 | settings.$referrer.attr('href', '#' + firstPage.attr('id')); | ||
495 | } | ||
496 | if (settings.callback) { | ||
497 | settings.callback(true); | ||
498 | } | ||
499 | } | ||
500 | }, | ||
501 | error: function (data) { | ||
502 | if (settings.$referrer) { | ||
503 | settings.$referrer.unselect(); | ||
504 | } | ||
505 | if (settings.callback) { | ||
506 | settings.callback(false); | ||
507 | } | ||
508 | } | ||
509 | }); | ||
510 | } else if (settings.$referrer) { | ||
511 | settings.$referrer.unselect(); | ||
512 | } | ||
513 | } | ||
514 | function submitHandler(e, callback) { | ||
515 | |||
516 | $(':focus').trigger('blur'); | ||
517 | |||
518 | e.preventDefault(); | ||
519 | |||
520 | var $form = (typeof(e)==='string') ? $(e).eq(0) : (e.target ? $(e.target) : $(e)); | ||
521 | |||
522 | if ($form.length && $form.is(jQTSettings.formSelector) && $form.attr('action')) { | ||
523 | showPageByHref($form.attr('action'), { | ||
524 | data: $form.serialize(), | ||
525 | method: $form.attr('method') || "POST", | ||
526 | animation: getAnimation($form), | ||
527 | callback: callback | ||
528 | }); | ||
529 | return false; | ||
530 | } | ||
531 | return true; | ||
532 | } | ||
533 | function submitParentForm($el) { | ||
534 | |||
535 | var $form = $el.closest('form'); | ||
536 | if ($form.length === 0) { | ||
537 | warn('No parent form found'); | ||
538 | } else { | ||
539 | warn('About to submit parent form'); | ||
540 | $form.trigger('submit'); | ||
541 | return false; | ||
542 | } | ||
543 | return true; | ||
544 | } | ||
545 | function supportForTransform3d() { | ||
546 | |||
547 | var head, body, style, div, result; | ||
548 | |||
549 | head = document.getElementsByTagName('head')[0]; | ||
550 | body = document.body; | ||
551 | |||
552 | style = document.createElement('style'); | ||
553 | style.textContent = '@media (transform-3d),(-o-transform-3d),(-moz-transform-3d),(-webkit-transform-3d){#jqt-3dtest{height:3px}}'; | ||
554 | |||
555 | div = document.createElement('div'); | ||
556 | div.id = 'jqt-3dtest'; | ||
557 | |||
558 | // Add to the page | ||
559 | head.appendChild(style); | ||
560 | body.appendChild(div); | ||
561 | |||
562 | // Check the result | ||
563 | result = div.offsetHeight === 3; | ||
564 | |||
565 | // Clean up | ||
566 | style.parentNode.removeChild(style); | ||
567 | div.parentNode.removeChild(div); | ||
568 | |||
569 | // Pass back result | ||
570 | warn('Support for 3d transforms: ' + result); | ||
571 | return result; | ||
572 | } | ||
573 | function supportIOS5() { | ||
574 | var support = false; | ||
575 | var REGEX_IOS_VERSION = /OS (\d+)(_\d+)* like Mac OS X/i; | ||
576 | |||
577 | var agentString = window.navigator.userAgent; | ||
578 | if (REGEX_IOS_VERSION.test(agentString)) { | ||
579 | support = (REGEX_IOS_VERSION.exec(agentString)[1] >= 5); | ||
580 | } | ||
581 | return support; | ||
582 | } | ||
583 | function touchStartHandler(e){ | ||
584 | |||
585 | var $el = $(e.target), | ||
586 | selectors = touchSelectors.join(', '); | ||
587 | |||
588 | // Find the nearest tappable ancestor | ||
589 | if (!$el.is(selectors)) { | ||
590 | $el = $el.closest(selectors); | ||
591 | } | ||
592 | |||
593 | // Make sure we have a tappable element | ||
594 | if ($el.length && $el.attr('href')) { | ||
595 | $el.addClass('active'); | ||
596 | } | ||
597 | |||
598 | // Remove our active class if we move | ||
599 | $el.on($.support.touch ? 'touchmove' : 'mousemove', function(){ | ||
600 | $el.removeClass('active'); | ||
601 | }); | ||
602 | |||
603 | $el.on('touchend', function(){ | ||
604 | $el.unbind('touchmove mousemove'); | ||
605 | }); | ||
606 | |||
607 | } | ||
608 | function tapHandler(e){ | ||
609 | |||
610 | if (e.isDefaultPrevented()) { | ||
611 | return true; | ||
612 | } | ||
613 | |||
614 | // Grab the target element | ||
615 | var $el = $(e.target); | ||
616 | |||
617 | // Find the nearest tappable ancestor | ||
618 | if (!$el.is(touchSelectors.join(', '))) { | ||
619 | $el = $el.closest(touchSelectors.join(', ')); | ||
620 | } | ||
621 | |||
622 | // Make sure we have a tappable element | ||
623 | if (!$el.length || !$el.attr('href')) { | ||
624 | warn('Could not find a link related to tapped element'); | ||
625 | return true; | ||
626 | } | ||
627 | |||
628 | // Init some vars | ||
629 | var target = $el.attr('target'), | ||
630 | hash = $el.prop('hash'), | ||
631 | href = $el.attr('href'); | ||
632 | |||
633 | var params = { | ||
634 | e: e, | ||
635 | $el: $el, | ||
636 | target: target, | ||
637 | hash: hash, | ||
638 | href: href, | ||
639 | jQTSettings: jQTSettings | ||
640 | }; | ||
641 | |||
642 | // Loop thru all handlers | ||
643 | for (var i=0, len=tapHandlers.length; i<len; i++) { | ||
644 | var handler = tapHandlers[i]; | ||
645 | var supported = handler.isSupported(e, params); | ||
646 | if (supported) { | ||
647 | var flag = handler.fn(e, params); | ||
648 | return flag; | ||
649 | } | ||
650 | } | ||
651 | } | ||
652 | function addDefaultTapHandlers() { | ||
653 | addTapHandler({ | ||
654 | name: 'external-link', | ||
655 | isSupported: function(e, params) { | ||
656 | return params.$el.isExternalLink(); | ||
657 | }, | ||
658 | fn: function(e, params) { | ||
659 | params.$el.unselect(); | ||
660 | return true; | ||
661 | } | ||
662 | }); | ||
663 | addTapHandler({ | ||
664 | name: 'back-selector', | ||
665 | isSupported: function(e, params) { | ||
666 | return params.$el.is(params.jQTSettings.backSelector); | ||
667 | }, | ||
668 | fn: function(e, params) { | ||
669 | // User clicked or tapped a back button | ||
670 | goBack(params.hash); | ||
671 | } | ||
672 | }); | ||
673 | addTapHandler({ | ||
674 | name: 'submit-selector', | ||
675 | isSupported: function(e, params) { | ||
676 | return params.$el.is(params.jQTSettings.submitSelector); | ||
677 | }, | ||
678 | fn: function(e, params) { | ||
679 | // User clicked or tapped a submit element | ||
680 | submitParentForm(params.$el); | ||
681 | } | ||
682 | }); | ||
683 | addTapHandler({ | ||
684 | name: 'webapp', | ||
685 | isSupported: function(e, params) { | ||
686 | return params.target === '_webapp'; | ||
687 | }, | ||
688 | fn: function(e, params) { | ||
689 | // User clicked or tapped an internal link, fullscreen mode | ||
690 | window.location = params.href; | ||
691 | return false; | ||
692 | } | ||
693 | }); | ||
694 | addTapHandler({ | ||
695 | name: 'no-op', | ||
696 | isSupported: function(e, params) { | ||
697 | return params.href === '#'; | ||
698 | }, | ||
699 | fn: function(e, params) { | ||
700 | // Allow tap on item with no href | ||
701 | params.$el.unselect(); | ||
702 | return true; | ||
703 | } | ||
704 | }); | ||
705 | addTapHandler({ | ||
706 | name: 'standard', | ||
707 | isSupported: function(e, params) { | ||
708 | return params.hash && params.hash !== '#'; | ||
709 | }, | ||
710 | fn: function(e, params) { | ||
711 | var animation = getAnimation(params.$el); | ||
712 | // Internal href | ||
713 | params.$el.addClass('active'); | ||
714 | goTo( | ||
715 | $(params.hash).data('referrer', params.$el), | ||
716 | animation, | ||
717 | params.$el.hasClass('reverse') | ||
718 | ); | ||
719 | return false; | ||
720 | } | ||
721 | }); | ||
722 | addTapHandler({ | ||
723 | name: 'external', | ||
724 | isSupported: function(e, params) { | ||
725 | return true; | ||
726 | }, | ||
727 | fn: function(e, params) { | ||
728 | var animation = getAnimation(params.$el); | ||
729 | |||
730 | // External href | ||
731 | params.$el.addClass('loading active'); | ||
732 | showPageByHref(params.$el.attr('href'), { | ||
733 | animation: animation, | ||
734 | callback: function() { | ||
735 | params.$el.removeClass('loading'); | ||
736 | setTimeout($.fn.unselect, 250, params.$el); | ||
737 | }, | ||
738 | $referrer: params.$el | ||
739 | }); | ||
740 | return false; | ||
741 | } | ||
742 | }); | ||
743 | }; | ||
744 | |||
745 | // Get the party started | ||
746 | init(options); | ||
747 | |||
748 | // Document ready stuff | ||
749 | $(document).ready(function RUMBLE() { | ||
750 | // Store some properties in a support object | ||
751 | if (!$.support) $.support = {}; | ||
752 | $.support.animationEvents = (typeof window.WebKitAnimationEvent != 'undefined'); | ||
753 | $.support.touch = (typeof window.TouchEvent != 'undefined') && (window.navigator.userAgent.indexOf('Mobile') > -1) && jQTSettings.useFastTouch; | ||
754 | $.support.transform3d = supportForTransform3d(); | ||
755 | $.support.ios5 = supportIOS5(); | ||
756 | |||
757 | if (!$.support.touch) { | ||
758 | warn('This device does not support touch interaction, or it has been deactivated by the developer. Some features might be unavailable.'); | ||
759 | } | ||
760 | if (!$.support.transform3d) { | ||
761 | warn('This device does not support 3d animation. 2d animations will be used instead.'); | ||
762 | } | ||
763 | |||
764 | // Define public jQuery functions | ||
765 | $.fn.isExternalLink = function() { | ||
766 | var $el = $(this); | ||
767 | return ($el.attr('target') == '_blank' || $el.attr('rel') == 'external' || $el.is('a[href^="http://maps.google.com"], a[href^="mailto:"], a[href^="tel:"], a[href^="javascript:"], a[href*="youtube.com/v"], a[href*="youtube.com/watch"]')); | ||
768 | }; | ||
769 | $.fn.makeActive = function() { | ||
770 | return $(this).addClass('active'); | ||
771 | }; | ||
772 | $.fn.unselect = function(obj) { | ||
773 | if (obj) { | ||
774 | obj.removeClass('active'); | ||
775 | } else { | ||
776 | $('.active').removeClass('active'); | ||
777 | } | ||
778 | }; | ||
779 | |||
780 | // Add extensions | ||
781 | for (var i=0, max=extensions.length; i < max; i++) { | ||
782 | var fn = extensions[i]; | ||
783 | if ($.isFunction(fn)) { | ||
784 | $.extend(publicObj, fn(publicObj)); | ||
785 | } | ||
786 | } | ||
787 | |||
788 | // Add extensions tapHandlers | ||
789 | for (var i=0, max=extTapHandlers.length; i < max; i++) { | ||
790 | addTapHandler(extTapHandlers[i]); | ||
791 | } | ||
792 | // Add default tapHandlers | ||
793 | addDefaultTapHandlers(); | ||
794 | |||
795 | // Add animations | ||
796 | for (var j=0, max_anims=defaults.animations.length; j < max_anims; j++) { | ||
797 | var animation = defaults.animations[j]; | ||
798 | if(jQTSettings[animation.name + 'Selector'] !== undefined){ | ||
799 | animation.selector = jQTSettings[animation.name + 'Selector']; | ||
800 | } | ||
801 | addAnimation(animation); | ||
802 | } | ||
803 | |||
804 | // Create an array of stuff that needs touch event handling | ||
805 | touchSelectors.push(jQTSettings.touchSelector); | ||
806 | touchSelectors.push(jQTSettings.backSelector); | ||
807 | touchSelectors.push(jQTSettings.submitSelector); | ||
808 | $(touchSelectors.join(', ')).css('-webkit-touch-callout', 'none'); | ||
809 | |||
810 | // Make sure we have a jqt element | ||
811 | $body = $('#jqt'); | ||
812 | var anatomy_lessons = []; | ||
813 | |||
814 | if ($body.length === 0) { | ||
815 | warn('Could not find an element with the id "jqt", so the body id has been set to "jqt". If you are having any problems, wrapping your panels in a div with the id "jqt" might help.'); | ||
816 | $body = $(document.body).attr('id', 'jqt'); | ||
817 | } | ||
818 | |||
819 | // Add some specific css if need be | ||
820 | if ($.support.transform3d) { | ||
821 | anatomy_lessons.push('supports3d'); | ||
822 | } | ||
823 | if ($.support.ios5 && jQTSettings.useTouchScroll) { | ||
824 | anatomy_lessons.push('touchscroll'); | ||
825 | } | ||
826 | |||
827 | if (jQTSettings.fullScreenClass && window.navigator.standalone === true) { | ||
828 | anatomy_lessons.push(jQTSettings.fullScreenClass, jQTSettings.statusBar); | ||
829 | } | ||
830 | |||
831 | // Bind events | ||
832 | |||
833 | $body | ||
834 | .addClass(anatomy_lessons.join(' ')) | ||
835 | .bind('click', clickHandler) | ||
836 | .bind('orientationchange', orientationChangeHandler) | ||
837 | .bind('submit', submitHandler) | ||
838 | .bind('tap', tapHandler) | ||
839 | .bind( $.support.touch ? 'touchstart' : 'mousedown', touchStartHandler) | ||
840 | .trigger('orientationchange'); | ||
841 | |||
842 | $(window).bind('hashchange', hashChangeHandler); | ||
843 | |||
844 | var startHash = location.hash; | ||
845 | |||
846 | // Determine what the initial view should be | ||
847 | if ($('#jqt > .current').length === 0) { | ||
848 | $currentPage = $('#jqt > *:first-child').addClass('current'); | ||
849 | } else { | ||
850 | $currentPage = $('#jqt > .current'); | ||
851 | } | ||
852 | |||
853 | setHash($currentPage.attr('id')); | ||
854 | addPageToHistory($currentPage); | ||
855 | |||
856 | if ($(startHash).length === 1) { | ||
857 | goTo(startHash); | ||
858 | } | ||
859 | }); | ||
860 | |||
861 | // Expose public methods and properties | ||
862 | publicObj = { | ||
863 | addAnimation: addAnimation, | ||
864 | animations: animations, | ||
865 | getOrientation: getOrientation, | ||
866 | goBack: goBack, | ||
867 | insertPages: insertPages, | ||
868 | goTo: goTo, | ||
869 | history: history, | ||
870 | settings: jQTSettings, | ||
871 | submitForm: submitHandler | ||
872 | }; | ||
873 | return publicObj; | ||
874 | }; | ||
875 | |||
876 | $.jQTouch.prototype.extensions = []; | ||
877 | $.jQTouch.prototype.tapHandlers = []; | ||
878 | |||
879 | // Extensions directly manipulate the jQTouch object, before it's initialized. | ||
880 | $.jQTouch.addExtension = function(extension) { | ||
881 | $.jQTouch.prototype.extensions.push(extension); | ||
882 | }; | ||
883 | |||
884 | // Experimental tap hanlders that can bypass default jQTouch tap handling | ||
885 | $.jQTouch.addTapHandler = function(extension) { | ||
886 | $.jQTouch.prototype.tapHandlers.push(extension); | ||
887 | }; | ||
888 | |||
889 | })(); // Double closure, ALL THE WAY ACROSS THE SKY | ||
diff --git a/frontend/gamma/js/Zepto/ajax.js b/frontend/gamma/js/Zepto/ajax.js new file mode 100644 index 0000000..f4da150 --- a/dev/null +++ b/frontend/gamma/js/Zepto/ajax.js | |||
@@ -0,0 +1,285 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function($){ | ||
6 | var jsonpID = 0, | ||
7 | isObject = $.isObject, | ||
8 | document = window.document, | ||
9 | key, | ||
10 | name, | ||
11 | rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, | ||
12 | scriptTypeRE = /^(?:text|application)\/javascript/i, | ||
13 | xmlTypeRE = /^(?:text|application)\/xml/i, | ||
14 | jsonType = 'application/json', | ||
15 | htmlType = 'text/html', | ||
16 | blankRE = /^\s*$/ | ||
17 | |||
18 | // trigger a custom event and return false if it was cancelled | ||
19 | function triggerAndReturn(context, eventName, data) { | ||
20 | var event = $.Event(eventName) | ||
21 | $(context).trigger(event, data) | ||
22 | return !event.defaultPrevented | ||
23 | } | ||
24 | |||
25 | // trigger an Ajax "global" event | ||
26 | function triggerGlobal(settings, context, eventName, data) { | ||
27 | if (settings.global) return triggerAndReturn(context || document, eventName, data) | ||
28 | } | ||
29 | |||
30 | // Number of active Ajax requests | ||
31 | $.active = 0 | ||
32 | |||
33 | function ajaxStart(settings) { | ||
34 | if (settings.global && $.active++ === 0) triggerGlobal(settings, null, 'ajaxStart') | ||
35 | } | ||
36 | function ajaxStop(settings) { | ||
37 | if (settings.global && !(--$.active)) triggerGlobal(settings, null, 'ajaxStop') | ||
38 | } | ||
39 | |||
40 | // triggers an extra global event "ajaxBeforeSend" that's like "ajaxSend" but cancelable | ||
41 | function ajaxBeforeSend(xhr, settings) { | ||
42 | var context = settings.context | ||
43 | if (settings.beforeSend.call(context, xhr, settings) === false || | ||
44 | triggerGlobal(settings, context, 'ajaxBeforeSend', [xhr, settings]) === false) | ||
45 | return false | ||
46 | |||
47 | triggerGlobal(settings, context, 'ajaxSend', [xhr, settings]) | ||
48 | } | ||
49 | function ajaxSuccess(data, xhr, settings) { | ||
50 | var context = settings.context, status = 'success' | ||
51 | settings.success.call(context, data, status, xhr) | ||
52 | triggerGlobal(settings, context, 'ajaxSuccess', [xhr, settings, data]) | ||
53 | ajaxComplete(status, xhr, settings) | ||
54 | } | ||
55 | // type: "timeout", "error", "abort", "parsererror" | ||
56 | function ajaxError(error, type, xhr, settings) { | ||
57 | var context = settings.context | ||
58 | settings.error.call(context, xhr, type, error) | ||
59 | triggerGlobal(settings, context, 'ajaxError', [xhr, settings, error]) | ||
60 | ajaxComplete(type, xhr, settings) | ||
61 | } | ||
62 | // status: "success", "notmodified", "error", "timeout", "abort", "parsererror" | ||
63 | function ajaxComplete(status, xhr, settings) { | ||
64 | var context = settings.context | ||
65 | settings.complete.call(context, xhr, status) | ||
66 | triggerGlobal(settings, context, 'ajaxComplete', [xhr, settings]) | ||
67 | ajaxStop(settings) | ||
68 | } | ||
69 | |||
70 | // Empty function, used as default callback | ||
71 | function empty() {} | ||
72 | |||
73 | $.ajaxJSONP = function(options){ | ||
74 | if (!('type' in options)) return $.ajax(options) | ||
75 | |||
76 | var callbackName = 'jsonp' + (++jsonpID), | ||
77 | script = document.createElement('script'), | ||
78 | abort = function(){ | ||
79 | $(script).remove() | ||
80 | if (callbackName in window) window[callbackName] = empty | ||
81 | ajaxComplete('abort', xhr, options) | ||
82 | }, | ||
83 | xhr = { abort: abort }, abortTimeout | ||
84 | |||
85 | if (options.error) script.onerror = function() { | ||
86 | xhr.abort() | ||
87 | options.error() | ||
88 | } | ||
89 | |||
90 | window[callbackName] = function(data){ | ||
91 | clearTimeout(abortTimeout) | ||
92 | $(script).remove() | ||
93 | delete window[callbackName] | ||
94 | ajaxSuccess(data, xhr, options) | ||
95 | } | ||
96 | |||
97 | serializeData(options) | ||
98 | script.src = options.url.replace(/=\?/, '=' + callbackName) | ||
99 | $('head').append(script) | ||
100 | |||
101 | if (options.timeout > 0) abortTimeout = setTimeout(function(){ | ||
102 | xhr.abort() | ||
103 | ajaxComplete('timeout', xhr, options) | ||
104 | }, options.timeout) | ||
105 | |||
106 | return xhr | ||
107 | } | ||
108 | |||
109 | $.ajaxSettings = { | ||
110 | // Default type of request | ||
111 | type: 'GET', | ||
112 | // Callback that is executed before request | ||
113 | beforeSend: empty, | ||
114 | // Callback that is executed if the request succeeds | ||
115 | success: empty, | ||
116 | // Callback that is executed the the server drops error | ||
117 | error: empty, | ||
118 | // Callback that is executed on request complete (both: error and success) | ||
119 | complete: empty, | ||
120 | // The context for the callbacks | ||
121 | context: null, | ||
122 | // Whether to trigger "global" Ajax events | ||
123 | global: true, | ||
124 | // Transport | ||
125 | xhr: function () { | ||
126 | return new window.XMLHttpRequest() | ||
127 | }, | ||
128 | // MIME types mapping | ||
129 | accepts: { | ||
130 | script: 'text/javascript, application/javascript', | ||
131 | json: jsonType, | ||
132 | xml: 'application/xml, text/xml', | ||
133 | html: htmlType, | ||
134 | text: 'text/plain' | ||
135 | }, | ||
136 | // Whether the request is to another domain | ||
137 | crossDomain: false, | ||
138 | // Default timeout | ||
139 | timeout: 0, | ||
140 | // Whether data should be serialized to string | ||
141 | processData: true | ||
142 | } | ||
143 | |||
144 | function mimeToDataType(mime) { | ||
145 | return mime && ( mime == htmlType ? 'html' : | ||
146 | mime == jsonType ? 'json' : | ||
147 | scriptTypeRE.test(mime) ? 'script' : | ||
148 | xmlTypeRE.test(mime) && 'xml' ) || 'text' | ||
149 | } | ||
150 | |||
151 | function appendQuery(url, query) { | ||
152 | return (url + '&' + query).replace(/[&?]{1,2}/, '?') | ||
153 | } | ||
154 | |||
155 | // serialize payload and append it to the URL for GET requests | ||
156 | function serializeData(options) { | ||
157 | if (options.processData && isObject(options.data)) | ||
158 | options.data = $.param(options.data, options.traditional) | ||
159 | if (options.data && (!options.type || options.type.toUpperCase() == 'GET')) | ||
160 | options.url = appendQuery(options.url, options.data) | ||
161 | } | ||
162 | |||
163 | $.ajax = function(options){ | ||
164 | var settings = $.extend({}, options || {}) | ||
165 | for (key in $.ajaxSettings) if (settings[key] === undefined) settings[key] = $.ajaxSettings[key] | ||
166 | |||
167 | ajaxStart(settings) | ||
168 | |||
169 | if (!settings.crossDomain) settings.crossDomain = /^([\w-]+:)?\/\/([^\/]+)/.test(settings.url) && | ||
170 | RegExp.$2 != window.location.host | ||
171 | |||
172 | var dataType = settings.dataType, hasPlaceholder = /=\?/.test(settings.url) | ||
173 | if (dataType == 'jsonp' || hasPlaceholder) { | ||
174 | if (!hasPlaceholder) settings.url = appendQuery(settings.url, 'callback=?') | ||
175 | return $.ajaxJSONP(settings) | ||
176 | } | ||
177 | |||
178 | if (!settings.url) settings.url = window.location.toString() | ||
179 | serializeData(settings) | ||
180 | |||
181 | var mime = settings.accepts[dataType], | ||
182 | baseHeaders = { }, | ||
183 | protocol = /^([\w-]+:)\/\//.test(settings.url) ? RegExp.$1 : window.location.protocol, | ||
184 | xhr = $.ajaxSettings.xhr(), abortTimeout | ||
185 | |||
186 | if (!settings.crossDomain) baseHeaders['X-Requested-With'] = 'XMLHttpRequest' | ||
187 | if (mime) { | ||
188 | baseHeaders['Accept'] = mime | ||
189 | if (mime.indexOf(',') > -1) mime = mime.split(',', 2)[0] | ||
190 | xhr.overrideMimeType && xhr.overrideMimeType(mime) | ||
191 | } | ||
192 | if (settings.contentType || (settings.contentType !== false && settings.data && settings.type.toUpperCase() != 'GET')) | ||
193 | baseHeaders['Content-Type'] = (settings.contentType || 'application/x-www-form-urlencoded') | ||
194 | settings.headers = $.extend(baseHeaders, settings.headers || {}) | ||
195 | |||
196 | xhr.onreadystatechange = function(){ | ||
197 | if (xhr.readyState == 4) { | ||
198 | xhr.onreadystatechange = empty; | ||
199 | clearTimeout(abortTimeout) | ||
200 | var result, error = false | ||
201 | if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304 || (xhr.status == 0 && protocol == 'file:')) { | ||
202 | dataType = dataType || mimeToDataType(xhr.getResponseHeader('content-type')) | ||
203 | result = xhr.responseText | ||
204 | |||
205 | try { | ||
206 | if (dataType == 'script') (1,eval)(result) | ||
207 | else if (dataType == 'xml') result = xhr.responseXML | ||
208 | else if (dataType == 'json') result = blankRE.test(result) ? null : $.parseJSON(result) | ||
209 | } catch (e) { error = e } | ||
210 | |||
211 | if (error) ajaxError(error, 'parsererror', xhr, settings) | ||
212 | else ajaxSuccess(result, xhr, settings) | ||
213 | } else { | ||
214 | ajaxError(null, xhr.status ? 'error' : 'abort', xhr, settings) | ||
215 | } | ||
216 | } | ||
217 | } | ||
218 | |||
219 | var async = 'async' in settings ? settings.async : true | ||
220 | xhr.open(settings.type, settings.url, async) | ||
221 | |||
222 | for (name in settings.headers) xhr.setRequestHeader(name, settings.headers[name]) | ||
223 | |||
224 | if (ajaxBeforeSend(xhr, settings) === false) { | ||
225 | xhr.abort() | ||
226 | return false | ||
227 | } | ||
228 | |||
229 | if (settings.timeout > 0) abortTimeout = setTimeout(function(){ | ||
230 | xhr.onreadystatechange = empty | ||
231 | xhr.abort() | ||
232 | ajaxError(null, 'timeout', xhr, settings) | ||
233 | }, settings.timeout) | ||
234 | |||
235 | // avoid sending empty string (#319) | ||
236 | xhr.send(settings.data ? settings.data : null) | ||
237 | return xhr | ||
238 | } | ||
239 | |||
240 | $.get = function(url, success){ return $.ajax({ url: url, success: success }) } | ||
241 | |||
242 | $.post = function(url, data, success, dataType){ | ||
243 | if ($.isFunction(data)) dataType = dataType || success, success = data, data = null | ||
244 | return $.ajax({ type: 'POST', url: url, data: data, success: success, dataType: dataType }) | ||
245 | } | ||
246 | |||
247 | $.getJSON = function(url, success){ | ||
248 | return $.ajax({ url: url, success: success, dataType: 'json' }) | ||
249 | } | ||
250 | |||
251 | $.fn.load = function(url, success){ | ||
252 | if (!this.length) return this | ||
253 | var self = this, parts = url.split(/\s/), selector | ||
254 | if (parts.length > 1) url = parts[0], selector = parts[1] | ||
255 | $.get(url, function(response){ | ||
256 | self.html(selector ? | ||
257 | $('<div>').html(response.replace(rscript, "")).find(selector) | ||
258 | : response) | ||
259 | success && success.apply(self, arguments) | ||
260 | }) | ||
261 | return this | ||
262 | } | ||
263 | |||
264 | var escape = encodeURIComponent | ||
265 | |||
266 | function serialize(params, obj, traditional, scope){ | ||
267 | var array = $.isArray(obj) | ||
268 | $.each(obj, function(key, value) { | ||
269 | if (scope) key = traditional ? scope : scope + '[' + (array ? '' : key) + ']' | ||
270 | // handle data in serializeArray() format | ||
271 | if (!scope && array) params.add(value.name, value.value) | ||
272 | // recurse into nested objects | ||
273 | else if (traditional ? $.isArray(value) : isObject(value)) | ||
274 | serialize(params, value, traditional, key) | ||
275 | else params.add(key, value) | ||
276 | }) | ||
277 | } | ||
278 | |||
279 | $.param = function(obj, traditional){ | ||
280 | var params = [] | ||
281 | params.add = function(k, v){ this.push(escape(k) + '=' + escape(v)) } | ||
282 | serialize(params, obj, traditional) | ||
283 | return params.join('&').replace(/%20/g, '+') | ||
284 | } | ||
285 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/assets.js b/frontend/gamma/js/Zepto/assets.js new file mode 100644 index 0000000..b5a5712 --- a/dev/null +++ b/frontend/gamma/js/Zepto/assets.js | |||
@@ -0,0 +1,21 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function($){ | ||
6 | var cache = [], timeout | ||
7 | |||
8 | $.fn.remove = function(){ | ||
9 | return this.each(function(){ | ||
10 | if(this.parentNode){ | ||
11 | if(this.tagName === 'IMG'){ | ||
12 | cache.push(this) | ||
13 | this.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=' | ||
14 | if (timeout) clearTimeout(timeout) | ||
15 | timeout = setTimeout(function(){ cache = [] }, 60000) | ||
16 | } | ||
17 | this.parentNode.removeChild(this) | ||
18 | } | ||
19 | }) | ||
20 | } | ||
21 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/data.js b/frontend/gamma/js/Zepto/data.js new file mode 100644 index 0000000..b4c289f --- a/dev/null +++ b/frontend/gamma/js/Zepto/data.js | |||
@@ -0,0 +1,67 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | // The following code is heavily inspired by jQuery's $.fn.data() | ||
6 | |||
7 | ;(function($) { | ||
8 | var data = {}, dataAttr = $.fn.data, camelize = $.camelCase, | ||
9 | exp = $.expando = 'Zepto' + (+new Date()) | ||
10 | |||
11 | // Get value from node: | ||
12 | // 1. first try key as given, | ||
13 | // 2. then try camelized key, | ||
14 | // 3. fall back to reading "data-*" attribute. | ||
15 | function getData(node, name) { | ||
16 | var id = node[exp], store = id && data[id] | ||
17 | if (name === undefined) return store || setData(node) | ||
18 | else { | ||
19 | if (store) { | ||
20 | if (name in store) return store[name] | ||
21 | var camelName = camelize(name) | ||
22 | if (camelName in store) return store[camelName] | ||
23 | } | ||
24 | return dataAttr.call($(node), name) | ||
25 | } | ||
26 | } | ||
27 | |||
28 | // Store value under camelized key on node | ||
29 | function setData(node, name, value) { | ||
30 | var id = node[exp] || (node[exp] = ++$.uuid), | ||
31 | store = data[id] || (data[id] = attributeData(node)) | ||
32 | if (name !== undefined) store[camelize(name)] = value | ||
33 | return store | ||
34 | } | ||
35 | |||
36 | // Read all "data-*" attributes from a node | ||
37 | function attributeData(node) { | ||
38 | var store = {} | ||
39 | $.each(node.attributes, function(i, attr){ | ||
40 | if (attr.name.indexOf('data-') == 0) | ||
41 | store[camelize(attr.name.replace('data-', ''))] = | ||
42 | $.zepto.deserializeValue(attr.value) | ||
43 | }) | ||
44 | return store | ||
45 | } | ||
46 | |||
47 | $.fn.data = function(name, value) { | ||
48 | return value === undefined ? | ||
49 | // set multiple values via object | ||
50 | $.isPlainObject(name) ? | ||
51 | this.each(function(i, node){ | ||
52 | $.each(name, function(key, value){ setData(node, key, value) }) | ||
53 | }) : | ||
54 | // get value from first element | ||
55 | this.length == 0 ? undefined : getData(this[0], name) : | ||
56 | // set value on all elements | ||
57 | this.each(function(){ setData(this, name, value) }) | ||
58 | } | ||
59 | |||
60 | $.fn.removeData = function(names) { | ||
61 | if (typeof names == 'string') names = names.split(/\s+/) | ||
62 | return this.each(function(){ | ||
63 | var id = this[exp], store = id && data[id] | ||
64 | if (store) $.each(names, function(){ delete store[camelize(this)] }) | ||
65 | }) | ||
66 | } | ||
67 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/detect.js b/frontend/gamma/js/Zepto/detect.js new file mode 100644 index 0000000..22c0386 --- a/dev/null +++ b/frontend/gamma/js/Zepto/detect.js | |||
@@ -0,0 +1,42 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function($){ | ||
6 | function detect(ua){ | ||
7 | var os = this.os = {}, browser = this.browser = {}, | ||
8 | webkit = ua.match(/WebKit\/([\d.]+)/), | ||
9 | android = ua.match(/(Android)\s+([\d.]+)/), | ||
10 | ipad = ua.match(/(iPad).*OS\s([\d_]+)/), | ||
11 | iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/), | ||
12 | webos = ua.match(/(webOS|hpwOS)[\s\/]([\d.]+)/), | ||
13 | touchpad = webos && ua.match(/TouchPad/), | ||
14 | kindle = ua.match(/Kindle\/([\d.]+)/), | ||
15 | silk = ua.match(/Silk\/([\d._]+)/), | ||
16 | blackberry = ua.match(/(BlackBerry).*Version\/([\d.]+)/), | ||
17 | chrome = ua.match(/Chrome\/([\d.]+)/) || ua.match(/CriOS\/([\d.]+)/) | ||
18 | |||
19 | // todo clean this up with a better OS/browser | ||
20 | // separation. we need to discern between multiple | ||
21 | // browsers on android, and decide if kindle fire in | ||
22 | // silk mode is android or not | ||
23 | |||
24 | if (browser.webkit = !!webkit) browser.version = webkit[1] | ||
25 | |||
26 | if (android) os.android = true, os.version = android[2] | ||
27 | if (iphone) os.ios = os.iphone = true, os.version = iphone[2].replace(/_/g, '.') | ||
28 | if (ipad) os.ios = os.ipad = true, os.version = ipad[2].replace(/_/g, '.') | ||
29 | if (webos) os.webos = true, os.version = webos[2] | ||
30 | if (touchpad) os.touchpad = true | ||
31 | if (blackberry) os.blackberry = true, os.version = blackberry[2] | ||
32 | if (kindle) os.kindle = true, os.version = kindle[1] | ||
33 | if (silk) browser.silk = true, browser.version = silk[1] | ||
34 | if (!silk && os.android && ua.match(/Kindle Fire/)) browser.silk = true | ||
35 | if (chrome) browser.chrome = true, browser.version = chrome[1] | ||
36 | } | ||
37 | |||
38 | detect.call($, navigator.userAgent) | ||
39 | // make available to unit tests | ||
40 | $.__detect = detect | ||
41 | |||
42 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/event.js b/frontend/gamma/js/Zepto/event.js new file mode 100644 index 0000000..b40af22 --- a/dev/null +++ b/frontend/gamma/js/Zepto/event.js | |||
@@ -0,0 +1,248 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function($){ | ||
6 | var $$ = $.zepto.qsa, handlers = {}, _zid = 1, specialEvents={}, | ||
7 | hover = { mouseenter: 'mouseover', mouseleave: 'mouseout' } | ||
8 | |||
9 | specialEvents.click = specialEvents.mousedown = specialEvents.mouseup = specialEvents.mousemove = 'MouseEvents' | ||
10 | |||
11 | function zid(element) { | ||
12 | return element._zid || (element._zid = _zid++) | ||
13 | } | ||
14 | function findHandlers(element, event, fn, selector) { | ||
15 | event = parse(event) | ||
16 | if (event.ns) var matcher = matcherFor(event.ns) | ||
17 | return (handlers[zid(element)] || []).filter(function(handler) { | ||
18 | return handler | ||
19 | && (!event.e || handler.e == event.e) | ||
20 | && (!event.ns || matcher.test(handler.ns)) | ||
21 | && (!fn || zid(handler.fn) === zid(fn)) | ||
22 | && (!selector || handler.sel == selector) | ||
23 | }) | ||
24 | } | ||
25 | function parse(event) { | ||
26 | var parts = ('' + event).split('.') | ||
27 | return {e: parts[0], ns: parts.slice(1).sort().join(' ')} | ||
28 | } | ||
29 | function matcherFor(ns) { | ||
30 | return new RegExp('(?:^| )' + ns.replace(' ', ' .* ?') + '(?: |$)') | ||
31 | } | ||
32 | |||
33 | function eachEvent(events, fn, iterator){ | ||
34 | if ($.isObject(events)) $.each(events, iterator) | ||
35 | else events.split(/\s/).forEach(function(type){ iterator(type, fn) }) | ||
36 | } | ||
37 | |||
38 | function eventCapture(handler, captureSetting) { | ||
39 | return handler.del && | ||
40 | (handler.e == 'focus' || handler.e == 'blur') || | ||
41 | !!captureSetting | ||
42 | } | ||
43 | |||
44 | function realEvent(type) { | ||
45 | return hover[type] || type | ||
46 | } | ||
47 | |||
48 | function add(element, events, fn, selector, getDelegate, capture){ | ||
49 | var id = zid(element), set = (handlers[id] || (handlers[id] = [])) | ||
50 | eachEvent(events, fn, function(event, fn){ | ||
51 | var handler = parse(event) | ||
52 | handler.fn = fn | ||
53 | handler.sel = selector | ||
54 | // emulate mouseenter, mouseleave | ||
55 | if (handler.e in hover) fn = function(e){ | ||
56 | var related = e.relatedTarget | ||
57 | if (!related || (related !== this && !$.contains(this, related))) | ||
58 | return handler.fn.apply(this, arguments) | ||
59 | } | ||
60 | handler.del = getDelegate && getDelegate(fn, event) | ||
61 | var callback = handler.del || fn | ||
62 | handler.proxy = function (e) { | ||
63 | var result = callback.apply(element, [e].concat(e.data)) | ||
64 | if (result === false) e.preventDefault(), e.stopPropagation() | ||
65 | return result | ||
66 | } | ||
67 | handler.i = set.length | ||
68 | set.push(handler) | ||
69 | element.addEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture)) | ||
70 | }) | ||
71 | } | ||
72 | function remove(element, events, fn, selector, capture){ | ||
73 | var id = zid(element) | ||
74 | eachEvent(events || '', fn, function(event, fn){ | ||
75 | findHandlers(element, event, fn, selector).forEach(function(handler){ | ||
76 | delete handlers[id][handler.i] | ||
77 | element.removeEventListener(realEvent(handler.e), handler.proxy, eventCapture(handler, capture)) | ||
78 | }) | ||
79 | }) | ||
80 | } | ||
81 | |||
82 | $.event = { add: add, remove: remove } | ||
83 | |||
84 | $.proxy = function(fn, context) { | ||
85 | if ($.isFunction(fn)) { | ||
86 | var proxyFn = function(){ return fn.apply(context, arguments) } | ||
87 | proxyFn._zid = zid(fn) | ||
88 | return proxyFn | ||
89 | } else if (typeof context == 'string') { | ||
90 | return $.proxy(fn[context], fn) | ||
91 | } else { | ||
92 | throw new TypeError("expected function") | ||
93 | } | ||
94 | } | ||
95 | |||
96 | $.fn.bind = function(event, callback){ | ||
97 | return this.each(function(){ | ||
98 | add(this, event, callback) | ||
99 | }) | ||
100 | } | ||
101 | $.fn.unbind = function(event, callback){ | ||
102 | return this.each(function(){ | ||
103 | remove(this, event, callback) | ||
104 | }) | ||
105 | } | ||
106 | $.fn.one = function(event, callback){ | ||
107 | return this.each(function(i, element){ | ||
108 | add(this, event, callback, null, function(fn, type){ | ||
109 | return function(){ | ||
110 | var result = fn.apply(element, arguments) | ||
111 | remove(element, type, fn) | ||
112 | return result | ||
113 | } | ||
114 | }) | ||
115 | }) | ||
116 | } | ||
117 | |||
118 | var returnTrue = function(){return true}, | ||
119 | returnFalse = function(){return false}, | ||
120 | ignoreProperties = /^([A-Z]|layer[XY]$)/, | ||
121 | eventMethods = { | ||
122 | preventDefault: 'isDefaultPrevented', | ||
123 | stopImmediatePropagation: 'isImmediatePropagationStopped', | ||
124 | stopPropagation: 'isPropagationStopped' | ||
125 | } | ||
126 | function createProxy(event) { | ||
127 | var key, proxy = { originalEvent: event } | ||
128 | for (key in event) | ||
129 | if (!ignoreProperties.test(key) && event[key] !== undefined) proxy[key] = event[key] | ||
130 | |||
131 | $.each(eventMethods, function(name, predicate) { | ||
132 | proxy[name] = function(){ | ||
133 | this[predicate] = returnTrue | ||
134 | return event[name].apply(event, arguments) | ||
135 | } | ||
136 | proxy[predicate] = returnFalse | ||
137 | }) | ||
138 | return proxy | ||
139 | } | ||
140 | |||
141 | // emulates the 'defaultPrevented' property for browsers that have none | ||
142 | function fix(event) { | ||
143 | if (!('defaultPrevented' in event)) { | ||
144 | event.defaultPrevented = false | ||
145 | var prevent = event.preventDefault | ||
146 | event.preventDefault = function() { | ||
147 | this.defaultPrevented = true | ||
148 | prevent.call(this) | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
153 | $.fn.delegate = function(selector, event, callback){ | ||
154 | return this.each(function(i, element){ | ||
155 | add(element, event, callback, selector, function(fn){ | ||
156 | return function(e){ | ||
157 | var evt, match = $(e.target).closest(selector, element).get(0) | ||
158 | if (match) { | ||
159 | evt = $.extend(createProxy(e), {currentTarget: match, liveFired: element}) | ||
160 | return fn.apply(match, [evt].concat([].slice.call(arguments, 1))) | ||
161 | } | ||
162 | } | ||
163 | }) | ||
164 | }) | ||
165 | } | ||
166 | $.fn.undelegate = function(selector, event, callback){ | ||
167 | return this.each(function(){ | ||
168 | remove(this, event, callback, selector) | ||
169 | }) | ||
170 | } | ||
171 | |||
172 | $.fn.live = function(event, callback){ | ||
173 | $(document.body).delegate(this.selector, event, callback) | ||
174 | return this | ||
175 | } | ||
176 | $.fn.die = function(event, callback){ | ||
177 | $(document.body).undelegate(this.selector, event, callback) | ||
178 | return this | ||
179 | } | ||
180 | |||
181 | $.fn.on = function(event, selector, callback){ | ||
182 | return !selector || $.isFunction(selector) ? | ||
183 | this.bind(event, selector || callback) : this.delegate(selector, event, callback) | ||
184 | } | ||
185 | $.fn.off = function(event, selector, callback){ | ||
186 | return !selector || $.isFunction(selector) ? | ||
187 | this.unbind(event, selector || callback) : this.undelegate(selector, event, callback) | ||
188 | } | ||
189 | |||
190 | $.fn.trigger = function(event, data){ | ||
191 | if (typeof event == 'string' || $.isPlainObject(event)) event = $.Event(event) | ||
192 | fix(event) | ||
193 | event.data = data | ||
194 | return this.each(function(){ | ||
195 | // items in the collection might not be DOM elements | ||
196 | // (todo: possibly support events on plain old objects) | ||
197 | if('dispatchEvent' in this) this.dispatchEvent(event) | ||
198 | }) | ||
199 | } | ||
200 | |||
201 | // triggers event handlers on current element just as if an event occurred, | ||
202 | // doesn't trigger an actual event, doesn't bubble | ||
203 | $.fn.triggerHandler = function(event, data){ | ||
204 | var e, result | ||
205 | this.each(function(i, element){ | ||
206 | e = createProxy(typeof event == 'string' ? $.Event(event) : event) | ||
207 | e.data = data | ||
208 | e.target = element | ||
209 | $.each(findHandlers(element, event.type || event), function(i, handler){ | ||
210 | result = handler.proxy(e) | ||
211 | if (e.isImmediatePropagationStopped()) return false | ||
212 | }) | ||
213 | }) | ||
214 | return result | ||
215 | } | ||
216 | |||
217 | // shortcut methods for `.bind(event, fn)` for each event type | ||
218 | ;('focusin focusout load resize scroll unload click dblclick '+ | ||
219 | 'mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave '+ | ||
220 | 'change select keydown keypress keyup error').split(' ').forEach(function(event) { | ||
221 | $.fn[event] = function(callback) { | ||
222 | return callback ? | ||
223 | this.bind(event, callback) : | ||
224 | this.trigger(event) | ||
225 | } | ||
226 | }) | ||
227 | |||
228 | ;['focus', 'blur'].forEach(function(name) { | ||
229 | $.fn[name] = function(callback) { | ||
230 | if (callback) this.bind(name, callback) | ||
231 | else this.each(function(){ | ||
232 | try { this[name]() } | ||
233 | catch(e) {} | ||
234 | }) | ||
235 | return this | ||
236 | } | ||
237 | }) | ||
238 | |||
239 | $.Event = function(type, props) { | ||
240 | if (typeof type != 'string') props = type, type = props.type | ||
241 | var event = document.createEvent(specialEvents[type] || 'Events'), bubbles = true | ||
242 | if (props) for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (event[name] = props[name]) | ||
243 | event.initEvent(type, bubbles, true, null, null, null, null, null, null, null, null, null, null, null, null) | ||
244 | event.isDefaultPrevented = function(){ return this.defaultPrevented } | ||
245 | return event | ||
246 | } | ||
247 | |||
248 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/form.js b/frontend/gamma/js/Zepto/form.js new file mode 100644 index 0000000..4d562a6 --- a/dev/null +++ b/frontend/gamma/js/Zepto/form.js | |||
@@ -0,0 +1,40 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function ($) { | ||
6 | $.fn.serializeArray = function () { | ||
7 | var result = [], el | ||
8 | $( Array.prototype.slice.call(this.get(0).elements) ).each(function () { | ||
9 | el = $(this) | ||
10 | var type = el.attr('type') | ||
11 | if (this.nodeName.toLowerCase() != 'fieldset' && | ||
12 | !this.disabled && type != 'submit' && type != 'reset' && type != 'button' && | ||
13 | ((type != 'radio' && type != 'checkbox') || this.checked)) | ||
14 | result.push({ | ||
15 | name: el.attr('name'), | ||
16 | value: el.val() | ||
17 | }) | ||
18 | }) | ||
19 | return result | ||
20 | } | ||
21 | |||
22 | $.fn.serialize = function () { | ||
23 | var result = [] | ||
24 | this.serializeArray().forEach(function (elm) { | ||
25 | result.push( encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value) ) | ||
26 | }) | ||
27 | return result.join('&') | ||
28 | } | ||
29 | |||
30 | $.fn.submit = function (callback) { | ||
31 | if (callback) this.bind('submit', callback) | ||
32 | else if (this.length) { | ||
33 | var event = $.Event('submit') | ||
34 | this.eq(0).trigger(event) | ||
35 | if (!event.defaultPrevented) this.get(0).submit() | ||
36 | } | ||
37 | return this | ||
38 | } | ||
39 | |||
40 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/fx.js b/frontend/gamma/js/Zepto/fx.js new file mode 100644 index 0000000..575449a --- a/dev/null +++ b/frontend/gamma/js/Zepto/fx.js | |||
@@ -0,0 +1,102 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function($, undefined){ | ||
6 | var prefix = '', eventPrefix, endEventName, endAnimationName, | ||
7 | vendors = { Webkit: 'webkit', Moz: '', O: 'o', ms: 'MS' }, | ||
8 | document = window.document, testEl = document.createElement('div'), | ||
9 | supportedTransforms = /^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i, | ||
10 | transform, | ||
11 | transitionProperty, transitionDuration, transitionTiming, | ||
12 | animationName, animationDuration, animationTiming, | ||
13 | cssReset = {} | ||
14 | |||
15 | function dasherize(str) { return downcase(str.replace(/([a-z])([A-Z])/, '$1-$2')) } | ||
16 | function downcase(str) { return str.toLowerCase() } | ||
17 | function normalizeEvent(name) { return eventPrefix ? eventPrefix + name : downcase(name) } | ||
18 | |||
19 | $.each(vendors, function(vendor, event){ | ||
20 | if (testEl.style[vendor + 'TransitionProperty'] !== undefined) { | ||
21 | prefix = '-' + downcase(vendor) + '-' | ||
22 | eventPrefix = event | ||
23 | return false | ||
24 | } | ||
25 | }) | ||
26 | |||
27 | transform = prefix + 'transform' | ||
28 | cssReset[transitionProperty = prefix + 'transition-property'] = | ||
29 | cssReset[transitionDuration = prefix + 'transition-duration'] = | ||
30 | cssReset[transitionTiming = prefix + 'transition-timing-function'] = | ||
31 | cssReset[animationName = prefix + 'animation-name'] = | ||
32 | cssReset[animationDuration = prefix + 'animation-duration'] = | ||
33 | cssReset[animationTiming = prefix + 'animation-timing-function'] = '' | ||
34 | |||
35 | $.fx = { | ||
36 | off: (eventPrefix === undefined && testEl.style.transitionProperty === undefined), | ||
37 | speeds: { _default: 400, fast: 200, slow: 600 }, | ||
38 | cssPrefix: prefix, | ||
39 | transitionEnd: normalizeEvent('TransitionEnd'), | ||
40 | animationEnd: normalizeEvent('AnimationEnd') | ||
41 | } | ||
42 | |||
43 | $.fn.animate = function(properties, duration, ease, callback){ | ||
44 | if ($.isObject(duration)) | ||
45 | ease = duration.easing, callback = duration.complete, duration = duration.duration | ||
46 | if (duration) duration = (typeof duration == 'number' ? duration : | ||
47 | ($.fx.speeds[duration] || $.fx.speeds._default)) / 1000 | ||
48 | return this.anim(properties, duration, ease, callback) | ||
49 | } | ||
50 | |||
51 | $.fn.anim = function(properties, duration, ease, callback){ | ||
52 | var key, cssValues = {}, cssProperties, transforms = '', | ||
53 | that = this, wrappedCallback, endEvent = $.fx.transitionEnd | ||
54 | |||
55 | if (duration === undefined) duration = 0.4 | ||
56 | if ($.fx.off) duration = 0 | ||
57 | |||
58 | if (typeof properties == 'string') { | ||
59 | // keyframe animation | ||
60 | cssValues[animationName] = properties | ||
61 | cssValues[animationDuration] = duration + 's' | ||
62 | cssValues[animationTiming] = (ease || 'linear') | ||
63 | endEvent = $.fx.animationEnd | ||
64 | } else { | ||
65 | cssProperties = [] | ||
66 | // CSS transitions | ||
67 | for (key in properties) | ||
68 | if (supportedTransforms.test(key)) transforms += key + '(' + properties[key] + ') ' | ||
69 | else cssValues[key] = properties[key], cssProperties.push(dasherize(key)) | ||
70 | |||
71 | if (transforms) cssValues[transform] = transforms, cssProperties.push(transform) | ||
72 | if (duration > 0 && typeof properties === 'object') { | ||
73 | cssValues[transitionProperty] = cssProperties.join(', ') | ||
74 | cssValues[transitionDuration] = duration + 's' | ||
75 | cssValues[transitionTiming] = (ease || 'linear') | ||
76 | } | ||
77 | } | ||
78 | |||
79 | wrappedCallback = function(event){ | ||
80 | if (typeof event !== 'undefined') { | ||
81 | if (event.target !== event.currentTarget) return // makes sure the event didn't bubble from "below" | ||
82 | $(event.target).unbind(endEvent, arguments.callee) | ||
83 | } | ||
84 | $(this).css(cssReset) | ||
85 | callback && callback.call(this) | ||
86 | } | ||
87 | if (duration > 0) this.bind(endEvent, wrappedCallback) | ||
88 | |||
89 | // trigger page reflow so new elements can animate | ||
90 | this.size() && this.get(0).clientLeft | ||
91 | |||
92 | this.css(cssValues) | ||
93 | |||
94 | if (duration <= 0) setTimeout(function() { | ||
95 | that.each(function(){ wrappedCallback.call(this) }) | ||
96 | }, 0) | ||
97 | |||
98 | return this | ||
99 | } | ||
100 | |||
101 | testEl = null | ||
102 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/fx_methods.js b/frontend/gamma/js/Zepto/fx_methods.js new file mode 100644 index 0000000..23daf6e --- a/dev/null +++ b/frontend/gamma/js/Zepto/fx_methods.js | |||
@@ -0,0 +1,71 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function($, undefined){ | ||
6 | var document = window.document, docElem = document.documentElement, | ||
7 | origShow = $.fn.show, origHide = $.fn.hide, origToggle = $.fn.toggle | ||
8 | |||
9 | function anim(el, speed, opacity, scale, callback) { | ||
10 | if (typeof speed == 'function' && !callback) callback = speed, speed = undefined | ||
11 | var props = { opacity: opacity } | ||
12 | if (scale) { | ||
13 | props.scale = scale | ||
14 | el.css($.fx.cssPrefix + 'transform-origin', '0 0') | ||
15 | } | ||
16 | return el.animate(props, speed, null, callback) | ||
17 | } | ||
18 | |||
19 | function hide(el, speed, scale, callback) { | ||
20 | return anim(el, speed, 0, scale, function(){ | ||
21 | origHide.call($(this)) | ||
22 | callback && callback.call(this) | ||
23 | }) | ||
24 | } | ||
25 | |||
26 | $.fn.show = function(speed, callback) { | ||
27 | origShow.call(this) | ||
28 | if (speed === undefined) speed = 0 | ||
29 | else this.css('opacity', 0) | ||
30 | return anim(this, speed, 1, '1,1', callback) | ||
31 | } | ||
32 | |||
33 | $.fn.hide = function(speed, callback) { | ||
34 | if (speed === undefined) return origHide.call(this) | ||
35 | else return hide(this, speed, '0,0', callback) | ||
36 | } | ||
37 | |||
38 | $.fn.toggle = function(speed, callback) { | ||
39 | if (speed === undefined || typeof speed == 'boolean') | ||
40 | return origToggle.call(this, speed) | ||
41 | else return this.each(function(){ | ||
42 | var el = $(this) | ||
43 | el[el.css('display') == 'none' ? 'show' : 'hide'](speed, callback) | ||
44 | }) | ||
45 | } | ||
46 | |||
47 | $.fn.fadeTo = function(speed, opacity, callback) { | ||
48 | return anim(this, speed, opacity, null, callback) | ||
49 | } | ||
50 | |||
51 | $.fn.fadeIn = function(speed, callback) { | ||
52 | var target = this.css('opacity') | ||
53 | if (target > 0) this.css('opacity', 0) | ||
54 | else target = 1 | ||
55 | return origShow.call(this).fadeTo(speed, target, callback) | ||
56 | } | ||
57 | |||
58 | $.fn.fadeOut = function(speed, callback) { | ||
59 | return hide(this, speed, null, callback) | ||
60 | } | ||
61 | |||
62 | $.fn.fadeToggle = function(speed, callback) { | ||
63 | return this.each(function(){ | ||
64 | var el = $(this) | ||
65 | el[ | ||
66 | (el.css('opacity') == 0 || el.css('display') == 'none') ? 'fadeIn' : 'fadeOut' | ||
67 | ](speed, callback) | ||
68 | }) | ||
69 | } | ||
70 | |||
71 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/gesture.js b/frontend/gamma/js/Zepto/gesture.js new file mode 100644 index 0000000..035455b --- a/dev/null +++ b/frontend/gamma/js/Zepto/gesture.js | |||
@@ -0,0 +1,35 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function($){ | ||
6 | if ($.os.ios) { | ||
7 | var gesture = {}, gestureTimeout | ||
8 | |||
9 | function parentIfText(node){ | ||
10 | return 'tagName' in node ? node : node.parentNode | ||
11 | } | ||
12 | |||
13 | $(document).bind('gesturestart', function(e){ | ||
14 | var now = Date.now(), delta = now - (gesture.last || now) | ||
15 | gesture.target = parentIfText(e.target) | ||
16 | gestureTimeout && clearTimeout(gestureTimeout) | ||
17 | gesture.e1 = e.scale | ||
18 | gesture.last = now | ||
19 | }).bind('gesturechange', function(e){ | ||
20 | gesture.e2 = e.scale | ||
21 | }).bind('gestureend', function(e){ | ||
22 | if (gesture.e2 > 0) { | ||
23 | Math.abs(gesture.e1 - gesture.e2) != 0 && $(gesture.target).trigger('pinch') && | ||
24 | $(gesture.target).trigger('pinch' + (gesture.e1 - gesture.e2 > 0 ? 'In' : 'Out')) | ||
25 | gesture.e1 = gesture.e2 = gesture.last = 0 | ||
26 | } else if ('last' in gesture) { | ||
27 | gesture = {} | ||
28 | } | ||
29 | }) | ||
30 | |||
31 | ;['pinch', 'pinchIn', 'pinchOut'].forEach(function(m){ | ||
32 | $.fn[m] = function(callback){ return this.bind(m, callback) } | ||
33 | }) | ||
34 | } | ||
35 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/polyfill.js b/frontend/gamma/js/Zepto/polyfill.js new file mode 100644 index 0000000..933d1f8 --- a/dev/null +++ b/frontend/gamma/js/Zepto/polyfill.js | |||
@@ -0,0 +1,36 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function(undefined){ | ||
6 | if (String.prototype.trim === undefined) // fix for iOS 3.2 | ||
7 | String.prototype.trim = function(){ return this.replace(/^\s+/, '').replace(/\s+$/, '') } | ||
8 | |||
9 | // For iOS 3.x | ||
10 | // from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce | ||
11 | if (Array.prototype.reduce === undefined) | ||
12 | Array.prototype.reduce = function(fun){ | ||
13 | if(this === void 0 || this === null) throw new TypeError() | ||
14 | var t = Object(this), len = t.length >>> 0, k = 0, accumulator | ||
15 | if(typeof fun != 'function') throw new TypeError() | ||
16 | if(len == 0 && arguments.length == 1) throw new TypeError() | ||
17 | |||
18 | if(arguments.length >= 2) | ||
19 | accumulator = arguments[1] | ||
20 | else | ||
21 | do{ | ||
22 | if(k in t){ | ||
23 | accumulator = t[k++] | ||
24 | break | ||
25 | } | ||
26 | if(++k >= len) throw new TypeError() | ||
27 | } while (true) | ||
28 | |||
29 | while (k < len){ | ||
30 | if(k in t) accumulator = fun.call(undefined, accumulator, t[k], k, t) | ||
31 | k++ | ||
32 | } | ||
33 | return accumulator | ||
34 | } | ||
35 | |||
36 | })() | ||
diff --git a/frontend/gamma/js/Zepto/selector.js b/frontend/gamma/js/Zepto/selector.js new file mode 100644 index 0000000..c0b035a --- a/dev/null +++ b/frontend/gamma/js/Zepto/selector.js | |||
@@ -0,0 +1,81 @@ | |||
1 | ;(function($){ | ||
2 | var zepto = $.zepto, oldQsa = zepto.qsa, oldMatches = zepto.matches | ||
3 | |||
4 | function visible(elem){ | ||
5 | elem = $(elem) | ||
6 | return !!(elem.width() || elem.height()) && elem.css("display") !== "none" | ||
7 | } | ||
8 | |||
9 | // Implements a subset from: | ||
10 | // http://api.jquery.com/category/selectors/jquery-selector-extensions/ | ||
11 | // | ||
12 | // Each filter function receives the current index, all nodes in the | ||
13 | // considered set, and a value if there were parentheses. The value | ||
14 | // of `this` is the node currently being considered. The function returns the | ||
15 | // resulting node(s), null, or undefined. | ||
16 | // | ||
17 | // Complex selectors are not supported: | ||
18 | // li:has(label:contains("foo")) + li:has(label:contains("bar")) | ||
19 | // ul.inner:first > li | ||
20 | var filters = $.expr[':'] = { | ||
21 | visible: function(){ if (visible(this)) return this }, | ||
22 | hidden: function(){ if (!visible(this)) return this }, | ||
23 | selected: function(){ if (this.selected) return this }, | ||
24 | checked: function(){ if (this.checked) return this }, | ||
25 | parent: function(){ return this.parentNode }, | ||
26 | first: function(idx){ if (idx === 0) return this }, | ||
27 | last: function(idx, nodes){ if (idx === nodes.length - 1) return this }, | ||
28 | eq: function(idx, _, value){ if (idx === value) return this }, | ||
29 | contains: function(idx, _, text){ if ($(this).text().indexOf(text) > -1) return this }, | ||
30 | has: function(idx, _, sel){ if (zepto.qsa(this, sel).length) return this } | ||
31 | } | ||
32 | |||
33 | var filterRe = new RegExp('(.*):(\\w+)(?:\\(([^)]+)\\))?$\\s*'), | ||
34 | childRe = /^\s*>/, | ||
35 | classTag = 'Zepto' + (+new Date()) | ||
36 | |||
37 | function process(sel, fn) { | ||
38 | // quote the hash in `a[href^=#]` expression | ||
39 | sel = sel.replace(/=#\]/g, '="#"]') | ||
40 | var filter, arg, match = filterRe.exec(sel) | ||
41 | if (match && match[2] in filters) { | ||
42 | var filter = filters[match[2]], arg = match[3] | ||
43 | sel = match[1] | ||
44 | if (arg) { | ||
45 | var num = Number(arg) | ||
46 | if (isNaN(num)) arg = arg.replace(/^["']|["']$/g, '') | ||
47 | else arg = num | ||
48 | } | ||
49 | } | ||
50 | return fn(sel, filter, arg) | ||
51 | } | ||
52 | |||
53 | zepto.qsa = function(node, selector) { | ||
54 | return process(selector, function(sel, filter, arg){ | ||
55 | try { | ||
56 | var taggedParent | ||
57 | if (!sel && filter) sel = '*' | ||
58 | else if (childRe.test(sel)) | ||
59 | // support "> *" child queries by tagging the parent node with a | ||
60 | // unique class and prepending that classname onto the selector | ||
61 | taggedParent = $(node).addClass(classTag), sel = '.'+classTag+' '+sel | ||
62 | |||
63 | var nodes = oldQsa(node, sel) | ||
64 | } catch(e) { | ||
65 | console.error('error performing selector: %o', selector) | ||
66 | throw e | ||
67 | } finally { | ||
68 | if (taggedParent) taggedParent.removeClass(classTag) | ||
69 | } | ||
70 | return !filter ? nodes : | ||
71 | zepto.uniq($.map(nodes, function(n, i){ return filter.call(n, i, nodes, arg) })) | ||
72 | }) | ||
73 | } | ||
74 | |||
75 | zepto.matches = function(node, selector){ | ||
76 | return process(selector, function(sel, filter, arg){ | ||
77 | return (!sel || oldMatches(node, sel)) && | ||
78 | (!filter || filter.call(node, null, arg) === node) | ||
79 | }) | ||
80 | } | ||
81 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/stack.js b/frontend/gamma/js/Zepto/stack.js new file mode 100644 index 0000000..c995285 --- a/dev/null +++ b/frontend/gamma/js/Zepto/stack.js | |||
@@ -0,0 +1,22 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function($){ | ||
6 | $.fn.end = function(){ | ||
7 | return this.prevObject || $() | ||
8 | } | ||
9 | |||
10 | $.fn.andSelf = function(){ | ||
11 | return this.add(this.prevObject || $()) | ||
12 | } | ||
13 | |||
14 | 'filter,add,not,eq,first,last,find,closest,parents,parent,children,siblings'.split(',').forEach(function(property){ | ||
15 | var fn = $.fn[property] | ||
16 | $.fn[property] = function(){ | ||
17 | var ret = fn.apply(this, arguments) | ||
18 | ret.prevObject = this | ||
19 | return ret | ||
20 | } | ||
21 | }) | ||
22 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/touch.js b/frontend/gamma/js/Zepto/touch.js new file mode 100644 index 0000000..af109b9 --- a/dev/null +++ b/frontend/gamma/js/Zepto/touch.js | |||
@@ -0,0 +1,113 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | ;(function($){ | ||
6 | var touch = {}, | ||
7 | touchTimeout, tapTimeout, swipeTimeout, | ||
8 | longTapDelay = 750, longTapTimeout | ||
9 | |||
10 | function parentIfText(node) { | ||
11 | return 'tagName' in node ? node : node.parentNode | ||
12 | } | ||
13 | |||
14 | function swipeDirection(x1, x2, y1, y2) { | ||
15 | var xDelta = Math.abs(x1 - x2), yDelta = Math.abs(y1 - y2) | ||
16 | return xDelta >= yDelta ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down') | ||
17 | } | ||
18 | |||
19 | function longTap() { | ||
20 | longTapTimeout = null | ||
21 | if (touch.last) { | ||
22 | touch.el.trigger('longTap') | ||
23 | touch = {} | ||
24 | } | ||
25 | } | ||
26 | |||
27 | function cancelLongTap() { | ||
28 | if (longTapTimeout) clearTimeout(longTapTimeout) | ||
29 | longTapTimeout = null | ||
30 | } | ||
31 | |||
32 | function cancelAll() { | ||
33 | if (touchTimeout) clearTimeout(touchTimeout) | ||
34 | if (tapTimeout) clearTimeout(tapTimeout) | ||
35 | if (swipeTimeout) clearTimeout(swipeTimeout) | ||
36 | if (longTapTimeout) clearTimeout(longTapTimeout) | ||
37 | touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null | ||
38 | touch = {} | ||
39 | } | ||
40 | |||
41 | $(document).ready(function(){ | ||
42 | var now, delta | ||
43 | |||
44 | $(document.body) | ||
45 | .bind('touchstart', function(e){ | ||
46 | now = Date.now() | ||
47 | delta = now - (touch.last || now) | ||
48 | touch.el = $(parentIfText(e.touches[0].target)) | ||
49 | touchTimeout && clearTimeout(touchTimeout) | ||
50 | touch.x1 = e.touches[0].pageX | ||
51 | touch.y1 = e.touches[0].pageY | ||
52 | if (delta > 0 && delta <= 250) touch.isDoubleTap = true | ||
53 | touch.last = now | ||
54 | longTapTimeout = setTimeout(longTap, longTapDelay) | ||
55 | }) | ||
56 | .bind('touchmove', function(e){ | ||
57 | cancelLongTap() | ||
58 | touch.x2 = e.touches[0].pageX | ||
59 | touch.y2 = e.touches[0].pageY | ||
60 | }) | ||
61 | .bind('touchend', function(e){ | ||
62 | cancelLongTap() | ||
63 | |||
64 | // swipe | ||
65 | if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) || | ||
66 | (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30)) | ||
67 | |||
68 | swipeTimeout = setTimeout(function() { | ||
69 | touch.el.trigger('swipe') | ||
70 | touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2))) | ||
71 | touch = {} | ||
72 | }, 0) | ||
73 | |||
74 | // normal tap | ||
75 | else if ('last' in touch) | ||
76 | |||
77 | // delay by one tick so we can cancel the 'tap' event if 'scroll' fires | ||
78 | // ('tap' fires before 'scroll') | ||
79 | tapTimeout = setTimeout(function() { | ||
80 | |||
81 | // trigger universal 'tap' with the option to cancelTouch() | ||
82 | // (cancelTouch cancels processing of single vs double taps for faster 'tap' response) | ||
83 | var event = $.Event('tap') | ||
84 | event.cancelTouch = cancelAll | ||
85 | touch.el.trigger(event) | ||
86 | |||
87 | // trigger double tap immediately | ||
88 | if (touch.isDoubleTap) { | ||
89 | touch.el.trigger('doubleTap') | ||
90 | touch = {} | ||
91 | } | ||
92 | |||
93 | // trigger single tap after 250ms of inactivity | ||
94 | else { | ||
95 | touchTimeout = setTimeout(function(){ | ||
96 | touchTimeout = null | ||
97 | touch.el.trigger('singleTap') | ||
98 | touch = {} | ||
99 | }, 250) | ||
100 | } | ||
101 | |||
102 | }, 0) | ||
103 | |||
104 | }) | ||
105 | .bind('touchcancel', cancelAll) | ||
106 | |||
107 | $(window).bind('scroll', cancelAll) | ||
108 | }) | ||
109 | |||
110 | ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(m){ | ||
111 | $.fn[m] = function(callback){ return this.bind(m, callback) } | ||
112 | }) | ||
113 | })(Zepto) | ||
diff --git a/frontend/gamma/js/Zepto/zepto.js b/frontend/gamma/js/Zepto/zepto.js new file mode 100644 index 0000000..e67b3a2 --- a/dev/null +++ b/frontend/gamma/js/Zepto/zepto.js | |||
@@ -0,0 +1,751 @@ | |||
1 | // Zepto.js | ||
2 | // (c) 2010-2012 Thomas Fuchs | ||
3 | // Zepto.js may be freely distributed under the MIT license. | ||
4 | |||
5 | var Zepto = (function() { | ||
6 | var undefined, key, $, classList, emptyArray = [], slice = emptyArray.slice, filter = emptyArray.filter, | ||
7 | document = window.document, | ||
8 | elementDisplay = {}, classCache = {}, | ||
9 | getComputedStyle = document.defaultView.getComputedStyle, | ||
10 | cssNumber = { 'column-count': 1, 'columns': 1, 'font-weight': 1, 'line-height': 1,'opacity': 1, 'z-index': 1, 'zoom': 1 }, | ||
11 | fragmentRE = /^\s*<(\w+|!)[^>]*>/, | ||
12 | tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, | ||
13 | rootNodeRE = /^(?:body|html)$/i, | ||
14 | |||
15 | // special attributes that should be get/set via method calls | ||
16 | methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'], | ||
17 | |||
18 | adjacencyOperators = [ 'after', 'prepend', 'before', 'append' ], | ||
19 | table = document.createElement('table'), | ||
20 | tableRow = document.createElement('tr'), | ||
21 | containers = { | ||
22 | 'tr': document.createElement('tbody'), | ||
23 | 'tbody': table, 'thead': table, 'tfoot': table, | ||
24 | 'td': tableRow, 'th': tableRow, | ||
25 | '*': document.createElement('div') | ||
26 | }, | ||
27 | readyRE = /complete|loaded|interactive/, | ||
28 | classSelectorRE = /^\.([\w-]+)$/, | ||
29 | idSelectorRE = /^#([\w-]*)$/, | ||
30 | tagSelectorRE = /^[\w-]+$/, | ||
31 | toString = {}.toString, | ||
32 | zepto = {}, | ||
33 | camelize, uniq, | ||
34 | tempParent = document.createElement('div') | ||
35 | |||
36 | zepto.matches = function(element, selector) { | ||
37 | if (!element || element.nodeType !== 1) return false | ||
38 | var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector || | ||
39 | element.oMatchesSelector || element.matchesSelector | ||
40 | if (matchesSelector) return matchesSelector.call(element, selector) | ||
41 | // fall back to performing a selector: | ||
42 | var match, parent = element.parentNode, temp = !parent | ||
43 | if (temp) (parent = tempParent).appendChild(element) | ||
44 | match = ~zepto.qsa(parent, selector).indexOf(element) | ||
45 | temp && tempParent.removeChild(element) | ||
46 | return match | ||
47 | } | ||
48 | |||
49 | function isFunction(value) { return toString.call(value) == "[object Function]" } | ||
50 | function isObject(value) { return value instanceof Object } | ||
51 | function isPlainObject(value) { | ||
52 | return isObject(value) && value != window && value.__proto__ == Object.prototype | ||
53 | } | ||
54 | function isArray(value) { return value instanceof Array } | ||
55 | function likeArray(obj) { return typeof obj.length == 'number' } | ||
56 | |||
57 | function compact(array) { return filter.call(array, function(item){ return item != null }) } | ||
58 | function flatten(array) { return array.length > 0 ? $.fn.concat.apply([], array) : array } | ||
59 | camelize = function(str){ return str.replace(/-+(.)?/g, function(match, chr){ return chr ? chr.toUpperCase() : '' }) } | ||
60 | function dasherize(str) { | ||
61 | return str.replace(/::/g, '/') | ||
62 | .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') | ||
63 | .replace(/([a-z\d])([A-Z])/g, '$1_$2') | ||
64 | .replace(/_/g, '-') | ||
65 | .toLowerCase() | ||
66 | } | ||
67 | uniq = function(array){ return filter.call(array, function(item, idx){ return array.indexOf(item) == idx }) } | ||
68 | |||
69 | function classRE(name) { | ||
70 | return name in classCache ? | ||
71 | classCache[name] : (classCache[name] = new RegExp('(^|\\s)' + name + '(\\s|$)')) | ||
72 | } | ||
73 | |||
74 | function maybeAddPx(name, value) { | ||
75 | return (typeof value == "number" && !cssNumber[dasherize(name)]) ? value + "px" : value | ||
76 | } | ||
77 | |||
78 | function defaultDisplay(nodeName) { | ||
79 | var element, display | ||
80 | if (!elementDisplay[nodeName]) { | ||
81 | element = document.createElement(nodeName) | ||
82 | document.body.appendChild(element) | ||
83 | display = getComputedStyle(element, '').getPropertyValue("display") | ||
84 | element.parentNode.removeChild(element) | ||
85 | display == "none" && (display = "block") | ||
86 | elementDisplay[nodeName] = display | ||
87 | } | ||
88 | return elementDisplay[nodeName] | ||
89 | } | ||
90 | |||
91 | function children(element) { | ||
92 | return 'children' in element ? | ||
93 | slice.call(element.children) : | ||
94 | $.map(element.childNodes, function(node){ if (node.nodeType == 1) return node }) | ||
95 | } | ||
96 | |||
97 | // `$.zepto.fragment` takes a html string and an optional tag name | ||
98 | // to generate DOM nodes nodes from the given html string. | ||
99 | // The generated DOM nodes are returned as an array. | ||
100 | // This function can be overriden in plugins for example to make | ||
101 | // it compatible with browsers that don't support the DOM fully. | ||
102 | zepto.fragment = function(html, name, properties) { | ||
103 | if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>") | ||
104 | if (name === undefined) name = fragmentRE.test(html) && RegExp.$1 | ||
105 | if (!(name in containers)) name = '*' | ||
106 | |||
107 | var nodes, dom, container = containers[name] | ||
108 | container.innerHTML = '' + html | ||
109 | dom = $.each(slice.call(container.childNodes), function(){ | ||
110 | container.removeChild(this) | ||
111 | }) | ||
112 | if (isPlainObject(properties)) { | ||
113 | nodes = $(dom) | ||
114 | $.each(properties, function(key, value) { | ||
115 | if (methodAttributes.indexOf(key) > -1) nodes[key](value) | ||
116 | else nodes.attr(key, value) | ||
117 | }) | ||
118 | } | ||
119 | return dom | ||
120 | } | ||
121 | |||
122 | // `$.zepto.Z` swaps out the prototype of the given `dom` array | ||
123 | // of nodes with `$.fn` and thus supplying all the Zepto functions | ||
124 | // to the array. Note that `__proto__` is not supported on Internet | ||
125 | // Explorer. This method can be overriden in plugins. | ||
126 | zepto.Z = function(dom, selector) { | ||
127 | dom = dom || [] | ||
128 | dom.__proto__ = arguments.callee.prototype | ||
129 | dom.selector = selector || '' | ||
130 | return dom | ||
131 | } | ||
132 | |||
133 | // `$.zepto.isZ` should return `true` if the given object is a Zepto | ||
134 | // collection. This method can be overriden in plugins. | ||
135 | zepto.isZ = function(object) { | ||
136 | return object instanceof zepto.Z | ||
137 | } | ||
138 | |||
139 | // `$.zepto.init` is Zepto's counterpart to jQuery's `$.fn.init` and | ||
140 | // takes a CSS selector and an optional context (and handles various | ||
141 | // special cases). | ||
142 | // This method can be overriden in plugins. | ||
143 | zepto.init = function(selector, context) { | ||
144 | // If nothing given, return an empty Zepto collection | ||
145 | if (!selector) return zepto.Z() | ||
146 | // If a function is given, call it when the DOM is ready | ||
147 | else if (isFunction(selector)) return $(document).ready(selector) | ||
148 | // If a Zepto collection is given, juts return it | ||
149 | else if (zepto.isZ(selector)) return selector | ||
150 | else { | ||
151 | var dom | ||
152 | // normalize array if an array of nodes is given | ||
153 | if (isArray(selector)) dom = compact(selector) | ||
154 | // Wrap DOM nodes. If a plain object is given, duplicate it. | ||
155 | else if (isObject(selector)) | ||
156 | dom = [isPlainObject(selector) ? $.extend({}, selector) : selector], selector = null | ||
157 | // If it's a html fragment, create nodes from it | ||
158 | else if (fragmentRE.test(selector)) | ||
159 | dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null | ||
160 | // If there's a context, create a collection on that context first, and select | ||
161 | // nodes from there | ||
162 | else if (context !== undefined) return $(context).find(selector) | ||
163 | // And last but no least, if it's a CSS selector, use it to select nodes. | ||
164 | else dom = zepto.qsa(document, selector) | ||
165 | // create a new Zepto collection from the nodes found | ||
166 | return zepto.Z(dom, selector) | ||
167 | } | ||
168 | } | ||
169 | |||
170 | // `$` will be the base `Zepto` object. When calling this | ||
171 | // function just call `$.zepto.init, which makes the implementation | ||
172 | // details of selecting nodes and creating Zepto collections | ||
173 | // patchable in plugins. | ||
174 | $ = function(selector, context){ | ||
175 | return zepto.init(selector, context) | ||
176 | } | ||
177 | |||
178 | function extend(target, source, deep) { | ||
179 | for (key in source) | ||
180 | if (deep && isPlainObject(source[key])) { | ||
181 | if (!isPlainObject(target[key])) target[key] = {} | ||
182 | extend(target[key], source[key], deep) | ||
183 | } | ||
184 | else if (source[key] !== undefined) target[key] = source[key] | ||
185 | } | ||
186 | |||
187 | // Copy all but undefined properties from one or more | ||
188 | // objects to the `target` object. | ||
189 | $.extend = function(target){ | ||
190 | var deep, args = slice.call(arguments, 1) | ||
191 | if (typeof target == 'boolean') { | ||
192 | deep = target | ||
193 | target = args.shift() | ||
194 | } | ||
195 | args.forEach(function(arg){ extend(target, arg, deep) }) | ||
196 | return target | ||
197 | } | ||
198 | |||
199 | // `$.zepto.qsa` is Zepto's CSS selector implementation which | ||
200 | // uses `document.querySelectorAll` and optimizes for some special cases, like `#id`. | ||
201 | // This method can be overriden in plugins. | ||
202 | zepto.qsa = function(element, selector){ | ||
203 | var found | ||
204 | return (element === document && idSelectorRE.test(selector)) ? | ||
205 | ( (found = element.getElementById(RegExp.$1)) ? [found] : [] ) : | ||
206 | (element.nodeType !== 1 && element.nodeType !== 9) ? [] : | ||
207 | slice.call( | ||
208 | classSelectorRE.test(selector) ? element.getElementsByClassName(RegExp.$1) : | ||
209 | tagSelectorRE.test(selector) ? element.getElementsByTagName(selector) : | ||
210 | element.querySelectorAll(selector) | ||
211 | ) | ||
212 | } | ||
213 | |||
214 | function filtered(nodes, selector) { | ||
215 | return selector === undefined ? $(nodes) : $(nodes).filter(selector) | ||
216 | } | ||
217 | |||
218 | $.contains = function(parent, node) { | ||
219 | return parent !== node && parent.contains(node) | ||
220 | } | ||
221 | |||
222 | function funcArg(context, arg, idx, payload) { | ||
223 | return isFunction(arg) ? arg.call(context, idx, payload) : arg | ||
224 | } | ||
225 | |||
226 | function setAttribute(node, name, value) { | ||
227 | value == null ? node.removeAttribute(name) : node.setAttribute(name, value) | ||
228 | } | ||
229 | |||
230 | // access className property while respecting SVGAnimatedString | ||
231 | function className(node, value){ | ||
232 | var klass = node.className, | ||
233 | svg = klass && klass.baseVal !== undefined | ||
234 | |||
235 | if (value === undefined) return svg ? klass.baseVal : klass | ||
236 | svg ? (klass.baseVal = value) : (node.className = value) | ||
237 | } | ||
238 | |||
239 | // "true" => true | ||
240 | // "false" => false | ||
241 | // "null" => null | ||
242 | // "42" => 42 | ||
243 | // "42.5" => 42.5 | ||
244 | // JSON => parse if valid | ||
245 | // String => self | ||
246 | function deserializeValue(value) { | ||
247 | var num | ||
248 | try { | ||
249 | return value ? | ||
250 | value == "true" || | ||
251 | ( value == "false" ? false : | ||
252 | value == "null" ? null : | ||
253 | !isNaN(num = Number(value)) ? num : | ||
254 | /^[\[\{]/.test(value) ? $.parseJSON(value) : | ||
255 | value ) | ||
256 | : value | ||
257 | } catch(e) { | ||
258 | return value | ||
259 | } | ||
260 | } | ||
261 | |||
262 | $.isFunction = isFunction | ||
263 | $.isObject = isObject | ||
264 | $.isArray = isArray | ||
265 | $.isPlainObject = isPlainObject | ||
266 | |||
267 | $.inArray = function(elem, array, i){ | ||
268 | return emptyArray.indexOf.call(array, elem, i) | ||
269 | } | ||
270 | |||
271 | $.camelCase = camelize | ||
272 | $.trim = function(str) { return str.trim() } | ||
273 | |||
274 | // plugin compatibility | ||
275 | $.uuid = 0 | ||
276 | $.support = { } | ||
277 | $.expr = { } | ||
278 | |||
279 | $.map = function(elements, callback){ | ||
280 | var value, values = [], i, key | ||
281 | if (likeArray(elements)) | ||
282 | for (i = 0; i < elements.length; i++) { | ||
283 | value = callback(elements[i], i) | ||
284 | if (value != null) values.push(value) | ||
285 | } | ||
286 | else | ||
287 | for (key in elements) { | ||
288 | value = callback(elements[key], key) | ||
289 | if (value != null) values.push(value) | ||
290 | } | ||
291 | return flatten(values) | ||
292 | } | ||
293 | |||
294 | $.each = function(elements, callback){ | ||
295 | var i, key | ||
296 | if (likeArray(elements)) { | ||
297 | for (i = 0; i < elements.length; i++) | ||
298 | if (callback.call(elements[i], i, elements[i]) === false) return elements | ||
299 | } else { | ||
300 | for (key in elements) | ||
301 | if (callback.call(elements[key], key, elements[key]) === false) return elements | ||
302 | } | ||
303 | |||
304 | return elements | ||
305 | } | ||
306 | |||
307 | $.grep = function(elements, callback){ | ||
308 | return filter.call(elements, callback) | ||
309 | } | ||
310 | |||
311 | if (window.JSON) $.parseJSON = JSON.parse | ||
312 | |||
313 | // Define methods that will be available on all | ||
314 | // Zepto collections | ||
315 | $.fn = { | ||
316 | // Because a collection acts like an array | ||
317 | // copy over these useful array functions. | ||
318 | forEach: emptyArray.forEach, | ||
319 | reduce: emptyArray.reduce, | ||
320 | push: emptyArray.push, | ||
321 | sort: emptyArray.sort, | ||
322 | indexOf: emptyArray.indexOf, | ||
323 | concat: emptyArray.concat, | ||
324 | |||
325 | // `map` and `slice` in the jQuery API work differently | ||
326 | // from their array counterparts | ||
327 | map: function(fn){ | ||
328 | return $($.map(this, function(el, i){ return fn.call(el, i, el) })) | ||
329 | }, | ||
330 | slice: function(){ | ||
331 | return $(slice.apply(this, arguments)) | ||
332 | }, | ||
333 | |||
334 | ready: function(callback){ | ||
335 | if (readyRE.test(document.readyState)) callback($) | ||
336 | else document.addEventListener('DOMContentLoaded', function(){ callback($) }, false) | ||
337 | return this | ||
338 | }, | ||
339 | get: function(idx){ | ||
340 | return idx === undefined ? slice.call(this) : this[idx] | ||
341 | }, | ||
342 | toArray: function(){ return this.get() }, | ||
343 | size: function(){ | ||
344 | return this.length | ||
345 | }, | ||
346 | remove: function(){ | ||
347 | return this.each(function(){ | ||
348 | if (this.parentNode != null) | ||
349 | this.parentNode.removeChild(this) | ||
350 | }) | ||
351 | }, | ||
352 | each: function(callback){ | ||
353 | emptyArray.every.call(this, function(el, idx){ | ||
354 | return callback.call(el, idx, el) !== false | ||
355 | }) | ||
356 | return this | ||
357 | }, | ||
358 | filter: function(selector){ | ||
359 | if (isFunction(selector)) return this.not(this.not(selector)) | ||
360 | return $(filter.call(this, function(element){ | ||
361 | return zepto.matches(element, selector) | ||
362 | })) | ||
363 | }, | ||
364 | add: function(selector,context){ | ||
365 | return $(uniq(this.concat($(selector,context)))) | ||
366 | }, | ||
367 | is: function(selector){ | ||
368 | return this.length > 0 && zepto.matches(this[0], selector) | ||
369 | }, | ||
370 | not: function(selector){ | ||
371 | var nodes=[] | ||
372 | if (isFunction(selector) && selector.call !== undefined) | ||
373 | this.each(function(idx){ | ||
374 | if (!selector.call(this,idx)) nodes.push(this) | ||
375 | }) | ||
376 | else { | ||
377 | var excludes = typeof selector == 'string' ? this.filter(selector) : | ||
378 | (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector) | ||
379 | this.forEach(function(el){ | ||
380 | if (excludes.indexOf(el) < 0) nodes.push(el) | ||
381 | }) | ||
382 | } | ||
383 | return $(nodes) | ||
384 | }, | ||
385 | has: function(selector){ | ||
386 | return this.filter(function(){ | ||
387 | return isObject(selector) ? | ||
388 | $.contains(this, selector) : | ||
389 | $(this).find(selector).size() | ||
390 | }) | ||
391 | }, | ||
392 | eq: function(idx){ | ||
393 | return idx === -1 ? this.slice(idx) : this.slice(idx, + idx + 1) | ||
394 | }, | ||
395 | first: function(){ | ||
396 | var el = this[0] | ||
397 | return el && !isObject(el) ? el : $(el) | ||
398 | }, | ||
399 | last: function(){ | ||
400 | var el = this[this.length - 1] | ||
401 | return el && !isObject(el) ? el : $(el) | ||
402 | }, | ||
403 | find: function(selector){ | ||
404 | var result | ||
405 | if (this.length == 1) result = $(zepto.qsa(this[0], selector)) | ||
406 | else result = this.map(function(){ return zepto.qsa(this, selector) }) | ||
407 | return result | ||
408 | }, | ||
409 | closest: function(selector, context){ | ||
410 | var node = this[0] | ||
411 | while (node && !zepto.matches(node, selector)) | ||
412 | node = node !== context && node !== document && node.parentNode | ||
413 | return $(node) | ||
414 | }, | ||
415 | parents: function(selector){ | ||
416 | var ancestors = [], nodes = this | ||
417 | while (nodes.length > 0) | ||
418 | nodes = $.map(nodes, function(node){ | ||
419 | if ((node = node.parentNode) && node !== document && ancestors.indexOf(node) < 0) { | ||
420 | ancestors.push(node) | ||
421 | return node | ||
422 | } | ||
423 | }) | ||
424 | return filtered(ancestors, selector) | ||
425 | }, | ||
426 | parent: function(selector){ | ||
427 | return filtered(uniq(this.pluck('parentNode')), selector) | ||
428 | }, | ||
429 | children: function(selector){ | ||
430 | return filtered(this.map(function(){ return children(this) }), selector) | ||
431 | }, | ||
432 | contents: function() { | ||
433 | return this.map(function() { return slice.call(this.childNodes) }) | ||
434 | }, | ||
435 | siblings: function(selector){ | ||
436 | return filtered(this.map(function(i, el){ | ||
437 | return filter.call(children(el.parentNode), function(child){ return child!==el }) | ||
438 | }), selector) | ||
439 | }, | ||
440 | empty: function(){ | ||
441 | return this.each(function(){ this.innerHTML = '' }) | ||
442 | }, | ||
443 | // `pluck` is borrowed from Prototype.js | ||
444 | pluck: function(property){ | ||
445 | return $.map(this, function(el){ return el[property] }) | ||
446 | }, | ||
447 | show: function(){ | ||
448 | return this.each(function(){ | ||
449 | this.style.display == "none" && (this.style.display = null) | ||
450 | if (getComputedStyle(this, '').getPropertyValue("display") == "none") | ||
451 | this.style.display = defaultDisplay(this.nodeName) | ||
452 | }) | ||
453 | }, | ||
454 | replaceWith: function(newContent){ | ||
455 | return this.before(newContent).remove() | ||
456 | }, | ||
457 | wrap: function(structure){ | ||
458 | var func = isFunction(structure) | ||
459 | if (this[0] && !func) | ||
460 | var dom = $(structure).get(0), | ||
461 | clone = dom.parentNode || this.length > 1 | ||
462 | |||
463 | return this.each(function(index){ | ||
464 | $(this).wrapAll( | ||
465 | func ? structure.call(this, index) : | ||
466 | clone ? dom.cloneNode(true) : dom | ||
467 | ) | ||
468 | }) | ||
469 | }, | ||
470 | wrapAll: function(structure){ | ||
471 | if (this[0]) { | ||
472 | $(this[0]).before(structure = $(structure)) | ||
473 | var children | ||
474 | // drill down to the inmost element | ||
475 | while ((children = structure.children()).length) structure = children.first() | ||
476 | $(structure).append(this) | ||
477 | } | ||
478 | return this | ||
479 | }, | ||
480 | wrapInner: function(structure){ | ||
481 | var func = isFunction(structure) | ||
482 | return this.each(function(index){ | ||
483 | var self = $(this), contents = self.contents(), | ||
484 | dom = func ? structure.call(this, index) : structure | ||
485 | contents.length ? contents.wrapAll(dom) : self.append(dom) | ||
486 | }) | ||
487 | }, | ||
488 | unwrap: function(){ | ||
489 | this.parent().each(function(){ | ||
490 | $(this).replaceWith($(this).children()) | ||
491 | }) | ||
492 | return this | ||
493 | }, | ||
494 | clone: function(){ | ||
495 | return this.map(function(){ return this.cloneNode(true) }) | ||
496 | }, | ||
497 | hide: function(){ | ||
498 | return this.css("display", "none") | ||
499 | }, | ||
500 | toggle: function(setting){ | ||
501 | return this.each(function(){ | ||
502 | var el = $(this) | ||
503 | ;(setting === undefined ? el.css("display") == "none" : setting) ? el.show() : el.hide() | ||
504 | }) | ||
505 | }, | ||
506 | prev: function(selector){ return $(this.pluck('previousElementSibling')).filter(selector || '*') }, | ||
507 | next: function(selector){ return $(this.pluck('nextElementSibling')).filter(selector || '*') }, | ||
508 | html: function(html){ | ||
509 | return html === undefined ? | ||
510 | (this.length > 0 ? this[0].innerHTML : null) : | ||
511 | this.each(function(idx){ | ||
512 | var originHtml = this.innerHTML | ||
513 | $(this).empty().append( funcArg(this, html, idx, originHtml) ) | ||
514 | }) | ||
515 | }, | ||
516 | text: function(text){ | ||
517 | return text === undefined ? | ||
518 | (this.length > 0 ? this[0].textContent : null) : | ||
519 | this.each(function(){ this.textContent = text }) | ||
520 | }, | ||
521 | attr: function(name, value){ | ||
522 | var result | ||
523 | return (typeof name == 'string' && value === undefined) ? | ||
524 | (this.length == 0 || this[0].nodeType !== 1 ? undefined : | ||
525 | (name == 'value' && this[0].nodeName == 'INPUT') ? this.val() : | ||
526 | (!(result = this[0].getAttribute(name)) && name in this[0]) ? this[0][name] : result | ||
527 | ) : | ||
528 | this.each(function(idx){ | ||
529 | if (this.nodeType !== 1) return | ||
530 | if (isObject(name)) for (key in name) setAttribute(this, key, name[key]) | ||
531 | else setAttribute(this, name, funcArg(this, value, idx, this.getAttribute(name))) | ||
532 | }) | ||
533 | }, | ||
534 | removeAttr: function(name){ | ||
535 | return this.each(function(){ this.nodeType === 1 && setAttribute(this, name) }) | ||
536 | }, | ||
537 | prop: function(name, value){ | ||
538 | return (value === undefined) ? | ||
539 | (this[0] && this[0][name]) : | ||
540 | this.each(function(idx){ | ||
541 | this[name] = funcArg(this, value, idx, this[name]) | ||
542 | }) | ||
543 | }, | ||
544 | data: function(name, value){ | ||
545 | var data = this.attr('data-' + dasherize(name), value) | ||
546 | return data !== null ? deserializeValue(data) : undefined | ||
547 | }, | ||
548 | val: function(value){ | ||
549 | return (value === undefined) ? | ||
550 | (this[0] && (this[0].multiple ? | ||
551 | $(this[0]).find('option').filter(function(o){ return this.selected }).pluck('value') : | ||
552 | this[0].value) | ||
553 | ) : | ||
554 | this.each(function(idx){ | ||
555 | this.value = funcArg(this, value, idx, this.value) | ||
556 | }) | ||
557 | }, | ||
558 | offset: function(coordinates){ | ||
559 | if (coordinates) return this.each(function(index){ | ||
560 | var $this = $(this), | ||
561 | coords = funcArg(this, coordinates, index, $this.offset()), | ||
562 | parentOffset = $this.offsetParent().offset(), | ||
563 | props = { | ||
564 | top: coords.top - parentOffset.top, | ||
565 | left: coords.left - parentOffset.left | ||
566 | } | ||
567 | |||
568 | if ($this.css('position') == 'static') props['position'] = 'relative' | ||
569 | $this.css(props) | ||
570 | }) | ||
571 | if (this.length==0) return null | ||
572 | var obj = this[0].getBoundingClientRect() | ||
573 | return { | ||
574 | left: obj.left + window.pageXOffset, | ||
575 | top: obj.top + window.pageYOffset, | ||
576 | width: obj.width, | ||
577 | height: obj.height | ||
578 | } | ||
579 | }, | ||
580 | css: function(property, value){ | ||
581 | if (arguments.length < 2 && typeof property == 'string') | ||
582 | return this[0] && (this[0].style[camelize(property)] || getComputedStyle(this[0], '').getPropertyValue(property)) | ||
583 | |||
584 | var css = '' | ||
585 | for (key in property) | ||
586 | if (!property[key] && property[key] !== 0) | ||
587 | this.each(function(){ this.style.removeProperty(dasherize(key)) }) | ||
588 | else | ||
589 | css += dasherize(key) + ':' + maybeAddPx(key, property[key]) + ';' | ||
590 | |||
591 | if (typeof property == 'string') | ||
592 | if (!value && value !== 0) | ||
593 | this.each(function(){ this.style.removeProperty(dasherize(property)) }) | ||
594 | else | ||
595 | css = dasherize(property) + ":" + maybeAddPx(property, value) | ||
596 | |||
597 | return this.each(function(){ this.style.cssText += ';' + css }) | ||
598 | }, | ||
599 | index: function(element){ | ||
600 | return element ? this.indexOf($(element)[0]) : this.parent().children().indexOf(this[0]) | ||
601 | }, | ||
602 | hasClass: function(name){ | ||
603 | return emptyArray.some.call(this, function(el){ | ||
604 | return this.test(className(el)) | ||
605 | }, classRE(name)) | ||
606 | }, | ||
607 | addClass: function(name){ | ||
608 | return this.each(function(idx){ | ||
609 | classList = [] | ||
610 | var cls = className(this), newName = funcArg(this, name, idx, cls) | ||
611 | newName.split(/\s+/g).forEach(function(klass){ | ||
612 | if (!$(this).hasClass(klass)) classList.push(klass) | ||
613 | }, this) | ||
614 | classList.length && className(this, cls + (cls ? " " : "") + classList.join(" ")) | ||
615 | }) | ||
616 | }, | ||
617 | removeClass: function(name){ | ||
618 | return this.each(function(idx){ | ||
619 | if (name === undefined) return className(this, '') | ||
620 | classList = className(this) | ||
621 | funcArg(this, name, idx, classList).split(/\s+/g).forEach(function(klass){ | ||
622 | classList = classList.replace(classRE(klass), " ") | ||
623 | }) | ||
624 | className(this, classList.trim()) | ||
625 | }) | ||
626 | }, | ||
627 | toggleClass: function(name, when){ | ||
628 | return this.each(function(idx){ | ||
629 | var newName = funcArg(this, name, idx, className(this)) | ||
630 | ;(when === undefined ? !$(this).hasClass(newName) : when) ? | ||
631 | $(this).addClass(newName) : $(this).removeClass(newName) | ||
632 | }) | ||
633 | }, | ||
634 | scrollTop: function(){ | ||
635 | if (!this.length) return | ||
636 | return ('scrollTop' in this[0]) ? this[0].scrollTop : this[0].scrollY | ||
637 | }, | ||
638 | position: function() { | ||
639 | if (!this.length) return | ||
640 | |||
641 | var elem = this[0], | ||
642 | // Get *real* offsetParent | ||
643 | offsetParent = this.offsetParent(), | ||
644 | // Get correct offsets | ||
645 | offset = this.offset(), | ||
646 | parentOffset = rootNodeRE.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset() | ||
647 | |||
648 | // Subtract element margins | ||
649 | // note: when an element has margin: auto the offsetLeft and marginLeft | ||
650 | // are the same in Safari causing offset.left to incorrectly be 0 | ||
651 | offset.top -= parseFloat( $(elem).css('margin-top') ) || 0 | ||
652 | offset.left -= parseFloat( $(elem).css('margin-left') ) || 0 | ||
653 | |||
654 | // Add offsetParent borders | ||
655 | parentOffset.top += parseFloat( $(offsetParent[0]).css('border-top-width') ) || 0 | ||
656 | parentOffset.left += parseFloat( $(offsetParent[0]).css('border-left-width') ) || 0 | ||
657 | |||
658 | // Subtract the two offsets | ||
659 | return { | ||
660 | top: offset.top - parentOffset.top, | ||
661 | left: offset.left - parentOffset.left | ||
662 | } | ||
663 | }, | ||
664 | offsetParent: function() { | ||
665 | return this.map(function(){ | ||
666 | var parent = this.offsetParent || document.body | ||
667 | while (parent && !rootNodeRE.test(parent.nodeName) && $(parent).css("position") == "static") | ||
668 | parent = parent.offsetParent | ||
669 | return parent | ||
670 | }) | ||
671 | } | ||
672 | } | ||
673 | |||
674 | // for now | ||
675 | $.fn.detach = $.fn.remove | ||
676 | |||
677 | // Generate the `width` and `height` functions | ||
678 | ;['width', 'height'].forEach(function(dimension){ | ||
679 | $.fn[dimension] = function(value){ | ||
680 | var offset, Dimension = dimension.replace(/./, function(m){ return m[0].toUpperCase() }) | ||
681 | if (value === undefined) return this[0] == window ? window['inner' + Dimension] : | ||
682 | this[0] == document ? document.documentElement['offset' + Dimension] : | ||
683 | (offset = this.offset()) && offset[dimension] | ||
684 | else return this.each(function(idx){ | ||
685 | var el = $(this) | ||
686 | el.css(dimension, funcArg(this, value, idx, el[dimension]())) | ||
687 | }) | ||
688 | } | ||
689 | }) | ||
690 | |||
691 | function traverseNode(node, fun) { | ||
692 | fun(node) | ||
693 | for (var key in node.childNodes) traverseNode(node.childNodes[key], fun) | ||
694 | } | ||
695 | |||
696 | // Generate the `after`, `prepend`, `before`, `append`, | ||
697 | // `insertAfter`, `insertBefore`, `appendTo`, and `prependTo` methods. | ||
698 | adjacencyOperators.forEach(function(operator, operatorIndex) { | ||
699 | var inside = operatorIndex % 2 //=> prepend, append | ||
700 | |||
701 | $.fn[operator] = function(){ | ||
702 | // arguments can be nodes, arrays of nodes, Zepto objects and HTML strings | ||
703 | var nodes = $.map(arguments, function(n){ return isObject(n) ? n : zepto.fragment(n) }), | ||
704 | parent, copyByClone = this.length > 1 | ||
705 | if (nodes.length < 1) return this | ||
706 | |||
707 | return this.each(function(_, target){ | ||
708 | parent = inside ? target : target.parentNode | ||
709 | |||
710 | // convert all methods to a "before" operation | ||
711 | target = operatorIndex == 0 ? target.nextSibling : | ||
712 | operatorIndex == 1 ? target.firstChild : | ||
713 | operatorIndex == 2 ? target : | ||
714 | null | ||
715 | |||
716 | nodes.forEach(function(node){ | ||
717 | if (copyByClone) node = node.cloneNode(true) | ||
718 | else if (!parent) return $(node).remove() | ||
719 | |||
720 | traverseNode(parent.insertBefore(node, target), function(el){ | ||
721 | if (el.nodeName != null && el.nodeName.toUpperCase() === 'SCRIPT' && | ||
722 | (!el.type || el.type === 'text/javascript') && !el.src) | ||
723 | window['eval'].call(window, el.innerHTML) | ||
724 | }) | ||
725 | }) | ||
726 | }) | ||
727 | } | ||
728 | |||
729 | // after => insertAfter | ||
730 | // prepend => prependTo | ||
731 | // before => insertBefore | ||
732 | // append => appendTo | ||
733 | $.fn[inside ? operator+'To' : 'insert'+(operatorIndex ? 'Before' : 'After')] = function(html){ | ||
734 | $(html)[operator](this) | ||
735 | return this | ||
736 | } | ||
737 | }) | ||
738 | |||
739 | zepto.Z.prototype = $.fn | ||
740 | |||
741 | // Export internal API functions in the `$.zepto` namespace | ||
742 | zepto.uniq = uniq | ||
743 | zepto.deserializeValue = deserializeValue | ||
744 | $.zepto = zepto | ||
745 | |||
746 | return $ | ||
747 | })() | ||
748 | |||
749 | // If `$` is not yet defined, point it to `Zepto` | ||
750 | window.Zepto = Zepto | ||
751 | '$' in window || (window.$ = Zepto) | ||
diff --git a/frontend/gamma/js/main_iPhone.js b/frontend/gamma/js/main.mobile.js index 0644f68..60a32fa 100644 --- a/frontend/gamma/js/main_iPhone.js +++ b/frontend/gamma/js/main.mobile.js | |||
@@ -47,11 +47,18 @@ Clipperz.PM.RunTime = {}; | |||
47 | 47 | ||
48 | 48 | ||
49 | function run() { | 49 | function run() { |
50 | MochiKit.DOM.removeElement('javaScriptAlert'); | ||
51 | Clipperz.PM.Strings.Languages.initSetup(); | 50 | Clipperz.PM.Strings.Languages.initSetup(); |
52 | 51 | ||
53 | Clipperz.PM.RunTime.mainController = new Clipperz.PM.UI.iPhone.Controllers.MainController(); | 52 | Clipperz.PM.RunTime.mainController = new Clipperz.PM.UI.Mobile.Controllers.MainController(); |
54 | Clipperz.PM.RunTime.mainController.run(false); | 53 | Clipperz.PM.RunTime.mainController.run(); |
55 | } | 54 | } |
56 | 55 | ||
56 | // if (navigator.standalone == false) { | ||
57 | // window.localStorage.setItem('PIN', '1234'); | ||
58 | // alert("Saved PIN"); | ||
59 | // } else { | ||
60 | // alert (window.localStorage.getItem('PIN')); | ||
61 | // } | ||
62 | |||
63 | |||
57 | MochiKit.DOM.addLoadEvent(run); | 64 | MochiKit.DOM.addLoadEvent(run); |