第6章 函数插件
本章涵盖以下内容:
定义一个函数插件;
通过函数插件本地化内容;
通过函数插件访问cookie。
前一章中介绍的集合插件用来操作在页面上通过选择或遍历得到的一组元素。但是开发者也可以创建一些不操作集合元素,而是在jQuery框架上提供一些工具函数的插件。这就是函数插件。
这种类型插件的例子包括Debug插件,用来记录一些调试信息;还包括Cookie插件,用来操作网站的cookie(将在6.2节中详述)。与前面的插件一样,只有想不到,没有做不到。
因为函数插件不操作元素集合,也通常不与UI组件打交道,所以它们非常容易实现。尽管开发者可以把这些函数定义为独立的JavaScript函数,但是把它们创建在jQuery的命名空间中可以得到很多好处。这样做可以降低全局命名空间的混乱,同时也降低了命名冲突的风险。它们通常也会使用jQuery本身,把它们包含在jQuery中能提供一致的使用方式。它们还旨在提供更易用的功能以及隐藏跨浏览器的差异(jQuery背后的核心原则)。
在第5章中,通过扩展$.fn来定义开发者的集合插件,把它集成到jQuery内置的集合处理中。对于函数插件,开发者直接扩展jQuery($),并且直接通过它来调用。
6.1 定义插件
作为函数插件的一个具体例子,开发者可以开发一个工具来协助自己网页的本地化。它根据特定的语言和地区,只加载必需的JavaScript文件来定制开发者的站点。
6.1.1 本地化插件
基于5.5.2节中描述的本地化方案,这个工具假定相关的JavaScript文件只由它们的语言或地区码来区别。当发生请求时,这个插件以语言和地区码的升序来加载这些文件,每个都覆盖前一个,这样能得到给定的语言和地区的最佳匹配结果。
例如,假定开发者有表6.1中的这些文件。每一个都代表不同的语言和地区组合,并设置一个公共变量(greeting)来显示消息。
为了把自己的页面欢迎词本地化为一种特定语言,开发者可以使用这段代码:
这个插件将顺序加载下列文件,从最少匹配到最佳匹配——greeting.js,greeting- en.js,greeting-en-AU.js——得到最匹配的澳大利亚英语:“G’day”。如果请求的语言是加拿大英语(en-CA),因为没有greeting-en-CA.js文件,链条将在第二个文件时停止(标准英语),它将产生欢迎语“Good day”。如果请求了科萨语(xh),会得到默认欢迎词:“Hello”。
当这个文件被加载和执行之后,就可以以通常的方式访问它们设置的那个变量。
如果调用localise()时没有指定任何语言,它就使用浏览器的默认语言。可以通过$.localise.default
Language容易地得到这个默认语言。
本地化不仅限于显示给最终用户的文本,还可以影响显示和外观的其他方面。图6.1展示了Datepicker的一些本地化。
选择年和月的下拉列表顺序不同;
每个日历中一周的开始日不同:法语是周一,日语是周日,阿拉伯语是周六;
阿拉伯语从右往左读,其他两个从左往右读。
现在读者应该知道这个插件的设计目的了,可以使用前一章中介绍的原则和框架来实现它。
6.1.2 框架代码
尽管上一章中介绍的插件框架大部分都不适用于函数插件,但是还是有几个应该保留的特性。开发者应该继续坚持“利用作用域隐藏实现细节”和“不要依赖$与jQuery的等同性”。解决方案与前面介绍的相同。
通过定义一个匿名函数来创建一个作用域1,立即调用它来创建它的作用域并执行它内部的代码2。通过定义一个参数$并且在调用时为其提供jQuery的引用,保证了它们在函数体内指向同一个对象。
这个插件同时也遵守了“在所有地方使用唯一的名字”和“把一切都放在jQuery对象中”原则。这里不必支持链式调用,因为不牵扯jQuery集合。当没有指定语言时使用浏览器的默认语言,这遵守了”使用合理的默认值”原则。
6.1.3 加载本地化文件
程序清单6.2展示的localise函数实现了插件的主要功能:根据请求的语言和地区,加载一个或多个本地化文件。
通过把这个函数声明为一个属性,把它直接附加到jQuery中1。然后就可以在开发者的页面上通过 jQuery 对象来访问这个函数。不需要为它选择任何操作元素,因为它应用于整个页面。
这个函数通过多个参数来改变它的行为。除了第一个参数,其余都是可选的。如果没有设置,则使用一个合适的默认值。使用它们的类型来确定它们所代表的含义。程序清单6.3展示了如何处理这些参数。
开发者必须指定一个(string)或一组(string)包名,以供这个函数使用。因为其余的参数都是可选的,代码就必须能区分它们。第二个参数是一个可选的语言代码(string)或者一组设置(object),它的每个属性都是一个独立的参数。为了使后续的处理更容易,所有单独的参数值都被收集到一个设置对象中,就像最初就提供了这个对象一样。如果第二个参数不是这些类型,这些参数被顺序移动1并继续处理下一个。
其余的参数包括一个用来指定是否需要重新加载基础本地化文件的可选标志(boolean)2,一个(string)或一组(string)可选的路径用来指定从哪里找到本地化文件3,一个可选的超时时间(number)4,一个可选的异步标志(boolean)5,以及一个可选的加载完成时的回调函数。缺失的参数被设置为默认值。
根据参数中提供的设置对象(覆盖所有默认值)或者单个参数值来创建一个累积设置对象6。检查path是一个还是多个路径,然后把它转换为后面需要的格式7。把后面Ajax需要用到的一些选项收集起来以便于后续使用8。
当参数处理完成之后,这个插件接下来依次处理所有指定的包。
开发者定义了一个内部函数1来处理单个包。每个都加载为基础文件(如果设置了加载基础)2,然后加上2字符的语言代码3,最后再加上一个5字符的语言和地区代码(如果有)4。这些文件被放在一个队列中以便顺序读取。
使用jQuery内置的ajax函数来加载单个文件5,从队列中的第一个文件开始,指定返回内容是“script”并以这个类型执行。因为默认使用同步加载(为了保证后续的代码可以依赖返回的内容),所以有一个超时时间。或者可以在调用localise时指定一个额外的参数来使用异步加载,同时指定一个在加载完成时调用的回调函数6。如果队列中还有其他文件,则递归调用处理下一个7。
当单个包和其中文件的处理流程定义好之后,找到需要的语言和地区8,然后依次加载每个包9。
为了实现这个插件所宣扬的功能,这里定义了另一个函数来提供地方化的版本:
本书的网站上可以下载到这个插件的完整代码。