/* 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/. */ if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } if (typeof(Clipperz.PM) == 'undefined') { Clipperz.PM = {}; } if (typeof(Clipperz.PM.Components) == 'undefined') { Clipperz.PM.Components = {}; } if (typeof(Clipperz.PM.Components.Panels) == 'undefined') { Clipperz.PM.Components.Panels = {}; } //############################################################################# Clipperz.PM.Components.Panels.AccountPanel = function(anElement, args) { //MochiKit.Logging.logDebug(">>> new AccountPanel"); args = args || {}; Clipperz.PM.Components.Panels.AccountPanel.superclass.constructor.call(this, anElement, args); Clipperz.NotificationCenter.register(null, 'setupDone', this, 'render'); this._shouldLoadLoginHistory = true; // this.render(); //MochiKit.Logging.logDebug("<<< new AccountPanel"); return this; } //============================================================================= YAHOO.extendX(Clipperz.PM.Components.Panels.AccountPanel, Clipperz.PM.Components.Panels.BasePanel, { 'toString': function() { return "Clipperz.PM.Components.AccountPanel component"; }, //------------------------------------------------------------------------- 'render': function() { var errorMessageActor; var changePasswordButton; var deleteAccountButton; try { //MochiKit.Logging.logDebug(">>> AccountPanel.render"); Clipperz.NotificationCenter.unregister(this); MochiKit.Signal.disconnectAllTo(this); this.element().update(""); Clipperz.YUI.DomHelper.append(this.element().dom, {tag:'table', border:'0', cellspacing:'0', cellpadding:'0', children:[ {tag:'tbody', children:[ {tag:'tr', children:[ {tag:'td', valign:'top', width:'200', children:[ {tag:'ul', id:"accountSubMenu", cls:'subMenu', children:[ {tag:'li', id:'changePassphraseTab', htmlString:Clipperz.PM.Strings['changePasswordTabLabel']}, {tag:'li', id:'manageOTPTab', htmlString:Clipperz.PM.Strings['manageOTPTabLabel']}, {tag:'li', id:'accountPreferencesTab', htmlString:Clipperz.PM.Strings['accountPreferencesLabel']}, {tag:'li', id:'loginHistoryTab', htmlString:Clipperz.PM.Strings['accountLoginHistoryLabel']}, {tag:'li', id:'deleteAccountTab', htmlString:Clipperz.PM.Strings['deleteAccountTabLabel']} // {tag:'li', id:'paidAccountTab'), htmlString:Clipperz.PM.Strings['paidAccountTabLabel']} ]} ]}, {tag:'td', valign:'top', children:[ {tag:'ul', cls:'clipperzTabPanels', children:[ {tag:'li', id:this.getId('changePassphrasePanel'), children:[ {tag:'div', cls:'clipperzSubPanel', children:[ {tag:'h5', htmlString:Clipperz.PM.Strings['changePasswordTabTitle']}, {tag:'div', cls:'panelBody', id:'changePassphraseBlock', children:[ {tag:'form', id:this.getId('changePassphraseForm'), children:[ {tag:'h5', cls:'errorMessage', id:this.getId('changePassphrase_errorMessage')}, {tag:'table', cls:'panelBody', children:[ {tag:'tr', children:[ {tag:'td', children:[ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['changePasswordFormUsernameLabel']} ]}, {tag:'td', children:[ {tag:'input', type:'text', name:'username', id:this.getId('changePassphrase_username')} ]} ]}, {tag:'tr', children:[ {tag:'td', children:[ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['changePasswordFormOldPassphraseLabel']} ]}, {tag:'td', children:[ {tag:'input', type:'password', name:'oldPassphrase', id:this.getId('changePassphrase_oldPassphrase')} ]} ]}, {tag:'tr', children:[ {tag:'td', children:[ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['changePasswordFormNewPassphraseLabel']} ]}, {tag:'td', children:[ {tag:'input', type:'password', name:'newPassphrase', id:this.getId('changePassphrase_newPassphrase')} ]} ]}, {tag:'tr', children:[ {tag:'td', children:[ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['changePasswordFormRetypePassphraseLabel']} ]}, {tag:'td', children:[ {tag:'input', type:'password', name:'renewPassphrase', id:this.getId('changePassphrase_renewPassphrase')} ]} ]}, {tag:'tr', children:[ {tag:'td', align:'right', children:[ {tag:'input', type:'checkbox', id:this.getId('changePassphrase_safetyCheck')} ]}, {tag:'td', children:[ {tag:'span', htmlString:Clipperz.PM.Strings['changePasswordFormSafetyCheckboxLabel']} ]} ]} ]}, {tag:'div', cls:'clipperzSubPanelButtonBox', children:[ {tag:'div', id:this.getId('changePassphraseButton')} ]} ]} ]} ]} ]}, {tag:'li', id:this.getId('manageOTPPanel'), children:[ {tag:'div', cls:'clipperzSubPanel', children:[ {tag:'h5', htmlString:Clipperz.PM.Strings['manageOTPTabTitle']}, {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['manageOTPTabDescription']}, {tag:'div', id:'OTPComponent'} ]} ]}, {tag:'li', id:this.getId('accountPreferencesPanel'), children:[ {tag:'div', cls:'clipperzSubPanel', children:[ {tag:'h5', htmlString:Clipperz.PM.Strings['accountPreferencesTabTitle']}, {tag:'div', cls:'panelBody', id:this.getId('preferencesPanelBody')} ]} ]}, {tag:'li', id:this.getId('loginHistoryAccountPanel'), children:[ {tag:'div', cls:'clipperzSubPanel', children:[ {tag:'h5', htmlString:Clipperz.PM.Strings['loginHistoryTabTitle']}, {tag:'div', cls:'panelBody', id:'loginHistoryAccountBlock'} ]} ]}, {tag:'li', id:this.getId('deleteAccountPanel'), children:[ {tag:'div', cls:'clipperzSubPanel', children:[ {tag:'h5', htmlString:Clipperz.PM.Strings['deleteAccountTabTitle']}, {tag:'div', cls:'panelBody', id:'deleteAccountBlock', children:[ {tag:'form', id:this.getId('deleteAccountForm'), children:[ {tag:'h5', cls:'errorMessage', id:this.getId('deleteAccount_errorMessage')}, {tag:'table', cls:'panelBody', children:[ {tag:'tr', children:[ {tag:'td', children:[ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['deleteAccountFormUsernameLabel']} ]}, {tag:'td', children:[ {tag:'input', type:'text', name:'username', id:this.getId('deleteAccount_username')} ]} ]}, {tag:'tr', children:[ {tag:'td', children:[ {tag:'span', cls:'formLabel', htmlString:Clipperz.PM.Strings['deleteAccountFormPassphraseLabel']} ]}, {tag:'td', children:[ {tag:'input', type:'password', name:'passphrase', id:this.getId('deleteAccount_passphrase')} ]} ]}, {tag:'tr', children:[ {tag:'td', align:'right', children:[ {tag:'input', type:'checkbox', id:this.getId('deleteAccount_safetyCheck')} ]}, {tag:'td', children:[ {tag:'span', htmlString:Clipperz.PM.Strings['deleteAccountFormSafetyCheckboxLabel']} ]} ]} ]}, {tag:'div', cls:'clipperzSubPanelButtonBox', children:[ {tag:'div', id:this.getId('deleteAccountButton')} ]} ]} ]} ]} ]} /* {tag:'li', id:this.getId('paidAccountPanel'), children:[ {tag:'div', cls:'clipperzSubPanel', children:[ {tag:'h5', htmlString:Clipperz.PM.Strings['upgradeAccountTabTitle']}, {tag:'div', htmlString:Clipperz.PM.Strings['comingSoon']} ]} ]} */ ]} ]} ]} ]} ]}); //MochiKit.Logging.logDebug("--- AccountPanel.render - 1"); MochiKit.Signal.connect(this.getId('changePassphraseForm'), 'onkeydown', this, 'onkeydown'); errorMessageActor = this.getActor('changePassphrase_errorMessage'); errorMessageActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY); errorMessageActor.update("---"); errorMessageActor.hide(); changePasswordButton = new YAHOO.ext.Button(this.getDom('changePassphraseButton'), {text:Clipperz.PM.Strings['changePasswordFormSubmitLabel'], handler:this.doChangePassphrase, scope:this}); //MochiKit.Logging.logDebug("--- AccountPanel.render - 2"); MochiKit.Signal.connect(this.getId('deleteAccountForm'), 'onkeydown', this, 'onkeydown'); errorMessageActor = this.getActor('deleteAccount_errorMessage'); errorMessageActor.setVisibilityMode(YAHOO.ext.Element.DISPLAY); errorMessageActor.update(Clipperz.PM.Strings['deleteAccountFormEmptyErrorMessage']); errorMessageActor.hide(); deleteAccountButton = new YAHOO.ext.Button(this.getDom('deleteAccountButton'), {text:Clipperz.PM.Strings['deleteAccountFormSubmitLabel'], handler:this.doDeleteAccount, scope:this}); //MochiKit.Logging.logDebug("--- AccountPanel.render - 5"); if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) { this.getElement('changePassphraseForm').addClass('read-only'); // this.getElement('accountPreferencesForm').addClass('read-only'); this.getElement('deleteAccountForm').addClass('read-only'); changePasswordButton.disable(); deleteAccountButton.disable(); } //MochiKit.Logging.logDebug("--- AccountPanel.render - 6"); new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('changePassphrase_oldPassphrase')); new Clipperz.PM.Components.PasswordEntropyDisplay(this.getElement('changePassphrase_newPassphrase')); new Clipperz.PM.Components.OTP.MainComponent(YAHOO.ext.Element.get('OTPComponent'), {user:this.user()}); this.tabPanelController().setUp(); Clipperz.NotificationCenter.register(null, 'tabSelected', this, 'tabSelectedHandler'); Clipperz.NotificationCenter.register(null, 'updatedPreferences', this, 'renderPreferences'); Clipperz.NotificationCenter.register(null, 'switchLanguage', this, 'switchLanguageHandler'); //MochiKit.Logging.logDebug("<<< AccountPanel.render"); } catch(exception) { MochiKit.Logging.logError("### " + exception); throw exception; } }, //------------------------------------------------------------------------- 'tabPanelController': function() { if (this._tabPanelController == null) { var tabPanelControllerConfig; tabPanelControllerConfig = {} tabPanelControllerConfig['changePassphraseTab'] = this.getId('changePassphrasePanel'); tabPanelControllerConfig['manageOTPTab'] = this.getId('manageOTPPanel'); tabPanelControllerConfig['accountPreferencesTab'] = this.getId('accountPreferencesPanel'); tabPanelControllerConfig['loginHistoryTab'] = this.getId('loginHistoryAccountPanel'); tabPanelControllerConfig['deleteAccountTab'] = this.getId('deleteAccountPanel'); // tabPanelControllerConfig['paidAccountTab'] = this.getId('paidAccountPanel'); this._tabPanelController = new Clipperz.PM.Components.TabPanel.TabPanelController({ name:'accountTabPanel', config:tabPanelControllerConfig, selectedTab:'changePassphraseTab' }); } return this._tabPanelController; }, //------------------------------------------------------------------------- 'doChangePassphrase': function() { if (Clipperz.PM.Proxy.defaultProxy.isReadOnly() == false) { var username; var oldPassphrase; var newPassphrase; var renewPassphrase; var safetyCheck; var areThereAnyErrors; var errorMessageActor; errorMessageActor = this.getActor('changePassphrase_errorMessage'); areThereAnyErrors = false; username = this.getDom('changePassphrase_username').value; oldPassphrase= this.getDom('changePassphrase_oldPassphrase').value; newPassphrase= this.getDom('changePassphrase_newPassphrase').value; renewPassphrase= this.getDom('changePassphrase_renewPassphrase').value; safetyCheck = this.getDom('changePassphrase_safetyCheck').checked; if (this.user().username() != username) { this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['changePasswordFormWrongUsernameWarning']); this.getElement('changePassphrase_username').focus().dom.select(); areThereAnyErrors = true; } else if (this.user().passphrase() != oldPassphrase) { this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['changePasswordFormWrongPassphraseWarning']); this.getElement('changePassphrase_oldPassphrase').focus().dom.select(); areThereAnyErrors = true; } else if (newPassphrase != renewPassphrase) { this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['changePasswordFormWrongRetypePassphraseWarning']); this.getElement('changePassphrase_renewPassphrase').focus().dom.select(); areThereAnyErrors = true; } else if (safetyCheck != true) { this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['changePasswordFormSafetyCheckWarning']); this.getElement('changePassphrase_safetyCheck').focus(); areThereAnyErrors = true; } if (areThereAnyErrors == false) { errorMessageActor.hide(); this.doChangePassphraseWithUsernameAndPassphrase(username, newPassphrase); } } }, //------------------------------------------------------------------------- 'doChangePassphraseWithUsernameAndPassphrase': function(anUsername, aPassphrase) { var deferredResult; //MochiKit.Logging.logDebug(">>> AccountPanel.doChangePassphraseWithUsernameAndPassphrase - this.user: " + this.user()); deferredResult = new MochiKit.Async.Deferred(); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 1: " + res); return res;}); deferredResult.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'), { title:Clipperz.PM.Strings['changePasswordFormProgressDialogTitle'], text:Clipperz.PM.Strings['changePasswordFormProgressDialogEmptyText'], width:240, showProgressBar:true, showCloseButton:false, steps:4 }, this.getDom('changePassphraseButton') ); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 2: " + res); return res;}); deferredResult.addCallback(MochiKit.Base.method(this.user(), 'changeCredentials'), anUsername, aPassphrase); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 3: " + res); return res;}); deferredResult.addCallback(function() { Clipperz.PM.Components.MessageBox().update({ title:Clipperz.PM.Strings['changePasswordFormProgressDialogConnectedMessageTitle'], text:Clipperz.PM.Strings['changePasswordFormProgressDialogConnectedMessageText'], /*showProgressBar:false,*/ step:'next' }); }); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 4: " + res); return res;}); deferredResult.addCallback(MochiKit.Async.wait, 1); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 5: " + res); return res;}); deferredResult.addCallback(function(anAccountPanel, res) { Clipperz.PM.Components.MessageBox().hide(YAHOO.ext.Element.get('main')); anAccountPanel.getDom('changePassphrase_username').value = ""; anAccountPanel.getDom('changePassphrase_oldPassphrase').value = ""; anAccountPanel.getElement('changePassphrase_oldPassphrase').focus(); anAccountPanel.getDom('changePassphrase_newPassphrase').value = ""; anAccountPanel.getElement('changePassphrase_newPassphrase').focus(); anAccountPanel.getDom('changePassphrase_renewPassphrase').value = ""; anAccountPanel.getDom('changePassphrase_safetyCheck').checked = false; anAccountPanel.getElement('changePassphrase_username').focus(); return res; }, this); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 6: " + res); return res;}); deferredResult.addErrback(function() { Clipperz.PM.Components.MessageBox().update({ title:Clipperz.PM.Strings['changePasswordFormProgressDialogErrorMessageTitle'], text:Clipperz.PM.Strings['changePasswordFormProgressDialogErrorMessageText'], buttons:{'ok':"close"} }); }); //deferredResult.addBoth(function(res) {MochiKit.Logging.logDebug(" AccountPanel.doChangePassphraseWithUsernameAndPassphrase 7: " + res); return res;}); deferredResult.callback(); //MochiKit.Logging.logDebug("<<< AccountPanel.doChangePassphraseWithUsernameAndPassphrase"); }, //------------------------------------------------------------------------- 'doDeleteAccount': function() { if (Clipperz.PM.Proxy.defaultProxy.isReadOnly() == false) { var username; var passphrase; var safetyCheck; var areThereAnyErrors; var errorMessageActor; errorMessageActor = this.getActor('deleteAccount_errorMessage'); areThereAnyErrors = false; username = this.getDom('deleteAccount_username').value; passphrase= this.getDom('deleteAccount_passphrase').value; safetyCheck = this.getDom('deleteAccount_safetyCheck').checked; if (this.user().username() != username) { this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['deleteAccountFormWrongUsernameWarning']); this.getElement('deleteAccount_username').focus().dom.select(); areThereAnyErrors = true; } else if (this.user().passphrase() != passphrase) { this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['deleteAccountFormWrongPassphraseWarning']); this.getElement('deleteAccount_passphrase').focus().dom.select(); areThereAnyErrors = true; } else if (safetyCheck != true) { this.showFormErrorMessageAnimation(errorMessageActor, Clipperz.PM.Strings['deleteAccountFormSafetyCheckWarning']); this.getElement('deleteAccount_safetyCheck').focus(); areThereAnyErrors = true; } if (areThereAnyErrors == false) { var deferred; deferred = new MochiKit.Async.Deferred(); errorMessageActor.hide(); deferred.addCallback(function() { var deferredResult; // TODO: if the form is submitted with the return key, the confirmation dialog is skipped!? deferredResult = new MochiKit.Async.Deferred(); Clipperz.PM.Components.MessageBox().deferredShow({ title:Clipperz.PM.Strings['accountPanelDeletingAccountPanelConfirmationTitle'], text:Clipperz.PM.Strings['accountPanelDeleteAccountPanelConfirmationText'], width:240, showProgressBar:false, showCloseButton:false, buttons:{ 'yes':Clipperz.PM.Strings['accountPanelDeleteAccountPanelConfirmButtonLabel'], 'no':Clipperz.PM.Strings['accountPanelDeleteAccountPanelDenyButtonLabel'] }, fn:MochiKit.Base.partial(function(aDeferred, aResult) { if (aResult == 'yes') { aDeferred.callback(aResult); } else { aDeferred.errback(aResult); } }, deferredResult) }); return deferredResult; }); deferred.addCallback(MochiKit.Base.method(Clipperz.PM.Components.MessageBox(), 'deferredShow'), { title:Clipperz.PM.Strings['accountPanelDeletingAccountPanelProgressTitle'], text:Clipperz.PM.Strings['accountPanelDeletingAccountPanelProgressText'], width:240, showProgressBar:true, showCloseButton:false } ); deferred.addCallback(MochiKit.Base.method(this.user(), 'deleteAccountAction')); deferred.addCallback(Clipperz.PM.exit, 'accountDeleted.html'); deferred.addErrback(function(res) { alert(res); }) deferred.callback(); } } }, //------------------------------------------------------------------------- 'showFormErrorMessageAnimation': function(anActor, anErrorMessage, aCallback) { anActor.update(anErrorMessage); anActor.show(true); anActor.play(aCallback); }, //------------------------------------------------------------------------- 'onkeydown': function(anEvent) { //MochiKit.Logging.logDebug(">>> onkeydown - " + anEvent.src().id); if (anEvent.key().code == 13) { anEvent.stop(); if (anEvent.src() == this.getDom('changePassphraseForm')) { this.doChangePassphrase(); } else if (anEvent.src() == this.getDom('deleteAccountForm')) { this.doDeleteAccount(); } else { } } }, //------------------------------------------------------------------------- 'selectSelectedLanguageOption': function() { var userSelectedLanguage; userSelectedLanguage = this.user().preferences().preferredLanguage() || "default"; MochiKit.Base.filter(function(anOption) {return (anOption.value == userSelectedLanguage)}, this.getDom('languageSelector').childNodes)[0].selected = true; }, //------------------------------------------------------------------------- 'doSaveUserPreferences': function() { var selectedLanguage; var showDonationReminderDialog; // var disableUnsecureFaviconLoadingForIE; //MochiKit.Logging.logDebug(">>> AccountPanel.doSaveUserPreferences"); selectedLanguage = this.getDom('languageSelector').value; if (selectedLanguage == "default") { selectedLanguage = null; } this.user().preferences().setPreferredLanguage(selectedLanguage); showDonationReminderDialog = this.getDom('showDonationReminderCheckbox').checked; this.user().preferences().setShouldShowDonationPanel(showDonationReminderDialog); // disableUnsecureFaviconLoadingForIE = this.getDom('disableFaviconForIECheckbox').checked; // this.user().preferences().setDisableUnsecureFaviconLoadingForIE(disableUnsecureFaviconLoadingForIE); this.user().preferences().saveChanges(this.getDom('saveUserPreferences')); }, 'doCancelUserPreferences': function() { this.renderPreferences(); }, // 'switchLanguage': function(anEvent) { // Clipperz.PM.Strings.Languages.setSelectedLanguage(anEvent.src().value); // }, //------------------------------------------------------------------------- 'renderLoginHistory': function() { var element; //MochiKit.Logging.logDebug(">>> AccountPanel.renderLoginHistory"); element = YAHOO.ext.Element.get('loginHistoryAccountBlock'); if (Clipperz.PM.Proxy.defaultProxy.isReadOnly()) { element.update(""); this.domHelper().append(element, {tag:'div', cls:'loginHistoryReadOnlyMessage', htmlString:Clipperz.PM.Strings['loginHistoryReadOnlyMessage']}); } else { var deferredResult; deferredResult = new MochiKit.Async.Deferred(); deferredResult.addCallback(MochiKit.Base.bind(function(anElement) { anElement.update(""); Clipperz.YUI.DomHelper.append(anElement, {tag:'div', cls:'loadingMessage', htmlString:Clipperz.PM.Strings['loginHistoryLoadingMessage']}); }, this), element); deferredResult.addCallback(MochiKit.Base.method(this.user(), 'loadLoginHistory')); deferredResult.addCallback(MochiKit.Base.bind(function(anElement, aResult) { var loginListItems; var tBodyElement; var imageExtension; var now; var i, c; loginListItems = aResult; //MochiKit.Logging.logDebug("=== loginListItems: " + Clipperz.Base.serializeJSON(loginListItems)); imageExtension = (Clipperz_IEisBroken == true) ? 'gif': 'png'; now = new Date(); anElement.update(""); Clipperz.YUI.DomHelper.append(anElement, {tag:'div', cls:'panelDescription', htmlString:Clipperz.PM.Strings['loginHistoryLoadedMessage']}); Clipperz.YUI.DomHelper.append(anElement, {tag:'table', id:'loginHistoryTable', cellspacing:'0', cellpadding:'2', border:'0', children:[ {tag:'tbody', id:this.getId('loginHistoryTBody'), children:[]} ]}); //# Clipperz.YUI.DomHelper.append(anElement, {tag:'div', id:'loginHistoryFooter', children:[ Clipperz.YUI.DomHelper.append(anElement, {tag:'div', cls:'clipperzSubPanelButtonBox', children:[ {tag:'div', id:this.getId('reloadHistoryButton')} ]}); new YAHOO.ext.Button(this.getDom('reloadHistoryButton'), {text:Clipperz.PM.Strings['loginHistoryReloadButtonLabel'], handler:this.reloadHistory, scope:this}); tBodyElement = this.getElement('loginHistoryTBody'); c = loginListItems.length; for (i=0; i