diff --git a/code/dialog.js b/code/dialog.js index 5d53d0f0..33a3beb7 100644 --- a/code/dialog.js +++ b/code/dialog.js @@ -1,6 +1,7 @@ // DIALOGS ///////////////////////////////////////////////////////// +// Inspired by TES III: Morrowind. Long live House Telvanni. /////// -/* The ID of onscreen dialogs. +/* The global ID of onscreen dialogs. * Starts at 0. */ window.DIALOG_ID = 0; @@ -9,15 +10,32 @@ window.DIALOG_ID = 0; */ window.DIALOGS = {}; -/* Creates a dialog and puts it onscreen. Takes one parameter: options. +/* Creates a dialog and puts it onscreen. Takes one argument: options. + * Here are the most commonly used ones: + * * (text|html): The text or HTML to display in the dialog. Text is auto-converted to HTML. - * title: The dialog's title + * title: The dialog's title. + * closeCallback: A callback to run on close. + * modal: Whether to open a modal dialog. Implies draggable=false; dialogClass='ui-dialog-modal'. + * Please note that modal dialogs hijack the entire screen and should only be used in very + * specific cases. (If IITC is running on mobile, modal will always be true). + * + * See http://docs.jquery.com/UI/API/1.8/Dialog for a list of all the options. If you previously + * applied a class to your dialog after creating it with alert(), dialogClass may be particularly + * useful. */ window.dialog = function(options) { - var id = 'dialog-' + window.DIALOG_ID++; - var jqID = '#' + id; + // Override for smartphones. Preserve default behavior and create a modal dialog. + options = options || {}; + if(isSmartphone()) { + options.modal = true; + } + var id = 'dialog-' + (options.modal ? 'modal' : window.DIALOG_ID++); + var jqID = '#' + id; var html = ''; + + // Convert text to HTML if necessary if(options.text) { html = window.convertTextToTableMagic(options.text); } else if(options.html) { @@ -27,46 +45,102 @@ window.dialog = function(options) { html = window.convertTextToTableMagic(''); } + // Modal dialogs should not be draggable + if(options.modal) { + options.dialogClass = 'ui-dialog-modal'; + options.draggable = false; + } + + // Create the window, appending a div to the body $('body').append('
'); window.DIALOGS[id] = $(jqID).dialog($.extend(true, { autoOpen: false, modal: false, + draggable: true, title: '#', + closeText: 'X', buttons: { 'OK': function() { - $(this).dialog('close'); + $(this).dialog('close'); } }, - close: function(event, ui) { - console.log('window.dialog: dialog ' + $(this).dialog('option', 'title') + ' closed.'); + create: function(event, ui) { + var titlebar = $(this).closest('.ui-dialog').find('.ui-dialog-titlebar'); + var close = titlebar.find('.ui-dialog-titlebar-close'); + + // Title should not show up on mouseover + close.removeAttr('title').addClass('ui-dialog-titlebar-button'); + + if(!$(this).dialog('option', 'modal')) { + // Start out with a cloned version of the close button + var collapse = close.clone(); + + // Change it into a collapse button and set the click handler + collapse.addClass('ui-dialog-titlebar-button-collapse'); + collapse.find('.ui-button-text').html('–'); + collapse.click($.proxy(function() { + var collapsed = ($(this).data('collapsed') === true); + + // Find the button pane and content dialog in this ui-dialog, and add or remove the 'hidden' class + var selector = $(this).closest('.ui-dialog').find('.ui-dialog-content,.ui-dialog-buttonpane'); + if (collapsed) { + $(selector).removeClass('ui-dialog-content-hidden'); + } else { + $(selector).addClass('ui-dialog-content-hidden'); + } + + // Toggle collapsed state + $(this).data('collapsed', !collapsed); + }, this)); + + // Put it into the titlebar + titlebar.prepend(collapse); + close.addClass('ui-dialog-titlebar-button-close'); + } + }, + close: function(event, ui) { + // We're closing, so log it to the console + console.log('window.dialog: ' + id + ' (' + $(this).dialog('option', 'title') + ') closed.'); + + // Run the close callback if we have one if($(this).data('closeCallback')) { - $(this).data('closeCallback')(); + $.proxy($(this).data('closeCallback'), this)(); } + // Remove this window $($(this).data('jqID')).remove(); delete window.DIALOGS[$(this).data('id')]; } }, options)); + // Set HTML and IDs $(jqID).html(html); - $(jqID).data('closeCallback', options.closeCallback); $(jqID).data('id', id); $(jqID).data('jqID', jqID); + // Set the callback to be executed on close + $(jqID).data('closeCallback', options.closeCallback); + + // ui-modal includes overrides for modal dialogs + if (options.modal) { + $(jqID).parent().addClass('ui-modal'); + } + + // Run it $(jqID).dialog('open'); + return $(jqID); } -/* Deprecated. Creates a dialog with default settings. - * Use window.dialog instead. +/* Creates an alert dialog with default settings. + * If you want more configurability, use window.dialog instead. */ window.alert = function(text, isHTML, closeCallback) { - var obj = {closeCallback: closeCallback}; + var obj = {title: '', closeCallback: closeCallback}; if(isHTML) { obj.html = text; } else { obj.text = text; } - console.log('window.alert: this function is deprecated, please use window.dialog instead'); window.dialog(obj); } diff --git a/code/redeeming.js b/code/redeeming.js index 399b501f..47bb2fe8 100644 --- a/code/redeeming.js +++ b/code/redeeming.js @@ -92,12 +92,16 @@ window.REDEEM_HINTS = { }; window.handleRedeemResponse = function(data, textStatus, jqXHR) { - var passcode = this.passcode, to_dialog, to_log, buttons; + var passcode = this.passcode, to_dialog, to_log, dialog_title, dialog_buttons; if(data.error) { + // What to display to_dialog = '' + data.error + '
' + (window.REDEEM_ERRORS[data.error] || 'There was a problem redeeming the passcode. Try again?'); to_log = '[ERROR] ' + data.error; - buttons = {}; + + // Dialog options + dialog_title = 'Error: ' + passcode; + dialog_buttons = {}; } else if(data.result) { var encouragement = window.REDEEM_ENCOURAGEMENT[Math.floor(Math.random() * window.REDEEM_ENCOURAGEMENT.length)]; var payload = {}; @@ -199,32 +203,34 @@ window.handleRedeemResponse = function(data, textStatus, jqXHR) { } // Display formatted versions in a table, plaintext, and the console log - to_dialog = '' + + to_dialog = '
' + results.table.map(function(a) {return '' + a + '';}).join("\n") + '
'; to_log = '[SUCCESS] ' + results.plain.join('/'); - buttons = { + + dialog_title = 'Passcode: ' + passcode; + dialog_buttons = { 'PLAINTEXT' : function() { dialog({ - title: 'Passcode: ' + passcode, - html: '' + encouragement + '' + - '
' + results.html.join('/') + '
' + title: 'Rewards: ' + passcode, + html: '' + results.html.join('/') + '' }); } } } + // Display it dialog({ - title: 'Passcode: ' + passcode, - html: to_dialog, - buttons: buttons + title: dialog_title, + buttons: dialog_buttons, + html: to_dialog }); console.log(passcode + ' => ' + to_log); } window.setupRedeem = function() { $("#redeem").keypress(function(e) { - if((e.keyCode ? e.keyCode : e.which) !== 13) return; + if((e.keyCode ? e.keyCode : e.which) !== 13 || !$(this).val()) return; var data = {passcode: $(this).val()}; window.postAjax('redeemReward', data, window.handleRedeemResponse, @@ -236,6 +242,7 @@ window.setupRedeem = function() { extra = 'No status code was returned.'; } dialog({ + title: 'Request failed: ' + data.passcode, html: 'The HTTP request failed. ' + extra }); }); diff --git a/code/utils_misc.js b/code/utils_misc.js index dc9c6a6f..53b61c35 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -27,8 +27,12 @@ window.aboutIITC = function(){ + '
' + attrib + '
' + '
' + '
' + contrib + '
'; - alert(a, true, function() {$('.ui-dialog').removeClass('ui-dialog-aboutIITC');}); - $('.ui-dialog').addClass('ui-dialog-aboutIITC'); + dialog({ + title: 'IITC ' + v, + html: a, + dialogClass: 'ui-dialog-aboutIITC', + closeCallback: function() {$('.ui-dialog').removeClass('ui-dialog-aboutIITC');} + }); } diff --git a/style.css b/style.css index c01f4147..c4db1026 100644 --- a/style.css +++ b/style.css @@ -503,7 +503,7 @@ h3 { .mods span { background-color: rgba(0, 0, 0, 0.3); - /* can’t use inline-block because Webkit’s implementation is buggy and + /* can’t use inline-block because Webkit's implementation is buggy and * introduces additional margins in random cases. No clear necessary, * as that’s solved by setting height on .mods. */ display: block; @@ -666,7 +666,6 @@ h3 { font-size: 16px; } - /* update status */ #updatestatus { background-color: rgba(8, 48, 78, 0.9); @@ -712,6 +711,25 @@ h3 { padding: 2px 4px; } +.ui-widget-overlay { + height: 100%; + left: 0; + position: fixed; + top: 0; + width: 100%; + z-index: 10000; + background: #444; + opacity: 0.6; +} + +.ui-modal { + z-index: 10001 !important; +} + +.ui-tooltip { + z-index: 10002 !important; +} + .ui-tooltip, .ui-dialog a { color: #FFCE00; } @@ -721,15 +739,8 @@ h3 { border-radius: 2px; } -.ui-widget-overlay { - height: 100%; - left: 0; - position: fixed; - top: 0; - width: 100%; - z-index:9998; - background: #444; - opacity: 0.6; +.ui-dialog-modal .ui-dialog-titlebar-close { + display: none; } .ui-dialog-titlebar { @@ -743,10 +754,26 @@ h3 { font-weight: bold; } -.ui-dialog-titlebar-close { +.ui-dialog-titlebar-button { position: absolute; - right: .2em; - top: 0; + float: left; + width: 17px; + height: 19px; + top: 2px; + cursor: pointer; + color: #FFCE00; + font-family: "Arial", sans; + font-size: 14px; + border-style: none; + background-color: rgba(0, 0, 0, 0); +} + +.ui-dialog-titlebar-button-close { + right: 4px; +} + +.ui-dialog-titlebar-button-collapse { + right: 28px; } .ui-dialog-content { @@ -757,6 +784,10 @@ h3 { max-width: 700px !important; } +.ui-dialog-content-hidden { + display: none !important; +} + .ui-dialog-buttonpane { padding: 12px; border-top: 1px solid #20A8B1; @@ -798,7 +829,7 @@ td + td { } /* redeem results *****************************************************/ -.redeem-result { +.redeem-result-table { font-size: 14px; font-family: Roboto, Arial, Helvetica, sans-serif; table-layout: fixed; @@ -809,6 +840,10 @@ td + td { text-align: right; } +.redeem-result-html { + font-family: Inconsolata, Consolas, Menlo, "Courier New", monospace; +} + .pl_nudge_date { background-color: #724510; border-left: 1px solid #ffd652;