/* Copyright 2008-2013 Clipperz Srl This file is part of Clipperz, the online password manager. For further information about its features and functionalities please refer to http://www.clipperz.com. * Clipperz is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * Clipperz is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. * You should have received a copy of the GNU Affero General Public License along with Clipperz. If not, see http://www.gnu.org/licenses/. */ "use strict"; Clipperz.Base.module('Clipperz.PM.UI'); Clipperz.PM.UI.MainController = function() { var genericPageProperties; // this._proxy = null; this._mediaQueryStyle = "narrow"; this._user = null; this._filter = {'type':'ALL'}; this._shouldIncludeArchivedCards = false; this._isSelectionPanelOpen = false; this._isSettingsPanelOpen = false; this._pageStack = ['loadingPage']; this._overlay = new Clipperz.PM.UI.Components.Overlay(); this._isTouchDevice = ('ontouchstart' in window || 'onmsgesturechange' in window); this._isDesktop = window.screenX != 0 && !this._isTouchDevice; this._hasKeyboard = this._isDesktop; this._closeMaskAction = null; this._pages = {}; this.renderPages([ 'loginPage', 'registrationPage', 'mainPage', 'cardDetailPage', 'errorPage', ]); this.registerForNotificationCenterEvents([ 'doLogin', 'registerNewUser', 'showRegistrationForm', 'goBack', 'toggleSelectionPanel', 'toggleSettingsPanel', 'matchMediaQuery', 'unmatchMediaQuery', 'selectAllCards', 'selectRecentCards', 'tagSelected', 'selectUntaggedCards', 'cardSelected', 'addCardClick', 'deleteCard', 'archiveCard', 'editCard', 'showArchivedCards', 'hideArchivedCards', 'goBackToMainPage', 'maskClick', ]); MochiKit.Signal.connect(MochiKit.DOM.currentDocument(), 'onselectionchange', this, 'selectionChangeHandler'); return this; } MochiKit.Base.update(Clipperz.PM.UI.MainController.prototype, { toString: function () { return "Clipperz.PM.UI.MainController"; }, //========================================================================= overlay: function () { return this._overlay; }, loginForm: function () { return this._loginForm; }, registrationWizard: function () { return this._registrationWizard; }, //========================================================================= isOnline: function() { return navigator.onLine; // return false; }, hasLocalData: function() { // return false; return (Clipperz.PM.DataModel.devicePreferences.accountData() != null); }, loginMode: function () { // PIN is set using this command: // Clipperz.PM.PIN.setCredentialsWithPIN('1234', {'username':'joe', 'passphrase':'clipperz'}); return Clipperz.PM.PIN.isSet() ? 'PIN' : 'CREDENTIALS'; }, //========================================================================= pages: function () { return this._pages; }, pageStack: function () { return this._pageStack; }, //========================================================================= showOfflineError: function () { console.log("THE BROWSER IS OFFLINE"); }, selectInitialProxy: function () { if (this.isOnline()) { // this._proxy = Clipperz.PM.Proxy.defaultProxy; } else { if (this.hasLocalData()) { // this._proxy = new Clipperz.PM.Proxy.Offline({dataStore: new Clipperz.PM.Proxy.Offline.LocalStorageDataStore(), shouldPayTolls:false}); Clipperz.PM.Proxy.defaultProxy = new Clipperz.PM.Proxy.Offline({dataStore: new Clipperz.PM.Proxy.Offline.LocalStorageDataStore(), shouldPayTolls:false}); } else { this.showOfflineError(); } } }, // proxy: function () { // return this._proxy; // }, //========================================================================= capitaliseFirstLetter: function (aValue) { return aValue.charAt(0).toUpperCase() + aValue.slice(1); }, renderPages: function (pages) { var self = this; MochiKit.Iter.forEach(pages, function (aPageName) { //console.log("RENDERING", aPageName); self._pages[aPageName] = React.renderComponent( Clipperz.PM.UI.Components.Pages[self.capitaliseFirstLetter(aPageName)](self.pageProperties(aPageName)), MochiKit.DOM.getElement(aPageName) ); }); }, registerForNotificationCenterEvents: function (events) { var self = this; MochiKit.Iter.forEach(events, function (anEvent) { MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent + '_handler')); }); // MochiKit.Signal.connect(window, 'onpopstate', MochiKit.Base.method(this, 'historyGoBack')); // MochiKit.Signal.connect(window, 'onbeforeunload', MochiKit.Base.method(this, 'shouldExitApp')); }, //------------------------------------------------------------------------- selectionChangeHandler: function (anEvent) { var selection; var selectionRange; var selectionNode; var valueElement; // other hints: http://www.bearpanther.com/2013/05/27/easy-text-selection-in-mobile-safari/ // SELECTION: https://developer.mozilla.org/en-US/docs/Web/API/Selection // RANGE: https://developer.mozilla.org/en-US/docs/Web/API/Range // NODE TYPES: https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeType selection = MochiKit.DOM.currentWindow().getSelection(); //console.log("-- selection", selection); selectionRange = selection.getRangeAt(0); selectionNode = selectionRange.startContainer.childNodes[selectionRange.startOffset]; //console.log("-- selectionNode", selectionNode); if (selectionNode != undefined) { valueElement = MochiKit.DOM.getFirstElementByTagAndClassName('*', 'value', selectionNode); //console.log("-- valueElement", valueElement); } if ((valueElement != null) && (valueElement != selectionNode)) { var range; range = MochiKit.DOM.currentDocument().createRange(); range.selectNodeContents(valueElement); selection.removeAllRanges(); selection.addRange(range); anEvent.preventDefault(); anEvent.stopPropagation(); //console.log("updated selection", MochiKit.DOM.currentWindow().getSelection()); } //console.log("-----------"); }, //------------------------------------------------------------------------- run: function (parameters) { var shouldShowRegistrationForm; var canRegisterNewUsers; canRegisterNewUsers = Clipperz.PM.Proxy.defaultProxy.canRegisterNewUsers(); this.selectInitialProxy(); shouldShowRegistrationForm = parameters['shouldShowRegistrationForm'] && canRegisterNewUsers; this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable':canRegisterNewUsers}); if (shouldShowRegistrationForm) { this.showRegistrationForm_handler(); } else { this.showLoginForm(); } // this.overlay().done("", 0.5); this.overlay().hide(); }, //------------------------------------------------------------------------- showLoginForm: function () { var loginFormPage; loginFormPage = this.pages()['loginPage']; loginFormPage.setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable':Clipperz.PM.Proxy.defaultProxy.canRegisterNewUsers()}); this.moveInPage(this.currentPage(), 'loginPage'); MochiKit.Async.callLater(0.5, MochiKit.Base.method(loginFormPage, 'setInitialFocus')); }, showRegistrationForm_handler: function () { var currentPage; var registrationPage; currentPage = this.currentPage(); registrationPage = this.pages()['registrationPage']; this.setCurrentPage('loginPage'); registrationPage.setProps({}); this.moveInPage(currentPage, 'registrationPage'); MochiKit.Async.callLater(0.5, MochiKit.Base.method(registrationPage, 'setInitialFocus')); }, //========================================================================= doLogin_handler: function (event) { return this.doLogin(event); }, doLogin: function (someCredentials) { var deferredResult; var credentials; var getPassphraseDelegate; var user; user = null; this.overlay().show("logging in"); this.pages()['loginPage'].setProps({disabled:true}); if ('pin' in someCredentials) { credentials = Clipperz.PM.PIN.credentialsWithPIN(someCredentials['pin']); } else { credentials = someCredentials; } getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase); user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate}); deferredResult = new Clipperz.Async.Deferred('MainController.doLogin', {trace:false}); deferredResult.addCallback(MochiKit.Async.wait, 0.1); deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection'); deferredResult.addMethod(user, 'login'); deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount'); deferredResult.addMethod(this, 'setUser', user); deferredResult.addMethod(this, 'runApplication'); deferredResult.addMethod(this.overlay(), 'done', "", 1); deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', someCredentials)); deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) { if (anError['isPermanent'] != true) { this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()}); this.pages()['loginPage'].setInitialFocus(); } return anError; }, this, someCredentials)) deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- registerNewUser_handler: function (credentials) { var deferredResult; this.overlay().show("creating user"); this.pages()['registrationPage'].setProps({disabled:true}); deferredResult = new Clipperz.Async.Deferred('MainController.registerNewUser', {trace:false}); deferredResult.addCallback(Clipperz.PM.DataModel.User.registerNewAccount, credentials['username'], MochiKit.Base.partial(MochiKit.Async.succeed, credentials['passphrase']) ); deferredResult.addMethod(this, 'doLogin', credentials); deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', credentials)); deferredResult.addErrback(MochiKit.Base.bind(function (anError) { if (anError['isPermanent'] != true) { this.pages()['registrationPage'].setProps({disabled:false}); this.pages()['registrationPage'].setInitialFocus(); } return anError; }, this)); deferredResult.callback(); return deferredResult; }, //------------------------------------------------------------------------- user: function () { return this._user; }, setUser: function (aUser) { console.log("SET USER", aUser); this._user = aUser; return this._user; }, //========================================================================= filter: function () { return this._filter; }, setFilter: function (aType, aValue) { this._filter = {'type':aType, 'value':aValue}; return this._filter; }, shouldIncludeArchivedCards: function () { return this._shouldIncludeArchivedCards; }, setShouldIncludeArchivedCards: function (aValue) { this._shouldIncludeArchivedCards = aValue; }, //---------------------------------------------------------------------------- collectFieldInfo: function (aField) { var deferredResult; deferredResult = new Clipperz.Async.Deferred('MainController.collectFieldInfo', {trace:false}); deferredResult.addMethod(aField, 'reference'); deferredResult.setValue('_reference'); deferredResult.addMethod(aField, 'label'); deferredResult.setValue('label'); deferredResult.addMethod(aField, 'value'); deferredResult.setValue('value'); deferredResult.addMethod(aField, 'actionType'); deferredResult.setValue('actionType'); deferredResult.addMethod(aField, 'isHidden'); deferredResult.setValue('isHidden'); deferredResult.values(); deferredResult.callback(); return deferredResult; }, collectDirectLoginInfo: function (aDirectLogin) { var deferredResult; deferredResult = new Clipperz.Async.Deferred('MainController.collectDirectLoginInfo', {trace:false}); deferredResult.addMethod(aDirectLogin, 'reference'); deferredResult.setValue('_reference'); deferredResult.addMethod(aDirectLogin, 'label'); deferredResult.setValue('label'); deferredResult.addMethod(aDirectLogin, 'favicon'); deferredResult.setValue('favicon'); deferredResult.values(); deferredResult.callback(); return deferredResult; }, collectRecordInfo: function (aRecord) { var deferredResult; deferredResult = new Clipperz.Async.Deferred('MainController.collectRecordInfo', {trace:false}); deferredResult.addMethod(aRecord, 'reference'); deferredResult.setValue('_reference'); deferredResult.addMethod(aRecord, 'isArchived'); deferredResult.setValue('_isArchived'); deferredResult.addMethod(aRecord, 'label'); deferredResult.setValue('label'); deferredResult.addMethod(aRecord, 'notes'); deferredResult.setValue('notes'); deferredResult.addMethod(aRecord, 'tags'); deferredResult.setValue('tags'); deferredResult.addMethod(aRecord, 'isArchived'); deferredResult.setValue('isArchived'); deferredResult.addMethod(aRecord, 'fields'); deferredResult.addCallback(MochiKit.Base.values); deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'collectFieldInfo')); deferredResult.addCallback(Clipperz.Async.collectAll); deferredResult.setValue('fields'); deferredResult.addMethod(aRecord, 'directLogins'); deferredResult.addCallback(MochiKit.Base.values); deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'collectDirectLoginInfo')); deferredResult.addCallback(Clipperz.Async.collectAll); deferredResult.setValue('directLogins'); deferredResult.values(); deferredResult.callback(); return deferredResult; }, updateSelectedCard: function (someInfo) { var deferredResult; if (someInfo == null) { this.setPageProperties('mainPage', 'selectedCard', {}); deferredResult = MochiKit.Async.succeed(); } else { this.setPageProperties('mainPage', 'selectedCard', {'loading':true, 'label':someInfo['label'], '_reference':someInfo['reference']}); deferredResult = new Clipperz.Async.Deferred('MainController.updateSelectedCard', {trace:false}); deferredResult.addMethod(this.user(), 'getRecord', someInfo['reference']); deferredResult.addMethod(this, 'collectRecordInfo'); //console.log("MEDIA QUERY STYLE", this.mediaQueryStyle()); deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'selectedCard'); if (this.mediaQueryStyle() == 'narrow') { deferredResult.addMethod(this, 'setPageProperties', 'cardDetailPage', 'selectedCard'); deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage'); // deferredResult.addCallback(function (aValue) { console.log("SHOULD SLIDE IN PAGE DETAIL"); return aValue; }); //console.log("SHOULD SLIDE IN PAGE DETAIL"); } MochiKit.Async.callLater(0.1, MochiKit.Base.method(deferredResult, 'callback')); } return deferredResult; }, //............................................................................ regExpFilterGenerator: function (aRegExp, aSearchField) { var searchField = aSearchField ? aSearchField : Clipperz.PM.DataModel.Record.defaultSearchField; return function (aCardInfo) { aRegExp.lastIndex = 0; return aRegExp.test(aCardInfo[searchField]); } }, selectedCardReference: function () { return this.pages()['mainPage'].props && this.pages()['mainPage'].props['selectedCard'] && this.pages()['mainPage'].props['selectedCard'] && this.pages()['mainPage'].props['selectedCard']['_reference'] ? this.pages()['mainPage'].props['selectedCard']['_reference'] : ''; }, isSelectedCardStillVisible: function (someCards) { var result; var reference; reference = this.selectedCardReference(); result = MochiKit.Iter.some(someCards, function (aCardInfo) { return aCardInfo['_reference'] == reference; }); return result; }, updateSelectedCards: function (shouldIncludeArchivedCards, aFilter) { var deferredResult; var sortCriteria; sortCriteria = Clipperz.Base.caseInsensitiveKeyComparator('label'); deferredResult = new Clipperz.Async.Deferred('MainController.setFilter', {trace:false}); deferredResult.addMethod(this.user(), 'getRecordsInfo', Clipperz.PM.DataModel.Record.defaultCardInfo, shouldIncludeArchivedCards); if (aFilter['type'] == 'ALL') { deferredResult.addMethodcaller('sort', sortCriteria); } else if (aFilter['type'] == 'RECENT') { deferredResult.addMethodcaller('sort', Clipperz.Base.reverseComparator(MochiKit.Base.keyComparator('accessDate'))); deferredResult.addCallback(function (someCards) { return someCards.slice(0, 9)}); } else if (aFilter['type'] == 'SEARCH') { deferredResult.addCallback(MochiKit.Base.filter, this.regExpFilterGenerator(Clipperz.PM.DataModel.Record.regExpForSearch(aFilter['value']))); deferredResult.addMethodcaller('sort', sortCriteria); } else if (aFilter['type'] == 'TAG') { deferredResult.addCallback(MochiKit.Base.filter, this.regExpFilterGenerator(Clipperz.PM.DataModel.Record.regExpForTag(aFilter['value']))); deferredResult.addMethodcaller('sort', sortCriteria); } else if (aFilter['type'] == 'UNTAGGED') { deferredResult.addCallback(MochiKit.Base.filter, this.regExpFilterGenerator(Clipperz.PM.DataModel.Record.regExpForNoTag())); deferredResult.addMethodcaller('sort', sortCriteria); } deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'cards'); deferredResult.addCallback(MochiKit.Base.bind(function (someCards) { if (!this.isSelectedCardStillVisible(someCards)) { this.updateSelectedCard(null); }; }, this)); deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'filter', this.filter()); deferredResult.callback(); return deferredResult; }, refreshSelectedCards: function () { return this.updateSelectedCards(this.shouldIncludeArchivedCards(), this.filter()); }, refreshUI: function (selectedCardReference) { var deferredResult; deferredResult = new Clipperz.Async.Deferred('MainController.refreshUI', {trace:false}); deferredResult.addMethod(this, 'refreshSelectedCards'); deferredResult.addMethod(this, 'renderTags'); if (selectedCardReference != null) { deferredResult.addMethod(this.user(), 'getRecord', selectedCardReference); deferredResult.addMethod(this, 'collectRecordInfo'); deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'selectedCard'); } deferredResult.callback(); return deferredResult; }, //---------------------------------------------------------------------------- getArchivedCardsCount: function () { return Clipperz.Async.callbacks("MainController.getArchivedCardsCount", [ MochiKit.Base.method(this.user(), 'getRecords'), MochiKit.Base.partial(MochiKit.Base.map, Clipperz.Async.collectResults("collectResults", {'_isArchived':MochiKit.Base.methodcaller('isArchived')}, {trace:false})), Clipperz.Async.collectAll, function (aResult) { return MochiKit.Base.filter(function (aRecordInfo) { return aRecordInfo['_isArchived']; }, aResult).length; } ], {trace:false}); }, getUntaggedCardsCount: function () { var archivedCardsFilter = this.shouldIncludeArchivedCards() ? MochiKit.Async.succeed : MochiKit.Base.partial(MochiKit.Base.filter, function (someRecordInfo) { return ! someRecordInfo['_isArchived']; }); return Clipperz.Async.callbacks("MainController.getUntaggedCardsCount", [ MochiKit.Base.method(this.user(), 'getRecords'), MochiKit.Base.partial(MochiKit.Base.map, Clipperz.Async.collectResults("collectResults", {'_fullLabel':MochiKit.Base.methodcaller('fullLabel'), '_isArchived':MochiKit.Base.methodcaller('isArchived')}, {trace:false})), Clipperz.Async.collectAll, archivedCardsFilter, MochiKit.Base.partial(MochiKit.Base.filter, this.regExpFilterGenerator(Clipperz.PM.DataModel.Record.regExpForNoTag(), '_fullLabel')), function (someCards) { return someCards.length; }, ], {trace:false}); }, //---------------------------------------------------------------------------- setPageProperties: function (aPageName, aKey, aValue) { var props = {}; props[aKey] = aValue; this.pages()[aPageName].setProps(props); return aValue; }, renderTags: function () { return Clipperz.Async.callbacks("MainController.renderTags", [ MochiKit.Base.method(this.user(), 'getTags', this.shouldIncludeArchivedCards()), MochiKit.Base.method(this, 'setPageProperties', 'mainPage', 'tags'), MochiKit.Base.method(this, 'getArchivedCardsCount'), MochiKit.Base.method(this, 'setPageProperties', 'mainPage', 'archivedCardsCount'), MochiKit.Base.method(this, 'getUntaggedCardsCount'), MochiKit.Base.method(this, 'setPageProperties', 'mainPage', 'untaggedCardsCount'), MochiKit.Base.method(this, 'setPageProperties', 'mainPage', 'shouldIncludeArchivedCards', this.shouldIncludeArchivedCards()), ], {trace:false}); }, renderAccountData: function () { return Clipperz.Async.callbacks("MainController.renderAccountData", [ MochiKit.Base.method(this, 'setFilter', 'ALL'), MochiKit.Base.method(this, 'refreshUI', null) ], {trace:false}); }, //========================================================================= runApplication: function (anUser) { this.moveInPage(this.currentPage(), 'mainPage'); return this.renderAccountData(); }, /* runDirectLogin_handler: function (someParameters) { //console.log("RUN DIRECT LOGIN", someParameters); var deferredResult; deferredResult = new Clipperz.Async.Deferred('MainController.runDirectLogin', {trace:false}); deferredResult.addMethod(this.user(), 'getRecord', someParameters['record']); deferredResult.addMethodcaller('directLoginWithReference', someParameters['directLogin']); deferredResult.addCallback(Clipperz.PM.UI.DirectLoginRunner.openDirectLogin); deferredResult.callback(); return deferredResult; }, shouldExitApp: function (anEvent) { //console.log("SHOULD EXIT APP"); anEvent.preventDefault(); anEvent.stopPropagation(); }, */ //========================================================================= /* searchCards_handler: function (someParameters) { //console.log("SEARCH CARDS", someParameters); this.setFilter(someParameters); this.renderAccountData(); }, */ //========================================================================= /* showPreferences_handler: function (anEvent) { var deferredResult; this.pages()['preferencePage'].setProps({}); deferredResult = new Clipperz.Async.Deferred('MainController.showPreferences', {trace:false}); deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'preferencePage', true); deferredResult.callback(); return deferredResult; }, */ //========================================================================= genericErrorHandler: function (anEvent, anError) { var errorMessage; var result; result = anError; errorMessage = "login failed"; if (anError['isPermanent'] === true) { this.pages()['errorPage'].setProps({message:anError.message}); this.moveInPage(this.currentPage(), 'errorPage'); errorMessage = "failure"; } else { if ('pin' in anEvent) { errorCount = Clipperz.PM.PIN.recordFailedAttempt(); if (errorCount == -1) { errorMessage = "PIN resetted"; } } } this.overlay().failed(errorMessage, 1); return result; }, //========================================================================= slidePage: function (fromPage, toPage, direction) { var fromPosition; var toPosition; var itemToTransition; if (direction == "LEFT") { fromPosition = 'right'; toPosition = 'left'; itemToTransition = toPage; } else { fromPosition = 'left'; toPosition = 'right'; itemToTransition = fromPage; } MochiKit.DOM.addElementClass(itemToTransition, 'transition'); MochiKit.Async.callLater(0, function () { MochiKit.DOM.addElementClass(fromPage, toPosition); MochiKit.DOM.removeElementClass(toPage, fromPosition); }) MochiKit.Async.callLater(0.5, function () { MochiKit.DOM.removeElementClass(itemToTransition, 'transition'); }) }, //......................................................................... goBack_handler: function () { var fromPage; var toPage; fromPage = this.pageStack().shift(); toPage = this.currentPage(); this.pages()[toPage].setProps({}); this.moveOutPage(fromPage, toPage); }, historyGoBack: function (anEvent) { anEvent.preventDefault(); anEvent.stopPropagation(); this.goBack(); }, currentPage: function () { return this.pageStack()[0]; }, setCurrentPage: function (aPage) { this.pageStack().unshift(aPage); this.refreshCurrentPage(); }, moveInPage: function (fromPage, toPage, addToHistory) { var shouldAddItemToHistory; shouldAddItemToHistory = typeof(addToHistory) == 'undefined' ? false : addToHistory; this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'LEFT'); this.setCurrentPage(toPage); if (shouldAddItemToHistory) { //console.log("ADD ITEM TO HISTORY"); //console.log("ADD ITEM TO HISTORY - window", window); //console.log("ADD ITEM TO HISTORY - window.history", window.history); window.history.pushState({'fromPage': fromPage, 'toPage': toPage}); //# window.history.pushState(); //console.log("ADDED ITEM TO HISTORY"); } else { //console.log("Skip HISTORY"); } }, moveOutPage: function (fromPage, toPage) { this.slidePage(MochiKit.DOM.getElement(fromPage), MochiKit.DOM.getElement(toPage), 'RIGHT'); this.setCurrentPage(toPage); }, //------------------------------------------------------------------------- messageBoxContent: function () { var message; var level; message = ""; level = 'HIDE'; //console.log("messageBox - this.user()", this.user()); if (this.user() != null && this.user().accountInfo() != null && this.user().accountInfo().featureSet() == 'EXPIRED') { message = "Exprired subscription"; level = 'ERROR'; } return { 'message': message, 'level': level }; }, userAccountInfo: function () { var result; result = {}; if (this.user() != null) { var usefulFields = [ 'currentSubscriptionType', 'expirationDate', 'featureSet', 'isExpired', 'isExpiring', 'paymentVerificationPending' ]; var attributes = this.user().accountInfo()._attributes; MochiKit.Iter.forEach(usefulFields, function (aFieldName) { result[aFieldName] = attributes[aFieldName]; }) }; return result; }, genericPageProperties: function () { return { 'style': this.mediaQueryStyle(), 'isTouchDevice': this.isTouchDevice(), 'isDesktop': this.isDesktop(), 'hasKeyboard': this.hasKeyboard() }; }, pageProperties: function (aPageName) { var result; var extraProperties = null; result = this.genericPageProperties(); if (aPageName == 'loginPage') { extraProperties = { 'mode': 'CREDENTIALS', 'isNewUserRegistrationAvailable': true, 'disabled': false, }; } else if (aPageName == 'registrationPage') { } else if (aPageName == 'mainPage') { extraProperties = { 'messageBox': this.messageBoxContent(), 'accountStatus': this.userAccountInfo(), 'selectionPanelStatus': this.isSelectionPanelOpen() ? 'OPEN' : 'CLOSED', 'settingsPanelStatus': this.isSettingsPanelOpen() ? 'OPEN' : 'CLOSED', // 'shouldIncludeArchivedCards': this.shouldIncludeArchivedCards(), // 'cards': …, // 'tags': …, // 'selectedCard': …, }; } else if (aPageName == 'errorPage') { extraProperties = { 'message': '' }; } if (extraProperties != null) { result = MochiKit.Base.update(result, extraProperties); } //console.log("MainController.pageProperties", result); return result; }, refreshCurrentPage: function () { if (this.pages()[this.currentPage()] != null) { this.pages()[this.currentPage()].setProps(this.pageProperties(this.currentPage())); } }, //========================================================================= /* synchronizeLocalData_handler: function (anEvent) { var deferredResult; deferredResult = new Clipperz.Async.Deferred('MainController.synchronizeLocalData', {trace:false}); // deferredResult.addMethod(this.proxy(), 'message', 'downloadAccountData', {}); deferredResult.addMethod(this.user().connection(), 'message', 'downloadAccountData', {}); deferredResult.addCallback(function (aResult) { Clipperz.PM.DataModel.devicePreferences.setAccountDataWityResponse(aResult); // localStorage.setItem('clipperz_dump_data', aResult['data']); // localStorage.setItem('clipperz_dump_version', aResult['version']); // localStorage.setItem('clipperz_dump_date', new Date()); }) deferredResult.callback(); return deferredResult; }, */ //========================================================================= resetPanels: function () { this._isSelectionPanelOpen = false; this._isSettingsPanelOpen = false; }, isSelectionPanelOpen: function () { return this._isSelectionPanelOpen; }, toggleSelectionPanel_handler: function (anEvent) { this._isSelectionPanelOpen = !this._isSelectionPanelOpen; this.setCloseMaskAction(MochiKit.Base.method(this, 'toggleSelectionPanel_handler')); this.refreshCurrentPage(); }, isSettingsPanelOpen: function () { return this._isSettingsPanelOpen; }, toggleSettingsPanel_handler: function (anEvent) { this._isSettingsPanelOpen = !this._isSettingsPanelOpen; this.setCloseMaskAction(MochiKit.Base.method(this, 'toggleSettingsPanel_handler')); this.refreshCurrentPage(); }, cardSelected_handler: function (someInfo) { this.updateSelectedCard(someInfo); }, //---------------------------------------------------------------------------- /* askConfirmation: function (aMessage) { var deferredResult; deferredResult = new Clipperz.Async.Deferred('MainController.askConfirmation', {trace:false}); deferredResult.callback(); // deferredResult.cancel(); return deferredResult; }, */ ask: function (someInfo) { var deferredResult; var currentPage = this.pages()[this.currentPage()]; deferredResult = new Clipperz.Async.Deferred('MainController.ask', {trace:false}); currentPage.setProps({'ask': {'info': someInfo, 'deferred':deferredResult}}); // deferredResult.addCallback(function (aResult) { console.log("ASK - OK", aResult); return aResult; }); // deferredResult.addErrback(function (aResult) { console.log("ASK - FAIL", aResult); return aResult; }); deferredResult.addBothPass(MochiKit.Base.method(currentPage, 'setProps', {'ask': null})); return deferredResult; }, //---------------------------------------------------------------------------- addCardClick_handler: function () { console.log("ADD CARD CLICK"); }, deleteCard_handler: function (anEvent) { var self = this; return Clipperz.Async.callbacks("MainController.deleteCard_handler", [ // MochiKit.Base.method(this, 'askConfirmation', {'message':"Delete card?"}), MochiKit.Base.method(self, 'ask', { 'question': "Delete card?", 'possibleAnswers':{ 'cancel': {'label':"No", 'isDefault':true, 'answer':MochiKit.Base.methodcaller('cancel', new MochiKit.Async.CancelledError())}, 'delete': {'label':"Yes", 'isDefault':false, 'answer':MochiKit.Base.methodcaller('callback')} } }), //function (aValue) { console.log("<-- ASK", aValue); return aValue; }, MochiKit.Base.method(this.user(), 'getRecord', anEvent['reference']), MochiKit.Base.method(this.user(), 'deleteRecord'), MochiKit.Base.method(this.user(), 'saveChanges'), MochiKit.Base.method(this, 'refreshUI') ], {trace:false}); }, archiveCard_handler: function (anEvent) { return Clipperz.Async.callbacks("MainController.archiveCard_handler", [ MochiKit.Base.method(this.user(), 'getRecord', anEvent['reference']), MochiKit.Base.methodcaller('archive'), MochiKit.Base.method(this.user(), 'saveChanges'), MochiKit.Base.method(this, 'refreshUI', anEvent['reference']) ], {trace:false}); }, editCard_handler: function (anEvent) { console.log("EDIT CARD", anEvent['reference']); }, goBackToMainPage_handler: function (anEvent) { this.updateSelectedCard(); this.moveOutPage(this.currentPage(), 'mainPage'); }, //============================================================================ selectAllCards_handler: function () { this.setFilter('ALL'); return this.refreshSelectedCards(); }, selectRecentCards_handler: function () { this.setFilter('RECENT'); return this.refreshSelectedCards(); }, tagSelected_handler: function (aTag) { this.setFilter('TAG', aTag); return this.refreshSelectedCards(); }, selectUntaggedCards_handler: function () { this.setFilter('UNTAGGED'); return this.refreshSelectedCards(); }, //............................................................................ showArchivedCards_handler: function () { this.setShouldIncludeArchivedCards(true); return this.refreshUI(); }, hideArchivedCards_handler: function () { this.setShouldIncludeArchivedCards(false); return this.refreshUI(); }, //---------------------------------------------------------------------------- setCloseMaskAction: function (aFunction) { this._closeMaskAction = aFunction; }, maskClick_handler: function () { this._closeMaskAction.apply(this); this._closeMaskAction = null; }, //============================================================================ matchMediaQuery_handler: function (newQueryStyle) { this._mediaQueryStyle = newQueryStyle; if (this.currentPage() == 'cardDetailPage') { this.moveOutPage(this.currentPage(), 'mainPage'); } this.resetPanels(); this.refreshCurrentPage(); }, unmatchMediaQuery_handler: function (queryStyle) { }, mediaQueryStyle: function () { return this._mediaQueryStyle; }, //---------------------------------------------------------------------------- isTouchDevice: function () { return this._isTouchDevice; }, isDesktop: function () { return this._isDesktop; }, hasKeyboard: function () { return this._hasKeyboard; }, //============================================================================ /* wrongAppVersion: function (anError) { // this.pages()['errorPage'].setProps({message:anError.message}); // this.moveInPage('errorPage', this.currentPage()); }, */ //========================================================================= __syntaxFix__: "syntax fix" });