CSS3动画

        .gif-1 {
            display: block;
            width: 150px;
            height: 220px;
            background: url(images/animation/ku_animation.png) 0 0 no-repeat;
            background-size: 100%;
            animation: ku 0.4s steps(14) infinite
        }

        @keyframes ku {
            from {
                background-position: 0 0;
            }
            to {
                background-position: 0 -3080px;
            }
        }

假设图片为150*3300,为15帧,每帧为150*220则

  1. background-position: 0 -3080px;    -3080为长图height-一帧的高度,即3300-220=3080
  2. animation: ku 0.4s steps(14) infinite     0.4s内完成整个懂的年华,steps为15帧-1=14

JS生成随机数

//parseInt(Math.random()*(上限-下限+1)+下限); 1-10
var count = Math.floor(Math.random() * 10 + 1);

checkbox和其父级容器事件传递问题

首先看下一下代码:

function contactsSel() {
	var that = $(this);
	var checkbox = that.find('input[type="checkbox"]');
	if (checkbox.prop('checked') == true) {
		that.css('background', '#ffffff');
		checkbox.prop('checked', false);
	} else {
		that.css('background', '#9ecaf0');
		checkbox.prop('checked', true);
	}
}

$("._contactsContainer li").on('click', contactsSel);

这样的效果会在单击li时候整个li的背景替换,并选中checkbox,看似完美,但是实际效果中会发现一个bug:
单击li没什么问题,单击checkbox时候,没有任何反应。why?
究其原因为checkbox单击时候事件传递给了li,单击checkbox选中了它,然后传递给li后执行contactSel,看到checkbox被选中就会取消选中。结果就是没单击一样。
fix方法:加checkbox单击事件

$("._contactsContainer input[name=\"em\"]").on('click', function () {
	var that = $(this);
	that.prop('checked', !that.prop('checked'));
});

jquery实现几分钟前、几小时前、几天前等时间差显示效果

1.<span class=”time timeago” title=”1411874275236″></span>

2.jQuery(“span.timeago”).timeago();


(function (factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define(['jquery'], factory);
  } else {
    // Browser globals
    factory(jQuery);
  }
}(function ($) {
  $.timeago = function(timestamp) {
    if (timestamp instanceof Date) {
      return inWords(timestamp);
    } else if (typeof timestamp === "string") {
      return inWords($.timeago.parse(timestamp));
    } else if (typeof timestamp === "number") {
      return inWords(new Date(timestamp));
    } else {
      return inWords($.timeago.datetime(timestamp));
    }
  };
  var $t = $.timeago;

  $.extend($.timeago, {
    settings: {
      refreshMillis: 60000,
      allowFuture: false,
      localeTitle: false,
      cutoff: 0,
      strings: {
        prefixAgo: null,
        prefixFromNow: null,
        suffixAgo: "前",
        suffixFromNow: "from now",
        seconds: "1分钟",
        minute: "1分钟",
        minutes: "%d分钟",
        hour: "1小时",
        hours: "%d小时",
        day: "1天",
        days: "%d天",
        month: "1月",
        months: "%d月",
        year: "1年",
        years: "%d年",
        wordSeparator: "",
        numbers: []
      }
    },
    inWords: function(distanceMillis) {
      var $l = this.settings.strings;
      var prefix = $l.prefixAgo;
      var suffix = $l.suffixAgo;
      if (this.settings.allowFuture) {
        if (distanceMillis < 0) {
          prefix = $l.prefixFromNow;
          suffix = $l.suffixFromNow;
        }
      }

      var seconds = Math.abs(distanceMillis) / 1000;
      var minutes = seconds / 60;
      var hours = minutes / 60;
      var days = hours / 24;
      var years = days / 365;

      function substitute(stringOrFunction, number) {
        var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
        var value = ($l.numbers && $l.numbers[number]) || number;
        return string.replace(/%d/i, value);
      }

      var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
        seconds < 90 && substitute($l.minute, 1) ||
        minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
        minutes < 90 && substitute($l.hour, 1) ||
        hours < 24 && substitute($l.hours, Math.round(hours)) ||
        hours < 42 && substitute($l.day, 1) ||
        days < 30 && substitute($l.days, Math.round(days)) ||
        days < 45 && substitute($l.month, 1) ||
        days < 365 && substitute($l.months, Math.round(days / 30)) ||
        years < 1.5 && substitute($l.year, 1) ||
        substitute($l.years, Math.round(years));

      var separator = $l.wordSeparator || "";
      if ($l.wordSeparator === undefined) { separator = " "; }
      return $.trim([prefix, words, suffix].join(separator));
    },
    parse: function(iso8601) {
        var s = $.trim(iso8601);
//      s = s.replace(/\.\d+/,""); // remove milliseconds
//      s = s.replace(/-/,"/").replace(/-/,"/");
//      s = s.replace(/T/," ").replace(/Z/," UTC");
//      s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
      return new Date(parseFloat(s));
    },
    datetime: function(elem) {
      var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
      return $t.parse(iso8601);
    },
    isTime: function(elem) {
      // jQuery's `is()` doesn't play well with HTML5 in IE
      return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
    }
  });

  // functions that can be called via $(el).timeago('action')
  // init is default when no action is given
  // functions are called with context of a single element
  var functions = {
    init: function(){
      var refresh_el = $.proxy(refresh, this);
      refresh_el();
      var $s = $t.settings;
      if ($s.refreshMillis > 0) {
        setInterval(refresh_el, $s.refreshMillis);
      }
    },
    update: function(time){
      $(this).data('timeago', { datetime: $t.parse(time) });
      refresh.apply(this);
    },
    updateFromDOM: function(){
      $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) });
      refresh.apply(this);
    }
  };

  $.fn.timeago = function(action, options) {
    var fn = action ? functions[action] : functions.init;
    if(!fn){
      throw new Error("Unknown function name '"+ action +"' for timeago");
    }
    // each over objects here and call the requested function
    this.each(function(){
      fn.call(this, options);
    });
    return this;
  };

  function refresh() {
    var data = prepareData(this);
    var $s = $t.settings;

    if (!isNaN(data.datetime)) {
      if ( $s.cutoff == 0 || distance(data.datetime) < $s.cutoff) {
        $(this).text(inWords(data.datetime));
      }
    }
    return this;
  }

  function prepareData(element) {
    element = $(element);
    if (!element.data("timeago")) {
      element.data("timeago", { datetime: $t.datetime(element) });
      var text = $.trim(element.text());
      if ($t.settings.localeTitle) {
        element.attr("title", element.data('timeago').datetime.toLocaleString());
      } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
        element.attr("title", text);
      }
    }
    return element.data("timeago");
  }

  function inWords(date) {
    return $t.inWords(distance(date));
  }

  function distance(date) {
    return (new Date().getTime() - date.getTime());
  }

  // fix for IE6 suckage
  document.createElement("abbr");
  document.createElement("time");
}));

yuicompressor-maven

<plugin>
				<groupId>net.alchim31.maven</groupId>
				<artifactId>yuicompressor-maven-plugin</artifactId>
				<version>1.3.0</version>
				<executions>
					<execution>
						<goals>
							<goal>compress</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<!-- 读取js,css文件采用UTF-8编码 -->
					<encoding>UTF-8</encoding>
					<!-- 不显示js可能的错误 -->
					<jswarn>false</jswarn>
					<!-- 若存在已压缩的文件,会先对比源文件是否有改动 有改动便压缩,无改动就不压缩 -->
					<force>false</force>
					<!-- 在指定的列号后插入新行 -->
					<linebreakpos>-1</linebreakpos>
					<!-- 压缩之前先执行聚合文件操作 -->
					<preProcessAggregates>true</preProcessAggregates>
					<!-- 压缩后保存文件后缀 -->
					<suffix>.min</suffix>
					<!-- 源目录,即需压缩的根目录 -->
					<sourceDirectory>${webapp.path}/js</sourceDirectory>
					<!-- 压缩js和css文件 -->
					<includes>
						<include>*.js</include>
					</includes>
					<!-- 以下目录和文件不会被压缩 -->
					<excludes>
						<exclude>*.min.js</exclude>
                        <exclude>**/*.css</exclude>
					</excludes>
					<!-- 压缩后输出文件目录 -->
					<outputDirectory>${webapp.path}/js/min</outputDirectory>
					<!-- 聚合文件 -->
					<aggregations>
						<aggregation>
							<!-- 合并每一个文件后插入一新行 -->
							<insertNewLine>true</insertNewLine>
							<!-- 需合并文件的根文件夹 -->
							<inputDir>${webapp.path}/js/min/</inputDir>
							<!-- 最终合并的输出文件 -->
							<output>${webapp.path}/js/min/all.js</output>
							<!-- 把以下js文件合并成一个js文件,是按顺序合并的 -->
							<includes>
								<include>*.min.js</include>
							</includes>
						</aggregation>
					</aggregations>
				</configuration>
			</plugin>

QQ音乐WEB版不完全分析

URL:http://y.qq.com/

Q1:为什么点击了导航的连接后在播放的音乐没有停止播放,一般情况下,页面刷新后整个展示都是刷新了的,所以音乐也会停止播放。

这个分析导航按钮后会发现玄机,看源码

<a href="/y/static/index.html?pgv_ref=qqmusic.y.topmenu" target="contentFrame" class=""><span>音乐馆</span></a>

看到 target=”contentFrame”没有,这个才是真正的显示首页内容的iframe容器,刷新的内容都在这里,最外面的body也就是播放中所在的元素其实是没有刷新的。
不过有个疑问,为什么浏览器地址栏变了,后面加了#xxx?

HTML JS渲染问题

这几天纠结了一个很蛋疼的问题,用jquery的$.html()方法改变div内容,但是显示上开来似乎没有改变内容。
通过获取html内容发现其实源码的内容已经是变了的,就是显示渲染没有做,导致看上去跟没有变一样。
解决办法。$.html()加一个延时,100ms就足以,视觉上也没什么感觉,但是效果很好,而且目前看来只要一个地方用了这个方法,其它地方都不会再有这个问题。很蛋疼。
这个问题也就只有在android4.0以后的webkit上存在。

JS判断系统/浏览器类型

  var browser={
    versions:function(){ 
           var u = navigator.userAgent, app = navigator.appVersion; 
           return {//移动终端浏览器版本信息 
                trident: u.indexOf('Trident') > -1, //IE内核
                presto: u.indexOf('Presto') > -1, //opera内核
                webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
                gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核
                mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
                ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
                android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器
                iPhone: u.indexOf('iPhone') > -1 , //是否为iPhone或者QQHD浏览器
                iPad: u.indexOf('iPad') > -1, //是否iPad
                webApp: u.indexOf('Safari') == -1 //是否web应该程序,没有头部与底部
            };
         }(),
         language:(navigator.browserLanguage || navigator.language).toLowerCase()
}

JavaScript 的列隊 (Queue) 和堆疊 (Stack)

在JavaScript中,我們也可以使用到列隊(Queue)和堆疊(Stack)這兩個數據結構。最簡單的方法是使用JS內置的陣列(Array)和內置的方法模仿列隊(Queue)和堆疊(Stack),達至先進先出(FIFO, First-In-First-Out)和後進先出(LIFO, Last In First Out)的原理。
內置push, pop, shift和unshift方法
JavaScript的陣列提供了4個方法,分別是push()、pop()、shift()和unshift()。我們先看看下面的圖片了解運用的方式。
如果我們假設左邊是頭(front),右邊是尾(rear)。如果要將新的元素加入數據結構之中,可以使用push()方法將元素加至數據結構的尾(rear),使用unshift()方法則可以加至數據結構的頭(front)。如果要刪除數據結構內的元素,可以使用pop()方法將元素由數據結構的尾(rear)刪除並返回,使用shift()方法將元素由數據結構的頭(front)刪除並返回。

很明顯,我們可以使用push()和shift()兩個方法做到先進先出(FIFO, First-In-First-Out)的原理。另外,unshift()和pop()兩個方法也可以做到先進先出(FIFO, First-In-First-Out)的原理;而push()和pop()兩個方法做到後進先出(LIFO, Last In First Out)的原理。shift()和unshift()兩個方法也可以做到後進先出(LIFO, Last In First Out)的原理。
使用push()和shift()兩個方法的列隊(Queue)例子

var fifoQueue = new Array();
// 建立新的Queue
 
fifoQueue.push("FoolEgg.com");
fifoQueue.push(123456789);
var ptr = fifoQueue.push(98.7654321);
// 將「FoolEgg.com」字串、「123456789」整數和「98.7654321」浮點數加入Queue
 
document.writeln("ptr is " + ptr + "<br />");
document.writeln("The length of queue is " + fifoQueue.length + " and the elements are [" + fifoQueue + "]<br />");
 
document.writeln("Delete the element [" + fifoQueue.shift() + "]<br />");
// 刪除並返回最頭的元素「FoolEgg.com」字串
 
document.writeln("The length of queue is " + fifoQueue.length + " and the elements are [" + fifoQueue + "]<br />");
 
document.writeln("Delete the element [" + fifoQueue.shift() + "]<br />");
// 刪除並返回最頭的元素「123456789」整數
 
document.writeln("The length of queue is " + fifoQueue.length + " and the elements are [" + fifoQueue + "]<br />");
 
document.writeln("Delete the element [" + fifoQueue.shift() + "]<br />");
// 刪除並返回最頭的元素「98.7654321」浮點數
 
document.writeln("Delete the element [" + fifoQueue.shift() + "]<br />");
// 刪除並返回最頭的元素
 
document.writeln("ptr is " + ptr + "<br />");
document.writeln("The length of queue is " + fifoQueue.length + " and the elements are [" + fifoQueue + "]<br />");

以下是輸出的結果︰
ptr is 3
The length of queue is 3 and the elements are [FoolEgg.com,123456789,98.7654321]
Delete the element [FoolEgg.com]
The length of queue is 2 and the elements are [123456789,98.7654321]
Delete the element [123456789]
The length of queue is 1 and the elements are [98.7654321]
Delete the element [98.7654321]
Delete the element [undefined]
ptr is 3
The length of queue is 0 and the elements are []
使用unshift()和pop()兩個方法的列隊(Queue)例子

var fifoQueue = new Array();
// 建立新的Queue
 
fifoQueue.unshift("FoolEgg.com");
fifoQueue.unshift(123456789);
var ptr = fifoQueue.unshift(98.7654321);
// 將「FoolEgg.com」字串、「123456789」整數和「98.7654321」浮點數加入Queue
 
document.writeln("ptr is " + ptr + "<br />");
document.writeln("The length of queue is " + fifoQueue.length + " and the elements are [" + fifoQueue + "]<br />");
 
document.writeln("Delete the element [" + fifoQueue.pop() + "]<br />");
// 刪除並返回最頭的元素「FoolEgg.com」字串
 
document.writeln("The length of queue is " + fifoQueue.length + " and the elements are [" + fifoQueue + "]<br />");
 
document.writeln("Delete the element [" + fifoQueue.pop() + "]<br />");
// 刪除並返回最頭的元素「123456789」整數
 
document.writeln("The length of queue is " + fifoQueue.length + " and the elements are [" + fifoQueue + "]<br />");
 
document.writeln("Delete the element [" + fifoQueue.pop() + "]<br />");
// 刪除並返回最頭的元素「98.7654321」浮點數
 
document.writeln("Delete the element [" + fifoQueue.pop() + "]<br />");
// 刪除並返回最頭的元素
 
document.writeln("ptr is " + ptr + "<br />");
document.writeln("The length of queue is " + fifoQueue.length + " and the elements are [" + fifoQueue + "]<br />");

以下是輸出的結果︰
ptr is 3
The length of queue is 3 and the elements are [98.7654321,123456789,FoolEgg.com]
Delete the element [FoolEgg.com]
The length of queue is 2 and the elements are [98.7654321,123456789]
Delete the element [123456789]
The length of queue is 1 and the elements are [98.7654321]
Delete the element [98.7654321]
Delete the element [undefined]
ptr is 3
The length of queue is 0 and the elements are []
使用push()和pop()兩個方法的堆疊(Stack)例子

var lifoStack = new Array();
// 建立新的Stack
 
lifoStack.push("FoolEgg.com");
lifoStack.push(123456789);
var ptr = lifoStack.push(98.7654321);
// 將「FoolEgg.com」字串、「123456789」整數和「98.7654321」浮點數加入Stack
 
document.writeln("ptr is " + ptr + "<br />");
document.writeln("The length of stack is " + lifoStack.length + " and the elements are [" + lifoStack + "]<br />");
 
document.writeln("Delete the element [" + lifoStack.pop() + "]<br />");
// 刪除並返回最頂的元素「98.7654321」浮點數
 
document.writeln("The length of stack is " + lifoStack.length + " and the elements are [" + lifoStack + "]<br />");
 
document.writeln("Delete the element [" + lifoStack.pop() + "]<br />");
// 刪除並返回最頂的元素「123456789」整數
 
document.writeln("The length of stack is " + lifoStack.length + " and the elements are [" + lifoStack + "]<br />");
 
document.writeln("Delete the element [" + lifoStack.pop() + "]<br />");
// 刪除並返回最頂的元素「FoolEgg.com」字串
 
document.writeln("Delete the element [" + lifoStack.pop() + "]<br />");
// 刪除並返回最頂的元素
 
document.writeln("ptr is " + ptr + "<br />");
document.writeln("The length of stack is " + lifoStack.length + " and the elements are [" + lifoStack + "]<br />");

以下是輸出的結果︰
ptr is 3
The length of stack is 3 and the elements are [FoolEgg.com,123456789,98.7654321]
Delete the element [98.7654321]
The length of stack is 2 and the elements are [FoolEgg.com,123456789]
Delete the element [123456789]
The length of stack is 1 and the elements are [FoolEgg.com]
Delete the element [FoolEgg.com]
Delete the element [undefined]
ptr is 3
The length of stack is 0 and the elements are []
使用shift()和unshift()兩個方法的堆疊(Stack)例子

var lifoStack = new Array();
// 建立新的Stack
 
lifoStack.unshift("FoolEgg.com");
lifoStack.unshift(123456789);
var ptr = lifoStack.unshift(98.7654321);
// 將「FoolEgg.com」字串、「123456789」整數和「98.7654321」浮點數加入Stack
 
document.writeln("ptr is " + ptr + "<br />");
document.writeln("The length of stack is " + lifoStack.length + " and the elements are [" + lifoStack + "]<br />");
 
document.writeln("Delete the element [" + lifoStack.shift() + "]<br />");
// 刪除並返回最頭的元素「98.7654321」浮點數
 
document.writeln("The length of stack is " + lifoStack.length + " and the elements are [" + lifoStack + "]<br />");
 
document.writeln("Delete the element [" + lifoStack.shift() + "]<br />");
// 刪除並返回最頭的元素「123456789」整數
 
document.writeln("The length of stack is " + lifoStack.length + " and the elements are [" + lifoStack + "]<br />");
 
document.writeln("Delete the element [" + lifoStack.shift() + "]<br />");
// 刪除並返回最頭的元素「FoolEgg.com」字串
 
document.writeln("Delete the element [" + lifoStack.shift() + "]<br />");
// 刪除並返回最頭的元素
 
document.writeln("ptr is " + ptr + "<br />");
document.writeln("The length of stack is " + lifoStack.length + " and the elements are [" + lifoStack + "]<br />");

以下是輸出的結果︰
ptr is 3
The length of stack is 3 and the elements are [98.7654321,123456789,FoolEgg.com]
Delete the element [98.7654321]
The length of stack is 2 and the elements are [123456789,FoolEgg.com]
Delete the element [123456789]
The length of stack is 1 and the elements are [FoolEgg.com]
Delete the element [FoolEgg.com]
Delete the element [undefined]
ptr is 3
The length of stack is 0 and the elements are []

如何写一个Jquery 的Plugin插件(超霸气文章~记录了)

想做一个好的插件必须应有的要求:

1、在JQuery命名空间下声明只声明一个单独的名称

2、接受options参数,以便控制插件的行为

3、暴露插件的默认设置 ,以便外面可以访问

4、适当地将子函数提供给外部访问调用

5、保持私有函数

6、支持元数据插件

下面将逐条地过一遍:

只声明一个单独的名称

这表明是一个单独的插件脚本。如果你的脚本包含多个插件或者是互补的插件(像$.fn.doSomething()和$.undoSomething()),那么你可以根据要求声明多个名称。但一般情况下,力争用单一的名称来维持插件现实的所有细节。

在本例中,我们将声明一个叫“hilight”的名称

// 插件的定义  
$.fn.hilight = function( options ){  
    // 这里就是插件的实现代码了...  
      
};

然后我们可以像这样调用它:

    $("divTest").hilight();

接受一个options参数,以便控件插件的行为

    $.fn.hilight = function(options){  
        var defaults = {  
            foreground    :    'red',  
            background    :    'yellow'  
        };  
        //Extends out defaults options with those privided 扩展我们默认的设置  
        $.extend(defaults,options);  
    };

而我们可以这样使用它:

    $('#myDiv').hilight({  
      foreground: 'blue'  
    });

暴露插件的默认设置 ,以便外面可以访问

作为插件的提升和优化,我们应该将上面的代码暴露出来作为插件的默认设置。

这非常重要,这样做让使用插件的用户可以非常容易地用最少的代码重写或自定义该插件。然而这个我们可以借助JavaScript function对象的优势:

    $.fn.hilight = function(options){  
        //Extend our default options with those provided  
        //Note that the first arg to extend is an empty object  
        //this is to keep from overriding our "defaults" object  
        var opts = $.extend({},$.fn.hilight.defaults,options);  
    }  
    $.fn.hilight.defaults = {  
        foreground    :    'red',  
        background    :    'yellow'  
    };

这里值得注意的是$.extend()第一个参数是一个空的对象,这样可以让我们重写插件的默认设置

用户可以像这样使用插件:

    // override plugin default foreground color  
    $.fn.hilight.defaults.foreground = 'blue';  
    // ...  
    // invoke plugin using new defaults  
    $('.hilightDiv').hilight();  
    // ...  
    // override default by passing options to plugin method  
    $('#green').hilight({  
      foreground: 'green'  
    });

适当地将子函数提供给外部访问调用

这个例子延续前面的例子,你会发现有一个有趣的方法可以扩展你的插件(然后还可以让其他人扩展你的插件 :))。例如,我们在插件里声明了一个函数叫“format”用来高这显示文本,我们的插件实现代码可能是这样子的:

    $.fn.hight = function(options){  
        //iterate and reformat each mached element  
        return this.each(function(){  
            var $this = $(this);  
            //...  
            var markup = $this.html();  
            //call our format function  
            markup = $.fn.hilight.format(markup);  
            $this.html(markup);  
        });  
    };  
    //define our format function  
    $.fn.hilight.format = function(txt){  
        return '<strong>' + txt + '</strong>';  
    };

保持私有函数

暴露插件有部分内容提供重写看上去似乎非常强大,但是你必须认真地考虑你的插件哪一部分是需要暴露出来的。一旦暴露出来,你就需要考虑这些变化点,一般情况下,如果你没有把握哪部分需要暴露出来,那么你可以不这样做。

那如何才能够定义更多的函数而不将其暴露出来呢?这个任务就交给闭包吧。为了证实,我们在插件中添加一个函数叫“debug”,这debug函数将会记录已选择的元素数量到FireBug控制台中。为了创建闭包,我们将插件定义的整部分都包装起来:

    //create closure  
    (function($){  
        //plugin definition  
        $.fn.hilight = function(options){  
            debug(this);  
            //...  
        };  
        //private function for debuggin  
        function debug($obj){  
            if(window.console && window.console.log){  
                window.console.log('hilight selection count :' + $obj.size());  
            }  
        }  
        //...  
        //end of closure  
    })(jQuery);

这样“debug”方法就不能被闭包这外调用了

 

支持元数据插件

 

依赖于所写的插件类型,并支持元数据插件会使得其本身更加强大。个人来讲,我喜欢元素据插件,因为它能让你分离标签中重写插件的配置(这在写demo和示例时特别有用)。最重要的是,想现实它特别的容易!

    $.fn.hilight = function(options){  
        //build main options before element interation  
        var opts = $.extend({},$.fn.hilight.defaults,options);  
        return this.each(function(){  
            var $this = $(this);  
            //build element specific options  
            var o = $.meta ? $.extend({},opts,$this.data()) : opts;  
      
             //一般句话,搞定支持元数据 功能         
        });  
    }

几行的变化完成了以下几件事:

1、检测元数据是否已经配置

2、如果已配置,将配置属性与额外的元数据进行扩展

    <!--  markup  -->  
    <div class="hilight { background: 'red', foreground: 'white' }">  
      Have a nice day!这是元数据  
    </div>  
    <div class="hilight { foreground: 'orange' }">  
      Have a nice day!在标签中配置  
    </div>  
    <div class="hilight { background: 'green' }">  
      Have a nice day!  
    </div>

 

然后我们通过一句脚本就可以根据元数据配置分开地高亮显示这些div标签:

    $('.hilight').hilight();

 

最后,将全部代码放在一起:

    //
    //create closure  
    //
    (function($){  
        //
        // plugin definition  
        //
        $.fn.hilight = function(options){  
            debug(this);  
            //build main options before element iteration  
            var opts = $.extend({}, $.fn.hilight.defaults, options);  
            //iterate and reformat each matched element  
            return this.each(function(){  
                $this = $(this);  
                //build element specific options  
                var o = $.meta ? $.extend({}, opts, $this.data()) : opts;  
                //update element styles  
                $this.css({  
                    backgroundColor: o.background,  
                    color: o.foreground  
                });  
                var markup = $this.html();  
            //call our format function  
              
            });  
        }  
          
        //
        // private function for debugging  
        //
        function debug($obj){  
            if(window.console && window.console.log){  
                window.console.log('hilight selection count: ' + $obj.size());  
            }  
        };  
        //
        // define and expose our format function  
        //
        $.fn.hilight.format = function(txt){  
            return '<strong>' + txt + '</strong>';  
        };  
          
        //
        // plugin defaults  
        //
        $.fn.hilight.defaults = {  
            foreground    :    'red',  
            background    :    'yellow'  
        };  
          
        //
        // end of clousure  
        //
    })(jQuery);

 

2、如何写一个Jquery 的Plugin插件

 

最近做项目想要一个控制会计数字输入的jquery插件,找了好久找不到, 没用办法,只有自己操刀上阵了,其实要求也不高, 就是:
1. 默认是: 0.00
2. 只能输入数字和小数点, 其它输入将被忽略
3. 输入整数后继续自动保持两位小数
4. 可以定义自己想保留几位小数

 

 

OK, 开始动手:

首先, 通过将函数封装为jquery plugin包, 可以将这个包非常容易的在各种项目和页面中使用, 而且代码管理维护起来方便. 再说, jquery的plugin实现起来超简单,为什么不这么做呢?如果你是第一次开发, 先阅读下这篇文章吧: How jQuery Works

 

一. Jquery Plugin 的基本框架

    (function($) {  
        $.fn.extend({  
            MyPlugin: function(options) {  
                var defaults = {  
                    decimal_length: 2,  
                };  
                var options = $.extend(defaults, options);  
                var len = parseInt(options['decimal_length']);  
                return this.each(function() {  
                    alert('edison');  
                });  
            }  
        });  
    })(jQuery);

 

其中options就是参数, 调用方法为:

    $('#ddd').MyPlugin({decimal_length:2});

好的, 我们接着完成要的功能: 文件名为 money.js

    (function($) {  
        var pasteEventName = ($.browser.msie ? 'paste' : 'input') + ".mask";  
        $.fn.extend({  
            money_type: function(options) {  
                var defaults = {  
                    decimal_length: 2,  
                };  
                var options = $.extend(defaults, options);  
                var len = parseInt(options['decimal_length']);  
                return this.each(function() {  
                    var input = $(this);  
      
                    function caret() {  
                        var input_value = input.val();  
                        var reCat = /\d+\.?\d{0,2}/i;  
                        var_new_value = reCat.exec(input_value);  
                        input.val(var_new_value);  
                    }  
      
                    input.bind("click", function(e) {  
                        if (input.val() == '0.00') {  
                            input.select();  
                        }  
                    })  
                    .bind(pasteEventName, function() {  
                        setTimeout(caret, 0);  
                    });  
                });  
            }  
        });  
    })(jQuery);

OK, 插件完成, 在使用的时候要包含这个文件和jquery文件, 然后通过以下代码就可以调用了

    $('#ddd').money_type();// 默认保留两位小数