/** * 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 * @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( '' ); } }; /** * 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 * * @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 = $( '').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( $( '' ).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( '
' + data + '
' ); // 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 );