jquery中使用hover多次出发动画的问题

在对元素使用hover后,如果触发的是一个动画效果,鼠标多次在元素上划过则会多次触发动画,这样在鼠标离开后,动画还会反复多次的执行。jquery提供了一个专门的stop函数来停止正在执行的动画,并触发新的动画而不会反复执行。
示例如下:

$(".c_slideitem").hover(function() {
    var _this = $(this).find(".j-box");
    _this.stop(true).animate({
        "margin-top": "0px"
    }, 200);
}, function() {
    var _this = $(this).find(".j-box");
    _this.stop(true).animate({
        "margin-top": "150px"
    }, 500);
});

TimThumb缩略图不显示问题处理

1.自定义栏目定义的字段和< ?php echo get_post_meta( $post->ID, “thumbnail_url”, true ); ?> 这里设置的thumbnail_url一致
2.timthumb的代码一定要是最新代码,我因为这个代码版本旧了图片一直不显示倒腾了几天也找不到原因。。。大坑timthumb最新代码地址: http://code.google.com/p/timthumb

[转]Three.js + HTML5 Audio API 打造3D音乐频谱,Let’s ROCK!

继续玩味之前写的音乐频谱作品,将原来在Canvas标签上的 作图利用Three.js让它通过WebGL呈现,这样就打造出了一个全立体感的频谱效果了。

项目详情及源码
项目GitHub地址:https://github.com/Wayou/3D_Audio_Spectrum_VIsualizer/tree/master

在线演示地址:http://wayou.github.io/3D_Audio_Spectrum_VIsualizer

如果你想的话,可以从这里下载示例音乐:http://pan.baidu.com/s/1eQqqSfS

Note:
可以直接点击’play default’ 播放自带的音乐,神探夏洛克插曲,如果你也看了的话,听着应该会有感的
支持文件拖拽进行播放,将音频文件拖拽到页面即可
也可以通过文件上传按钮选择一个音频文件进行播放
鼠标拖拽可以移动镜头变换视野
鼠标滚轮可以进行缩放
右上角的控制面板可以进行一些外观及镜头上的设置,可以自己探索玩玩
利用Three.js呈现

关于音频处理方面的逻辑基本和之前介绍HTML5 Audio API那篇博客里讲的差不多,差别只在这个项目里面将频谱的展示从2d的canvas换成3d的WebGL进行展示,使用的是Three.js。所以只简单介绍关于3d场景方面的构建,具体实现可以访问项目GitHub页面下载源码。

构建跃动的柱条
每根绿色柱条是一个CubeGeometry,柱条上面的盖子也是CubeGeometry,只是长度更短而以,同时使用的是白色。

//创建绿色柱条的形状
var cubeGeometry = new THREE.CubeGeometry(MWIDTH, 1, MTHICKNESS);
//创建绿色柱条的材质
var cubeMaterial = new THREE.MeshPhongMaterial({
color: 0x01FF00,
ambient: 0x01FF00,
specular: 0x01FF00,
shininess: 20,
reflectivity: 5.5
});
//创建白色盖子的形状
var capGeometry = new THREE.CubeGeometry(MWIDTH, 0.5, MTHICKNESS);
//创建白色盖子的材质
var capMaterial = new THREE.MeshPhongMaterial({
color: 0xffffff,
ambient: 0x01FF00,
specular: 0x01FF00,
shininess: 20,
reflectivity: 5.5
});
上面只是创建了形状及材质,需要将这两者组合在一起形成一个模型,才是我们看到的实际物体。下面通过一个循环创建了一字排开的柱条和对应的盖子,然后添加到场景中。

//创建一字排开的柱条和盖子,并添加到场景中
for (var i = METERNUM - 1; i >= 0; i–) {
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = -45 + (MWIDTH + GAP) i;
cube.position.y = -1;
cube.position.z = 0.5;
cube.castShadow = true;
cube.name = ‘cube’ + i;
scene.add(cube);
var cap = new THREE.Mesh(capGeometry, capMaterial);
cap.position.x = -45 + (MWIDTH + GAP)
i;
cap.position.y = 0.5;
cap.position.z = 0.5;
cap.castShadow = true;
cap.name = ‘cap’ + i;
scene.add(cap);
};
注意到我们为每个物体指定了名称以方便之后获取该物体。

添加动画

动画部分同时是使用requestAnimation,根据传入的音频分析器(analyser)的数据来更新每根柱条的长度。

