diff --git a/code/boot.js b/code/boot.js
index fa578d63..70bc32fc 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
@@ -341,22 +339,6 @@ window.setupTooltips = function(element) {
}
}
-window.setupDialogs = function() {
- $('#dialog').dialog({
- autoOpen: false,
- modal: true,
- buttons: [
- { text: 'OK', click: function() { if($(this).data("closeCallback")) {$(this).data("closeCallback")();} $(this).dialog('close'); } }
- ]
- });
-
- window.alert = function(text, isHTML, closeCallback) {
- var h = isHTML ? text : window.convertTextToTableMagic(text);
- $('#dialog').data("closeCallback", closeCallback);
- $('#dialog').html(h).dialog('open');
- }
-}
-
window.setupTaphold = function() {
@@INCLUDERAW:external/taphold.js@@
}
diff --git a/code/dialog.js b/code/dialog.js
new file mode 100644
index 00000000..1b5a31ac
--- /dev/null
+++ b/code/dialog.js
@@ -0,0 +1,239 @@
+// DIALOGS /////////////////////////////////////////////////////////
+// Inspired by TES III: Morrowind. Long live House Telvanni. ///////
+////////////////////////////////////////////////////////////////////
+
+/* The global ID of onscreen dialogs.
+ * Starts at 0.
+ */
+window.DIALOG_ID = 0;
+
+/* All onscreen dialogs, keyed by their ID.
+ */
+window.DIALOGS = {};
+
+/* 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.
+ * 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
+ * useful.
+ */
+window.dialog = function(options) {
+ // Override for smartphones. Preserve default behavior and create a modal dialog.
+ options = options || {};
+ if(isSmartphone()) {
+ options.modal = true;
+ }
+
+ // Build an identifier for this dialog
+ var id = 'dialog-' + (options.modal ? 'modal' : (options.id ? options.id : 'anon-' + 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) {
+ html = options.html;
+ } else {
+ console.log('window.dialog: warning: no text in dialog');
+ html = window.convertTextToTableMagic('');
+ }
+
+ // Modal dialogs should not be draggable
+ if(options.modal) {
+ options.dialogClass = 'ui-dialog-modal';
+ options.draggable = false;
+ }
+
+ // Close out existing dialogs.
+ if(window.DIALOGS[id]) {
+ try {
+ var selector = $(window.DIALOGS[id]);
+ selector.dialog('close');
+ selector.remove();
+ } catch(err) {
+ console.log('window.dialog: Tried to close nonexistent dialog ' + id);
+ }
+ }
+
+ // Create the window, appending a div to the body
+ $('body').append('');
+ var dialog = $(jqID).dialog($.extend(true, {
+ autoOpen: false,
+ modal: false,
+ draggable: true,
+ closeText: ' ',
+ title: '',
+ buttons: {
+ 'OK': function() {
+ $(this).dialog('close');
+ }
+ },
+ 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
+ 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 ui-dialog-titlebar-button-collapse-expanded');
+ collapse.click($.proxy(function() {
+ var collapsed = ($(this).data('collapsed') === true);
+
+ // 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
+ $(this).data('collapsed', !collapsed);
+ }, this));
+
+ // Put it into the titlebar
+ titlebar.prepend(collapse);
+ close.addClass('ui-dialog-titlebar-button-close');
+ }
+
+ window.DIALOGS[$(this).data('id')] = this;
+ 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)();
+ }
+
+ // 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
+ 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) {
+ dialog.parent().addClass('ui-modal');
+ }
+
+ // Enable snapping
+ dialog.dialog().parents('.ui-dialog').draggable('option', 'snap', true);
+
+ // Run it
+ dialog.dialog('open');
+
+ return dialog;
+}
+
+/* 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};
+ if(isHTML) {
+ obj.html = text;
+ } else {
+ obj.text = text;
+ }
+
+ return dialog(obj);
+}
+
+window.setupDialogs = function() {
+ window.DIALOG_ID = 0;
+ 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/redeeming.js b/code/redeeming.js
index 1c4931de..e5efa643 100644
--- a/code/redeeming.js
+++ b/code/redeeming.js
@@ -1,5 +1,6 @@
-
-// REDEEMING /////////////////////////////////////////////////////////
+// REDEEMING ///////////////////////////////////////////////////////
+// Heuristic passcode redemption that tries to guess unknown items /
+////////////////////////////////////////////////////////////////////
/* Resource type names mapped to actual names and abbreviations.
* Add more here if necessary.
@@ -93,11 +94,16 @@ window.REDEEM_HINTS = {
};
window.handleRedeemResponse = function(data, textStatus, jqXHR) {
- var passcode = this.passcode, to_alert, to_log;
+ var passcode = this.passcode, to_dialog, to_log, dialog_title, dialog_buttons;
if(data.error) {
- to_alert = '' + data.error + ' ' + (window.REDEEM_ERRORS[data.error] || 'There was a problem redeeming the passcode. Try again?');
- to_log = '[ERROR] ' + 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;
+
+ // 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 = {};
@@ -190,7 +196,7 @@ window.handleRedeemResponse = function(data, textStatus, jqXHR) {
// Let the user know if we had to guess
if (inferred.length > 0) {
- results.table.push('
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 = '