Código fuente de WordPress - jquery-plugins (jquery.masonry-2.1.05.js)

1	/**
2	 * jQuery Masonry v2.1.05
3	 * A dynamic layout plugin for jQuery
4	 * The flip-side of CSS Floats
5	 * http://masonry.desandro.com
6	 *
7	 * Licensed under the MIT license.
8	 * Copyright 2012 David DeSandro
9	 */
10	
11	/*jshint browser: true, curly: true, eqeqeq: true, forin: false, immed: false, newcap: true, noempty: true, strict: true, undef: true */
12	/*global jQuery: false */
13	
14	(function( window, $, undefined ){
15	
16	  'use strict';
17	
18	  /*
19	   * smartresize: debounced resize event for jQuery
20	   *
21	   * latest version and complete README available on Github:
22	   * https://github.com/louisremi/jquery.smartresize.js
23	   *
24	   * Copyright 2011 @louis_remi
25	   * Licensed under the MIT license.
26	   */
27	
28	  var $event = $.event,
29	      resizeTimeout;
30	
31	  $event.special.smartresize = {
32	    setup: function() {
33	      $(this).bind( "resize", $event.special.smartresize.handler );
34	    },
35	    teardown: function() {
36	      $(this).unbind( "resize", $event.special.smartresize.handler );
37	    },
38	    handler: function( event, execAsap ) {
39	      // Save the context
40	      var context = this,
41	          args = arguments;
42	
43	      // set correct event type
44	      event.type = "smartresize";
45	
46	      if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
47	      resizeTimeout = setTimeout(function() {
48	        $.event.handle.apply( context, args );
49	      }, execAsap === "execAsap"? 0 : 100 );
50	    }
51	  };
52	
53	  $.fn.smartresize = function( fn ) {
54	    return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
55	  };
56	
57	
58	
59	// ========================= Masonry ===============================
60	
61	
62	  // our "Widget" object constructor
63	  $.Mason = function( options, element ){
64	    this.element = $( element );
65	
66	    this._create( options );
67	    this._init();
68	  };
69	
70	  $.Mason.settings = {
71	    isResizable: true,
72	    isAnimated: false,
73	    animationOptions: {
74	      queue: false,
75	      duration: 500
76	    },
77	    gutterWidth: 0,
78	    isRTL: false,
79	    isFitWidth: false,
80	    containerStyle: {
81	      position: 'relative'
82	    }
83	  };
84	
85	  $.Mason.prototype = {
86	
87	    _filterFindBricks: function( $elems ) {
88	      var selector = this.options.itemSelector;
89	      // if there is a selector
90	      // filter/find appropriate item elements
91	      return !selector ? $elems : $elems.filter( selector ).add( $elems.find( selector ) );
92	    },
93	
94	    _getBricks: function( $elems ) {
95	      var $bricks = this._filterFindBricks( $elems )
96	        .css({ position: 'absolute' })
97	        .addClass('masonry-brick');
98	      return $bricks;
99	    },
100	   
101	    // sets up widget
102	    _create : function( options ) {
103	     
104	      this.options = $.extend( true, {}, $.Mason.settings, options );
105	      this.styleQueue = [];
106	
107	      // get original styles in case we re-apply them in .destroy()
108	      var elemStyle = this.element[0].style;
109	      this.originalStyle = {
110	        // get height
111	        height: elemStyle.height || ''
112	      };
113	      // get other styles that will be overwritten
114	      var containerStyle = this.options.containerStyle;
115	      for ( var prop in containerStyle ) {
116	        this.originalStyle[ prop ] = elemStyle[ prop ] || '';
117	      }
118	
119	      this.element.css( containerStyle );
120	
121	      this.horizontalDirection = this.options.isRTL ? 'right' : 'left';
122	
123	      this.offset = {
124	        x: parseInt( this.element.css( 'padding-' + this.horizontalDirection ), 10 ),
125	        y: parseInt( this.element.css( 'padding-top' ), 10 )
126	      };
127	     
128	      this.isFluid = this.options.columnWidth && typeof this.options.columnWidth === 'function';
129	
130	      // add masonry class first time around
131	      var instance = this;
132	      setTimeout( function() {
133	        instance.element.addClass('masonry');
134	      }, 0 );
135	     
136	      // bind resize method
137	      if ( this.options.isResizable ) {
138	        $(window).bind( 'smartresize.masonry', function() { 
139	          instance.resize();
140	        });
141	      }
142	
143	
144	      // need to get bricks
145	      this.reloadItems();
146	
147	    },
148	 
149	    // _init fires when instance is first created
150	    // and when instance is triggered again -> $el.masonry();
151	    _init : function( callback ) {
152	      this._getColumns();
153	      this._reLayout( callback );
154	    },
155	
156	    option: function( key, value ){
157	      // set options AFTER initialization:
158	      // signature: $('#foo').bar({ cool:false });
159	      if ( $.isPlainObject( key ) ){
160	        this.options = $.extend(true, this.options, key);
161	      } 
162	    },
163	   
164	    // ====================== General Layout ======================
165	
166	    // used on collection of atoms (should be filtered, and sorted before )
167	    // accepts atoms-to-be-laid-out to start with
168	    layout : function( $bricks, callback ) {
169	
170	      // place each brick
171	      for (var i=0, len = $bricks.length; i < len; i++) {
172	        this._placeBrick( $bricks[i] );
173	      }
174	     
175	      // set the size of the container
176	      var containerSize = {};
177	      containerSize.height = Math.max.apply( Math, this.colYs );
178	      if ( this.options.isFitWidth ) {
179	        var unusedCols = 0;
180	        i = this.cols;
181	        // count unused columns
182	        while ( --i ) {
183	          if ( this.colYs[i] !== 0 ) {
184	            break;
185	          }
186	          unusedCols++;
187	        }
188	        // fit container to columns that have been used;
189	        containerSize.width = (this.cols - unusedCols) * this.columnWidth - this.options.gutterWidth;
190	      }
191	      this.styleQueue.push({ $el: this.element, style: containerSize });
192	
193	      // are we animating the layout arrangement?
194	      // use plugin-ish syntax for css or animate
195	      var styleFn = !this.isLaidOut ? 'css' : (
196	            this.options.isAnimated ? 'animate' : 'css'
197	          ),
198	          animOpts = this.options.animationOptions;
199	
200	      // process styleQueue
201	      var obj;
202	      for (i=0, len = this.styleQueue.length; i < len; i++) {
203	        obj = this.styleQueue[i];
204	        obj.$el[ styleFn ]( obj.style, animOpts );
205	      }
206	
207	      // clear out queue for next time
208	      this.styleQueue = [];
209	
210	      // provide $elems as context for the callback
211	      if ( callback ) {
212	        callback.call( $bricks );
213	      }
214	     
215	      this.isLaidOut = true;
216	    },
217	   
218	    // calculates number of columns
219	    // i.e. this.columnWidth = 200
220	    _getColumns : function() {
221	      var container = this.options.isFitWidth ? this.element.parent() : this.element,
222	          containerWidth = container.width();
223	
224	                         // use fluid columnWidth function if there
225	      this.columnWidth = this.isFluid ? this.options.columnWidth( containerWidth ) :
226	                    // if not, how about the explicitly set option?
227	                    this.options.columnWidth ||
228	                    // or use the size of the first item
229	                    this.$bricks.outerWidth(true) ||
230	                    // if there's no items, use size of container
231	                    containerWidth;
232	
233	      this.columnWidth += this.options.gutterWidth;
234	
235	      this.cols = Math.floor( ( containerWidth + this.options.gutterWidth ) / this.columnWidth );
236	      this.cols = Math.max( this.cols, 1 );
237	
238	    },
239	
240	    // layout logic
241	    _placeBrick: function( brick ) {
242	      var $brick = $(brick),
243	          colSpan, groupCount, groupY, groupColY, j;
244	
245	      //how many columns does this brick span
246	      colSpan = Math.ceil( $brick.outerWidth(true) / this.columnWidth );
247	      colSpan = Math.min( colSpan, this.cols );
248	
249	      if ( colSpan === 1 ) {
250	        // if brick spans only one column, just like singleMode
251	        groupY = this.colYs;
252	      } else {
253	        // brick spans more than one column
254	        // how many different places could this brick fit horizontally
255	        groupCount = this.cols + 1 - colSpan;
256	        groupY = [];
257	
258	        // for each group potential horizontal position
259	        for ( j=0; j < groupCount; j++ ) {
260	          // make an array of colY values for that one group
261	          groupColY = this.colYs.slice( j, j+colSpan );
262	          // and get the max value of the array
263	          groupY[j] = Math.max.apply( Math, groupColY );
264	        }
265	
266	      }
267	
268	      // get the minimum Y value from the columns
269	      var minimumY = Math.min.apply( Math, groupY ),
270	          shortCol = 0;
271	     
272	      // Find index of short column, the first from the left
273	      for (var i=0, len = groupY.length; i < len; i++) {
274	        if ( groupY[i] === minimumY ) {
275	          shortCol = i;
276	          break;
277	        }
278	      }
279	
280	      // position the brick
281	      var position = {
282	        top: minimumY + this.offset.y
283	      };
284	      // position.left or position.right
285	      position[ this.horizontalDirection ] = this.columnWidth * shortCol + this.offset.x;
286	      this.styleQueue.push({ $el: $brick, style: position });
287	
288	      // apply setHeight to necessary columns
289	      var setHeight = minimumY + $brick.outerHeight(true),
290	          setSpan = this.cols + 1 - len;
291	      for ( i=0; i < setSpan; i++ ) {
292	        this.colYs[ shortCol + i ] = setHeight;
293	      }
294	
295	    },
296	   
297	   
298	    resize: function() {
299	      var prevColCount = this.cols;
300	      // get updated colCount
301	      this._getColumns();
302	      if ( this.isFluid || this.cols !== prevColCount ) {
303	        // if column count has changed, trigger new layout
304	        this._reLayout();
305	      }
306	    },
307	   
308	   
309	    _reLayout : function( callback ) {
310	      // reset columns
311	      var i = this.cols;
312	      this.colYs = [];
313	      while (i--) {
314	        this.colYs.push( 0 );
315	      }
316	      // apply layout logic to all bricks
317	      this.layout( this.$bricks, callback );
318	    },
319	   
320	    // ====================== Convenience methods ======================
321	   
322	    // goes through all children again and gets bricks in proper order
323	    reloadItems : function() {
324	      this.$bricks = this._getBricks( this.element.children() );
325	    },
326	   
327	   
328	    reload : function( callback ) {
329	      this.reloadItems();
330	      this._init( callback );
331	    },
332	   
333	
334	    // convienence method for working with Infinite Scroll
335	    appended : function( $content, isAnimatedFromBottom, callback ) {
336	      if ( isAnimatedFromBottom ) {
337	        // set new stuff to the bottom
338	        this._filterFindBricks( $content ).css({ top: this.element.height() });
339	        var instance = this;
340	        setTimeout( function(){
341	          instance._appended( $content, callback );
342	        }, 1 );
343	      } else {
344	        this._appended( $content, callback );
345	      }
346	    },
347	   
348	    _appended : function( $content, callback ) {
349	      var $newBricks = this._getBricks( $content );
350	      // add new bricks to brick pool
351	      this.$bricks = this.$bricks.add( $newBricks );
352	      this.layout( $newBricks, callback );
353	    },
354	   
355	    // removes elements from Masonry widget
356	    remove : function( $content ) {
357	      this.$bricks = this.$bricks.not( $content );
358	      $content.remove();
359	    },
360	   
361	    // destroys widget, returns elements and container back (close) to original style
362	    destroy : function() {
363	
364	      this.$bricks
365	        .removeClass('masonry-brick')
366	        .each(function(){
367	          this.style.position = '';
368	          this.style.top = '';
369	          this.style.left = '';
370	        });
371	     
372	      // re-apply saved container styles
373	      var elemStyle = this.element[0].style;
374	      for ( var prop in this.originalStyle ) {
375	        elemStyle[ prop ] = this.originalStyle[ prop ];
376	      }
377	
378	      this.element
379	        .unbind('.masonry')
380	        .removeClass('masonry')
381	        .removeData('masonry');
382	     
383	      $(window).unbind('.masonry');
384	
385	    }
386	   
387	  };
388	 
389	 
390	  // ======================= imagesLoaded Plugin ===============================
391	  /*!
392	   * jQuery imagesLoaded plugin v1.1.0
393	   * http://github.com/desandro/imagesloaded
394	   *
395	   * MIT License. by Paul Irish et al.
396	   */
397	
398	
399	  // $('#my-container').imagesLoaded(myFunction)
400	  // or
401	  // $('img').imagesLoaded(myFunction)
402	
403	  // execute a callback when all images have loaded.
404	  // needed because .load() doesn't work on cached images
405	
406	  // callback function gets image collection as argument
407	  //  `this` is the container
408	
409	  $.fn.imagesLoaded = function( callback ) {
410	    var $this = this,
411	        $images = $this.find('img').add( $this.filter('img') ),
412	        len = $images.length,
413	        blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==',
414	        loaded = [];
415	
416	    function triggerCallback() {
417	      callback.call( $this, $images );
418	    }
419	
420	    function imgLoaded( event ) {
421	      var img = event.target;
422	      if ( img.src !== blank && $.inArray( img, loaded ) === -1 ){
423	        loaded.push( img );
424	        if ( --len <= 0 ){
425	          setTimeout( triggerCallback );
426	          $images.unbind( '.imagesLoaded', imgLoaded );
427	        }
428	      }
429	    }
430	
431	    // if no images, trigger immediately
432	    if ( !len ) {
433	      triggerCallback();
434	    }
435	
436	    $images.bind( 'load.imagesLoaded error.imagesLoaded',  imgLoaded ).each( function() {
437	      // cached images don't fire load sometimes, so we reset src.
438	      var src = this.src;
439	      // webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
440	      // data uri bypasses webkit log warning (thx doug jones)
441	      this.src = blank;
442	      this.src = src;
443	    });
444	
445	    return $this;
446	  };
447	
448	
449	  // helper function for logging errors
450	  // $.error breaks jQuery chaining
451	  var logError = function( message ) {
452	    if ( window.console ) {
453	      window.console.error( message );
454	    }
455	  };
456	 
457	  // =======================  Plugin bridge  ===============================
458	  // leverages data method to either create or return $.Mason constructor
459	  // A bit from jQuery UI
460	  //   https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
461	  // A bit from jcarousel
462	  //   https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
463	
464	  $.fn.masonry = function( options ) {
465	    if ( typeof options === 'string' ) {
466	      // call method
467	      var args = Array.prototype.slice.call( arguments, 1 );
468	
469	      this.each(function(){
470	        var instance = $.data( this, 'masonry' );
471	        if ( !instance ) {
472	          logError( "cannot call methods on masonry prior to initialization; " +
473	            "attempted to call method '" + options + "'" );
474	          return;
475	        }
476	        if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
477	          logError( "no such method '" + options + "' for masonry instance" );
478	          return;
479	        }
480	        // apply method
481	        instance[ options ].apply( instance, args );
482	      });
483	    } else {
484	      this.each(function() {
485	        var instance = $.data( this, 'masonry' );
486	        if ( instance ) {
487	          // apply options & init
488	          instance.option( options || {} );
489	          instance._init();
490	        } else {
491	          // initialize new instance
492	          $.data( this, 'masonry', new $.Mason( options, this ) );
493	        }
494	      });
495	    }
496	    return this;
497	  };
498	
499	})( window, jQuery );

Contacte con nosotros
¿No puede leer el artículo? ¡Póngase en contacto con nosotros para obtener una respuesta gratuita! Ayuda gratuita para sitios personales y de pequeñas empresas
Tel: 020-2206-9892
QQ咨询:1025174874
(iii) Correo electrónico: info@361sale.com
Horario de trabajo: de lunes a viernes, de 9:30 a 18:30, días festivos libres
© Declaración de reproducción
Este artículo fue escrito por Harry
EL FIN
Si le gusta, apóyela.
felicitaciones0 compartir (alegrías, beneficios, privilegios, etc.) con los demás
comentarios compra de sofás

Por favor, inicie sesión para enviar un comentario

    Sin comentarios