MediaWiki:Gadget-ImageAnnotator.js: Difference between revisions

Content deleted Content added
No edit summary
Use native Array.isArray in modern browsers instead of Object#toString comparision ($.isArray is defined as polyfill using toString in old browsers and a direct reference to isArray in new browsers)
Line 2:
 
/*
ImageAnnotator v2v3.30.20
 
ATTENTION:
This legacy version of ImageAnnotator is on longer maintained and kept at this address
for backwards compatibility with wikis running MediaWiki 1.23 or older.
User Krinkle has decided to fork this to
https://commons.wikimedia.org/wiki/MediaWiki:Gadget-ImageAnnotator-v3.js.
and to make sure the Commons uses _that_.
For any problems with that v3 version, please contact https://commons.wikimedia.org/wiki/User:Krinkle.
 
Image annotations. Draw rectangles onto image thumbnail displayed on image description
Line 31 ⟶ 22:
*/
 
// Global: importScript, importScriptURI (wikiwikibits.js)
// Global: wgPageName, wgCurRevisionId, wgUserGroups, wgRestrictionEdit (inline script on the page)
// Global: wgAction, wgNamespaceNumber, wgUserLanguage, wgContentLanguage, stylepath (inline script)
// Global: wgNamespaceIds (inline script)
/*jshint eqnull:true, laxbreak:true, laxcomma:true */
Line 45 ⟶ 36:
 
