From 94dd38b9fc4fe25801201a59573268443af0d1dd Mon Sep 17 00:00:00 2001 From: gogobody <138950128@qq.com> Date: Wed, 14 Oct 2020 20:48:35 +0800 Subject: [PATCH] init --- Action.php | 623 +++++++++++++++++++++++++++++++++++++++ Plugin.php | 198 +++++++++++++ README.md | 36 ++- css/input.css | 67 +++++ css/input.min.css | 1 + css/input.min.min.css | 1 + css/modal.css | 122 ++++++++ css/modal.min.css | 1 + css/modal.min.min.css | 1 + css/smms.diy.css | 69 +++++ css/smms.diy.min.css | 1 + css/smms.diy.min.min.css | 1 + imgs/loading.gif | Bin 0 -> 3494 bytes js/comment.js | 62 ++++ js/comment.min.js | 1 + js/comment.min.min.js | 1 + js/content.js | 135 +++++++++ js/content.min.js | 1 + js/content.min.min.js | 1 + js/jquery.min.js | 4 + js/jquery.min.min.js | 1 + js/modal.js | 18 ++ js/modal.min.js | 1 + js/modal.min.min.js | 1 + language.php | 83 ++++++ manage.php | 211 +++++++++++++ smapi.php | 61 ++++ smms.function.php | 44 +++ 28 files changed, 1745 insertions(+), 1 deletion(-) create mode 100644 Action.php create mode 100644 Plugin.php create mode 100644 css/input.css create mode 100644 css/input.min.css create mode 100644 css/input.min.min.css create mode 100644 css/modal.css create mode 100644 css/modal.min.css create mode 100644 css/modal.min.min.css create mode 100644 css/smms.diy.css create mode 100644 css/smms.diy.min.css create mode 100644 css/smms.diy.min.min.css create mode 100644 imgs/loading.gif create mode 100644 js/comment.js create mode 100644 js/comment.min.js create mode 100644 js/comment.min.min.js create mode 100644 js/content.js create mode 100644 js/content.min.js create mode 100644 js/content.min.min.js create mode 100644 js/jquery.min.js create mode 100644 js/jquery.min.min.js create mode 100644 js/modal.js create mode 100644 js/modal.min.js create mode 100644 js/modal.min.min.js create mode 100644 language.php create mode 100644 manage.php create mode 100644 smapi.php create mode 100644 smms.function.php diff --git a/Action.php b/Action.php new file mode 100644 index 0000000..ce4e188 --- /dev/null +++ b/Action.php @@ -0,0 +1,623 @@ +'), '', $name); + $name = str_replace('\\', '/', $name); + $name = false === strpos($name, '/') ? ('a' . $name) : str_replace('/', '/a', $name); + $info = pathinfo($name); + $name = substr($info['basename'], 1); + + return isset($info['extension']) ? strtolower($info['extension']) : ''; + } + + /** + * 上传文件处理函数,如果需要实现自己的文件哈希或者特殊的文件系统,请在options表里把uploadHandle改成自己的函数 + * + * @access public + * @param array $file 上传的文件 + * @return mixed + */ + public static function uploadHandle($file) + { + if (empty($file['name'])) { + return false; + } else { +// print_r($file); + } + + $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasUploaded)->uploadHandle($file); + if ($hasUploaded) { + return $result; + } + + $ext = self::getSafeName($file['name']); + +// print_r($ext); + + if (!self::checkFileType($ext) || Typecho_Common::isAppEngine()) { + return false; + } + + $date = new Typecho_Date(); + $path = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR, + defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__) + . '/' . $date->year . '/' . $date->month; + + //创建上传目录 + if (!is_dir($path)) { + if (!self::makeUploadDir($path)) { + return false; + } + } + + //获取文件名 + $fileName = sprintf('%u', crc32(uniqid())) . '.' . $ext; + $path = $path . '/' . $fileName; + + if (isset($file['tmp_name'])) { + + //移动上传文件 + if (!@move_uploaded_file($file['tmp_name'], $path)) { + return false; + } + } else if (isset($file['bytes'])) { + + //直接写入文件 + if (!file_put_contents($path, $file['bytes'])) { + return false; + } + } else { + return false; + } + + if (!isset($file['size'])) { + $file['size'] = filesize($path); + } + + //返回相对存储路径 + return array( + 'name' => $file['name'], + 'path' => (defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR) + . '/' . $date->year . '/' . $date->month . '/' . $fileName, + 'size' => $file['size'], + 'type' => $ext, + 'mime' => Typecho_Common::mimeContentType($path) + ); + } + + /** + * 修改文件处理函数,如果需要实现自己的文件哈希或者特殊的文件系统,请在options表里把modifyHandle改成自己的函数 + * + * @access public + * @param array $content 老文件 + * @param array $file 新上传的文件 + * @return mixed + */ + public static function modifyHandle($content, $file) + { + if (empty($file['name'])) { + return false; + } + + $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasModified)->modifyHandle($content, $file); + if ($hasModified) { + return $result; + } + + $ext = self::getSafeName($file['name']); + + if ($content['attachment']->type != $ext || Typecho_Common::isAppEngine()) { + return false; + } + + $path = Typecho_Common::url($content['attachment']->path, + defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__); + $dir = dirname($path); + + //创建上传目录 + if (!is_dir($dir)) { + if (!self::makeUploadDir($dir)) { + return false; + } + } + + if (isset($file['tmp_name'])) { + + @unlink($path); + + //移动上传文件 + if (!@move_uploaded_file($file['tmp_name'], $path)) { + return false; + } + } else if (isset($file['bytes'])) { + + @unlink($path); + + //直接写入文件 + if (!file_put_contents($path, $file['bytes'])) { + return false; + } + } else { + return false; + } + + if (!isset($file['size'])) { + $file['size'] = filesize($path); + } + + //返回相对存储路径 + return array( + 'name' => $content['attachment']->name, + 'path' => $content['attachment']->path, + 'size' => $file['size'], + 'type' => $content['attachment']->type, + 'mime' => $content['attachment']->mime + ); + } + + /** + * 删除文件 + * + * @access public + * @param array $content 文件相关信息 + * @return string + */ + public static function deleteHandle(array $content) + { + $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasDeleted)->deleteHandle($content); + if ($hasDeleted) { + return $result; + } + + return !Typecho_Common::isAppEngine() + && @unlink(__TYPECHO_ROOT_DIR__ . '/' . $content['attachment']->path); + } + + /** + * 获取实际文件绝对访问路径 + * + * @access public + * @param array $content 文件相关信息 + * @return string + */ + public static function attachmentHandle(array $content) + { + $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasPlugged)->attachmentHandle($content); + if ($hasPlugged) { + return $result; + } + + $options = Typecho_Widget::widget('Widget_Options'); + return Typecho_Common::url($content['attachment']->path, + defined('__TYPECHO_UPLOAD_URL__') ? __TYPECHO_UPLOAD_URL__ : $options->siteUrl); + } + + /** + * 获取实际文件数据 + * + * @access public + * @param array $content + * @return string + */ + public static function attachmentDataHandle(array $content) + { + $result = Typecho_Plugin::factory('Widget_Upload')->trigger($hasPlugged)->attachmentDataHandle($content); + if ($hasPlugged) { + return $result; + } + + return file_get_contents(Typecho_Common::url($content['attachment']->path, + defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__)); + } + + /** + * 检查文件名 + * + * @access private + * @param string $ext 扩展名 + * @return boolean + */ + public static function checkFileType($ext) + { + $options = Typecho_Widget::widget('Widget_Options'); + return in_array($ext, $options->allowedAttachmentTypes); + } + + + public static function getDataFromWebUrl($url) + { + $file_contents = ""; + if (function_exists('file_get_contents')) { + $file_contents = @file_get_contents($url); + } + if ($file_contents == "") { + $ch = curl_init(); + $timeout = 30; + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); + $file_contents = curl_exec($ch); + curl_close($ch); + } + return $file_contents; + } + + + /** + * 执行升级程序 + * + * @access public + * @return void + */ + public function upload() + { + + $uploadType = "file"; + $original = ""; + if (!empty($_FILES)) { + $file = array_pop($_FILES); +// print_r($file); + if (is_array($file["error"])) {//处理传过来的是一个file数组 + $file = array( + "name" => $file["name"][0], + "type" => $file["type"][0], + "error" => $file["error"][0], + "tmp_name" => $file["tmp_name"][0], + "size" => $file["size"][0], + ); + } + } else { + $post = json_decode(file_get_contents("php://input"), true); +// print_r($post); + if (@!empty($post["url"])) { + $imageUrl = $post["url"]; + $original = $imageUrl; + if (substr($imageUrl, 0, 4) != "http") {//图片地址没有http前缀 + if (substr($imageUrl,0,2) =="//"){//图片地址是相对路径 + $imageUrl = "http:".$imageUrl; + }else{ + $imageUrl = ""; + } + } else {//正确的url +// $imageUrl = ""; + } +// print_r("imageUrl".$imageUrl); + if ($imageUrl!=""){ + $ret = parse_url($imageUrl); +// $url = @$ret["scheme"] . "://" . @$ret["host"] . @$ret["path"]; + $fileName = mb_split("/", @$ret["path"]); + $fileName = $fileName[count($fileName) - 1]; + $file = array( + "name" => $fileName, + "error" => 0, + "bytes" => self::getDataFromWebUrl($imageUrl), + ); + $uploadType = "web"; +// print_r($file); + } + + } else { + //不需要处理 + print_r("图片外链格式不正确"); + } + } + + + if (!empty($file)) { + if (0 == $file['error'] && ((isset($file['tmp_name']) && is_uploaded_file($file['tmp_name'])) || isset + ($file["bytes"]))) { + // xhr的send无法支持utf8 + if ($this->request->isAjax()) { + $file['name'] = urldecode($file['name']); + } + $result = self::uploadHandle($file); + + if (false !== $result) { + $this->pluginHandle()->beforeUpload($result); + + $struct = array( + 'title' => $result['name'], + 'slug' => $result['name'], + 'type' => 'attachment', + 'status' => 'publish', + 'text' => serialize($result), + 'allowComment' => 1, + 'allowPing' => 0, + 'allowFeed' => 1 + ); + + if (isset($this->request->cid)) { + $cid = $this->request->filter('int')->cid; + + if ($this->isWriteable($this->db->sql()->where('cid = ?', $cid))) { + $struct['parent'] = $cid; + } + } + + $insertId = $this->insert($struct); + + $this->db->fetchRow($this->select()->where('table.contents.cid = ?', $insertId) + ->where('table.contents.type = ?', 'attachment'), array($this, 'push')); + + /** 增加插件接口 */ + $this->pluginHandle()->upload($this); + + + if ($uploadType == "file") { + $this->response->throwJson(array($this->attachment->url, array( + 'cid' => $insertId, + 'title' => $this->attachment->name, + 'type' => $this->attachment->type, + 'size' => $this->attachment->size, + 'bytes' => number_format(ceil($this->attachment->size / 1024)) . ' Kb', + 'isImage' => $this->attachment->isImage, + 'url' => $this->attachment->url, + 'permalink' => $this->permalink + ))); + } else { + $this->response->throwJson(array( + "msg" => "", + "code" => 0, + "data" => array( + 'cid' => $insertId, + "title" => $this->attachment->name, + 'type' => $this->attachment->type, + 'size' => $this->attachment->size, + 'bytes' => number_format(ceil($this->attachment->size / 1024)) . ' Kb', + 'isImage' => $this->attachment->isImage, + "url" => $this->attachment->url, + 'permalink' => $this->permalink, + "originalURL"=>$original, + + ) + ) + ); + } + + + } + } + + } + + $this->response->throwJson(false); + } + + /** + * 执行升级程序 + * + * @access public + * @return void + */ + public function modify() + { + if (!empty($_FILES)) { + $file = array_pop($_FILES); + if (0 == $file['error'] && is_uploaded_file($file['tmp_name'])) { + $this->db->fetchRow($this->select()->where('table.contents.cid = ?', $this->request->filter('int')->cid) + ->where('table.contents.type = ?', 'attachment'), array($this, 'push')); + + if (!$this->have()) { + $this->response->setStatus(404); + exit; + } + + if (!$this->allow('edit')) { + $this->response->setStatus(403); + exit; + } + + // xhr的send无法支持utf8 + if ($this->request->isAjax()) { + $file['name'] = urldecode($file['name']); + } + + $result = self::modifyHandle($this->row, $file); + + if (false !== $result) { + $this->pluginHandle()->beforeModify($result); + + $this->update(array( + 'text' => serialize($result) + ), $this->db->sql()->where('cid = ?', $this->cid)); + + $this->db->fetchRow($this->select()->where('table.contents.cid = ?', $this->cid) + ->where('table.contents.type = ?', 'attachment'), array($this, 'push')); + + /** 增加插件接口 */ + $this->pluginHandle()->modify($this); + + $this->response->throwJson(array($this->attachment->url, array( + 'cid' => $this->cid, + 'title' => $this->attachment->name, + 'type' => $this->attachment->type, + 'size' => $this->attachment->size, + 'bytes' => number_format(ceil($this->attachment->size / 1024)) . ' Kb', + 'isImage' => $this->attachment->isImage, + 'url' => $this->attachment->url, + 'permalink' => $this->permalink + ))); + } + } + } + + $this->response->throwJson(false); + } + + /** + * 初始化函数 + * + * @access public + * @return void + */ + public function action() + { +// echo "hello upload"; + if ($this->user->pass('contributor', true) && $this->request->isPost()) { + $this->security->protect(); + if ($this->request->is('do=modify&cid')) { + $this->modify(); + } else { + $this->upload(); + } + } else { + $this->response->setStatus(403); + } + } +} + +class SmmsForTypecho_Action extends Typecho_Widget implements Widget_Interface_Do +{ + //上传文件目录 + const UPLOAD_DIR = '/usr/uploads'; + + public function smms_forward_callback() + { + //$paged = $request->get_param('paged'); + $tdb = Typecho_Db::get();; + + $lastname = $_FILES['smfile']['tmp_name']; + + $date = new Typecho_Date(); + $wp_uploads = Typecho_Common::url(defined('__TYPECHO_UPLOAD_DIR__') ? __TYPECHO_UPLOAD_DIR__ : self::UPLOAD_DIR, + defined('__TYPECHO_UPLOAD_ROOT_DIR__') ? __TYPECHO_UPLOAD_ROOT_DIR__ : __TYPECHO_ROOT_DIR__) + . '/' . $date->year . '/' . $date->month; + + //创建上传目录 + $tpath = $wp_uploads.'/smms_imglist/'; + if (!is_dir($tpath)) { + if (!Upload::makeUploadDir($tpath)) { + return false; + } + } + +// $path = $tpath.$_FILES['smfile']['name']; + $ext = Upload::getSafeName($_FILES['smfile']['name']); + //获取文件名 + $fileName = sprintf('%u', crc32(uniqid())) . '.' . $ext; + $path = $tpath . $fileName; + + //return $path; + copy($lastname, $path); + unlink($lastname); + + $options = Helper::options(); + + $plugin_config = $options->plugin('SmmsForTypecho'); // 获取 后台设置 + + $auth = $plugin_config->Authorization_; + + $smapi = new SMApi($auth); + + $result = $smapi->Upload($path); + + if ($result["success"]) { + $data['width'] = $result['data']['width']; + $data['height'] = $result['data']['height']; + $data['size'] = $result['data']['size']; + $data['hash'] = $result['data']['hash']; + $data['url'] = $result['data']['url']; + + $insert = $tdb->insert('table.'.MY_NEW_TABLE_NAME) + ->rows($data); + $insertId = $tdb->query($insert); + + if ($plugin_config->Nolocal_) { + unlink($path); + } + } elseif ($result["code"] == "image_repeated") { + $result['data']['url'] = $result["images"]; + } + + print_r(json_encode($result)); + return $result; + } + + public function smms_getlist_callback() + { + $tdb = Typecho_Db::get();; + $request = Typecho_Request::getInstance(); + + $pages = $request->get('pages'); + $pages = $pages? : 1; + $limit = 10; + $offset = ($pages - 1) * 10; + $query = $tdb->select('url')->from('table.'.MY_NEW_TABLE_NAME)->order('id',Typecho_Db::SORT_DESC)->offset($offset)->limit($limit); + $result = $tdb->fetchAll($query); + + print_r(json_encode($result)); + return $result; + + } + + + public function action() + { + if ($this->request->isPost()){ + $this->on($this->request->is('do=upload'))->smms_forward_callback(); + + }elseif ($this->request->isGet()){ + $this->on($this->request->is('do=list'))->smms_getlist_callback(); + + } + + } +} \ No newline at end of file diff --git a/Plugin.php b/Plugin.php new file mode 100644 index 0000000..4bdd5c8 --- /dev/null +++ b/Plugin.php @@ -0,0 +1,198 @@ +pluginUrl . '/SmmsForTypecho/'); //返回当前插件的目录URI, +define('SMMS_VERSION', "4.3"); +function outHtml(){ + $html_ = '
SMMS 图床
'; + return $html_; +} + +class SmmsForTypecho_Plugin implements Typecho_Plugin_Interface +{ + /** + * 激活插件方法,如果激活失败,直接抛出异常 + * + * @access public + * @return void + * @throws Typecho_Plugin_Exception + */ + public static function activate() + { + Typecho_Plugin::factory('admin/header.php')->header = array('SmmsForTypecho_Plugin', 'admin_scripts_css'); + Typecho_Plugin::factory('admin/write-post.php')->bottom = array('SmmsForTypecho_Plugin', 'admin_writepost_scripts'); + + Typecho_Plugin::factory('Widget_Archive')->beforeRender = array('SmmsForTypecho_Plugin','Widget_Archive_beforeRender'); + + Typecho_Plugin::factory('Widget_Archive')->afterRender = array('SmmsForTypecho_Plugin','Widget_Archive_afterRender'); + + plugin_activation_cretable(); + Helper::addAction('multi-upload', 'SmmsForTypecho_Action'); + + //add panel + Helper::addPanel(3, 'SmmsForTypecho/manage.php', 'SMMS图床', '管理SMMS图床', 'administrator'); //editor //contributor + + } + + /** + * 禁用插件方法,如果禁用失败,直接抛出异常 + * + * @static + * @access public + * @return void + * @throws Typecho_Plugin_Exception + */ + public static function deactivate(){ + plugin_deactivation_deltable(); + Helper::removePanel(3, 'SmmsForTypecho/manage.php'); + } + + /** + * 获取插件配置面板 + * + * @access public + * @param Typecho_Widget_Helper_Form $form 配置面板 + * @return void + */ + public static function config(Typecho_Widget_Helper_Form $form) + { + /** 分类名称 */ + global $language; + + $Authorization = new Typecho_Widget_Helper_Form_Element_Text('Authorization_', NULL, null,'Authorization'.$language[2], _t('Authorization '.$language[6].'
+ +

