diff --git a/app/assets/javascripts/discourse.js b/app/assets/javascripts/discourse.js index 997ffcb5a57..c2e8be02abc 100644 --- a/app/assets/javascripts/discourse.js +++ b/app/assets/javascripts/discourse.js @@ -184,6 +184,9 @@ Discourse = Ember.Application.createWithMixins({ } }); + bootbox.animate(false); + bootbox.backdrop(true); // clicking outside a bootbox modal closes it + setInterval(function(){ Discourse.Formatter.updateRelativeAge($('.relative-date')); },60 * 1000); diff --git a/app/assets/javascripts/discourse/controllers/composer_controller.js b/app/assets/javascripts/discourse/controllers/composer_controller.js index f4553ab28ce..b145f7573bf 100644 --- a/app/assets/javascripts/discourse/controllers/composer_controller.js +++ b/app/assets/javascripts/discourse/controllers/composer_controller.js @@ -59,22 +59,17 @@ Discourse.ComposerController = Discourse.Controller.extend({ message = Em.String.i18n("composer.posting_not_on_topic", {title: this.get('content.topic.title')}); buttons = [{ - "label": Em.String.i18n("composer.cancel"), - "class": "btn" - }]; - - buttons.push({ - "label": Em.String.i18n("composer.reply_original"), - "class": "btn-primary", + "label": Em.String.i18n("composer.reply_original") + "
" + this.get('content.topic.title') + "
", + "class": "btn-primary btn-reply-on-original", "callback": function(){ _this.save(true); } - }); + }]; if(topic) { buttons.push({ - "label": Em.String.i18n("composer.reply_here"), - "class": "btn-primary", + "label": Em.String.i18n("composer.reply_here") + "
" + topic.get('title') + "
", + "class": "btn btn-reply-here", "callback": function(){ composer.set('topic', topic); composer.set('post', null); @@ -83,7 +78,13 @@ Discourse.ComposerController = Discourse.Controller.extend({ }); } - bootbox.dialog(message, buttons); + buttons.push({ + "label": Em.String.i18n("composer.cancel"), + "class": "cancel", + "link": true + }); + + bootbox.dialog(message, buttons, {"classes": "reply-where-modal"}); return; } } diff --git a/app/assets/javascripts/external/bootbox.js b/app/assets/javascripts/external/bootbox.js index 3d811afc5c3..256e538d943 100644 --- a/app/assets/javascripts/external/bootbox.js +++ b/app/assets/javascripts/external/bootbox.js @@ -1,103 +1,26 @@ /** - * bootbox.js v2.3.2 + * bootbox.js v3.2.0 * - * The MIT License - * - * Copyright (C) 2011-2012 by Nick Payne - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE + * http://bootboxjs.com/license.txt */ -var bootbox = window.bootbox || (function($) { +var bootbox = window.bootbox || (function(document, $) { + /*jshint scripturl:true sub:true */ var _locale = 'en', _defaultLocale = 'en', - _animate = false, + _animate = true, + _backdrop = 'static', + _defaultHref = 'javascript:;', + _classes = '', + _btnClasses = {}, _icons = {}, /* last var should always be the public object we'll return */ that = {}; + /** - * standard locales. Please add more according to ISO 639-1 standard. Multiple language variants are - * unlikely to be required. If this gets too large it can be split out into separate JS files. + * public API */ - var _locales = { - 'en' : { - OK : 'OK', - CANCEL : 'Cancel', - CONFIRM : 'OK' - }, - 'fr' : { - OK : 'OK', - CANCEL : 'Annuler', - CONFIRM : 'D\'accord' - }, - 'de' : { - OK : 'OK', - CANCEL : 'Abbrechen', - CONFIRM : 'Akzeptieren' - }, - 'es' : { - OK : 'OK', - CANCEL : 'Cancelar', - CONFIRM : 'Aceptar' - }, - 'br' : { - OK : 'OK', - CANCEL : 'Cancelar', - CONFIRM : 'Sim' - }, - 'nl' : { - OK : 'OK', - CANCEL : 'Annuleren', - CONFIRM : 'Accepteren' - }, - 'ru' : { - OK : 'OK', - CANCEL : 'Отмена', - CONFIRM : 'Применить' - }, - 'it' : { - OK : 'OK', - CANCEL : 'Annulla', - CONFIRM : 'Conferma' - } - }; - - function _translate(str, locale) { - // we assume if no target locale is probided then we should take it from current setting - if (locale == null) { - locale = _locale; - } - if (typeof _locales[locale][str] == 'string') { - return _locales[locale][str]; - } - - // if we couldn't find a lookup then try and fallback to a default translation - - if (locale != _defaultLocale) { - return _translate(str, _defaultLocale); - } - - // if we can't do anything then bail out with whatever string was passed in - last resort - return str; - } - that.setLocale = function(locale) { for (var i in _locales) { if (i == locale) { @@ -106,23 +29,30 @@ var bootbox = window.bootbox || (function($) { } } throw new Error('Invalid locale: '+locale); - } + }; that.addLocale = function(locale, translations) { - if (typeof _locales[locale] == 'undefined') { + if (typeof _locales[locale] === 'undefined') { _locales[locale] = {}; } for (var str in translations) { _locales[locale][str] = translations[str]; } - } + }; that.setIcons = function(icons) { _icons = icons; - if (typeof _icons !== 'object' || _icons == null) { + if (typeof _icons !== 'object' || _icons === null) { _icons = {}; } - } + }; + + that.setBtnClasses = function(btnClasses) { + _btnClasses = btnClasses; + if (typeof _btnClasses !== 'object' || _btnClasses === null) { + _btnClasses = {}; + } + }; that.alert = function(/*str, label, cb*/) { var str = "", @@ -151,17 +81,20 @@ var bootbox = window.bootbox || (function($) { break; default: throw new Error("Incorrect number of arguments: expected 1-3"); - break; } return that.dialog(str, { - "label": label, - "icon" : _icons.OK, + // only button (ok) + "label" : label, + "icon" : _icons.OK, + "class" : _btnClasses.OK, "callback": cb }, { - "onEscape": cb + // ensure that the escape key works; either invoking the user's + // callback or true to just close the dialog + "onEscape": cb || true }); - } + }; that.confirm = function(/*str, labelCancel, labelOk, cb*/) { var str = "", @@ -198,33 +131,44 @@ var bootbox = window.bootbox || (function($) { break; default: throw new Error("Incorrect number of arguments: expected 1-4"); - break; } - return that.dialog(str, [{ - "label": labelCancel, - "icon" : _icons.CANCEL, - "callback": function() { - if (typeof cb == 'function') { - cb(false); - } + var cancelCallback = function() { + if (typeof cb === 'function') { + return cb(false); } - }, { - "label": labelOk, - "icon" : _icons.CONFIRM, - "callback": function() { - if (typeof cb == 'function') { - cb(true); - } - } - }]); - } + }; - that.prompt = function(/*str, labelCancel, labelOk, cb*/) { + var confirmCallback = function() { + if (typeof cb === 'function') { + return cb(true); + } + }; + + return that.dialog(str, [{ + // first button (cancel) + "label" : labelCancel, + "icon" : _icons.CANCEL, + "class" : _btnClasses.CANCEL, + "callback": cancelCallback + }, { + // second button (confirm) + "label" : labelOk, + "icon" : _icons.CONFIRM, + "class" : _btnClasses.CONFIRM, + "callback": confirmCallback + }], { + // escape key bindings + "onEscape": cancelCallback + }); + }; + + that.prompt = function(/*str, labelCancel, labelOk, cb, defaultVal*/) { var str = "", labelCancel = _translate('CANCEL'), labelOk = _translate('CONFIRM'), - cb = null; + cb = null, + defaultVal = ""; switch (arguments.length) { case 1: @@ -253,39 +197,62 @@ var bootbox = window.bootbox || (function($) { labelOk = arguments[2]; cb = arguments[3]; break; - default: - throw new Error("Incorrect number of arguments: expected 1-4"); + case 5: + str = arguments[0]; + labelCancel = arguments[1]; + labelOk = arguments[2]; + cb = arguments[3]; + defaultVal = arguments[4]; break; + default: + throw new Error("Incorrect number of arguments: expected 1-5"); } var header = str; // let's keep a reference to the form object for later var form = $("
"); - form.append(""); + form.append(""); + + var cancelCallback = function() { + if (typeof cb === 'function') { + // yep, native prompts dismiss with null, whereas native + // confirms dismiss with false... + return cb(null); + } + }; + + var confirmCallback = function() { + if (typeof cb === 'function') { + return cb(form.find("input[type=text]").val()); + } + }; var div = that.dialog(form, [{ - "label": labelCancel, - "icon" : _icons.CANCEL, - "callback": function() { - if (typeof cb == 'function') { - cb(null); - } - } + // first button (cancel) + "label" : labelCancel, + "icon" : _icons.CANCEL, + "class" : _btnClasses.CANCEL, + "callback": cancelCallback }, { - "label": labelOk, - "icon" : _icons.CONFIRM, - "callback": function() { - if (typeof cb == 'function') { - cb( - form.find("input[type=text]").val() - ); - } - } + // second button (confirm) + "label" : labelOk, + "icon" : _icons.CONFIRM, + "class" : _btnClasses.CONFIRM, + "callback": confirmCallback }], { - "header": header + // prompts need a few extra options + "header" : header, + // explicitly tell dialog NOT to show the dialog... + "show" : false, + "onEscape": cancelCallback }); + // ... the reason the prompt needs to be hidden is because we need + // to bind our own "shown" handler, after creating the modal but + // before any show(n) events are triggered + // @see https://github.com/makeusabrew/bootbox/issues/69 + div.on("shown", function() { form.find("input[type=text]").focus(); @@ -297,61 +264,21 @@ var bootbox = window.bootbox || (function($) { }); }); + div.modal("show"); + return div; - } - - that.modal = function(/*str, label, options*/) { - var str; - var label; - var options; - - var defaultOptions = { - "onEscape": null, - "keyboard": true, - "backdrop": true - }; - - switch (arguments.length) { - case 1: - str = arguments[0]; - break; - case 2: - str = arguments[0]; - if (typeof arguments[1] == 'object') { - options = arguments[1]; - } else { - label = arguments[1]; - } - break; - case 3: - str = arguments[0]; - label = arguments[1]; - options = arguments[2]; - break; - default: - throw new Error("Incorrect number of arguments: expected 1-3"); - break; - } - - defaultOptions['header'] = label; - - if (typeof options == 'object') { - options = $.extend(defaultOptions, options); - } else { - options = defaultOptions; - } - - return that.dialog(str, [], options); - } + }; that.dialog = function(str, handlers, options) { - var hideSource = null, - buttons = "", - callbacks = [], - options = options || {}; + var buttons = "", + callbacks = []; + + if (!options) { + options = {}; + } // check for single object and convert to array if necessary - if (handlers == null) { + if (typeof handlers === 'undefined') { handlers = []; } else if (typeof handlers.length == 'undefined') { handlers = [handlers]; @@ -360,6 +287,7 @@ var bootbox = window.bootbox || (function($) { var i = handlers.length; while (i--) { var label = null, + href = null, _class = null, icon = '', callback = null; @@ -399,6 +327,12 @@ var bootbox = window.bootbox || (function($) { _class = 'btn-primary'; } + // See: https://github.com/makeusabrew/bootbox/pull/114 + // Upgrade to official bootbox release when it gets merged. + if (handlers[i]['link'] !== true) { + _class = 'btn ' + _class; + } + if (handlers[i]['label']) { label = handlers[i]['label']; } else { @@ -409,17 +343,30 @@ var bootbox = window.bootbox || (function($) { icon = " "; } - buttons += ""+icon+""+label+""; + if (handlers[i]['href']) { + href = handlers[i]['href']; + } + else { + href = _defaultHref; + } + + buttons = ""+icon+""+label+"" + buttons; callbacks[i] = callback; } - var parts = ["