65.9K
CodeProject 正在变化。 阅读更多。
Home

用于自适应 960 网格系统的 jQuery 插件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (4投票s)

2011年10月3日

GPL3

8分钟阅读

viewsIcon

34914

downloadIcon

340

讨论开发用于自适应 960 网格系统的 jQuery 插件的文章。

引言

我一直是 960.gs 工作中的忠实粉丝,在我看来,它在网页布局和设计上的简洁方法很可能会引起他人的兴趣。

在过去几年里,我对 jQuery 的兴趣同样巨大(可能更多)。主要是因为我喜欢它将 JavaScript 开发简化为可重用库的想法,这样我就不必弄乱自己的开发。所以最近,当我偶然发现了 http://adapt.960.gs 的一些 JavaScript 代码,用于使网页能够适应不断变化的浏览器窗口大小时,自然而然地,我开始寻找一个更简单的方法。

当然,我希望能够以 jQuery 插件的形式来完成,从而简化我的日常开发。

所以在这篇文章中,我将详细介绍开发一个 jQuery 插件的细节,同时创建一个我们都可以在日常开发中使用的东西。

背景

好了,对于所有 jQuery 开发者(无论是老手还是新手),你们可能知道插件应该如何工作,对吧?

就我个人而言,我总是对那些插件感到惊叹,在使用这些插件时,作为开发者,只需要写一行代码,然后所有这些非常酷的功能就会自动实现。你知道那种通常需要你写几十甚至几百行代码才能完成的事情(更不用说花费的时间)。

别误会我的意思,我喜欢复杂的挑战,但一旦它们被我或其他人解决了,我的兴趣就会减弱。在我看来,改进轮子的设计只有那么多方法。

我希望能够将类似以下内容的内容整齐地放置在一个网页的脚本块中

// variable to hold instance of my plugin
var plugin;

$(function() {
    plugin = new $.jQueryAdaptive960(window);

    // other code to be run on page load
 });

jQuery 插件基础

让我们通过展示一个简单的框架来快速回顾一下 jQuery 插件的基础知识。

;(function($) {
    $.jQueryAdaptive960 = function(element, options) {
	var defaultOptions = {
	}

	// save the element
         	var pluginElement = el;

	var jQuery960 = this;

	var init = function() {
	    if(options) {
		jQuery960.settings = 
			$.extend(defaultOptions, options);
	    }
	    else {
		jQuery960.settings = defaultOptions;
	    }

	    // other init stuff for you plugin goes here
	}

	// your own plugin development stuff goes here

	// always keep this at the end
	init();
    }
}) (jQuery); 

看起来很简单,对吧?让我更详细地解释一下。

插件的第一行和最后一行是我们如何使这个控件成为 jQuery 的一部分,同时确保我们仍然可以访问 jQuery 本身。我们有了这个出色的框架,因此我们希望确保在我们的插件开发中仍然可以使用它。

插件的入口从 $.jQueryAdaptive960 = function(element, options) 开始,在这里创建插件对象以及将与之交互的接收对象。

传递给我们的 jQuery 插件的第一个参数是 element,在开发 jQuery 插件的约 99% 的情况下,你会找到控件或页面元素。对于这个插件,我们将传入 window,原因稍后解释。

第二个参数仅仅是页面开发者和插件用户可能希望传入的任何选项。非常重要的是,你要理解传入插件的选项是可选的,因为有时开发者只想让它工作。稍后在 init 函数中,我们将看到如何处理这种情况。

现在让我们进入插件更核心的部分。

插件设置

还记得我说过理解某些开发者永远不想将任何选项传递给你的插件是很重要的吗?考虑到这一点,你会想确保你的插件有一组默认选项供其运行。我们通过创建一个对象来包含我们将使用的 defaultOptions 来实现这一点。

我不想深入探讨 JavaScript 面向对象编程的细节,但以下是我们如何将我们的 public 属性暴露给外部世界的方式。

// save the element
var pluginElement = el;

var jQuery960 = this;

对于所有面向对象的纯粹主义者(是的,你知道你是谁),请不要争论 JavaScript 不是面向对象的语言。

任何分配给 jQuery960 的内容现在都将成为插件使用者的可公开访问的属性或函数。

最后,我们将传递给我们的 pluginElement 保存起来,以便在代码的其他地方引用它。

插件初始化

再迈出一步,你就可以获得官方(好吧,可能不是官方)的 jQuery 插件魔法师徽章了。由于我们已经包含了 jQuery 框架,所以最后一步对我们来说更加简化了。

var init = function() {
    if(options) {
	jQuery960.settings = $.extend(defaultOptions, options);
    }
    else {
	jQuery960.settings = defaultOptions;
    }

    // other init stuff for you plugin goes here
}

// your own plugin development stuff goes here

// always keep this at the end
init();

还记得我说过有时开发者只想使用你的插件而不传递任何参数吗?嗯,在插件的初始化中,我们将通过检查是否传递了任何内容来处理这种情况。如果收到了某些内容,我们将使用 jQuery 的 $.extend() 函数调用来更新我们的默认设置。

最后,在插件的最后,我们将调用 init() 函数,以确保所有内容都已初始化。作为个人重要的一点,我喜欢将 init() 放在插件的最后一行,这确保了所有内容都已加载并完全可供插件的其余部分访问。

Using the Code

现在插件的基础已经处理完毕,让我们一起来看看如何使用它的一个工作示例。