var renderAnimation = function() {
if (analyser) {
//从音频分析器中获取数据
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
var step = Math.round(array.length / METERNUM);
//更新每根柱条的高度
for (var i = 0; i < METERNUM; i++) {
var value = array[i * step] / 4;
value = value < 1 ? 1 : value;
var meter = scene.getObjectByName(‘cube’ + i, true);
meter.scale.y = value;
}
};
//重新渲染画面
render.render(scene, camera);
requestAnimationFrame(renderAnimation);
};
requestAnimationFrame(renderAnimation);
对于白色盖子的处理稍微不同,因为它是缓慢下落的,不能使用及时送达的音频数据来更新它。实现的方式是每次动画更新中检查当前柱条的高度与前一时刻盖子的高度,看谁大,如果柱条更高,则盖子使用新的高度,否则盖子高度减1,这样就实现了缓落的效果。

var renderAnimation = function() {
if (analyser) {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
var step = Math.round(array.length / METERNUM);
for (var i = 0; i < METERNUM; i++) {
var value = array[i step] / 4;
value = value < 1 ? 1 : value;
var meter = scene.getObjectByName(‘cube’ + i, true),
cap = scene.getObjectByName(‘cap’ + i, true);
meter.scale.y = value;
//计算柱条边沿尺寸以获得高度
meter.geometry.computeBoundingBox();
height = (meter.geometry.boundingBox.max.y - meter.geometry.boundingBox.min.y)
value;
//将柱条高度与盖子高度进行比较
if (height / 2 > cap.position.y) {
cap.position.y = height / 2;
} else {
cap.position.y -= controls.dropSpeed;
};
}
};
//重新渲染画面
render.render(scene, camera);
requestAnimationFrame(renderAnimation);
};
requestAnimationFrame(renderAnimation);
镜头控制

镜头的控制使用的是与Three.js搭配的一个插件ObitControls.js,如果你下载了Three.js的源码可以在里面找到。只需获取一个鼠标拖动的前后时间差,然后在动画循环中调用插件进行画面更新即可。

var orbitControls = new THREE.OrbitControls(camera);
orbitControls.minDistance = 50;
orbitControls.maxDistance = 200;
orbitControls.maxPolarAngle = 1.5;
var renderAnimation = function() {
var delta = clock.getDelta();
orbitControls.update(delta);
if (analyser) {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
var step = Math.round(array.length / METERNUM);
for (var i = 0; i < METERNUM; i++) {
var value = array[i step] / 4;
value = value < 1 ? 1 : value;
var meter = scene.getObjectByName(‘cube’ + i, true),
cap = scene.getObjectByName(‘cap’ + i, true);
meter.scale.y = value;
//计算柱条边沿尺寸以获得高度
meter.geometry.computeBoundingBox();
height = (meter.geometry.boundingBox.max.y - meter.geometry.boundingBox.min.y)
value;
//将柱条高度与盖子高度进行比较
if (height / 2 > cap.position.y) {
cap.position.y = height / 2;
} else {
cap.position.y -= controls.dropSpeed;
};
}
};
//重新渲染画面
render.render(scene, camera);
requestAnimationFrame(renderAnimation);
};
requestAnimationFrame(renderAnimation);
注意到在实例化一个ObitControls后,进行了一些角度和镜头伸缩方面的设置,限制了用户把画面翻转到平面的底部,也保证了镜头在伸缩时不会太远及太近。

参数控制

右上角的控制面板可以进行画面的一些参数更改,使用的是谷歌员工创建的一个插件dat.gui.js 。

首先需要定义一个包含全部需要控制的参数的对象:

var controls = new function() {
this.capColor = 0xFFFFFF;
this.barColor = 0x01FF00;
this.ambientColor = 0x0c0c0c;
this.dropSpeed = 0.1;
this.autoRotate = false;
};
然后实例化一个控制器,将这个对象及相应参数进行绑定:

var gui = new dat.GUI();
//添加盖子下降速度的控制
gui.add(controls, ‘dropSpeed’, 0.1, 0.5);
//盖子颜色控制
gui.addColor(controls, ‘capColor’).onChange(function(e) {
scene.children.forEach(function(child) {
if (child.name.indexOf(‘cap’) > -1) {
child.material.color.setStyle(e);
child.material.ambient = new THREE.Color(e)
child.material.emissive = new THREE.Color(e)
child.material.needsUpdate = true;
}
});
});
//柱条颜色控制
gui.addColor(controls, ‘barColor’).onChange(function(e) {
scene.children.forEach(function(child) {
if (child.name.indexOf(‘cube’) > -1) {
child.material.color.setStyle(e);
child.material.ambient = new THREE.Color(e)
child.material.emissive = new THREE.Color(e)
child.material.needsUpdate = true;
}
});
});
//镜头自动移动控制
gui.add(controls, ‘autoRotate’).onChange(function(e) {
orbitControls.autoRotate = e;
});
总结

