From dfadadd2967d4c7ffb52fb2ec48dffbc0400b86b Mon Sep 17 00:00:00 2001 From: Morgan Jones Date: Wed, 8 May 2013 03:31:32 -0600 Subject: [PATCH] IITC Dialog Overhaul, part 2 Core changes * window_management.js => panes.js (clarity, distinction from dialogs) * Make portal preview use dialogs instead of the large preview "window" * Use `open' callback instead of `create' callback for all dialogs * Replace collapse/close buttons with themed buttons inspired by the AP Gain plugin * Dialogs can now gain and lose focus, with changing title bar * Tweak the Poslinks window to use dialogs * Add collapseCallback, expandCallback, collapseExpandCallback, focusCallback, and blurCallback * Fix http in About dialog that caused Chrome to complain Plugin changes * guess-player-level 0.4.1: Use dialogs with titles, typo fix * portal-counts 0.0.8: Use dialogs with titles, typo fix * portals-list 0.0.12: Don't hijack every single dialog onscreen, add titles, typo fix * scoreboard 0.1.8: Use dialogs with titles --- code/boot.js | 30 +++-- code/dialog.js | 146 +++++++++++++++++++----- code/{window_management.js => panes.js} | 0 code/portal_detail_display.js | 9 +- code/utils_misc.js | 16 ++- plugins/guess-player-levels.user.js | 9 +- plugins/portal-counts.user.js | 17 ++- plugins/portals-list.user.js | 25 ++-- plugins/scoreboard.user.js | 22 +++- style.css | 42 +++++-- 10 files changed, 224 insertions(+), 92 deletions(-) rename code/{window_management.js => panes.js} (100%) diff --git a/code/boot.js b/code/boot.js index db2411b9..09d56bf3 100644 --- a/code/boot.js +++ b/code/boot.js @@ -27,25 +27,23 @@ window.setupBackButton = function() { } } - - - window.setupLargeImagePreview = function() { $('#portaldetails').on('click', '.imgpreview', function() { - var ex = $('#largepreview'); - if(ex.length > 0) { - ex.remove(); - return; - } var img = $(this).find('img')[0]; - var w = img.naturalWidth/2; - var h = img.naturalHeight/2; - var c = $('#portaldetails').attr('class'); - $('body').append( - '
' + img.outerHTML + '
' - ); - $('#largepreview').click(function() { $(this).remove() }); - }); + var w = img.naturalWidth, c = $('#portaldetails').attr('class'); + var d = dialog({ + html: '' + img.outerHTML + '', + title: $(this).parent().find('h3.title').html() + }); + + // We have to dynamically set the width of this dialog, so get the .ui-dialog component + var p = d.parents('.ui-dialog'); + + // Don't let this dialog get smaller than the default maximum dialog width + var width = Math.max(parseInt(p.css('max-width')), w); + p.css('min-width', width + 'px'); + p.css('width', width + 'px'); + }); } // adds listeners to the layer chooser such that a long press hides diff --git a/code/dialog.js b/code/dialog.js index e45e697d..f818171b 100644 --- a/code/dialog.js +++ b/code/dialog.js @@ -1,5 +1,6 @@ // DIALOGS ///////////////////////////////////////////////////////// // Inspired by TES III: Morrowind. Long live House Telvanni. /////// +//////////////////////////////////////////////////////////////////// /* The global ID of onscreen dialogs. * Starts at 0. @@ -10,15 +11,33 @@ window.DIALOG_ID = 0; */ window.DIALOGS = {}; -/* Creates a dialog and puts it onscreen. Takes one argument: options. - * Here are the most commonly used ones: - * +/* The number of dialogs on screen. + */ +window.DIALOG_COUNT = 0; + +/* The dialog that has focus. + */ +window.DIALOG_FOCUS = null; + +/* Creates a dialog and puts it onscreen. Takes one argument: options, a JS object. + * == Common options * (text|html): The text or HTML to display in the dialog. Text is auto-converted to HTML. * 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). + * id: A unique ID for this dialog. If a dialog with id `id' is already open and dialog() is called + * again, it will be automatically closed. + * + * == Callbacks + * closeCallback: A callback to run on close. Takes no arguments. + * collapseCallback: A callback to run on dialog collapse. Takes no arguments. + * expandCallback: A callback to run on dialog expansion. Takes no arguments. + * collapseExpandCallback: A callback to run on both collapse and expand (overrides collapseCallback + * and expandCallback, takes a boolean argument `collapsing' - true if collapsing; + * false if expanding) + * focusCallback: A callback to run when the dialog gains focus. + * blurCallback: A callback to run when the dialog loses focus. * * 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 @@ -31,7 +50,8 @@ window.dialog = function(options) { options.modal = true; } - var id = 'dialog-' + (options.modal ? 'modal' : window.DIALOG_ID++); + // Build an identifier for this dialog + var id = 'dialog-' + (options.modal ? 'modal' : (options.id ? options.id : 'anonymous-' + window.DIALOG_ID++)); var jqID = '#' + id; var html = ''; @@ -49,23 +69,35 @@ window.dialog = function(options) { if(options.modal) { options.dialogClass = 'ui-dialog-modal'; options.draggable = false; + options.resizable = false; + } + + // Close out existing dialogs. + if(window.DIALOGS[id]) { + try { + window.DIALOGS[id].dialog('close'); + } catch(err) { + // This dialog doesn't exist anyway + } } // Create the window, appending a div to the body $('body').append('
'); - window.DIALOGS[id] = $(jqID).dialog($.extend(true, { + var dialog = $(jqID).dialog($.extend(true, { autoOpen: false, modal: false, draggable: true, + resizable: true, + closeText: ' ', title: '#', - closeText: 'X', buttons: { 'OK': function() { $(this).dialog('close'); } }, - create: function(event, ui) { + open: function() { var titlebar = $(this).closest('.ui-dialog').find('.ui-dialog-titlebar'); + titlebar.find('.ui-dialog-title').addClass('ui-dialog-title-active'); var close = titlebar.find('.ui-dialog-titlebar-close'); // Title should not show up on mouseover @@ -76,17 +108,33 @@ window.dialog = function(options) { 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.addClass('ui-dialog-titlebar-button-collapse ui-dialog-titlebar-button-collapse-expanded'); 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'); + // Run callbacks if we have them + if($(this).data('collapseExpandCallback')) { + $.proxy($(this).data('collapseExpandCallback'), this)(!collapsed); + } else { + if(collapsed && $(this).data('collapseCallback')) { + $.proxy($(this).data('collapseCallback'), this)(); + } else if (!collapsed && $(this).data('expandCallback')) { + $.proxy($(this).data('expandCallback'), this)(); + } + } + + // Find the button pane and content dialog in this ui-dialog, and add or remove the 'hidden' class. + var dialog = $(this).closest('.ui-dialog'); + var selector = dialog.find('.ui-dialog-content,.ui-dialog-buttonpane'); + var button = dialog.find('.ui-dialog-titlebar-button-collapse'); if (collapsed) { $(selector).removeClass('ui-dialog-content-hidden'); + $(button).removeClass('ui-dialog-titlebar-button-collapse-collapsed'); + $(button).addClass('ui-dialog-titlebar-button-collapse-expanded'); } else { $(selector).addClass('ui-dialog-content-hidden'); + $(button).removeClass('ui-dialog-titlebar-button-collapse-expanded'); + $(button).addClass('ui-dialog-titlebar-button-collapse-collapsed'); } // Toggle collapsed state @@ -97,41 +145,77 @@ window.dialog = function(options) { 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.'); + window.DIALOG_COUNT++; + + console.log('window.dialog: ' + $(this).data('id') + ' (' + $(this).dialog('option', 'title') + ') opened. ' + window.DIALOG_COUNT + ' remain.'); + }, + close: function() { // Run the close callback if we have one if($(this).data('closeCallback')) { $.proxy($(this).data('closeCallback'), this)(); } - // Remove this window - $($(this).data('jqID')).remove(); + // Make sure that we don't keep a dead dialog in focus + if(window.DIALOG_FOCUS && $(window.DIALOG_FOCUS).data('id') === $(this).data('id')) { + window.DIALOG_FOCUS = null; + } + + // Finalize delete window.DIALOGS[$(this).data('id')]; + + window.DIALOG_COUNT--; + console.log('window.dialog: ' + $(this).data('id') + ' (' + $(this).dialog('option', 'title') + ') closed. ' + window.DIALOG_COUNT + ' remain.'); + }, + focus: function() { + if($(this).data('focusCallback')) { + $.proxy($(this).data('focusCallback'), this)(); + } + + // Blur the window currently in focus unless we're gaining focus + if(window.DIALOG_FOCUS && $(window.DIALOG_FOCUS).data('id') !== $(this).data('id')) { + $.proxy(function(event, ui) { + if($(this).data('blurCallback')) { + $.proxy($(this).data('blurCallback'), this)(); + } + + $(this).closest('.ui-dialog').find('.ui-dialog-title').removeClass('ui-dialog-title-active').addClass('ui-dialog-title-inactive'); + }, window.DIALOG_FOCUS)(); + } + + // This dialog is now in focus + window.DIALOG_FOCUS = this; + $(this).closest('.ui-dialog').find('.ui-dialog-title').removeClass('ui-dialog-title-inactive').addClass('ui-dialog-title-active'); } }, options)); - // Set HTML and IDs - $(jqID).html(html); - $(jqID).data('id', id); - $(jqID).data('jqID', jqID); + window.DIALOGS[id] = dialog[0]; - // Set the callback to be executed on close - $(jqID).data('closeCallback', options.closeCallback); + // Set HTML and IDs + dialog.html(html); + dialog.data('id', id); + dialog.data('jqID', jqID); + + // Set callbacks + dialog.data('closeCallback', options.closeCallback); + dialog.data('collapseCallback', options.collapseCallback); + dialog.data('expandCallback', options.expandCallback); + dialog.data('collapseExpandCallback', options.collapseExpandCallback); + dialog.data('focusCallback', options.focusCallback); + dialog.data('blurCallback', options.blurCallback); // ui-modal includes overrides for modal dialogs if (options.modal) { - $(jqID).parent().addClass('ui-modal'); + dialog.parent().addClass('ui-modal'); } // Enable snapping - $(jqID).dialog().parents('.ui-dialog').draggable('option', 'snap', true); + dialog.dialog().parents('.ui-dialog').draggable('option', 'snap', true); // Run it - $(jqID).dialog('open'); - return $(jqID); + dialog.dialog('open'); + + return dialog; } /* Creates an alert dialog with default settings. @@ -145,10 +229,12 @@ window.alert = function(text, isHTML, closeCallback) { obj.text = text; } - window.dialog(obj); + return dialog(obj); } window.setupDialogs = function() { window.DIALOG_ID = 0; - window.DIALOGS = {}; + window.DIALOGS = {} + window.DIALOG_COUNT = 0; + window.DIALOG_FOCUS = null; } diff --git a/code/window_management.js b/code/panes.js similarity index 100% rename from code/window_management.js rename to code/panes.js diff --git a/code/portal_detail_display.js b/code/portal_detail_display.js index 0f02d879..ed2e3e8d 100644 --- a/code/portal_detail_display.js +++ b/code/portal_detail_display.js @@ -18,7 +18,7 @@ window.renderPortalDetails = function(guid) { if(d.portalV2.linkedEdges) $.each(d.portalV2.linkedEdges, function(ind, link) { links[link.isOrigin ? 'outgoing' : 'incoming']++; }); - function linkExpl(t) { return ''+t+''; } + function linkExpl(t) { return ''+t+''; } var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+'  •  '+links.outgoing+' ↴')]; var player = d.captured && d.captured.capturingPlayerId @@ -50,14 +50,13 @@ window.renderPortalDetails = function(guid) { var perma = '/intel?ll='+lat+','+lng+'&z=17&pll='+lat+','+lng; var imgTitle = 'title="'+getPortalDescriptionFromDetails(d)+'\n\nClick to show full image."'; var poslinks = 'window.showPortalPosLinks('+lat+','+lng+',\'' + d.portalV2.descriptiveText.TITLE + '\')'; - var postcard = 'Send in a postcard. Will put it online after receiving. Address:\\n\\nStefan Breunig\\nINF 305 – R045\\n69120 Heidelberg\\nGermany'; $('#portaldetails') .attr('class', TEAM_TO_CSS[getTeam(d)]) .html('' + '

'+d.portalV2.descriptiveText.TITLE+'

' + 'X' - // help cursor via “.imgpreview img” + // help cursor via ".imgpreview img" + '
' + '' + ''+Math.floor(getPortalLevel(d))+'' @@ -73,7 +72,7 @@ window.renderPortalDetails = function(guid) { ); // try to resolve names that were required for above functions, but - // weren’t available yet. + // weren't available yet. resolvePlayerNames(); runHooks('portalDetailsUpdated', {portalDetails: d}); @@ -107,7 +106,7 @@ window.clearPortalIndicators = function() { // highlights portal with given GUID. Automatically clears highlights // on old selection. Returns false if the selected portal changed. -// Returns true if it’s still the same portal that just needs an +// Returns true if it's still the same portal that just needs an // update. window.selectPortal = function(guid) { var update = selectedPortal === guid; diff --git a/code/utils_misc.js b/code/utils_misc.js index 53b61c35..c3966db4 100644 --- a/code/utils_misc.js +++ b/code/utils_misc.js @@ -19,7 +19,7 @@ window.aboutIITC = function(){ + ' ' + '
' + '
' - + ' MapQuest OSM tiles Courtesy of MapQuest ' + + ' MapQuest OSM tiles Courtesy of MapQuest ' + '
' + '
' + '
Version: ' + v + '
' @@ -139,19 +139,23 @@ window.rangeLinkClick = function() { } window.showPortalPosLinks = function(lat, lng, name) { - var portal_name = ''; + var encoded_name = ''; if(name !== undefined) { - portal_name = encodeURIComponent(' (' + name + ')'); + encoded_name = encodeURIComponent(' (' + name + ')'); } if (typeof android !== 'undefined' && android && android.intentPosLink) { android.intentPosLink(lat, lng, portal_name); } else { var qrcode = '
'; var script = ''; - var gmaps = 'Google maps'; + var gmaps = 'Google Maps'; var osm = 'OpenStreetMap'; - var latLng = ''+lat+','+lng +''; - alert('
' + qrcode + script + gmaps + ' ' + osm + '
' + latLng + '
'); + var latLng = '<' + lat + ',' + lng +'>'; + dialog({ + html: '
' + qrcode + script + gmaps + '; ' + osm + '
' + latLng + '
', + title: name, + id: 'poslinks' + }); } } diff --git a/plugins/guess-player-levels.user.js b/plugins/guess-player-levels.user.js index daf5ab7a..2a9582e2 100644 --- a/plugins/guess-player-levels.user.js +++ b/plugins/guess-player-levels.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-guess-player-levels@breunigs // @name IITC plugin: guess player level -// @version 0.4.0.@@DATETIMEVERSION@@ +// @version 0.4.1.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -101,7 +101,7 @@ window.plugin.guessPlayerLevels.guess = function() { }); }); - var s = 'the players have at least the following level:\n\n'; + var s = 'Players have at least the following level:\n\n'; s += 'Resistance:\t   \tEnlightened:\t\n'; var namesR = plugin.guessPlayerLevels.sort(playersRes); @@ -132,7 +132,10 @@ window.plugin.guessPlayerLevels.guess = function() { s += '\nAverage level:\t'+averageR.toFixed(2)+'\tAverage level:\t'+averageE.toFixed(2); s += '\n\nIf there are some unresolved names, simply try again.' //console.log(s); - alert(s); + dialog({ + text: s, + title: 'Player levels: R' + averageR.toFixed(2) + ', E' + averageE.toFixed(2) + }); } window.plugin.guessPlayerLevels.sort = function(playerHash) { diff --git a/plugins/portal-counts.user.js b/plugins/portal-counts.user.js index 76800b97..b0b699bd 100644 --- a/plugins/portal-counts.user.js +++ b/plugins/portal-counts.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-portals-count@yenky // @name IITC plugin: Show total counts of portals -// @version 0.0.7.@@DATETIMEVERSION@@ +// @version 0.0.8.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -13,6 +13,7 @@ // ==/UserScript== /* whatsnew +* 0.0.8 : use dialog() instead of alert() * 0.0.6 : ignoring outside bounds portals (even if close to) * 0.0.5 : changed table layout, added some colors * 0.0.4 : reverse show order of portals, using MAX_PORTAL_LEVEL now for array, changed table layout to be more compact, cleaned up code @@ -74,7 +75,7 @@ window.plugin.portalcounts.getPortals = function(){ var counts = ''; if(retval) { - counts += ''; //'+window.plugin.portalcounts.enlP+' Portal(s)'; + counts += ''; //'+window.plugin.portalcounts.enlP+' Portal(s)'; for(var level = window.MAX_PORTAL_LEVEL; level > 0; level--){ counts += ''; if(minlvl > level) @@ -90,12 +91,18 @@ window.plugin.portalcounts.getPortals = function(){ else counts += window.plugin.portalcounts.neuP; counts += ' Portal(s)'; - counts += ''; + counts += ''; counts += ''; } else - counts += ''; + counts += ''; counts += '
EnlightmentResistance
EnlightenedResistance
Level '+level+'
Enlightment:'+window.plugin.portalcounts.enlP+' Portal(s)
Enlightened:'+window.plugin.portalcounts.enlP+' Portal(s)
Resistance:'+window.plugin.portalcounts.resP+' Portal(s)
No Portals in range !
No Portals in range!
'; - alert('
'+counts+'
'); + + + var total = window.plugin.portalcounts.enlP + window.plugin.portalcounts.resP + window.plugin.portalcounts.neuP; + dialog({ + html: '
' + counts + '
', + title: 'Portal counts: ' + total + ' ' + (total == 1 ? 'portal' : 'portals'), + }); } var setup = function() { diff --git a/plugins/portals-list.user.js b/plugins/portals-list.user.js index 3877d5c3..fdb94300 100644 --- a/plugins/portals-list.user.js +++ b/plugins/portals-list.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @id iitc-plugin-portals-list@teo96 // @name IITC plugin: show list of portals -// @version 0.0.11.@@DATETIMEVERSION@@ +// @version 0.0.12.@@DATETIMEVERSION@@ // @namespace https://github.com/jonatkins/ingress-intel-total-conversion // @updateURL @@UPDATEURL@@ // @downloadURL @@DOWNLOADURL@@ @@ -13,6 +13,7 @@ // ==/UserScript== /* whatsnew +* 0.0.12: Use dialog() instead of alert so the user can drag the box around * 0.0.11: Add nominal energy column and # links, fix sort bug when opened even amounts of times, nits * 0.0.10: Fixed persistent css problem with alert * 0.0.9 : bugs hunt @@ -120,13 +121,15 @@ window.plugin.portalslist.displayPL = function() { if (window.plugin.portalslist.getPortals()) { html += window.plugin.portalslist.portalTable('level', window.plugin.portalslist.sortOrder,window.plugin.portalslist.filter); } else { - html = '
Nothing to Show !
'; + html = '
Nothing to show!
'; }; - alert('
' + html + '
', true, function() { - $(".ui-dialog").removeClass('ui-dialog-portalslist'); - $(document).off('.portalslist'); - }); - $(".ui-dialog").addClass('ui-dialog-portalslist'); + + dialog({ + html: '
' + html + '
', + dialogClass: 'ui-dialog-portalslist', + title: 'Portal list: ' + window.plugin.portalslist.listPortals.length + ' ' + (window.plugin.portalslist.listPortals.length == 1 ? 'portal' : 'portals'), + id: 'portal-list' + }); // Setup sorting $(document).on('click.portalslist', '#portalslist table th', function() { @@ -264,7 +267,7 @@ window.plugin.portalslist.portalTable = function(sortBy, sortOrder, filter) { html += ''; html += '
Click on portals table headers to sort by that column. ' - + 'Click on All Portals, Resistant Portals, Enlightened Portals to filter
' + + 'Click on All Portals, Resistance Portals, Enlightened Portals to filter
' + 'Thanks to @vita10gy & @xelio for their IITC plugins who inspired me. A @teo96 production. Vive la Résistance !
'; window.plugin.portalslist.sortOrder = window.plugin.portalslist.sortOrder*-1; @@ -275,7 +278,7 @@ window.plugin.portalslist.stats = function(sortBy) { //console.log('** stats'); var html = '' + '' - + '' + + '' + '' + '' + '
All Portals : (click to filter)' + window.plugin.portalslist.listPortals.length + 'Resistant Portals : ' + window.plugin.portalslist.resP +' (' + Math.floor(window.plugin.portalslist.resP/window.plugin.portalslist.listPortals.length*100) + '%)Resistance Portals : ' + window.plugin.portalslist.resP +' (' + Math.floor(window.plugin.portalslist.resP/window.plugin.portalslist.listPortals.length*100) + '%)Enlightened Portals : '+ window.plugin.portalslist.enlP +' (' + Math.floor(window.plugin.portalslist.enlP/window.plugin.portalslist.listPortals.length*100) + '%)
'; @@ -318,8 +321,8 @@ window.plugin.portalslist.getPortalLink = function(portal,guid) { var setup = function() { $('#toolbox').append(' Portals list'); $('head').append('