此时,我假设你已经有机会查看 http://adapt.960.gs,因为目标是将它打造成一个 jQuery 插件。记住,目标是为我们的插件用户提供一些简单易用的东西,由插件处理一切。我认为类似以下内容会有效。

// variable to hold instance of my plugin
var plugin;

$(function() {
    plugin = new $.jQueryAdaptive960(window);

    // other code to be run on page load
 });

默认设置

为了保持简单,我认为最好将所有必需的 CSS 文件与插件捆绑在一起。同时,我想尽量照顾那些希望更进一步的人。

以下内容应足以同时支持开发人员及其个人使用。

var defaultOptions = {
    ranges: ['0px    to 760px  = mobile.css',
    '760px  to 980px  = 720.css',
    '980px  to 1280px = 960.css',
    '1280px to 1600px = 1200.css',
    '1600px to 1920px = 1560.css',
    '1940px to 2540px = 1920.css',
    '2540px           = 2520.css'],
    path: 'jquery960/css/',
    onResize: function () { },
    onRotate: function () { }
}

为了使此插件具有可扩展性,我将 CSS 信息中的 rangespath 作为选项,开发人员可以替换它们。然后我添加了两个回调函数,以便在浏览器大小改变或旋转时通知开发人员。

如果你阅读了 http://adapt.960.gs 的代码,你会注意到他们有一个 dynamic 变量来打开/关闭动态更新页面的功能。起初,我将该选项设为可配置,但随后我想到,如果他们不想使其动态化,那么他们很可能就不需要该插件了。

插件初始化

设置就绪后,现在让我们进入插件的初始化。我们的初始化步骤应该非常简单。在这个阶段,我们的大部分工作将是订阅事件,以通知插件浏览器大小何时改变或发生倾斜。

var init = function () {
    if (options) {
        jQuery960.settings = $.extend(defaultOptions, options);
    }
    else {
        jQuery960.settings = options;
    }

    if (pluginElement.addEventListener) {
        pluginElement.addEventListener('resize', reactiveDisplay, false);

        if (pluginElement.onorientationchange) {
            pluginElement.addEventListener
		('orientationchange', rotateDisplay, false);
        }

        setTimeout(checkDisplayOrientation, 1000);
    }
    else if (pluginElement.attachEvent) {
        // old ie support and there is no support for orientation
        pluginElement.attachEvent('onresize', reactiveDisplay);
    }
    else {
        // definitely no orientation support
        pluginElement.onresize = reactiveDisplay;
    }

    adaptDisplay();
}

正如之前所说,基本上所做的一切都是订阅事件。这应该使插件能够跨大多数(希望是全部)正在运行的浏览器正常工作。需要注意的重要一点是最后一行,其中调用了 adaptDisplay()

屏幕适应

我无意逐行解释 adaptDisplay() 函数中的代码,其中细节在于 while 循环,它会遍历 defaultOptions.ranges,查找与浏览器当前尺寸匹配的范围。

var adaptDisplay = function () {
    ....

    // get the width of the browser
    var width = pluginElement.innerWidth || 
		pluginElement.document.documentElement.clientWidth || 
		pluginElement.document.body.clientWidth || 0;

    // loop through each of the items inside of defaultOptions.ranges
    while (index--) {
        item = defaultOptions.ranges[index].split('=');

        range = item[0];
        cssFile = item[1] ? item[1].replace(/\s/g, '') : index;

        // check to see if a range has been specified
        is_range = range.match('to');

        // get the min and max values for the range
        val_1 = is_range ? parseInt(range.split('to')[0], 10) : parseInt(range, 10);
        val_2 = is_range ? parseInt(range.split('to')[1], 10) : undefined;

        // check to see if the width of the browser falls 
        // within the range of the current range setting
        if ((!val_2 && index === (rangeLen - 1) && width > val_1) || 
				(width > val_1 && width <= val_2)) {
            url = defaultOptions.path + cssFile;
            break;
        }
        else {
            url = '';
        }
    }

    ....
}

就我们的插件默认设置而言,总会找到一个包含 CSS 文件的有效范围来匹配浏览器当前的尺寸。当你调整浏览器大小时,你会注意到这段代码被执行了,如果你查看页面的源代码(不是原始源代码),你会看到 CSS 文件链接正在被更改。

页面本身适应新尺寸是浏览器与它被告知渲染的 CSS 文件相结合的内部工作机制。

查看页面源代码

重要提示

查看页面源代码时,请确保你正在查看活动文档。如果你没有在头部看到类似以下内容的行……

<link href="jquery960/css/###.css" rel="stylesheet" />

……那么你很可能没有在查看页面的活动源代码。

通知事件

在所有通知处理程序中需要注意的重要一点是它们如何向使用插件的开发人员进行通知。还记得最初的想法是允许开发人员使用插件,并且只需要提供它将工作的 window 吗?这种情况是通过为回调函数提供一个默认函数处理程序来处理的。

var defaultOptions = {
    ....
    onResize: function () { },
    onRotate: function () { }
}

如果开发人员希望扩展插件的使用并被通知这些事件,他们只需在如何使用插件时更改他们的调用。

以下是如何覆盖控件并被通知浏览器何时被调整大小或倾斜的示例。

$(function () {
    var plugin = new $.jQueryAdaptive960(window, { onResize: function () { }, 
			onRotate: function () { } })
});

关注点

有关这个令人惊叹的 JavaScript 框架的更多信息,请访问 https://jqueryjs.cn/

有关 960 网格系统的更多信息,请访问 http://960.gs/

历史

  • 2011年10月3日:首次发布
© . All rights reserved.