完成了主要功能,但没达到我预期的效果,我想的是把柱条做成发光的,调研了一下,需要用更复杂的材质,同时也不能用WebGL来渲染画面了,性能是一方面,同时也还没研究得那么深入,所以就先出了这个版本先。以后或许弄个水波效果。

REFERENCE

Offical Documentation: http://threejs.org/docs/

A Demo: http://srchea.com/blog/2013/05/experimenting-with-web-audio-api-three-js-webgl/

Another Example: https://github.com/arirusso/three-audio-spectrum

A Working Demo: http://badassjs.com/post/27056714305/plucked-html5-audio-editor-and-threeaudio-js

Dat GUI plugin: https://code.google.com/p/dat-gui/

PLEASE KINDLY SHOW YOUR RESPECT TO THE AUTHOR OF THIS ARTICLE

Feel free to repost but keep the link to this page please!

本文链接:http://www.cnblogs.com/Wayou/p/html5_audio_api_3d_visualizer_with_threejs.html

javascript DOM事件的一些资料

DOM Event interface
Event handlers may be attached to various objects including DOM elements, document, the window object, etc. When an event occurs, an event object is created and passed sequentially to the event listeners.

The DOM Event interface is accessible from within the handler function, via the event object passed as the first argument. The following simple example shows how an event object is passed to the event handler function, and can be used from within one such function.

function foo(evt) {
  // the evt parameter is automatically assigned the event object
  alert(evt);
}

手机端网页添加active状态效果_add active state in mobile page

1.需要把链接在移动端上默认的一层半透明的层删掉
a{-webkit-tap-highlight-color: rgba(0,0,0,0);}
2.给document绑定一个touchstart事件
document.addEventListener(“touchstart”, function(){}, true);

链接: http://www.mobify.com/blog/beginners-guide-to-perceived-performance/

手机端固定定位元素不可点击问题处理_mobile fixed element can not click issue

在安卓手机若一个div设置了固定定位,在给其隐藏后再控制让其显示,会出现不可点击的问题。
解决方法是不使用display:none;这个属性控制显示,而使用visibility:hidden;属性来控制其隐藏和显示

[转]Jquery 插件设计模式_[repost]jquery-plugin-patterns

原文:coding.smashingmagazine.com/2011/10/11/essential-jquery-plugin-patterns/ By Addy Osmani
译者原文: http://wlog.cn/jquery/essential-jquery-plugin-patterns.html
译者注:目前还有部分内容没有翻译完成,如翻译有误,敬请指正。

我前面写过javascript 设计模式,它为javascript开发中的一些常见问题提供了很好的解决方案,使用这些设计模式将使你的开发获益良多。众所周知,javascript 设计模式非常有用,另一方面得益于它自己的设计模式:jquery 插件。 官方的jQuery 插件开发指南 可以作为学习编写插件的一个很好的开始。在这篇文章中我们将更深入了解jquery插件开发技巧。

jquery插件开发经过这几年的不断发展,我们现在很少只使用一种方式来编写插件。事实上,使用特定的设计模式在某些解决某些特定问题或场景,比其它模式更为有效。

一些开发人员可能希望使用jQuery UI 组件 工厂模式(the jQuery UI widget factory),这种模式适合复杂、灵活的UI组件。另外一些开发人员可能喜欢像模块(类似模块模式)一样组织他们的代码,或者使用更正式的模块模式如AMD(asynchronous module definition) 。还有一些开发人员希望他们的插件使用javascript强大的原型继承。还有另外一些开发人员可能想使用自定义的事件或发布/订阅(pub/sub)使插件和app之间通信。等等…

我注意到一些开发者尝试创建一种通用的jquery插件模板(one-size-fits-all jQuery plugin boilerplate), 这引发了我的思考。理论上来说,使用统一模板(boilerplate)是一个很好的想法,然而,实际开发中,我们很少只使用一种模式来开发插件。

