gplx/mediawiki/extensions/SemanticMediaWiki/res/smw/special/ext.smw.special.ask.js

394 lines
9.9 KiB
JavaScript

/**
* This file is part of the Semantic MediaWiki Special:Ask module
* @see https://semantic-mediawiki.org/
*
* @section LICENSE
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* @file
* @ignore
*
* @since 1.9
* @ingroup SMW
*
* @licence GNU GPL v2+
* @author: Jeroen De Dauw <jeroendedauw at gmail dot com>
* @author mwjames
*/
( function( $, mw, smw ) {
'use strict';
/**
* @since 3.0
* @constructor
*
* @return {this}
*/
var change = function ( name ) {
this.name = name;
this.messages = {};
this.html = mw.html;
// Message box is server-rendered in LinksWidget.php
this.messageBox = $( '.smw-ask-change-info' );
// Default state is "notice"
this.messageBoxType = 'notice';
this.hideList = '#ask-embed, #inlinequeryembed, #ask-showhide,' +
'#ask-debug, #ask-clipboard, #ask-navinfo, #ask-cache, #result,' +
'.smw-error-result-error, #ask-pagination, #ask-export-links, #tab-label-smw-askt-compact,' +
'#tab-label-smw-askt-code, #tab-label-smw-askt-debug, #tab-label-smw-askt-extra,' +
'#tab-label-smw-askt-result, #tab-label-smw-askt-clipboard, #search';
return this;
};
/**
* @since 3.0
* @method
*
* @param {Sting} key
* @param {Sting} message
*/
change.prototype.add = function( key, message, type ) {
this.messages[key] = [ message, type ];
};
/**
* @since 3.0
* @method
*
* @param {Sting} key
*/
change.prototype.delete = function( key ) {
delete this.messages[key];
};
/**
* @since 3.0
* @method
*
* @param {Sting} key
*/
change.prototype.informAbout = function( key ) {
var informAbout = '';
// Anything to inform about?
if ( this.messages.hasOwnProperty( key ) ) {
informAbout = key;
} else {
for( var prop in this.messages ) {
if ( prop !== key && this.messages.hasOwnProperty( prop ) ) {
informAbout = prop;
}
}
}
if ( informAbout !== '' ) {
this.show( informAbout );
} else {
this.hide();
}
};
/**
* @since 3.0
* @method
*
* @param {Sting} key
*/
change.prototype.show = function( key ) {
$( this.hideList ).hide();
var msg = this.messages[key];
var msgType = msg[1];
var messageBox = this.messageBox;
// Remove old type class and add new one
messageBox.removeClass( 'smw-message-' + this.messageBoxType )
.addClass( 'smw-message-' + msgType );
messageBox.attr( 'id', 'status-format-change' );
// Clear existing content before adding new message
messageBox.find( '.smw-message-content' )
.empty()
.append( mw.msg( msg[0], this.name ) );
messageBox.removeClass( 'smw-message--hidden' );
this.messageBoxType = msgType;
};
/**
* @since 3.0
* @method
*/
change.prototype.hide = function() {
$( this.hideList ).show();
$( '#inlinequeryembed, #embed_hide' ).hide();
$( '#embed_show' ).show();
// Reset message box to inital state
var msgType = 'notice';
var messageBox = this.messageBox;
messageBox.addClass( 'smw-message--hidden' );
// Remove old type class and add new one
messageBox.removeClass( 'smw-message-' + this.messageBoxType )
.addClass( 'smw-message-' + msgType );
messageBox.removeAttr( 'id' );
messageBox.find( '.smw-message-content' ).empty();
this.messageBoxType = msgType;
};
/**
* Support and helper methods
* @ignore
*/
var tooltip = smw.Factory.newTooltip();
var _init = {
// Tooltip
tooltip: function(){
$( '.smw-ask-info' ).each( function(){
tooltip.show( {
context: $( this ),
content: $( this ).data( 'info' ),
title : mw.msg( 'smw-ui-tooltip-title-parameter' ),
button : false
} );
} );
$( '#options-list' ).trigger( 'smw.autocomplete.propertysubject', { context: $( '#options-list' ) } );
$( '#options-list' ).trigger( 'smw.autocomplete.property', { context: $( '#options-list' ) } );
},
// Format help link
formatHelp: function( options ){
$( '.smw-ask-format-help-link' ).replaceWith(
'<li class="smw-ask-format-help-link">'+ mw.msg( 'smw-ask-format-selection-help', addFormatHelpLink( options ) ) + '</li>'
);
}
};
/**
* Add format help link
*
* We do not try to be smart here but using a pragmatic approach to generate
* the URL by assuming Help:<format> format
*
* @return object
*/
function addFormatHelpLink ( options ){
var h = mw.html,
link = h.element( 'a', {
href: 'https://semantic-mediawiki.org/wiki/Help:' + options.format + ' format',
title: options.name
}, options.name
);
return link;
}
/**
* Multiple sorting
*/
var num_elements = $( '#sorting_main > div' ).length;
function addSortInstance(starter_div_id, main_div_id) {
num_elements++;
var starter_div = $( '#' + starter_div_id),
main_div = $( '#' + main_div_id),
new_div = starter_div.clone();
new_div.attr( {
'class': 'smw-ask-sort-input multipleTemplate',
'id': 'sort_div_' + num_elements
} );
new_div.css( 'display', 'block' );
//Create 'delete' link
var button = $( '<a>').attr( {
'class': 'smw-ask-sort-delete-action',
'data-target': 'sort_div_' + num_elements
} ).text( mw.msg( 'smw-ask-delete' ) );
// Register event on the added instance
button.click( function( event ) {
removeInstance( $( this ).data( 'target' ) );
} );
new_div.append(
$( '<span class="smw-ask-sort-delete">' ).html( button )
);
// Trigger an event to ensure that the input field has an autocomplete
// instance attached
main_div.trigger( 'SMW::Property::Autocomplete' , {
'context': new_div
} );
// Add the new instance
main_div.append( new_div );
}
function removeInstance(div_id) {
$( '#' + div_id ).remove();
}
/**
* Implementation of an Special:Ask instance
* @since 1.8
* @ignore
*/
$( document ).ready( function() {
var condition = $( '#ask-query-condition' ),
condVal = '',
isEmpty = '';
if ( condition.length ) {
condVal = condition.val().trim(),
isEmpty = condVal === '';
var entitySuggester = smw.Factory.newEntitySuggester(
condition
);
// Register autocomplete default tokens
entitySuggester.registerDefaultTokenList(
[
'property',
'concept',
'category'
]
);
};
// Field input is kept disabled until JS is fully loaded to signal
// "ready for input"
$( '#ask, #result' ).removeClass( 'is-disabled' );
// Get initial format and language settings
var selected = $( '#formatSelector option:selected' ),
options = {
selector : '#formatSelector',
format : selected.val(),
name : selected.text(),
isExport: selected.data( 'isexport' ) == 1
};
var chg = new change( options['name'] );
// Init
_init.tooltip();
_init.formatHelp( options );
$( '.smw-ask-sort-delete-action' ).click( function() {
removeInstance( $( this).data( 'target' ) );
} );
$( '.smw-ask-sort-add-action' ).click( function() {
addSortInstance( 'sorting_starter', 'sorting_main' );
} );
// Options toggle icon
$( '.options-toggle-action label' ).click( function() {
if ( $( '#options-toggle' ).prop( 'checked' ) ) {
$( this ).html( '+' );
$( this ).attr( 'title', mw.msg( 'smw-section-expand' ) );
} else {
$( this ).html( '-' );
$( this ).attr( 'title', mw.msg( 'smw-section-collapse' ) );
}
} );
// `CTRL + q` shortcut support to invoke a query/search with a keystroke
// Char check for `q` means in:
// - Chrome: event.charCode == 17
// - FF: event.charCode == 113
$( "#mw-content-text" ).keypress( function ( event ) {
if ( event.ctrlKey && ( event.charCode == 17 || event.charCode == 113 ) ) {
$( '#search-action' ).click();
event.preventDefault();
return false;
};
return true;
} );
// Changed condition
$( '#ask-query-condition' ).change( function( event, $opts ) {
var $this = $( this );
if ( isEmpty === false && $this.val().trim() !== condVal ) {
chg.add( 'condition', 'smw-ask-condition-change-info', 'warning' );
} else {
chg.delete( 'condition' );
}
chg.informAbout( 'condition' );
} );
// Change format parameter form via ajax
$( '#formatSelector' ).change( function( event, $opts ) {
var $this = $( this ),
isExport = $this.find( 'option:selected' ).data( 'isexport' ) == 1;
// Opaque options list for as long as the list is being generated
// via an ajax request
$( '#options-list' ).addClass( 'is-disabled' );
if ( isExport ) {
chg.add( 'format', 'smw-ask-format-export-info', 'info' );
} else if ( isEmpty === false && options['format'] !== $this.val() ) {
chg.add( 'format', 'smw-ask-format-change-info', 'warning' );
} else {
chg.delete( 'format' );
}
chg.informAbout( 'format' );
$.ajax( {
// Evil hack to get more evil Spcial:Ask stuff to work with less evil JS.
'url': $this.data( 'url' ).replace( 'this.value', $this.val() ),
'context': document.body,
'success': function( data ) {
$( '#options-list' ).html(
'<div class="options-parameter-list">' + data + '</div>'
);
// Remove disable state that was set at the beginning of the
// onChange event
$( '#options-list' ).removeClass( 'is-disabled' );
// Reinitialize functions after each ajax request
_init.tooltip();
// Update format created by the ajax instance
_init.formatHelp( $.extend( {}, options, {
format: $this.val(),
name: $this.find( 'option:selected' ).text()
} ) );
}
} );
} );
} );
} )( jQuery, mediaWiki, semanticMediaWiki );