')); + $form->addInput($Authorization); + + $Comment_Selector = new Typecho_Widget_Helper_Form_Element_Text('Comment_Selector', NULL, '#textarea','评论选择器', _t('因为不同的主题的评论框是不同主题开发者自定义的,所以需要手动定位点击这里查看')); + $form->addInput($Comment_Selector); + + $Content_ = new Typecho_Widget_Helper_Form_Element_Radio('Content_', array( + 1 => _t('启用'), + 0 => _t('关闭'), + ), 1, _t($language[7]), _t($language[8])); + $form->addInput($Content_); + + $Comment_ = new Typecho_Widget_Helper_Form_Element_Radio('Comment_', array( + 1 => _t('启用'), + 0 => _t('关闭'), + ), 1, _t($language[9]), _t($language[10])); + $form->addInput($Comment_); + + $Nolocal_ = new Typecho_Widget_Helper_Form_Element_Radio('Nolocal_', array( + 1 => _t('启用'), + 0 => _t('关闭'), + ), 1, _t($language[11]), _t($language[12])); + $form->addInput($Nolocal_); + } + + /** + * 个人用户的配置面板 + * + * @access public + * @param Typecho_Widget_Helper_Form $form + * @return void + */ + public static function personalConfig(Typecho_Widget_Helper_Form $form){} + + public static function add_scripts_css(){ + echo ''; + echo ''; + echo ''; + + } + public static function admin_scripts_css($header){ + echo $header; +// SmmsForTypecho_Plugin::add_scripts_css(); + + echo ''; + echo ''; + + + } + public static function admin_writepost_scripts($post){ + $option = Helper::options()->plugin('SmmsForTypecho'); + if (!$option->Content_){ + return; + } + + echo ''; + echo ''; + + ?> + + plugin('SmmsForTypecho'); + if (!$option->Comment_){ + return; + } + if (!$archive->is('single')) { + return; + } + if (!$archive->allow('comment')) { + return; + } + echo ''; + + } + + public static function Widget_Archive_afterRender($archive) + { + $option = Helper::options()->plugin('SmmsForTypecho'); + if (!$option->Comment_){ + return; + } + if (!$archive->is('single')) { + return; + } + if (!$archive->allow('comment')) { + return; + } + + echo ''; + ?> + + '; + + + } +} diff --git a/README.md b/README.md index 7087932..a5888fc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,36 @@ # SmmsForTypecho -sm.ms 图床的typecho 插件 + sm.ms 图床的typecho 插件 ,欢迎 star,pr +sm.ms 是一个好用免费的图床,因为不想把图片存服务器,所以写了这个插件 + +#### 插件版本 v 1.0 +#### 功能: +1. 后台图片管理页面,以及写文章时的单独图片管理页,及插及用 +2. 支持批量上传图片到图床 +3. 支持上传图片到自己的 smms 免费空间(自己管理的空间是容量有限的) +4. 支持评论框上传图片(需要设置) + +#### 关于评论框设置 +因为不同的作者的主题的评论框代码不一样,所以需要我们自己手动定位到评论框。 +在插件的设置中填入 评论框的选择器,比如评论框 '",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("