假如你自己动手编写过一些jquery插件,它们运行良好,但是,你可能会觉得它可以有更好的代码组织结构,它可以更灵活,解决更多的问题。这听起来很熟悉,你不确定不同的jquery插件模式之间的差异,你会发现我后面将要讲的内容非常有用。

这篇文章不会为你提供所有问题的解决方案,但是它覆盖了所有开发人员在使用的流行的设计模式。

注:这篇文章主要面向由中高级的开发人员。如果你觉得还没准备好,推荐你可以先看官方的jQuery 插件开发指南 、Ben Alman的plugin style guide和Remy Sharp的Signs of a Poorly Written jQuery Plugin

模式(Patterns)

jQuery插件定义了很少的规则,而这也是为什么这些插件方法多种多样的原因之一。最简单的,你可以为jquery的$.fn对象添加一个方法,如:

$.fn.myPluginName = function() {
    // your plugin logic
};

前面的方法很间单,不过下面的这种方法会更好一些:

(function( $ ){
    $.fn.myPluginName = function() {
        // your plugin logic
    };
})( jQuery );

这里,我们在插件代码内嵌到一个匿名函数中,使用匿名函数创建了一个闭包,将jQuery这个全局变量传入匿名函数,并执行匿名函数。这样可以确保$不会和其它的javascript库冲突,避免$变量和页面中的全局变量冲突。

还有另外一种写法是使用$.extend,使用这种方法一次可以定义多个方法,这在有些场景下非常有用:

(function( $ ){
    $.extend($.fn, {
        myplugin: function(){
            // your plugin logic
        }
    });
})( jQuery );

对此,我们可以做一些改进。首先,我们来看第一个完整的模式 - 轻量级的模式(the lightweight pattern),这种模式覆盖了我们日常插件开发的一些最佳实践和常见问题。

注意:

你可在jquery-plugin-patterns(翻译本文时,项目已经迁移到jquery-boilerplate/patterns)这个项目找到这篇文章里面谈到的设计模式。

虽然,这篇文章会对每一种模式做讲解,但是还是建议阅读代码中的注释,注释可以让你更深入的了解为什么使用这种做法是最好的。

另外,如果有兴趣的话也可以读一下每种模式后面的扩展内容。

简单的开始(A Lightweight Start)

首先,我们先来看一些基本的、遵循最佳实践(包括jQuery插件编写指南)的设计模式。这种模式在开发一个新的插件或实现一些简单插件时非常理想。轻量级的插件模式遵循了下面的一些原则:

  • 常见的最佳做法,如函数的调用前使用一个分号; window, document, undefined作为参数传入;遵循jQuery风格规范。
  • 插件默认配置。
  • 一个简单的插件的构造函数,用于逻辑相关的初始化和委派元素处理。
  • 使插件的配置可扩展。
  • 避免创建多个实例。

代码:

/*!
 * jQuery lightweight plugin boilerplate
 * Original author: @ajpiano
 * Further changes, comments: @addyosmani
 * Licensed under the MIT license
 */

// the semi-colon before the function invocation is a safety 
// net against concatenated scripts and/or other plugins 
// that are not closed properly.
;(function ( $, window, document, undefined ) {

    // undefined is used here as the undefined global 
    // variable in ECMAScript 3 and is mutable (i.e. it can 
    // be changed by someone else). undefined isn't really 
    // being passed in so we can ensure that its value is 
    // truly undefined. In ES5, undefined can no longer be 
    // modified.

    // window and document are passed through as local 
    // variables rather than as globals, because this (slightly) 
    // quickens the resolution process and can be more 
    // efficiently minified (especially when both are 
    // regularly referenced in your plugin).

    // Create the defaults once
    var pluginName = 'defaultPluginName',
        defaults = {
            propertyName: "value"
        };

    // The actual plugin constructor
    function Plugin( element, options ) {
        this.element = element;

        // jQuery has an extend method that merges the 
        // contents of two or more objects, storing the 
        // result in the first object. The first object 
        // is generally empty because we don't want to alter 
        // the default options for future instances of the plugin
        this.options = $.extend( {}, defaults, options) ;

        this._defaults = defaults;
        this._name = pluginName;

        this.init();
    }

    Plugin.prototype.init = function () {
        // Place initialization logic here
        // You already have access to the DOM element and
        // the options via the instance, e.g. this.element 
        // and this.options
    };

    // A really lightweight plugin wrapper around the constructor, 
    // preventing against multiple instantiations
    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName, 
                new Plugin( this, options ));
            }
        });
    }

})( jQuery, window, document );

