summaryrefslogtreecommitdiff
path: root/frontend/gamma/js/Clipperz/PM
Unidiff
Diffstat (limited to 'frontend/gamma/js/Clipperz/PM') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/gamma/js/Clipperz/PM/Connection.js34
-rw-r--r--frontend/gamma/js/Clipperz/PM/DataModel/User.js20
-rw-r--r--frontend/gamma/js/Clipperz/PM/PIN.js134
-rw-r--r--frontend/gamma/js/Clipperz/PM/Proxy/Proxy.OfflineCache.js65
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Common/Components/BaseComponent.js4
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Common/Components/Button.js34
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Common/Components/SimpleMessagePanel.js34
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardDetail.js299
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardList.js (renamed from frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/CardList.js)111
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/LoginForm.js356
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js393
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Web/Components/AccountPanel.js17
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Web/Components/DataPanel.js18
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Web/Components/LoginProgress.js14
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Web/Components/ToolsPanel.js8
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Web/Controllers/AppController.js31
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/CardDetail.js163
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/iPhone/Components/LoginForm.js178
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/iPhone/Controllers/MainController.js369
19 files changed, 1484 insertions, 798 deletions
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
@@ -32,24 +32,25 @@ if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
32// 32//
33//----------------------------------------------------------------------------- 33//-----------------------------------------------------------------------------
34 34
35Clipperz.PM.Connection = function (args) { 35Clipperz.PM.Connection = function (args) {
36 args = args || {}; 36 args = args || {};
37 37
38 this._proxy = args.proxy || Clipperz.PM.Proxy.defaultProxy; 38 this._proxy = args.proxy || Clipperz.PM.Proxy.defaultProxy;
39 this._getCredentialsFunction = args.getCredentialsFunction; 39 this._getCredentialsFunction = args.getCredentialsFunction;
40 40
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}
47 48
48Clipperz.PM.Connection.prototype = MochiKit.Base.update(null, { 49Clipperz.PM.Connection.prototype = MochiKit.Base.update(null, {
49 50
50 'toString': function() { 51 'toString': function() {
51 return "Connection [" + this.version() + "]"; 52 return "Connection [" + this.version() + "]";
52 }, 53 },
53 54
54 //========================================================================= 55 //=========================================================================
55 56
@@ -137,24 +138,34 @@ MochiKit.Logging.logError("### Connection.defaultErrorHandler: " + anErrorString
137 }, 138 },
138 139
139 //------------------------------------------------------------------------- 140 //-------------------------------------------------------------------------
140 141
141 'connectionId': function() { 142 'connectionId': function() {
142 return this._connectionId; 143 return this._connectionId;
143 }, 144 },
144 145
145 'setConnectionId': function(aValue) { 146 'setConnectionId': function(aValue) {
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: ?????
152 'oneTimePassword': function() { 163 'oneTimePassword': function() {
153 return this._oneTimePassword; 164 return this._oneTimePassword;
154 }, 165 },
155 166
156 'setOneTimePassword': function(aValue) { 167 'setOneTimePassword': function(aValue) {
157 this._oneTimePassword = aValue; 168 this._oneTimePassword = aValue;
158 }, 169 },
159*/ 170*/
160 //========================================================================= 171 //=========================================================================
@@ -311,31 +322,30 @@ Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz.
311 return Clipperz.PM.Crypto.deferredDecrypt({ 322 return Clipperz.PM.Crypto.deferredDecrypt({
312 value:aResult['data'], 323 value:aResult['data'],
313 key:normalizedOTP, 324 key:normalizedOTP,
314 version:aResult['version'] 325 version:aResult['version']
315 }); 326 });
316 }, 327 },
317 function(aResult) { 328 function(aResult) {
318 return (new Clipperz.ByteArray().appendBase64String(aResult['passphrase'])).asString(); 329 return (new Clipperz.ByteArray().appendBase64String(aResult['passphrase'])).asString();
319 } 330 }
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');
333 // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_sendingCredentials'); 343 // deferredResult.addCallbackPass(MochiKit.Signal.signal, this, 'updatedProgressState', 'connection_sendingCredentials');
334 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); 344 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
335 deferredResult.addCallback(MochiKit.Base.bind(function(someCredentials) { 345 deferredResult.addCallback(MochiKit.Base.bind(function(someCredentials) {
336 srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() }); 346 srpConnection = new Clipperz.Crypto.SRP.Connection({ C:someCredentials['username'], P:someCredentials['password'], hash:this.hash() });
337 }, this)); 347 }, this));
338 deferredResult.addCallback(function() { 348 deferredResult.addCallback(function() {
339 var result; 349 var result;
340 350
341 result = { 351 result = {
@@ -390,24 +400,31 @@ Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz.
390 } 400 }
391 401
392 return result; 402 return result;
393 }); 403 });
394 deferredResult.addCallback(MochiKit.Base.bind(function(someParameters) { 404 deferredResult.addCallback(MochiKit.Base.bind(function(someParameters) {
395 this.setConnectionId(someParameters['connectionId']); 405 this.setConnectionId(someParameters['connectionId']);
396 this.setSharedSecret(srpConnection.K()); 406 this.setSharedSecret(srpConnection.K());
397 407
398 // TODO: ????? 408 // TODO: ?????
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');
405 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress'); 422 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'advanceProgress');
406 deferredResult.addCallback(MochiKit.Async.succeed, {result:"done"}); 423 deferredResult.addCallback(MochiKit.Async.succeed, {result:"done"});
407 424
408 deferredResult.callback(); 425 deferredResult.callback();
409 426
410 return deferredResult; 427 return deferredResult;
411 }, 428 },
412 429
413 //========================================================================= 430 //=========================================================================
@@ -420,46 +437,52 @@ Clipperz.PM.Connection.SRP['1.0'].prototype = MochiKit.Base.update(new Clipperz.
420 }, 437 },
421 438
422 //========================================================================= 439 //=========================================================================
423 440
424 'ping': function () { 441 'ping': function () {
425 //TODO: ping the server in order to have a valid session 442 //TODO: ping the server in order to have a valid session
426 }, 443 },
427 444
428 //========================================================================= 445 //=========================================================================
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);
441 }, 465 },
442 466
443 //------------------------------------------------------------------------- 467 //-------------------------------------------------------------------------
444 468
445 'sendMessage': function(someArguments) { 469 'sendMessage': function(someArguments) {
446 vardeferredResult; 470 vardeferredResult;
447 471
448 deferredResult = new Clipperz.Async.Deferred("Connection.sendMessage", {trace:false}); 472 deferredResult = new Clipperz.Async.Deferred("Connection.sendMessage", {trace:false});
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));
457 480
458 deferredResult.addErrback(MochiKit.Base.method(this, 'messageExceptionHandler'), someArguments); 481 deferredResult.addErrback(MochiKit.Base.method(this, 'messageExceptionHandler'), someArguments);
459 deferredResult.callback(); 482 deferredResult.callback();
460 483
461 return deferredResult 484 return deferredResult
462 }, 485 },
463 486
464 //------------------------------------------------------------------------- 487 //-------------------------------------------------------------------------
465 488
@@ -578,24 +601,25 @@ Clipperz.PM.Connection.SRP['1.1'].prototype = MochiKit.Base.update(new Clipperz.
578 601
579 'hash': function() { 602 'hash': function() {
580 return Clipperz.PM.Crypto.encryptingFunctions.versions['0.2'].hash; 603 return Clipperz.PM.Crypto.encryptingFunctions.versions['0.2'].hash;
581 }, 604 },
582 605
583 //----------------------------------------------------------------------------- 606 //-----------------------------------------------------------------------------
584 __syntaxFix__: "syntax fix" 607 __syntaxFix__: "syntax fix"
585 608
586}); 609});
587 610
588Clipperz.PM.Connection.exception = { 611Clipperz.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
593 617
594Clipperz.PM.Connection.communicationProtocol = { 618Clipperz.PM.Connection.communicationProtocol = {
595 'currentVersion': '0.2', 619 'currentVersion': '0.2',
596 'versions': { 620 'versions': {
597 '0.1': Clipperz.PM.Connection.SRP['1.0'],//Clipperz.Crypto.SRP.versions['1.0'].Connection, 621 '0.1': Clipperz.PM.Connection.SRP['1.0'],//Clipperz.Crypto.SRP.versions['1.0'].Connection,
598 '0.2': Clipperz.PM.Connection.SRP['1.1']//Clipperz.Crypto.SRP.versions['1.1'].Connection 622 '0.2': Clipperz.PM.Connection.SRP['1.1']//Clipperz.Crypto.SRP.versions['1.1'].Connection
599 }, 623 },
600 'fallbackVersions': { 624 'fallbackVersions': {
601 // 'current':'0.1', 625 // 'current':'0.1',
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
@@ -35,25 +35,25 @@ Clipperz.PM.DataModel.User = function (args) {
35 35
36 Clipperz.PM.DataModel.User.superclass.constructor.apply(this, arguments); 36 Clipperz.PM.DataModel.User.superclass.constructor.apply(this, arguments);
37 37
38 this._username = args.username || null; 38 this._username = args.username || null;
39 this._getPassphraseFunction = args.getPassphraseFunction || null; 39 this._getPassphraseFunction = args.getPassphraseFunction || null;
40 40
41 this._data = null; 41 this._data = null;
42 42
43 this._connection = null; 43 this._connection = null;
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 = {
51 'passphrase': new MochiKit.Async.DeferredLock(), 51 'passphrase': new MochiKit.Async.DeferredLock(),
52 'serverData': new MochiKit.Async.DeferredLock(), 52 'serverData': new MochiKit.Async.DeferredLock(),
53 // 'recordsIndex': new MochiKit.Async.DeferredLock(), 53 // 'recordsIndex': new MochiKit.Async.DeferredLock(),
54 // 'directLoginsIndex':new MochiKit.Async.DeferredLock() 54 // 'directLoginsIndex':new MochiKit.Async.DeferredLock()
55 // 'preferences': new MochiKit.Async.DeferredLock() 55 // 'preferences': new MochiKit.Async.DeferredLock()
56 // 'oneTimePasswords': new MochiKit.Async.DeferredLock() 56 // 'oneTimePasswords': new MochiKit.Async.DeferredLock()
57 '__syntaxFix__': 'syntax fix' 57 '__syntaxFix__': 'syntax fix'
58 }; 58 };
59 59
@@ -84,33 +84,33 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
84 84
85 //------------------------------------------------------------------------- 85 //-------------------------------------------------------------------------
86 86
87 'data': function () { 87 'data': function () {
88 if (this._data == null) { 88 if (this._data == null) {
89 this._data = new Clipperz.KeyValueObjectStore(/*{'name':'User.data [1]'}*/); 89 this._data = new Clipperz.KeyValueObjectStore(/*{'name':'User.data [1]'}*/);
90 }; 90 };
91 91
92 return this._data; 92 return this._data;
93 }, 93 },
94 94
95 //------------------------------------------------------------------------- 95 //-------------------------------------------------------------------------
96 96/*
97 'serverLockValue': function () { 97 'serverLockValue': function () {
98 return this._serverLockValue; 98 return this._serverLockValue;
99 }, 99 },
100 100
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 () {
108 if (this._transientState == null) { 108 if (this._transientState == null) {
109 this._transientState = {} 109 this._transientState = {}
110 } 110 }
111 111
112 return this._transientState; 112 return this._transientState;
113 }, 113 },
114 114
115 'resetTransientState': function (isCommitting) { 115 'resetTransientState': function (isCommitting) {
116 this._transientState = null; 116 this._transientState = null;
@@ -211,26 +211,26 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
211 //......................................................................... 211 //.........................................................................
212 212
213 'registerAsNewAccount': function () { 213 'registerAsNewAccount': function () {
214 var deferredResult; 214 var deferredResult;
215 215
216 deferredResult = new Clipperz.Async.Deferred("User.registerAsNewAccount", {trace:false}); 216 deferredResult = new Clipperz.Async.Deferred("User.registerAsNewAccount", {trace:false});
217 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3}); 217 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3});
218 deferredResult.addMethod(this, 'initialSetupWithNoData') 218 deferredResult.addMethod(this, 'initialSetupWithNoData')
219 deferredResult.addMethod(this, 'getPassphrase'); 219 deferredResult.addMethod(this, 'getPassphrase');
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'));
228 228
229 deferredResult.callback(); 229 deferredResult.callback();
230 230
231 return deferredResult; 231 return deferredResult;
232 }, 232 },
233 233
234 //------------------------------------------------------------------------- 234 //-------------------------------------------------------------------------
235 235
236 'login': function () { 236 'login': function () {
@@ -238,25 +238,25 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
238 238
239 deferredResult = new Clipperz.Async.Deferred("User.login", {trace:false}); 239 deferredResult = new Clipperz.Async.Deferred("User.login", {trace:false});
240 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3}); 240 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3});
241 deferredResult.addMethod(this, 'getPassphrase'); 241 deferredResult.addMethod(this, 'getPassphrase');
242 deferredResult.addCallback(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue); 242 deferredResult.addCallback(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue);
243 deferredResult.addCallback(Clipperz.Async.deferredIf("Is the passphrase an OTP", [ 243 deferredResult.addCallback(Clipperz.Async.deferredIf("Is the passphrase an OTP", [
244 MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':1}), 244 MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':1}),
245 MochiKit.Base.method(this, 'getCredentials'), 245 MochiKit.Base.method(this, 'getCredentials'),
246 MochiKit.Base.method(this.connection(), 'redeemOneTimePassword'), 246 MochiKit.Base.method(this.connection(), 'redeemOneTimePassword'),
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
254 deferredResult.callback(); 254 deferredResult.callback();
255 255
256 return deferredResult; 256 return deferredResult;
257 }, 257 },
258 258
259 //......................................................................... 259 //.........................................................................
260 260
261 'handleConnectionFallback': function(aValue) { 261 'handleConnectionFallback': function(aValue) {
262 var result; 262 var result;
@@ -320,25 +320,25 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
320 320
321 //------------------------------------------------------------------------- 321 //-------------------------------------------------------------------------
322 322
323 'unpackServerData': function (someServerData) { 323 'unpackServerData': function (someServerData) {
324 var unpackedData; 324 var unpackedData;
325 var headerVersion; 325 var headerVersion;
326 326
327 varrecordsIndex; 327 varrecordsIndex;
328 var preferences; 328 var preferences;
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
336 switch (headerVersion) { 336 switch (headerVersion) {
337 case 'LEGACY': 337 case 'LEGACY':
338 varlegacyHeader; 338 varlegacyHeader;
339 339
340 legacyHeader = new Clipperz.PM.DataModel.User.Header.Legacy({ 340 legacyHeader = new Clipperz.PM.DataModel.User.Header.Legacy({
341 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'), 341 'retrieveKeyFunction': MochiKit.Base.method(this, 'getPassphrase'),
342 'remoteData': { 342 'remoteData': {
343 'data': someServerData['header'], 343 'data': someServerData['header'],
344 'version': someServerData['version'], 344 'version': someServerData['version'],
@@ -653,26 +653,26 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
653 653
654 return deferredResult; 654 return deferredResult;
655 }, 655 },
656 656
657 //========================================================================= 657 //=========================================================================
658 658
659 'commitTransientState': function () { 659 'commitTransientState': function () {
660 return Clipperz.Async.callbacks("User.commitTransientState", [ 660 return Clipperz.Async.callbacks("User.commitTransientState", [
661 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'commitTransientState'), 661 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'commitTransientState'),
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 },
670 670
671 //------------------------------------------------------------------------- 671 //-------------------------------------------------------------------------
672 672
673 'revertChanges': function () { 673 'revertChanges': function () {
674 return Clipperz.Async.callbacks("User.revertChanges", [ 674 return Clipperz.Async.callbacks("User.revertChanges", [
675 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'revertChanges'), 675 MochiKit.Base.method(this, 'invokeMethodNamedOnHeader', 'revertChanges'),
676 MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'revertChanges'), 676 MochiKit.Base.method(this, 'invokeMethodNamedOnRecords', 'revertChanges'),
677 MochiKit.Base.method(this, 'resetTransientState', false) 677 MochiKit.Base.method(this, 'resetTransientState', false)
678 ], {trace:false}); 678 ], {trace:false});
@@ -731,25 +731,25 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, {
731 header['records'] = someHeaderPackedData['recordIndex']['records']; 731 header['records'] = someHeaderPackedData['recordIndex']['records'];
732 header['directLogins'] = someHeaderPackedData['recordIndex']['directLogins']; 732 header['directLogins'] = someHeaderPackedData['recordIndex']['directLogins'];
733 header['preferences'] = {'data': someHeaderPackedData['preferences']['data']}; // this._serverData['header']['preferences']; // Clipperz.Base.evalJSON(this._serverData['header']['data'])['preferences']; //??????????? 733 header['preferences'] = {'data': someHeaderPackedData['preferences']['data']}; // this._serverData['header']['preferences']; // Clipperz.Base.evalJSON(this._serverData['header']['data'])['preferences']; //???????????
734 header['oneTimePasswords'] = {'data': someHeaderPackedData['oneTimePasswords']['data']}; // this._serverData['header']['oneTimePasswords']; // Clipperz.Base.evalJSON(this._serverData['header']['data'])['oneTimePasswords']; //??????????? 734 header['oneTimePasswords'] = {'data': someHeaderPackedData['oneTimePasswords']['data']}; // this._serverData['header']['oneTimePasswords']; // Clipperz.Base.evalJSON(this._serverData['header']['data'])['oneTimePasswords']; //???????????
735 header['version'] = '0.1'; 735 header['version'] = '0.1';
736 736
737 aResult['header'] = Clipperz.Base.serializeJSON(header); 737 aResult['header'] = Clipperz.Base.serializeJSON(header);
738 aResult['statistics'] = this._serverData['statistics']; //"someHeaderPackedData['statistics']['data']"; 738 aResult['statistics'] = this._serverData['statistics']; //"someHeaderPackedData['statistics']['data']";
739 739
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;
747 }, 747 },
748 748
749 //========================================================================= 749 //=========================================================================
750 750
751 'saveChanges': function () { 751 'saveChanges': function () {
752 vardeferredResult; 752 vardeferredResult;
753 var messageParameters; 753 var messageParameters;
754 754
755 messageParameters = {}; 755 messageParameters = {};
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
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz Community Edition.
6Clipperz Community Edition is an online password manager.
7For further information about its features and functionalities please
8refer 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
26if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
27if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
28if (typeof(Clipperz.PM.PIN) == 'undefined') { Clipperz.PM.PIN = {}; }
29
30MochiKit.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
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz Community Edition.
6Clipperz Community Edition is an online password manager.
7For further information about its features and functionalities please
8refer 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
26if (typeof(Clipperz) == 'undefined') { Clipperz = {}; }
27if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; }
28
29//=============================================================================
30
31Clipperz.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
41Clipperz.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
@@ -397,24 +397,28 @@ Clipperz.Base.extend(Clipperz.PM.UI.Common.Components.BaseComponent, /*Ext.Compo
397 397
398 result = "Clipperz_PM_Components_" + aValue + "_" + _Clipperz_PM_Components_base_id_; 398 result = "Clipperz_PM_Components_" + aValue + "_" + _Clipperz_PM_Components_base_id_;
399 this._ids[aValue] = result; 399 this._ids[aValue] = result;
400 } 400 }
401 } else { 401 } else {
402 // result = Clipperz.PM.UI.Common.Components.BaseComponent.superclass.getId.call(this); 402 // result = Clipperz.PM.UI.Common.Components.BaseComponent.superclass.getId.call(this);
403 throw "call to BaseComponent.getId with an undefined value"; 403 throw "call to BaseComponent.getId with an undefined value";
404 } 404 }
405 405
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) {
412 return Clipperz.DOM.get(this.getId(aValue)); 416 return Clipperz.DOM.get(this.getId(aValue));
413 }, 417 },
414 418
415 //------------------------------------------------------------------------- 419 //-------------------------------------------------------------------------
416 420
417 'hideElement': function(anElementName) { 421 'hideElement': function(anElementName) {
418 MochiKit.Style.hideElement(this.getElement(anElementName)); 422 MochiKit.Style.hideElement(this.getElement(anElementName));
419 }, 423 },
420 424
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
@@ -53,53 +53,61 @@ Clipperz.Base.extend(Clipperz.PM.UI.Common.Components.Button, Clipperz.PM.UI.Com
53 53
54 'text': function () { 54 'text': function () {
55 return this._text; 55 return this._text;
56 }, 56 },
57 57
58 'isDefault': function () { 58 'isDefault': function () {
59 return this._isDefault; 59 return this._isDefault;
60 }, 60 },
61 61
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()}
69 ]}, 70 ]},
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 },
102 110
103 //------------------------------------------------------------------------- 111 //-------------------------------------------------------------------------
104 __syntaxFix__: "syntax fix" 112 __syntaxFix__: "syntax fix"
105}); 113});
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
@@ -89,32 +89,47 @@ Clipperz.Base.extend(Clipperz.PM.UI.Common.Components.SimpleMessagePanel, Clippe
89 if (this.getElement('text') != null) { 89 if (this.getElement('text') != null) {
90 this.getElement('text').innerHTML = aValue; 90 this.getElement('text').innerHTML = aValue;
91 } 91 }
92 }, 92 },
93 93
94 //------------------------------------------------------------------------- 94 //-------------------------------------------------------------------------
95 95
96 'type': function () { 96 'type': function () {
97 return this._type; 97 return this._type;
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 () {
112 return this._buttons; 127 return this._buttons;
113 }, 128 },
114 129
115 'setButtons': function (someValues) { 130 'setButtons': function (someValues) {
116 MochiKit.Iter.forEach(this.buttonComponents(), MochiKit.Base.methodcaller('clear')); 131 MochiKit.Iter.forEach(this.buttonComponents(), MochiKit.Base.methodcaller('clear'));
117 132
118 this._buttons = someValues; 133 this._buttons = someValues;
119 134
120 if (this.getElement('buttonArea') != null) { 135 if (this.getElement('buttonArea') != null) {
@@ -123,35 +138,38 @@ Clipperz.Base.extend(Clipperz.PM.UI.Common.Components.SimpleMessagePanel, Clippe
123 }, 138 },
124 139
125 //......................................................................... 140 //.........................................................................
126 141
127 'buttonComponents': function () { 142 'buttonComponents': function () {
128 return this._buttonComponents; 143 return this._buttonComponents;
129 }, 144 },
130 145
131 //------------------------------------------------------------------------- 146 //-------------------------------------------------------------------------
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();
149 }, 167 },
150 168
151 //------------------------------------------------------------------------- 169 //-------------------------------------------------------------------------
152 170
153 'renderButtons': function () { 171 'renderButtons': function () {
154 this.getElement('buttonArea').innerHTML = ''; 172 this.getElement('buttonArea').innerHTML = '';
155 173
156 MochiKit.Base.map(MochiKit.Base.bind(function (aButton) { 174 MochiKit.Base.map(MochiKit.Base.bind(function (aButton) {
157 var buttonElement; 175 var buttonElement;
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
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz Community Edition.
6Clipperz Community Edition is an online password manager.
7For further information about its features and functionalities please
8refer 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
26Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components');
27
28Clipperz.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
40Clipperz.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 () {
61console.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
158console.log("ADD DIRECT LOGIN", aDirectLogin);
159 },
160
161 //=========================================================================
162
163 'showCard': function (aCard) {
164 var deferredResult;
165
166 // this.render();
167
168console.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
@@ -14,76 +14,129 @@ refer to http://www.clipperz.com.
14 14
15* Clipperz Community Edition is distributed in the hope that it will 15* Clipperz Community Edition is distributed in the hope that it will
16 be useful, but WITHOUT ANY WARRANTY; without even the implied 16 be useful, but WITHOUT ANY WARRANTY; without even the implied
17 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU Affero General Public License for more details. 18 See the GNU Affero General Public License for more details.
19 19
20* You should have received a copy of the GNU Affero General Public 20* You should have received a copy of the GNU Affero General Public
21 License along with Clipperz Community Edition. If not, see 21 License along with Clipperz Community Edition. If not, see
22 <http://www.gnu.org/licenses/>. 22 <http://www.gnu.org/licenses/>.
23 23
24*/ 24*/
25 25
26Clipperz.Base.module('Clipperz.PM.UI.iPhone.Components'); 26Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components');
27 27
28Clipperz.PM.UI.iPhone.Components.CardList = function(args) { 28Clipperz.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
35 return this; 35 return this;
36} 36}
37 37
38//============================================================================= 38//=============================================================================
39 39
40Clipperz.Base.extend(Clipperz.PM.UI.iPhone.Components.CardList, Clipperz.PM.UI.Common.Components.BaseComponent, { 40Clipperz.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');
64 65 MochiKit.Signal.connect(this.getElement('list'), 'ontouchstart',this, 'cardSelectionHandler');
65 MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onsubmit', this,'searchHandler'); 66 // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onsubmit', this,'searchHandler');
66 MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeydown', this,'searchHandler'); 67 // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeydown', this,'searchHandler');
67 MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeyup', this,'searchHandler'); 68 // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeyup', this,'searchHandler');
68 69
69 MochiKit.Signal.connect(this.getElement('cardListPanel'), 'onclick', this,'cardListClickHandler'); 70 // MochiKit.Signal.connect(this.getElement('cardListPanel'), 'onclick', this,'cardListClickHandler');
70 MochiKit.Signal.connect('backButton', 'onclick', this,'backButtonClickHandler'); 71 // MochiKit.Signal.connect('backButton', 'onclick', this,'backButtonClickHandler');
71 72
72 MochiKit.Style.hideElement('backButton'); 73 // MochiKit.Style.hideElement('backButton');
73 MochiKit.Style.hideElement(this.getElement('cardDetail')); 74 // MochiKit.Style.hideElement(this.getElement('cardDetail'));
74 }, 75 },
75 76
76 //------------------------------------------------------------------------- 77 'showCards': function (someCards) {
78 varcardListElement;
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 },
103
104 'appendCardToList': function (aCardListElement, aCardInfo) {
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;
116
117 anEvent.preventDefault();
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');
124console.log("###", listElement, cardReference);
125 //TODO: Notify card with reference MochiKit.DOM.getNodeAttribute(listElement, 'cardreference') has been selected
126 MochiKit.Signal.signal(this, 'selectedCard', cardReference);
127 },
77 128
129 //-------------------------------------------------------------------------
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();
81 } else { 134 } else {
82 if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ESCAPE')) { 135 if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ESCAPE')) {
83 anEvent.target().value = ""; 136 anEvent.target().value = "";
84 } 137 }
85 138
86 if (anEvent.type() == 'keyup') { 139 if (anEvent.type() == 'keyup') {
87 MochiKit.Signal.signal(this, 'searchEvent', anEvent.target().value); 140 MochiKit.Signal.signal(this, 'searchEvent', anEvent.target().value);
88 } 141 }
89 } 142 }
@@ -118,25 +171,25 @@ Clipperz.Base.extend(Clipperz.PM.UI.iPhone.Components.CardList, Clipperz.PM.UI.C
118 var cardListReference; 171 var cardListReference;
119 172
120 cardListReference = anEvent.target().id.match(/(cardListReference_|cardListItem_)(.*)/)[2]; 173 cardListReference = anEvent.target().id.match(/(cardListReference_|cardListItem_)(.*)/)[2];
121//console.log("Showing detail for card named", cardListReference); 174//console.log("Showing detail for card named", cardListReference);
122 MochiKit.Signal.signal(this, 'selectedCard', cardListReference); 175 MochiKit.Signal.signal(this, 'selectedCard', cardListReference);
123 } 176 }
124 }, 177 },
125 178
126 //========================================================================= 179 //=========================================================================
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;
134 }, 187 },
135 188
136 //------------------------------------------------------------------------- 189 //-------------------------------------------------------------------------
137 190
138 'removeCardDetail': function () { 191 'removeCardDetail': function () {
139 if (this._cardDetail != null) { 192 if (this._cardDetail != null) {
140 this._cardDetail.remove(); 193 this._cardDetail.remove();
141 this._cardDetail = null; 194 this._cardDetail = null;
142 } 195 }
@@ -186,16 +239,16 @@ Clipperz.Base.extend(Clipperz.PM.UI.iPhone.Components.CardList, Clipperz.PM.UI.C
186 offset = ((MochiKit.DOM.getNodeAttribute(MochiKit.DOM.currentDocument().body, 'orientation') == 'portrait') ? 320 : 480); 239 offset = ((MochiKit.DOM.getNodeAttribute(MochiKit.DOM.currentDocument().body, 'orientation') == 'portrait') ? 320 : 480);
187 MochiKit.Style.setElementPosition(this.getElement('cardList'), {x:-offset}); 240 MochiKit.Style.setElementPosition(this.getElement('cardList'), {x:-offset});
188 MochiKit.DOM.showElement(this.getElement('cardList')); 241 MochiKit.DOM.showElement(this.getElement('cardList'));
189 242
190 new MochiKit.Visual.Parallel([ 243 new MochiKit.Visual.Parallel([
191 new MochiKit.Visual.Move(this.getElement('cardList'), {x:offset, y:0, mode:'relative',transition:MochiKit.Visual.Transitions.linear, sync:true}), 244 new MochiKit.Visual.Move(this.getElement('cardList'), {x:offset, y:0, mode:'relative',transition:MochiKit.Visual.Transitions.linear, sync:true}),
192 new MochiKit.Visual.Move(this.getElement('cardDetail'), {x:offset, y:0, mode:'relative',transition:MochiKit.Visual.Transitions.linear, sync:true}), 245 new MochiKit.Visual.Move(this.getElement('cardDetail'), {x:offset, y:0, mode:'relative',transition:MochiKit.Visual.Transitions.linear, sync:true}),
193 MochiKit.Visual.fade (this.getElement('cardDetail'), { transition:MochiKit.Visual.Transitions.linear, sync:true}), 246 MochiKit.Visual.fade (this.getElement('cardDetail'), { transition:MochiKit.Visual.Transitions.linear, sync:true}),
194 MochiKit.Visual.fade ('backButton', { transition:MochiKit.Visual.Transitions.linear, sync:true}) 247 MochiKit.Visual.fade ('backButton', { transition:MochiKit.Visual.Transitions.linear, sync:true})
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
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz Community Edition.
6Clipperz Community Edition is an online password manager.
7For further information about its features and functionalities please
8refer 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
26Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components');
27
28Clipperz.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
49Clipperz.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
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz Community Edition.
6Clipperz Community Edition is an online password manager.
7For further information about its features and functionalities please
8refer 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
26Clipperz.Base.module('Clipperz.PM.UI.Mobile.Controllers');
27
28Clipperz.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
39MochiKit.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 &gt; 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 () {
131console.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 () {
170console.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
235console.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
@@ -32,24 +32,28 @@ Clipperz.PM.UI.Web.Components.AccountPanel = function(args) {
32 32
33 //this._initiallySelectedTab = args.selected || 'ACCOUNT'; 33 //this._initiallySelectedTab = args.selected || 'ACCOUNT';
34 this._initiallySelectedTab = args.selected || 'PASSPHRASE'; 34 this._initiallySelectedTab = args.selected || 'PASSPHRASE';
35 this._tabPanelControllerConfiguration = { 35 this._tabPanelControllerConfiguration = {
36 // 'ACCOUNT': { 36 // 'ACCOUNT': {
37 // tab:'accountTab', 37 // tab:'accountTab',
38 // panel:'accountPanel' 38 // panel:'accountPanel'
39 // }, 39 // },
40 'PASSPHRASE': { 40 'PASSPHRASE': {
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'
47 }, 51 },
48 'LOGIN_HISTORY': { 52 'LOGIN_HISTORY': {
49 tab:'loginHistoryTab', 53 tab:'loginHistoryTab',
50 panel:'loginHistoryPanel' 54 panel:'loginHistoryPanel'
51 } 55 }
52 }; 56 };
53 57
54 return this; 58 return this;
55} 59}
@@ -65,24 +69,25 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.AccountPanel, Clipperz.PM.UI.
65 }, 69 },
66 70
67 //------------------------------------------------------------------------- 71 //-------------------------------------------------------------------------
68 72
69 'renderSelf': function(/*aContainer, aPosition*/) { 73 'renderSelf': function(/*aContainer, aPosition*/) {
70//Clipperz.log("AccountPanel.renderSelf element", this.element()); 74//Clipperz.log("AccountPanel.renderSelf element", this.element());
71 this.append(this.element(), [ 75 this.append(this.element(), [
72 {tag:'div', cls:'header', children:[ 76 {tag:'div', cls:'header', children:[
73 {tag:'div', cls:'subPanelTabs', children:[ 77 {tag:'div', cls:'subPanelTabs', children:[
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 ]}
80 ]} 85 ]}
81 ]}, 86 ]},
82 {tag:'div', cls:'body', children:[ 87 {tag:'div', cls:'body', children:[
83 {tag:'div', cls:'accountPanel', children:[ 88 {tag:'div', cls:'accountPanel', children:[
84 {tag:'div', cls:'subPanelContent', children:[ 89 {tag:'div', cls:'subPanelContent', children:[
85 {tag:'ul', children:[ 90 {tag:'ul', children:[
86 // {tag:'li', id:this.getId('accountPanel'),children:[ 91 // {tag:'li', id:this.getId('accountPanel'),children:[
87 // {tag:'h3', html:"-- Account --"} 92 // {tag:'h3', html:"-- Account --"}
88 // ]}, 93 // ]},
@@ -108,34 +113,34 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.AccountPanel, Clipperz.PM.UI.
108 {tag:'label', html:"re-new passphrase", 'for':this.getId('reNewPassphrase')}, 113 {tag:'label', html:"re-new passphrase", 'for':this.getId('reNewPassphrase')},
109 {tag:'input', id:this.getId('reNewPassphrase')} 114 {tag:'input', id:this.getId('reNewPassphrase')}
110 ]} 115 ]}
111 ]}, 116 ]},
112 {tag:'div', cls:'confirm', children:[ 117 {tag:'div', cls:'confirm', children:[
113 {tag:'input', type:'checkbox', id:this.getId('confirm')}, 118 {tag:'input', type:'checkbox', id:this.getId('confirm')},
114 {tag:'label', html:"I understand that Clipperz will not be able to recover a lost passphrase", 'for':this.getId('confirm')} 119 {tag:'label', html:"I understand that Clipperz will not be able to recover a lost passphrase", 'for':this.getId('confirm')}
115 ]} 120 ]}
116 ]}, 121 ]},
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"}
120 ]}, 125 ]}
121 126 ]},
122 {tag:'h3', cls:'manageOTP', html:"Manage One-Time Passphrases"}, 127 {tag:'li', id:this.getId('OTPPanel'), children:[
123 {} 128 // {tag:'h3', html:"Manage One-Time Passphrases"}
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 ]}
133 ]} 138 ]}
134 ]}, 139 ]},
135 {tag:'div', cls:'footer'} 140 {tag:'div', cls:'footer'}
136 ]); 141 ]);
137 142
138 this.tabPanelController().setup({selected:this.initiallySelectedTab()}); 143 this.tabPanelController().setup({selected:this.initiallySelectedTab()});
139 }, 144 },
140 145
141 //------------------------------------------------------------------------- 146 //-------------------------------------------------------------------------
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
@@ -73,36 +73,44 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.DataPanel, Clipperz.PM.UI.Com
73 {tag:'li', id:this.getId('offlineCopyTab'),children:[{tag:'a', href:'#', html:'Offline copy'}], cls:'first'}, 73 {tag:'li', id:this.getId('offlineCopyTab'),children:[{tag:'a', href:'#', html:'Offline copy'}], cls:'first'},
74 {tag:'li', id:this.getId('sharingTab'), children:[{tag:'a', href:'#', html:'Sharing'}]}, 74 {tag:'li', id:this.getId('sharingTab'), children:[{tag:'a', href:'#', html:'Sharing'}]},
75 {tag:'li', id:this.getId('importTab'), children:[{tag:'a', href:'#', html:'Import'}]}, 75 {tag:'li', id:this.getId('importTab'), children:[{tag:'a', href:'#', html:'Import'}]},
76 {tag:'li', id:this.getId('exportTab'), children:[{tag:'a', href:'#', html:'Export'}]} 76 {tag:'li', id:this.getId('exportTab'), children:[{tag:'a', href:'#', html:'Export'}]}
77 ]} 77 ]}
78 ]} 78 ]}
79 ]}, 79 ]},
80 {tag:'div', cls:'body', children:[ 80 {tag:'div', cls:'body', children:[
81 {tag:'div', cls:'accountPanel', children:[ 81 {tag:'div', cls:'accountPanel', children:[
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 ]}
98 ]} 100 ]}
99 ]}, 101 ]},
100 {tag:'div', cls:'footer'} 102 {tag:'div', cls:'footer'}
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');
104 }, 107 },
105 108
109 'downloadOfflineCopy': function (anEvent) {
110 anEvent.preventDefault();
111 MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'downloadOfflineCopy', anEvent.src());
112 },
113
106 //------------------------------------------------------------------------- 114 //-------------------------------------------------------------------------
107 __syntaxFix__: "syntax fix" 115 __syntaxFix__: "syntax fix"
108}); 116});
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
@@ -73,38 +73,40 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.LoginProgress, Clipperz.PM.UI
73 {tag:'h3', id:this.getId('title'), html:"login progress"} 73 {tag:'h3', id:this.getId('title'), html:"login progress"}
74 ]}, 74 ]},
75 {tag:'div', cls:'body', children:[ 75 {tag:'div', cls:'body', children:[
76 {tag:'div', id:this.getId('progressBar')}, 76 {tag:'div', id:this.getId('progressBar')},
77 {tag:'div', id:this.getId('errorBox'), cls:'errorBox', children:[ 77 {tag:'div', id:this.getId('errorBox'), cls:'errorBox', children:[
78 // {tag:'div',cls:'img ALERT', children:[{tag:'div'}]}, 78 // {tag:'div',cls:'img ALERT', children:[{tag:'div'}]},
79 {tag:'div',cls:'img ALERT', children:[{tag:'canvas', id:this.getId('canvas')}]}, 79 {tag:'div',cls:'img ALERT', children:[{tag:'canvas', id:this.getId('canvas')}]},
80 {tag:'p', html:"Login failed"} 80 {tag:'p', html:"Login failed"}
81 ]} 81 ]}
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 ]});
91 // ]); 92 // ]);
92 93
93 Clipperz.PM.UI.Canvas.marks['!'](this.getElement('canvas'), "#ffffff"); 94 Clipperz.PM.UI.Canvas.marks['!'](this.getElement('canvas'), "#ffffff");
94 95
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 //-------------------------------------------------------------------------
102 104
103 'displayElement': function() { 105 'displayElement': function() {
104 return MochiKit.DOM.getElement('loginProgress'); 106 return MochiKit.DOM.getElement('loginProgress');
105 }, 107 },
106 108
107 //------------------------------------------------------------------------- 109 //-------------------------------------------------------------------------
108 110
109 'cancelEventHandler': function(anEvent) { 111 'cancelEventHandler': function(anEvent) {
110 anEvent.preventDefault(); 112 anEvent.preventDefault();
@@ -112,25 +114,27 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.LoginProgress, Clipperz.PM.UI
112 MochiKit.Signal.signal(this, 'cancelEvent'); 114 MochiKit.Signal.signal(this, 'cancelEvent');
113 }, 115 },
114 116
115 //------------------------------------------------------------------------- 117 //-------------------------------------------------------------------------
116 118
117 'disableCancel': function() { 119 'disableCancel': function() {
118 MochiKit.Style.hideElement(this.getElement('buttonArea')); 120 MochiKit.Style.hideElement(this.getElement('buttonArea'));
119 }, 121 },
120 122
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
128 this.getElement('title').innerHTML = "Error"; 132 this.getElement('title').innerHTML = "Error";
129 MochiKit.Style.showElement(this.getElement('errorBox')); 133 MochiKit.Style.showElement(this.getElement('errorBox'));
130 MochiKit.Style.showElement(this.getElement('buttonArea')); 134 MochiKit.Style.showElement(this.getElement('buttonArea'));
131 }, 135 },
132 136
133 //------------------------------------------------------------------------- 137 //-------------------------------------------------------------------------
134 138
135 'deferredHideModalAndRemove': function(someParameters, aResult) { 139 'deferredHideModalAndRemove': function(someParameters, aResult) {
136 vardeferredResult; 140 vardeferredResult;
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
@@ -73,34 +73,34 @@ Clipperz.Base.extend(Clipperz.PM.UI.Web.Components.ToolsPanel, Clipperz.PM.UI.Co
73 {tag:'li', id:this.getId('passwordGeneratorTab'),children:[{tag:'a', href:'#', html:'Password generator'}], cls:'first'}, 73 {tag:'li', id:this.getId('passwordGeneratorTab'),children:[{tag:'a', href:'#', html:'Password generator'}], cls:'first'},
74 {tag:'li', id:this.getId('bookmarkletTab'), children:[{tag:'a', href:'#', html:'Bookmarklet'}]}, 74 {tag:'li', id:this.getId('bookmarkletTab'), children:[{tag:'a', href:'#', html:'Bookmarklet'}]},
75 {tag:'li', id:this.getId('compactEditionTab'), children:[{tag:'a', href:'#', html:'Compact edition'}]}, 75 {tag:'li', id:this.getId('compactEditionTab'), children:[{tag:'a', href:'#', html:'Compact edition'}]},
76 {tag:'li', id:this.getId('httpAuthTab'), children:[{tag:'a', href:'#', html:'HTTP Auth'}]} 76 {tag:'li', id:this.getId('httpAuthTab'), children:[{tag:'a', href:'#', html:'HTTP Auth'}]}
77 ]} 77 ]}
78 ]} 78 ]}
79 ]}, 79 ]},
80 {tag:'div', cls:'body', children:[ 80 {tag:'div', cls:'body', children:[
81 {tag:'div', cls:'accountPanel', children:[ 81 {tag:'div', cls:'accountPanel', children:[
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 ]}
98 ]} 98 ]}
99 ]}, 99 ]},
100 {tag:'div', cls:'footer'} 100 {tag:'div', cls:'footer'}
101 ]); 101 ]);
102 102
103 this.tabPanelController().setup({selected:this.initiallySelectedTab()}); 103 this.tabPanelController().setup({selected:this.initiallySelectedTab()});
104 }, 104 },
105 105
106 //------------------------------------------------------------------------- 106 //-------------------------------------------------------------------------
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
@@ -222,27 +222,29 @@ MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.AppController.prototype, {
222 slot.setContent(this.appPage()); 222 slot.setContent(this.appPage());
223 223
224 this.appPage().slotNamed('userInfoBox').setContent(this.userInfoBox()); 224 this.appPage().slotNamed('userInfoBox').setContent(this.userInfoBox());
225 this.appPage().slotNamed('tabSidePanel').setContent(this.tabSidePanel()); 225 this.appPage().slotNamed('tabSidePanel').setContent(this.tabSidePanel());
226 226
227 this.appPage().slotNamed('accountPanel').setContent(this.accountPanel()); 227 this.appPage().slotNamed('accountPanel').setContent(this.accountPanel());
228 this.appPage().slotNamed('dataPanel').setContent(this.dataPanel()); 228 this.appPage().slotNamed('dataPanel').setContent(this.dataPanel());
229 this.appPage().slotNamed('toolsPanel').setContent(this.toolsPanel()); 229 this.appPage().slotNamed('toolsPanel').setContent(this.toolsPanel());
230 230
231 this.hideAllAppPageTabSlots(); 231 this.hideAllAppPageTabSlots();
232 this.appPage().showSlot(this.slotNameForTab('cards')); 232 this.appPage().showSlot(this.slotNameForTab('cards'));
233 233
234 MochiKit.Signal.connect(this.tabSidePanel(), 'tabSelected',this, 'handleTabSelected'); 234 MochiKit.Signal.connect(this.tabSidePanel(), 'tabSelected', this, 'handleTabSelected');
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
238 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'downloadOfflineCopy',this, 'handleDownloadOfflineCopy');
237 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});
241 // deferredResult.addMethod(this.directLoginsController(), 'run', {slot:this.appPage().slotNamed('directLoginGrid'), user:user}); 243 // deferredResult.addMethod(this.directLoginsController(), 'run', {slot:this.appPage().slotNamed('directLoginGrid'), user:user});
242 deferredResult.addMethod(this, 'populateUserInfo'); 244 deferredResult.addMethod(this, 'populateUserInfo');
243 245
244 deferredResult.addCallback(MochiKit.Visual.ScrollTo, 'miscLinks', {duration:0}); 246 deferredResult.addCallback(MochiKit.Visual.ScrollTo, 'miscLinks', {duration:0});
245 deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'CARDS_CONTROLLER_DID_RUN'); 247 deferredResult.addCallback(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'CARDS_CONTROLLER_DID_RUN');
246 deferredResult.addMethod(this.tabSidePanel(), 'selectTab', 'cards'); 248 deferredResult.addMethod(this.tabSidePanel(), 'selectTab', 'cards');
247 deferredResult.callback(); 249 deferredResult.callback();
248 }, 250 },
@@ -312,15 +314,38 @@ MochiKit.Base.update(Clipperz.PM.UI.Web.Controllers.AppController.prototype, {
312 //............................................................................. 314 //.............................................................................
313 315
314 'handleUnlock': function (anEvent) { 316 'handleUnlock': function (anEvent) {
315 return Clipperz.Async.callbacks("AppController.handleUnock", [ 317 return Clipperz.Async.callbacks("AppController.handleUnock", [
316 MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress'), 318 MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress'),
317 MochiKit.Base.method(this.user(), 'login'), 319 MochiKit.Base.method(this.user(), 'login'),
318 MochiKit.Base.method(this.cardsController(), 'focus'), 320 MochiKit.Base.method(this.cardsController(), 'focus'),
319 MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'progressDone'), 321 MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'progressDone'),
320 MochiKit.Base.method(this.userInfoBox(), 'unlock') 322 MochiKit.Base.method(this.userInfoBox(), 'unlock')
321 ], {trace:false}); 323 ], {trace:false});
322 }, 324 },
323 325
326 'handleDownloadOfflineCopy': function (anEvent) {
327console.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
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz Community Edition.
6Clipperz Community Edition is an online password manager.
7For further information about its features and functionalities please
8refer 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
26Clipperz.Base.module('Clipperz.PM.UI.iPhone.Components');
27
28Clipperz.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
40Clipperz.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
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz Community Edition.
6Clipperz Community Edition is an online password manager.
7For further information about its features and functionalities please
8refer 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
26Clipperz.Base.module('Clipperz.PM.UI.iPhone.Components');
27
28Clipperz.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
38Clipperz.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
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz Community Edition.
6Clipperz Community Edition is an online password manager.
7For further information about its features and functionalities please
8refer 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
26Clipperz.Base.module('Clipperz.PM.UI.iPhone.Controllers');
27
28 //Some parts of this controller have been derived from the iUI library.
29
30Clipperz.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
59MochiKit.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