请选择 进入手机版 | 继续访问电脑版

Bacysoft.cn

 找回密码
 邀请注册
查看: 14134|回复: 3

1.2 源码分析

[复制链接]
发表于 2014-5-15 00:20:36 | 显示全部楼层 |阅读模式

本插件已经发布在官方的应用中心,所以这里仅给出一些关键代码的解释,完整源码可以前往 http://addon.discuz.com/?@bacy_gmt.plugin 下载。

1.2.1 gmt.class.php 页面嵌入模块
这个文件我们前面介绍过,是本插件页面嵌入模块所对应的 PHP 文件,是本插件功能实现的主体。

代码内容并不复杂,首先是根据 Discuz!X 插件机制的要求,定义了一个全局嵌入点类:“plugin_bacy_gmt”,此类包含一个成员函数:“global_cpnav_extra1()”,每当 Discuz!X 加载包含“global_cpnav_extra1” 这个嵌入点的页面时,都会在页面输出前调用此函数,并且将其返回值插入到“global_cpnav_extra1”所在的位置上。至于为什么会这样工作,是由 Discuz!X 插件机制决定的,有兴趣的读者可以自行研究下 Discuz!X 的源码,或者关注本站后续教程。

global_cpnav_extra1() 函数内部主要做了5件事情:
1)获取用户 cookie,用于设置时钟显示的时区,如果没有获取到 cookie,则设置默认时区为 GMT +8,即北京时间。相关代码如下:
  1.   $custom_zone = getcookie('bacy_gmt_cz');
  2.                 if(!$custom_zone) $custom_zone = 8;
复制代码
getcookie() 是 Discuz!X 内置函数,用于获取相关的 cookie 值。读者可以在 source\function\function_core.php 中找到它。

2)获取 Discuz!X 系统自带的时区数据。Discuz!X 系列版本均内置了比较完整的时区信息,我们直接调用就好了。相关代码如下:
  1.   eval("\$timezone = array(".lang('home/template','timezone').");");
复制代码
lang() 也是 Discuz!X 内置函数,用于读取相关模块语言包的数据,第一个参数表示需要加载的语言包文件为:source\language\home\lang_template.php ;第二个参数表示需要加载的字段是:timezone。读者可以自行找到这个语言包文件中的“timezone”看看。

3)加载 JS 库。并不是每个插件都需要自定义一个 JS 文件,但是如果需要用到 JavaScript,那么最好定义一个独立的 JS 文件,并在合适的位置调用它。代码如下:
  1.   $gmt = '<script type="text/javascript" src="./source/plugin/bacy_gmt/gmt.js" ></script>';
复制代码
变量 $gmt 是用来做返回值的,所有需要插入到最终页面的内容都应该添加到 $gmt 里面。

4)定义“世界时钟”的UI界面,这里代码比较长,仅列出最关键的两个地方。代码如下:
  1.   $gmt.= '<a id="bacy_gmt" href="javascript:;" style="text-decoration:none;" onmouseover="delayShow(this, function(){showMenu({\'ctrlid\':\'bacy_gmt\',\'pos\':\'43!\',\'duration\':\'3\'})});"></a>';

  2.                 $gmt.= '<table id="bacy_gmt_menu" class="p_pop" style="display:none;">';
  3. ...这里省略部分代码...完整代码请下载插件...
  4.                 $gmt.= '</table>';
复制代码
这段代码首先定义了一个<a>标签,并定义了 onmouseover 事件,代码意思是当鼠标移动到<a>上时将弹出一个菜单;紧接着下面<table></table>标签所包含的内容就是弹出菜单的全部 HTML 代码。这里需要指出的关键点是:之所以这样设计,是遵循了 Discuz!X 内置 js 函数 showMenu 的规定,关于此函数的详细描述,读者可以参考官网的相关资料:通用JavaScript脚本(AJAX使用和弹层)。大家只要搞清楚这里 <a> 标签和 <table> 标签的 id 值的规律,就基本明白了 showMenu 这个函数的工作原理了。其实就是当鼠标移动到<a>上以后,根据 <a> 的位置,在 <a> 的左下方往右的位置上将 <table> 显示出来。

5)调用 Js 函数,时钟开始计时。代码如下:
  1.   $gmt.= '<script type="text/javascript">startGmtClock()</script>';
复制代码
 楼主| 发表于 2014-5-15 00:23:33 | 显示全部楼层

1.2.2 gmt.js JS 库
gmt.js 文件里面也只有一个函数,即 startGmtClock()。该函数的主要工作流程如下:
1)获取用户设定的时区,该值就是弹出菜单里面<select>标签的值,通过 $('bacy_gmt_timeoffset').value 来访问。
2)根据用户指定的时区计算该时区的标准时间,并将数据格式化以后显示在指定位置,即:$('bacy_gmt').innerHTML。
3)设定定时器,每 1000ms 更新时钟,即1秒中。
因为代码相对简单,这里就不贴出来了。

1.2.3 gmt.inc.php 标准插件模块
在 Discuz!X 插件开发中,除了前面介绍的页面嵌入模块(后缀为:.class.php)外,其他模块本人将他们统称为标准模块(后缀为:.inc.php)。使用标准模块可以开发独立于 Discuz!X 的功能的插件,而使用页面嵌入模块则可以开发与 Discuz!X 结合十分紧密的功能,当然这些都不是绝对,当你熟悉了 Discuz!X 开发机制后,完全可以根据需要加以运用。在本例中,仅仅是为了像读者展示此类模块的使用方法,与“世界时钟”的主体功能无关。此模块代码很简单,全部代码如下:
  1. <?php
  2. if(!defined('IN_DISCUZ')) {
  3.         exit('Access Denied');
  4. }
  5. $act = $_GET['act'];

  6. switch($act){
  7.         case 'aboutme':
  8.                 include template('bacy_gmt:gmt');
  9.                 exit;
  10.         default:
  11.                 exit;
  12. }
  13. ?>
