// ==UserScript==
// @name nicovideo - wnp
// @description windowised nicovideo player.
// @author miya2000
// @namespace http://d.hatena.ne.jp/miya2000/
// @version 1.0.0
// @include http://www.nicovideo.jp/*
// @exclude http://www.nicovideo.jp/watch/*
// @exclude http://*http*
// ==/UserScript==
/*
[usage]
Open http://www.nicovideo.jp/
and you can start with the right-bottom button on the page.
@see http://d.hatena.ne.jp/kotas/20070925/playlist
http://abc.s65.xrea.com/prox/wiki/%A5%D5%A5%A3%A5%EB%A5%BF%A1%A2%A5%EA%A5%B9%A5%C8%B8%F8%B3%AB/nicovideo/#iroiro
http://blog.fulltext-search.biz/articles/2008/01/31/nico-nico-player-wrapper
http://blog.guron.net/2009/06/04/636.php
*/
// ==== preparation ==== //
(function(f) {
if (typeof unsafeWindow == "undefined") return f;
return function() {
var s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.setAttribute('style', 'display: none;');
s.innerHTML = '(' + f.toString() + ')()';
(document.body || document.documentElement).appendChild(s);
};
})
// ==== wnp ==== //
(function() {
if (window.name == 'wnp') return;
var WNP = {};
// ==== Prefs ==== //
WNP.Prefs = {
WIDTH : 610, // startup window size.
HEIGHT : 470, //
LOOP_ON_STARTUP : false, // "loop" on startup.
COMMENT_OFF_ON_STARTUP : false, // "comment-off" on startup.
ALWAYS_ON_TOP_ON_STARTUP : false, // "always on top" on startup.
PLAYLIST_STYLE_SIMPLE_ON_STARTUP : false, // "playlist style simple" on startup.
REMOVE_ON_FINISH_ON_STARTUP : true, // "remove on finish" on startup.
USE_HISTORY_ON_STARTUP : true, // "use history" on startup.
SKIP_DELETED_MOVIE : true, // skip deleted movie.
MENU_WIDTH_RATIO : 50, // (%) menu width ratio when showing menu.
OBSERVE_INTERVAL : 500, // (ms) observe interval.
PAGE_TIMEOUT : 80, // (sec) page load timeout.
VIDEO_TIMEOUT : 60, // (sec) video play timeout.
OFFTIMER : 120, // (min) off timer.
LOOP_BREAK_COUNT : 3 // exit from loop video by specified count.
};
// ==== const ==== //
var Consts = {
WNP_TITLE : 'WNP',
WNP_GLOBAL_NAME : 'WNP', // global name of WNP entry object.
WNP_IMAGE_SAVE : 'data:image/gif;base64,R0lGODlhEAAQAIAAAAAAAPD4%2FyH5BAEAAAAALAAAAAAQABAAAAIhhI%2Bpq%2BEPHYo0zAovlscy4BnhMo7N9IHoV6Ytq23pTAMFADs%3D',
WNP_IMAGE_PLAY : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAAt0lEQVQ4y2NgoCL4%2F%2F8%2FXnnB0NBQFyAtQA0DJVatWtUPVHALRAP5kpQaqAmUvAzE%2F4D4OxDvB4rZAzE7uQZqASWvQA2EgSchISG5oKAgy4X%2F%2Fv27DMR%2Fgfg%2FDAPBm5UrV07AFQSkuvA%2FoSAgx0BkcAnkE3K8jAxgXn8CTFL56OFJjgvxxjipBr4BpskJ%2BNIkPgO1gV67geZFvEmGkIFKQMntQPyB2ERNTF6WAnoxjdhsR4yBZJU2AAcDLeBOG3M7AAAAAElFTkSuQmCC',
WNP_IMAGE_PAUSE : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAAe0lEQVQ4y2NgoCL4%2F%2F8%2FfgWhoaFuxIgRYyDLqlWrooAKfoJoEB%2BHGCOxBnIAJTf9h4BNID4OsYEzkP3fv38b%2F0HARhAfhxjDqJeHsJc5gN7aAdIJomEGYhEj2stsQMl2UGCBaBAfhxjRLgQDYBZrICBGmoG4NOISAxkIAIbuKTCbOZywAAAAAElFTkSuQmCC',
ORG_PLAYER_VIEW_WIDTH : 544,
ORG_PLAYER_VIEW_HEIGHT : 384,
ORG_PLAYER_CONTROL_HEIGHT : 63,
ORG_PLAYER_MINIMUM_WIDTH : 561
}
WNP.Consts = Consts;
Consts.svg_xml_base = [
'',
''
].join('\n');
Consts.svg_mime_type = 'image/svg+xml';
// ==== color settings ==== //
var Colors = {
item_hover: '#D7EBFF',
item_selected: '#B4DAFF',
item_dragging: '#FFCCCC',
status_error: 'red',
control_loop: 'yellow',
control_repeat: 'yellow',
control_comment_off: 'yellow',
control_mute: 'yellow',
control_always_on_top: 'yellow'
};
WNP.Colors = Colors;
// ==== main ==== //
var fn = {};
WNP.fn = fn;
BUILD_FUNC(fn);
var browser = fn.browser;
var ie = fn.ie;
var $e = fn.$e;
var toJSON = fn.toJSON;
var getAbsolutePosition = fn.getAbsolutePosition;
var addStyle = fn.addStyle;
var getStyle = fn.getStyle;
var $XS = fn.$XS;
var findVideoTitle = fn.findVideoTitle;
var createPlayInfo = fn.createPlayInfo;
WNP.html = function() {
var browser = WNP.fn.browser;
return [
'',
'',
'
',
'',
'',
'',
'',
'' + Consts.WNP_TITLE + '',
'',
'',
'',
'',
'',
'',
'',
'',
''
].join('\n');
};
WNP.pageStyle = function(pref) { return [
'.wnp_tooltip {',
' width: 168px;',
' opacity: 0.4; ', /*@cc_on 'filter:alpha(opacity=40);', @*/
' position: absolute; ',
' z-index: 999; ',
'}',
'.wnp_tooltip:hover {',
' opacity: 1; ', /*@cc_on 'filter:alpha(opacity=100);', @*/
'}',
'.wnp_tooltip a {',
' cursor: pointer;',
' display: block;',
' width: 54px;',
' height: 0;',
' line-height: 22px;',
' font-family: cursive;',
' font-size: 14px;',
' font-weight: bold;',
' text-align: center;',
' text-decoration: none;',
' color: #F0F0F0;',
' border-style: solid;',
' border-width: 15px 0;', /*@cc_on 'border-width: 15px 0 16px;', @*/
' border-top-color: #555;',
' border-bottom-color: #000;',
' padding: 0;',
' float: left;',
' margin-right: 2px;',
'}',
'.wnp_tooltip * span {',
' box-sizing: border-box;', browser.mozilla ? '-moz-box-sizing : border-box;' : '',
' border: 1px solid #DDD;',
' display: inline-block;',
' width: 50px;', /*@cc_on 'width: 48px;', @*/
' height: 24px;',
' position: relative;',
' top: -15px;',
' margin-top: 3px;',
'}',
'.wnp_tooltip a:hover {',
' border-top-color: #666;',
'}',
'.wnp_tooltip a:hover span {',
' color: #FFF;',
' border-color: #FFF;',
'}',
'.wnp_tooltip a span:active { padding: 1px 0 0 2px; }',
].join('\n');
};
function BUILD_FUNC(T) {
if (T == null) T = window;
// -- utils --
// browser
var browser = {
opera : (navigator.appName.indexOf("Opera") >= 0),
mozilla : (navigator.userAgent.indexOf("Gecko/") >= 0),
ie : /*@cc_on!@*/false
};
T.browser = browser;
var ie = {};
ie.cssStandard = (document.compatMode && document.compatMode == 'CSS1Compat');
ie.clientWidth = (function() {
return ie.cssStandard ? function(d) { return (d || document).documentElement.clientWidth }
: function(d) { return (d || document).body.clientWidth }
})();
ie.clientHeight = (function() {
return ie.cssStandard ? function(d) { return (d || document).documentElement.clientHeight }
: function(d) { return (d || document).body.clientHeight }
})();
ie.window = function(element) {
return element.parentWindow || element.ownerDocument.parentWindow || window;
};
T.ie = ie;
// event.
var $e = (function() {
if ('addEventListener' in window) return function(element) { return element };
function preventDefault() { this.returnValue = false; }
function stopPropagation() { this.cancelBubble = true; }
function compat(e, el) {
if (!('preventDefault' in e)) e.preventDefault = preventDefault;
if (!('stopPropagation' in e)) e.stopPropagation = stopPropagation;
if (!('target' in e)) e.target = e.srcElement;
if (!('relatedTarget' in e)) e.relatedTarget = (e.srcElement === e.toElement) ? e.fromElement : e.toElement;
if (!('currentTarget' in e)) e.currentTarget = el;
var d = el.ownerDocument || el.document || el;
if (!('pageX' in e)) e.pageX = (d.body.scrollLeft||d.documentElement.scrollLeft) + e.clientX;
if (!('pageY' in e)) e.pageY = (d.body.scrollTop ||d.documentElement.scrollTop ) + e.clientY;
if (!e.detail && e.wheelDelta) e.detail = -(e.wheelDelta/120)*4;
}
function indexOf(listeners, a, b, c) {
for (var i = 0, len = listeners.length; i < len; i++) {
var l = listeners[i];
if (l.a === a && l.b === b && l.c === c) return i;
}
return -1;
}
if ('attachEvent' in window) {
return function $e(element) {
if ('addEventListener' in element) return element;
return (function(el) {
var listeners = [];
el.addEventListener = function(a, b, c) {
if (indexOf(listeners, a, b, c) >= 0) return;
var f = function(e) { compat(e, el); b.call(el, e); };
el.attachEvent('on' + a, f);
listeners.push({ a: a, b: b, c: c, f: f});
};
el.removeEventListener = function(a, b, c) {
var index = indexOf(listeners, a, b, c);
if (index < 0) return;
el.detachEvent('on' + a, listeners[index].f);
listeners.splice(index, 1);
};
return el;
})(element);
}
}
else {
return function(el) {
if (el.addEventListener) return el;
el.addEventListener = el.removeEventListener = function() {};
throw 'Neither "addEventListener" nor "attachEvent" is supported on this browser.';
}
}
})();
T.$e = $e;
function uescape(s) {
return escape(s).replace(/%([0-9A-F]{2})/g, '\\u00$1').replace(/%u/g, '\\u');
}
T.uescape = uescape;
function toJSON(o) {
if (o == null) return 'null';
var c = o.constructor;
if (c === Boolean) return o.toString();
if (c === Number ) return isNaN(o) ? '"NaN"' : !isFinite(o) ? '"Infinity"' : o.toString(10);
if (c === String ) return '"' + uescape(o) + '"';
if (c === Array ) {
var tmp = [];
for (var i = 0; i < o.length; i++) {
tmp[i] = toJSON(o[i]);
}
return '[' + tmp.join(',') + ']';
}
if (typeof o == 'object') {
var tmp = [];
for (var i in o) {
if (Object.prototype.hasOwnProperty.call(o, i)) {
tmp.push('"' + uescape(i) + '":' + toJSON(o[i]));
}
}
return '{' + tmp.join(',') + '}';
}
return '\"' + uescape(o.toString()) + '\"';
};
T.toJSON = toJSON;
var escapeHTML = (function() {
var dv;
return function escapeHTML(str, d) {
if (dv == null) {
dv = (d||document).createElement('div');
setTimeout(function() { dv = null; }, 0);
}
dv.textContent = /*@cc_on dv.innerText = @*/ str;
return dv.innerHTML;
};
})();
T.escapeHTML = escapeHTML;
function formatNumber(d) {
return d.toString().replace(/(\d{1,3})(?=(?:\d\d\d)+$)/g, "$1,"); //http://nanto.asablo.jp/blog/2007/12/07/2479257
};
T.formatNumber = formatNumber;
function getAbsolutePosition(el) {
var p = el.offsetParent, x = el.offsetLeft, y = el.offsetTop;
while (p) {
x += p.offsetLeft - p.scrollLeft, y += p.offsetTop - p.scrollTop, p = p.offsetParent;
}
return { x : x, y : y }
};
T.getAbsolutePosition = getAbsolutePosition;
function hasClass(el, className) {
//http://d.hatena.ne.jp/higeorange/20090613/1244821192
return new RegExp('(?:^|\\s)' + className + '(?:\\s|$)').test(el.className);
}
T.hasClass = hasClass;
function appendClass(el, className) {
if (!el) return;
if (new RegExp('(?:^|\\s)' + className + '\\s*$').test(el.className)) return;
removeClass(el, className);
el.className += ' ' + className;
}
T.appendClass = appendClass;
function removeClass(el, className) {
if (!el) return;
var orgClassName = el.className;
var newClassName = orgClassName.replace(new RegExp('(?:^|\\s)' + className + '(?:\\s|$)', 'g'), '').replace(/\s+/g, ' ').replace(/^\s|\s$/, '');
if (orgClassName != newClassName) {
el.className = newClassName;
}
}
T.removeClass = removeClass;
function addStyle(styleStr, doc) {
var document = doc || window.document;
var style = document.createElement('style');
style.type = 'text/css';
style.style.display = 'none';
if (/*@cc_on !@*/true) { style.innerHTML = styleStr; } else { style.styleSheet.cssText = styleStr; }
document.body.appendChild(style);
return style;
}
T.addStyle = addStyle;
function getStyle(element, property, pseudo) {
return (
element.currentStyle
||
element.ownerDocument.defaultView.getComputedStyle(element, pseudo || '')
)[property];
}
T.getStyle = getStyle;
function $XS(xpath, context) {
return document.evaluate(xpath,context||document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;
}
T.$XS = $XS;
function findVideoTitle(a) {
var title = '';
if (!/