├── .gitignore ├── LICENSE ├── Lazyload.class.php ├── Lazyload.php ├── README.md ├── extension.json ├── i18n ├── en.json ├── zh-hans.json └── zh-hant.json └── modules └── lazyload.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Mudkip.me 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software 4 | and associated documentation files (the "Software"), to deal in the Software without restriction, 5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 6 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 7 | is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 13 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 15 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Lazyload.class.php: -------------------------------------------------------------------------------- 1 | getVal('action') === 'parse') return true; 10 | $url = preg_replace('/^(http|https):/', '', $url); 11 | $img = ' '; 12 | return false; 13 | } 14 | 15 | public static function ThumbnailBeforeProduceHTML($thumb, &$attribs, &$linkAttribs) { 16 | global $wgRequest, $wgTitle; 17 | if (defined('MW_API') && $wgRequest->getVal('action') === 'parse') return true; 18 | if (isset($wgTitle) && $wgTitle->getNamespace() === NS_FILE) return true; 19 | $attribs['data-url'] = $attribs['src']; 20 | $attribs['src'] = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; 21 | if (isset($attribs['srcset'])) { 22 | $attribs['data-srcset'] = $attribs['srcset']; 23 | unset($attribs['srcset']); 24 | } 25 | return true; 26 | } 27 | 28 | public static function BeforePageDisplay($out, $skin) { 29 | $out->addModules( 'ext.lazyload' ); 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Lazyload.php: -------------------------------------------------------------------------------- 1 | 0 && $( this ).height() > 0 28 | && $( window ).scrollTop() - opt.threshold < $( this ).offset().top + $( this ).height() 29 | && $( window ).scrollTop() + $( window ).height() > $( this ).offset().top - opt.threshold ) { 30 | $( this ).trigger( 'appear' ); 31 | } 32 | } ); 33 | }, 200 ); 34 | } 35 | 36 | this.each( function () { 37 | var $this = $( this ); 38 | 39 | $this.one( 'appear', function () { 40 | 41 | if( this.loaded ) { 42 | return; 43 | } 44 | 45 | this.loaded = true; 46 | 47 | if ( $this.data( 'url' ) ) { 48 | var img = this.tagName.toUpperCase() == 'IMG' ? $this : $( '' ); 49 | 50 | img.one( 'load', function ( e ) { 51 | if ( $this.prop( 'tagName' ).toUpperCase() != 'IMG' ) { 52 | $this.html( img ); 53 | } 54 | img.hide()[ opt.effect ](); 55 | if ( $this.hasClass( 'apng' ) && window.APNG ) { 56 | APNG.ifNeeded().then( function () { 57 | APNG.animateImage( img.get( 0 ) ); 58 | } ); 59 | } 60 | } ); 61 | 62 | img.attr( 'src', replaceHost( $this.data( 'url' ) ) ); 63 | if ( img.data( 'srcset' ) && !mw.config.get( 'Lazyload.disableHidpi' ) ) { 64 | img.attr( 'srcset', replaceHost( img.data( 'srcset' ) ) ); 65 | var testImage = new Image(); 66 | 67 | if ( window.devicePixelRatio > 1 && testImage.srcset === undefined ) { 68 | var srcset = img.attr( 'srcset' ), match; 69 | if ( typeof srcset === 'string' && srcset !== '' ) { 70 | match = $.matchSrcSet( devicePixelRatio, srcset ); 71 | if ( match !== null ) { 72 | img.attr( 'src', match ); 73 | } 74 | } 75 | } 76 | } 77 | 78 | // Let other extensions to handle updated content 79 | mw.hook( 'wikipage.content' ).fire( 80 | // images are always wrapped either into `thumb` or `p` 81 | // so it's safe to pass 2nd parent chunk and 82 | // to also make the MultimediaViewer happy 83 | $( img ).parent().parent() 84 | ); 85 | } 86 | 87 | elements = $($.grep(elements, function(element) { 88 | return !element.loaded; 89 | })); 90 | }); 91 | }); 92 | 93 | $( function () { 94 | update(); 95 | } ); 96 | 97 | $( window ).on( 'resize scroll', function () { 98 | update(); 99 | } ); 100 | 101 | $( document ).on( 'mouseup touchend', function () { 102 | update(); 103 | } ); 104 | 105 | return this; 106 | }; 107 | 108 | $( function() { 109 | $( '.external-image, img[data-url]' ).lazyload(); 110 | }); 111 | 112 | }( jQuery, mediaWiki ) ); 113 | --------------------------------------------------------------------------------