MediaWiki:Gadget-ImageAnnotator.js: Difference between revisions
Content deleted Content added
More code cleanup; remove unused variables, use mw.config.get |
Migrate from legacy globals and hardcoded script paths to using getUrl() and wikiScript(); Also hoist functions that were nested in if() blocks, Javascript doesn't support this and just hoists them unconditonally to the nearest top of a function scope. |
||
Line 25:
/*jshint undef:true, unused:true, browser:true, eqnull:true, laxbreak:true, laxcomma:true */
/*global prompt */ // discouraged browser globals
/*global wgServer
/*global wgUserGroups, wgNamespaceNumber, wgRestrictionEdit */ // legacy config page globals
/*global mw, $ */
Line 390:
},
destroy
if (this.view) LAPI.DOM.removeNode(this.view);
if (this.dummy) LAPI.DOM.removeNode(this.dummy);
Line 402:
},
area
if (!this.model || !this.model.dimension) return 0;
return (this.model.dimension.w * this.model.dimension.h);
},
cannotEdit
if (this.content && this.content.button_section) {
LAPI.DOM.removeNode(this.content.button_section);
Line 421:
ImageAnnotationEditor.prototype =
{
initialize
var editor_width = 50;
// Respect potential user-defined width setting
Line 447:
,onpreview : this.onpreview.bind(this)
,oncancel : this.cancel.bind(this)
,ongettext
if (text == null) return '';
text = text.trim()
Line 512:
},
get_editor
return this.box;
},
editNote
var same_note = (note == this.note);
this.note = note;
Line 565:
},
open_editor
this.editor.hidePreview();
if (!same_note || this.editor.textarea.readOnly)
Line 603:
},
hide_editor
if (!this.visible) return;
this.visible = false;
Line 623:
},
save
var data = editor.getText();
if (!data || !data.length) {
Line 846:
if (lk && lk.length && lk[0].firstChild.nodeName.toLowerCase() === 'a') {
lk = lk[0].firstChild;
lk.href =
}
if (ex) {
Line 868:
},
onpreview
if (this.tooltip) this.tooltip.size_change();
},
cancel
if (!this.note) return;
if (!this.note.content) {
Line 882:
},
close_tooltip
this.hide_editor(evt);
this.cancel();
Line 893:
ImageNotesViewer.prototype =
{
initialize
Object.merge(descriptor, this);
this.annotations = [];
Line 921:
},
setup
this.setup_done = true;
var name = this.realName;
Line 1,144:
},
cannotEdit
if (!this.may_edit) return;
this.may_edit = false;
Line 1,150:
},
setShowHideEvents
if (this.icon) return;
if (set) {
Line 1,164:
},
removeMoveListener
if (this.icon) return;
this.move_listening = false;
Line 1,174:
},
adjustRectangleSize
if (this.icon) return;
// Make sure the note boxes don't overlap the image boundary; we might get an event
Line 1,205:
},
toggle
var i;
if (!this.annotations || this.annotations.length === 0 || this.icon) return;
Line 1,228:
},
show
if (this.visible || this.icon) return;
this.toggle(IA.is_adding || IA.is_editing);
Line 1,239:
},
hide
function intersect_rectangles (a, b) {
if (b.x > a.r || b.r < a.x || b.y > a.b || b.b < a.y)
return { x:0, y:0, r:0, b:0 };
return {
x: Math.max(a.x, b.x),
y: Math.max(a.y, b.y),
r: Math.min(a.r, b.r),
b: Math.min(a.b, b.b)
};
}
if (this.icon) return true;
if (!this.visible) {
Line 1,266 ⟶ 1,277:
// Compute the actually visible region by intersecting the rectangle given by img_pos and
// this.img.offsetWidth, this.img.offsetTop with the rectangles of all overflow parents.
for (i = 0; i < this.overflowParents.length && rect.x < rect.r && rect.y < rect.b; i++) {
Line 1,351 ⟶ 1,350:
lk.parentNode.replaceChild(
LAPI.DOM.makeLink(
, this.realName
, this.realName
Line 1,375 ⟶ 1,374:
// for drawing rectangles onto the image if there is only one image and editing is allowed.
haveAjax
button_div : null,
Line 1,629 ⟶ 1,628:
},
wait_for_required_libraries
if (typeof Tooltip === 'undefined' || typeof LAPI === 'undefined') {
if (IA.install_attempts++ < IA.max_install_attempts) {
Line 1,783 ⟶ 1,782:
}
return { scope : scope
,file_div
,img : img
,realName : name
Line 1,889 ⟶ 1,888:
function set_info (json) {
function get_size (info) {
if (!info.imageinfo || info.imageinfo.length === 0) return;
var title = info.title.replace(/ /g, '_');
var indices = cache[title];
if (!indices) return;
Array.forEach(
indices
, function (i) {
self.imgs[i].full_img = { width : info.imageinfo[0].width
,height: info.imageinfo[0].height};
self.imgs[i].has_page = (typeof info.missing === 'undefined');
self.imgs[i].isLocal = !info.imagerepository || info.imagerepository === 'local';
if (i != 0 || !self.may_edit || !info.protection || wgNamespaceNumber !== 6) return;
// Care about the protection settings
var protection = Array.any(info.protection, function (e) {
return (e.type === 'edit' ? e : null);
});
self.may_edit =
!protection
|| (wgUserGroups && wgUserGroups.join(' ').contains(protection.level))
;
}
);
}
try {
if (json && json.query && json.query.pages) {
for (var page in json.query.pages) {
get_size (json.query.pages[page]);
Line 1,927 ⟶ 1,926:
// prompt by using getScript instead of parseWikitext in this case.
ImageAnnotator.info_callbacks = [];
var template =
+ '&prop=info|imageinfo&inprop=protection&iiprop=size'
+ '&titles=&callback=ImageAnnotator.info_callbacks[].callback';
Line 1,986 ⟶ 1,985:
},
setup_ui
// Complete the UI object we've gotten from config.
Line 2,078 ⟶ 2,077:
span.appendChild(
LAPI.DOM.makeLink(
withJS: 'MediaWiki:ImageAnnotatorTranslator.js',
language: conf.wgUserLanguage
}),
translate,
(typeof translate === 'string' ? translate : LAPI.DOM.getInnerText(translate).trim())
)
);
Line 2,126 ⟶ 2,128:
function get_ui_no_ajax () {
var url =
+ encodeURIComponent(ui_page) + '&title=API&prop=text'
+ '&callback=ImageAnnotator.UI.init&maxage=14400&smaxage=14400'
Line 2,170 ⟶ 2,172:
},
setup_step_two
var self = IA;
Line 2,192 ⟶ 2,194:
},
complete_setup
function track(evt) {
evt = evt || window.event;
if (self.is_adding) self.update_zoom(evt);
Line 2,291 ⟶ 2,229:
}
function resume
// captureEvents is actually deprecated, but I haven't succeeded to make this work with
// addEventListener only.
Line 2,302 ⟶ 2,240:
}
function stop_tracking
evt = evt || window.event;
// Check that we're within the image. Note: this check can fail only on IE >= 7, on other
Line 2,349 ⟶ 2,287:
}
function start_tracking
if (!self.is_tracking) {
self.is_tracking = true;
Line 2,382 ⟶ 2,320:
}
function add_new
if (!self.canEdit()) return;
Line 2,429 ⟶ 2,367:
self.viewers[0].msg.style.display = '';
}
// We can be sure to have the UI here because this is called only when the ready event of the
// UI object is fired.
var self = IA;
// Check edit permissions
if (self.may_edit && typeof wgRestrictionEdit !== 'undefined' ) {
self.may_edit =
( (wgRestrictionEdit.length === 0 || wgUserGroups && wgUserGroups.join(' ').contains('sysop'))
|| ( wgRestrictionEdit.length === 1 && wgRestrictionEdit[0] === 'autoconfirmed'
&& wgUserGroups && wgUserGroups.join(' ').contains('confirmed') // confirmed & autoconfirmed
)
);
}
if (self.may_edit) {
// Check whether the image is local. Don't allow editing if the file is remote.
var sharedUpload = document.getElementsByClassName('sharedUploadNotice');
self.may_edit = (!sharedUpload || sharedUpload.length === 0);
}
if (self.may_edit && wgNamespaceNumber !== 6) {
// Only allow edits if the stored page name matches the current one.
var img_page_name = self.imgs[0].scope.getElementsByClassName('wpImageAnnotatorPageName');
if (img_page_name && img_page_name.length)
img_page_name = LAPI.DOM.getInnerText(img_page_name[0]);
else
img_page_name = '';
self.may_edit = (img_page_name.replace(/ /g, '_') == conf.wgTitle.replace(/ /g, '_'));
}
if (self.may_edit && self.ajaxQueried) self.may_edit = self.haveAjax;
// Now create viewers for all images
self.viewers = new Array (self.imgs.length);
for (var i = 0; i < self.imgs.length; i++) {
self.viewers[i] = new ImageNotesViewer (self.imgs[i], i === 0 && self.may_edit);
}
if (self.may_edit) {
// Respect user override for zoom, if any
self.zoom_threshold = ImageAnnotator_config.zoom_threshold;
if ( typeof window.ImageAnnotator_zoom_threshold !== 'undefined'
&& !isNaN (window.ImageAnnotator_zoom_threshold)
&& window.ImageAnnotator_zoom_threshold >= 0.0
) {
// If somebody sets it to a nonsensical high value, that's his or her problem: there won't be any
// zooming.
self.zoom_threshold = window.ImageAnnotator_zoom_threshold;
}
// Adapt zoom threshold for small thumbnails or images with a very lopsided width/height ratio,
// but only if we *can* zoom at least twice
if ( self.viewers[0].full_img.width > 300
&& Math.min(self.viewers[0].factors.dx, self.viewers[0].factors.dy) >= 2.0
) {
if ( self.viewers[0].thumb.width < 400
|| self.viewers[0].thumb.width / self.viewers[0].thumb.height > 2.0
|| self.viewers[0].thumb.height / self.viewers[0].thumb.width > 2.0
) {
self.zoom_threshold = 0; // Force zooming
}
}
self.editor = new ImageAnnotationEditor();
self.button_div = LAPI.make('div');
Line 2,692 ⟶ 2,694:
if ((!window.XMLHttpRequest && !!window.ActiveXObject) || !self.haveAjax) {
make_script_calls(get_local,
} else {
make_calls(
Line 2,717 ⟶ 2,719:
},
show_zoom
var self = IA;
if ( ( self.viewers[0].factors.dx < self.zoom_threshold
Line 2,812 ⟶ 2,814:
},
update_zoom
if (!evt) return; // We need an event to calculate positions!
var self = IA;
Line 2,848 ⟶ 2,850:
},
hide_zoom
if (!IA.zoom) return;
if (evt) {
Line 2,857 ⟶ 2,859:
},
createHelpLink
var msg = ImageAnnotator.UI.get('wpImageAnnotatorHelp', false, true);
if (!msg || !msg.lastChild) return null;
Line 2,881 ⟶ 2,883:
tgt = msg.lastChild;
if (tgt.nodeName.toLowerCase() !== 'a')
tgt =
else
tgt = tgt.href;
Line 2,914 ⟶ 2,916:
},
get_cover
var self = IA;
var shim;
Line 2,972 ⟶ 2,974:
},
show_cover
var self = IA;
if (self.cover && !self.cover_visible) {
Line 2,985 ⟶ 2,987:
},
hide_cover
var self = IA;
if (self.cover && self.cover_visible) {
Line 2,998 ⟶ 3,000:
},
getRawItem
var node = null;
if (!scope || scope == document) {
Line 3,009 ⟶ 3,011:
},
getItem
var node = IA.getRawItem(what, scope);
if (!node) return null;
Line 3,015 ⟶ 3,017:
},
getIntItem
var x = IA.getItem(what, scope);
if (x !== null) x = parseInt (x, 10);
Line 3,021 ⟶ 3,023:
},
findNote
function find (text, id, delim) {
var start = delim.start.replace('$1', id);
Line 3,039 ⟶ 3,041:
},
setWikitext
var self = IA;
if (self.wiki_read) return;
Line 3,063 ⟶ 3,065:
},
setSummary
if (initial_text.contains('$1')) {
var max = (summary.maxlength || 200) - initial_text.length;
Line 3,075 ⟶ 3,077:
},
getScript
// Don't use LAPI here, it may not yet be available
if (bypass_caches) {
Line 3,093 ⟶ 3,095:
},
canEdit
var self = IA;
if (self.may_edit) {
Line 3,125 ⟶ 3,127:
// Start it. Bypass caches; but allow for 4 hours client-side caching. Small file.
IA.getScript(
// Cache 4 hours
+ '&dummy=' + Math.floor((new Date()).getTime() / (14400 * 1000)),
|