扩展阅读

完整的 Widget factory(“Complete” Widget Factory)

代码:

/*!
 * jQuery UI Widget-factory plugin boilerplate (for 1.8/9+)
 * Author: @addyosmani
 * Further changes: @peolanha
 * Licensed under the MIT license
 */

;(function ( $, window, document, undefined ) {

    // define your widget under a namespace of your choice
    //  with additional parameters e.g. 
    // $.widget( "namespace.widgetname", (optional) - an 
    // existing widget prototype to inherit from, an object 
    // literal to become the widget's prototype ); 

    $.widget( "namespace.widgetname" , {

        //Options to be used as defaults
        options: {
            someValue: null
        },

        //Setup widget (eg. element creation, apply theming
        // , bind events etc.)
        _create: function () {

            // _create will automatically run the first time 
            // this widget is called. Put the initial widget 
            // setup code here, then you can access the element 
            // on which the widget was called via this.element. 
            // The options defined above can be accessed 
            // via this.options this.element.addStuff();
        },

        // Destroy an instantiated plugin and clean up 
        // modifications the widget has made to the DOM
        destroy: function () {

            // this.element.removeStuff();
            // For UI 1.8, destroy must be invoked from the 
            // base widget
            $.Widget.prototype.destroy.call(this);
            // For UI 1.9, define _destroy instead and don't 
            // worry about 
            // calling the base widget
        },

        methodB: function ( event ) {
            //_trigger dispatches callbacks the plugin user 
            // can subscribe to
            // signature: _trigger( "callbackName" , [eventObject], 
            // [uiObject] )
            // eg. this._trigger( "hover", e /*where e.type == 
            // "mouseenter"*/, { hovered: $(e.target)});
            this._trigger('methodA', event, {
                key: value
            });
        },

        methodA: function ( event ) {
            this._trigger('dataChanged', event, {
                key: value
            });
        },

        // Respond to any changes the user makes to the 
        // option method
        _setOption: function ( key, value ) {
            switch (key) {
            case "someValue":
                //this.options.someValue = doSomethingWith( value );
                break;
            default:
                //this.options[ key ] = value;
                break;
            }

            // For UI 1.8, _setOption must be manually invoked 
            // from the base widget
            $.Widget.prototype._setOption.apply( this, arguments );
            // For UI 1.9 the _super method can be used instead
            // this._super( "_setOption", key, value );
        }
    });

})( jQuery, window, document );

扩展阅读

命名空间和嵌套的命名空间

使用命名空间可以避免你的代码和和全局变量或对象冲突。命名空间可以保护你的插件不会被页面上的其它同名变量或者和你的插件同名的插件破坏。同样,你也不要使其它开发者的脚本无法运行。

JavaScript没有其它语言一样的内置了命名空间,但很容易使用对象来模拟命名空间。可以将一个顶级对象作为你的命名空间,可以在一开始先检查这个对象是否存在,如果不存在就定义它,如果存在,你直接可以扩展它。

对象(确切地说,对象字面量)可以用来创建嵌套的命名空间,如namespace.subnamespace.pluginName等。

/*!
 * jQuery namespaced 'Starter' plugin boilerplate
 * Author: @dougneiner
 * Further changes: @addyosmani
 * Licensed under the MIT license
 */

;(function ( $ ) {
    if (!$.myNamespace) {
        $.myNamespace = {};
    };

    $.myNamespace.myPluginName = function ( el, myFunctionParam, options ) {
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;

        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el;

        // Add a reverse reference to the DOM object
        base.$el.data( "myNamespace.myPluginName" , base );

        base.init = function () {
            base.myFunctionParam = myFunctionParam;

            base.options = $.extend({}, 
            $.myNamespace.myPluginName.defaultOptions, options);

            // Put your initialization code here
        };

        // Sample Function, Uncomment to use
        // base.functionName = function( paramaters ){
        // 
        // };
        // Run initializer
        base.init();
    };

    $.myNamespace.myPluginName.defaultOptions = {
        myDefaultValue: ""
    };

    $.fn.mynamespace_myPluginName = function 
        ( myFunctionParam, options ) {
        return this.each(function () {
            (new $.myNamespace.myPluginName(this, 
            myFunctionParam, options));
        });
    };

})( jQuery );

扩展阅读

Pub/Sub自定义事件

