User:Kattixie/vector.js

/** * @context {window} * @param {Object} jQuery */ (function( $ ) {

/**    * @example *     $( '.foo' ).slideshow; *    * @context {jQuery} * @param options {Object} * @return {String} jQuery object */   $.fn.slideshow = function( options ) { /*        *         * Private Properties *        */        var _plugin = this; var _fileTemplates = { standard: { description: '#fileinfotpl_desc', date: '#fileinfotpl_date', source: '#fileinfotpl_src', author: '#fileinfotpl_aut', license: '#fileinfotpl_perm .licensetpl' },

simple: { description: '#summary' }       };        /*         *         * Private Methods *        */        var _setUI = function { };       /*         *          * Public Methods *         */        /**         * @context {jQuery} * @param options */       this.init = function( options ) {

$.log( 'Initializing the slideshow.' ); $.log( 'There are ' + this.length + ' images in this article.' ); $.log( 'This article: ' + mw.config.get('wgPageName') ); // Append or override defaults with supplied configuration options. if ( options ) { $.extend( $.fn.slideshow.defaults, options ); }

return this.each( function {

// In this context, $this is the image element. var $this = $( this ), data = $this.data( 'slideshow' );

// If the plugin hasn't been initialized yet, perform one-time setup. if ( ! data ) { var $container = $this.closest( '.thumb' ), file, height, width, aspectRatio, decimals = 0, thumbnailPath, medPath, fullPath, $caption, $section, $subSection; file = $container.find( 'a.image' ).attr( 'href' ).replace( '/wiki/', '' ); data = _plugin.getFileData( file ); height = parseInt( $this.attr( 'height' ), 10 ); width = parseInt( $this.attr( 'width' ), 10 ); if ( height > 0 ) { aspectRatio = width / height; var decimals = aspectRatio - Math.floor( aspectRatio ); $.log( '%s: %d/%d = %f (%f)', 'Calculated aspect ratio', width, height, aspectRatio, decimals ); }                   medHeight = $.fn.slideshow.defaults.medSlideHeight; medWidth = ( Math.round( decimals ) > 0 ) ? Math.ceil( aspectRatio * medHeight ) : Math.floor( aspectRatio * medHeight ); // Todo: Explore better ways to retrieve the full image path, hopefully // without additional API requests. thumbnailPath = $this.attr( 'src' ); medPath = _plugin.getScaled( thumbnailPath, medWidth ); fullPath = _plugin.getScaled( thumbnailPath ); $caption = $container.find( '.thumbcaption' ); $caption.find( '.magnify' ).remove; $section = $container.prevAll( 'h2' ).eq( 0 ).find( '.mw-headline' ); $subSection = $container.prevAll( 'h3' ).eq( 0 ).find( '.mw-headline' );

// Attach plugin data to each image. This is data that is available to us                    // directly from the article. $this.data( 'slideshow', {                       file: file,                        scaled: {                            thumb: {                                path: thumbnailPath,                                height: height,                                width: width                            },                            med: {                                path: medPath,                                height: medHeight,                                width: medWidth                            },                            full: {                                path: fullPath,                                height: null,                                width: null                            }                        },                        aspectRatio: aspectRatio,                        caption: {                            text: $caption.text.trim,                            markup: $caption.html.trim },                       section: $section.text.trim, subSection: $subSection.text.trim } );                   data = $this.data( 'slideshow' );                }                $.log( data );            } ); };       /**         * It would be ideal to retrieve this information via a single API request. We have * access to some data through queries like: *         * http://[lang].wikipedia.org/w/api.php?action=query * &titles=File:Antennae galaxies xl.jpg|File:M51Sketch.jpg * &prop=imageinfo * &iiprop=size|url|timestamp|mime|metadata * &format=json *          * However we also need: description, source, author, licensing information, * and categories. Some of this information may be available through separate requests. *         * There may be a better way to do this, I'd love any feedback from experienced Wiki * members. *         * @context {jQuery} * @param file {String} The name of the file to retrieve data for. */       this.getFileData = function( file ) { if ( ! file ) {               return false; }           $.log( 'Retrieving data for: ' + file ); // On average, this implementation seems to yield 2-10 KB responses. var fileData = {}, params = { action: 'parse', page: file, prop: 'text|categories', format: 'json' };

$.ajax( {               url: $.fn.slideshow.defaults.commonsApiUrl,                cache: true,                dataType: 'jsonp',                data: params,                type: 'GET',                success: function(response) {

if ( response.error === undefined ) { fileData = _plugin.parseFilePage( response ); }               }            } );           /*            var fileData = {};

// On average, this implementation seems to yield 5-15 KB responses. $.ajax( {               url: '/wiki/' + file,                cache: true,                dataType: 'html',                type: 'GET',                success: function(response) {

fileData = _plugin.parseFilePage( response ); }           } );            */            return fileData;        };        /**         * @context {jQuery}         * @param response {String} JSON string retrieved via an API request.         */        this.parseFilePage = function( response ) {

if ( response.parse === undefined ) { return false; }           var $markup = $(response.parse.text[ '*' ]), $description, $date, $author, fileData = {}; $description = $markup.find( _fileTemplates.standard.description ); if ( $description.length ) {               var $descriptionLang = $description.siblings(0).find( '[lang="' + mw.config.get( 'wgUserLanguage' ) + '"]' ); if ( $descriptionLang.length ) {                   $descriptionLang.find( '.language' ).remove; $description = $descriptionLang; }               else {                   $description = $description.siblings(0); $description.find( '.summary' ).remove; }               $date = $markup.find( _fileTemplates.standard.date ).siblings(0); $date.find( 'span' ).remove; $author = $markup.find( _fileTemplates.standard.author ).siblings(0); fileData = { description: $description.html.trim, date: $date.text.trim, author: { name: $author.text.trim, url: $author.find('a').attr('href') }               }            }            else {               $description = $markup.find( _fileTemplates.simple.description ); $.log( '%s: %s', 'Simple', $markup.html ); //fileData.description = $description.html.trim; }

$.log( '%s: %o', 'File Data', fileData ); return fileData; };       this.getScaled = function( path, width ) {

var fileUri = path.replace( $.fn.slideshow.defaults.uploadPath,  ).replace( /^thumb\//,  ); var segments = fileUri.split( '/' ); $.log( 'Segments: %o', segments );

if ( segments.length >= 3 ) { var subFolders = segments[0] + '/' + segments[1]; var fileName = segments[2]; if ( width ) {

return $.fn.slideshow.defaults.uploadPath + 'thumb/' + subFolders + '/' + fileName + '/' + width + 'px-' + fileName; }               else {                   return $.fn.slideshow.defaults.uploadPath + subFolders + '/' + fileName; }           }        };        this.destroy = function { $.log( 'Destroying the slideshow.' ); return this.each( function {               var $this = $(this),                    data = $this.data('slideshow');

$(window).unbind( '.slideshow' ); data.slideshow.remove; $this.removeData( 'slideshow' ); } );       };        this.init( options );    };    /*     *     * Public Properties     *     */    $.extend( $.fn.slideshow, { defaults: { commonsApiUrl: 'http://commons.wikimedia.org/w/api.php', uploadPath: '//upload.wikimedia.org/wikipedia/commons/', medSlideHeight: 600, startIndex: 0 },       i18n: { closeText: 'Close', prevText: 'Prev', nextText: 'Next' }   } );    /*     *     * Log     *     */    /**     * @context {jQuery}     * @param {String|Array|Object|Number} Anything that could be sent to console.log can be      * passed to this function.     * @link http://paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/     * @link http://stackoverflow.com/questions/2653963/why-doesnt-javascript-function-aliasi     * ng-work     */    $.log = function {        if ($.log.defaults.debug === true) {            if ( console === undefined || typeof console.log !== 'function') {

window.console = { log: function {} }; }           console.log.apply( console, arguments ); }   };    $.extend($.log, {        defaults: {            debug: false        },

/**       * @context {$.log} * @param {Object} Properties to append or overwrite the default values for log. */               set: function( options ) {

if ( options ) {

$.extend( this.defaults, options ); }       }    });

} )( jQuery );

jQuery(document).ready( function( $ ) {   $.log.set( { debug: true } );    $.log( '%s: %o', 'Defaults', $.fn.slideshow.defaults );    $( '.thumbimage' ).slideshow; } );