Douban Helper
— Last update Sep 30, 2008 — Installed 571 times.There are 5 previous versions of this script.
Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)
// vim: fdm=marker
// ==UserScript==
// @name Douban Helper
// @namespace http://leechael.org/plugins/douban-helper
// @include http://www.douban.com/*
// @include http://douban.com/*
// @exclude http://9.douban.com/*
// ==/UserScript==
var bean = {};
// {{{ class: bean.config
/**
* All your settings storage here. You can modify by you own to fit you
* need. For example, enable or disable a feature specially.
*
* All options limited to true or false except it had note its range.
*/
bean.config = {
/**
* Enable wrapper means:
* - Enable all built-in features. (except you disable them in
* following settings.
* - GreaseMonkey scripts for douban.com can be add a new feature
* quickly by bean.addWrapper().
*/
enableWrapper : true,
/**
* Hot keys is supports, but limited to shift + <key> (or using
* ctrl instead of shift, you can set the option below).
*/
enableHotKey : true,
/**
* Console is the most important feature what Douban Helper had,
* you can show or hide by click an switcher on toolbar, using
* hot key like shift + ; or shift + / (vim-like) if you hadn't
* disable hot key before.
*/
enableConsole : true,
/**
* Using graphic characters as console switcher.
*/
useShortConsoleSwitcher : false,
/**
* If hot key shift + <key> has been defined as hot key for other
* applications, or it's a system shortcut already, try turn on
* this options. If problem hasn't be solved after turn it on, what
* you can do is just disable hot key.
*/
useCtrlInsteadOfShift : false,
/**
* When you hover on stick, sidebar will be auto show.
*/
showSidebarAtHover : false,
/**
* Auto expanding albums.
*/
autoExpandAlbum : false,
};
// }}}
// {{{ properties
bean.version = '0.3';
bean.debug = false;
bean.bindedKey = {},
// }}}
// {{{ class: bean.utils
bean.utils = {
// {{{ and (list, fn)
and : function (list, fn)
{
var i = list.length, j = 0;
while (j < i)
{
if (fn.call(null, list[j]) == false)
{
return false;
}
j++;
}
return true;
},
// }}}
// {{{ filter (list, fn)
/**
* @param Array | Object list
* @param Function fn
* @return Array
*/
filter : function (list, fn)
{
var i = list.length, j = 0, rs = [];
while (j < i)
{
if (fn.call(null, list[j]))
{
rs.push(list[j]);
}
j++;
}
return rs;
},
// }}}
// {{{ existsElement (id)
/**
* @param String id
* @return Boolean | Object
*/
existsElement : function (id)
{
return (document.getElementById(id) == null) ?
false :
document.getElementById(id);
},
// }}}
// {{{ isChar (keyCode)
isChar : function (keyCode)
{
var _tmp = String.fromCharCode(keyCode);
if (/^[\w-]$/i.test(_tmp))
{
return _tmp;
}
return false;
},
// }}}
// {{{ testScope (scope)
testScope: function (scope)
{
if (typeof scope == 'function')
{
if (!scope.call(bean.url))
{
return false;
}
} else {
if (typeof scope.test == 'function')
{
if (!bean.url.match(scope))
{
return false;
}
} else {
if (scope !== true)
{
return false;
}
}
}
return true;
},
// }}}
}
// }}}
// {{{ class: bean.key
bean.key = {
ESC : 27,
ENTER : 13,
SPACE : 32,
BACKSPACE : 8,
LEFT : 37,
UP : 38,
RIGHT : 39,
DOWN : 40,
SEMICOLON : 59,
SLASH : 191,
QUESTION_MARK : 63,
COLON : 58,
PERIOD : 46,
COMMA : 44,
QUOTATION_MARK : 39,
}
// }}}
// {{{ class: bean.cmd
bean.cmd = {
// {{{ properties
// messages.
defConsoleShowMsg : '显示控制台',
defConsoleHideMsg : '隐藏控制台',
shortConsoleShowMsg : '●',
shortConsoleHideMsg : '○',
defCommandHelp : '查阅可用的命令列表请键入 <strong>:help</strong> 或 '
+ '<strong>:h</strong>。',
defSearchHelp : '在豆瓣全站范围内搜索含关键字 <em>keywords</em> 的条目。',
undefinedCmd : '该命令不存在,键入 <strong>:help</strong> 或 <strong>:h'
+ '</strong> 可查看可用的命令列表。',
avoidMode : '请以 <strong>:</strong> 切入命令模式或 <strong>?'
+ '</strong> 切入查询模式。',
// true for console is hidden, false for opened.
isHidden : true,
// turn to off when command complete.
isAutoMatch : true,
// console elements
console : {},
input : {},
switcher : {},
displayer : {},
// command index
commonCmdIdx : [],
commonCmds : {},
searchCmdIdx : [],
searchCmds : {},
// }}}
// {{{ init ()
init: function ()
{
$('body').append($(['<div id="dh_console">'
+ '<div id="dh_console_bar"><span>X</span>'
+ '</div>'
+ '<textarea id="dh_console_input">'
+ '</textarea>'
+ '<div id="dh_console_display">'
+ this.defCommandHelp + '</div>'
+ '</div>'].join('')));
this.console = $('#dh_console');
this.input = $('#dh_console_input');
this.displayer = $('#dh_console_display');
var _swap = bean.config.useShortConsoleSwitcher
? this.shortConsoleShowMsg
: this.defConsoleShowMsg;
this.switcher = $('<a id="dh_console_switcher">' + _swap + '</a>')
this.switcher.insertAfter('#status a:last');
this.switcher.click(function ()
{
var cmd = bean.cmd;
cmd.isHidden ? cmd.show() : cmd.hide();
return false;
});
$('#dh_console_bar span').click(function ()
{
bean.cmd.hide();
});
this.setStyle();
this.setDefaultCommand();
},
// }}}
// {{{ show ()
show : function ()
{
if (!this.isHidden)
{
return;
}
var _resizeEvent = this.updateSize;
var _hideEvent = this._hideByEsc;
var _deamon = this.deamon;
this.isHidden = false;
this.updateSize();
this.console.css('visibility', 'visible')
.css('position', 'fixed')
.css('height', 'auto');
window.addEventListener('resize', _resizeEvent, false);
this.switcher.text(bean.config.useShortConsoleSwitcher
? this.shortConsoleHideMsg
: this.defConsoleHideMsg);
this.input.val('');
this.input.focus();
unsafeWindow.document
.getElementById('dh_console_input')
.addEventListener('keypress', _deamon, false);
bean.utils
.existsElement('dh_console')
.addEventListener('keypress', _hideEvent, false);
this.autoMatching = true;
},
// }}}
// {{{ hide ()
hide : function ()
{
if (this.isHidden)
{
return false;
}
var _hideEvent = this._hideByEsc;
var _deamon = this.deamon;
var _resizeEvent = this.updateSize;
this.isHidden = true;
this.console.css('visibility', 'hidden')
.css('position', 'static')
.css('height', '0');
this.switcher.text(bean.config.useShortConsoleSwitcher
? this.shortConsoleShowMsg
: this.defConsoleShowMsg);
bean.utils
.existsElement('dh_console')
.removeEventListener('keypress', _hideEvent, true);
this.input.blur();
unsafeWindow.document
.getElementById('dh_console_input')
.removeEventListener('keypress', _deamon, false);
window.removeEventListener('resize', _resizeEvent, false);
},
// }}}
// {{{ _hideByEsc (e)
_hideByEsc : function (e)
{
if (e.keyCode == bean.key.ESC)
{
bean.cmd.hide();
}
},
// }}}
// {{{ updateSize ()
updateSize: function ()
{
this.console.css('left', (window.innerWidth - 500) / 2 + 'px');
},
// }}}
// {{{ deamon (e)
/**
* deamon for user input.
*/
deamon : function (e)
{
var cmd = bean.cmd, key = bean.key;
if (e.keyCode == key.ENTER)
{
e.preventDefault();
if (cmd.parse())
{
cmd.isAutoMatch = false;
cmd.input.val('');
}
}
if (e.keyCode == key.UP
|| e.keyCode == key.DOWN)
{
e.preventDefault();
}
/*
if (e.keyCode == key.SPACE)
{
}
*/
/**
* Check the input and auto find out all commend may be fit
* what user want. We call this feature suggesting.
*/
if (!cmd.isAutoMatch && cmd.input.val().length < 1)
{
return;
}
cmd.displayer.css('overflow-y', 'hidden');
var _c = bean.utils.isChar(e.which);
if (e.which == key.BACKSPACE)
{
_c = cmd.input.val().slice(0, -1);
} else {
_c = cmd.input.val() + (_c !== false ? _c : '');
}
if (cmd.input.val().length < 1)
{
switch (e.which)
{
case key.QUESTION_MARK:
_c = '?';
break;
case key.COLON:
_c = ':';
break;
default:
return;
}
}
if (_c !== false)
{
var _msg = cmd.guessCommand(_c);
if (_msg !== false)
{
cmd.display(_msg);
}
}
},
// }}}
// {{{ guessCommand (input)
guessCommand : function (input)
{
var _m = input[0], _rest = input.substr(1), _len = _rest.length;
var _suggestions, _commands, _args, _template;
if (input.length <= 1)
{
/**
* User has type in only one character, colon and question
* with be show the relative help without suggestion.
* Other character user types in and puts it at first, will
* got a avoid mode message.
*/
if (_m == '?')
{
return this.defSearchHelp;
} else if (_m == ':' || input.length == 0) {
return this.defCommandHelp;
} else {
return this.avoidMode;
}
return;
} else if (_m == '?') {
// Query Mode.
if (input.length == 1)
{
return bean.cmd.defSearchHelp;
}
_suggestions = this.searchCmdIdx;
_commands = this.searchCmds;
_template = ' [keywords]';
} else if (_m == ':') {
// Command Mode.
_suggestions = this.commonCmdIdx;
_commands = this.commonCmds;
_template = '';
} else {
/**
* User has been type in something, and the first
* character neither colon nor question mark. So
* he/her got the aoid mode message again.
*/
return false;
}
// Do searching here.
for (var i = 0; i < _len; ++i)
{
var _c = _rest[i];
_suggestions = bean.utils.filter(_suggestions, function (val)
{
return (val[i] == _c) ? true : false;
});
}
// If no command match, no suggestion will be display.
if (_suggestions.length < 1)
{
return this.undefinedCmd;
}
// Take five suggestions fit input well, then list to user.
_suggestions.sort();
_suggestions = _suggestions.slice(0, 5);
var _i = ['</dl>'];
var _j = _suggestions.length - 1, _n, _tmp;
while (_j > 0)
{
_n = _suggestions[_j--];
var _nameSwap = (_commands[_n].isShortcut)
? _commands[_n].shortcut
: _commands[_n].name;
_tmp = '<dt><strong>'
+ _m
+ _nameSwap
+ '</strong>'
+ _template
+ '</dt><dd>'
+ _commands[_n].description
+ '</dd>';
_i.push(_tmp);
}
_n = _suggestions[0];
_tmp = '<dt id="dh_suggest_fst"><strong>'
+ _m
+ _commands[_n].name
+ '</strong>'
+ _template
+ '</dt><dd>'
+ _commands[_n].description
+ '</dd>';
_i.push(_tmp);
_i.push('<dl>');
_i.reverse();
return _i.join('');
},
// }}}
// {{{ parse ()
parse : function ()
{
var input = this.input.val();
var _t = (input.indexOf(' ') == -1)
? input.length
: input.indexOf(' ');
var _m = input[0], _cmd = $.trim(input.substr(1, _t));
var _rest = input.substr(_t);
var _fn;
if (_m == ':')
{
if (typeof this.commonCmds[_cmd] == 'undefined')
{
this.display(this.undefinedCmd);
return false;
}
_fn = this.commonCmds[_cmd];
} else if (_m == '?') {
if (typeof this.searchCmds[_cmd] == 'undefined')
{
_rest = encodeURIComponent($.trim(input.substr(1)));
window.location = 'http://www.douban.com/subject_search?'
+ 'search_text='
+ _rest;
return true;
}
_fn = this.searchCmds[_cmd];
} else {
this.display(this.avoidMode);
return false;
}
_fn.execute.call(_fn, $.trim(_rest));
if (_fn.hideConsoleAfterExecute === true)
{
this.hide();
}
return true;
},
// }}}
// {{{ display (msg)
display : function (msg)
{
this.displayer.html(msg);
},
// }}}
// {{{ setStyle ()
setStyle : function ()
{
var _style = [
'#dh_console_switcher {',
'cursor: pointer;',
'}',
'#dh_stick {',
'width: 5px;',
'float: left;',
'cursor: pointer;',
'background-color: #F9F9F9;',
'-moz-border-radius: 4px',
'}',
'#dh_stick:hover {',
'background-color: #DADADA;',
'}',
'#dh_console {',
'width: 500px;',
'height: 0;',
'max-height: 320px;',
'position: static;',
'top: 26%;',
'z-index: 99;',
'visibility: hidden;',
'text-align: center;',
'color: #FFF;',
'}',
'#dh_help {',
'height: 300px;',
'position: fixed;',
'left: 30%;',
'z-index: 98;',
'visibility: visible;',
'overflow-y: scroll;',
'-moz-border-radius-topleft: 5px;',
'-moz-border-radius-topright: 5px;',
'background-color: rgba(80, 80, 80, 0.75);',
'text-align: left;',
'}',
'#dh_console_bar {',
'margin: 0;',
'padding: 7px 10px 0;',
'text-align: right;',
'-moz-border-radius-topleft: 5px;',
'-moz-border-radius-topright: 5px;',
'background-color: rgba(80, 80, 80, 0.75);',
'}',
'#dh_console_bar span {',
'cursor: pointer;',
'font-weight: bolder;',
'}',
'#dh_console_display {',
'max-height: 280px;',
'margin: 0;',
'padding: 5px 10px 7px;',
'text-align: left;',
'font-size: 14px;',
'line-height: 1.5em;',
'-moz-border-radius-bottomleft: 5px;',
'-moz-border-radius-bottomright: 5px;',
'background-color: rgba(80, 80, 80, 0.75);',
'}',
'#dh_console_display dl {',
'margin: 0;',
'padding-top: 3px;',
'padding-bottom: 7px;',
'}',
'#dh_console_display h4 {',
'margin: 10px 0 3px;',
'padding: 4px 20px;',
'background: none;',
'background-color: #A0A0A0;',
'height: auto;',
'font-weight: bold;',
'line-height: 1.4em;',
'font-size: 16px;',
'}',
'#dh_console_display dt {',
'margin: 3px 10px 0;',
'font-size: 16px',
'}',
'#dh_console_display dd {',
'margin: 0 10px 0; ',
'}',
'#dh_console_display dt strong {',
'color: #FF3',
'}',
'#dh_console_input {',
'width: 480px;',
'height: 1.4em;',
'margin: 0;',
'padding: 0 10px;',
'line-height: 1.3em;',
'font-family: monaco, verdana, sans-serif;',
'background-color: #7F7F7F;',
'color: #FFF;',
'border: none;',
'border-top: 1px solid #888;',
'border-bottom: 1px solid #909090;',
'}',
'#dh_overlay {',
'height: 100%;',
'width: 100%;',
'position: fixed;',
'z-index: 30;',
'top: 0;',
'left: 0;',
'background-color: rgba(180, 180, 180, 0.8);',
'text-align: center;',
'padding-top: 20px;',
'}',
];
$('head').append('<style>' + _style.join("\n") + '</style>');
},
// }}}
// {{{ setDefaultCommand ()
setDefaultCommand : function ()
{
var s = function (name, desc, path, param)
{
var cmd = {};
cmd['scope'] = true;
cmd['name'] = name;
cmd['isSearchMode'] = true;
cmd['description'] = '搜索关键字含有 [keywords] 的' + desc + '。';
cmd['execute'] = function (keywords)
{
window.location = 'http://www.douban.com'
+ path
+ encodeURIComponent(keywords)
+ param;
return true;
};
bean.createCommand(cmd);
}
s('book', '书籍', '/subject_search?search_text=', '&cat=1001');
s('movie', '电影/电视剧', '/subject_search?search_text=', '&cat=1002');
s('music', '音乐专辑', '/subject_search?search_text=', '&cat=1003');
s('blog', '网志博客', '/subject_search?search_text=', '&cat=1010');
s('group', '小组', '/group/search?search_text=', '');
s('topic', '主题', '/group/topic_search?q=', '');
s('user', '用户', '/people_search?search_text=', '');
s('event', '活动', '/event/search?loc=all&search_text=', '');
var c = function (name, desc, path, shortcut)
{
var cmd = {};
cmd['scope'] = true;
cmd['name'] = name;
cmd['description'] = desc;
if (typeof shortcut != 'undefined')
{
cmd['shortcut'] = shortcut;
}
cmd['execute'] = function (keywords)
{
window.location = 'http://www.douban.com' + path;
return true;
};
bean.createCommand(cmd);
}
c('logout', '退出登录。', '/logout' , 'q');
c('settings', '转到个人设置界面。', '/settings/');
c('diary', '转到日记撰写界面。', '/note/create');
c('mail', '查看站内邮件。', '/doumail/');
c('plaza', '转到广场列表。', '/plaza/all');
c('book', '转到我的书。', '/book/mine');
c('movie', '转到我的电影。', '/movie/mine');
c('music', '转到我的音乐。', '/music/mine');
c('group', '转到我的小组列表。', '/group/mine');
bean.createCommand({
scope: true,
name : 'help',
shortcut : 'h',
description : '列出当前页面中所有可用的命令及说明。',
hideConsoleAfterExecute : false,
execute : function ()
{
var src = ['<dl>', '<h4>命令模式</h4>'], c;
var cmd = bean.cmd;
for (var i in cmd.commonCmds)
{
c = cmd.commonCmds[i];
if (i == c.shortcut)
{
continue;
}
src.push('<dt><strong>:'
+ c.name
+ '</strong>'
+ ((c.shortcut == '')
? ''
: ', <strong>' + c.shortcut + '</strong>')
+ '</dt><dd>'
+ c.description
+ '</dd>');
}
src.push('<h4>查询模式</h4>');
for (var i in cmd.searchCmds)
{
c = cmd.searchCmds[i];
if (i == c.shortcut)
{
continue;
}
src.push('<dt><strong>?'
+ c.name
+ '</strong>'
+ ((c.shortcut == '')
? ''
: ', <strong>' + c.shortcut + '</strong>')
+ '</dt><dd>'
+ c.description
+ '</dd>');
}
src.push('</dl>');
var _b = $('<div>' + src.join('') + '</div>');
_b.css('overflow-y', 'scroll')
.css('margin', '0 4px 10px')
.css('height', '240px');
bean.cmd.display(_b);
},
});
},
// }}}
}
// }}}
// {{{ function: bean.addWrapper(options)
/**
* @param regex | function scope
* If it's a function, require return a boolean value.
* @param function wrap
* @param boolean hideSidebar
* @param function showEvent
* Call when sidebar is show.
* @param function hideEvent
* Call when sidebar is hide.
*
* // -- using following options to add as command.
*
* @param string name
* @param boolean isSearchMode
* @param boolean hideConsoleAfterExecute
* @param string shortcut
* @param function execute
* @param string description
* @param function preview
*
* @return boolean
*
* @TODO auto hide sidebar has bug, so disable this feature here.
*/
bean.addWrapper = function (options)
{
// bind options.
options = $.extend({
scope : '',
//hideSidebar : false,
showEvent : null,
hideEvent : null,
wrap : null,
}, options);
if (this.utils.testScope(options.scope) === false)
{
return false;
}
bean.createCommand(options);
if (typeof options.wrap == 'function')
{
options.wrap.call(options);
}
if (bean.utils.existsElement('dh_stick') !== false)
{
return true;
}
/**
* Base on Douban's default style, make out the sidebar hidden
* switcher.
*/
var _main, _side, _main_width, _side_width, _container, _container_width;
var _stick = $('<div id="dh_stick"></div>');
var _hidden = false;
if (this.utils.existsElement('table'))
{
_main = $('#table');
_side = $('#tabler');
_container_width = 345;
}
else if (this.utils.existsElement('tablem'))
{
_main = $('#tablem');
_side = $('#tablerm');
_container_width = 270;
} else {
return false;
}
_container = _main.children();
_side_width = parseInt(_side.css('width'));
_side.css('width', _side_width - 10 + 'px');
_stick.insertAfter(_main);
_stick.css('height', _side.css('height'));
var _toggle = function ()
{
if (_hidden == true)
{
_hidden = false;
_side.show();
_side.css('width', _side_width - 10 + 'px');
_main.css('margin-right', '-' + _side_width + 'px');
_container.css('margin-right', _side_width + 10 + 'px');
_updateStickHeight.call();
if (typeof options.showEvent == 'function')
{
options.showEvent.call();
}
} else {
_hidden = true;
_side.hide();
_side.css('width', '0');
_main.css('margin-right', '-10px');
_container.css('margin-right', '0');
_updateStickHeight.call();
if (typeof options.hideEvent == 'function')
{
options.hideEvent.call();
}
}
}
/*
if (options.hideSidebar)
{
_toggle();
}
*/
_stick.click(_toggle);
if (bean.config.showSidebarAtHover)
{
_stick.hover(function ()
{
if (_hidden == true)
{
_toggle();
}
}, function()
{
});
}
return true;
}
// }}}
// {{{ function: bean.createCommand (options)
/**
* @param regex | function scope
* If it's a function, require return a boolean value.
* @param string name
* @param boolean isSearchMode
* @param boolean hideConsoleAfterExecute
* @param string shortcut
* @param function execute
* @param string description
* @param function preview
*
* @return boolean
*/
bean.createCommand = function (options)
{
if (!this.config.enableConsole)
{
return false;
}
options = $.extend({
scope : '',
name : '',
isSearchMode : false,
hideConsoleAfterExecute : true,
shortcut : '',
execute : null,
description : '',
preview : null,
}, options);
if (options.name == ''
|| typeof options.execute != 'function'
|| options.description == '')
{
return false;
}
if (this.utils.testScope(options.scope) === false)
{
return false;
}
var cmd = this.cmd;
if (!options.isSearchMode)
{
// :command
if (typeof cmd.commonCmds[options.name] == 'undefined'
|| (options.shortcut != ''
&& typeof cmd.commonCmds[options.shortcut] == 'undefined'))
{
cmd.commonCmdIdx.push(options.name);
cmd.commonCmds[options.name] = options;
if (options.shortcut != '')
{
cmd.commonCmdIdx.push(options.shortcut);
cmd.commonCmds[options.shortcut] = options;
cmd.commonCmds[options.shortcut].isShortcut = true;
}
} else {
return false;
}
} else {
// ?command
if (typeof cmd.searchCmds[options.name] == 'undefined'
|| (options.shortcut != ''
&& typeof cmd.searchCmds[options.shortcut] == 'undefined'))
{
cmd.searchCmdIdx.push(options.name);
cmd.searchCmds[options.name] = options;
if (options.shortcut != '')
{
cmd.searchCmdIdx.push(options.shortcut);
cmd.searchCmds[options.shortcut] = options;
}
} else {
return false;
}
}
return true;
}
// }}}
// {{{ function: bean.addHotKey (key, fn, looseInTextBox)
/**
*
*/
bean.addHotKey = function (key, fn, looseInTextBox)
{
if (!bean.config.enableHotKey
|| typeof bean.bindedKey[key] != 'undefined')
{
return false;
}
bean.bindedKey[key] = fn;
$(window).keydown(function (e)
{
var _tn = e.target.tagName.toLowerCase();
if ((typeof looseInTextBox == 'undefined'
|| looseInTextBox == true)
&& (_tn == 'input' || _tn == 'textarea'))
{
return;
}
var _soc = bean.config.useCtrlInsteadOfShift ? e.ctrlKey : e.shiftKey;
if (_soc)
{
for (i in bean.bindedKey)
{
if (e.which == i)
{
bean.bindedKey[i].call();
}
}
}
});
}
// }}}
// {{{ function: bean.init ()
/**
*
*/
bean.init = function ()
{
/**
* Bind jQuery to window.$
*/
if (typeof unsafeWindow.jQuery == 'undefined')
{
window.setTimeout(function ()
{
bean.init();
}, 100);
return;
} else {
window.$ = unsafeWindow.jQuery;
}
/**
* When debug is on, bind firebug console to
* window.console, otherwise, make a mock object.
*/
this.console = (this.debug &&
typeof unsafeWindow.console != 'undefined') ?
unsafeWindow.console :
{};
/**
* Bind to current window, so we can using this
* in Firebug.
*/
if (typeof unsafeWindow.bean == 'undefined')
{
unsafeWindow.bean = bean;
}
/**
* Sets up url arguments. Public access.
*/
this.url = {
path : '',
args : {},
match : function ()
{
return (arguments.length < 1) ?
false :
(bean.utils.and(arguments, function (regex)
{
return regex.test(bean.url.path) ?
true :
false;
}));
},
is9dot : function ()
{
return (window.location.host.substr(0,2) == '9.');
},
};
this.url.path = window.location.pathname.substr(1);
if (window.location.search != '')
{
$.each(window.location.search.substr(1).split('&'), function ()
{
var swap = this.split('=');
bean.url.args[swap[0]] = swap[1];
});
}
// Init console.
if (this.config.enableConsole)
{
this.cmd.init();
var _showEvent = function ()
{
bean.cmd.show();
}
if (this.config.enableHotKey)
{
this.addHotKey(bean.key.SEMICOLON, _showEvent);
this.addHotKey(bean.key.SLASH, _showEvent);
}
}
}
// }}}
bean.init();
// {{{ wrapper: album expander
bean.addWrapper({
// {{{ bind to command 'toggle'
name : 'toggle',
execute: function ()
{
this._toggle();
},
description: '切换相册图片的显示方式:大图/缩略图。',
// }}}
// {{{ _toggle ()
_toggle : function ()
{
var button = $('#dh_expander');
var _isExpanded = true, _css = {}, _cssDiv = {};
var _replace = function (isExpended)
{
return isExpended ?
function (src)
{
return src.replace(/photo\/photo/, 'photo/thumb');
} :
function (src)
{
return src.replace(/thumb/, 'photo');
};
}
if (button.attr('href') == '#expand')
{
button.text('收缩为小图')
.attr('href', '#unexpand');
_css = {'float':'none',
'width':'auto',
'clear':'both',
'padding-top':'8px'
};
_cssDiv = {'width':'100%',
'padding-bottom' : '7px',
'border-bottom':'1px solid #DDD'
};
var _r = _replace(false);
} else if (button.attr('href') == '#unexpand') {
button.text('展开为大图')
.attr('href', '#expand');
_css = {'float':'left',
'width':'163px',
'clear':'none',
'padding-top':'0'
};
_cssDiv = {'width':'auto',
'padding-bottom' : 'auto',
'border-bottom':'none'
};
var _r = _replace(true);
}
$('.photo_wrap').each(function ()
{
var _img = $(this).find('img');
_img.attr('src', _r(_img.attr('src')));
$(this).css(_css);
$(this).find('div.pl').css(_cssDiv);
});
$('.photo_wrap div:last').css('border-bottom', 'none');
$('.photo_wrap div.pl:last').css('border-bottom', 'none');
},
// }}}
// {{{ scope ()
scope : function ()
{
return (this.match(/^photos\/album\/\w+/i)
|| this.match(/^event\/album\/\w+/i));
},
// }}}
// {{{ wrap ()
wrap: function ()
{
$('#in_tablem .photitle').append(
$(document.createTextNode(' > ')),
$('<a id="dh_expander" href="#expand">展开为大图</a>'));
var _toggle = this._toggle;
$('#dh_expander').click(function ()
{
_toggle();
});
if (bean.config.autoExpandAlbum)
{
_toggle();
}
},
// }}}
});
// }}}
// {{{ wrapper: subject photo box
bean.addWrapper({
scope : /^subject\/\d+\/$/i,
wrap : function ()
{
$('#mainpic a:first').click(function ()
{
var src = $(this).attr('href');
var p = $('<div id="dh_overlay"><img src="' + src + '" /></div>');
$('body').append(p);
p.click(function ()
{
p.remove();
});
return false;
});
},
});
// }}}
// {{{ wrapper: news feed photo expander
bean.addWrapper({
scope : /^contacts\/$/i,
wrap : function ()
{
$('.album_photo').each(function ()
{
var _item = $(this);
_item.click(function ()
{
var img = _item.find('img');
var src = img.attr('src');
if (src.indexOf('icon') !== -1)
{
src = src.replace('photo/icon', 'photo/photo');
} else {
src = src.replace('photo/photo', 'photo/icon');
}
img.attr('src', src);
unsafeWindow.console.debug('been here');
return false;
});
});
},
});
// }}}
//{{{ wrapper: page turner
bean.addWrapper({
scope : function ()
{
if (this.match(/^contacts\/$/i))
{
this._step = 20;
return true;
}
if (this.match(/^group\/topic\/\d+\/$/i))
{
this._step = 100;
return true;
}
if (this.match(/^group\/\w+\/discussion$/i))
{
this._step = 25;
return true;
}
if (this.match(/^people\/\w+\/(notes|event)$/i))
{
this._step = 10;
return true;
}
if (this.match(/^(movie|book|music)\/mine$/i)
|| this.match(/^(movie|book|music)\/list\/\w+\/(collect|wish|do)$/i))
{
this._step = 15;
return true;
}
if (this.match(/^photos\/album\/\d+\/$/i))
{
this._step = 18;
return true;
}
return false;
},
wrap : function ()
{
var url = bean.url;
var _step = url._step;
var redrect = function (param)
{
var _path = '';
for (i in url.args)
{
if (i == 'start')
{
continue;
}
_path += i + '=' + url.args[i] + '&';
}
window.location = '/' + url.path + '?' + _path + 'start=' + param;
}
if ($('.next a').length == 1)
{
bean.addHotKey(bean.key.RIGHT, function ()
{
var _tmp = (typeof url.args['start'] == 'undefined')
? _step
: parseInt(url.args['start']) + _step;
redrect(_tmp);
});
}
if ($('.prev a').length == 1)
{
bean.addHotKey(bean.key.LEFT, function ()
{
var _tmp = (typeof url.args['start'] == 'undefined')
? _step
: parseInt(url.args['start']) - _step;
redrect(_tmp);
});
}
},
});
// }}}
// {{{ wrapper: better note browsing
bean.addWrapper({
hideSidebar : true,
scope: function ()
{
return (this.match(/^mine\/notes$/i) ||
this.match(/^people\/[^\/]+\/notes$/i) ||
this.match(/^note\/\d+\/$/i));
},
wrap: function ()
{
_title_s = {
'font-size' : '18px',
};
_body_s = {
'line-height' : '1.6em',
'font-size' : '14px',
};
$('.note-header h3').css(_title_s);
$('pre.note').css(_body_s);
},
});
// }}}
// {{{ wrapper: better review browsing
bean.addWrapper({
scope: /^review\/\d+\/$/i,
wrap: function ()
{
$('.piir').css('font-size', '14px');
$('.piir').css('line-height', '1.6em');
},
});
// }}}
/**
* I don't think this is necessary.
* Maybe change it later on,
* one day I get energy to continue work on this script again.
*
// {{{ wrapper: better group browsing
bean.addWrapper({
scope : /^group\/[\w+_\-]+\/$/i,
hideSidebar : true,
});
bean.addWrapper({
scope : /^group\/topic\/\d+\/$/i,
hideSidebar : true,
hideEvent : function ()
{
var _rs = [];
$('.wr').slice(1).each(function ()
{
// eg: ["2008-08-28", "17:42:41", "Leechael\n", "", "", "", "", "(肇庆)"]
var _t1 = $(this).find('h4').text().split(' ');
// img element, it's parent node is an anchor.
var _t2 = $(this).find('.pil');
var _i = {
loc : _t1.pop().slice(1, -1),
time : _t1.slice(0, 2).join(' '),
nick : $.trim(_t1.slice(2).join(' ')),
reply: $.trim($(this).find('.wrc').html()),
src : _t2.attr('src'),
uri : _t2.parent().attr('href'),
};
_rs.push(_i);
});
}
});
// }}}
*/
