mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-25 23:05:35 +00:00
205 lines
4.8 KiB
JavaScript
205 lines
4.8 KiB
JavaScript
|
/*!
|
||
|
* VisualEditor UserInterface MWMediaSelectWidget class.
|
||
|
*
|
||
|
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
|
||
|
* @license The MIT License (MIT); see LICENSE.txt
|
||
|
*/
|
||
|
|
||
|
/*global mw*/
|
||
|
|
||
|
/**
|
||
|
* Creates an ve.ui.MWMediaSelectWidget object.
|
||
|
*
|
||
|
* @class
|
||
|
* @extends ve.ui.Widget
|
||
|
*
|
||
|
* @constructor
|
||
|
* @param {Object} [config] Config options
|
||
|
* @param {number} [size] Vertical size of thumbnails
|
||
|
*/
|
||
|
ve.ui.MWMediaSelectWidget = function VeUiMWMediaSelectWidget( config ) {
|
||
|
// Configuration intialization
|
||
|
config = config || {};
|
||
|
|
||
|
// Parent constructor
|
||
|
ve.ui.Widget.call( this, config );
|
||
|
|
||
|
// Properties
|
||
|
this.input = new ve.ui.TextInputWidget( {
|
||
|
'$$': this.$$,
|
||
|
'placeholder': ve.msg( 'visualeditor-media-input-placeholder' ),
|
||
|
'value': mw.config.get( 'wgTitle' ),
|
||
|
'icon': 'search'
|
||
|
} );
|
||
|
this.select = new ve.ui.SelectWidget( { '$$': this.$$ } );
|
||
|
this.$query = this.$$( '<div>' );
|
||
|
this.$results = this.$$( '<div>' );
|
||
|
|
||
|
this.sources = ve.copyArray( ve.init.platform.getMediaSources() );
|
||
|
this.size = config.size || 150;
|
||
|
this.inputTimeout = null;
|
||
|
this.titles = {};
|
||
|
this.queryMediaSourcesCallback = ve.bind( this.queryMediaSources, this );
|
||
|
|
||
|
// Events
|
||
|
this.input.connect( this, { 'change': 'onInputChange' } );
|
||
|
this.select.connect( this, { 'select': 'onSelectSelect' } );
|
||
|
this.$results.on( 'scroll', ve.bind( this.onResultsScroll, this ) );
|
||
|
|
||
|
// Initialization
|
||
|
this.$query
|
||
|
.addClass( 've-ui-mwMediaSelectWidget-query' )
|
||
|
.append( this.input.$ );
|
||
|
this.$results
|
||
|
.addClass( 've-ui-mwMediaSelectWidget-results' )
|
||
|
.append( this.select.$ );
|
||
|
this.$
|
||
|
.addClass( 've-ui-mwMediaSelectWidget' )
|
||
|
.append( this.$results, this.$query );
|
||
|
this.queryMediaSources();
|
||
|
};
|
||
|
|
||
|
/* Inheritance */
|
||
|
|
||
|
ve.inheritClass( ve.ui.MWMediaSelectWidget, ve.ui.Widget );
|
||
|
|
||
|
/* Events */
|
||
|
|
||
|
/**
|
||
|
* @event select
|
||
|
* @param {Object} item Media item info
|
||
|
*/
|
||
|
|
||
|
/* Methods */
|
||
|
|
||
|
/**
|
||
|
* Handle select widget select events.
|
||
|
*
|
||
|
* @param {string} value New value
|
||
|
*/
|
||
|
ve.ui.MWMediaSelectWidget.prototype.onInputChange = function () {
|
||
|
var i, len;
|
||
|
|
||
|
if ( this.loading || this.input.getValue() === '' ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Reset
|
||
|
this.select.clearItems();
|
||
|
for ( i = 0, len = this.sources.length; i < len; i++ ) {
|
||
|
delete this.sources[i].gsroffset;
|
||
|
}
|
||
|
|
||
|
// Queue
|
||
|
clearTimeout( this.inputTimeout );
|
||
|
this.inputTimeout = setTimeout( this.queryMediaSourcesCallback, 100 );
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handle select widget select events.
|
||
|
*
|
||
|
* @param {ve.ui.MWMediaSelectItemWidget} item Selected item
|
||
|
* @emits select
|
||
|
*/
|
||
|
ve.ui.MWMediaSelectWidget.prototype.onSelectSelect = function ( item ) {
|
||
|
this.emit( 'select', item ? item.getData() : null );
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handle results scroll events.
|
||
|
*
|
||
|
* @param {jQuery.Event} e Scroll event
|
||
|
*/
|
||
|
ve.ui.MWMediaSelectWidget.prototype.onResultsScroll = function () {
|
||
|
var position = this.$results.scrollTop() + this.$results.outerHeight(),
|
||
|
threshold = this.select.$.outerHeight() - this.size;
|
||
|
if ( !this.input.isPending() && position > threshold ) {
|
||
|
this.queryMediaSources();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Query all sources for media.
|
||
|
*
|
||
|
* @method
|
||
|
*/
|
||
|
ve.ui.MWMediaSelectWidget.prototype.queryMediaSources = function () {
|
||
|
var i, len, source;
|
||
|
|
||
|
for ( i = 0, len = this.sources.length; i < len; i++ ) {
|
||
|
source = this.sources[i];
|
||
|
if ( source.request ) {
|
||
|
source.request.abort();
|
||
|
}
|
||
|
if ( !source.gsroffset ) {
|
||
|
source.gsroffset = 0;
|
||
|
}
|
||
|
this.input.pushPending();
|
||
|
source.request = $.ajax( {
|
||
|
'url': source.url,
|
||
|
'data': {
|
||
|
'format': 'json',
|
||
|
'action': 'query',
|
||
|
'generator': 'search',
|
||
|
'gsrsearch': this.input.getValue(),
|
||
|
'gsrnamespace': 6,
|
||
|
'gsrlimit': 15,
|
||
|
'gsroffset': source.gsroffset,
|
||
|
'prop': 'imageinfo',
|
||
|
'iiprop': 'dimensions|url',
|
||
|
'iiurlheight': this.size
|
||
|
},
|
||
|
'dataType': 'jsonp'
|
||
|
} )
|
||
|
.always( ve.bind( this.onMediaQueryAlways, this, source ) )
|
||
|
.done( ve.bind( this.onMediaQueryDone, this, source ) );
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handle media query response events.
|
||
|
*
|
||
|
* @method
|
||
|
* @param {Object} source Media query source
|
||
|
*/
|
||
|
ve.ui.MWMediaSelectWidget.prototype.onMediaQueryAlways = function ( source ) {
|
||
|
source.request = null;
|
||
|
this.input.popPending();
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Handle media query load events.
|
||
|
*
|
||
|
* @method
|
||
|
* @param {Object} source Media query source
|
||
|
* @param {Object} data Media query response
|
||
|
*/
|
||
|
ve.ui.MWMediaSelectWidget.prototype.onMediaQueryDone = function ( source, data ) {
|
||
|
if ( !data.query || !data.query.pages ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var page, title,
|
||
|
items = [],
|
||
|
pages = data.query.pages;
|
||
|
|
||
|
if ( data['query-continue'] && data['query-continue'].search ) {
|
||
|
source.gsroffset = data['query-continue'].search.gsroffset;
|
||
|
}
|
||
|
|
||
|
for ( page in pages ) {
|
||
|
title = pages[page].title;
|
||
|
if ( !( title in this.titles ) ) {
|
||
|
this.titles[title] = true;
|
||
|
items.push(
|
||
|
new ve.ui.MWMediaSelectItemWidget(
|
||
|
pages[page],
|
||
|
{ '$$': this.$$, 'size': this.size }
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.select.addItems( items );
|
||
|
};
|