复制代码
首先定义了一个变量 $act,顾名思义,这个变量用于获取用户的操作类型。然后通过 switch 结构跳转到对应的代码。
include template(); 是 Discuz!X 加载模块的方法,template() 函数的参数为需要加载的模板名称。template()函数在执行的时候通常会检测对应的模板文件是否有对应的缓存文件,如果有则直接加载缓存的文件,如果没有则要先按照 Discuz!X 模板机制解析模板文件并生成对应的缓存,然后再加载缓存。

那么这个模块是如果调用的呢,在本例中起什么作用呢?请看下面的代码(gmt.class.php 文件第 20 行):
  1. <a href="plugin.php?id=bacy_gmt:gmt&act=aboutme" onclick="showWindow(\'gmt_aboutme\',this.href);return false;">[About Me]</a>
复制代码
这个<a>标签的 “href” 属性就是访问此模块的超链接,并提供了一个 act 参数。也就是说当用户将鼠标移动到“世界时钟”上面的时候,将弹出一个选择时区的菜单,菜单右上角有一个链接“About Me”,当用户点击此链接后,将执行 onclick 中定义的代码,即调用 Discuz!X 内置 js 函数 showWindow(),此函数将显示一个 id 为 “gmt_aboutme” 的窗口。showWindow 的具体用法参考官网提供的资料,与 showMenu 在一起。

这里简单解释一下 showWindow 的工作原理:
1)showWindow() 内部其实是通过 ajaxget() 函数来访问指定的 url 的。
2)ajaxget() 是 Discuz!X 内置的专门用于 ajax 相关操作的函数,整个 Discuz!X 用到 ajaxget 或者 ajaxpost 的地方非常多。关于 ajaxget 或者 ajaxpost 的更多信息,可以参考:Discuz!X 源码分析之 ajaxget() 函数 以及 Discuz!X 源码分析之 ajaxpost() 函数
3)ajaxget() 的返回数据会插入到页面上一个 id 为 “append_parent” <div> 块中,通常返回的内容就是将要显示的窗口。然后通过设置 display 属性为空,窗口就显示出来了。

 楼主| 发表于 2014-5-15 00:24:45 | 显示全部楼层
本帖最后由 bacy001 于 2014-5-15 00:28 编辑

1.2.4 template/gmt.htm 插件模板
并不是每个插件都需要模板,本插件引入标准模块以及模板文件仅仅是为了向读者展示 Discuz!X 插件的工作原理。先看源码:
  1. {template common/header}

  2. <h3 class="flb">
  3.         <em>{lang bacy_gmt:sysname}</em>
  4.         <span>
  5.                 <a href="javascript:;" class="flbc" onclick="hideWindow('gmt_aboutme')" title="{lang close}">{lang close}</a>
  6.         </span>
  7. </h3>

  8. <div style="width:250px;padding:10px;">
  9.         <div class="bm bmw">
  10.                 <div class="bm_c">
  11.                         <dl class="bbda">
  12.                                 <dt>{lang bacy_gmt:ver}1.00</dt>
  13.                                 <dt>{lang bacy_gmt:auth}{lang bacy_gmt:link}</dt>
  14.                         </dl>
  15.                 </div>
  16.         </div>
  17. </div>

  18. {template common/footer}
复制代码
通常模板代码的开头和结尾都要有:{template common/header} 和 {template common/footer},当 url 的调用是非 ajax 请求时(比如:用户浏览器直接输入,或者点击相关链接)你看到的将是 Discuz!X 的标准页面,即包含完整的由template\default\common\header.htm 模板文件生成的头部以及 template\default\common\footer.htm 模板文件生成的尾部;
而如果 url 请求来自 ajax,则 header 和 footer 都会被忽略,取而代之的是一个仅包含中间部分的 xml 标准文档,也就是之前提到的 ajaxget 的返回值,也就是 “aboutme” 的窗口代码。

模板中类似 “{lang bacy_gmt:sysname}” 这样的代码是用来调用的语言包对应字段的文字的,hideWindow() 则是用来关闭窗口的。
 楼主| 发表于 2014-5-15 00:31:37 | 显示全部楼层
1.2.5 bacy_gmt.lang.php 语言包文件
文件结构没有任何变化,仅仅是添加了相关字段,完整代码如下:
  1. <?php
  2. $templatelang['bacy_gmt'] = array(
  3.         'sysname' => '世界时钟',
  4.         'ver' => '版本:',
  5.         'auth' => '作者:',
  6.         'link' => '<a href="http://www.Bacysoft.cn">Bacysoft.cn</a>',
  7. );

  8. $scriptlang['bacy_gmt'] = array(
  9.         'sysname' => '世界时钟',
  10.         'info' => '请选择您所在的时区:',
  11.         'about' => 'About Me',
  12. );
  13. ?>
复制代码
至此,所有的代码都完成了,插件的制作就剩下最后一步了!加油!
您需要登录后才可以回帖 登录 | 邀请注册

本版积分规则



京ICP备08000958号-1|腾讯云|阿里云|联系方式|Bacysoft.cn

GMT+8, 2024-3-19 15:45 , Processed in 0.016849 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表