');
let r = re.exec(comment);
if (r)
videos.push(new RelatedID(link, r[1].slice(-20)));
});
} catch (e) {
U.log('stella: ' + e)
}
return videos;
}
function tagsFromPage () {
let nodes = content.document.getElementsByClassName('nicopedia');
return [new RelatedTag(it.textContent) for each (it in nodes) if (it.rel == 'tag')];
}
return [].concat(IDsFromComment(), IDsFromAPI(), tagsFromPage());
},
get repeating () this.player.ext_isRepeat(),
set repeating (value) (this.player.ext_setRepeat(value), value),
get large () this.player.ext_getVideoSize() === NicoPlayer.SIZE_LARGE,
set large (value) {
if (value && !this.large) {
let win = Buffer.findScrollableWindow();
this.storage.scrollPositionBeforeLarge = {x: win.scrollX, y: win.scrollY};
}
this.player.ext_setVideoSize(value ? NicoPlayer.SIZE_LARGE : NicoPlayer.SIZE_NORMAL);
let pos = this.storage.scrollPositionBeforeLarge;
if (!value && typeof pos != "undefined")
setTimeout(function () buffer.scrollTo(pos.x, pos.y), 0);
this.last.screenMode = this.large ? 'large' : null;
return this.large;
},
get state () {
switch (this.player.ext_getStatus()) {
case 'end':
return Player.ST_ENDED;
case 'playing':
return this.storage.bug_paused ? Player.ST_PAUSED : Player.ST_PLAYING;
case 'paused':
return Player.ST_PAUSED;
case 'buffering':
default:
return Player.ST_OTHER;
}
},
get title () content.document.title.replace(/\s*\u2010\s*\u30CB\u30B3\u30CB\u30B3\u52D5\u753B(.+)$/, ''),
get totalTime () parseInt(this.player.ext_getTotalTime()),
get volume () parseInt(this.player.ext_getVolume()),
set volume (value) (this.player.ext_setVolume(value), this.volume),
fetch: function (filepath) {
let self = this;
let watchURL = U.currentURL;
let [,id] = watchURL.match(/watch\/(.+)$/);
let apiURL = 'http://www.nicovideo.jp/api/getflv?v=' + id;
U.httpRequest(
watchURL,
null,
function () {
U.httpRequest(
'http://www.nicovideo.jp/api/getflv?v=' + self.id,
null,
function (xhr) {
let res = xhr.responseText;
let info = {};
res.split(/&/).forEach(function (it) let ([n, v] = it.split(/=/)) (info[n] = v));
U.download(decodeURIComponent(info.url), filepath, self.fileExtension, self.title);
let postData = '';
// FIXME
let msgFilepath = filepath.replace(/\.[^\.]+$/, '.xml');
U.download(decodeURIComponent(info.ms), msgFilepath, '.xml', self.title, postData);
}
);
}
);
},
makeURL: function (value, type) {
switch (type) {
case Player.URL_ID:
return 'http://www.nicovideo.jp/watch/' + value;
case Player.URL_TAG:
return 'http://www.nicovideo.jp/tag/' + encodeURIComponent(value);
case Player.URL_SEARCH:
return 'http://www.nicovideo.jp/search/' + encodeURIComponent(value);
}
return value;
},
pause: function () {
this.storage.bug_paused = true;
this.player.ext_play(false);
},
play: function () {
this.storage.bug_paused = false;
this.player.ext_play(true)
},
playOrPause: function () {
if (this.is(Player.ST_PLAYING)) {
this.pause();
} else {
let base = this.currentTime;
setTimeout(U.bindr(this, function () (base === this.currentTime ? this.playEx() : this.pause())), 100);
}
},
say: function (message) {
U.log('stsay');
this.sendComment(message);
},
// みかんせいじん
// test -> http://www.nicovideo.jp/watch/sm2586636
// 自分のコメントが見れないので、うれしくないかも。
sendComment: function (message, command, vpos) {
let self = this;
// コメント連打を防止
{
let now = new Date();
let last = this.__last_comment_time;
if (last && (now.getTime() - last.getTime()) < 5000)
return U.raise('Shurrup!!');
this.__last_comment_time = now;
}
function getThumbInfo () {
U.log('getThumbInfo');
if (self.cachedInfo.block_no !== undefined)
return;
let xhr = U.httpRequest(self.baseURL + 'api/getthumbinfo/' + self.id);
let xml = xhr.responseXML;
let cn = xml.getElementsByTagName('comment_num')[0];
self.cachedInfo.block_no = cn.textContent.replace(/..$/, '');
}
function getFLV () {
U.log('getFLV');
if (self.cachedInfo.flvInfo !== undefined)
return;
let xhr = U.httpRequest(self.baseURL + 'api/getflv?v=' + self.id);
let res = xhr.responseText;
self.cachedInfo.flvInfo = U.parseParameter(res);
}
function getPostkey () {
U.log('getPostkey');
let info = self.cachedInfo;
if (info.postkey !== undefined)
return;
let url = U.fromTemplate(
'--base--api/getpostkey?thread=--thread_id--&block_no=--block_no--',
{
base: self.baseURL,
thread_id: info.flvInfo.thread_id,
block_no: info.block_no
}
);
U.log(url);
let xhr = U.httpRequest(url);
let res = xhr.responseText;
info.postkey = res.replace(/^.*=/, '');
}
function getComments () {
U.log('getComments');
let info = self.cachedInfo;
if (info.ticket !== undefined)
return;
let tmpl = '';
let xhr = U.httpRequest(info.flvInfo.ms, U.fromTemplate(tmpl, info.flvInfo));
let xml = xhr.responseXML;
let r = xml.evaluate('//packet/thread', xml, null, 9, null, 7, null).singleNodeValue;
info.ticket = r.getAttribute('ticket');
}
function sendChat () {
U.log('sendChat');
let info = self.cachedInfo;
let tmpl = '--body--';
let args = {
__proto__: info.flvInfo,
ticket: info.ticket,
postkey: info.postkey,
vpos: vpos * 100,
mail: command,
body: message
};
U.log(args);
let data = U.fromTemplate(tmpl, args);
let xhr = U.httpRequest(info.flvInfo.ms, data);
U.log(xhr.responseText);
}
function sendDummyComment (message, command, position) {
self.player.ext_sendLocalMessage(message, command, vpos);
}
// 0 秒コメントはうざいらしいので勝手に自重する
vpos = Math.max(1, parseInt(vpos || self.currentTime, 10));
U.log('sendcommnet');
getThumbInfo();
getFLV();
getPostkey();
getComments();
sendChat();
sendDummyComment(message, command, vpos);
}
};
// }}}
/*********************************************************************************
* VimeoPlayer {{{
*********************************************************************************/
function VimeoPlayer () {
Player.apply(this, arguments);
}
VimeoPlayer.getIDfromURL = function (url) let ([_, r] = url.match(/[?;&]v=([-\w]+)/)) r;
VimeoPlayer.prototype = {
__proto__: Player.prototype,
functions: {
currentTime: 'w',
fetch: 'x',
makeURL: 'x',
muted: 'w',
pause: 'x',
play: 'x',
playEx: 'x',
playOrPause: 'x',
title: 'r'
},
__initializePlayer: function (player) {
if (!player || player.__stella_initialized)
return player;
player.__stella_mute = false;
player.__stella_volume = 100;
player.__stella_initialized = true;
return player;
},
icon: 'http://www.vimeo.com/favicon.ico',
set currentTime (value) (this.player.api_seekTo(U.fromTimeCode(value)), value),
get muted () this.__mute,
set muted (value) (this.volume = value ? 0 : 100),
get player ()
this.__initializePlayer(content.document.querySelector('.vimeo_holder * object').wrappedJSObject),
get ready () !!this.player,
get state () {
if (this.player.api_isPlaying())
return Player.ST_PLAYING
if (this.player.api_isPaused())
return Player.ST_PAUSED;
return Player.ST_OTHER;
},
get title ()
U.xpathGet('//div[@class="title"]').textContent,
get isValid () U.currentURL.match(/^http:\/\/(www\.)?vimeo\.com\/(channels\/(hd)?#)?\d+$/),
// XXX setVolume は実際には存在しない?
get volume () parseInt(this.player.__stella_volume),
set volume (value) (this.api_setVolume(value), this.player.__stella_volume = value),
fetch: function(filepath) {
let self = this;
let id = U.currentURL.match(/vimeo\.com\/(\d+)/)[1];
U.httpRequest(
'http://www.vimeo.com/moogaloop/load/clip:' + id,
null,
function(xhr) {
let doc = xhr.responseXML;
let signature = U.xpathGet('/xml/request_signature', doc).textContent;
let timestamp = U.xpathGet('/xml/timestamp', doc).textContent;
let isHD = parseInt(U.xpathGet('/xml/video/isHD', doc).textContent);
let url = 'http://www.vimeo.com/moogaloop/play/clip:' + id
+ '/' + signature + '/' + timestamp
+ '/?q=' + (isHD ? 'hd' : 'sd');
U.download(url, filepath, isHD ? '.mp4' : '.flv', self.title);
}
);
},
makeURL: function (value, type) {
switch (type) {
case Player.URL_ID:
return 'http://www.vimeo.com/' + value;
case Player.URL_SEARCH:
return 'http://www.vimeo.com/videos/search:' + encodeURIComponent(value);
}
return value;
},
play: function () this.player.api_play(),
pause: function () this.player.api_pause()
};
// }}}
/*********************************************************************************
* ContextMenu {{{
*********************************************************************************/
const ContextMenuVolume = [];
for (let i = 0; i <= 100; i += 10)
ContextMenuVolume.push({name: 'setVolume', label: i + '%', attributes: {volume: i}});
const ContextMenuTree = [
'play',
'pause',
'comment',
'repeating',
'fullscreen',
'fetch',
{
name: 'volume-root',
label: 'Volume',
id: ID_PREFIX + 'volume-menupopup',
sub: ContextMenuVolume
},
{
name: 'relations-root',
label: 'Relations',
id: ID_PREFIX + 'relations-menupopup',
sub: []
},
'cancel',
];
function buildContextMenu (setting) {
function append (parent, menu) {
if (typeof menu == 'string')
menu = {name: menu};
if (menu instanceof Array)
return menu.forEach(function (it) append(parent, it));
if (!menu.label)
menu.label = U.capitalize(menu.name);
let (elem) {
if (menu.sub) {
let _menu = document.createElement('menu');
let _menupopup = elem = document.createElement('menupopup');
_menu.setAttribute('label', menu.label);
_menu.appendChild(_menupopup);
parent.appendChild(_menu);
append(_menupopup, menu.sub);
} else {
elem = document.createElement('menuitem');
elem.setAttribute('label', menu.label);
parent.appendChild(elem);
}
menu.id && elem.setAttribute('id', menu.id);
for (let [name, value] in Iterator(menu.attributes || {}))
elem.setAttribute(name, value);
setting.onAppend.call(setting, elem, menu);
}
}
let root = document.createElement('menupopup');
root.id = setting.id;
append(root, setting.tree);
setting.set.setAttribute('context', root.id);
setting.parent.appendChild(root);
return root;
}
// }}}
/*********************************************************************************
* Event {{{
*********************************************************************************/
function WebProgressListener (listeners) {
let self = this;
for (let [name, listener] in Iterator(listeners))
this[name] = listener;
getBrowser().addProgressListener(this);
// これは必要?
window.addEventListener('unload', U.bindr(this.uninstall), false);
}
WebProgressListener.prototype = {
onStatusChange: function (webProgress, request, stateFlags, staus) undefined,
onProgressChange: function (webProgress, request, curSelfProgress,
maxSelfProgress, curTotalProgress, maxTotalProgress) undefined,
onLocationChange: function (webProgress, request, location) undefined,
onStateChange: function (webProgress, request, status, message) undefined,
onSecurityChange: function (webProgress, request, state) undefined,
uninstall: function () getBrowser().removeProgressListener(this)
};
// }}}
/*********************************************************************************
* Stella {{{
*********************************************************************************/
function Stella (setting) {
this.initialize.apply(this, arguments);
this.setting = setting;
}
Stella.MAIN_PANEL_ID = ID_PREFIX + 'main-panel',
Stella.MAIN_MENU_ID = ID_PREFIX + 'main-menu',
Stella.VOLUME_MENU_ID = ID_PREFIX + 'volume-menu',
Stella.prototype = {
// new 時に呼ばれる
initialize: function () {
let self = this;
this.players = {
niconico: new NicoPlayer(this.stella),
youtube: new YouTubePlayer(this.stella),
youtube5: new YouTubePlayer5(this.stella),
youtubeuc: new YouTubeUserChannelPlayer(this.stella),
vimeo: new VimeoPlayer(this.stella)
};
// this.noGUI = true;
this.createGUI();
this.__onResize = window.addEventListener('resize', U.bindr(this, this.onResize), false);
this.progressListener = new WebProgressListener({onLocationChange: U.bindr(this, this.onLocationChange)});
},
createGUI: function () {
if (this.noGUI)
return;
this.createStatusPanel();
this.onLocationChange();
this.hidden = true;
},
// もちろん、勝手に呼ばれたりはしない。
finalize: function () {
this.removeStatusPanel();
this.disable();
this.progressListener.uninstall();
for each (let player in this.players)
player.finalize();
window.removeEventListener('resize', this.__onResize, false);
},
get hidden () (this.panel.hidden),
set hidden (v) (this.panel.hidden = v),
get isValid () (this.where),
get player () (this.where && this.players[this.where]),
get statusBar () document.getElementById('status-bar'),
get statusBarVisible () !this.statusBar.getAttribute('moz-collapsed', false),
set statusBarVisible (value) (this.statusBar.setAttribute('moz-collapsed', !value), value),
get storage ()
(content.document.__stella_storage || (content.document.__stella_storage = {})),
get where () {
for (let [name, player] in Iterator(this.players))
if (player.isValid)
return name;
},
addUserCommands: function () {
let self = this;
function add (cmdName, funcS, funcB) {
commands.addUserCommand(
['st' + cmdName],
cmdName.replace(/[\[\]]+/g, '') + ' - Stella',
(funcS instanceof Function)
? funcS
: function (arg) {
if (!self.isValid)
U.raiseNotSupportedPage();
let p = self.player;
let func = arg.bang ? funcB : funcS;
if (p.has(func, 'rwt'))
p.toggle(func);
else if (p.has(func, 'rw'))
p[func] = arg[0];
else if (p.has(func, 'x'))
p[func].apply(p, arg);
else
U.raiseNotSupportedFunction();
self.update();
},
{argCount: '*', bang: !!funcB},
true
);
}
add('pl[ay]', 'playOrPause', 'play');
add('pa[use]', 'pause');
add('mu[te]', 'muted');
add('re[peat]', 'repeating');
add('co[mment]', 'comment');
add('vo[lume]', 'volume', 'turnUpDownVolume');
add('se[ek]', 'seek', 'seekRelative');
add('fe[tch]', 'fetch');
add('la[rge]', 'large');
add('fu[llscreen]', 'fullscreen');
if (U.s2b(liberator.globalVariables.stella_nico_use_comment, false))
add('sa[y]', 'say');
commands.addUserCommand(
['stfe[tch]'],
'Download movie file - Stella',
function (args) {
if (!self.isValid)
return U.raiseNotSupportedPage();
if (!self.player.has('fetch', 'x'))
return U.raiseNotSupportedFunction();
self.player.fetch(args.literalArg);
},
{
literal: 0,
completer: function (context) completion.file(context)
},
true
);
commands.addUserCommand(
['stqu[ality]'],
'Quality - Stella',
function (args) {
if (!self.isValid)
return U.raiseNotSupportedPage();
if (!self.player.has('quality', 'w'))
return U.raiseNotSupportedFunction();
self.player.quality = args.literalArg;
},
{
literal: 0,
completer: function (context) {
if (!self.player.has('qualities', 'r'))
return;
context.title = ['Quality', 'Description'];
context.completions = [[q, q] for each ([, q] in self.player.qualities)];
}
},
true
);
let (lastCompletions = []) {
commands.addUserCommand(
['strel[ations]'],
'relations - Stella',
function (args) {
if (!self.isValid)
return U.raiseNotSupportedPage();
let arg = args.literalArg;
let index = /^\d+:/.test(arg) && parseInt(arg, 10);
if (index > 0)
arg = lastCompletions[index - 1].command;
let url = self.player.has('makeURL', 'x') ? makeRelationURL(self.player, arg) : arg;
liberator.open(url, args.bang ? liberator.NEW_TAB : liberator.CURRENT_TAB);
},
{
literal: 0,
argCount: '*',
bang: true,
completer: function (context, args) {
if (!self.isValid)
U.raiseNotSupportedPage();
if (!self.player.has('relations', 'r'))
U.raiseNotSupportedFunction();
context.filters = [CompletionContext.Filter.textDescription];
context.anchored = false;
context.title = ['Tag/ID', 'Description'];
context.keys = {text: 'text', description: 'description', thumbnail: 'thumbnail'};
let process = Array.slice(context.process);
context.process = [
process[0],
function (item, text)
(item.thumbnail ? <>
{text}>
: process[1].apply(this, arguments))
];
lastCompletions = self.player.relations;
context.completions = lastCompletions.map(function (rel) rel.completionItem);
},
},
true
);
}
},
addPageInfo: function () {
let self = this;
delete buffer.pageInfo.S;
buffer.addPageInfoSection(
'S',
'Stella Info',
function (verbose)
(self.isValid && self.player.has('pageinfo', 'r')
? [
[n, {modules.template.maybeXML(v)}
]
for each ([n, v] in self.player.pageinfo)
]
: [])
);
},
createStatusPanel: function () {
let self = this;
function setEvents (name, elem) {
['click', 'command', 'popupshowing'].forEach(function (eventName) {
let onEvent = self[
'on' +
U.capitalize(name) +
U.capitalize(eventName == 'command' ? 'click' : eventName)
];
onEvent && elem.addEventListener(eventName, function (event) {
if (eventName == 'click' && event.button != 0)
return;
onEvent.apply(self, arguments);
self.update();
}, false);
});
}
function createLabel (store, name, l, r) {
let label = store[name] = document.createElement('label');
label.setAttribute('value', '-');
label.style.marginLeft = (l || 0) + 'px';
label.style.marginRight = (r || 0) + 'px';
label.__defineGetter__('text', function () this.getAttribute('value'));
label.__defineSetter__('text', function (v) this.setAttribute('value', v));
setEvents(name, label);
}
let panel = this.panel = document.createElement('statusbarpanel');
panel.setAttribute('id', Stella.MAIN_PANEL_ID);
let hbox = document.createElement('hbox');
hbox.setAttribute('align', 'center');
let icon = this.icon = document.createElement('image');
icon.setAttribute('class', 'statusbarpanel-iconic');
icon.style.marginRight = '4px';
setEvents('icon', icon);
icon.addEventListener('dblclick', U.bindr(this, this.onIconDblClick), false);
let labels = this.labels = {};
let toggles = this.toggles = {};
createLabel(labels, 'main', 2, 2);
createLabel(labels, 'volume', 0, 2);
for each (let player in this.players) {
for (let func in player.functions) {
if (player.has(func, 't'))
(func in labels) || createLabel(toggles, func);
}
}
panel.appendChild(hbox);
hbox.appendChild(icon);
[hbox.appendChild(label) for each (label in labels)];
[hbox.appendChild(toggle) for each (toggle in toggles)];
let menu = this.mainMenu = buildContextMenu({
id: Stella.MAIN_MENU_ID,
parent: panel,
set: hbox,
tree: ContextMenuTree,
onAppend: function (elem, menu) setEvents(U.capitalize(menu.name), elem)
});
let stbar = document.getElementById('status-bar');
stbar.appendChild(panel);
let relmenu = document.getElementById('anekos-stella-relations-menupopup');
panel.addEventListener('DOMMouseScroll', U.bindr(this, this.onMouseScroll), true);
},
disable: function () {
if (this.noGUI)
return;
this.hidden = true;
if (this.__updateTimer) {
clearInterval(this.__updateTimer);
delete this.__updateTimer;
}
if (this.__autoFullscreenTimer) {
clearInterval(this.__autoFullscreenTimer);
}
},
enable: function () {
if (this.noGUI)
return;
this.hidden = false;
this.icon.setAttribute('src', this.player.icon);
for (let name in this.toggles) {
this.toggles[name].hidden = !this.player.has(name, 't');
}
if (!this.__updateTimer) {
this.__updateTimer = setInterval(U.bindr(this, this.update), 500);
}
},
removeStatusPanel: function () {
let e = this.panel || document.getElementById(this.panelId);
if (e && e.parentNode)
e.parentNode.removeChild(e);
},
update: function () {
if (!(this.isValid && this.player.ready))
return;
this.labels.main.text =
let (v = this.player.statusText)
(this.__currentTimeTo == undefined) ? v
: v.replace(/^\d*\:\d*/,
U.toTimeCode(this.__currentTimeTo));
this.labels.volume.text = this.player.volume;
for (let name in this.toggles) {
this.toggles[name].text = (this.player[name] ? String.toUpperCase : U.id)(name[0]);
}
},
onCommentClick: function () (this.player.toggle('comment')),
onFetchClick: function () this.player.fetch(),
// フルスクリーン時にステータスバーを隠さないようにする
onFullScreen: function () {
if (window.fullScreen) {
this.__statusBarVisible = this.statusBarVisible;
this.statusBarVisible = true;
} else {
if (this.__statusBarVisible !== undefined)
this.statusBarVisible = this.__statusBarVisible;
}
},
onFullscreenClick: function () this.player.toggle('fullscreen'),
onIconClick: function () this.player.playOrPause(),
onIconDblClick: function () this.player.toggle('fullscreen'),
onLargeClick: function () {
// XXX fullscreen と large の実装が同じ場合に問題になるので、toggle は使わない
let old = this.player.large;
if (this.player.fullscreen)
this.player.fullscreen = false;
this.player.large = !old;
},
onLocationChange: function () {
if (this.__valid !== this.isValid) {
(this.__valid = this.isValid) ? this.enable() : this.disable();
}
if (this.isValid) {
clearInterval(this.__onReadyTimer);
this.__onReadyTimer = setInterval(
U.bindr(this, function () {
if (this.player && this.player.ready) {
clearInterval(this.__onReadyTimer);
delete this.__onReadyTimer;
this.onReady();
}
}),
200
);
}
},
onMainClick: function (event) {
if (event.button)
return;
if (!(this.player && this.player.has('currentTime', 'rw', 'totalTime', 'r')))
return;
let rect = event.target.getBoundingClientRect();
let x = event.screenX;
let per = (x - rect.left) / (rect.right - rect.left);
this.player.currentTime = parseInt(this.player.totalTime * per);
},
onMouseScroll: (function () {
let timerHandle;
return function (event) {
if (!(this.isValid && this.player.ready && event.detail))
return;
if (event.target == this.labels.main) {
if (this.__currentTimeTo == undefined)
this.__currentTimeTo = this.player.currentTime;
this.__currentTimeTo += (event.detail > 0) ? -5 : 5;
this.__currentTimeTo = Math.min(Math.max(this.__currentTimeTo, 0), this.player.totalTime);
clearTimeout(timerHandle);
timerHandle = setTimeout(
U.bindr(this, function () {
this.player.currentTime = this.__currentTimeTo;
delete this.__currentTimeTo;
}),
1000
);
this.update();
} else {
this.player.volume += (event.detail > 0) ? -5 : 5;
this.update();
}
}
})(),
onMutedClick: function (event) this.player.toggle('muted'),
onPauseClick: function () this.player.pause(),
onPlayClick: function () this.player.play(),
onReady: function () {
if (this.player.last.screenMode && !this.storage.alreadyAutoFullscreen
&& !this.__autoFullscreenTimer) {
this.__autoFullscreenTimer = setInterval(
U.bindr(this, function () {
if (!this.player.ready)
return;
clearInterval(this.__autoFullscreenTimer)
setTimeout(
U.bindr(this, function () (this.player[this.player.last.screenMode] = true)),
this.setting.common.autoFullscreenDelay
);
delete this.__autoFullscreenTimer;
}),
200
);
}
this.storage.alreadyAutoFullscreen = true;
},
onRepeatingClick: function () this.player.toggle('repeating'),
onRelationsRootPopupshowing: function () {
let self = this;
function clickEvent (cmd)
function () liberator.open(makeRelationURL(self.player, cmd));
if (!this.player)
return;
let relmenu = document.getElementById('anekos-stella-relations-menupopup');
let rels = this.player.relations;
while (relmenu.firstChild)
relmenu.removeChild(relmenu.firstChild);
rels.forEach(function (rel) {
let elem = document.createElement('menuitem');
let prefix = rel instanceof RelatedID ? 'ID: ' :
rel instanceof RelatedTag ? 'Tag: ' :
'';
elem.setAttribute('label', prefix + rel.description);
elem.addEventListener('command', clickEvent(rel.command), false);
relmenu.appendChild(elem);
}, this);
},
onResize: function () {
if (this.__fullScreen !== window.fullScreen) {
this.__fullScreen = window.fullScreen;
this.onFullScreen(this.__fullScreen);
}
},
onSetVolumeClick: function (event) (this.player.volume = event.target.getAttribute('volume'))
};
U.fixDoubleClick(Stella.prototype, 'onIconClick', 'onIconDblClick');
// }}}
/*********************************************************************************
* Functions {{{
*********************************************************************************/
function makeRelationURL (player, command) {
if (!player.has('makeURL', 'x'))
U.raise('Mysterious Error! makeURL has been not implmented.');
if (command.match(/^[#\uff03]/))
return player.makeURL(command.slice(1), Player.URL_ID);
if (command.match(/^[:\uff1a]/))
return player.makeURL(command.slice(1), Player.URL_TAG);
if (command.indexOf('http://') == -1)
return player.makeURL(encodeURIComponent(command), Player.URL_TAG);
return command;
}
// }}}
/*********************************************************************************
* Install {{{
*********************************************************************************/
if (InVimperator) {
let estella = liberator.globalVariables.stella;
let install = function () {
let stella = liberator.globalVariables.stella = new Stella(new Setting());
stella.addUserCommands();
stella.addPageInfo();
U.log('Stella: installed.');
};
// すでにインストール済みの場合は、一度ファイナライズする
// (デバッグ時に前のパネルが残ってしまうため)
if (estella) {
estella.finalize();
install();
} else {
window.addEventListener(
'DOMContentLoaded',
function () {
window.removeEventListener('DOMContentLoaded', arguments.callee, false);
install();
},
false
);
}
} else {
/* do something */
}
// }}}
})();
// vim:sw=2 ts=2 et si fdm=marker: