text: ﻿/*! Copyright (c) 2010 Brandon Aaron (http://brandonaaron.net)
   * Dual licensed under the MIT (MIT_LICENSE.txt)
   * and GPL Version 2 (GPL_LICENSE.txt) licenses.
   *
   * Version: 1.1.1
   * Requires jQuery 1.3+
   * Docs: http://docs.jquery.com/Plugins/livequery
   */
  
  (function ($) {
  
      $.extend($.fn, {
          livequery: function (type, fn, fn2) {
  
              //code by FuzhePan - 统一处理livequery多次绑定的问题。
              this.expire(type, fn, fn2);
  
              var self = this, q;
  
              // Handle different call patterns
              if ($.isFunction(type)) {
                  fn2 = fn, fn = type, type = undefined;
              }
              //code by FuzhePan - 给出提示：不要使用livequery进行事件绑定。
              else {
                  //兼容IE8的判断
                  if (typeof console != "undefined") {
                      console.warn("event bind please use jQuery,not livequery!");
                  }
              }
  
              // See if Live Query already exists
              $.each($.livequery.queries, function (i, query) {
                  if (self.selector == query.selector && self.context == query.context &&
                      type == query.type && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid))
                      // Found the query, exit the each loop
                      return (q = query) && false;
              });
  
              // Create new Live Query if it wasn't found
              q = q || new $.livequery(this.selector, this.context, type, fn, fn2);
  
              // Make sure it is running
              q.stopped = false;
  
              // Run it immediately for the first time
              q.run();
  
              // Contnue the chain
              return this;
          },
  
          expire: function (type, fn, fn2) {
              var self = this;
  
              // Handle different call patterns
              if ($.isFunction(type))
                  fn2 = fn, fn = type, type = undefined;
  
              // Find the Live Query based on arguments and stop it
              $.each($.livequery.queries, function (i, query) {
                  if (self.selector == query.selector && self.context == query.context &&
                      (!type || type == query.type) && (!fn || fn.$lqguid == query.fn.$lqguid) && (!fn2 || fn2.$lqguid == query.fn2.$lqguid) && !this.stopped)
                      $.livequery.stop(query.id);
              });
  
              // Continue the chain
              return this;
          }
      });
  
      $.livequery = function (selector, context, type, fn, fn2) {
          this.selector = selector;
          this.context = context;
          this.type = type;
          this.fn = fn;
          this.fn2 = fn2;
          this.elements = [];
          this.stopped = false;
  
          // The id is the index of the Live Query in $.livequery.queries
          this.id = $.livequery.queries.push(this) - 1;
  
          // Mark the functions for matching later on
          fn.$lqguid = fn.$lqguid || $.livequery.guid++;
          if (fn2) fn2.$lqguid = fn2.$lqguid || $.livequery.guid++;
  
          // Return the Live Query
          return this;
      };
  
      $.livequery.prototype = {
          stop: function () {
              var query = this;
  
              if (this.type)
                  // Unbind all bound events
                  this.elements.unbind(this.type, this.fn);
              else if (this.fn2)
                  // Call the second function for all matched elements
                  this.elements.each(function (i, el) {
                      query.fn2.apply(el);
                  });
  
              // Clear out matched elements
              this.elements = [];
  
              // Stop the Live Query from running until restarted
              this.stopped = true;
          },
  
          run: function () {
              // Short-circuit if stopped
              if (this.stopped) return;
              var query = this;
  
              var oEls = this.elements,
                  els = $(this.selector, this.context),
                  nEls = els.not(oEls);
  
              // Set elements to the latest set of matched elements
              this.elements = els;
  
              if (this.type) {
  
                  // Bind events to newly matched elements
                  nEls.bind(this.type, this.fn);
  
                  // Unbind events to elements no longer matched
                  if (oEls.length > 0)
                      $.each(oEls, function (i, el) {
                          if ($.inArray(el, els) < 0)
                              $.event.remove(el, query.type, query.fn);
                      });
              }
              else {
                  // Call the first function for newly matched elements
                  nEls.each(function () {
                      query.fn.apply(this);
                  });
  
                  //commenet by FuzhePan : 因为伙伴中用不到fn2,注释掉这段代码以提高效率
                  //// Call the second function for elements no longer matched
                  //if ( this.fn2 && oEls.length > 0 )
                  //	$.each(oEls, function(i, el) {
                  //		if ( $.inArray(el, els) < 0 )
                  //			query.fn2.apply(el);
                  //	});
              }
          }
      };
  
      $.extend($.livequery, {
          guid: 0,
          queries: [],
          queue: [],
          running: false,
          timeout: null,
  
          checkQueue: function () {
              if ($.livequery.running && $.livequery.queue.length) {
                  var length = $.livequery.queue.length;
                  // Run each Live Query currently in the queue
                  while (length--)
                      $.livequery.queries[$.livequery.queue.shift()].run();
              }
          },
  
          pause: function () {
              // Don't run anymore Live Queries until restarted
              $.livequery.running = false;
          },
  
          play: function () {
              // Restart Live Queries
              $.livequery.running = true;
              // Request a run of the Live Queries
              $.livequery.run();
          },
  
          registerPlugin: function () {
              $.each(arguments, function (i, n) {
                  // Short-circuit if the method doesn't exist
                  if (!$.fn[n]) return;
  
                  // Save a reference to the original method
                  var old = $.fn[n];
  
                  // Create a new method
                  $.fn[n] = function () {
                      // Call the original method
                      var r = old.apply(this, arguments);
  
                      // Request a run of the Live Queries
                      $.livequery.run();
  
                      // Return the original methods result
                      return r;
                  }
              });
          },
  
          run: function (id) {
              if (id != undefined) {
                  // Put the particular Live Query in the queue if it doesn't already exist
                  if ($.inArray(id, $.livequery.queue) < 0)
                      $.livequery.queue.push(id);
              }
              else
                  // Put each Live Query in the queue if it doesn't already exist
                  $.each($.livequery.queries, function (id) {
                      if ($.inArray(id, $.livequery.queue) < 0)
                          $.livequery.queue.push(id);
                  });
  
              // Clear timeout if it already exists
              if ($.livequery.timeout) clearTimeout($.livequery.timeout);
              // Create a timeout to check the queue and actually run the Live Queries
              $.livequery.timeout = setTimeout($.livequery.checkQueue, 20);
          },
  
          stop: function (id) {
              if (id != undefined)
                  // Stop are particular Live Query
                  $.livequery.queries[id].stop();
              else
                  // Stop all Live Queries
                  $.each($.livequery.queries, function (id) {
                      $.livequery.queries[id].stop();
                  });
          }
      });
  
      // Register core DOM manipulation methods
      $.livequery.registerPlugin('append', 'prepend', 'after', 'before', 'wrap', 'replaceWith', 'html');
  
      // Run Live Queries when the Document is ready
      $(function () { $.livequery.play(); });
  
  })(jQuery);