// ==UserScript==
// @name BP Funcs
// @description Small script to be @require-d, providing useful functions and extensions I like to refularly refer to
// @version 1.0.0
// @namespace BP
// @author Benjamin Philipp <dev [at - please don't spam] benjamin-philipp.com>
// ==/UserScript==
/*
BP Funcs, as of 2022-06-26 19:18:49 (GMT +02:00)
*/
String.prototype.after = function(str, fromRight, returnAll){
if(fromRight === undefined)
fromRight = false;
if(returnAll === undefined)
returnAll = false;
var os = this.indexOf(str);
if(fromRight)
os = this.lastIndexOf(str);
if(os<0)
return returnAll?this:"";
return this.substring(os + str.length);
};
String.prototype.before = function(str, fromRight, returnAll){
if(fromRight === undefined)
fromRight = false;
if(returnAll === undefined)
returnAll = false;
var os = this.indexOf(str);
if(fromRight)
os = this.lastIndexOf(str);
if(os<0)
return returnAll?this:"";
return this.substr(0, os);
};
function bpMenu(){
var r = {};
r.obj = null;
r.items = {};
r.styles = {
default: {
colors : {
background : "#fff",
text : "#333",
item : "#555",
itemHover : "#46a",
itemBack : "transparent",
frame : "#fff"
},
paddingFrame : "10px",
radiusFrame : "10px",
fontSize : "18px"
}
};
r.style = r.styles.default;
r.setup = function(override=false){
var head, script;
head = document.getElementsByTagName("head")[0];
// if(typeof $ !== "function"){
// console.log("jQuery not available?\nTrying to insert & load...", typeof $);
// script = document.createElement("script");
// script.type = "text/javascript";
// script.onload = function(){
// r.setup();
// };
// script.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js";
// head.appendChild(script);
// return;
// }
if(typeof bpModal !== "function"){
console.log("BP Modal not available?\nTrying to insert & load...", typeof bpModal);
script = document.createElement("script");
script.type = "text/javascript";
script.onload = function(){
r.setup();
};
script.src = "https://benjamin-philipp.com/js/gm/funcs.js?funcs=bpModal";
head.appendChild(script);
return;
}
// console.log("Setup BP Menu");
if(override){
$("body>#bpMenu").remove();
}
r.injectStyles(override);
if($("body>#bpMenu").length <=0)
$("body").append("<div id='bpMenu'><div class='inner'></div></div>");
r.obj = $("body>#bpMenu");
};
r.injectStyles = function(override=false){
if(override)
$("#bpMenuStyle").remove();
if($("#bpMenuStyle").length<=0)
$("head").append(`<style id="bpMenuStyle">
.bpbutton{
padding: 5px;
display: inline-block;
background: #aaa;
color: #333;
cursor: pointer;
font-weight: 600;
line-height: 1em;
}
.bpbutton:hover, .bpbutton.on{
background: #1c82fa;
color: #fff;
}
#bpMenu{
position: fixed;
z-index: 99999;
top: -50px;
right: 0px;
height: 70px;
display: inline-block;
transition: top 0.5s;
padding: 0px 0px 10px;
}
#bpMenu .inner{
display: inline-block;
background-color: #fff;
color: #aaa;
padding: 0px 10px 5px;
border-radius: 0 0 10px 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}
#bpMenu:hover{
top: 0px;
}
#bpMenu .bp{
display: inline-block;
padding: 5px;
font-size: ' + r.style.fontSize + ';
}
#bpMenu .bp.item{
color: ' + r.style.colors.item + ';
font-weight: bold;
cursor: pointer;
}
#bpMenu .bp.item:hover{
color: ' + r.style.colors.itemHover + ';
}
#bpMenu .bp+.bp{
margin-left: 10px;
}
</style>`);
};
r.add = function(id, html, cb=null, title="", override=false, sel=""){
let l = $("body>#bpMenu>.inner #" + id);
let add = true;
if(l.length >0){
add = false;
if(override){
l.remove();
add = true;
}
}
if(add){
if(title)
title = " title='" + title + "'";
$("body>#bpMenu .inner").append("<div id='" + id + "' class='bp" + (cb?" item":"") + "'" + title + ">" + html + "</div>");
r.items[id] = $("#bpMenu #" + id);
if(cb)
$("#bpMenu #" + id).click(function(e){
cb(e);
});
}
};
r.changeStyle = function(obj){
mergeDeep(r.style, obj);
r.injectStyles(true);
};
r.setup();
return r;
}
//if("undefined" === typeof bpMenuHelper){ // jshint ignore:line
// var bpMenuHelper = bpMenu(); // jshint ignore:line
//}
function dateString(date, format){
if(date===undefined || date===null || date === "")
date = new Date();
if(format===undefined)
format="YYYY-MM-DD HH:mm:SS";
else if(format==="file")
format="YYYY-MM-DD HH-mm-SS";
date = new Date(date);
var year = date.getUTCFullYear();
var months = pad(date.getUTCMonth() + 1);
var days = pad(date.getUTCDate());
var hours = pad(date.getUTCHours());
var minutes = pad(date.getUTCMinutes());
var seconds = pad(date.getUTCSeconds());
return format.replace("YYYY", year)
.replace("MM", months)
.replace("DD", days)
.replace("HH", hours)
.replace("mm", minutes)
.replace("SS", seconds);
}
function pad(num){
var r = String(num);
if(r.length<=1)
r = "0" + r;
return r;
}
var bpTitleFormats = {
movies: [
"[title] [[year]]",
"[title] ([year])",
"[title] - [year]"
],
series: [
"[name] - Season [season] Episode [episode] - [title]",
"[name] - Season [season] Episode [episode]",
"[name] - S[lzseason]E[lzepisode] - [title]",
"[name] - S[lzseason]E[lz3episode] - [title]"
]
};
var bpMediaTitleRegex = {
movies: [
/(.+) \[(\d{4})\]$/mi,
/(.+) \((\d{4})\)$/mi,
/(.+) - (\d{4})$/mi,
],
series: [
// /(.+?) ?-? (?:(?:season |S)?0?0?(\d+))? ?(?:episode |E|x)0*(\d+(?:-\d+)?)(?: ?[:-]? (.+))?/mi
/(.+?) ?-? (?:(?:season |S)?0*(\d+))?(?: -|,)?\s*(?:episode |E|x)0*(\d+(?:-\d+)?)(?: ?[:-]? (.+))?/mi
]
};
{//// Check RegEx against:
// Some series name 1x12
// Some series name 1x12 and a title
// Some series name 1x12 - and a title
// Some series name S01E12
// Some series name S01E12 and a title
// Some series name S01E12 - and a title
// Some series name S01E12-13
// Some series name S01E12-13 and a title
// Some series name S01E12-13 - and a title
// Some series name - 1x12
// Some series name - 1x12 and a title
// Some series name - 1x12 - and a title
// Some series name - S01E12
// Some series name - S01E12 and a title
// Some series name - S01E12 - and a title
// Some series name - S01E12-13
// Some series name - S01E12-13 and a title
// Some series name - S01E12-13 - and a title
// Some series name Episode 12
// Some series name Episode 12 and a title
// Some series name Episode 12 - and a title
// Some series name Episode 12-13
// Some series name Episode 12-13 and a title
// Some series name Episode 12-13 - and a title
// Some series name Season 1 Episode 12
// Some series name Season 1 Episode 12 and a title
// Some series name Season 1 Episode 12 - and a title
// Some series name Season 1 Episode 12-13
// Some series name Season 1 Episode 12-13 and a title
// Some series name Season 1 Episode 12-13 - and a title
// Some series name - Episode 12
// Some series name - Episode 12 and a title
// Some series name - Episode 12 - and a title
// Some series name - Episode 12-13
// Some series name - Episode 12-13 and a title
// Some series name - Episode 12-13 - and a title
// Some series name - Season 1 Episode 12
// Some series name - Season 1 Episode 12 and a title
// Some series name - Season 1 Episode 12 - and a title
// Some series name - Season 1 Episode 12-13
// Some series name - Season 1 Episode 12-13 and a title
// Some series name - Season 1 Episode 12-13 - and a title
// Some series name - Season 1 Episode 12: and a title
// Some series name - Season 1 Episode 12 : and a title
// Some series name - Season 1 Episode 12-13: and a title
// Some series name - Season 1 Episode 12-13 : and a title
// Some series name - Season 1, Episode 12
// Some series name - Season 1, Episode 12 and a title
// Some series name - Season 1, Episode 12 - and a title
// Some series name - Season 1, Episode 12-13
// Some series name - Season 1, Episode 12-13 and a title
// Some series name - Season 1, Episode 12-13 - and a title
// Some series name - Season 1, Episode 12: and a title
// Some series name - Season 1, Episode 12 : and a title
// Some series name - Season 1, Episode 12-13: and a title
// Some series name - Season 1 - Episode 12
// Some series name - Season 1 - Episode 12 and a title
// Some series name - Season 1 - Episode 12 - and a title
// Some series name - Season 1 - Episode 12-13
// Some series name - Season 1 - Episode 12-13 and a title
// Some series name - Season 1 - Episode 12-13 - and a title
// Some series name - Season 1 - Episode 12: and a title
// Some series name - Season 1 - Episode 12 : and a title
// Some series name - Season 1 - Episode 12-13: and a title
// Some series name - Season 1 - Episode 12-13 : and a title
}
function guessMovieOrTV(title){
var tit = title.replace(/[—–]/g, "-"); // em-dash, en-dash
for(let rex of bpMediaTitleRegex.series){
if(rex.test(tit))
return "TV";
}
for(let rex of bpMediaTitleRegex.movies){
if(rex.test(tit))
return "Movie";
}
return false;
}
function formatMovieTV(tit, templateSeries, templateMovie){
switch(guessMovieOrTV(tit)){
case "TV":
return formatEpisodeTitle(tit, templateSeries);
case "Movie":
return formatMovieTitle(tit, templateMovie);
default:
console.log("Could not identify TV or Movie title");
return tit;
}
}
function formatMovieTitle(tit, template){
if(!template)
template = bpTitleFormats.movies[0];
// console.log("preferred format: " + template);
var match = false;
for(let rex of bpMediaTitleRegex.movies){
match = tit.match(rex);
if(match){
// match = rex.exec(tit);
console.log("title matches format " + rex.toString(), match);
break;
}
}
if(!match){
console.log("Title format not recognized", tit);
return tit;
}
var name = match[1];
var year = match[2];
tit = template.replace("[title]", name)
.replace("[year]", year);
console.log("formatted title:", tit);
return tit;
}
function formatEpisodeTitle(tit, template){
if(!template)
template = bpTitleFormats.series[0];
// console.log("preferred format: " + template);
tit = tit.replace(/[—–]/g, "-"); // em-dash, en-dash
var match = false;
for(let rex of bpMediaTitleRegex.series){
match = tit.match(rex);
if(match){
// match = rex.exec(tit);
console.log("title matches format " + rex.toString(), match);
break;
}
}
if(!match){
console.log("Title format not recognized", tit);
return tit;
}
var name = match[1];
var season = match[2];
if(!season)
season = 1;
var episode = match[3];
var title = (match.length>=5 && match[4] !== undefined)? match[4] : "";
if((/(Episode #? ?\d+|S\d+ ?E\d+)/i).test(title))
title = "";
// console.log({"name" : name, "season" : season, "episode" : episode, "title" : title});
if(title===""){
template = template.replace(/ ?-? \[title\]/, "");
console.log("no title:", template);
}
tit = template.replace("[name]", name)
.replace("[season]", season)
.replace("[episode]", episode)
.replace(/\[lz(\d*)season]/i, function(_,p){
if(p==="")
p = 2;
return lz(season, p);
})
.replace(/\[lz(\d*)episode]/i, function(_,p){
if(p==="")
p = 2;
return lz(episode, p);
})
.replace("[title]", title);
console.log("formatted title:", tit);
return tit;
}
function sanitize(str){
str = str.replace(/[\\"]/g, "-");
str = str.replace(/\?/g, "");
str = str.replace(/[\/:]/g, " - ");
str = str.replace(/[\/:]/g, " - ");
str = str.replace(/\s+-\s*(?:-+\s+)+/g, " - ");
str = str.replace(/\s\s+/g, " ");
return str;
}
function lz(num, places = 2){
return ("0000" + num).slice(-places);
}
function toTitleCase(str, preserveCaps=false, preserveAllCaps=false){
return str.replace(/\w[^\s_:-]*/g, function(txt){
var rest = txt.substr(1);
if(!preserveCaps){
if(preserveAllCaps){
if(txt.charAt(0) != txt.charAt(0).toUpperCase()|| rest != rest.toUpperCase())
rest = rest.toLowerCase();
}
else
rest = rest.toLowerCase();
}
return txt.charAt(0).toUpperCase() + rest;
});
}
const mimeTypes = {
".aac": "audio/aac",
".abw": "application/x-abiword",
".arc": "application/x-freearc",
".avif": "image/avif",
".avi": "video/x-msvideo",
".azw": "application/vnd.amazon.ebook",
".bin": "application/octet-stream",
".bmp": "image/bmp",
".bz": "application/x-bzip",
".bz2": "application/x-bzip2",
".cda": "application/x-cdf",
".csh": "application/x-csh",
".css": "text/css",
".csv": "text/csv",
".doc": "application/msword",
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".eot": "application/vnd.ms-fontobject",
".epub": "application/epub+zip",
".gz": "application/gzip",
".gif": "image/gif",
".htm": "text/html",
".html": "text/html",
".ico": "image/vnd.microsoft.icon",
".ics": "text/calendar",
".jar": "application/java-archive",
".jpeg.jpg": "image/jpeg",
".js": "text/javascript",
".json": "application/json",
".jsonld": "application/ld+json",
".mid.midi": "audio/midi",
".mjs": "text/javascript",
".mp3": "audio/mpeg",
".mp4": "video/mp4",
".mpeg": "video/mpeg",
".mpkg": "application/vnd.apple.installer+xml",
".odp": "application/vnd.oasis.opendocument.presentation",
".ods": "application/vnd.oasis.opendocument.spreadsheet",
".odt": "application/vnd.oasis.opendocument.text",
".oga": "audio/ogg",
".ogv": "video/ogg",
".ogx": "application/ogg",
".opus": "audio/opus",
".otf": "font/otf",
".png": "image/png",
".pdf": "application/pdf",
".php": "application/x-httpd-php",
".ppt": "application/vnd.ms-powerpoint",
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
".rar": "application/vnd.rar",
".rtf": "application/rtf",
".sh": "application/x-sh",
".svg": "image/svg+xml",
".swf": "application/x-shockwave-flash",
".tar": "application/x-tar",
".tif": "image/tiff",
".tiff": "image/tiff",
".ts": "video/mp2t",
".ttf": "font/ttf",
".txt": "text/plain",
".vsd": "application/vnd.visio",
".wav": "audio/wav",
".weba": "audio/webm",
".webm": "video/webm",
".webp": "image/webp",
".woff": "font/woff",
".woff2": "font/woff2",
".xhtml": "application/xhtml+xml",
".xls": "application/vnd.ms-excel",
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
".xml": "application/xml",
".xul": "application/vnd.mozilla.xul+xml",
".zip": "application/zip",
".3gp": "video/3gpp",
".3g2": "video/3gpp2",
".7z": "application/x-7z-compressed"
};
function getContentTypeByExtension(ext){
var defaultType = "application/octet-stream";
if(typeof ext != "string")
return console.warn('[getContentTypeByExtension] Invalid type supplied, please supply string', ext) || defaultType;
if(ext.indexOf(".")<0)
ext = "." + ext;
else
ext = ext.replace(/^.*(?=[.]\w+$)/, '');
var mime = mimeTypes[ext.toLowerCase()];
if(!mime)
return console.warn('[getContentTypeByExtension] Failed to resolve for content name: %s', ext) || defaultType;
return mime;
}
function getParam(s){
return getParamFromString(location.href, s);
}
function getParamFromString(u, s){
var url = new URL(u);
return url.searchParams.get(s);
}
function getSelectedElements(){
var allSelected = [];
try{
var selection = window.getSelection();
var range = selection.getRangeAt(0);
if(range.startOffset == range.endOffset)
return allSelected;
var cont = range.commonAncestorContainer;
if(!cont){
// console.log("no parent container?");
return range.startContainer;
}
if(!cont.nodeName || cont.nodeName == "#text" || !cont.getElementsByTagName){
var p = cont.parentElement;
// console.log("weird container or text node; return parent", cont, p);
if(!p){
// console.log("actually, never mind; has no parent. Return element instead");
return [cont];
}
return [p];
}
var allWithinRangeParent = cont.getElementsByTagName("*");
for (var i=0, el; el = allWithinRangeParent[i]; i++){ // jshint ignore:line
// The second parameter says to include the element
// even if it's not fully selected
if (selection.containsNode(el, true))
allSelected.push(el);
}
}catch(e){
console.log(e);
}
return allSelected;
}
function htmlEntities(str){
return str.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
return '&#' + i.charCodeAt(0) + ';';
});
}
function isNativeFunction(value) {
// Used to resolve the internal `[[Class]]` of values
var toString = Object.prototype.toString;
// Used to resolve the decompiled source of functions
var fnToString = Function.prototype.toString;
// Used to detect host constructors (Safari > 4; really typed array specific)
var reHostCtor = /^\[object .+?Constructor\]$/;
// Compile a regexp using a common native method as a template.
// We chose `Object#toString` because there's a good chance it is not being mucked with.
var reNative = RegExp('^' +
// Coerce `Object#toString` to a string
String(toString)
// Escape any special regexp characters
.replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')
// Replace mentions of `toString` with `.*?` to keep the template generic.
// Replace thing like `for ...` to support environments like Rhino which add extra info
// such as method arity.
.replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
);
var type = typeof value;
return type == 'function'
// Use `Function#toString` to bypass the value's own `toString` method
// and avoid being faked out.
? // jshint ignore:line
reNative.test(fnToString.call(value))
// Fallback to a host object check because some environments will represent
// things like typed arrays as DOM methods which may not conform to the
// normal native pattern.
:
(value && type == 'object' && reHostCtor.test(toString.call(value))) || false;
}
function jqExtend(jQ=false){
if(jQ || ("undefined" != typeof(jQuery) && "undefined" != typeof(jQuery.fn)) || ("undefined" != typeof($) && "undefined" != typeof($.fn))){
var fn;
if("undefined" != typeof(jQ) && "undefined" != typeof(jQ.fn))
fn = jQ.fn;
else if("undefined" != typeof(jQuery) && "undefined" != typeof(jQuery.fn))
fn = jQuery.fn;
else
fn = $.fn;
fn.selectText = function(){
var doc = document;
for(var i = 0; i<this.length; i++){
var element = this[i];
var range;
if (doc.body.createTextRange){
range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
} else if (window.getSelection){
var selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
}
}
};
fn.fare = function(){
$(this).fadeOut(function(){
$(this).remove();
});
};
fn.textOnly = function(trim=true){
var c = this.clone();
c.children().remove();
if(trim)
return c.text().trim();
return c.text();
};
}
else
console.log("no jQuery, no extensions :(");
}
jqExtend();
class BPLogger {
constructor(name = false, prefix = false, debugging = false, level = 1){
if(!name && typeof GM_info !== "undefined")
name = GM_info.script.name;
if(prefix === false && name)
prefix = name;
if(!name)
name = "Logger";
this.name = name;
this.prefix = prefix;
this.debugging = debugging;
this.level = level;
this.colors = {
default: [180, 100],
warn: [60, 100],
error: [0, 100],
success: [150, 100]
};
this.history = [];
this.keepHistory = false;
if (typeof name == "object"){
Object.assign(this, name);
}
return this;
}
writeLog(args, type = "default", level = 1){
if (this.keepHistory)
this.history.push([Date.now(), type, level, args]);
if(this.prefix)
args = ["%c" + this.prefix + ":", `color: hsl(${this.colors[type][0]},${this.colors[type][1]}%,80%); background-color: hsl(${this.colors[type][0]},${this.colors[type][1]}%,15%); font-weight: 900!important`, ...args];
if (this.debugging)
args = [...args, new Error().stack.replace(/^\s*(Error|Stack trace):?\n/gi, "").replace(/^([^\n]*\n)/, "\n")];
if(["warn", "error"].includes(type))
console[type](...args);
else
console.log(...args);
}
log(...args){
this.writeLog(args);
}
warn(...args){
this.writeLog(args, "warn");
}
error(...args){
this.writeLog(args, "error");
}
success(...args){
this.writeLog(args, "success");
}
}
function BPLogger_default(...args){
if(args.length<=0)
args = "";
var logger = new BPLogger(args);
log = function(...args){
logger.log(...args);
};
warn = function(...args){
logger.warn(...args);
};
error = function(...args){
logger.error(...args);
};
success = function(...args){
logger.success(...args);
};
return logger;
}
String.prototype.matches = function(rex){
if(!(rex instanceof RegExp))
return log("Not a regular Expression:", rex);
return rex.exec(this);
};
function mergeDeep(target, source, mutate=true){
let output = mutate ? target : Object.assign({}, target);
if(typeof target == "object"){
if(typeof source != "object")
source = {source};
Object.keys(source).forEach(key => {
if(typeof source[key] == "object"){
if(!(key in target))
Object.assign(output, { [key]: source[key] });
else
output[key] = mergeDeep(target[key], source[key]);
}else{
Object.assign(output, { [key]: source[key] });
}
});
}
return output;
}
function bpModal(){
var r = {};
r.messages = [];
r.count = 0;
r.setup = function(){
// if(typeof $ !== "function"){
// console.log("jQuery not available?\nTrying to insert & load...", typeof $);
// var head = document.getElementsByTagName("head")[0];
// var script = document.createElement("script");
// script.type = "text/javascript";
// script.onload = function(){
// r.setup();
// };
// script.id="bpJQ";
// script.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js";
// head.appendChild(script);
// return;
// }
// console.log("Actual setup with jQuery");
if($("head #bpModalStyle").length<=0){
$("head").append(`<style id="bpModalStyle">
#messageoverlays{
position:fixed;
top:20vh;
z-index:100;
text-align:left;
margin: 0 auto;
left:50%;
transform: translate(-50%, 0px);
}
#messageoverlays>.table{
margin: 0px auto;
}
#messageoverlays .msg{
display:inline-block;
width:auto;
margin: 5px auto;
position:relative;
padding: 10px;
box-sizing: border-box;
border-radius: 5px;
}
#messageoverlays .msg{
border: 1px solid #666;
background-color: #ddd;
color: #333;
}
#messageoverlays .msg.dark,
.dark #messageoverlays .msg,
#messageoverlays.dark .msg{
border: 1px solid #ccc;
background-color: #333;
color: #ccc;
}
#messageoverlays .msg.error{
border-color: #a10;
color: #710;
background-color: #ffcabf;
}
#messageoverlays .msg.dark.error,
.dark #messageoverlays .msg.error,
#messageoverlays.dark .msg.error{
background-color: #300;
color: #b66;
border: 1px solid #b66;
}
#messageoverlays .msg.warn{
border-color: #dd0;
color: #bb0;
background-color: #fec;
}
#messageoverlays .msg.dark.warn,
.dark #messageoverlays .msg.warn,
#messageoverlays.dark .msg.warn{
background-color: #330;
color: #bb6;
border: 1px solid #bb6;
}
#messageoverlays .msg.success{
border-color: #190;
color: #070;
background-color: #bf9;
}
#messageoverlays .msg.dark.success,
.dark #messageoverlays .msg.success,
#messageoverlays.dark .msg.success{
background-color:#030;
color:#6b6;
border:1px solid #6b6;
}
.closebutton{
font-weight: 900;
font-size: 12px;
cursor: pointer;
z-index: 20;
opacity: 0.75;
color: #fff;
background-color: #a10;
padding: 0 5px 1px;
border-radius: 100%;
position: absolute;
right: -5px;
top: -2px;
line-height: 16px;
}
.closebutton:hover,
.bpModback .modclose:hover{
opacity: 1;
}
.bpModback{
position:fixed;
width:100%;
height:100%;
display:table;
left:0;
top:0;
z-index:99000;
}
.bpModback.tint{
background-color:rgba(0,0,0,0.5);
}
.bpModback.nomodal{
display:block;
width: auto;
height: auto;
left: 50%;
top: 20px;
transform: translateX(-50%);
}
.bpModback .modcent{
display:table-cell;
vertical-align:middle;
height:100%;
max-height:100%;
min-height:100%;
}
.bpModback.nomodal .modcent{
height:auto;
max-height:auto;
}
.bpModback .modtable{
display:table;
margin:auto;
position:relative;
left:0;
}
.bpModback .modframe{
border-radius: 6px;
border:10px solid #fff;
display:block;
background-color: #fff;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
max-height: 90vh!important;
max-width: 90vw!important;
overflow-y:auto;
}
.bpModback .modclose{
display:block;
background-color: #000;
color: #fff;
opacity:0.7;
position:absolute;
right:-12px;
top:-12px;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
border-radius: 20px;
border:4px solid #fff;
font-weight:900;
font-size:12pt;
padding:0px 7px;
cursor:pointer;
z-index:400;
}
.bpModback .modbox{
position:relative;
display: table;
padding:20px 20px 10px;
color:#666;
overflow:hidden;
display:block;
/*text-align:center;*/
}
.bpModback .table{
display:table;
}
.bpModback .tr{
display:table-row;
}
.bpModback .td{
display: table-cell;
}
#watch #player{
height: 200px;
}
</style>`);
}
};
r.msg = function(instr, id="", modal=true, callback=null){
r.count++;
if(!id){
id = "bpmod" + r.count;
}
var noclose = false;
if(typeof(modal)=="string" && modal == "noclose"){
noclose = true;
modal = true;
}
var m = {
id : id,
msg: instr,
callback: callback,
modal: modal,
obj: $("<div class='bpModback " + (!!modal?"tint":"nomodal") + (noclose?" noclose":"") + "' id='" + id + "'><div class='tr'><div class='modcent'><div class='modtable'><div class='modclose'>X</div><div class='modframe'><div class='modbox'>" + instr + "</div></div></div></div></div></div>"),
close: function(){
this.obj.remove();
delete r.messages[this.id];
if(this.callback)
this.callback(this);
}
};
$("body").append(m.obj);
$("#" + id + ":not('.noclose') .modcent").click(function(e){
if(e.target == this)
m.close(this);
});
$("#" + id + " .modclose").click(function(e){
m.close(this);
});
r.messages[id] = m;
return m;
};
r.close = function(el="all"){
if(el=="all"){
}
};
r.setup();
return r;
}
//if("undefined" === typeof bpModHelper){ // jshint ignore:line
// var bpModHelper = bpModal(); // jshint ignore:line
//}
function message(content, classname, id, expirein, closable){
expirein = typeof expirein !== 'undefined' ? expirein : 0;
if(closable===undefined)
closable = true;
var expires = expirein !== 0 ? true : false;
if (id === undefined || id === ""){
for (var i = 0; i < 512; i++){
if ($(document).find("#message-" + i)[0] !== undefined){} else {
this.id = "message-" + i;
break;
}
}
} else {
this.id = id;
}
var fid = this.id;
this.expire = function(){
if (expirein > 0){
if(this.extimer)
window.clearTimeout(this.extimer);
this.extimer = window.setTimeout(function(){
$("#" + fid).fadeOut(function(){
$("#" + fid).remove();
});
}, expirein);
}
};
this.html = "<div id='" + this.id + "' class='table'><div class='msg " + classname + "'>" + content + (closable?"<div class='closebutton' id='c-" + this.id + "'>x</div>":"") + "</div></div>";
}
function overlaymessage(content, classname, id, expirein, closable){
expirein = typeof expirein !== 'undefined' ? expirein : 5000;
classname = classname || "hint";
id = id || "";
var curmes = new message(content, classname, id, expirein, closable);
//console.log(curmes);
if($("#messageoverlays").length<=0)
$("body").append("<div id='messageoverlays'></div>");
$("#messageoverlays").append(curmes.html);
$(".msg .closebutton").off("click").on("click", function(){
console.log("close", $(this).parent().parent());
$(this).parent().parent().fare();
});
curmes.expire();
}
function msg(content, classname, id, expirein){
overlaymessage(content, classname, id, expirein);
}
function msgbox(content, classname="", id=""){
if (id === undefined || id === ""){
for (var i = 0; i < 512; i++){
if ($(document).find("#message-" + i)[0] !== undefined){} else {
id = "message-" + i;
break;
}
}
} else {
id = id;
}
return "<div id='" + id + "' class='msg " + classname + "'>" + content + "</div>";
}
String.prototype.rIndexOf = function(regex, startpos) {
var indexOf = this.substring(startpos || 0).search(regex);
return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf;
};
var regEsc = regEsc?regEsc : function(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
};
String.prototype.replaceAll = function(str1, str2, insensitive)
{
return this.replace(new RegExp(regEsc(str1),(insensitive?"gi":"g")),(typeof(str2)=="string")?str2.replace(/\$/g,"$$$$"):str2);
};
function scrollIntoView(object, offsetTop = 20, offsetLeft = 20){
object = $(object);
if(object.length<=0)
return;
object = object[0];
var offset = $(object).offset();
$('html, body').animate({
scrollTop: offset.top - offsetTop,
scrollLeft: offset.left - offsetLeft
});
object.scrollIntoView();
}
/* globals isElement, isNativeFunction, uneval */
function stringify(obj, forHTML, onlyOwnProperties, completeFunctions, level, maxLevel, skipEmpty){
if(!level) level = 0;
var r = "";
if(obj===undefined) r = "[undefined]";
else if(obj === null) r = "[null]";
else if(obj === false) r = "FALSE";
else if(obj === true) r = "TRUE";
else if(obj==="") r = "[empty]";
else if(typeof obj == "object"){
var isDOMElement = isElement(obj);
if(onlyOwnProperties === undefined) onlyOwnProperties = true;
if(completeFunctions === undefined) completeFunctions = false;
if(maxLevel === undefined) maxLevel = 5;
if(skipEmpty === undefined) skipEmpty = false;
r = "[object] ";
var level_padding = "";
var padString = " ";
for(var j = 0; j < level; j++) level_padding += padString;
if(isDOMElement){
r = "[DOMElement " + obj.nodeName + "] ";
skipEmpty = true;
completeFunctions = false;
}
if(level<maxLevel){
r += "{\n";
if(isDOMElement){
r += level_padding + padString + "HTML => " + obj.outerHTML.replace(/\r?\n/g, "\\n").replace(/\s+/g, " ") + "\n";
}
for(var item in obj){
try{
var value = obj[item];
if(onlyOwnProperties && obj.hasOwnProperty && !obj.hasOwnProperty(item) || isNativeFunction(value) || skipEmpty && (value===undefined || value === null || value===""))
continue;
if(typeof(value) == 'object'){
r += level_padding + padString + "'" + item + "' => ";
r += stringify(value, forHTML, onlyOwnProperties, completeFunctions, level+1, maxLevel, skipEmpty) + "\n";
}else if(typeof(value) == 'undefined'){
r += level_padding + padString + "'" + item + "' => [undefined]\n";
}else{
if(typeof(value.toString)=="function")
value = value.toString();
if(!completeFunctions){
let m = value.match(/function\s*\(([^\)]*)\)\s*\{/i);
if(m)
value = "function(" + m[1] + ")";
}
r += level_padding + padString + "'" + item + ("' => \"" + value).replace(/\r?\n/g, "\\n").replace(/\s+/g, " ") + "\"\n";
}
}catch(e){
console.log(e);
}
}
r += level_padding + "}";
}else
r += "[Max depth of " + maxLevel + " exceeded]";
}
else if(typeof obj == "function"){
if(typeof(obj.toString)=="function")
r = obj.toString();
else
r = uneval(obj);
if(!completeFunctions){
let m = r.match(/function\s*\(([^\)]*)\)\s*\{/i);
if(m)
r = "function(" + m[1] + ")";
}
}
else
r = obj + "";
if(level===0){
if(!!forHTML){
r = r.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
r = "<pre>" + r + "</pre>";
}
}
return r;
}
function isNode(o){
return (
typeof Node === "object" ? o instanceof Node :
o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
);
}
/* globals HTMLDocument */
function isElement(o){
return (
((typeof HTMLElement === "object" && o instanceof HTMLElement) || (typeof Element === "object" && o instanceof Element) || (typeof HTMLDocument === "object" && o instanceof HTMLDocument))? true : //DOM2
o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string"
);
}
function stringifyWithFuncs(val, withTabs = true){
return JSON.stringify(val, function(key, value){
if (typeof value === 'function') {
return value.toString();
}
return value;
}, withTabs?"\t":" ");
}
function toText(str, maxBreaks=2){
// if($ === undefined){
// $ = jQuery = require( "jquery" )(new JSDOM("").window);
// }
var hack = "__break god dammit__";
str = str.replace(/(<(?:br|hr) ?\/?>|<\/(?:p|li|div|td|h\d)>)/gi, hack + "$1");
str = $("<div/>").append(str).text();
var rex = new RegExp(hack, "gi");
str = str.replace(rex, "\n");
rex = new RegExp("(\\n{" + maxBreaks + "})\\n+", "g");
str = str.replace(rex, "$1");
return str.trim();
}
function trim(s, what="\\s"){
var rex = new RegExp("^(?:[" + what + "])*((?:[\\r\\n]|.)*?)(?:[" + what + "])*$");
var m = s.match(rex);
// log(m);
if(m !== null && m.length>=2)
return m[1];
return "";
}
function varToPretty(str){
return str.replace(/(.+?)([A-Z])/g, "$1 $2").replace(/_|-/g, " ").replace(/\s\s+/g, " ").replace(/\b([a-z])/g, function(v,i){return v.toUpperCase();});
}
class eleWaiter{
constructor(sel, cb, cbFail=null, findIn="document", delay=500, maxTries=50, alwaysOn=false, autoStart=true, debug = false){
this.sel = "";
this.cb = null;
this.cbFail = null;
this.findIn = "document";
this.delay = 500;
this.maxTries = 50;
this.alwaysOn = false;
this.autoStart = true;
this.debug = false;
this.colors = {
label: [180,100],
warn: [60,100],
error: [0,100]
};
this.__running = false;
this.__tries = 0;
this.__timer = 0;
this.__jqo = {};
if(typeof sel == "object" && !(sel instanceof Array)){ // 2022-04-16 : Now allowing array of selectors
// log("got object");
Object.assign(this, sel);
}
else{
this.sel = sel;
this.cb = cb;
if(cbFail!== undefined || cbFail!== null)
this.cbFail = cbFail;
if(findIn!== undefined || findIn!== null)
this.findIn = findIn;
this.delay = delay;
this.maxTries = maxTries;
this.alwaysOn = alwaysOn;
this.autoStart = autoStart;
this.debug = debug;
}
if(typeof this.sel == "string"){ // 2022-04-16 : Now allowing array of selectors
this.sel = [this.sel];
}
if(this.debug){
if(typeof this.debug == "string"){
this.debug = {
prefix: this.debug + " ",
level: 1
};
}
else if(typeof this.debug == "number"){
this.debug = {
prefix: "",
level: this.debug
};
}
else if(typeof this.debug == "object"){
if(!this.debug.prefix)
this.debug.prefix = "";
else
this.debug.prefix += " ";
if(!this.debug.level)
this.debug.level = 1;
}
else{
this.debug = {
prefix: "",
level: 1
};
}
}
// this.log(this.cb);
this.log(this);
if(this.autoStart)
this.__wait();
}
log(...args){
if(!this.debug)
return;
if(typeof args == "object" && args.length>=2 && typeof args[args.length-1] == "string" && args[args.length-1].toLowerCase().indexOf("loglevel:")===0){
var level = args[args.length-1].substr(9)*1;
if(level>this.debug.level){
return;
}
args.pop();
}
console.log(this.debug.prefix + "EleWaiter:", ...args);
}
start(){
if(!this.__running){
this.log("Start waiting", this.findIn, this.sel);
this.__wait();
}
}
stop(){
clearTimeout(this.__timer);
this.__running = false;
}
__wait(){
if(this.findIn == "document" && !!document)
this.findIn = document;
this.__running = true;
if(this.maxTries!=-1)
this.__tries++;
var triesLeft = this.alwaysOn?1:(this.maxTries - this.__tries);
this.log("tries left:", triesLeft, "loglevel:3");
var hasAll = true;
this.__jqo = $();
for(let sel of this.sel){
var jqo = $(this.findIn).find(sel);
if(jqo.length<=0){
if(this.debug && this.debug.level>2 || !this.alwaysOn)
this.log("Not found: " + sel, "in", this.findIn);
if(triesLeft!==0){
this.__timer = setTimeout(function(){this.__wait();}.bind(this), this.delay);
if(this.alwaysOn)
this.__result(false);
}
else
this.__result(false);
return;
}
else{
this.__jqo = this.__jqo.add(jqo);
this.log("Found something, is now:", this.__jqo, "loglevel:3");
}
}
this.__result(this.__jqo);
if(this.alwaysOn){
this.log("Always on, repeat", "loglevel:3");
this.__timer = setTimeout(function(){this.__wait();}.bind(this), this.delay);
}
}
__result(success=false){
if(!this.alwaysOn){
this.__running = false;
this.log("Result:", success, "loglevel:2");
}else if(this.debug.level>2)
this.log("Result:", success);
if(success){
if(this.cb!==undefined && typeof this.cb == "function")
this.cb(this.__jqo);
else
console.log("Warning: callback cb not function", this.cb);
}
else{
if(this.cbFail!==undefined && typeof this.cbFail == "function")
this.cbFail(this.__jqo);
}
}
}
if("undefined" === typeof eleWaiters){ // jshint ignore:line
var eleWaiters ={}; // jshint ignore:line
}
function waitFor(sel, cb, cbFail=null, findIn="document", delay=500, maxTries=50, alwaysOn=false, debug = false){ // 2021-01-29
return new eleWaiter(sel, cb, cbFail, findIn, delay, maxTries, alwaysOn, true, debug);
}