MediaWiki:Gadget-ImageAnnotator.js: Difference between revisions
Content deleted Content added
eslint-config-wikimedia autofix |
eslint-config-wikimedia autofix |
||
Line 2:
/*
*/
Line 81:
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 ⟶ 93:
view_y = Math.floor( y / viewer.factors.dy );
this.view = LAPI.make(
'div', null,
{
position: 'absolute',
display: 'none',
Line 145 ⟶ 147:
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 ⟶ 198:
}
}
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 ⟶ 218:
},
display: function ( evt ) {
if ( !this.content ) {
this.content = LAPI.make( 'div' );
Line 240 ⟶ 238:
);
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( 'wpImageAnnotatorDelete', true ),
null,
LAPI.Evt.makeListener( this, this.remove_event )
) );
}
}
Line 329 ⟶ 323:
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:
// 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 ⟶ 488:
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 ⟶ 555:
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 ⟶ 676:
}
this.to_insert =
'|id=' + this.note.model.id +
'|x=' + dim.x + '|y=' + dim.y + '|w=' + dim.w + '|h=' + dim.h +
Line 713 ⟶ 710:
span = IA.findNote( pagetext, self.note.model.id );
}
if ( span ) { // Replace
self.to_insert +
pagetext.substring( span.end );
Line 729 ⟶ 726:
}
if ( lastNote >= 0 ) {
pagetext =
pagetext.substring( 0, lastNote ) + '\n' + self.to_insert +
pagetext.substring( lastNote );
Line 771 ⟶ 769:
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 ⟶ 775:
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 ⟶ 795:
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 ⟶ 805:
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 ⟶ 919:
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 ⟶ 938:
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 ⟶ 946:
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 ⟶ 957:
if (
( this.isThumbnail || this.isOther ) && !this.may_edit &&
(
onlyIcon || this.iconOnly ||
ImageAnnotator_config.inlineImageUsesIndicator(
Line 999 ⟶ 989:
}
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,051:
}
}
if (
!( this.isThumbnail || this.isOther ) || !this.noCaption &&
!IA.hideCaptions &&
Line 1,087 ⟶ 1,078:
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,157:
}
// 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,249:
is_within = !( rect.x >= rect.r || rect.y >= rect.b || // Empty rectangle
);
if ( is_within ) {
Line 1,310 ⟶ 1,302:
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,353:
// 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,367:
}
],
tooltip_styles: { // The style for all our tooltips
border: '1px solid #8888aa',
backgroundColor: '#ffffe0',
Line 1,445 ⟶ 1,435:
if (
typeof list[ i ] === 'string' &&
(
list[ i ] === '*' || namespaceIds[ list[ i ].toLowerCase().replace( / /g, '_' ) ] === namespaceNumber
)
Line 1,476 ⟶ 1,467:
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,520:
// 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,528:
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,631:
// 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,689:
var file_div = scope;
var is_thumb =
scope != document &&
scope.nodeName.toLowerCase() == 'div' &&
LAPI.DOM.hasClass( scope, 'thumbinner' );
Line 1,753 ⟶ 1,757:
}
}
return { scope: scope,
file_div: file_div,
img: img,
Line 1,868 ⟶ 1,871:
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,919:
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:
// 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,942:
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:
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:
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 ⟶ 2,095:
var ui_page = '{{MediaWiki:ImageAnnotatorTexts' +
function get_ui_no_ajax() {
Line 2,181 ⟶ 2,187:
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,215:
// 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 ⟶ 2,330:
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 ⟶ 2,396:
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,573:
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,616:
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 ⟶ 2,650:
};
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,879:
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,892:
var shim;
if ( !self.cover ) {
var pos = { position: 'absolute',
left: '0px',
top: '0px',
Line 2,895 ⟶ 2,901:
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,918:
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,042:
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,071 ⟶ 3,077:
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,104:
// 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!
);
|