diff --git a/static/js/pandora.js b/static/js/pandora.js index 91ebdbeaa..17962bddc 100644 --- a/static/js/pandora.js +++ b/static/js/pandora.js @@ -63,8 +63,14 @@ Ox.load({ body: $('body'), document: $(document), window: $(window) - .resize(resizeWindow) - .unload(unloadWindow) + .bind({ + resize: function() { + pandora.resizeWindow(); + }, + unload: function() { + pandora.unloadWindow(); + } + }) }, site: data.site, user: data.user.level == 'guest' ? Ox.clone(data.site.user) : data.user @@ -168,75 +174,4 @@ Ox.load({ }); } - function resizeWindow() { - pandora.resizeFolders(); - pandora.$ui.leftPanel.size(2, pandora.getInfoHeight()); - pandora.$ui.info.resizeInfo(); - if (!pandora.user.ui.item) { - pandora.resizeGroups(pandora.$ui.rightPanel.width()); - if (pandora.user.ui.listView == 'clips') { - var clipsItems = pandora.getClipsItems(); - previousClipsItems = pandora.getClipsItems(pandora.$ui.list.options('width')); - pandora.$ui.list.options({ - width: window.innerWidth - - pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1 - - Ox.UI.SCROLLBAR_SIZE - }); - if (clipsItems != previousClipsItems) { - Ox.Request.clearCache(); // fixme - pandora.$ui.list.reloadList(true); - } - } else if (pandora.user.ui.listView == 'timelines') { - pandora.$ui.list.options({ - width: window.innerWidth - - pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1 - - Ox.UI.SCROLLBAR_SIZE - }); - } else if (pandora.user.ui.listView == 'map') { - pandora.$ui.map.resizeMap(); - } else if (pandora.user.ui.listView == 'calendar') { - pandora.$ui.calendar.resizeCalendar(); - } else { - pandora.$ui.list.size(); - } - } else { - //Ox.print('pandora.$ui.window.resize'); - pandora.$ui.browser.scrollToSelection(); - if (pandora.user.ui.itemView == 'info') { - pandora.$ui.info.resize(); - } else if (pandora.user.ui.itemView == 'clips') { - pandora.$ui.clips.size(); - } else if (pandora.user.ui.itemView == 'video') { - pandora.$ui.player.options({ - // fixme: duplicated - height: pandora.$ui.contentPanel.size(1), - width: pandora.$ui.document.width() - pandora.$ui.mainPanel.size(0) - 1 - }); - } else if (pandora.user.ui.itemView == 'timeline') { - pandora.$ui.editor.options({ - // fixme: duplicated - height: pandora.$ui.contentPanel.size(1), - width: pandora.$ui.document.width() - pandora.$ui.mainPanel.size(0) - 1 - }); - } else if (pandora.user.ui.itemView == 'map') { - pandora.$ui.map.resizeMap(); - } else if (pandora.user.ui.itemView == 'calendar') { - pandora.$ui.calendar.resizeCalendar(); - } - } - } - - function unloadWindow() { - // fixme: ajax request has to have async set to false for this to work - pandora.user.ui.section == 'items' - && pandora.user.ui.item - && ['video', 'timeline'].indexOf(pandora.user.ui.itemView) > -1 - && pandora.UI.set( - 'videoPosition.' + pandora.user.ui.item, - pandora.$ui[ - pandora.user.ui.itemView == 'video' ? 'player' : 'editor' - ].options('position') - ); - } - }); diff --git a/static/js/pandora/UI.js b/static/js/pandora/UI.js index 2ac8afd1a..c176c4523 100644 --- a/static/js/pandora/UI.js +++ b/static/js/pandora/UI.js @@ -14,6 +14,13 @@ pandora.UI = (function() { return !key ? self.previousUI : self.previousUI[key]; }; + that.reset = function() { + pandora.user.ui = pandora.site.user.ui; + pandora.user.ui._list = pandora.getListsState(pandora.user.ui.find); + pandora.user.ui._groupsState = pandora.getGroupsState(pandora.user.ui.find); + pandora.user.ui._findState = pandora.getFindState(pandora.user.ui.find); + }; + // sets pandora.user.ui.key to val // key foo.bar.baz sets pandora.user.ui.foo.bar.baz // val null removes a key diff --git a/static/js/pandora/autovalidate.js b/static/js/pandora/autovalidate.js index 2a8ec29dc..3d0dd3f02 100644 --- a/static/js/pandora/autovalidate.js +++ b/static/js/pandora/autovalidate.js @@ -1,51 +1,69 @@ // vim: et:ts=4:sw=4:sts=4:ft=javascript + pandora.autovalidateCode = function(value, blur, callback) { - value = value.toUpperCase().split('').map(function(v) { - return /[0-9A-Z]/.test(v) ? v : null; - }).join(''); - callback(value); + value = value.split('').map(function(v) { + return /[A-Z]/.test(v) ? v : null; + }).join('').substr(0, 16); + callback({valid: value.length == 16, value: value}); }; pandora.autovalidateEmail = function(value, blur, callback) { value = value.toLowerCase().split('').map(function(v, i) { return /[0-9a-z\.\+\-_@]/.test(v) ? v : null; - }).join(''); - callback(value); + }).join('').substr(0, 255); + callback({valid: Ox.isValidEmail(value), value: value}); }; pandora.autovalidateListname = function(value, blur, callback) { + // A valid listname consists of 1 to 255 unicode characters, + // without leading, trailing or consecutive spaces var length = value.length; - value = value.split('').map(function(v, i) { - if (new RegExp('[0-9' + Ox.regexp.letters + '\\(\\)' + ((i == 0 || (i == length - 1 && blur)) ? '' : ' \-') + ']', 'i').test(v)) { - return v; - } else { - return null; - } + value = value.toLowerCase().split('').map(function(v, i) { + return /\s/.test(v) && (i == 0 || (i == length - 1 && blur)) ? null : v; }).join(''); - [' ', ' -', '- ', '--', '\\(\\(', '\\)\\(', '\\)\\)'].forEach(function(v) { - //Ox.print(v, v[0], v[0] == '\\') - while (value.indexOf(v) > -1) { - value = value.replace(new RegExp(v, 'g'), v[0] + (v[0] == '\\' ? v[1] : '')); - } - }); - callback(value); + value = value.replace(/\s+/g, ' ').substr(0, 255); + callback({valid: !!value.length, value: value}); }; pandora.autovalidateUsername = function(value, blur, callback) { + // A valid username consists of 1 to 255 unicode characters, + // without leading, trailing or consecutive spaces var length = value.length; value = value.toLowerCase().split('').map(function(v, i) { - if (new RegExp('[0-9a-z' + ((i == 0 || (i == length - 1 && blur)) ? '' : '\-_') + ']').test(v)) { - return v; - } else { - return null; - } + return /\s/.test(v) && (i == 0 || (i == length - 1 && blur)) ? null : v; }).join(''); - ['--', '-_', '_-', '__'].forEach(function(v) { - while (value.indexOf(v) > -1) { - value = value.replace(new RegExp(v, 'g'), v[0]); - } + value = value.replace(/\s+/g, ' ').substr(0, 255); + callback({valid: !!value.length, value: value}); +}; + +pandora.validateNewEmail = function(value, callback) { + value == pandora.user.email ? callback({ + message: '', + valid: true, + value: value + }) : Ox.isValidEmail(value) ? pandora.api.findUser({ + key: 'email', + value: value, + operator: '==' + }, function(result) { + callback({ + message: 'E-mail address already exists', + valid: !result.data.users.length, + value: value + }); + }) : callback({ + message: (!value.length ? 'Missing' : 'Invalid') + ' e-mail address', + valid: false, + value: value + }); +}; + +pandora.validateNewPassword = function(value, callback) { + callback({ + message: 'Missing password', + valid: value.length > 0, + value: value }); - callback(value); }; pandora.validateUser = function(key, existing) { @@ -56,7 +74,7 @@ pandora.validateUser = function(key, existing) { valid ? pandora.api.findUser({ key: key, value: value, - operator: '=' + operator: '==' }, function(result) { var valid = existing == !!result.data.users.length; //Ox.print(existing, result.data.users) diff --git a/static/js/pandora/ui/account.js b/static/js/pandora/ui/account.js index ac403e801..bd7b4d0ee 100644 --- a/static/js/pandora/ui/account.js +++ b/static/js/pandora/ui/account.js @@ -215,12 +215,7 @@ pandora.ui.accountForm = function(action, value) { label: 'New Password', labelWidth: 120, type: 'password', - validate: function(value, callback) { - callback({ - message: 'Missing password', - valid: value.length > 0 - }); - }, + validate: pandora.validateNewPassword, width: 320 }); } else if (type == 'newUsername') { @@ -282,10 +277,12 @@ pandora.ui.accountForm = function(action, value) { change: function(data) { var selected = data.selected[0].id; pandora.$ui.usernameOrEmailInput.options({ - autovalidate: selected == 'username' ? pandora.autovalidateUsername : autovalidateEmail, - validate: validateUser(selected, true), + autovalidate: selected == 'username' + ? pandora.autovalidateUsername : pandora.autovalidateEmail, + validate: pandora.validateUser(selected, true), value: '' }).focus(); + pandora.$ui.accountDialog.disableButton('submitReset'); } }), pandora.$ui.usernameOrEmailInput = Ox.Input({ diff --git a/static/js/pandora/ui/preferencesDialog.js b/static/js/pandora/ui/preferencesDialog.js index 2b2e76a8b..23dfcffba 100644 --- a/static/js/pandora/ui/preferencesDialog.js +++ b/static/js/pandora/ui/preferencesDialog.js @@ -26,24 +26,66 @@ pandora.ui.preferencesDialog = function() { width: 320 }), Ox.Input({ - id: 'password', - label: 'New Passowrd', - labelWidth: 120, - type: 'password', - width: 320 - }), + autovalidate: /.+/, + id: 'password', + label: 'New Password', + labelWidth: 120, + type: 'password', + validate: pandora.validateNewPassword, + width: 320 + }) + .bindEvent({ + validate: function(data) { + data.valid && pandora.api.editPreferences({password: data.value}); + } + }), Ox.Input({ - id: 'email', - label: 'E-Mail Address', - labelWidth: 120, - value: pandora.user.email, - width: 320 - }) + autovalidate: pandora.autovalidateEmail, + id: 'email', + label: 'E-Mail Address', + labelWidth: 120, + validate: pandora.validateNewEmail, + value: pandora.user.email, + width: 320 + }) + .bindEvent({ + validate: function(data) { + if (data.valid && data.value != pandora.user.email) { + pandora.user.email = data.value; + pandora.api.editPreferences({email: data.value}); + } + } + }) ] }) .css({position: 'absolute', left: '96px', top: '16px'}) + .bindEvent({ + change: function(data) { + return; + var preferences = {}; + preferences[data.id] = data.data.value; + pandora.api.editPreferences(preferences, function(result) { + if (data.id == 'email') { + pandora.user.email = data.data.value; + } + }); + } + }) ); } else { + $content.append( + Ox.Button({ + title: 'Reset UI Settings', + width: 150 + }) + .bindEvent({ + click: function() { + pandora.UI.reset(); + pandora.$ui.appPanel.reload(); + } + }) + .css({position: 'absolute', left: '96px', top: '16px'}) + ); /* content.append(Ox.FormElementGroup({ elements: [ diff --git a/static/js/pandora/utils.js b/static/js/pandora/utils.js index 8bc7248af..779ab7bab 100644 --- a/static/js/pandora/utils.js +++ b/static/js/pandora/utils.js @@ -674,7 +674,8 @@ pandora.signin = function(data) { pandora.user.ui._groupsState = pandora.getGroupsState(pandora.user.ui.find); pandora.user.ui._findState = pandora.getFindState(pandora.user.ui.find); Ox.Theme(pandora.user.ui.theme); - pandora.UI.set({find: pandora.user.ui.find}) + pandora.UI.set({find: pandora.user.ui.find}); + Ox.Request.clearCache(); pandora.$ui.appPanel.reload(); }; @@ -684,7 +685,8 @@ pandora.signout = function(data) { pandora.user.ui._groupsState = pandora.getGroupsState(pandora.user.ui.find); pandora.user.ui._findState = pandora.getFindState(pandora.user.ui.find); Ox.Theme(pandora.site.user.ui.theme); - pandora.UI.set({find: pandora.user.ui.find}) + pandora.UI.set({find: pandora.user.ui.find}); + Ox.Request.clearCache(); pandora.$ui.appPanel.reload(); }; @@ -755,6 +757,64 @@ pandora.resizeFolders = function() { }); }; +pandora.resizeWindow = function() { + pandora.resizeFolders(); + pandora.$ui.leftPanel.size(2, pandora.getInfoHeight()); + pandora.$ui.info.resizeInfo(); + if (!pandora.user.ui.item) { + pandora.resizeGroups(pandora.$ui.rightPanel.width()); + if (pandora.user.ui.listView == 'clips') { + var clipsItems = pandora.getClipsItems(); + previousClipsItems = pandora.getClipsItems(pandora.$ui.list.options('width')); + pandora.$ui.list.options({ + width: window.innerWidth + - pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1 + - Ox.UI.SCROLLBAR_SIZE + }); + if (clipsItems != previousClipsItems) { + Ox.Request.clearCache(); // fixme + pandora.$ui.list.reloadList(true); + } + } else if (pandora.user.ui.listView == 'timelines') { + pandora.$ui.list.options({ + width: window.innerWidth + - pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1 + - Ox.UI.SCROLLBAR_SIZE + }); + } else if (pandora.user.ui.listView == 'map') { + pandora.$ui.map.resizeMap(); + } else if (pandora.user.ui.listView == 'calendar') { + pandora.$ui.calendar.resizeCalendar(); + } else { + pandora.$ui.list.size(); + } + } else { + //Ox.print('pandora.$ui.window.resize'); + pandora.$ui.browser.scrollToSelection(); + if (pandora.user.ui.itemView == 'info') { + pandora.$ui.info.resize(); + } else if (pandora.user.ui.itemView == 'clips') { + pandora.$ui.clips.size(); + } else if (pandora.user.ui.itemView == 'video') { + pandora.$ui.player.options({ + // fixme: duplicated + height: pandora.$ui.contentPanel.size(1), + width: pandora.$ui.document.width() - pandora.$ui.mainPanel.size(0) - 1 + }); + } else if (pandora.user.ui.itemView == 'timeline') { + pandora.$ui.editor.options({ + // fixme: duplicated + height: pandora.$ui.contentPanel.size(1), + width: pandora.$ui.document.width() - pandora.$ui.mainPanel.size(0) - 1 + }); + } else if (pandora.user.ui.itemView == 'map') { + pandora.$ui.map.resizeMap(); + } else if (pandora.user.ui.itemView == 'calendar') { + pandora.$ui.calendar.resizeCalendar(); + } + } +}; + pandora.selectList = function() { if (pandora.user.ui._list) { pandora.api.findLists({ @@ -779,6 +839,19 @@ pandora.selectList = function() { } }; +pandora.unloadWindow = function() { + // fixme: ajax request has to have async set to false for this to work + pandora.user.ui.section == 'items' + && pandora.user.ui.item + && ['video', 'timeline'].indexOf(pandora.user.ui.itemView) > -1 + && pandora.UI.set( + 'videoPosition.' + pandora.user.ui.item, + pandora.$ui[ + pandora.user.ui.itemView == 'video' ? 'player' : 'editor' + ].options('position') + ); +}; + (function() { // Note: getFindState has to run after getListsState and getGroupsState