MediaWiki:Gadget-ImageAnnotator.js: Difference between revisions
Content deleted Content added
eslint-config-wikimedia autofix |
Per request |
||
(5 intermediate revisions by 5 users not shown) | |||
Line 1:
/*
*/
Line 81 ⟶ 75:
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 );
}
Line 92 ⟶ 87:
view_y = Math.floor( y / viewer.factors.dy );
this.view = LAPI.make(
'div', null,
{
position: 'absolute',
display: 'none',
Line 145 ⟶ 141:
this.view.appendChild(
LAPI.make(
'div', null
fontSize: '0px', // IE
width: String( Math.max( view_w - 2, 0 ) ) + 'px', // -2 to leave space for the border
Line 196 ⟶ 192:
}
}
if ( this.viewer.tip == tooltip ) { this.viewer.tip = null; }
// Hide all boxes if we're outside the image. Relies on hide checking the
// coordinates! (Otherwise, we'd always hide...)
if ( evt ) { this.viewer.hide( evt ); }
} ).bind( this ),
onopen: ( function ( tooltip ) {
Line 220 ⟶ 212:
},
display: function ( evt ) {
if ( !this.content ) {
this.content = LAPI.make( 'div' );
Line 240 ⟶ 232:
);
this.content.appendChild( this.content.button_section );
this.content.button_section.appendChild( LAPI.DOM.makeLink(
ImageAnnotator.UI.get( 'wpImageAnnotatorEdit', true ),
null,
LAPI.Evt.makeListener( this, this.edit )
) );
if ( ImageAnnotator_config.mayDelete() ) {
this.content.button_section.appendChild( document.createTextNode( '\xa0' ) );
this.content.button_section.appendChild( LAPI.DOM.makeLink(
'#',
ImageAnnotator.UI.get( '
null,
LAPI.Evt.makeListener( this, this.
) );
}
}
Line 329 ⟶ 317:
if ( span.start > 0 ) { char_before = pagetext.charCodeAt( span.start - 1 ); }
if ( span.end < pagetext.length ) { char_after = pagetext.charCodeAt( span.end ); }
if (
String.fromCharCode( char_before ) == '\n' && String.fromCharCode( char_after ) == '\n'
) { span.start = span.start - 1; }
pagetext = pagetext.substring( 0, span.start ) + pagetext.substring( span.end );
textbox.value = pagetext;
var summary = editForm.wpSummary;
if ( !summary ) {
throw new Error( '#Summary field not found. Check that edit pages have valid XHTML.' ); }
IA.setSummary(
summary,
ImageAnnotator.UI.get( 'wpImageAnnotatorRemoveSummary', true ) ||
'[[MediaWiki talk:Gadget-ImageAnnotator.js|Removing image note]]$1',
( reason.length ? reason + ': ' : '' ) + self.model.wiki
);
Line 410 ⟶ 404:
// Respect potential user-defined width setting
if ( window.ImageAnnotationEditor_columns &&
editor_width = window.ImageAnnotationEditor_columns;
}
this.editor = new LAPI.Edit(
{
box: ImageAnnotator.UI.get( 'wpImageAnnotatorEditorLabel', false ),
nullsave: ImageAnnotator_config.mayDelete() ?
ImageAnnotator.UI.get( 'wpImageAnnotatorDelete', true ).capitalizeFirst() :
null,
post: ImageAnnotator.UI.get( 'wpImageAnnotatorCopyright', false )
},
onsave: this.save.bind( this ),
.replace( /\{\{(\s*ImageNote(End)?\s*\|)/g, '{{$1' );
// Guard against people trying to break notes on purpose
if ( text.length && typeof TextCleaner !== 'undefined' ) { text = TextCleaner.sanitizeWikiText( text, true ); }
return text;
}
);
this.box = LAPI.make( 'div' );
this.box.appendChild( this.editor.getView() );
Line 489 ⟶ 482:
this.visible = false;
LAPI.Evt.listenTo( this, this.tooltip.popup, IA.mouse_in,
function ( evt ) {
Array.forEach( IA.viewers, ( function ( viewer ) {
if ( viewer != this.viewer && viewer.visible ) { viewer.hide(); }
Line 556 ⟶ 549:
this.editor.setText( this.note.model.wiki );
}
this.editor.enable( LAPI.Edit.SAVE + LAPI.Edit.PREVIEW + LAPI.Edit.REVERT + LAPI.Edit.CANCEL );
this.editor.textarea.readOnly = false;
this.editor.textarea.style.backgroundColor = 'white';
Line 679 ⟶ 670:
}
this.to_insert =
'|id=' + this.note.model.id +
'|x=' + dim.x + '|y=' + dim.y + '|w=' + dim.w + '|h=' + dim.h +
Line 713 ⟶ 704:
span = IA.findNote( pagetext, self.note.model.id );
}
if ( span ) { // Replace
self.to_insert +
pagetext.substring( span.end );
Line 729 ⟶ 720:
}
if ( lastNote >= 0 ) {
pagetext =
pagetext.substring( 0, lastNote ) + '\n' + self.to_insert +
pagetext.substring( lastNote );
Line 771 ⟶ 763:
if ( !html ) {
if ( doc.isFake && ( typeof doc.dispose === 'function' ) ) { doc.dispose(); }
failureFunc( request, new Error( '#Note not found after saving. Please reload the page.' ) );
return;
}
Line 779 ⟶ 769:
if ( !revision_id ) {
if ( doc.isFake && ( typeof doc.dispose === 'function' ) ) { doc.dispose(); }
failureFunc( request, new Error( '#Version inconsistency after saving. Please reload the page.' ) );
return;
}
Line 801 ⟶ 789:
var idxOfNote = Array.indexOf( self.viewer.annotations, self.note );
if ( idxOfNote + 1 < self.viewer.annotations.length ) {
LAPI.DOM.insertNode( self.note.view, self.viewer.annotations[ idxOfNote + 1 ].view );
}
}
Line 813 ⟶ 799:
IA.is_editing = false;
self.editor.setText( data ); // In case the same note is re-opened: start new undo cycle
}
, function ( request, ex ) {
if ( edit_page.isFake && ( typeof edit_page.dispose === 'function' ) ) { edit_page.dispose(); }
failureFunc( request, ex );
Line 927 ⟶ 913:
var isEnabledImage = LAPI.DOM.hasClass( this.scope, 'wpImageAnnotatorEnable' );
if ( !this.isThumbnail && !this.isOther && !isEnabledImage ) {
this.img_div = LAPI.make( 'div', null, { position: 'relative', width: String( this.thumb.width ) + 'px' } );
var floater = LAPI.make(
cssFloat: ( IA.is_rtl ? 'right' : 'left' ),
position: 'relative' // Fixes IE layout bugs...
}
floater.appendChild( this.img_div );
this.img.parentNode.parentNode.insertBefore( floater, this.img.parentNode );
Line 947 ⟶ 932:
if ( breaker.nextSibling && breaker.nextSibling.nodeName.toLowerCase() == 'br' ) { LAPI.DOM.removeNode( breaker.nextSibling ); }
} else if ( this.isOther || isEnabledImage ) {
this.img_div = LAPI.make( 'div', null, { position: 'relative', width: String( this.thumb.width ) + 'px' } );
this.img.parentNode.parentNode.insertBefore( this.img_div, this.img.parentNode );
this.img_div.appendChild( this.img.parentNode );
Line 956 ⟶ 940:
this.file_div.appendChild( this.img_div );
} else { // Thumbnail
this.img_div = LAPI.make(
{ className: '
{ position: 'relative', width: String( this.thumb.width ) + 'px' }
);
this.img.parentNode.parentNode.insertBefore( this.img_div, this.img.parentNode );
this.img.style.border = 'none';
Line 968 ⟶ 951:
if (
( this.isThumbnail || this.isOther ) && !this.may_edit &&
(
onlyIcon || this.iconOnly ||
ImageAnnotator_config.inlineImageUsesIndicator(
Line 999 ⟶ 983:
}
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,061 ⟶ 1,045:
}
}
if (
!( this.isThumbnail || this.isOther ) || !this.noCaption &&
!IA.hideCaptions &&
Line 1,087 ⟶ 1,072:
curStyle = ( simple ? window.getComputedStyle( up, null ) : ( up.currentStyle || up.style ) );
// "up.style" is actually incorrect, but a best-effort fallback.
var overflow = Array.any( checks, function ( t ) {
} );
if ( overflow ) {
if ( !this.overflowParents ) { this.overflowParents = [ up ]; } else { this.overflowParents[ this.overflowParents.length ] = up; }
Line 1,167 ⟶ 1,151:
}
// 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 = String( view_y ) + 'px';
node.style.left = String( view_x ) + 'px';
Line 1,257 ⟶ 1,243:
is_within = !( rect.x >= rect.r || rect.y >= rect.b || // Empty rectangle
);
if ( is_within ) {
Line 1,310 ⟶ 1,296:
if ( this.annotations && this.annotations.length && this.msg ) {
LAPI.DOM.removeChildren( this.msg );
this.msg.appendChild( ImageAnnotator.UI.get( 'wpImageAnnotatorHasNotesMsg', false ) );
if ( this.realName && typeof this.realName === 'string' && this.realName.length ) {
var otherPageMsg = ImageAnnotator.UI.get( 'wpImageAnnotatorEditNotesMsg', false );
Line 1,363 ⟶ 1,347:
// important, because the old format also used the ImageNote template, but for a different
// purpose.
note_delim:
{
start: '<div id="image_annotation_note_$1"',
Line 1,377 ⟶ 1,361:
}
],
tooltip_styles: { // The style for all our tooltips
border: '1px solid #8888aa',
backgroundColor: '#ffffe0',
Line 1,445 ⟶ 1,429:
if (
typeof list[ i ] === 'string' &&
(
list[ i ] === '*' || namespaceIds[ list[ i ].toLowerCase().replace( / /g, '_' ) ] === namespaceNumber
)
Line 1,476 ⟶ 1,461:
self.rules.thumbs.show = false;
}
if ( mw.config.get( 'wgNamespaceNumber' ) == 6 ) {
self.rules.shared.show = true; } else if ( !config.sharedImagesEnabled() || ) {
self.rules.shared.show = false;
Line 1,527 ⟶ 1,514:
// Make sure the shared value is set
self.rules.shared.show = typeof self.rules.shared.show === 'undefined' || self.rules.shared.show;
var do_thumbs = typeof self.rules.thumbs.show === 'undefined' || self.rules.thumbs.show;
Line 1,536 ⟶ 1,522:
document.getElementById( 'mw_contentholder' ) || // modern
document.getElementById( 'article' ); // old skins
if ( bodyContent ) {
var all_imgs = bodyContent.getElementsByTagName( 'img' );
// This prevents traversing a page with more than 400 images
// There are extreme cases like [[Emoji]] that high number of images can cause
// huge lag specially on Chrome
if ( all_imgs.length > 400 ) {
// purging the array, simply a hack to avoid more indention
all_imgs = [];
}
for ( var i = 0; i < all_imgs.length; i++ ) {
// Exclude all that are in img_with_notes or in thumbs. Also exclude all in galleries.
Line 1,629 ⟶ 1,625:
// Use this to temporarily display an image off-screen to get its dimensions
var testImgDiv = LAPI.make(
{
display: 'none', position: 'absolute', width: '300px',
overflow: 'hidden', overflowX: 'hidden', left: '-10000px'
}
);
document.body.insertBefore( testImgDiv, document.body.firstChild );
Line 1,685 ⟶ 1,683:
var file_div = scope;
var is_thumb =
scope != document &&
scope.nodeName.toLowerCase() == 'div' &&
LAPI.DOM.hasClass( scope, 'thumbinner' );
Line 1,737 ⟶ 1,735:
}
}
if ( name.search( /\.(jpe?g|png|gif|svg|tiff?|webp)$/i ) < 0 ) { return null; } // Only PNG, JPE?G, GIF, SVG,
// Finally check for wpImageAnnotatorControl
var icon_only = false;
Line 1,753 ⟶ 1,751:
}
}
return { scope: scope,
file_div: file_div,
img: img,
Line 1,868 ⟶ 1,865:
if ( !indices ) { return; }
Array.forEach(
indices
, function ( i ) {
self.imgs[ i ].full_img = { width: info.imageinfo[ 0 ].width,
self.imgs[ i ].has_page = ( typeof info.missing === 'undefined' );
self.imgs[ i ].isLocal = !info.imagerepository || info.imagerepository == 'local';
Line 1,918 ⟶ 1,913:
done: false
};
ImageAnnotator.info_callbacks[ idx ].script = IA.getScript(
template.replace( 'info_callbacks[].callback', 'info_callbacks[' + idx + '].callback' )
.replace( '&titles=&', '&titles=' + titles + '&' ),
Line 1,928 ⟶ 1,922:
// script (and call the callback) synchronously before the assignment is done. Clean
// up in that case.
if (
ImageAnnotator.info_callbacks && ImageAnnotator.info_callbacks[ idx ] && ImageAnnotator.info_callbacks[ idx ].done && ImageAnnotator.info_callbacks[ idx ].script
) {
Line 1,941 ⟶ 1,936:
function ( length, titles ) {
LAPI.Ajax.apiGet(
'query'
, { titles: titles,
prop: 'info|imageinfo',
inprop: 'protection',
iiprop: 'size'
}
, function ( request, json_result ) {
set_info( json_result );
check_done( length );
}
, function () { check_done( length ); }
);
}
Line 2,051 ⟶ 2,045:
LAPI.DOM.makeLink(
mw.config.get( 'wgServer' ) + mw.config.get( 'wgScript' ) + '?title=MediaWiki_talk:ImageAnnotatorTexts' +
translate,
( typeof translate === 'string' ? translate : LAPI.DOM.getInnerText( translate ).trim() )
Line 2,063 ⟶ 2,057:
ImageAnnotator.UI.init = function ( html_text_or_json ) {
var text;
if ( typeof html_text_or_json === 'string' ) {
} else if (
typeof html_text_or_json !== 'undefined' &&
typeof html_text_or_json.parse !== 'undefined' &&
typeof html_text_or_json.parse.text !== 'undefined' &&
typeof html_text_or_json.parse.text[ '*' ] !== 'undefined'
) {
text = html_text_or_json.parse.text[ '*' ]; } else { text = null; }
if ( !text ) {
Line 2,089:
var ui_page = '{{MediaWiki:ImageAnnotatorTexts' +
function get_ui_no_ajax() {
Line 2,181:
if ( self.may_edit && mw.config.get( 'wgNamespaceNumber' ) != 6 ) {
// Only allow edits if the stored page name matches the current one.
var img_page_name = getElementsByClassName( self.imgs[ 0 ].scope, '*', '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, '_' ) == mw.config.get( 'wgTitle' ).replace( / /g, '_' ) );
Line 2,210 ⟶ 2,209:
// 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
) {
Line 2,324:
self.base_y = mouse_pos.y - origin.y;
Object.merge(
{ left: String( self.base_x ) + 'px',
top: String( self.base_y ) + 'px',
width: '0px',
height: '0px',
display: ''
}
, self.definer.style );
// Set mouse handlers
Line 2,390:
LAPI.Evt.attach( cover, self.mouse_out, self.hide_zoom_evt );
LAPI.DOM.removeChildren( self.viewers[ 0 ].msg );
self.viewers[ 0 ].msg.appendChild( ImageAnnotator.UI.get( 'wpImageAnnotatorDrawRectMsg', false ) );
self.viewers[ 0 ].msg.style.display = '';
}
Line 2,569 ⟶ 2,567:
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' )
) {
Line 2,608 ⟶ 2,610:
if ( !self.viewers[ v ].isThumbnail || local_rules.thumbs.show ) {
self.viewers[ v ].scope = pages[ i ];
self.viewers[ v ].setup( self.viewers[ v ].isThumbnail && local_rules.thumbs.icon ||
}
} );
Line 2,644:
};
ImageAnnotator.script_callbacks[ idx ].script =
IA.getScript(
template.replace( 'script_callbacks[].callback', 'script_callbacks[' + idx + '].callback' )
.replace( '
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,872 ⟶ 2,873:
if ( text.nodeName.toLowerCase() === 'span' ) { text = LAPI.DOM.getInnerText( text ); } else { text = 'Help'; }
return LAPI.DOM.makeButton(
'ImageAnnotationHelpButton'
, make_handler( tgt )
);
} else {
Line 2,885 ⟶ 2,886:
var shim;
if ( !self.cover ) {
var pos = { position: 'absolute',
left: '0px',
top: '0px',
Line 2,895:
self.border = self.cover.cloneNode( false );
Object.merge(
{ border: '3px solid green', top: '-3px', left: '-3px' }, self.border.style );
self.cover.style.zIndex = 2000; // Above the tooltips
if ( LAPI.Browser.is_ie ) {
Line 2,914 ⟶ 2,912:
shim = LAPI.make( 'div', null, pos );
Object.merge(
{ top: '0px',
backgroundImage: 'url(' + self.viewers[ 0 ].img.src + ')',
zIndex: imgZ + 2
}
, shim.style );
self.ieFix2 = shim;
Line 3,038 ⟶ 3,036:
if ( note_text ) {
initial_text =
initial_text.replace( '$1', ': ' + note_text.replace( '\n', ' ' ).substring( 0, max ) );
} else {
initial_text = initial_text.replace( '$1', '' ); }
}
summary.value = initial_text;
Line 3,058:
return s;
} else {
return
}
},
Line 3,071:
if ( !self.may_edit && self.button_div ) {
LAPI.DOM.removeChildren( self.button_div );
self.button_div.appendChild( ImageAnnotator.UI.get( 'wpImageAnnotatorCannotEditMsg', false ) );
self.viewers[ 0 ].msg.style.display = '';
self.viewers[ 0 ].cannotEdit();
Line 3,100 ⟶ 3,098:
// Start it. Bypass caches; but allow for 4 hours client-side caching. Small file.
IA.getScript(
mw.config.get( 'wgScript' ) + '?title=MediaWiki:ImageAnnotatorConfig.js&action=raw&ctype=text/javascript'
true // No local caching!
);
Line 3,108 ⟶ 3,105:
} // end if (guard against double inclusions)
|