你可能在开发异步JavaScript应用时使用过观察者模式( 又名发布-订阅者模式(Pub/Sub) pattern)。观察者模式的本质是对应用中某个对象状态进行观察,并且在其发生改变时能够对通知做出响应。

在jQuery中,jquery提供的自定义事件和观察者模式很类似,bind(‘eventType’)相当于subscribe(‘eventType’),trigger(‘eventType’)相当于publish(‘eventType’)。

一些开发者可能认为jQuery事件系统作为发布和订阅系统使用开销太大,但是它的构架在多数情况下非常健壮和稳定。在 jQuery UI widget factory 模板中,我们实现了一个基本的自定义事件的发布/订阅模式:

/*!
 * jQuery custom-events plugin boilerplate
 * Author: DevPatch
 * Further changes: @addyosmani
 * Licensed under the MIT license
 */

// In this pattern, we use jQuery's custom events to add 
// pub/sub (publish/subscribe) capabilities to widgets. 
// Each widget would publish certain events and subscribe 
// to others. This approach effectively helps to decouple 
// the widgets and enables them to function independently.

;(function ( $, window, document, undefined ) {
    $.widget("ao.eventStatus", {
        options: {

        },

        _create : function() {
            var self = this;

            //self.element.addClass( "my-widget" );

            //subscribe to 'myEventStart'
            self.element.bind( "myEventStart", function( e ) {
                console.log("event start");
            });

            //subscribe to 'myEventEnd'
            self.element.bind( "myEventEnd", function( e ) {
                console.log("event end");
            });

            //unsubscribe to 'myEventStart'
            //self.element.unbind( "myEventStart", function(e){
                ///console.log("unsubscribed to this event"); 
            //});
        },

        destroy: function(){
            $.Widget.prototype.destroy.apply( this, arguments );
        },
    });
})( jQuery, window , document );

//Publishing event notifications
//usage: 
// $(".my-widget").trigger("myEventStart");
// $(".my-widget").trigger("myEventEnd");

扩展阅读

带桥接模式的原型继承

在javascript中,没有类的概念。但是,我们可以使用javascript的原型继承,我们可以在juqery插件开发中使用原型继承。

Alex SextonScott Gonzalez已经详细的谈过这个话题。简而言之,使用桥接模式可以弱化它和使用它的类和对象之间的耦合。另外,桥接模式有助于保持API的简洁,你可以更容易的对你的插件进行单元测试。

在Sexton的文章中,他实现了一个可以让你添加自己的逻辑代码的桥接模式模板,你可以看下面的代码了解更多。这种模式的另一个优点你不必不断重复相同的插件初始化代码。一些开发人员可能觉得这种模式比其它模式更容易阅读:

/*!
 * jQuery prototypal inheritance plugin boilerplate
 * Author: Alex Sexton, Scott Gonzalez
 * Further changes: @addyosmani
 * Licensed under the MIT license
 */

// myObject - an object representing a concept that you want 
// to model (e.g. a car)
var myObject = {
  init: function( options, elem ) {
    // Mix in the passed-in options with the default options
    this.options = $.extend( {}, this.options, options );

    // Save the element reference, both as a jQuery
    // reference and a normal reference
    this.elem  = elem;
    this.$elem = $(elem);

    // Build the DOM's initial structure
    this._build();

    // return this so that we can chain and use the bridge with less code.
    return this;
  },
  options: {
    name: "No name"
  },
  _build: function(){
    //this.$elem.html('

‘+this.options.name+’

‘);
},
myMethod: function( msg ){
// You have direct access to the associated and cached
// jQuery element
// this.$elem.append(‘

‘+msg+’
‘);
}
};

