uchome开发之showMenu解析(一)
- 格式:doc
- 大小:36.50 KB
- 文档页数:7
二次开发资料整理目录【UCHome二次开发】uchome文件体系介绍......................... 错误!未定义书签。
站点结构图 ........................................................ 错误!未定义书签。
UCHOME安装后的主要目录与文件介绍.................................. 错误!未定义书签。
文件入口参数列表及详细介绍 ........................................ 错误!未定义书签。
数据调用图示 ...................................................... 错误!未定义书签。
入口文件分析 ...................................................... 错误!未定义书签。
【UCHome二次开发】基础....................................... 错误!未定义书签。
数据调用 .......................................................... 错误!未定义书签。
eval的使用........................................................ 错误!未定义书签。
直接外部文件的扩展 ................................................ 错误!未定义书签。
【UCHome二次开发】文件解析................................... 错误!未定义书签。
文件解析: ........................................................ 错误!未定义书签。
menu命令的用法-回复menu命令是一种在计算机操作系统中使用的指令,它通常用于显示可用的选项列表,并允许用户选择其中的一个选项。
menu命令的主要目的是通过简化用户界面,使用户能够更轻松地与计算机进行交互。
在本文中,我们将详细介绍menu命令的用法,并提供一些示例来说明其具体实施步骤。
要使用menu命令,您需要先了解一些基本的语法和关键字。
menu命令通常包含一系列选项,每个选项都有一个唯一的标识符和一个对应的操作描述。
以下是menu命令的通用语法:menu [选项1]:[操作1];[选项2]:[操作2];...;[选项n]:[操作n]其中,选项表示用户可以选择的不同选项,操作是与每个选项相关联的具体任务。
这些选项和操作由冒号(:)分隔,每个选项和操作由分号(;)分隔。
在一些操作系统中,您还可以为每个选项指定一个数字作为快捷键。
让我们举一个简单的例子来说明menu命令的用法。
假设我们正在编写一个文本编辑器,并且我们想要添加一个菜单选项,用于保存当前编辑的文档。
我们可以使用menu命令来实现这个功能。
以下是一个可能的menu命令的示例:menu Save:save_file;Exit:exit_program在这个示例中,我们定义了两个选项:“Save”和“Exit”。
选项“Save”表示保存当前编辑的文档,它与操作“save_file”相关联。
选项“Exit”表示退出程序,它与操作“exit_program”相关联。
在实际使用中,menu命令通常是与一些其他命令结合使用的。
例如,在Unix/Linux系统中,menu命令可以与shell脚本一起使用,以提供一个交互式菜单界面。
以下是一个简单的示例:bash#!/bin/bashmenu "Option 1":echo "You selected Option 1";"Option 2":echo "You selected Option 2";"Option 3":echo "You selected Option 3"在这个示例中,我们使用了一个shell脚本来定义一个含有三个选项的菜单。
1.<!–{xxxxx}–> 在html里面表示将一段代码注释掉,而在uchome模板里表示嵌入了php语句。
用一个花括号包起来,里面输入php的功能代码,这样在解析的时候,可以把它当做php语句来处理。
2.在模板里面,是可以直接显示php的变量的,模板解析函数会将这些变量替换成实际的数字或者字符。
3.设置变量的值<!–{eval $_TPL['titles'] = array(’日志’, ‘随便看看’);}–>表示将$_TPL['titles']变量设置为array(’日志’, ‘随便看看’);调用另外一个模板文件进来<!–{template header}–>实际上相当于php中的template(”header”) 即解析/template/default/header.htm文件条件判断<!–{if xxx}–><!–{/if}–>类a.<!–{if $a==’’}–>如果满足条件,这里显示一些东西<!–{/if}–>b.<!–{if $a==’'}–>如果满足条件,这里显示一些东西<!–{else}–>否则显示其他的东西<!–{/if}–>循环显示<!–{loop}–><!–{/loop}–>类<!–{loop $list $value}–>$value[name] : $value[name]<!–{/loop}–>第一个参数是用于循环的数组,第二个参数是对数组中每一项循环时项的值。
解析后:<?php if(is_array(变量){foreach (变量as $value){?>输出的内容<?php }}?><!–{loop $list $key $value}–>$value[name] : $value[name] <br /><!–{/loop}–>解析后:<?php if(is_array(变量){foreach (变量as $key=>$value){?>输出的内容<?php }}?>第一个参数是用于循环的数组,第二个和第三个参数分别是对数组中每一项循环时项的键名和值。
实例:<a href=”cp.php?ac=msg” id=”show_pay” onclick=”ajaxmenu(event, this.id,2);hidden();”>查看收费标准</a>href就是ajax要请求的页面,直接用ajaxmenu条用即可。
然后在服务器端处理页面输出结果,如果是大量的html,可以单独做成模板页面,通过参数把大量的ajax输出合到一个页面,如果是少量的输出直接:showmessage($mess)就可以了,注:echo $mess;是不行的,好像uchome已经对结果做了处理,没有细究!在刚开始发现放到自己搞的页面来后不会弹出那个框,而是直接跳转了过去,原来是在自己的页面里面使用了prototype.js,并且Ajax对象的命名和uchome的冲突导致!在这里我只是在首页用prototype.js,所以我直接把header的内容写到首页里面了,还有其他的解决方法,诸如修改prototype.js,或者在uchome的不同页面实现不同的js调用,具体要根据自己的开发需求来定。
注:不要在php里面直接echo 数据或者在php页面里面直接输入一段html代码,这样ajaxmenu有时会出现问题,就是只出现一个小框框。
最好用template(”)涵数包括一个模板面将数据输出到模板页里。
模板里面您仍可以使用下面的结构:1 <!–{template header}–>2 <h1>付费标准</h1>3 <a href=“javascript:hideMenu();” class=“float_del” title=“关闭”onclick=’show();’>关闭</a>4 <div class=“popupmenu_inner” id=“show_pay”>5 这里是弹出框要显示的内容6 </div>7 <!–{template footer}–> “这里是弹出框要显示的内容”是ajaxmenu要取到的数据,header,footer部分uch已经用正则去掉了。
uchome_ROOT/为uchome的根目录第一步:定位到uchome_ROOT/source/do_login.php,找到如下函数:PHP代码∙//同步获取用户源∙if(!$passport = getpassport($username, $password)) {∙showmessage(…login_failure_please_re_login‟,‟do.php?ac=‟.$_SCONFIG['log in_action']);∙}上示函数便是登陆的第一步处理函数,再次定位:uchome_ROOT/source/function_common.php,找到如下函数:PHP代码∙//获取用户数据∙function getpassport($username, $password) {∙ global $_SGLOBAL, $_SC;∙∙ $passport = array();∙ if(!@include_once S_ROOT.‟./uc_client/client.php‟) {∙showmessage(‟system_error‟);∙ }∙∙ $ucresult = uc_user_login($username, $password);∙ if($ucresult[0] > 0) {∙ $passport['uid'] = $ucresult[0];∙ $passport['username'] = $ucresult[1];∙ $passport['email'] = $ucresult[3];∙ }∙ return $passport;∙}至此,我们可以发现现在开始和uc_client相关函数关联了.我们进入uc_client文件夹,开始分析,定位至:uchome_ROOT/uc_client/client.phpPHP代码∙/**∙ * 用户登陆检查∙ *∙ * @param string $username 用户名/uid∙ * @param string $password 密码∙ * @param int $isuid 是否为uid∙ * @param int $checkques 是否使用检查安全问答∙ * @param int $questionid 安全提问∙ * @param string $answer 安全提问答案∙ * @return array (uid/status, username, password, email)∙数组第一项∙ 1 : 成功∙ -1 : 用户不存在,或者被删除∙ -2 : 密码错∙*/∙ 448function uc_user_login($username, $password, $isuid = 0, $checkques = 0, $que stionid = ”, $answer = ”) {∙ $isuid = intval($isuid);∙//define(…UC_API_FUNC‟, UC_CONNECT == ‟mysql‟ ? ‟uc_api_mysql‟ : ‟uc_a pi_post‟);∙ $return = call_user_func(UC_API_FUNC, ‟user‟,‟login‟,array(…username‟=> $username, ‟password‟=>$password,‟isuid‟=>$isuid,‟checkques‟=>$checkques,‟questionid‟=>$questionid,‟answer‟=>$answer));∙ return UC_CONNECT == ‟mysql‟ ? $return : uc_unserialize($return);∙}因为是mysql,故,UC_API_FUNC的值为uc_api_mysql,通过call_user_func()函数,将参数传给uc_api_mysql(),下面进入最关键的函数了:uchome_ROOT/uc_client/client.php => uc_api_mysql()PHP代码∙/**∙ * MYSQL 方式取指定的模块和动作的数据∙ *∙ * @param string $model 请求的模块∙ * @param string $action 请求的动作∙ * @param string $args 参数(会加密的方式传送)∙ * @return mix∙ */∙ 116∙function uc_api_mysql($model, $action, $args=array()) {∙ //$model = ‟user‟,$action=‟login‟,∙ //$args = Array ( [username] => test2 [password] => test [isuid] => 0 [ch eckques] => 0 [questionid] => [answer] => )∙ global $uc_controls;∙ if(empty($uc_controls[$model])) {∙ //UC_ROOT uc_client/∙ include_once UC_ROOT.‟./lib/db.class.php‟;∙ include_once UC_ROOT.‟./model/base.php‟;∙ include_once UC_ROOT.”./control/$model.php”;∙eval(“\$uc_controls['$model'] = new {$model}control();”);∙ //uc_client/control/user.php,usercontrol()类(继承至base基类)实例化∙ }∙ if($action{0} != ‟_') {∙ $args = uc_addslashes($args, 1, TRUE);∙ $action = ‟on‟.$action;//onlogin,usercontrol()中的方法,可以考虑改造此函数以实现预定功能∙ $uc_controls[$model]->input = $args;//base.php,base基类的方法∙ //return Array ( [0] => 3 [1] => test2 [2] => test [3] => test@ [4] => 0 )∙∙ return $uc_controls[$model]->$action($args);//返回预定数组,供调用函数分析∙ } else {∙ return ”;∙ }∙}我们看看usercontrol类的onlogin()方法:uchome_ROOT/uc_client/control/user.phpPHP代码∙//note public 外部接口登陆接口∙function onlogin() {∙ $this->init_input();∙ $isuid = $this->input(…isuid‟);∙ $username = $this->input(…username‟);∙ $password = $this->input(…password‟);∙ $checkques = $this->input(…checkques‟);∙ $questionid = $this->input(…questionid‟);∙ $answer = $this->input(…answer‟);∙ if($isuid) {∙ $user = $_ENV['user']->get_user_by_uid($username);∙ } else {∙ $user = $_ENV['user']->get_user_by_username($username);∙ }∙//这部分即可改动∙ $passwordmd5 = preg_match(…/^\w{32}$/‟, $password) ? $password : md 5($password);∙ //note 用户名不存在∙ if(empty($user)) {∙ $status = -1;∙ } elseif($user['password'] != md5($passwordmd5.$user['salt'])) {∙ $status = -2;∙ } elseif($checkques && $user['secques'] != ” && $user['secques'] != $_ENV ['user']->quescrypt($questionid, $answer)) {∙ $status = -3;∙ } else {∙ $status = $user['uid'];∙ }∙ $merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser($u sername) ? 1 : 0;∙ return array($status, $user['username'], $password, $user['email'], $merge );∙}可以改成如下形式:PHP代码∙//note public 外部接口登陆接∙ function onlogin($type=‟myself‟) {∙ $this->init_input();∙ $isuid = $this->input(…isuid‟);∙ $username = $this->input(…username‟);∙ $password = $this->input(…password‟);∙ $checkques = $this->input(…checkques‟);∙ $questionid = $this->input(…questionid‟);∙ $answer = $this->input(…answer‟);∙ if($isuid) {∙ $user = $_ENV['user']->get_user_by_uid($username);∙ } else {∙ $user = $_ENV['user']->get_user_by_username($username);∙ }∙∙ $passwordmd5 = preg_match(…/^\w{32}$/‟, $password) ? $password : md5($password);∙∙$type=‟myself‟;∙if($type==‟myself‟)∙ {∙ echo ‟$password:‟.$password.‟<br>‟;∙ $testmd5 = md5(…test‟);//假设数据库中保持的所有的密码为test∙// print_r($passwordmd5);∙// print_r($user);∙ //note 用户名不存在∙∙ if(emptyempty($user)) {∙ $status = -1;∙ } elseif($user['password'] != $passwordmd5) {∙ $status = -2;∙ } elseif($checkques && $user['secques'] != ” && $user['secques'] != $ _ENV['user']->quescrypt($questionid, $answer)) {∙ $status = -3;∙ } else {∙ $status = $user['uid'];∙ }∙// echo ‟<br>$statusz:‟.$status.‟<br>‟;∙// die();∙ }else{∙ if(emptyempty($user)) {∙ $status = -1;∙ } elseif($user['password'] != md5($passwordmd5.$user['salt'])) { ∙ $status = -2;∙ } elseif($checkques && $user['secques'] != ” && $user['secques'] != $ _ENV['user']->quescrypt($questionid, $answer)) {∙ $status = -3;∙ } else {∙ $status = $user['uid'];∙ }∙ }∙ $merge = $status != -1 && !$isuid && $_ENV['user']->check_mergeuser ($username) ? 1 : 0;∙ return array($status, $user['username'], $password, $user['email'], $me rge);∙ }至此,我们可以更改uchome默认的认证方式了,如果这里更改了,以后相关的也需要作出更改,这个就留下大家自己去跟踪调试了.tips:uchome_ROOT/uc_client/model/user.php下还有一个check_login(),这个函数暂时没有找到调用的地方.PHP代码∙function check_login($username, $password, &$user) {∙ $user = $this->get_user_by_username($username);∙ if(empty($user['username'])) {∙ return -1;∙ } elseif($user['password'] != md5(md5($password).$user['salt'])) {∙ return -2;∙ }∙ return $user['uid'];∙}eclipsePDT还是不错的,可以试试这个IDE.。
showpage用法-概述说明以及解释1.引言1.1 概述showpage是一种在文档中使用的命令,用于显示当前页面的内容。
它是一种常用的命令,被广泛应用于各种文档或报告的编写中。
通过使用showpage命令,读者或编辑者可以清晰地查看当前页面的布局、文字、图片等内容。
在本篇文章中,我们将详细介绍showpage的基本概念、用法和功能,以及展望其未来的发展。
首先,让我们来了解一下showpage的基本概念。
showpage命令是一种在页面描述语言(Page Description Language,简称PDL)中使用的命令,广泛应用于打印和显示设备中。
它的作用是将当前页面的内容输出到输出设备上,以便用户能够查看、打印或保存页面的内容。
在一些PDL 中,如PostScript和PDF,showpage通常是用于显示或输出当前页面的最后一个命令。
接下来,我们将详细介绍showpage的用法和功能。
showpage命令通常在文档的末尾使用,用于显示当前页面的内容。
在使用showpage 命令之前,通常需要进行一些页面布局、文字、图片等的设置和绘制工作。
然后,使用showpage命令将这些内容输出到设备上,实现页面的显示。
showpage命令还可以用于将页面保存为图像文件,方便后续的处理和使用。
showpage的功能不仅限于显示当前页面的内容,还可以实现一些其他的功能。
例如,通过使用showpage命令,可以在页面中插入标志或水印,以增强文档的可读性和安全性。
showpage命令还可以用于控制页面的打印顺序、方向以及页面之间的切换等。
同时,showpage命令还可以与其他命令结合使用,实现更加复杂的页面效果和布局。
最后,让我们来展望一下showpage的未来发展。
随着科技的不断进步和应用的不断拓展,showpage命令可能会在许多领域中发挥更加重要的作用。
例如,在电子书阅读器和平板电脑等移动设备上,showpage命令可以实现更加丰富多样的页面展示效果,提升用户的阅读体验。
class_m ysql.php,数据库操作文件dbstuff类中最重要的方法就是connect()和query()方法,connect负责开启数据库连接,具体取数据就靠query了,query的核心代码如下:$func = $type == …UNBUFFERED‟ && @function_exists(…m ysql_unbuffered_query‟) ?…m ysql_unbuffered_query‟ : …mysql_query‟;if(!($query = $func($sql, $this->link)) && $type != …SILENT‟) {$this->halt(…MySQL Query Error‟, $sql);}声明变量$func,进行type判断后,赋值为“mysql_query”,然后$func(),就等于mysql_query().query并不仅仅负责查询,数据的插入和更新都是通过query来完成的,在function_common.php中://添加数据function inserttable($tablename, $insertsqlarr, $returnid=0, $replace = false) { global $_SGLOBAL;$insertkeysql = $insertvaluesql = $comma = ”;foreach ($insertsqlarr as $insert_key => $insert_value) {$insertkeysql .= $comma.‟`‟.$insert_key.‟`';$insertvaluesql .= $comma.‟\”.$insert_value.‟\”;$comma = …, …;}$m ethod = $replace?‟REPLACE‟:'INSERT‟;$_SGLOBAL['db']->query($method.‟ INTO ….tname($tablename).‟(….$insertkeysql.‟) VALUES (….$insertvaluesql.‟) …);if($returnid && !$replace) {return $_SGLOBAL['db']->insert_id();}}//更新数据function updatetable($tablename, $setsqlarr, $wheresqlarr) {global $_SGLOBAL;$setsql = $comma = ”;foreach ($setsqlarr as $set_key => $set_value) {$setsql .= $comma.‟`‟.$set_key.‟`‟.‟=\”.$set_value.‟\”;$comma = …, …;}$where = $comma = ”;if(em pty($wheresqlarr)) {$where = …1′;} elseif(is_array($wheresqlarr)) {foreach ($wheresqlarr as $key => $value) {$where .= $comma.‟`‟.$key.‟`‟.‟=\”.$value.‟\”;$comma = … AND …;}} else {$where = $wheresqlarr;}$_SGLOBAL['db']->query(…UPDATE ….tnam e($tablename).‟ SET ….$setsql.‟ WHERE ….$where);}//删除数据function_delete.php$_SGLOBAL['db']->query(“DELETE FROM “.tnam e(…comment‟).” WHERE cid IN (“.simplode($newcids).”)”);。
1、系统首页/index.php显示页面为/template/模板文件夹名/index.htm。
2、个人页面/space.php不带参数时显示个人首页;带uid参数(用户编号)为显示其他人的首页;do参数指示调用的模块,如/space.php?do=blog将显示日志内容。
带do参数页面的处理:/space.php?do=xxx将调用/source/space_xxx.php(其中xxx为相关模块或操作,下同)进行数据和逻辑处理,最终的页面是显示对应的模板页,为/template/模板文件夹名/space_xxx.htm。
具体模板的解析请参考《【UCHome二次开发】模板解析》,下同。
3、随便看看页面/network.php不带参数时显示随便看看首页;带ac参数时显示某个模块的随便看看页面,如/network.php?ac=space为随便看看现有的成员。
带ac参数页面的处理:/network.php?ac=xxx将调用/source/network_xxx.php进行数据和逻辑处理,最终的页面是显示对应的模板页,为/template/模板文件夹名/network_xxx.htm。
4、操作页面/cp.php不带参数时显示个人设置页;带ac参数时显示某个操作的页面,如/cp.php?ac=profile 为设置个人资料。
带ac参数页面的处理:/cp.php?ac=xxx将调用/source/cp_xxx.php进行数据和逻辑处理,最终的页面是显示对应的模板页,为/template/模板文件夹名/cp_xxx.htm。
5、动作页面/do.php不带参数时会被跳转到个人首页或系统首页(看是否已登录);带ac参数时为进行某项动作,不一定有显示的界面。
带ac参数页面的处理:/do.php?ac=xxx将调用/source/do_xxx.php进行数据和逻辑处理,最终的页面是显示对应的模板页,为/template/模板文件夹名/do_xxx.htm(不是所有的动作需要页面显示结果,所以不一定存在对应的模板文件)。
<!DOCTYPE html PUBLIC ―-//W3C//DTD XHTML 1.0 Transitional//EN‖ ―/TR/xhtml1/DTD/xhtml1-transitional.dtd―><html xmlns=‖/1999/xhtml―><head><meta http-equiv=‖Content-Type‖ content=‖text/html; charset=utf-8″ /><title>无标题文档</title><script>var userAgent = erAgent.toLowerCase();var is_opera = userAgent.indexOf(‗opera‘) != -1 && opera.version();var is_moz = (navigator.product == ‗Gecko‘) && userAgent.substr(userAgent.indexOf(‗firefox‘) + 8, 3);var is_ie = (userAgent.indexOf(‗msie‘) != -1 && !is_opera) && userAgent.substr(userAgent.indexOf(‗msie‘) + 5, 3);var is_safari = (userAgent.indexOf(‗webkit‘) != -1 || userAgent.indexOf(‘safari‘) != -1);function $(id) {return document.getElementById(id);}function doane(event) {e = event ? event : window.event;if(is_ie) {e.returnValue = false;e.cancelBubble = true;} else if(e) {e.stopPropagation();e.preventDefault();}}function isUndefined(variable) {return typeof variable == ‗undefined‘ ? true : false;}function in_array(needle, haystack) {if(typeof needle == ‘string‘ || typeof needle == ‗number‘) {for(var i in haystack) {if(haystack[i] == needle) {return true;}}}return false;}/*———————-script_menu.js——————–*/var jsmenu = new Array();var ctrlobjclassName;jsmenu['active'] = new Array();jsmenu['timer'] = new Array();jsmenu['iframe'] = new Array();function initCtrl(ctrlobj, click, duration, timeout, layer) {if(ctrlobj && !ctrlobj.initialized) {ctrlobj.initialized = true;ctrlobj.unselectable = true;ctrlobj.outfunc = typeof ctrlobj.onmouseout == ‗function‘ ? ctrlobj.onmouseout : null;ctrlobj.onmouseout = function() {if(this.outfunc) this.outfunc();if(duration < 3) jsmenu['timer'][ctrlobj.id] = setTimeout(‗hideMenu(‗ + layer + ‗)‘, timeout);}ctrlobj.overfunc = typeof ctrlobj.onmouseover == ‗function‘ ? ctrlobj.onmouseover : null;ctrlobj.onmouseover = function(e) {doane(e);if(this.overfunc) this.overfunc();if(click) {clearTimeout(jsmenu['timer'][this.id]);} else {for(var id in jsmenu['timer']) {if(jsmenu['timer'][id]) clearTimeout(jsmenu['timer'][id]);}}}}}function initMenu(ctrlid, menuobj, duration, timeout, layer, drag) {if(menuobj && !menuobj.initialized) {menuobj.initialized = true;menuobj.ctrlkey = ctrlid;menuobj.onclick = ebygum;menuobj.style.position = ‗absolute‘;if(duration < 3) {if(duration > 1) {menuobj.onmouseover = function() {clearTimeout(jsmenu['timer'][ctrlid]);}}if(duration != 1) {menuobj.onmouseout = function() {jsmenu['timer'][ctrlid] = setTimeout(‗hideMenu(‗ + layer + ‗)‘, timeout);}}}menuobj.style.zIndex = 50;if(is_ie) {menuobj.style.filter += ―progid:DXImageTransform.Microsoft.shadow(direction=135,color=#CCCCCC,stre ngth=2)‖;}if(drag) {menuobj.onmousedown = function(event) {try{menudrag(menuobj, event, 1);}catch(e){}};document.body.onmousemove = function(event) {try{menudrag(menuobj, event, 2);}catch(e){}};menuobj.onmouseup = function(event) {try{menudrag(menuobj, event, 3);}catch(e){}};}}}var menudragstart = new Array();function menudrag(menuobj, e, op) {if(op == 1) {if(in_array(is_ie ? event.srcElement.tagName : e.target.tagName, ['TEXTAREA', 'INPUT', 'BUTTON', 'SELECT'])) {return;}menudragstart = is_ie ? [event.clientX, event.clientY] : [e.clientX, e.clientY];menudragstart[2] = parseInt(menuobj.style.left);menudragstart[3] = parseInt(menuobj.style.top);doane(e);} else if(op == 2 && menudragstart[0]) {var menudragnow = is_ie ? [event.clientX, event.clientY] : [e.clientX, e.clientY]; menuobj.style.left = (menudragstart[2] + menudragnow[0] – menudragstart[0]) + ‗px‘;menuobj.style.top = (menudragstart[3] + menudragnow[1] – menudragstart[1]) + ‗px‘;doane(e);} else if(op == 3) {menudragstart = [];doane(e);}}function showMenu(ctrlid, click, offset, duration, timeout, layer, showid, maxh, drag) {var ctrlobj = $(ctrlid);if(!ctrlobj) return;if(isUndefined(click)) click = false;if(isUndefined(offset)) offset = 0;if(isUndefined(duration)) duration = 2;if(isUndefined(timeout)) timeout = 250;if(isUndefined(layer)) layer = 0;if(isUndefined(showid)) showid = ctrlid;var showobj = $(showid);var menuobj = $(showid + ‗_menu‘);if(!showobj|| !menuobj) return;if(isUndefined(maxh)) maxh = 400;if(isUndefined(drag)) drag = false;if(click && jsmenu['active'][layer] == menuobj) {hideMenu(layer);return;} else {hideMenu(layer);}var len = jsmenu['timer'].length;if(len > 0) {for(var i=0; i<len; i++) {if(jsmenu['timer'][i]) clearTimeout(jsmenu['timer'][i]); }}initCtrl(ctrlobj, click, duration, timeout, layer);ctrlobjclassName = ctrlobj.className;ctrlobj.className += ‗ hover‘;initMenu(ctrlid, menuobj, duration, timeout, layer, drag); menuobj.style.display = ‖;if(!is_opera) {menuobj.style.clip = ‗rect(auto, auto, auto, auto)‘;}setMenuPosition(showid, offset);if(maxh && menuobj.scrollHeight > maxh) { menuobj.style.height = maxh + ‗px‘;if(is_opera) {menuobj.style.overflow = ‗auto‘;} else {menuobj.style.overflowY = ‗auto‘;}}if(!duration) {set Timeout(‗hideMenu(‗ + layer + ‗)‘, timeout);}jsmenu['active'][layer] = menuobj;}function setMenuPosition(showid, offset) {var showobj = $(showid);var menuobj = $(showid + ‗_menu‘);if(isUndefined(offset)) offset = 0;if(showobj) {showobj.pos = fetchOffset(showobj);showobj.X = showobj.pos['left'];showobj.Y = showobj.pos['top'];showobj.w = showobj.offsetWidth;showobj.h = showobj.offsetHeight;menuobj.w = menuobj.offsetWidth;menuobj.h = menuobj.offsetHeight;if(offset != -1) {menuobj.style.left = (showobj.X + menuobj.w > document.body.clientWidth) && (showobj.X + showobj.w –menuobj.w >= 0) ? showobj.X + showobj.w –menuobj.w + ‗px‘ : showobj.X + ‗px‘;menuobj.style.top = offset == 1 ? showobj.Y + ‗px‘ : (offset == 2 || ((showobj.Y + showobj.h + menuobj.h > document.documentElement.scrollTop + document.documentElement.clientHeight) && (showobj.Y –menuobj.h >= 0)) ? (showobj.Y –menuobj.h) + ‗px‘ : showobj.Y + showobj.h + ‗px‘);} else if(offset == -1) {menuobj.style.left = (document.body.clientWidth-menuobj.w)/2 + ‗px‘;var divtop = document.documentElement.scrollTop + (document.documentElement.clientHeight-menuobj.h)/2;if(divtop > 100) divtop = divtop – 100;menuobj.style.top = divtop + ‗px‘;}if(menuobj.style.clip && !is_opera) {menuobj.style.clip = ‗rect(auto, auto, auto, auto)‘;}}}function hideMenu(layer) {if(isUndefined(layer)) layer = 0;if(jsmenu['active'][layer]) {try {$(jsmenu['active'][layer].ctrlkey).className = ctrlobjclassName;} catch(e) {}clearTimeout(jsmenu['timer'][jsmenu['active'][layer].ctrlkey]);jsmenu['active'][layer].style.display = ‗none‘;if(is_ie && is_ie < 7 && jsmenu['iframe'][layer]) {jsmenu['iframe'][layer].style.display = ‗none‘;}jsmenu['active'][layer] = null;}}function fetchOffset(obj) {var left_offset = obj.offsetLeft;var top_offset = obj.offsetTop;while((obj = obj.offsetParent) != null) {left_offset += obj.offsetLeft;top_offset += obj.offsetTop;}return { ‗left‘: left_offset, ‗top‘ : top_offset };}function ebygum(eventobj) {if(!eventobj || is_ie) {window.event.cancelBubble = true;return window.event;} else {if(eventobj.target.type == ‘submit‘) {eventobj.target.form.submit();}eventobj.stopPropagation();return eventobj;}}</script><style>.aa_menu{ border:1px solid red; width:120px; background:#f3f3f3}</style></head><body><a id=‖aa‖ style=‖width:100px; height:25px‖ onclick=‖showMenu(‗ctrl_aa‘,0,0,0,2000,1,‘aa‘,150,0)‖>菜单</a><a id=‖bb‖ style=‖width:100px; height:25px‖ onmouseover=‖showMenu(this.id)‖>菜单</a><div id=‖aa_menu‖ style=‖display:none‖><h3 id=‖ctrl_aa‖>的十分舒服是</h3><ul><li><a href=‖#‖>菜单也</a></li><li>菜单也</li><li>菜单也</li><li>菜单也</li><li><textarea>dfsdfs</textarea></li></ul></div><div id=‖bb_menu‖ style=‖display:none‖> <ul><li>菜单也</li><li>菜单也</li><li>菜单也</li><li>菜单也</li><li>菜单也</li></ul></div></body></html>。