(function () { // Local scope
 
var conf = mw.config.get([
'skin',
'stylepath'
]);
 
var ImageAnnotator_config = null;
Line 65 ⟶ 61:
viewer : null, // Reference to the viewer this note belongs to
 
initialize : function (node, viewer, id) {
{
var is_new = false;
var view_w = 0, view_h = 0, view_x = 0, view_y = 0;
Line 82 ⟶ 77:
throw new Error ('Invalid note: origin invalid on note ' + id);
if ( x + w > viewer.full_img.width + 10
|| y + h > viewer.full_img.height + 10)
) {
throw new Error ('Invalid note: size extends beyond image on note ' + id);
}
// Notes written by early versions may be slightly too large, whence the + 10 above. Fix this.
Line 94 ⟶ 89:
view_y = Math.floor(y / viewer.factors.dy);
this.view =
LAPI.make( 'div', null, {
position: 'divabsolute', null
, { position display: 'absolutenone',
// ,display : 'none'IE
,lineHeight : '0px' // IE,
,fontSize : '0px' // IE
fontSize: '0px',
,top top: '' + view_y + 'px',
,left : '' + view_x + 'px',
,width : '' + view_w + 'px',
,height : '' + view_h + 'px'
});
);
// We'll add the view to the DOM once we've loaded all notes
this.model = {
{ id : id,
,dimension: { x: x, y: y, w: w, h: h },
,wiki : '',
,html : html.cloneNode(true)
};
} else {
is_new = true;
this.view = node;
this.model = {
{ id : -1,
,dimension: null,
,wiki : '',
,html : null
};
view_w = this.view.offsetWidth - 2; // Subtract cumulated border widths
view_h = this.view.offsetHeight - 2;
Line 132 ⟶ 127:
if (view_h < 6) {view_y = Math.floor(view_y + view_h / 2 - 3); view_h = 6; }
Object.merge(
{
{ left: '' + view_x + 'px',
top: '' + view_y + 'px',
,width: '' + view_w + 'px',
height: '' + view_h + 'px'}
},
this.view.style
);
this.view.style.zIndex = 500; // Below tooltips
Line 171 ⟶ 170:
},
 
setTooltip : function () {
{
if (this.tooltip || !this.view) return; // Already set, or corrupt
// Note: on IE, don't have tooltips appear automatically. IE doesn't do it right for transparent
Line 215 ⟶ 213:
},
 
display : function (evt) {
{
if (!this.content) {
this.content = LAPI.make('div');
Line 259 ⟶ 256:
},
 
edit : function (evt) {
{
if (IA.canEdit()) IA.editor.editNote(this);
if (evt) return LAPI.Evt.kill(evt);
Line 266 ⟶ 262:
},
 
remove_event : function (evt) {
{
if (IA.canEdit()) this.remove();
return LAPI.Evt.kill(evt);
},
 
remove : function () {
{
if (!this.content) { // New note: just destroy it.
this.destroy();
Line 303 ⟶ 297:
LAPI.Ajax.editPage(
wgPageName
, function (doc, editForm, failureFunc, revision_id) {
{
try {
if (revision_id && revision_id != wgCurRevisionId)
Line 381 ⟶ 374:
},
 
destroy : function () {
{
if (this.view) LAPI.DOM.removeNode(this.view);
if (this.dummy) LAPI.DOM.removeNode(this.dummy);
Line 394 ⟶ 386:
},
 
area : function () {
{
if (!this.model || !this.model.dimension) return 0;
return (this.model.dimension.w * this.model.dimension.h);
},
 
cannotEdit : function () {
{
if (this.content && this.content.button_section) {
LAPI.DOM.removeNode(this.content.button_section);
Line 415 ⟶ 405:
ImageAnnotationEditor.prototype =
{
initialize : function () {
{
var editor_width = 50;
// Respect potential user-defined width setting
Line 511 ⟶ 500:
},
 
editNote : function (note) {
{
var same_note = (note == this.note);
this.note = note;
Line 561 ⟶ 549:
},
 
open_editor : function (same_note, cover) {
{
this.editor.hidePreview();
if (!same_note || this.editor.textarea.readOnly)
Line 600 ⟶ 587:
},
 
hide_editor : function (evt) {
{
if (!this.visible) return;
this.visible = false;
Line 621 ⟶ 607:
},
 
save : function (editor) {
{
var data = editor.getText();
if (!data || !data.length) {
Line 708 ⟶ 693:
LAPI.Ajax.editPage(
wgPageName
, function (doc, editForm, failureFunc, revision_id) {
{
try {
if (revision_id && revision_id != wgCurRevisionId)
Line 836 ⟶ 820:
);
}
, function (request, ex) {
{
self.editor.busy(false);
self.saving = false;
Line 847 ⟶ 830:
// Error message. Use preview field for this.
var error_msg = ImageAnnotator.UI.get('wpImageAnnotatorSaveError', false);
var lk = error_msg.getElementsByClassName(error_msg, 'span', 'wpImageAnnotatorOwnPageLink');
if (lk && lk.length && lk[0].firstChild.nodeName.toLowerCase() === 'a') {
lk = lk[0].firstChild;
Line 872 ⟶ 855:
},
 
onpreview : function (editor) {
{
if (this.tooltip) this.tooltip.size_change();
},
 
cancel : function (editor) {
{
if (!this.note) return;
if (!this.note.content) {
Line 888 ⟶ 869:
},
 
close_tooltip : function (tooltip, evt) {
{
this.hide_editor(evt);
this.cancel();
Line 900 ⟶ 880:
ImageNotesViewer.prototype =
{
initialize : function (descriptor, may_edit) {
{
Object.merge(descriptor, this);
this.annotations = [];
Line 911 ⟶ 890:
this.tip = null;
this.icon = null;
this.factors = {
{ dx : this.full_img.width / this.thumb.width,
,dy : this.full_img.height / this.thumb.height
};
 
if (!this.isThumbnail && !this.isOther) {
Line 929 ⟶ 908:
},
 
setup : function (onlyIcon) {
{
this.setup_done = true;
var name = this.realName;
var $fullname;
if (this.isThumbnail || this.scope == document || this.may_edit || !IA.haveAjax) {
this.imgName = this.realName;
this.realName = '';
} else {
name$fullname = getElementsByClassName $(this.scope, '*', ).find('.wpImageAnnotatorFullName');
this.realName = ((name && name$fullname.length) ? LAPI$fullname.DOM.getInnerTexttext(name[0]) : '');
this.imgName = this.realName;
}
 
var annotations = getElementsByClassName (this.scope, 'div', .getElementsByClassName(IA.annotation_class);
 
if (!this.may_edit && (!annotations || annotations.length === 0))
Line 997 ⟶ 976:
(name, this.isLocal, this.thumb, this.full_img, annotations.length, this.isThumbnail)
)
) ){
{
// Use an onclick handler instead of a link around the image. The link may have a default white
// background, but we want to be sure to have transparency. The image should be an 8-bit indexed
Line 1,008 ⟶ 986:
&& this.icon.nodeName.toLowerCase() == 'a'
&& this.icon.firstChild.nodeName.toLowerCase() == 'img'
) ){
{
// Make sure we use the right protocol:
var srcFixed = this.icon.firstChild.getAttribute('src', 2).replace(/^https?\:/, document.___location.protocol);
Line 1,024 ⟶ 1,001:
}
Object.merge(
{ {position: 'absolute', zIndex: 1000, top: '0px', cursor: 'pointer' },
, this.icon.style
);
this.icon.onclick = (function () { ___location.href = this.img.parentNode.href; }).bind(this);
Line 1,057 ⟶ 1,034:
if ( w == this.full_img.width && h == this.full_img.height
&& !Array.exists(this.annotations, function (note) { return note.model.id == id; })
) ){
{
try {
this.register(new ImageAnnotation(annotations[i], this, id));
Line 1,072 ⟶ 1,048:
Array.forEach(this.annotations, (function (note) {this.img_div.appendChild(note.view);}).bind(this));
if (this.isThumbnail) {
this.main_div = getElementsByClassName (this.file_div, 'div', .getElementsByClassName('thumbcaption');
if (!this.main_div || this.main_div.length === 0)
this.main_div = null;
else
Line 1,098 ⟶ 1,074:
&& ImageAnnotator_config.displayCaptionInArticles
(name, this.isLocal, this.thumb, this.full_img, annotations.length, this.isThumbnail)
) ){
this.msg = LAPI.make('div', null, { display: 'none' });
{
this.msg = LAPI.make('div', null, {display: 'none'});
if (IA.is_rtl) {
this.msg.style.direction = 'rtl';
Line 1,156 ⟶ 1,131:
},
 
cannotEdit : function () {
{
if (!this.may_edit) return;
this.may_edit = false;
Line 1,163 ⟶ 1,137:
},
 
setShowHideEvents : function (set) {
{
if (this.icon) return;
if (set) {
Line 1,178 ⟶ 1,151:
},
 
removeMoveListener : function () {
{
if (this.icon) return;
this.move_listening = false;
Line 1,189 ⟶ 1,161:
},
 
adjustRectangleSize : function (node) {
{
if (this.icon) return;
// Make sure the note boxes don't overlap the image boundary; we might get an event
Line 1,210 ⟶ 1,181:
// Now set position and width and height, subtracting cumulated border widths
if ( view_x != node.offsetLeft || view_y != node.offsetTop
|| view_w != node.offsetWidth || view_h != node.offsetHeight)
) {
node.style.top = '' + view_y + 'px';
node.style.left = '' + view_x + 'px';
Line 1,221 ⟶ 1,192:
},
 
toggle : function (dummies) {
{
var i;
if (!this.annotations || this.annotations.length === 0 || this.icon) return;
Line 1,245 ⟶ 1,215:
},
 
show : function (evt) {
{
if (this.visible || this.icon) return;
this.toggle(IA.is_adding || IA.is_editing);
Line 1,257 ⟶ 1,226:
},
 
hide : function (evt) {
{
if (this.icon) return true;
if (!this.visible) {
Line 1,318 ⟶ 1,286:
if ( display !== 'none' && display != null
&& LAPI.Pos.isWithin(this.annotations[i].view.firstChild, mouse_pos.x, mouse_pos.y)
) {
{
if (!this.annotations[i].tooltip.visible) this.annotations[i].tooltip.show(evt);
return true;
Line 1,336 ⟶ 1,303:
},
 
check_hide : function (evt) {
{
if (this.icon) return true;
if (this.visible)
Line 1,344 ⟶ 1,310:
},
 
register : function (new_note) {
{
this.annotations[this.annotations.length] = new_note;
if (new_note.model.id > 0) {
Line 1,354 ⟶ 1,319:
},
 
deregister : function (note) {
{
Array.remove(this.annotations, note);
if (note.model.id == this.max_id) this.max_id--;
Line 1,361 ⟶ 1,325:
},
 
setDefaultMsg : function () {
{
if (this.annotations && this.annotations.length && this.msg) {
LAPI.DOM.removeChildren(this.msg);
Line 1,394 ⟶ 1,357:
};
 
var IA = {
{
// This object is responsible for setting up annotations when a page is loaded. It loads all
// annotations in the page source, and adds an "Annotate this image" button plus the support
Line 1,432 ⟶ 1,394:
],
 
tooltip_styles : // The style for all our tooltips
tooltip_styles: {
{ border : '1px solid #8888aa'
, backgroundColor border: '1px solid #ffffe08888aa'
, padding backgroundColor: '0.3em#ffffe0'
, padding: '0.3em'
, fontSize : ((skin && (skin == 'monobook' || skin == 'modern')) ? '127%' : '100%')
, fontSize: (conf.skin === 'monobook' ? '127%' : '100%')
// Scale up to default text size
},
 
editor : null,
 
wiki_read : false,
is_rtl : false,
 
move_listening : false,
is_tracking : false,
is_adding : false,
is_editing : false,
 
zoom_threshold : 8.0,
zoom_factor : 4.0,
 
install_attempts : 0,
max_install_attempts : 10, // Maximum 5 seconds
 
imgs_with_notes : [],
thumbs : [],
other_images : [],
 
// Fallback
indication_icon : '//upload.wikimedia.org/wikipedia/commons/8/8a/Gtk-dialog-info-14px.png',
 
install : function (config) {
{
if (typeof ImageAnnotator_disable !== 'undefined' && !!ImageAnnotator_disable) return;
if (!config || ImageAnnotator_config != null) return;
Line 1,480 ⟶ 1,442:
&& typeof LAPI.Ajax !== 'undefined'
&& typeof LAPI.Ajax.getRequest !== 'undefined'
) ){
{
self.haveAjax = (LAPI.Ajax.getRequest() != null);
self.ajaxQueried = true;
Line 1,492 ⟶ 1,453:
self.may_edit = wgNamespaceNumber >= 0 && wgArticleId > 0 && self.haveAjax && config.editingEnabled();
 
function namespaceCheck (list) {
if (!list || !$.isArray(list)) return false;
{
if (!list || Object.prototype.toString.call(list) !== '[object Array]') return false;
for (var i = 0; i < list.length; i++) {
if (wgNamespaceIds
Line 1,514 ⟶ 1,474:
if ( !self.haveAjax
|| !config.generalImagesEnabled()
|| namespaceCheck (window.ImageAnnotator_no_images || null)
) ){
{
self.rules.inline.show = false;
self.rules.thumbs.show = false;
Line 1,524 ⟶ 1,483:
|| !config.thumbsEnabled()
|| namespaceCheck(window.ImageAnnotator_no_thumbs || null)
) ){
{
self.rules.thumbs.show = false;
}
Line 1,532 ⟶ 1,490:
else if ( !config.sharedImagesEnabled()
|| namespaceCheck(window.ImageAnnotator_no_shared || null)
) ){
{
self.rules.shared.show = false;
}
Line 1,558 ⟶ 1,515:
if ( typeof self.rules.inline.show === 'undefined'
&& rules.className.indexOf('wpImageAnnotatorDisplay') >= 0
) ){
{
self.rules.inline.show = true;
}
Line 1,567 ⟶ 1,523:
if ( typeof self.rules.thumbs.show === 'undefined'
&& rules.className.indexOf('wpImageAnnotatorThumbDisplay') >= 0
) ){
{
self.rules.thumbs.show = true;
}
Line 1,577 ⟶ 1,532:
self.rules.thumbs.icon = true;
}
if (rules.className.indexOf('wpImageAnnotatorOnlyLocal') >= 0) {
{
self.rules.shared.show = false;
}
Line 1,642 ⟶ 1,596:
}
} else {
self.imgs_with_notes = document.getElementsByClassName (document, '*', 'wpImageAnnotatorEnable');
if (do_thumbs)
self.thumbs = getElementsByClassName (document, 'div', 'thumbinner'); // No galleries!
self.thumbs = document.getElementsByClassName('thumbinner');
}
if ( wgNamespaceNumber == 6
Line 1,650 ⟶ 1,605:
|| (self.thumbs.length)
|| (self.other_images.length)
) ){
{
// Publish parts of config.
ImageAnnotator.UI = config.UI;
Line 1,662 ⟶ 1,616:
},
 
wait_for_required_libraries : function () {
{
if (typeof Tooltip == 'undefined' || typeof LAPI == 'undefined') {
if (IA.install_attempts++ < IA.max_install_attempts) {
Line 1,676 ⟶ 1,629:
},
 
setup: function () {
{
var self = IA;
self.imgs = [];
Line 1,688 ⟶ 1,640:
)
;
 
var stylepath = mw.config.get('stylepath') || '/skin';
 
// Use this to temporarily display an image off-screen to get its dimensions
var testImgDiv =
LAPI.make('div', null, {
{ display: 'none', position: 'absolute', width: '300px',
, overflow: 'hidden', overflowX: 'hidden', left: '-10000px'
});
);
document.body.insertBefore(testImgDiv, document.body.firstChild);
 
function img_check (img, is_other) {
{
var srcW = parseInt (img.getAttribute('width', 2), 10);
var srcH = parseInt (img.getAttribute('height', 2), 10);
Line 1,726 ⟶ 1,674:
if (w != srcW || h != srcH) return null;
// Exclude system images
if (img.src.contains(conf.stylepath)) return null;
// Only if within a link
if (img.parentNode.nodeName.toLowerCase() != 'a') return null;
Line 1,760 ⟶ 1,708:
file_div = LAPI.$('file');
} else if (!is_thumb && !is_other) {
file_div = scope.getElementsByClassName(scope, 'div', 'wpImageAnnotatorFile');
if (!file_div || file_div.length != 1) return null;
file_div = file_div[0];
Line 1,833 ⟶ 1,781:
}
 
function setup_images (list) {
{
Array.forEach(list,
function (elem) {
Line 1,894 ⟶ 1,841:
var done = 0;
 
function check_done (length) {
{
done += length;
if (done >= names.length) {
Line 1,903 ⟶ 1,849:
}
 
function make_calls (execute_call, url_limit) {
function build_titles (from, length, url_limit) {
{
function build_titles (from, length, url_limit)
{
var done = 0;
var text = '';
Line 1,930 ⟶ 1,874:
}
 
function set_info (json) {
{
try {
if (json && json.query && json.query.pages) {
Line 1,977 ⟶ 1,920:
function (length, titles) {
var idx = ImageAnnotator.info_callbacks.length;
ImageAnnotator.info_callbacks[idx] = {
{ callback : function (json) {
set_info (json);
ImageAnnotator.info_callbacks[idx].done = true;
if (ImageAnnotator.info_callbacks[idx].script) {
LAPI.DOM.removeNode(ImageAnnotator.info_callbacks[idx].script);
ImageAnnotator.info_callbacks[idx].script = null;
}
check_done (length);
},
} done: false
,done : false};
};
ImageAnnotator.info_callbacks[idx].script =
IA.getScript(
Line 2,000 ⟶ 1,943:
// up in that case.
if ( ImageAnnotator.info_callbacks && ImageAnnotator.info_callbacks[idx]
&& ImageAnnotator.info_callbacks[idx].done && ImageAnnotator.info_callbacks[idx].script)
) {
LAPI.DOM.removeNode(ImageAnnotator.info_callbacks[idx].script);
ImageAnnotator.info_callbacks[idx].script = null;
Line 2,029 ⟶ 1,972:
},
 
setup_ui : function () {
{
// Complete the UI object we've gotten from config.
 
Line 2,058 ⟶ 2,000:
};
 
ImageAnnotator.UI.setup = function () {
{
if (ImageAnnotator.UI.repo) return;
var self = ImageAnnotator.UI;
var node = LAPI.make('div', null, { display: 'none' });
var item;
document.body.appendChild(node);
if (typeof UIElements === 'undefined') {
self.basic = true;
self.repo = {};
for (var item in self.defaults) {
node.innerHTML = self.defaults[item];
self.repo[item] = node.firstChild;
Line 2,075 ⟶ 2,017:
self.basic = false;
self.repo = UIElements.emptyRepository(self.defaultLanguage);
for (var item in self.defaults) {
node.innerHTML = self.defaults[item];
UIElements.setEntry(item, self.repo, node.firstChild);
Line 2,085 ⟶ 2,027:
};
 
ImageAnnotator.UI.get = function (id, basic, no_plea) {
{
var self = ImageAnnotator.UI;
if (!self.repo) self.setup();
Line 2,116 ⟶ 2,057:
};
 
ImageAnnotator.UI.get_plea = function () {
{
var self = ImageAnnotator.UI;
var translate = self.get('wpTranslate', false, true) || 'translate';
Line 2,135 ⟶ 2,075:
};
 
ImageAnnotator.UI.init = function (html_text_or_json) {
{
var text;
if (typeof html_text_or_json === 'string')
Line 2,154 ⟶ 2,093:
}
 
var node = LAPI.make('div', null, { display: 'none' });
document.body.appendChild(node);
try {
Line 2,171 ⟶ 2,110:
+ '|live=1}}';
 
function get_ui_no_ajax () {
{
var url =
wgServer + wgScriptPath + '/api.php?format=json&action=parse&pst&text='
+ encodeURIComponent(ui_page) + '&title=API&prop=text&format=json'
+ '&callback=ImageAnnotator.UI.init&maxage=14400&smaxage=14400'
;
Line 2,184 ⟶ 2,122:
}
 
function get_ui () {
{
IA.haveAjax = (LAPI.Ajax.getRequest() != null);
IA.ajaxQueried = true;
Line 2,219 ⟶ 2,156:
},
 
setup_step_two : function () {
{
var self = IA;
 
Line 2,242 ⟶ 2,178:
},
 
complete_setup : function () {
{
// We can be sure to have the UI here because this is called only when the ready event of the
// UI object is fired.
Line 2,260 ⟶ 2,195:
if (self.may_edit) {
// Check whether the image is local. Don't allow editing if the file is remote.
var sharedUpload = document.getElementsByClassName (document, 'div', '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');
getElementsByClassName (self.imgs[0].scope, '*', 'wpImageAnnotatorPageName');
if (img_page_name && img_page_name.length)
img_page_name = LAPI.DOM.getInnerText(img_page_name[0]);
Line 2,289 ⟶ 2,223:
&& !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.
Line 2,299 ⟶ 2,232:
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
}
Line 2,404 ⟶ 2,335:
}
 
function start_tracking (evt) {
{
if (!self.is_tracking) {
self.is_tracking = true;
Line 2,531 ⟶ 2,461:
// API limits and to keep the URL length below the limit for the foreign_repo calls.
 
function make_calls (list, execute_call, url_limit) {
function composer (list, from, length, url_limit) {
{
function composercompose (list, from, length, url_limit) {
{
function compose (list, from, length, url_limit)
{
var text = '';
var done = 0;
Line 2,639 ⟶ 2,566:
}
 
function setup_thumb_viewers (html_text) {
{
var node = LAPI.make('div', null, {display: 'none'});
document.body.appendChild(node);
try {
node.innerHTML = strip_noise (html_text);
var pages = node.getElementsByClassName (node, 'div', 'wpImageAnnotatorInlineImageWrapper');
for (var i = 0; pages && i < pages.length; i++) {
var notes = getElementsByClassName (pages[i], 'div', .getElementsByClassName(self.annotation_class);
if (!notes || notes.length === 0) continue;
var page = self.getItem('inline_name', pages[i]);
if (!page) continue;
page = page.replace(/ /g, '_');
var viewers = cache[page] || cache['File:' + page.substring(page.indexOf(':') + 1)];
if (!viewers || viewers.length === 0) continue;
// Update rules.
var rules = getElementsByClassName (pages[i], 'div', .getElementsByClassName('wpImageAnnotatorInlinedRules');
var local_rules = {
{ inline: Object.clone(IA.rules.inline),
,thumbs: Object.clone(IA.rules.thumbs)
};
if (rules && rules.length) {
rules = rules[0];
if ( typeof local_rules.inline.show === 'undefined'
&& LAPI.DOM.hasClass(rules, 'wpImageAnnotatorNoInlineDisplay')
) ){
{
local_rules.inline.show = false;
}
if ( typeof local_rules.inline.icon === 'undefined'
&& LAPI.DOM.hasClass(rules, 'wpImageAnnotatorInlineDisplayIcon')
) ){
{
local_rules.inline.icon = true;
}
if ( typeof local_rules.thumbs.show === 'undefined'
&& LAPI.DOM.hasClass(rules, 'wpImageAnnotatorNoThumbs')
) ){
{
local_rules.thumbs.show = false;
}
if ( typeof local_rules.thumbs.icon === 'undefined'
&& LAPI.DOM.hasClass(rules, 'wpImageAnnotatorThumbDisplayIcon')
) ){
{
local_rules.thumbs.icon = true;
}
Line 2,716 ⟶ 2,638:
ImageAnnotator.script_callbacks = [];
 
function make_script_calls (list, api) {
{
var template = api + '?action=parse&pst&text=&prop=text&format=json'
+ '&maxage=1800&smaxage=1800&uselang=' + wgUserLanguage //see bugzilla 22764
Line 2,726 ⟶ 2,647:
, function (text) {
var idx = ImageAnnotator.script_callbacks.length;
ImageAnnotator.script_callbacks[idx] = {
{ callback : function (json) {
if (json && json.parse && json.parse.text && json.parse.text['*']) {
setup_thumb_viewers (json.parse.text['*']);
}
ImageAnnotator.script_callbacks[idx].done = true;
if (ImageAnnotator.script_callbacks[idx].script) {
LAPI.DOM.removeNode(ImageAnnotator.script_callbacks[idx].script);
ImageAnnotator.script_callbacks[idx].script = null;
}
},
done: false
};
,done : false
};
ImageAnnotator.script_callbacks[idx].script =
IA.getScript(
Line 2,746 ⟶ 2,667:
);
if ( ImageAnnotator.script_callbacks && ImageAnnotator.script_callbacks[idx]
&& ImageAnnotator.script_callbacks[idx].done && ImageAnnotator.script_callbacks[idx].script)
) {
LAPI.DOM.removeNode(ImageAnnotator.script_callbacks[idx].script);
ImageAnnotator.script_callbacks[idx].script = null;
Line 2,782 ⟶ 2,703:
},
 
show_zoom : function () {
{
var self = IA;
if ( ( self.viewers[0].factors.dx < self.zoom_threshold
Line 2,789 ⟶ 2,709:
)
|| Math.max(self.viewers[0].factors.dx, self.viewers[0].factors.dy) < 2.0
) ){
{
// Below zoom threshold, or full image not even twice the size of the preview
return;
Line 2,880 ⟶ 2,799:
},
 
update_zoom : function (evt) {
{
if (!evt) return; // We need an event to calculate positions!
var self = IA;
Line 2,917 ⟶ 2,835:
},
 
hide_zoom : function (evt) {
{
if (!IA.zoom) return;
if (evt) {
Line 2,927 ⟶ 2,844:
},
 
createHelpLink : function () {
{
var msg = ImageAnnotator.UI.get('wpImageAnnotatorHelp', false, true);
if (!msg || !msg.lastChild) return null;
Line 2,985 ⟶ 2,901:
},
 
get_cover : function () {
{
var self = IA;
var shim;
Line 3,044 ⟶ 2,959:
},
 
show_cover : function () {
{
var self = IA;
if (self.cover && !self.cover_visible) {
Line 3,058 ⟶ 2,972:
},
 
hide_cover : function () {
{
var self = IA;
if (self.cover && self.cover_visible) {
Line 3,072 ⟶ 2,985:
},
 
getRawItem : function (what, scope) {
{
var node = null;
if (!scope || scope == document) {
node = LAPI.$ ('image_annotation_' + what);
} else {
node = scope.getElementsByClassName (scope, '*', 'image_annotation_' + what);
if (node && node.length) node = node[0]; else node = null;
}
Line 3,084 ⟶ 2,996:
},
 
getItem : function (what, scope) {
{
var node = IA.getRawItem(what, scope);
if (!node) return null;
Line 3,091 ⟶ 3,002:
},
 
getIntItem : function (what, scope) {
{
var x = IA.getItem(what, scope);
if (x !== null) x = parseInt (x, 10);
Line 3,098 ⟶ 3,008:
},
 
findNote : function (text, id) {
{
function find (text, id, delim) {
var start = delim.start.replace('$1', id);
Line 3,117 ⟶ 3,026:
},
 
setWikitext : function (pagetext) {
{
var self = IA;
if (self.wiki_read) return;
Line 3,142 ⟶ 3,050:
},
 
setSummary : function (summary, initial_text, note_text) {
{
if (initial_text.contains('$1')) {
var max = (summary.maxlength || 200) - initial_text.length;
Line 3,155 ⟶ 3,062:
},
 
getScript : function (url, bypass_local_cache, bypass_caches) {
{
// Don't use LAPI here, it may not yet be available
if (bypass_caches) {
Line 3,174 ⟶ 3,080:
},
 
canEdit : function () {
{
var self = IA;
if (self.may_edit) {
Line 3,195 ⟶ 3,100:
 
}; // end IA
 
// Backwards compatibility
function getElementsByClassName (scope, tag, className) {
if (window.jQuery) {
return jQuery(scope).find(((!tag || tag === '*') ? '' : tag) + '.' + className);
} else {
// For non-WMF wikis that might not have jQuery (yet), use the wikibits.js getElementsByClassName
return getElementsByClassName(scope, tag, className);
}
}
 
window.ImageAnnotator = {
install: function (config) {
IA.install(config);
}
};
 
// Start it. Bypass caches; but allow for 4 hours client-side caching. Small file.
IA.getScript(
wgScript + '?title=MediaWiki:ImageAnnotatorConfig.js&action=raw&ctype=text/javascript'
// Cache 4 hours
+ '&dummy=' + Math.floor((new Date()).getTime() / (14400 * 1000)) // 4 hours,
, true // No local caching!
true
);