// Object.create support test, and fallback for browsers without it
if ( typeof Object.create !== 'function' ) {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

// Create a plugin based on a defined object
$.plugin = function( name, object ) {
  $.fn[name] = function( options ) {
    return this.each(function() {
      if ( ! $.data( this, name ) ) {
        $.data( this, name, Object.create(object).init( 
        options, this ) );
      }
    });
  };
};

// Usage:
// With myObject, we could now essentially do this:
// $.plugin('myobj', myObject);

// and at this point we could do the following
// $('#elem').myobj({name: "John"});
// var inst = $('#elem').data('myobj');
// inst.myMethod('I am a method');

扩展阅读

jQuery UI Widget Factory Bridge

/*!
 * jQuery UI Widget factory "bridge" plugin boilerplate
 * Author: @erichynds
 * Further changes, additional comments: @addyosmani
 * Licensed under the MIT license
 */

// a "widgetName" object constructor
// required: this must accept two arguments,
// options: an object of configuration options
// element: the DOM element the instance was created on
var widgetName = function( options, element ){
  this.name = "myWidgetName";
  this.options = options;
  this.element = element;
  this._init();
}

// the "widgetName" prototype
widgetName.prototype = {

    // _create will automatically run the first time this 
    // widget is called
    _create: function(){
        // creation code
    },

    // required: initialization logic for the plugin goes into _init
    // This fires when your instance is first created and when 
    // attempting to initialize the widget again (by the bridge)
    // after it has already been initialized.
    _init: function(){
        // init code
    },

    // required: objects to be used with the bridge must contain an 
    // 'option'. Post-initialization, the logic for changing options
    // goes here. 
    option: function( key, value ){

        // optional: get/change options post initialization
        // ignore if you don't require them.

        // signature: $('#foo').bar({ cool:false });
        if( $.isPlainObject( key ) ){
            this.options = $.extend( true, this.options, key );

        // signature: $('#foo').option('cool'); - getter
        } else if ( key && typeof value === "undefined" ){
            return this.options[ key ];

        // signature: $('#foo').bar('option', 'baz', false);
        } else {
            this.options[ key ] = value;
        }

        // required: option must return the current instance. 
        // When re-initializing an instance on elements, option 
        // is called first and is then chained to the _init method.
        return this;  
    },

    // notice no underscore is used for public methods
    publicFunction: function(){ 
        console.log('public function');
    },

    // underscores are used for private methods
    _privateFunction: function(){ 
        console.log('private function');
    }
};

// usage:

// connect the widget obj to jQuery's API under the "foo" namespace
// $.widget.bridge("foo", widgetName);

// create an instance of the widget for use
// var instance = $("#elem").foo({
//     baz: true
// });

// your widget instance exists in the elem's data
// instance.data("foo").element; // => #elem element

// bridge allows you to call public methods...
// instance.foo("publicFunction"); // => "public method"

// bridge prevents calls to internal methods
// instance.foo("_privateFunction"); // => #elem element

扩展阅读

jQuery Mobile Widgets With The Widget factory

/*!
 * (jQuery mobile) jQuery UI Widget-factory plugin boilerplate (for 1.8/9+)
 * Author: @scottjehl
 * Further changes: @addyosmani
 * Licensed under the MIT license
 */

;(function ( $, window, document, undefined ) {

    //define a widget under a namespace of your choice
    //here 'mobile' has been used in the first parameter
    $.widget( "mobile.widgetName", $.mobile.widget, {

        //Options to be used as defaults
        options: {
            foo: true,
            bar: false
        },

        _create: function() {
            // _create will automatically run the first time this 
            // widget is called. Put the initial widget set-up code 
            // here, then you can access the element on which 
            // the widget was called via this.element
            // The options defined above can be accessed via 
            // this.options

            //var m = this.element,
            //p = m.parents(":jqmData(role='page')"),
            //c = p.find(":jqmData(role='content')")
        },

        // Private methods/props start with underscores
        _dosomething: function(){ ... },

        // Public methods like these below can can be called 
                // externally: 
        // $("#myelem").foo( "enable", arguments );

        enable: function() { ... },

        // Destroy an instantiated plugin and clean up modifications 
        // the widget has made to the DOM
        destroy: function () {
            //this.element.removeStuff();
            // For UI 1.8, destroy must be invoked from the 
            // base widget
            $.Widget.prototype.destroy.call(this);
            // For UI 1.9, define _destroy instead and don't 
            // worry about calling the base widget
        },

        methodB: function ( event ) {
            //_trigger dispatches callbacks the plugin user can 
            // subscribe to
            //signature: _trigger( "callbackName" , [eventObject],
            //  [uiObject] )
            // eg. this._trigger( "hover", e /*where e.type == 
            // "mouseenter"*/, { hovered: $(e.target)});
            this._trigger('methodA', event, {
                key: value
            });
        },

        methodA: function ( event ) {
            this._trigger('dataChanged', event, {
                key: value
            });
        },

        //Respond to any changes the user makes to the option method
        _setOption: function ( key, value ) {
            switch (key) {
            case "someValue":
                //this.options.someValue = doSomethingWith( value );
                break;
            default:
                //this.options[ key ] = value;
                break;
            }

            // For UI 1.8, _setOption must be manually invoked from 
            // the base widget
            $.Widget.prototype._setOption.apply(this, arguments);
            // For UI 1.9 the _super method can be used instead
            // this._super( "_setOption", key, value );
        }
    });

})( jQuery, window, document );

//usage: $("#myelem").foo( options );

/* Some additional notes - delete this section before using the boilerplate.

 We can also self-init this widget whenever a new page in jQuery Mobile is created. jQuery Mobile's "page" plugin dispatches a "create" event when a jQuery Mobile page (found via data-role=page attr) is first initialized.

We can listen for that event (called "pagecreate" ) and run our plugin automatically whenever a new page is created.

$(document).bind("pagecreate", function (e) {
    // In here, e.target refers to the page that was created 
    // (it's the target of the pagecreate event)
    // So, we can simply find elements on this page that match a 
    // selector of our choosing, and call our plugin on them.
    // Here's how we'd call our "foo" plugin on any element with a 
    // data-role attribute of "foo":
    $(e.target).find("[data-role='foo']").foo(options);

    // Or, better yet, let's write the selector accounting for the configurable 
    // data-attribute namespace
    $(e.target).find(":jqmData(role='foo')").foo(options);
});

That's it. Now you can simply reference the script containing your widget and pagecreate binding in a page running jQuery Mobile site, and it will automatically run like any other jQM plugin.
 */

RequireJS And The jQuery UI Widget Factory

Globally And Per-Call Overridable Options (Best Options Pattern)

AMD- And CommonJS-Compatible Modules

如何编写一个优秀的插件?

最后,来看一下我在选择第三方插件时遵循的一些原则,它对你开发插件来说非常有用:

质量

尽可能的遵循javascript和juqery最佳实践。在编辑写插件时,思考一下,这是最佳的解决方案吗?它们是否遵循jQuery 插件开发指南?如果不是,你的代码至少应该干净可读。

兼容性

你的插件都支持哪个版本的jquery?最新的版本是否经过测试? 我更喜欢一些插件作者在必要时更新他们的插件,至少,测试一下插件对jquery新版本的支持情况,确保插件正常运行。

可靠性

你的插件应该有单元测试,单元测试不仅可以验证你的插件能否正常的运行,同时可以保证在不影响用户使用的情况下改进你的插件。我认为用于在生产环境插件都需要进行单元测试,它们并不难写。建议你可以看一下QUnit下的JavaScript自动化单元测试

性能

如果你的插件需要执行大量复杂的计算,或者频繁对DOM进行操作,建议你使用jsPerf.com测试你的代码在不同的浏览器的性能。

文档

如果你打算让其它的开发人员使用你的插件,请确保它有良好的文档。插件有哪些方法?有哪些配置选项?有哪些用户需要注意的陷阱?如果他们无法搞清楚你的插件如何使用,他们可能会寻找别外和替代方案。另外,你的代码也需要良好的注释,这对于使用你插件的其他开发者很有用。 If someone feels they can navigate your code base well enough to fork it or improve it, then you’ve done a good job.

维护

发布一个插件时,预计一下你会有多少时间来提供插件的维护和支持。我们都喜欢在一些社区分享自己的插件,但这需要时间和精力来回答问题,解决问题,并做出改进。最简单的,你可以ReadMe文件中说明,让用户自己决定是否他们自己来修复遇到的问题。

总结

前面,我们探讨了几种可以改善jquery插件开发的设计模式。在特定的场景下,一些模式会比另一些更合适,我希望代码中的注释对有助于你深入理解这些设计模式。

记住,不要为了使用设计模式而使用设计模式,而是需要花些时间去理解这些模式,了解如何选择合适的模式来解决你的问题或适应你的组件。总之,选择合适的设计模式很重要。

-happy coding!

ie6半透明最好解决方法DD_belatedPNG

使用DD_belatedPNG在页面加入ie6专用代码:
&lt;!--[if IE 6]&gt; &lt;script type="text/javascript" src="DD_belatedPNG.js"&gt;&lt;/script&gt; &lt;script type="text/javascript"&gt; /* EXAMPLE */ DD_belatedPNG.fix('.png_bg'); /* string argument can be any CSS selector */ /* .png_bg example is unnecessary */ /* change it to what suits you! */ &lt;/script&gt; &lt;![endif]--&gt;
这里的选择器填写需要半透明效果的元素

IE下overflow:hidden 失效解决方法

在父元素上加上position:relative;

搞笑视频:松鼠、坚果和时间机器

创意搞笑视频: