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 <img> 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
This commit is contained in:
Morgan Jones
2013-05-08 03:31:32 -06:00
parent 9b56ac0982
commit dfadadd296
10 changed files with 224 additions and 92 deletions

View File

@ -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(
'<div id="largepreview" class="'+c+'" style="margin-left: '+(-SIDEBAR_WIDTH/2-w-2)+'px; margin-top: '+(-h-2)+'px">' + img.outerHTML + '</div>'
);
$('#largepreview').click(function() { $(this).remove() });
});
var w = img.naturalWidth, c = $('#portaldetails').attr('class');
var d = dialog({
html: '<span class="' + c + '" style="position: relative; width: 100%; left: 50%; margin-left: ' + -(w / 2) + 'px;">' + img.outerHTML + '</span>',
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

View File

@ -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('<div id="' + id + '"></div>');
window.DIALOGS[id] = $(jqID).dialog($.extend(true, {
var dialog = $(jqID).dialog($.extend(true, {
autoOpen: false,
modal: false,
draggable: true,
resizable: true,
closeText: '&nbsp;',
title: '#<Dialog: ' + id + '>',
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('&ndash;');
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;
}

View File

@ -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 '<tt title="↳ incoming links\n↴ outgoing links\n• is meant to be the portal.">'+t+'</tt>'; }
function linkExpl(t) { return '<tt title="↳ incoming links\n↴ outgoing links\n• is the portal">'+t+'</tt>'; }
var linksText = [linkExpl('links'), linkExpl(' ↳ ' + links.incoming+'&nbsp;&nbsp;•&nbsp;&nbsp;'+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(''
+ '<h3 class="title">'+d.portalV2.descriptiveText.TITLE+'</h3>'
+ '<span class="close" onclick="unselectOldPortal();" title="Close">X</span>'
// help cursor via .imgpreview img
// help cursor via ".imgpreview img"
+ '<div class="imgpreview" '+imgTitle+' style="background-image: url('+img+')">'
+ '<img class="hide" src="'+img+'"/>'
+ '<span id="level">'+Math.floor(getPortalLevel(d))+'</span>'
@ -73,7 +72,7 @@ window.renderPortalDetails = function(guid) {
);
// try to resolve names that were required for above functions, but
// werent 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 its 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;

View File

@ -19,7 +19,7 @@ window.aboutIITC = function(){
+ ' </ul>'
+ ' </div>'
+ ' <div>'
+ ' MapQuest OSM tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">'
+ ' MapQuest OSM tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="https://developer.mapquest.com/content/osm/mq_logo.png">'
+ ' </div>'
+ ' <hr>'
+ ' <div>Version: ' + v + '</div>'
@ -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 = '<div id="qrcode"></div>';
var script = '<script>$(\'#qrcode\').qrcode({text:\'GEO:'+lat+','+lng+'\'});</script>';
var gmaps = '<a href="https://maps.google.com/?q='+lat+','+lng+portal_name+'">Google maps</a>';
var gmaps = '<a href="https://maps.google.com/?q='+lat+','+lng+encoded_name+'">Google Maps</a>';
var osm = '<a href="http://www.openstreetmap.org/?mlat='+lat+'&mlon='+lng+'&zoom=16">OpenStreetMap</a>';
var latLng = '<span>'+lat+','+lng +'</span>';
alert('<div style="text-align: center;">' + qrcode + script + gmaps + ' ' + osm + '<br />' + latLng + '</div>');
var latLng = '<span>&lt;' + lat + ',' + lng +'&gt;</span>';
dialog({
html: '<div style="text-align: center;">' + qrcode + script + gmaps + '; ' + osm + '<br />' + latLng + '</div>',
title: name,
id: 'poslinks'
});
}
}