From c30b4df849b6b12e25c5d329406edd2dfe0ca42e Mon Sep 17 00:00:00 2001 From: Shane Tomlinson <set117@yahoo.com> Date: Sun, 13 Nov 2011 14:53:58 +0000 Subject: [PATCH] A large merge to unify code, flatten structure, and reduce the impact of JavascriptMVC. * Add new directory `shared` which is code shared between dialog and pages. * Add a renderer and template loader that is shared to unify rendering of templates. * Remove JavascriptMVC's Views and use EJS directly. * Add a script to create our own bundled javascript object with all templates. * Use EJS templates for both error messages and tooltips * Simplify unit test dependency chain by doing nearly all dependencies in qunit.js. * Update compression script for new files/structure. --- .../static/communication_iframe/iframe.js | 20 ++-- resources/static/css/style.css | 6 +- .../controllers/authenticate_controller.js | 2 +- .../checkregistration_controller.js | 6 +- .../dialog/controllers/dialog_controller.js | 6 +- .../dialog/controllers/page_controller.js | 49 ++-------- .../controllers/pickemail_controller.js | 2 +- resources/static/dialog/dialog.js | 46 +++++---- resources/static/dialog/views/error.ejs | 12 ++- .../static/dialog/views/testBodyTemplate.ejs | 2 +- resources/static/dialog/views/tooltip.ejs | 4 + resources/static/lib/dom-jquery.js | 14 ++- resources/static/lib/module.js | 96 +++++++++++++++++++ resources/static/pages/page_helpers.js | 8 +- resources/static/resources/error-display.js | 30 ------ .../{resources => shared}/browser-support.js | 0 .../browserid-extensions.js | 0 .../static/{resources => shared}/browserid.js | 0 resources/static/shared/error-display.js | 33 +++++++ .../{resources => shared}/error-messages.js | 0 .../static/{resources => shared}/network.js | 0 resources/static/shared/renderer.js | 78 +++++++++++++++ resources/static/shared/screens.js | 40 ++++++++ .../static/{resources => shared}/storage.js | 0 resources/static/shared/templates.js | 2 + .../static/{resources => shared}/tooltip.js | 26 ++--- .../static/{resources => shared}/user.js | 0 .../{resources => shared}/validation.js | 0 .../{resources => shared}/wait-messages.js | 0 resources/static/test/qunit.html | 16 +--- .../authenticate_controller_unit_test.js | 2 +- .../dialog_controller_unit_test.js | 6 +- .../controllers/page_controller_unit_test.js | 17 ++-- .../static/test/qunit/mocks/templates.js | 4 + .../qunit/pages/add_email_address_test.js | 8 +- .../test/qunit/pages/browserid_unit_test.js | 2 +- .../test/qunit/pages/forgot_unit_test.js | 8 +- .../qunit/pages/manage_account_unit_test.js | 4 +- .../qunit/pages/page_helpers_unit_test.js | 2 +- .../test/qunit/pages/signin_unit_test.js | 4 +- .../test/qunit/pages/signup_unit_test.js | 4 +- .../qunit/pages/verify_email_address_test.js | 10 +- resources/static/test/qunit/qunit.js | 89 +++++++++-------- .../test/qunit/resources/channel_unit_test.js | 6 +- .../browser-support_unit_test.js | 4 +- .../error-display_unit_test.js | 21 ++-- .../network_unit_test.js | 4 +- .../test/qunit/shared/renderer_unit_test.js | 82 ++++++++++++++++ .../test/qunit/shared/screens_unit_test.js | 86 +++++++++++++++++ .../storage_unit_test.js | 4 +- .../tooltip_unit_test.js | 9 +- .../{resources => shared}/user_unit_test.js | 4 +- .../validation_unit_test.js | 4 +- resources/views/dialog_layout.ejs | 5 - resources/views/layout.ejs | 80 ++++------------ resources/views/relay.ejs | 2 +- scripts/compress.sh | 14 ++- scripts/create_templates.js | 24 +++++ 58 files changed, 696 insertions(+), 311 deletions(-) create mode 100644 resources/static/dialog/views/tooltip.ejs create mode 100644 resources/static/lib/module.js delete mode 100644 resources/static/resources/error-display.js rename resources/static/{resources => shared}/browser-support.js (100%) rename resources/static/{resources => shared}/browserid-extensions.js (100%) rename resources/static/{resources => shared}/browserid.js (100%) create mode 100644 resources/static/shared/error-display.js rename resources/static/{resources => shared}/error-messages.js (100%) rename resources/static/{resources => shared}/network.js (100%) create mode 100644 resources/static/shared/renderer.js create mode 100644 resources/static/shared/screens.js rename resources/static/{resources => shared}/storage.js (100%) create mode 100644 resources/static/shared/templates.js rename resources/static/{resources => shared}/tooltip.js (90%) rename resources/static/{resources => shared}/user.js (100%) rename resources/static/{resources => shared}/validation.js (100%) rename resources/static/{resources => shared}/wait-messages.js (100%) create mode 100644 resources/static/test/qunit/mocks/templates.js rename resources/static/test/qunit/{resources => shared}/browser-support_unit_test.js (97%) rename resources/static/test/qunit/{resources => shared}/error-display_unit_test.js (78%) rename resources/static/test/qunit/{resources => shared}/network_unit_test.js (99%) create mode 100644 resources/static/test/qunit/shared/renderer_unit_test.js create mode 100644 resources/static/test/qunit/shared/screens_unit_test.js rename resources/static/test/qunit/{resources => shared}/storage_unit_test.js (98%) rename resources/static/test/qunit/{resources => shared}/tooltip_unit_test.js (89%) rename resources/static/test/qunit/{resources => shared}/user_unit_test.js (99%) rename resources/static/test/qunit/{resources => shared}/validation_unit_test.js (98%) create mode 100755 scripts/create_templates.js diff --git a/resources/static/communication_iframe/iframe.js b/resources/static/communication_iframe/iframe.js index 57409c9f1..da4e50dfb 100644 --- a/resources/static/communication_iframe/iframe.js +++ b/resources/static/communication_iframe/iframe.js @@ -44,16 +44,16 @@ steal .then('../lib/jschannel', '../lib/base64', '../lib/underscore-min', - '../resources/channel', - '../resources/browserid', - '../resources/storage', - '../resources/tooltip', - '../resources/validation', - '../resources/browserid-extensions', - '../resources/network', - '../resources/user', - '../resources/error-messages', - '../resources/wait-messages', + '../dialog/resources/channel', + '../shared/browserid', + '../shared/storage', + '../shared/tooltip', + '../shared/validation', + '../shared/browserid-extensions', + '../shared/network', + '../shared/user', + '../shared/error-messages', + '../shared/wait-messages', afterResourceLoad); function afterResourceLoad() { diff --git a/resources/static/css/style.css b/resources/static/css/style.css index fc2e75568..c5101f1c5 100644 --- a/resources/static/css/style.css +++ b/resources/static/css/style.css @@ -116,6 +116,10 @@ hr { background-color: rgba(0,0,0,.6); } +#error { + display: none; +} + #error > div { background-color: #fff; position: absolute; @@ -128,7 +132,7 @@ hr { } #error ul, #error li { - list-style-type: none; + list-style-type: none; } #wait strong, #error strong { diff --git a/resources/static/dialog/controllers/authenticate_controller.js b/resources/static/dialog/controllers/authenticate_controller.js index b270a65d7..9fd77e4b6 100644 --- a/resources/static/dialog/controllers/authenticate_controller.js +++ b/resources/static/dialog/controllers/authenticate_controller.js @@ -186,7 +186,7 @@ options = options || {}; this._super(el, { - bodyTemplate: "authenticate.ejs", + bodyTemplate: "authenticate", bodyVars: { sitename: user.getHostname(), email: options.email || "" diff --git a/resources/static/dialog/controllers/checkregistration_controller.js b/resources/static/dialog/controllers/checkregistration_controller.js index 06558c8be..b19fa0be9 100644 --- a/resources/static/dialog/controllers/checkregistration_controller.js +++ b/resources/static/dialog/controllers/checkregistration_controller.js @@ -1,5 +1,5 @@ -/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ -/*global BrowserID: true, PageController: true */ +/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ +/*global BrowserID: true, PageController: true */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -43,7 +43,7 @@ init: function(el, options) { var me=this; me._super(el, { - waitTemplate: "confirmemail.ejs", + waitTemplate: "confirmemail", waitVars: { email: options.email } diff --git a/resources/static/dialog/controllers/dialog_controller.js b/resources/static/dialog/controllers/dialog_controller.js index e919c3b45..7e0af554a 100644 --- a/resources/static/dialog/controllers/dialog_controller.js +++ b/resources/static/dialog/controllers/dialog_controller.js @@ -75,7 +75,7 @@ win.setupChannel(self); self.stateMachine(); } catch (e) { - self.renderError("error.ejs", { + self.renderError("error", { action: errors.relaySetup }); } @@ -185,13 +185,13 @@ }, doOffline: function() { - this.renderError("offline.ejs", {}); + this.renderError("offline", {}); offline = true; }, doXHRError: function(info) { if (!offline) { - this.renderError("error.ejs", $.extend({ + this.renderError("error", $.extend({ action: errors.xhrError }, info)); } diff --git a/resources/static/dialog/controllers/page_controller.js b/resources/static/dialog/controllers/page_controller.js index 9ff9f3386..ed4a4fdaa 100644 --- a/resources/static/dialog/controllers/page_controller.js +++ b/resources/static/dialog/controllers/page_controller.js @@ -39,7 +39,8 @@ var ANIMATION_TIME = 250, bid = BrowserID, - dom = bid.DOM; + dom = bid.DOM, + screens = bid.Screens; $.Controller.extend("PageController", { @@ -70,16 +71,12 @@ // XXX move all of these, bleck. dom.bindEvent("form", "submit", me.onSubmit.bind(me)); - dom.bindEvent("#cancel", "click", me.onCancel.bind(me)); - dom.bindEvent("#back", "click", me.onBack.bind(me)); dom.bindEvent("#thisIsNotMe", "click", me.close.bind(me, "notme")); }, destroy: function() { dom.unbindEvent("form", "submit"); dom.unbindEvent("input", "keyup"); - dom.unbindEvent("#cancel", "click"); - dom.unbindEvent("#back", "click"); dom.unbindEvent("#thisIsNotMe", "click"); dom.removeClass("body", "waiting"); @@ -87,40 +84,24 @@ this._super(); }, - renderTemplates: function(target, body, body_vars) { - if (body) { - var bodyHtml = new EJS({url: "/dialog/views/" + body}).render(body_vars); - target = $(target + " .contents"); - target.html(bodyHtml).find("input").eq(0).focus(); - } - }, - renderDialog: function(body, body_vars) { - this.renderTemplates("#formWrap", body, body_vars); - dom.removeClass("body", "error"); - dom.removeClass("body", "waiting"); - dom.addClass("body", "form"); + screens.form(body, body_vars); $("#wait, #error").stop().fadeOut(ANIMATION_TIME); + dom.focus("input:visible:eq(0)"); }, renderWait: function(body, body_vars) { - this.renderTemplates("#wait", body, body_vars); - dom.removeClass("body", "error"); - dom.removeClass("body", "form"); - dom.addClass("body", "waiting"); + screens.wait(body, body_vars); $("body").css('opacity', 1); $("#wait").stop().hide().fadeIn(ANIMATION_TIME); }, renderError: function(body, body_vars) { - this.renderTemplates("#error", body, body_vars); - dom.removeClass("body", "waiting"); - dom.removeClass("body", "form"); - dom.addClass("body", "error"); + screens.error(body, body_vars); $("#error").stop().css('opacity', 1).hide().fadeIn(ANIMATION_TIME); /** - * What a big steaming pile, use CSS animations for this! + * TODO What a big steaming pile, use CSS animations for this! */ dom.bindEvent("#openMoreInfo", "click", function(event) { event.preventDefault(); @@ -149,7 +130,7 @@ }, doWait: function(info) { - this.renderWait("wait.ejs", info); + this.renderWait("wait", info); dom.addClass("body", "waiting"); }, @@ -170,22 +151,10 @@ getErrorDialog: function(action) { var self=this; return function(lowLevelInfo) { - self.renderError("error.ejs", $.extend({ + self.renderError("error", $.extend({ action: action }, lowLevelInfo)); } - }, - - onCancel: function(event) { - event.preventDefault(); - event.stopPropagation(); - this.close("cancel"); - }, - - onBack: function(event) { - event.preventDefault(); - event.stopPropagation(); - this.close("start"); } }); diff --git a/resources/static/dialog/controllers/pickemail_controller.js b/resources/static/dialog/controllers/pickemail_controller.js index e3cb978f9..01cea06fa 100644 --- a/resources/static/dialog/controllers/pickemail_controller.js +++ b/resources/static/dialog/controllers/pickemail_controller.js @@ -181,7 +181,7 @@ init: function(el, options) { var origin = user.getOrigin(); this._super(el, { - bodyTemplate: "pickemail.ejs", + bodyTemplate: "pickemail", bodyVars: { identities: user.getStoredEmailKeypairs(), // XXX ideal is to get rid of this and have a User function diff --git a/resources/static/dialog/dialog.js b/resources/static/dialog/dialog.js index 1270aee6f..319fa4cca 100644 --- a/resources/static/dialog/dialog.js +++ b/resources/static/dialog/dialog.js @@ -39,14 +39,7 @@ window.console = window.console || { log: function() {} }; -steal( - '../lib/jschannel', - '../lib/base64', - '../lib/underscore-min', - '../lib/ejs', - '../resources/browserid', - '../lib/jquery-1.6.2.min.js', - '../lib/dom-jquery') +steal .plugins( 'jquery/controller', // a widget factory 'jquery/controller/subscribe') // subscribe to OpenAjax.hub @@ -54,15 +47,26 @@ steal( .resources( 'channel') .then( - '../resources/storage', - '../resources/tooltip', - '../resources/validation', - '../resources/browser-support', - '../resources/browserid-extensions', - '../resources/network', - '../resources/user', - '../resources/error-messages', - '../resources/wait-messages') // 3rd party script's (like jQueryUI), in resources folder + '../lib/jschannel', + '../lib/base64', + '../lib/underscore-min', + '../lib/ejs', + '../shared/browserid', + '../lib/dom-jquery', + + '../shared/storage', + '../shared/templates', + '../shared/renderer', + '../shared/error-display', + '../shared/screens', + '../shared/tooltip', + '../shared/validation', + '../shared/browser-support', + '../shared/browserid-extensions', + '../shared/network', + '../shared/user', + '../shared/error-messages', + '../shared/wait-messages') .controllers('page', 'dialog', @@ -71,7 +75,7 @@ steal( 'pickemail') // loads files in controllers folder .then(function() { - $(function() { - $('body').dialog().show(); - }); - }); // adds views to be added to build + $(function() { + $('body').dialog().show(); + }); + }); // adds views to be added to build diff --git a/resources/static/dialog/views/error.ejs b/resources/static/dialog/views/error.ejs index 537d2471f..6c5e9bcbd 100644 --- a/resources/static/dialog/views/error.ejs +++ b/resources/static/dialog/views/error.ejs @@ -2,7 +2,11 @@ <h2>We are very sorry, there has been an error!</h2> <p> + <% if (typeof dialog !== "undefined" && dialog !== false) { %> + To retry, you will have to reload the page and try again. More info can be found by opening the expanded info below. + <% } else { %> To retry, you will have to close BrowserID and try again. More info can be found by opening the expanded info below. + <% } %> </p> <a href="#" id="openMoreInfo">See more info</a> @@ -15,7 +19,7 @@ <% if (action.message) { %> <p> <%= action.message %> - </p> + </p> <% } %> </li> <% } %> @@ -26,13 +30,13 @@ <strong id="network">Network Info:</strong> <%= network.type %>: <%= network.url %> <p> - <strong>Response Code - </strong> <%= network.textStatus %> + <strong>Response Code - </strong> <%= network.textStatus %> </p> <% if (network.errorThrown) { %> <p> - <strong>Error Type:</strong> <%= network.errorThrown %> - </p> + <strong>Error Type:</strong> <%= network.errorThrown %> + </p> <% } %> </li> diff --git a/resources/static/dialog/views/testBodyTemplate.ejs b/resources/static/dialog/views/testBodyTemplate.ejs index 77a06e46b..cb93998d2 100644 --- a/resources/static/dialog/views/testBodyTemplate.ejs +++ b/resources/static/dialog/views/testBodyTemplate.ejs @@ -1,2 +1,2 @@ -<input type="text" value="" /> +<input id="templateInput" type="text" value="" /> diff --git a/resources/static/dialog/views/tooltip.ejs b/resources/static/dialog/views/tooltip.ejs new file mode 100644 index 000000000..191af143e --- /dev/null +++ b/resources/static/dialog/views/tooltip.ejs @@ -0,0 +1,4 @@ +<div class="tooltip"> + <%= contents %> +</div> + diff --git a/resources/static/lib/dom-jquery.js b/resources/static/lib/dom-jquery.js index 25d2a691f..889d165bf 100644 --- a/resources/static/lib/dom-jquery.js +++ b/resources/static/lib/dom-jquery.js @@ -137,7 +137,6 @@ BrowserID.DOM = ( function() { else { target.html( value ); } - }, /** @@ -256,7 +255,9 @@ BrowserID.DOM = ( function() { * @param {selector || element} elementToAppendTo */ appendTo: function( elementToInsert, elementToAppendTo ) { - jQuery( elementToInsert ).appendTo( jQuery( elementToAppendTo ) ); + var el = jQuery(elementToInsert ); + el.appendTo( jQuery( elementToAppendTo ) ); + return el; }, /** @@ -286,6 +287,15 @@ BrowserID.DOM = ( function() { elementToInsert.insertBefore( insertBefore ); } + }, + + /** + * Focus an element + * @method focus + * @param {selelector || element} elementToFocus + */ + focus: function( elementToFocus ) { + jQuery( elementToFocus ).focus(); } diff --git a/resources/static/lib/module.js b/resources/static/lib/module.js new file mode 100644 index 000000000..e9b06f406 --- /dev/null +++ b/resources/static/lib/module.js @@ -0,0 +1,96 @@ +/** +* Author Shane Tomlinson +* Original source can be found at: +* https://github.com/stomlinson/appcore/blob/master/js/module.js +* Licences under Mozilla Tri-License +*/ +BrowserID.module = (function() { + "use strict"; + + var registration = {}, + created = {}, + running = {}; + + function register(service, module, config) { + if (!module) { + throw "module constructor missing for " + service; + } + + registration[service] = { + constructor: module, + config: config + }; + } + + function getRegistration(service) { + return registration[service]; + } + + function getModule(service) { + return registration[service].constructor; + } + + function reset() { + registration = {}; + running = {}; + created = {}; + } + + function start(service, data) { + if (running[service]) { + throw "module already running for " + service; + } + + var module = created[service]; + + if (!module) { + var registration = getRegistration(service); + if (registration) { + var constr = registration.constructor, + config = registration.config; + + module = new constr(); + created[service] = module; + module.init(config); + } + else { + throw "module not registered for " + service; + } + } + + module.start(data); + running[service] = module; + + return module; + } + + function stop(service) { + var module = running[service]; + + if (module) { + module.stop(); + delete running[service]; + } + else { + throw "module not started for " + service; + } + } + + function stopAll() { + for(var key in running) { + var module = running[key]; + module.stop(); + delete running[key]; + } + } + + + return { + register: register, + getModule: getModule, + reset: reset, + start: start, + stop: stop, + stopAll: stopAll + }; +}()); diff --git a/resources/static/pages/page_helpers.js b/resources/static/pages/page_helpers.js index f53a0844a..11e8546b3 100644 --- a/resources/static/pages/page_helpers.js +++ b/resources/static/pages/page_helpers.js @@ -52,7 +52,7 @@ BrowserID.PageHelpers = (function() { } function prefillEmail() { - // If the user tried to sign in on the sign up page with an existing email, + // If the user tried to sign in on the sign up page with an existing email, // place that email in the email field, then focus the password. var el = $("#email"), email = locStorage.signInEmail; @@ -64,7 +64,7 @@ BrowserID.PageHelpers = (function() { el.keyup(onEmailKeyUp); } - + function clearStoredEmail() { locStorage.removeItem("signInEmail"); } @@ -86,8 +86,8 @@ BrowserID.PageHelpers = (function() { function getFailure(error) { return function onFailure(info) { - info = $.extend(info, { action: error }); - errorDisplay.render("#error", "#templateError", info); + info = $.extend(info, { action: error, dialog: false }); + bid.Screens.error("error", info); $("#errorBackground").fadeIn(); $("#error").fadeIn(); } diff --git a/resources/static/resources/error-display.js b/resources/static/resources/error-display.js deleted file mode 100644 index c70452133..000000000 --- a/resources/static/resources/error-display.js +++ /dev/null @@ -1,30 +0,0 @@ -BrowserID.ErrorDisplay = (function() { - "use strict"; - - function render(target, template, data) { - template = $(template).html(); - _.templateSettings = { - interpolate : /\{\{(.+?)\}\}/g, - evaluate : /\{\%(.+?)\%\}/g - }; - var display = $(_.template(template, data)).appendTo(target); - - /** - * What a big steaming pile, use CSS animations for this! - */ - display.find("#openMoreInfo").click(function(event) { - event.preventDefault(); - - display.find("#moreInfo").slideDown(); - display.find("#openMoreInfo").css({visibility: "hidden"}); - }); - - return display; - } - - return { - render: render - }; - -}()); - diff --git a/resources/static/resources/browser-support.js b/resources/static/shared/browser-support.js similarity index 100% rename from resources/static/resources/browser-support.js rename to resources/static/shared/browser-support.js diff --git a/resources/static/resources/browserid-extensions.js b/resources/static/shared/browserid-extensions.js similarity index 100% rename from resources/static/resources/browserid-extensions.js rename to resources/static/shared/browserid-extensions.js diff --git a/resources/static/resources/browserid.js b/resources/static/shared/browserid.js similarity index 100% rename from resources/static/resources/browserid.js rename to resources/static/shared/browserid.js diff --git a/resources/static/shared/error-display.js b/resources/static/shared/error-display.js new file mode 100644 index 000000000..c26c830ec --- /dev/null +++ b/resources/static/shared/error-display.js @@ -0,0 +1,33 @@ +BrowserID.ErrorDisplay = (function() { + "use strict"; + + var bid = BrowserID, + dom = bid.DOM; + + function open(event) { + event && event.preventDefault(); + + /** + * XXX What a big steaming pile, use CSS animations for this! + */ + $("#moreInfo").slideDown(); + $("#openMoreInfo").css({visibility: "hidden"}); + } + + function init(target) { + dom.bindEvent("#openMoreInfo", "click", open); + return dom.getElements(target); + } + + function stop() { + dom.unbindEvent("#openMoreInfo", "click", open); + } + + return { + start: init, + stop: stop, + open: open + }; + +}()); + diff --git a/resources/static/resources/error-messages.js b/resources/static/shared/error-messages.js similarity index 100% rename from resources/static/resources/error-messages.js rename to resources/static/shared/error-messages.js diff --git a/resources/static/resources/network.js b/resources/static/shared/network.js similarity index 100% rename from resources/static/resources/network.js rename to resources/static/shared/network.js diff --git a/resources/static/shared/renderer.js b/resources/static/shared/renderer.js new file mode 100644 index 000000000..60785aeed --- /dev/null +++ b/resources/static/shared/renderer.js @@ -0,0 +1,78 @@ +/*jshint browsers:true, forin: true, laxbreak: true */ +/*global BrowserID: true, _: true */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla BrowserID. + * + * The Initial Developer of the Original Code is Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +BrowserID.Renderer = (function() { + "use strict"; + + var bid = BrowserID, + dom = bid.DOM; + + function getTemplateHTML(body, vars) { + var config, + templateText = bid.Templates[body]; + + if(templateText) { + config = { + text: templateText + }; + } + else { + // TODO - be able to set the directory + config = { + url: "/dialog/views/" + body + ".ejs" + }; + } + + var html = new EJS(config).render(vars); + return html; + } + + function render(target, body, vars) { + var html = getTemplateHTML(body, vars); + return dom.setInner(target, html); + } + + function append(target, body, vars) { + var html = getTemplateHTML(body, vars); + return dom.appendTo(html, target); + } + + return { + render: render, + append: append + } +}()); + diff --git a/resources/static/shared/screens.js b/resources/static/shared/screens.js new file mode 100644 index 000000000..97338199f --- /dev/null +++ b/resources/static/shared/screens.js @@ -0,0 +1,40 @@ +BrowserID.Screens = (function() { + "use strict"; + + var bid = BrowserID, + dom = BrowserID.DOM, + renderer = bid.Renderer; + + function render(target, body, vars) { + renderer.render(target + " .contents", body, vars); + } + + function form(template, vars) { + render("#formWrap", template, vars); + dom.removeClass("body", "error"); + dom.removeClass("body", "waiting"); + dom.addClass("body", "form"); + } + + function wait(template, vars) { + render("#wait", template, vars); + dom.removeClass("body", "error"); + dom.removeClass("body", "form"); + dom.addClass("body", "waiting"); + } + + function error(template, vars) { + render("#error", template, vars); + dom.removeClass("body", "waiting"); + dom.removeClass("body", "form"); + dom.addClass("body", "error"); + + bid.ErrorDisplay.start("#error"); + } + + return { + form: form, + wait: wait, + error: error + }; +}()); diff --git a/resources/static/resources/storage.js b/resources/static/shared/storage.js similarity index 100% rename from resources/static/resources/storage.js rename to resources/static/shared/storage.js diff --git a/resources/static/shared/templates.js b/resources/static/shared/templates.js new file mode 100644 index 000000000..58a7358fe --- /dev/null +++ b/resources/static/shared/templates.js @@ -0,0 +1,2 @@ +BrowserID.Templates = {}; + diff --git a/resources/static/resources/tooltip.js b/resources/static/shared/tooltip.js similarity index 90% rename from resources/static/resources/tooltip.js rename to resources/static/shared/tooltip.js index 602602b4a..8800b6cea 100644 --- a/resources/static/resources/tooltip.js +++ b/resources/static/shared/tooltip.js @@ -1,4 +1,4 @@ -/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ +/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ /*globals BrowserID: true, _:true */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 @@ -40,17 +40,17 @@ BrowserID.Tooltip = (function() { var ANIMATION_TIME = 250, TOOLTIP_DISPLAY = 2000, - READ_WPM = 200; + READ_WPM = 200, + bid = BrowserID, + dom = bid.DOM, + renderer = bid.Renderer; function createTooltip(el) { var contents = el.html(); - var template = $("#templateTooltip").html(); - _.templateSettings = { - interpolate : /\{\{(.+?)\}\}/g - }; - var tooltip = $(_.template(template, { + + var tooltip = renderer.append("body", "tooltip", { contents: contents - })); + }); return tooltip; } @@ -79,11 +79,11 @@ BrowserID.Tooltip = (function() { } function createAndShowRelatedTooltip(el, relatedTo, complete) { - // This means create a copy of the tooltip element and position it in - // relation to an element. Right now we are putting the tooltip directly - // above the element. Once the tooltip is no longer needed, remove it + // This means create a copy of the tooltip element and position it in + // relation to an element. Right now we are putting the tooltip directly + // above the element. Once the tooltip is no longer needed, remove it // from the DOM. - var tooltip = createTooltip(el).appendTo("body"); + var tooltip = createTooltip(el); var target = $("#" + relatedTo); positionTooltip(tooltip, target); @@ -101,7 +101,7 @@ BrowserID.Tooltip = (function() { el = $(el); var messageFor = el.attr("for"); - // First, see if we are "for" another element, if we are, create a copy of + // First, see if we are "for" another element, if we are, create a copy of // the tooltip to attach to the element. if(messageFor) { createAndShowRelatedTooltip(el, messageFor, complete); diff --git a/resources/static/resources/user.js b/resources/static/shared/user.js similarity index 100% rename from resources/static/resources/user.js rename to resources/static/shared/user.js diff --git a/resources/static/resources/validation.js b/resources/static/shared/validation.js similarity index 100% rename from resources/static/resources/validation.js rename to resources/static/shared/validation.js diff --git a/resources/static/resources/wait-messages.js b/resources/static/shared/wait-messages.js similarity index 100% rename from resources/static/resources/wait-messages.js rename to resources/static/shared/wait-messages.js diff --git a/resources/static/test/qunit.html b/resources/static/test/qunit.html index 3e2ae0292..05fcf8726 100644 --- a/resources/static/test/qunit.html +++ b/resources/static/test/qunit.html @@ -58,23 +58,13 @@ </div> <ul class="notifications"> - <li class="notification emailsent">Email Sent</li> - <li class="notification doh">doh</li> + <li class="notification emailsent">Email Sent</li> + <li class="notification doh">doh</li> </ul> - <ul id="emailList"> + <ul id="emailList"> </ul> - <script type="text/html" id="templateError"> - <div class="message">{{ action.title }}</div> - </script> - - <script type="text/html" id="templateTooltip"> - <div class="tooltip" id="createdTooltip"> - {{ contents }} - </div> - </script> - <script type="text/html" id="templateUser"> <li>{{email}}</li> </script> diff --git a/resources/static/test/qunit/controllers/authenticate_controller_unit_test.js b/resources/static/test/qunit/controllers/authenticate_controller_unit_test.js index 2d0aa6964..a09787fac 100644 --- a/resources/static/test/qunit/controllers/authenticate_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/authenticate_controller_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/test/qunit/mocks/xhr", "/resources/network", "/dialog/controllers/page_controller", "/dialog/controllers/authenticate_controller", function() { +steal.then("/dialog/controllers/page_controller", "/dialog/controllers/authenticate_controller", function() { "use strict"; var controller, diff --git a/resources/static/test/qunit/controllers/dialog_controller_unit_test.js b/resources/static/test/qunit/controllers/dialog_controller_unit_test.js index bdfbe742b..fa602bbc4 100644 --- a/resources/static/test/qunit/controllers/dialog_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/dialog_controller_unit_test.js @@ -53,8 +53,8 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con function initController() { controller = el.dialog({ window: { - setupChannel: function() { - if (channelError) throw "Channel error"; + setupChannel: function() { + if (channelError) throw "Channel error"; } } }).controller(); @@ -69,7 +69,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", "/dialog/con teardown: function() { controller.destroy(); reset(); - } + } }); test("initialization with channel error", function() { diff --git a/resources/static/test/qunit/controllers/page_controller_unit_test.js b/resources/static/test/qunit/controllers/page_controller_unit_test.js index 299b8ed00..8d898fc49 100644 --- a/resources/static/test/qunit/controllers/page_controller_unit_test.js +++ b/resources/static/test/qunit/controllers/page_controller_unit_test.js @@ -38,13 +38,14 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { "use strict"; var controller, el, - bodyTemplate = "testBodyTemplate.ejs", - waitTemplate = "wait.ejs"; + bodyTemplate = "testBodyTemplate", + waitTemplate = "wait"; function reset() { el = $("#controller_head"); el.find("#formWrap .contents").html(""); el.find("#wait .contents").html(""); + $("#error").html("<div class='contents'></div>"); el.find("#error .contents").html(""); } @@ -56,7 +57,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { teardown: function() { controller.destroy(); reset(); - } + } }); test("page controller with no template causes no side effects", function() { @@ -130,8 +131,8 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { message: "Test message" } }).controller(); - - controller.renderError("wait.ejs", { + + controller.renderError("wait", { title: "error title", message: "error message" }); @@ -149,8 +150,8 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { message: "Test message" } }).controller(); - - controller.renderError("error.ejs", { + + controller.renderError("error", { action: { title: "expanded action info", message: "expanded message" @@ -180,7 +181,7 @@ steal.plugins("jquery").then("/dialog/controllers/page_controller", function() { message: "Test message" } }).controller(); - + // This is the medium level info. var func = controller.getErrorDialog({ title: "medium level info error title", diff --git a/resources/static/test/qunit/mocks/templates.js b/resources/static/test/qunit/mocks/templates.js new file mode 100644 index 000000000..d1d8ee165 --- /dev/null +++ b/resources/static/test/qunit/mocks/templates.js @@ -0,0 +1,4 @@ +BrowserID.Templates = { + inMemoryTemplate: "<div id='templateInput'></div>" +}; + diff --git a/resources/static/test/qunit/pages/add_email_address_test.js b/resources/static/test/qunit/pages/add_email_address_test.js index 4a4c4ed73..6bbca4c28 100644 --- a/resources/static/test/qunit/pages/add_email_address_test.js +++ b/resources/static/test/qunit/pages/add_email_address_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/resources/network", "/pages/add_email_address", function() { +steal.then("/pages/add_email_address", function() { "use strict"; var bid = BrowserID, @@ -47,12 +47,14 @@ steal.plugins("jquery").then("/resources/network", "/pages/add_email_address", f setup: function() { network.setXHR(xhr); xhr.useResult("valid"); - $(".error").stop().hide(); + $(".error").removeClass("error"); + $("#error").stop().hide(); $(".website").text(""); }, teardown: function() { network.setXHR($); - $(".error").stop().hide(); + $(".error").removeClass("error"); + $("#error").stop().hide(); $(".website").text(""); } }); diff --git a/resources/static/test/qunit/pages/browserid_unit_test.js b/resources/static/test/qunit/pages/browserid_unit_test.js index ab0e6ec97..7a5184845 100644 --- a/resources/static/test/qunit/pages/browserid_unit_test.js +++ b/resources/static/test/qunit/pages/browserid_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery", "funcunit/qunit").then("/pages/page_helpers", "/pages/browserid", function() { +steal.then("/pages/page_helpers", "/pages/browserid", function() { "use strict"; module("/pages/browserid"); diff --git a/resources/static/test/qunit/pages/forgot_unit_test.js b/resources/static/test/qunit/pages/forgot_unit_test.js index d49932e66..ab17c1d0e 100644 --- a/resources/static/test/qunit/pages/forgot_unit_test.js +++ b/resources/static/test/qunit/pages/forgot_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/resources/network", "/resources/user", "/pages/forgot", function() { +steal.then("/pages/forgot", function() { "use strict"; var bid = BrowserID, @@ -46,13 +46,15 @@ steal.plugins("jquery").then("/resources/network", "/resources/user", "/pages/fo module("pages/forgot", { setup: function() { network.setXHR(xhr); - $(".error").stop().hide(); + $(".error").removeClass("error"); + $("#error").stop().hide(); xhr.useResult("valid"); bid.forgot(); }, teardown: function() { network.setXHR($); - $(".error").stop().hide(); + $(".error").removeClass("error"); + $("#error").stop().hide(); $(".website").text(""); bid.forgot.reset(); } diff --git a/resources/static/test/qunit/pages/manage_account_unit_test.js b/resources/static/test/qunit/pages/manage_account_unit_test.js index 97a4b8a9b..8ac855e0c 100644 --- a/resources/static/test/qunit/pages/manage_account_unit_test.js +++ b/resources/static/test/qunit/pages/manage_account_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/resources/network", "/pages/manage_account", function() { +steal.then("/pages/manage_account", function() { "use strict"; var bid = BrowserID, @@ -57,6 +57,7 @@ steal.plugins("jquery").then("/resources/network", "/pages/manage_account", func xhr.useResult("valid"); user.setOrigin(TEST_ORIGIN); $("#emailList").empty(); + $(".error").removeClass("error"); $("#error").hide(); mocks.document.location = ""; storage.clear(); @@ -64,6 +65,7 @@ steal.plugins("jquery").then("/resources/network", "/pages/manage_account", func teardown: function() { network.setXHR($); $("#emailList").empty(); + $(".error").removeClass("error"); $("#error").hide(); } }); diff --git a/resources/static/test/qunit/pages/page_helpers_unit_test.js b/resources/static/test/qunit/pages/page_helpers_unit_test.js index 1ccd4958d..813b669be 100644 --- a/resources/static/test/qunit/pages/page_helpers_unit_test.js +++ b/resources/static/test/qunit/pages/page_helpers_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery", "funcunit/qunit").then("/resources/browserid", function() { +steal.then(function() { "use strict"; var pageHelpers = BrowserID.PageHelpers; diff --git a/resources/static/test/qunit/pages/signin_unit_test.js b/resources/static/test/qunit/pages/signin_unit_test.js index 28d907a7f..8f001abb4 100644 --- a/resources/static/test/qunit/pages/signin_unit_test.js +++ b/resources/static/test/qunit/pages/signin_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/test/qunit/mocks/xhr", "/resources/network", "/resources/user", "/pages/signin", function() { +steal.then("/pages/signin", function() { "use strict"; var bid = BrowserID, @@ -49,6 +49,7 @@ steal.plugins("jquery").then("/test/qunit/mocks/xhr", "/resources/network", "/re module("pages/signin", { setup: function() { network.setXHR(xhr); + $(".error").removeClass("error"); $("#error").stop().hide(); xhr.useResult("valid"); docMock.location = "signin"; @@ -56,6 +57,7 @@ steal.plugins("jquery").then("/test/qunit/mocks/xhr", "/resources/network", "/re }, teardown: function() { network.setXHR($); + $(".error").removeClass("error"); $("#error").stop().hide(); $("#error .message").remove(); bid.signIn.reset(); diff --git a/resources/static/test/qunit/pages/signup_unit_test.js b/resources/static/test/qunit/pages/signup_unit_test.js index 57b2d6c07..e6aae6e93 100644 --- a/resources/static/test/qunit/pages/signup_unit_test.js +++ b/resources/static/test/qunit/pages/signup_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/test/qunit/mocks/xhr", "/resources/network", "/resources/user", "/pages/signup", function() { +steal.then("/pages/signup", function() { "use strict"; var bid = BrowserID, @@ -47,6 +47,7 @@ steal.plugins("jquery").then("/test/qunit/mocks/xhr", "/resources/network", "/re module("pages/signup", { setup: function() { network.setXHR(xhr); + $(".error").removeClass("error"); $("#error").stop().hide(); $(".notification").stop().hide(); xhr.useResult("valid"); @@ -55,6 +56,7 @@ steal.plugins("jquery").then("/test/qunit/mocks/xhr", "/resources/network", "/re }, teardown: function() { network.setXHR($); + $(".error").removeClass("error"); $("#error").stop().hide(); $(".notification").stop().hide(); $("#error .message").remove(); diff --git a/resources/static/test/qunit/pages/verify_email_address_test.js b/resources/static/test/qunit/pages/verify_email_address_test.js index 1108be14c..e1d273a9a 100644 --- a/resources/static/test/qunit/pages/verify_email_address_test.js +++ b/resources/static/test/qunit/pages/verify_email_address_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery").then("/resources/network", "/pages/verify_email_address", function() { +steal.then("/pages/verify_email_address", function() { "use strict"; var bid = BrowserID, @@ -47,12 +47,16 @@ steal.plugins("jquery").then("/resources/network", "/pages/verify_email_address" setup: function() { network.setXHR(xhr); xhr.useResult("valid"); - $("#error,.error").stop().hide(); + $("body").removeClass("error"); + $(".error").removeClass("error"); + $("#error").stop().hide(); $(".website").text(""); }, teardown: function() { network.setXHR($); - $("#error,.error").stop().hide(); + $("body").removeClass("error"); + $(".error").removeClass("error"); + $("#error").stop().hide(); $(".website").text(""); } }); diff --git a/resources/static/test/qunit/qunit.js b/resources/static/test/qunit/qunit.js index fa8952941..c4a5bce55 100644 --- a/resources/static/test/qunit/qunit.js +++ b/resources/static/test/qunit/qunit.js @@ -1,41 +1,50 @@ -steal("/resources/browserid.js", - "/test/qunit/mocks/mocks.js", - "/test/qunit/mocks/xhr.js", - "/lib/ejs.js", - "/resources/browser-support.js", - "/resources/error-messages.js", - "/resources/error-display.js", - "/resources/storage.js", - "/resources/tooltip.js", - "/resources/validation.js", - "/lib/underscore-min.js" - ) - .plugins("jquery", - "jquery/controller", - "jquery/controller/subscribe", - "funcunit/qunit") - .then("/lib/dom-jquery.js", - "pages/browserid_unit_test", - "pages/page_helpers_unit_test", - "include_unit_test", - "relay/relay_unit_test", - "pages/add_email_address_test", - "pages/verify_email_address_test", - "pages/forgot_unit_test", - "pages/signin_unit_test", - "pages/signup_unit_test", - "pages/manage_account_unit_test", - "resources/tooltip_unit_test", - "resources/error-display_unit_test", - "resources/channel_unit_test", - "resources/browser-support_unit_test", - "resources/validation_unit_test", - "resources/storage_unit_test", - "resources/network_unit_test", - "resources/user_unit_test", - "controllers/page_controller_unit_test", - "controllers/pickemail_controller_unit_test", - "controllers/dialog_controller_unit_test", - "controllers/checkregistration_controller_unit_test", - "controllers/authenticate_controller_unit_test"); +steal.plugins( + "jquery", + "jquery/controller", + "jquery/controller/subscribe", + "funcunit/qunit") + .then( + "/lib/underscore-min", + "/lib/ejs", + "/shared/browserid", + "/lib/dom-jquery", + "mocks/mocks", + "mocks/xhr", + "/shared/renderer", + "/shared/screens", + "/shared/browser-support", + "/shared/error-messages", + "/shared/error-display", + "/shared/storage", + "/shared/tooltip", + "/shared/network", + "/shared/user", + "/shared/validation", + + "pages/browserid_unit_test", + "pages/page_helpers_unit_test", + + "include_unit_test", + "relay/relay_unit_test", + "pages/add_email_address_test", + "pages/verify_email_address_test", + "pages/forgot_unit_test", + "pages/signin_unit_test", + "pages/signup_unit_test", + "pages/manage_account_unit_test", + "shared/renderer_unit_test", + "shared/screens_unit_test", + "shared/tooltip_unit_test", + "shared/error-display_unit_test", + "shared/browser-support_unit_test", + "shared/validation_unit_test", + "shared/storage_unit_test", + "shared/network_unit_test", + "shared/user_unit_test", + "resources/channel_unit_test", + "controllers/page_controller_unit_test", + "controllers/pickemail_controller_unit_test", + "controllers/dialog_controller_unit_test", + "controllers/checkregistration_controller_unit_test", + "controllers/authenticate_controller_unit_test"); diff --git a/resources/static/test/qunit/resources/channel_unit_test.js b/resources/static/test/qunit/resources/channel_unit_test.js index e5c26c079..94c2df40a 100644 --- a/resources/static/test/qunit/resources/channel_unit_test.js +++ b/resources/static/test/qunit/resources/channel_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/channel", function() { +steal.then("/dialog/resources/channel", function() { var channel = BrowserID.Channel; var navMock = { @@ -83,7 +83,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/channel", func test("window.setupChannel exists for legacy uses", function() { ok(typeof window.setupChannel, "function", "window.setupChannel exists for legacy uses"); }); - + test("IFRAME channel with assertion", function() { channel.init({ window: winMock, @@ -138,7 +138,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/channel", func test("IFRAME channel with error on open", function() { var winMockWithoutRelay = $.extend(true, {}, winMock); - delete winMockWithoutRelay.opener.frames.browserid_relay_1234; + delete winMockWithoutRelay.opener.frames.browserid_relay_1234; channel.init({ window: winMockWithoutRelay, diff --git a/resources/static/test/qunit/resources/browser-support_unit_test.js b/resources/static/test/qunit/shared/browser-support_unit_test.js similarity index 97% rename from resources/static/test/qunit/resources/browser-support_unit_test.js rename to resources/static/test/qunit/shared/browser-support_unit_test.js index 36a29531c..bbba6db90 100644 --- a/resources/static/test/qunit/resources/browser-support_unit_test.js +++ b/resources/static/test/qunit/shared/browser-support_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery", "funcunit/qunit").then(function() { +steal.then(function() { "use strict"; var bid = BrowserID, @@ -42,7 +42,7 @@ steal.plugins("jquery", "funcunit/qunit").then(function() { stubWindow, stubNavigator; - module("resources/browser-support", { + module("shared/browser-support", { setup: function() { // Hard coded goodness for testing purposes stubNavigator = { diff --git a/resources/static/test/qunit/resources/error-display_unit_test.js b/resources/static/test/qunit/shared/error-display_unit_test.js similarity index 78% rename from resources/static/test/qunit/resources/error-display_unit_test.js rename to resources/static/test/qunit/shared/error-display_unit_test.js index 162aeee56..232641dae 100644 --- a/resources/static/test/qunit/resources/error-display_unit_test.js +++ b/resources/static/test/qunit/shared/error-display_unit_test.js @@ -34,27 +34,34 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery", "funcunit/qunit").then("/resources/error-display", function() { +steal.then(function() { "use strict"; var bid = BrowserID, errorDisplay = bid.ErrorDisplay; - module("/resources/error-display", { + module("shared/error-display", { setup: function() { + $("#error").html("<div class='contents'><a href='#' id='openMoreInfo'>Open</a><div id='moreInfo' style='display:none'>Expanded Info</div></div>"); }, teardown: function() { + $("#error").hide(); } }); - test("can show an error", function() { - var target = $("#error .contents"); - target.empty(); + test("can initialize and open the error display", function() { + $("#error").show(); + bid.ErrorDisplay.start("#error"); + bid.ErrorDisplay.open(); - errorDisplay.render(target, "#templateError", { action: { title: "Error Message" } }); + setTimeout(function() { + ok($("#moreInfo").is(":visible"), "expanded info is visible"); + start(); + }, 100); - ok(target.html(), "Error has some contents"); + stop(); }); + }); diff --git a/resources/static/test/qunit/resources/network_unit_test.js b/resources/static/test/qunit/shared/network_unit_test.js similarity index 99% rename from resources/static/test/qunit/resources/network_unit_test.js rename to resources/static/test/qunit/shared/network_unit_test.js index 97dce2b7d..525ce1c01 100644 --- a/resources/static/test/qunit/resources/network_unit_test.js +++ b/resources/static/test/qunit/shared/network_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery", "funcunit/qunit").then("/resources/network", function() { +steal.then(function() { "use strict"; var testName, @@ -108,7 +108,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/resources/network", function() var network = BrowserID.Network; - module("/resources/network", { + module("shared/network", { setup: function() { network.setXHR(xhr); xhr.useResult("valid"); diff --git a/resources/static/test/qunit/shared/renderer_unit_test.js b/resources/static/test/qunit/shared/renderer_unit_test.js new file mode 100644 index 000000000..f33e59cc0 --- /dev/null +++ b/resources/static/test/qunit/shared/renderer_unit_test.js @@ -0,0 +1,82 @@ +/*jshint browser:true, jQuery: true, forin: true, laxbreak:true */ +/*globals BrowserID: true, _:true */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla bid. + * + * The Initial Developer of the Original Code is Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +steal.then("/test/qunit/mocks/templates", "/shared/renderer", function() { + "use strict"; + + var bid = BrowserID, + renderer = bid.Renderer; + + module("shared/renderer", { + setup: function() { + + }, + + teardown: function() { + + } + }); + + test("render template loaded using XHR", function() { + $("#formWrap .contents").empty(); + $("#templateInput").remove(); + + renderer.render("#formWrap .contents", "testBodyTemplate"); + + ok($("#templateInput").length, "template written when loaded using XHR"); + }); + + test("render template from memory", function() { + $("#formWrap .contents").empty(); + $("#templateInput").remove(); + + renderer.render("#formWrap .contents", "inMemoryTemplate"); + + ok($("#templateInput").length, "template written when loaded from memory"); + }); + + test("append template to element", function() { + $("#formWrap .contents").empty(); + $("#templateInput").remove(); + + renderer.append("#formWrap", "inMemoryTemplate"); + + ok($("#formWrap > #templateInput").length && $("#formWrap > .contents"), "template appended to element instead of overwriting it"); + + }); +}); + + diff --git a/resources/static/test/qunit/shared/screens_unit_test.js b/resources/static/test/qunit/shared/screens_unit_test.js new file mode 100644 index 000000000..70df97ee4 --- /dev/null +++ b/resources/static/test/qunit/shared/screens_unit_test.js @@ -0,0 +1,86 @@ +/*jshint browsers:true, forin: true, laxbreak: true */ +/*global steal: true, test: true, start: true, stop: true, module: true, ok: true, equal: true, BrowserID: true */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla BrowserID. + * + * The Initial Developer of the Original Code is Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +steal.then(function() { + "use strict"; + + var bid = BrowserID, + screens = bid.Screens, + el; + + module("shared/screens", { + setup: function() { + + }, + + teardown: function() { + el.empty(); + } + }); + + test("form", function() { + el = $("#formWrap .contents"); + el.empty(); + screens.form("testBodyTemplate"); + + ok($("#templateInput").length, "the template has been written"); + equal($("body").hasClass("error"), false, "error class taken off of body"); + equal($("body").hasClass("waiting"), false, "waiting class taken off of body"); + equal($("body").hasClass("form"), true, "form class added to body"); + }); + + test("wait", function() { + var el = $("#wait .contents"); + el.empty(); + screens.wait("testBodyTemplate"); + + ok($("#templateInput").length, "the template has been written"); + equal($("body").hasClass("error"), false, "error class taken off of body"); + equal($("body").hasClass("form"), false, "form class taken off of body"); + equal($("body").hasClass("waiting"), true, "waiting class added to body"); + }); + + test("error", function() { + var el = $("#error .contents"); + el.empty(); + screens.error("testBodyTemplate"); + + ok($("#templateInput").length, "the template has been written"); + equal($("body").hasClass("waiting"), false, "waiting class taken off of body"); + equal($("body").hasClass("form"), false, "form class taken off of body"); + equal($("body").hasClass("error"), true, "error class added to body"); + }); +}); diff --git a/resources/static/test/qunit/resources/storage_unit_test.js b/resources/static/test/qunit/shared/storage_unit_test.js similarity index 98% rename from resources/static/test/qunit/resources/storage_unit_test.js rename to resources/static/test/qunit/shared/storage_unit_test.js index 1f7e2ec79..0a6235380 100644 --- a/resources/static/test/qunit/resources/storage_unit_test.js +++ b/resources/static/test/qunit/shared/storage_unit_test.js @@ -34,10 +34,10 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery", "funcunit/qunit").then("/resources/storage", function() { +steal.then(function() { var storage = BrowserID.Storage; - module("storage", { + module("shared/storage", { setup: function() { storage.clear(); }, diff --git a/resources/static/test/qunit/resources/tooltip_unit_test.js b/resources/static/test/qunit/shared/tooltip_unit_test.js similarity index 89% rename from resources/static/test/qunit/resources/tooltip_unit_test.js rename to resources/static/test/qunit/shared/tooltip_unit_test.js index 3070b0080..3dde6b3d3 100644 --- a/resources/static/test/qunit/resources/tooltip_unit_test.js +++ b/resources/static/test/qunit/shared/tooltip_unit_test.js @@ -34,13 +34,13 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery", "funcunit/qunit").then("/resources/tooltip", function() { +steal.then(function() { "use strict"; var bid = BrowserID, tooltip = bid.Tooltip - module("/resources/tooltip", { + module("shared/tooltip", { setup: function() { }, teardown: function() { @@ -59,11 +59,6 @@ steal.plugins("jquery", "funcunit/qunit").then("/resources/tooltip", function() start(); }); - var el = $("#createdTooltip"); - equal(el.length, 1, "one tooltip created"); - var contents = el.html() || ""; - equal(contents.indexOf("contents") === -1, true, "contents have been replaced"); - stop(); }); diff --git a/resources/static/test/qunit/resources/user_unit_test.js b/resources/static/test/qunit/shared/user_unit_test.js similarity index 99% rename from resources/static/test/qunit/resources/user_unit_test.js rename to resources/static/test/qunit/shared/user_unit_test.js index a70a87633..66d46bd73 100644 --- a/resources/static/test/qunit/resources/user_unit_test.js +++ b/resources/static/test/qunit/shared/user_unit_test.js @@ -38,7 +38,7 @@ var jwk = require("./jwk"); var jwt = require("./jwt"); var jwcert = require("./jwcert"); -steal.plugins("jquery", "funcunit/qunit").then("/resources/user", function() { +steal.then(function() { var lib = BrowserID.User, storage = BrowserID.Storage, xhr = BrowserID.Mocks.xhr, @@ -86,7 +86,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/resources/user", function() { */ } - module("resources/user", { + module("shared/user", { setup: function() { BrowserID.Network.setXHR(xhr); xhr.useResult("valid"); diff --git a/resources/static/test/qunit/resources/validation_unit_test.js b/resources/static/test/qunit/shared/validation_unit_test.js similarity index 98% rename from resources/static/test/qunit/resources/validation_unit_test.js rename to resources/static/test/qunit/shared/validation_unit_test.js index d834ba9ba..8db0dd50a 100644 --- a/resources/static/test/qunit/resources/validation_unit_test.js +++ b/resources/static/test/qunit/shared/validation_unit_test.js @@ -34,7 +34,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -steal.plugins("jquery", "funcunit/qunit").then("/resources/browserid", function() { +steal.then(function() { "use strict"; var bid = BrowserID, @@ -46,7 +46,7 @@ steal.plugins("jquery", "funcunit/qunit").then("/resources/browserid", function( tooltipShown = true; } - module("resources/validation", { + module("shared/validation", { setup: function() { origShowTooltip = bid.Tooltip.showTooltip; bid.Tooltip.showTooltip = showTooltip; diff --git a/resources/views/dialog_layout.ejs b/resources/views/dialog_layout.ejs index ddc32e74f..b362ae940 100644 --- a/resources/views/dialog_layout.ejs +++ b/resources/views/dialog_layout.ejs @@ -46,11 +46,6 @@ </div> <% if (useJavascript !== false) { %> - <script type="text/html" id="templateTooltip"> - <div class="tooltip"> - {{ contents }} - </div> - </script> <script type="text/javascript" src="/vepbundle"></script> <script type="text/javascript" src="steal/steal<%= production ? '.production' : '' %>.js?dialog"></script> <% } %> diff --git a/resources/views/layout.ejs b/resources/views/layout.ejs index 2f8a3d009..1caa4fe8b 100644 --- a/resources/views/layout.ejs +++ b/resources/views/layout.ejs @@ -18,18 +18,25 @@ <script src="/lib/jquery-1.6.2.min.js" type="text/javascript"></script> <script src="/lib/json2.js" type="text/javascript"></script> <script src="/lib/underscore-min.js" type="text/javascript"></script> - <script src="/resources/browserid-extensions.js" type="text/javascript"></script> - <script src="/resources/browserid.js" type="text/javascript"></script> - <script src="/resources/error-display.js" type="text/javascript"></script> - <script src="/resources/error-messages.js" type="text/javascript"></script> + <script src="/lib/ejs.js" type="text/javascript"></script> + <script src="/shared/browserid-extensions.js" type="text/javascript"></script> + <script src="/shared/browserid.js" type="text/javascript"></script> + <script src="/lib/dom-jquery.js" type="text/javascript"></script> + + <script src="/shared/templates.js" type="text/javascript"></script> + <script src="/shared/renderer.js" type="text/javascript"></script> + <script src="/shared/error-display.js" type="text/javascript"></script> + <script src="/shared/screens.js" type="text/javascript"></script> + <script src="/shared/error-messages.js" type="text/javascript"></script> + <script src="/shared/storage.js" type="text/javascript"></script> + <script src="/shared/network.js" type="text/javascript"></script> + <script src="/shared/user.js" type="text/javascript"></script> + <script src="/shared/tooltip.js" type="text/javascript"></script> + <script src="/shared/validation.js" type="text/javascript"></script> + <script src="/pages/page_helpers.js" type="text/javascript"></script> <script src="/pages/browserid.js" type="text/javascript"></script> <script src="/pages/index.js" type="text/javascript"></script> - <script src="/resources/storage.js" type="text/javascript"></script> - <script src="/resources/network.js" type="text/javascript"></script> - <script src="/resources/user.js" type="text/javascript"></script> - <script src="/resources/tooltip.js" type="text/javascript"></script> - <script src="/resources/validation.js" type="text/javascript"></script> <script src="/pages/add_email_address.js" type="text/javascript"></script> <script src="/pages/verify_email_address.js" type="text/javascript"></script> <script src="/pages/forgot.js" type="text/javascript"></script> @@ -59,7 +66,7 @@ </ul> </header> - <div id="error"></div> + <div id="error"><div class="contents"></div></div> <%- body %> @@ -75,58 +82,5 @@ </div> -<script type="text/html" id="templateTooltip"> - <div class="tooltip"> - {{ contents }} - </div> -</script> - -<script type="text/html" id="templateError"> - <div> - - <h2>We are very sorry, there has been an error!</h2> - - <p> - To retry, you will have to reload the page and try again. More info can be found by opening the expanded info below. - </p> - - <a href="#" id="openMoreInfo">See more info</a> - - <ul id="moreInfo"> - {% if (typeof action !== "undefined") { %} - <li> - <strong id="action">Action: </strong>{{ action.title }} - - {% if (action.message) { %} - <p> - {{ action.message }} - </p> - {% } %} - </li> - {% } %} - - {% if (typeof network !== "undefined") { %} - <li> - - <strong id="network">Network Info:</strong> {{ network.type }}: {{ network.url }} - - <p> - <strong>Response Code - </strong> {{ network.textStatus }} - </p> - - {% if (network.errorThrown) { %} - <p> - <strong>Error Type:</strong> {{ network.errorThrown }} - </p> - {% } %} - - </li> - - {% } %} - - </ul> - </div> -</script> - </body> </html> diff --git a/resources/views/relay.ejs b/resources/views/relay.ejs index 53ce9739d..648ae21f6 100644 --- a/resources/views/relay.ejs +++ b/resources/views/relay.ejs @@ -14,7 +14,7 @@ <script type='text/javascript' src='https://browserid.org/lib/jschannel.js'></script> <script type='text/javascript' - src='https://browserid.org/resources/browserid.js'></script> + src='https://browserid.org/shared/browserid.js'></script> <script type='text/javascript' src='https://browserid.org/relay/relay.js'></script> <% } %> diff --git a/scripts/compress.sh b/scripts/compress.sh index 69e8b934a..530dc9c3f 100755 --- a/scripts/compress.sh +++ b/scripts/compress.sh @@ -28,8 +28,18 @@ echo '' echo '****Building dialog HTML, CSS, and JS****' echo '' +## This creates a combined templates file which is copied into +## resources/templates.js and included into the minified bundle. + +cd dialog/views +../../../../scripts/create_templates.js +cd ../../ +cp shared/templates.js shared/templates.js.orig +cp dialog/views/templates.js shared/templates.js + steal/js dialog/scripts/build.js + cd communication_iframe $UGLIFY < production.js > production.min.js mv production.min.js production.js @@ -43,7 +53,7 @@ cat popup.css m.css > production.css $JAVA -jar $YUI_LOCATION production.css -o production.min.css cd ../../relay -cat ../lib/jschannel.js ../resources/browserid.js relay.js > production.js +cat ../lib/jschannel.js ../shared/browserid.js relay.js > production.js $UGLIFY < production.js > production.min.js mv production.min.js production.js @@ -54,7 +64,7 @@ echo '' cd ../pages # re-minimize everything together -cat ../lib/jquery-1.6.2.min.js ../lib/json2.js ../resources/browserid.js ../resources/error-display.js ../resources/error-messages.js page_helpers.js browserid.js ../lib/underscore-min.js ../resources/browserid-extensions.js ../resources/storage.js ../resources/network.js ../resources/user.js ../resources/tooltip.js ../resources/validation.js index.js add_email_address.js verify_email_address.js manage_account.js signin.js signup.js forgot.js > lib.js +cat ../lib/jquery-1.6.2.min.js ../lib/json2.js ../lib/underscore-min.js ../lib/ejs.js ../shared/browserid-extensions.js ../shared/browserid.js ../lib/dom-jquery.js ../shared/templates.js ../shared/renderer.js ../shared/error-display.js ../shared/screens.js ../shared/error-messages.js ../shared/storage.js ../shared/network.js ../shared/user.js ../shared/tooltip.js ../shared/validation.js page_helpers.js browserid.js index.js add_email_address.js verify_email_address.js forgot.js manage_account.js signin.js signup.js > lib.js $UGLIFY < lib.js > lib.min.js cd ../css diff --git a/scripts/create_templates.js b/scripts/create_templates.js new file mode 100755 index 000000000..4595d2333 --- /dev/null +++ b/scripts/create_templates.js @@ -0,0 +1,24 @@ +#!/usr/bin/env node + +const fs = require("fs"); + +var dir = process.env.TEMPLATE_DIR || process.cwd(); +console.log(dir); + +var templates = {}; + + +fs.readdir(dir, function(err, fileNames) { + for(var index = 0, max = fileNames.length; index < max; index++) { + var fileName = fileNames[index]; + if(fileName.match(/\.ejs$/)) { + var templateName = fileName.replace(/\.ejs/, ''); + templates[templateName] = fs.readFileSync(dir + "/" + fileName, "utf8") + } + } + + var templateData = "BrowserID.Templates =" + JSON.stringify(templates) + ";"; + + fs.writeFileSync(dir + "/templates.js", templateData, "utf8"); +}); + -- GitLab