slow! / DGY Duckduckgo/Google Columns & YouTube Sort by date

// ==UserScript==
// @name DGY Duckduckgo/Google Columns & YouTube Sort by date
// @updateURL    https://openuserjs.org/meta/slow!/DGY_DuckduckgoGoogle_Columns_YouTube_Sort_by_date.meta.js
// @namespace    DGY
// @run-at       document-start
// @description  Sort by date as default at youtube & google-video.  Duckduckgo and Google results also formatted to 2 columns.  See GM menu to disable columns.  Also makes links go directly to target and not via the search website's advertising department.
// @version      2.1.1
// @include       https://duckduckgo.com/*
// @include       http://duckduckgo.com/*
// @include       http://www.youtube.*
// @include       https://www.youtube.*
// @include       http://www.google.*
// @include       https://www.google.*
// @include       https://encrypted.google.*
// @exclude       http*://*.google.*/maps/*
// @exclude       http*://*.google.*/imgres*
// @grant GM_registerMenuCommand
// @grant GM_log
// @grant GM_getResourceText
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @require https://openuserjs.org/src/libs/slow!/GM_registerMenuCommand_Submenu_JS_Module.js
// @require https://code.jquery.com/jquery-2.2.1.js
// @require https://code.jquery.com/ui/1.11.4/jquery-ui.js
// @resource jqueryuiCss https://code.jquery.com/ui/1.11.4/themes/vader/jquery-ui.css
// ==/UserScript==

// @updated       Dec 2016.  Updated for Chrome and other bugfixes.
// @updated       July 2016. Bug when sort by relevance is clicked, was being ignored.
// @updated       May 2016.  Exclude google image site, 'imgres?' address above.
// @updated       Feb 2016.  2.0.7 Fixes bug handling google video search in date order.  Adds submenu module.
// @updated       Nov 2015.  2.0 Use of mutation observer since DOMNodeInserted is being removed.
// @updated       2015.  1.6 updated for google chrome/chromium
// @updated       2014.  Youtube interface changed to use results in iframe, unable to change parent href.
// @updated       1st  of May, 2013.  Duckduckgo changed style, columns are now going left to right, so the format for Duck is now in row order (terraced);
// @updated       27th of May, 2010. Page layout changed.
// @updated       27th of April, 2010. GM menu option added to toggle columns.  When selected search results are presented from then on in a three column layout.

// @run-at        document-start //should be this but cant register menus even after load if used.


// if (!sessionStorage.cnt) sessionStorage.cnt=1; else sessionStorage.cnt++;
// var cnt=sessionStorage.cnt;

var iframe=window.parent!=window, ss=sessionStorage;
if (iframe) return; //!!

var cnt=(new Date).getTime();
function tstamp() {return (((new Date).getTime()-cnt)/1000).toFixed(3);}

if (!iframe) ss.floglineindex=1;

String.prototype.justify = justify;
String.prototype.count=function(str) { return (this.match(str,"g")||[]).length;};

function log(t) {
    console.log.apply(console,arguments);
    // console.info(tstamp()+": "+t);
    // if (flog) flog(t);
};

GM_log=log;
//log=function(){};
log2=log;
var flog=function(s) { //log to file ~/Dest./afile
    s=ss.floglineindex+" - "+s+"\n";
    ss.floglineindex=Number(ss.floglineindex)+s.count("\n");
    ss.fmsg+=s;
}

var page_key=location.host+location.pathname, host=window.document.location.host;
var href=window.document.location.href;path=window.document.location.pathname;
var uwin=unsafeWindow;
var toolbelt=uwin.toggleToolbelt || ( uwin.yt && uwin.yt.www && uwin.yt.www.search ? uwin.yt.www.search.toggleToolbelt : function(){} );
var pageLoaded, pagele, obs;

var results_page, sorted_page, reflexive, listening="";
var results_list_selector="#results"; // yt as default values
var late_classes=[], main_col, fitting, already_done;
var duck=false, ducklite=false, youtube=false, google=false, googlev=false, goo_images=false, goo_cse=false, duckresultsclass="results_links_deep"; var vgoogle=false, aol=false;


if (/\/results/.test(location.pathname)) results_page=true;
if (/search_sort/.test(location.pathname)) sorted_page=true;
if (/zimyt/.test(location.search)) reflexive=true;
if ( /^duckduckgo/.test(location.host)) { duck=true;youtube=false }
if ( /\.google/.test(location.host)) { duck=false;youtube=false; google=true; if (/^cse/.test(host)) goo_cse=true;}
if ( /\.youtube\./.test(location.host)) { youtube=true;}
if (/tbm=isch/.test(location.search)) goo_images=true;
if (/tbm=vid/.test(location.search)) googlev=true;
if (/lite/.test(location.pathname)) ducklite=true;
if ( /^video.google/.test(location.host))	vgoogle=true;
else if (/^video.aol/.test(location.host))	aol=true;

log("DGY Sort Start, iframe: "+iframe+", href: "+location.href+", readyState: "+document.readyState+", doc.body:"+document.body);
if (iframe) try { log("Parent href:" + window.parent.location.href); }catch(e){}

log("matches:"+[duck,google,youtube,goo_cse,googlev,goo_images].map(Number).join("")); //parseInt("0111", 2) ==> 7 //closest to binary literal 0b111


//GM_platform_wrapper("DGY Duckduckgo/Google Cols, Youtube Sort by Date", 6, waitTillLoaded);

//////////////////////////////////////////////
if (! (duck||google||youtube)) return; //For chrome ////////////////////////////////////////////////

chromeInit();


if (google) {
    inhibitGoogleTracker();
    mkLinksDirect();
    if (iframe) window.addEventListener("load", function(){
	inhibitGoogleTracker();
    });
}

if (youtube) main_col="div#results";
if (google) main_col="div#center_col .g";
if (goo_cse) main_col="div.gsc-results div.gsc-result";
if (duck) main_col="div#links";
if (ducklite) main_col="body>table";
//log("main_col:"+main_col);

var columns=GM_getValue("columns", true);
var no_of_cols=GM_getValue("no_of_cols", 2);
// name: extensions.greasemonkey.scriptvals.userscripts.org/YouTube Sort by date.no_of_cols
var blocked_domains=GM_getValue("blocked_domains", []);
console.log("set blocked_domains to:",blocked_domains);
// var colcss=(FireFox?"-moz-column-count":"-webkit-column-count")+":"+no_of_cols;
// GM_addStyle2(main_col+" { "+colcss+"}", "colcss");

if (!iframe) {
    log("setup doc.body:"+document.body)
    if (! document.body)
	obs=nodeInsertedListener(document,"body",observeBody);
    else observeBody([document.body]);
    if (!chrome) 
	loader(); //in chrome, this is called instead after jquery is loaded via platform_wrapper loadScript().
}

function observeBody(nodes){
    //if ( ! (youtube && !results_page))
    noFlicker(true);
    console.log("Body present, create no flicker div."+nodes);

    if (obs) obs.disconnect(); // or for pause/play use takeRecord()/observe().
    if (main_col) obs=nodeMutationListener(document,main_col,function(nodes, ancestor) {
	if (!nodes[0].parentNode) { // node removed
	    console.log("Mutation--Removed "+nodes[0].id+".  Ancestor "+nodeInfo(ancestor));
	    //$("head style.GM_Style").remove();
	    if (youtube) putAtEnd("feed-pyv-container");
	}
	else { //results node added
	    //alert(1);
	    noFlicker(true);
	    obs.takeRecords();
	    if (already_done) already_done=false; 
	    console.log("Mutation--Added main node0: "+nodeInfo(nodes[0])+"\n. New node's Ancestor "+nodeInfo(ancestor)+", GM_style? "+$("#putToEnd").length);
	    if (youtube) {
		//results_page=sorted_page=reflexive=false;
		results_page=reflexive=false; //rm'ed sorted_page
		if (/\/results/.test(location.pathname)) results_page=true;
		if (/search_sort/.test(location.search)) sorted_page=true;
		if (/zimyt/.test(location.search)) reflexive=true;
		if(results_page && !sorted_page) {
		    location=location.href+"&search_sort=video_date_uploaded"+"&zimyt=2";
		} else loader(); //putAtEndAndCollimate("nodeInsertedListener");
	    }
	    else if (googlev) { 
		if (/tbs=sbd/.test(location.search)) sorted_page=true; //location.search is ? and bit after ?
		if (/zimyt/.test(location.search)) reflexive=true;
		if(!sorted_page) {
		    location=location.href+"&tbs=sbd:1"+"&zimyt=2";
		} else loader();
	    }
	    else loader(); //handleGoogle("nodeInsertedListener");
	    
	    //already_done=true;
	    //noFlicker();
	}//end else node added
	return true;
    },true); //nodeMutationListener(...main_col
};//observeBody()


function loader() {
    if (document.readyState=="complete") main();
    else addEventListener("load", main);
};

function main(){
    console.log("main");
    if (already_done) { log("Already_done");return;}
    already_done=true;
    regMenu();
    GM_addStyle2(".putToEnd {position:relative}", "putToEnd");
    pagelen=$(document).height();
    setTimeout(function() {
	console.log("Call site function, "+google);
	if (google) handleGoogle();
	else  putAtEndAndCollimate("main"); // DDG and youtube 
	noFlicker(); //clears blank no flicker div.
	if (youtube) $(document).click(function(e){
	    var text=$(e.target).parents(".filter-col").find("h4").text();
	    if (/sort/i.test(text)) sorted_page=true;
	});
    },0);
    blockDomains();
}

function blockDomains() {       	// to specified: <span class="result__url__domain">experts-exchange.com</span>
                                        // ancestor:     <div data-nir="1" class="result results_links_deep highlight_d" id="r1-1"><div class="result__body links_main links_deep"><h2 style="margin: 0px;" class="result__title"><a href="http://www.experts-exchange.com/questions/21946163/Cisco-command-for-changing-subnet-mask.html" class="result__a"><b>Cisco</b> command for changing <b>subnet mask</b> - Experts-Exchange</a><a style="position: relative;" href="http://www.experts-exchange.com/questions/21946163/Cisco-command-for-changing-subnet-mask.html" class="result__check"><span class="result__check__tt">Your browser indicates if you've visited this link</span></a></h2><div class="result__snippet">Hi, I have a <b>Cisco</b> 1600 series <b>router</b> and I need to <b>change</b> the <b>subnet mask</b> from 25 to 24 bits. ie 172.24.224.1/25 to 172.24.224.1/24. Can someone show me the command ...</div><div class="result__extras"><div class="result__extras__url"><span class="result__icon"><a title="Search domain www.experts-exchange.com" href="/?q=cisco%20router%20change%20%22subnet%20mask%22+site:www.experts-exchange.com"><img src="//icons.duckduckgo.com/ip2/www.experts-exchange.com.ico" class="result__icon__img" title="Search domain www.experts-exchange.com" height="16" width="16"></a></span><a href="http://www.experts-exchange.com/questions/21946163/Cisco-command-for-changing-subnet-mask.html" class="result__url"><span class="result__url__domain">experts-exchange.com</span><span class="result__url__full">/questions/21946163/Cisco-command-for-chan...</span></a></div><a class="result__menu" title="Search domain www.experts-exchange.com" href="/?q=cisco%20router%20change%20%22subnet%20mask%22+site:www.experts-exchange.com">More results</a></div></div></div>
    blocked_domains.forEach(function(v, i, ar){
	var span=$("span.result__url__domain:contains("+v+")");
	span.closest(".result").remove();
    });
}

function putAtEndAndCollimate(from) { 
    console.log("putAtEndAndCollimate from:"+from+", iframe: "+iframe);
    pageLoaded=true;
    if (duck) {       //////duckduckgo putatend ids
	results_list_selector="#links";
	snippetFontSize();
	if (ducklite) {
	    //$("table").wrapAll("<div id="+results_list_selector.substring(1)+"></div>");
	    var c=$(".result-snippet:first").closest("table");
	    //c.attr("id",results_list_selector.substring(1)); //set tbody to #links id.
	    results_list_selector="table";
	    var tb=c.find("tbody:first");
	    var fourths=tb.find("> tr:nth-child(4n+1)"); //1st of each set of 4.
	    //f.find("+ tr + tr + tr").addClass("sib3")	
	    fourths.addClass("fourthform");
	    fourths.each(function(){
		var group4=$(this).add($(this).find("+ tr,+ + tr, + tr + tr + tr")); // add three next neighbours
		group4.wrapAll("<div class='"+duckresultsclass+" dgy'></div>");
	    });
	}
	if ($(results_list_selector).length==0) {
	    console.info("No #links for duckduckgo @"+location.href);
	    return;
	}
	fixCss(results_list_selector, "z-index","17");
	fixCss(".result--more, .result--more__btn", "position", "absolute", true);//loads more
	$(".result--more").addClass("DGYabs");
	fixCss("#links_wrapper","padding-left","20px");
	fixCss(".result__check","position","relative");
	fixCss(".results--sidebar",{top:50,right:50,zIndex:999});
	fixCss($(".results--sidebar").parent(),{poistion:"static"});
	fixCss(".link-text", "font-size","100%");
	
	fixCss(".results__title","margin","0");
	putAtEnd("ads");
	putAtEnd("side");
	rm("#side");
	rm("#feedback");
	$(".result-sponsored").closest("."+duckresultsclass).addClass("duckad");
	fixCss(".result--sep","display","none", true);
	putAtEnd("web-result-sponsored",0,0,true);
	putToEnd(".duckad");
	putToEnd(".sponsored");
    } //end if(duck)
    if (youtube) {
	putToEnd(".yt-consent");
	if ($(results_list_selector)[0]) {
	    putAtEnd("feed-pyv-container");
	    putAtEnd("feed-item-dismissable");
	    putAtEnd("branded-page-v2-secondary-col"); //removes main promoted/popular vid.
	    putAtEnd("ticker");
	    putToEnd("#ticker-content");
	    putToEnd(".pyv-afc-ads-container");
	    putToEnd(".signin-container");
	    putToEnd("#yt-masthead-signin");
	    putToEnd(".alerts-wrapper");
	    putToEnd("#yt-consent-dialog");
	    fixCss("#content","width" ,"100%"); //rejigs shape
	    rm("#appbar-guide-menu"); // box on left col.
	    fixCss(".yt-lockup-badges","margin",-4);
	    fixCss(".search-pager",{width:"100%",float:"left"});
	}
	$("body").addClass("DGYbody");
	fixPageLinks();
    }//end if youtube
    collimate(from);      ///////// >>>>>>>>>>>>>>>>>>>>
}//end putAtEndAndCollimate

function collimate(from) {
    log("collimate cols, from:"+from+", cols:"+columns+", no of cols: "+no_of_cols+ ", list id: "+results_list_selector);
    if (! columns || no_of_cols<2) {
	return;
    }
    var indiv_res_selector, indiv_res_not_padded_out;
    if (duck) 
	indiv_res_selector="."+duckresultsclass;
    else if (youtube) indiv_res_selector=".item-section>li";
    else { //google
	if (goo_cse) {
	    indiv_res_selector="div.gsc-result";//google
	} else {
	    indiv_res_selector=".g";//google
	    indiv_res_not_padded_out=".g:not(.card-section,g-blk)";
	}
    }
    var list=$(results_list_selector); // #search-results, #center_col, or #links
    if (!list.length || !$(indiv_res_selector).length) {
	console.info("DGY.js.  No list/results for "+results_list_selector);
	//if (from != "frtout") setTimeout(collimate,200, "frtout");
	//noFlicker();
	return;
    }
    var winWidth=window.innerWidth-(chrome?0:100);
    var msmargin=(duck ? "5px" : "1px");
    list.addClass("DGYcolsort");
    if (duck) { //////////////////////////////  duckduckgo cols  \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
	indiv_res_selector="."+duckresultsclass;
	//fixCss(indiv_res_selector, "padding","10px 0px 10px 5px"); //needs 'px'es
	fixCss("#logo", "margin", "5px 10px -5px 10px"); 
	fixCss("#search_form_homepage", "margin","10px 0px 14px 0px");
	fixCss("#content",{padding:0});
	fixCss("#content_wrapper",{margin: 0,padding:0});   	//addEventListener("resize", function(){
	fixCss(".large",{fontSize:"100%"});
	fixCss(".snippet, .url",{fontSize:"80%"});
	fixCss(".result__title","margin","0");
	GM_addStyle2(".result__check { display:none;}");
	if (from && from[0]=="t"){
	    var numbered=document.getElementsByClassName("icon_fav2");
	    numbered=$(".icon_fav, .icon_fav2");
	    for(var i=0;i<numbered.length;i++) {
		var el=numbered[i].firstElementChild;
		if(el) el.innerHTML = "<font size=1 style='opacity:0.4'>"+(i+1)+")</font>" + el.innerHTML;
	    }
	}
    }//end if (duck) /////////////////////\\\\\\\\\\\\\\\\\\\\
    var margin=20,padding=0, no_to_packin=0;
    list.css({"left": 20, "box-sizing":"border-box"}); //, "padding":0, "border":0});//box-sizing is not inheritable.
    fitting=calcFitting(list, no_of_cols, no_to_packin, margin, (youtube?120:30));
    if (duck) { fitting.width-=2; fitting.height-=2; }
    GM_addStyle2(indiv_res_selector + "{ box-sizing:border-box;"
		 +"margin: 0px "+fitting.margin+"px "+fitting.margin+"px 0px !important;"
		 +"padding: 0px "+padding+"px "+padding+"px 0px;"
		 //+"border: 0 !important;"
		 //+"border: 1px solid red;" //transparent
		 +" }");
    list.css({"max-width":fitting.winwidth, "min-width": fitting.winwidth, "padding":0});
    list.css({margin: (fitting.margin||padding)+"px 0px 0px "+(fitting.margin||padding)+"px"}); // margin of a container pushes contents from its edge.
    //list.css({fontSize:fitting.height/4|0});
    GM_addStyle2(indiv_res_selector      
		 +"{ display: list-item;" //inline-block;    //inline-table; " //table;inline  "
      		 +"float: left; max-width: "+(fitting.width)+"px;"
		 +"min-width: "+(fitting.width-5)+"px; "
		 +"text-overflow:ellipsis;overflow:hidden; "
		 +"clear:none !important;"
      		 +"} ","iressel");
    GM_addStyle2(indiv_res_selector+" *:not(img) { "                     //+":nth-child(2n+1) * { "
		 +"max-width: "+(fitting.width)+"px;"
		 +"text-overflow:ellipsis; " //  overflow:hidden; "
		 +"vertical-align: top;"
		 //+(google?"display:inline-block;":"")
		 //+(google?"display:-moz-groupbox;":"")
		 // +"font-size: "+(fitting.height/4|0)+"px;" //is heritable
		 // +"line-height: "+(fitting.height/4|0)+"px;" //is heritable
		 +"} ","iresselnot");
    var full_reses=""+(indiv_res_not_padded_out||indiv_res_selector);
    GM_addStyle2(full_reses+"{"
		 +"max-height: "+fitting.height+"px;"
		 +(!false?"min-height: "+fitting.height+"px;":"")
		 +"}", "fullres");
    
    //log("Added col style for "+$(indiv_res_selector).length+" elements, width:"+fitting.width+", h: "+fitting.height+" indiv_res_selector:"+indiv_res_selector+", list ww:"+fitting.winwidth+", list: "+list+", results lists:"+list.length);
    document.body.style.wordWrap="normal";
    var page=document.getElementById("page"); 
    if (page) page.setAttribute("style", "margin-left: 5px ! important");
    $("#page").css("padding-left", "10px");
    rm("#slim_appbar > *:not(:first-child)",true,true); //.slice(1)
} //collimate()

function handleGoogle() {
    log("handleGoogle start");
    inhibitGoogleTracker();
    var matched;
    var change, dest1, dest=""+document.location;
    dest1=dest;
    $(".g a").removeAttr("onmousedown"); //Remove redirect to yt prior to going to href.
    if (vgoogle) {
	if (/so=[^1]/.test(dest))                    change=true;
	if ( ! /so=/.test(dest) )                         change=true;
	dest=dest.replace(/&so=\d/g, "");
	if ( dest && ! /&so=/.test(dest))          dest=dest.replace(/\?/,"?so=1&");
	if (columns) {
	if ( /view=[^1]/.test(dest))                 change=true;
	  if (  ! /view=/.test(dest) )                    change=true;
	  dest=dest.replace(/&view=\d/g, "");
	  if ( dest && ! /&view=/.test(dest))      dest=dest.replace(/\?/,"?view=1&");
	}
    } else
	if (google) {
	    if (goo_images) {
		var links=$("a.rg_l, a.rg_fbl");
		links.each(convertHref);
	    } //else mkLinksDirect($(".g").find("a:first"));
	    if ( ! /resnum=0/.test(dest) ) {
		dest=dest.replace(/&resnum=\d/g, "&resnum=1");
		dest=dest.replace(/&tbs=(?!sbd)/g, "&tbs=sbd:1,");
		if ( dest != dest1)     change=true;
	    }
	} //elseif(google)
    else { //else if vgoogle
	var sel=uwin.document.sFilter.maintab;//aol
	if (sel.selectedIndex!=3) {
	    sel.selectedIndex=3;
	    sel.onchange();
	}
    } ///end if/elses block
    if (change && ! /start=/.test(dest) )
	document.location=dest;
    $("#tads").remove();
    $("#mbEnd").remove();
    results_list_selector="#center_col";
    if (goo_cse) {
	results_list_selector="div.gsc-results";
	$("a[data-cturl]").each(function(){
	    var href=$(this).data("cturl");
	    //log("got href:"+href);
	    href=href.split(/url\?q=|&/)[1];
	    this.dataset.cturl=href; //cant use jquery on data.
	    //log("set to:"+this.dataset.cturl);
	});
	fixCss("div.gsc-result *:not(img)","padding-bottom",7);
    }
    if (google) { //not vgoogle
	log("no vgoogle");
	var tbpi=document.getElementById("tbpi");
	if (tbpi && /^\W*Hide/.test(tbpi.textContent) && typeof unsafeWindow.google.Toolbelt == "function") 
	    unsafeWindow.google.Toolbelt.toggle();
	pagelen=$(document).height()/2;
	putAtEnd("rhs");
	putAtEnd("wmxmsg");
	putToEnd("#bottomads");
	putToEnd(".gb_Rb"); //gb_2c, gb_ac, gb_g
	putToEnd("#gbw");
	putToEnd("#taw");
	putToEnd("DIV#lb");
	rm("#footer");
	putToEnd(".kno-ftr");
	putToEnd("iframe");
	rm("div._OKe");
	rm("div._tN _fXg");
	rm("#botstuff");
	putToEnd(".gsc-adBlock");
	putToEnd(".gsc-adBlockNoHeight");
	
	rm("._cwc");
	rm("#cnso, #cnsi, #taw",true, true);	//rm("#cnsi",true,true);
	$(".ads-ad").remove();
	fixCss("#res",{margin: 0,padding:0});
	fixCss("#rhs","margin-left",0);
	putToEnd("#rhscol");
	fixCss("g-flippy-carousel",{left:5, width:"95%"});
	$(".g g-flippy-carousel").closest(".g").addClass("card-section");
	$(".bl").remove();
	fixCss("g-left-button", "left",-18);
	fixCss("g-right-button", "margin-top",-40);
	fixCss("#foot","float","left");
	fixCss("#iur","display","inline-block");
	fixCss("div.action-menu-panel", "top", "-20px", true); //action-menu-panel
	fixCss("div.action-menu-panel", "max-height", "55px", true); //action-menu-panel
	if (goo_images) return true;
	collimate("handleGoogle");         /////////////// >>>>>>>>>>>>>>>>>>>>>>
	if (fitting) fixCss("#imagebox_bigimages", {maxHeight:"100%"}) //fitting.height*1.5});
    } //end if (google)
    else if (vgoogle) {
	var tbh=document.getElementById("tbt-hide");
	if (tbh && ! invisible(tbh)) {
	    clickElem(tbh);
	}
	var putatend=document.getElementById("suggestion-bottom");
	if (putatend) document.body.appendChild(putatend);
	var putatend=document.getElementById("youtube-text-container");
	if (putatend) document.body.appendChild(putatend);
	putatend=document.getElementsByClassName("message"); 
	for(var i=0; i < putatend.length; i++) document.body.appendChild(putatend[i]);
    }
    window.scrollBy(0,1);	window.scrollBy(0,-1);
    return true;
} //end handleGoogle;

function putAtEnd(idOrClassOrObj, class_name, obj, place) { //id parameter can also be a class name.
    if (!idOrClassOrObj.charAt) { return putAtEnd("","",idOrClassOrObj, null, place);}
    var putatend=$(idOrClassOrObj?"#"+idOrClassOrObj:"")[0];  // try as id
    if (putatend) 
	append(putatend, place);
    else {
	if (idOrClassOrObj) putAtEnd("", idOrClassOrObj, null, place);// try it as a class name
	var i=0;
	if (class_name) {
	    putatend=$("."+class_name); 
	    for(; i < putatend.length; i++) append(putatend[i],place);
	    if (i) return true;
	}
	if (obj) { append(obj, place); return true;}
    }
    function append(el) {
	//log("putAtEnd #"+el.id+", class:"+el.className+", "+el+(place?" placed":""));
	if ( ! place) {
	    document.body.appendChild(el);
	    el.style.setProperty("position","relative","important");

	}
	else {
	    var p=document.querySelectorAll(results_list_selector)[0];
	    if(p) p.appendChild(el);
	}
	$(el).addClass("putAtEnd");
    } //append()
} //putAtEnd()

function putToEnd(selector) {
    var jels=$(selector);
    jels.appendTo(document.body);
    jels.addClass("putToEnd");
    jels.css({position: "relative",opacity:0.3});
    //log("putToEnd "+selector);
}

function fixPageLinks() { //Fix links to page 1,2 3...<next>, at bottom of page.
    if (!sorted_page) return;
    var pagers=$(".yt-uix-pager-button"), href=location.href;
    pagers.each(function(){
	var h=this.href, search_value;
	if (/search_sort/.test(h)) return false;
	search_value=href.split("search_sort=")[1].split("&")[0];
	this.href=h.replace("&","&search_sort="+search_value+"&");
    });
    if (/search_sort/.test(href)) {
	var search_value=href.split("search_sort=")[1].split("&")[0];
	$("#masthead-search-term").after("<input id=dgymst type=hidden name=search_sort value="+search_value+">");
	window.addEventListener("click",function(e){
	    if ($(e.target).is("span.yt-uix-button-content"))
		noFlicker(true);
	});
    }
}//fixPageLinks()

function noFlicker(start) {
    //log("noflick "+!!start+" parent len:"+$("#noFlicker").parent().length);
    if (noFlicker.disabled) return;
    if (start) {
	if (!noFlicker.el) {
	    noFlicker.el=document.createElement("div");
	    document.body.insertBefore(noFlicker.el,document.body.firstChild);
	    noFlicker.el.id="noFlicker";
	    noFlicker.el.style.cssText= "z-index:2999999999; padding-right:2000px;padding-bottom:2000px; position:absolute; background-color: white;";
	} else 	noFlicker.el.style.setProperty("display","block"); //$(noFlicker.el).prependTo("body");
    }
    else 
	setTimeout(function(){$(noFlicker.el).css("display","none");},100); //put to end of exec queue.
}

function GM_addStyle2(style, id) {
    //console.log("Add style:",style);
    GM_addStyle(style);
    var s=$("head style:last");
    s.addClass("GM_Style");
    if (id) s[0].id=id;
}

function fixCss(sel, name_Or_obj, value, perm) { //allows logging.
    //log("fixCss:"+sel+", "+name_Or_obj+", "+value+" #els:"+$(sel).length);
    if (value !== null) {
	if (perm)
	    GM_addStyle(sel + "{ "+name_Or_obj+":"+value +"}");
	else 
	    $(sel).css(name_Or_obj,value); // a name
    }
    else
	$(sel).css(name_Or_obj); //an object;
}


function rm(sel, hide, perm){
    //log("rm "+$(sel).length+" "+sel+" hide:"+hide);
    if (perm) GM_addStyle2(sel+" {display:none !important;}");
    if (hide) $(sel).css("display","none");
    else $(sel).remove();
}

function removeIdClass(id, class_name) {
  var putatend;
  if (id) {
    putatend=document.getElementById(id);
    if (putatend) putatend.parentNode.removeChild(putatend);
  }
  if (class_name) {
    var el,i=0,els=document.body.getElementsByClassName(class_name);
    while (els.length){
      el=els[i];
      el.parentNode.removeChild(el);
    }
  }
}

function regMenu() {
    //    if (!chrome)
    submenuModule.register("DGY columns & Sort by Date");
    //try { submenuModule.register("DGY columns & Sort by Date"); } catch(e) {}; // if site down and update needed?
    GM_registerMenuCommand( "========Sort By Date======", function(){});
    GM_registerMenuCommand("Youtube sort by date -- Toggle collimation ["+!!GM_getValue("columns", false)+"].", function() {
	columns^=true;
	GM_setValue("columns", columns);
	alert("Collimation "+(columns?"on":"off")+", at "+location+", reload to see effect.");
    });
    GM_registerMenuCommand("Set number of columns ["+GM_getValue("no_of_cols", 2)+"]...", function() {
	columns^=true;
	var reply=prompt("Set number of columns to display ( >0 )",no_of_cols);
	reply=parseInt(reply);
	if (reply > 0) GM_setValue("no_of_cols", reply);
    });
    if (duck) GM_registerMenuCommand( "Change result snippets' font size", function() {
	var cv=snippetFontSize(null,true);
	var res=prompt("Give below the new font size in percent, use zero to reset.",cv).replace(/\D*/g,"");
	snippetFontSize(res);
	
    });
    GM_registerMenuCommand( "Don't show results from...", function() {
	sprompt("Enter name of server domain whose result you no longer "
		+"wish to see.\n Current set of domains set to not show up in results:\n"+blocked_domains.join("\n")
		+"\nIf name entered is already on list it'll be removed.",
		"", function(reply) {
		    if (!reply) return;
		    var already_domain=blocked_domains.indexOf(reply);
		    if (already_domain!=-1)
			blocked_domains.push(reply);
		    else
			blocked_domains=blocked_domains.splice(already_domain,1);
		    GM_setValue("blocked_domains",blocked_domains);
		    blockDomains();
		});
    });
    GM_registerMenuCommand( "_____________________________________", function(){});
}

function convertHref(){ //from an $("a").each(), a has .rg_l , takes direct to image not via yt.
    // .find("img").removeAttr("jsaction");
    fixhref(this);
    if (!convertHref.listener) {
	convertHref.listener=true;
	nodeMutationListener(document, "a.rg_l", function(nodes) { //document is target since lower ones get renewed.
	    //log("New link(s) <a> at gooimg, mutated:"+nodes.length+" "+nodes[0].parentNode.dataset["ri"] +" th: "+nodeInfo(nodes[0]));
	    for(var i=0; i<nodes.length;i++) 
		fixhref(nodes[i]);
	});
    }
    function fixhref(el) {
	$(el).removeAttr("jsaction"); //prevents http calls to google when hovering over image.
	var ref=decodeURIComponent(el.href);
	var pindex=ref.indexOf("&imgrefurl=",1);
	if (pindex==-1) pindex=ref.indexOf("&imgurl=",1);
	if (pindex==-1) return;
	var ref2=ref.substring(pindex+11);
	ref2=ref2.replace(/&.*/,"");
	el.href=ref2;
    }
    
    //that.attr("oldhref",ref);
    //log(convertHref.count+" set to "+ref2+"\t.Was:"+ref);
    //window.status="href fix:convertHref:"+convertHref.count;
};


function mkLinksDirect(links) { //capture events so google doesn't send them to google.com.
    if (!mkLinksDirect.ev) { // && false) {
	mkLinksDirect.ev=true;
	function catchEvent(type,obj){
	    if (!obj) obj=window;
	    //log("Catch "+type+", on:"+obj);
	    obj.addEventListener(type, function(e){
		var parent=""+e.target.parentNode, src=e.target.src||"", text=e.target.textContent||"";
		if (src) src=src.substring(0,40);
		if (text) text=text.substring(0,40);
		// log(" Event: "+e.type+", currentTarget:"+e.currentTarget+", target:"+e.target+", parent:"+parent.substring(0,40)
		//     +", cancelable:"+e.cancelable+", eventPhase:"+e.eventPhase
		//     +", bubbles:"+e.bubbles+", listener:"+(obj||window)
		//     +", src:"+src+", text40:"+text+", href:"+e.target.href
		//    );
		if (/click/.test(e.type))
		    if (e.target.href) {
			var href=decodeURIComponent(e.target.href), dhref;
			dhref=href.split("&url=")[1]||"";
			dhref=dhref.split("&")[0];
			if (dhref) href=dhref;
			if (href && e.button==0) document.location=href;
			else if (href && e.button==1) window.open(href, '_blank');
		    }// end if(href)
		else return; //allow click through if not going to a href.
		if (e.target.value===undefined) {
		    //log("Blocking "+e.type+" "+e.target+" "+typeof e.target.value);
		    e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation();
		}
	    },true);
	    obj["on"+type]=function(e){
		//log("--"+e.type);
	    };
	}//catchEvent()
	// ar=["click", "blur", "focus" , "unload","pagehide", "popstate",
	//     "pageshow","focus","mousedown","message","open","mouseup","toggle",
	//     "resize", "visibilitychange", "orientationchange", "touchstart", "mouseup",
	//     //"webkitvisibilitychange",
	//     "DOMFocusIn", "DOMFocusOut" ];
	//
	//clicks, focus, blur, visibilitychange and resize events: google sends marketing data etc. back to google.com.  It also send a message every 30 secs to google.
	var ar=["click","blur","focus", "visibilitychange", "resize"];
	// for (i in ar) catchEvent(ar[i]);
	// for (i in ar) catchEvent(ar[i], document);
	//var html=document.documentElement; //also used by google.
    }
}

function inhibitGoogleTracker() {
    var i, end_id=setInterval(null), begin_id=inhibitGoogleTracker.si_begin;
    if (!inhibitGoogleTracker.si_begin) {
	inhibitGoogleTracker.si_begin=setInterval(null);
	navigator.__proto__.sendBeacon=function(){ log("Attempt to sendbeacon");return true;};
    }
    else {
	for (i=begin_id; i<=end_id;i++) setTimeout(function(){
	    clearInterval(i); //google sends back marketing messages with setInterval.
	    //console.log("Cleared intervals:"+begin_id+"-"+end_id);
	},10000);
	// $("form").each(function(){
	//     this.addEventListener("submit", function(){log("Submit or not?")});
	//     this.addEventListener("blur", function(){log("blur form or not?")});
	//     this.addEventListener("focus", function(){log("focus form or not?")});
	// });
	// var setint=window.setInterval;
	// window.setInterval=function(f,t){
	//     //log("setInterval "+f+" "+t);
	//     setint(f,t);
	// };
    }
}

function invisible(elem){ return getComputedStyle(elem, null).display=="none";  }
function clickElem(elem) {
    var pseudo_event = window.document.createEvent("MouseEvents");
                                                    // type,    canBubble, cancelable,  view,      detail,           screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget)
    pseudo_event.initMouseEvent("click", true,            true,            window, 0,                   0,   0,                       0,      0,                false,   false, false,    false,                0,           null);
    elem.dispatchEvent(pseudo_event);
}

function getById(id) {
    var el=window.document.getElementById(id);
    return el;
}

function justify (max_line, char) {
    if (this.length<=max_line) return this;
    var res="", last_newline_pos=0;char=char||" ";
    this.split(char).forEach(function(v, i, ar){
	res+=v;
	if (i==ar.length-1) return;
	if (res.length-last_newline_pos >= max_line) {
	    res+=(/\s/.test(char)?"":char)+"\n"; last_newline_pos=res.length; }
	else res+=char;
    });
    return res;
};
function vscroll(y) {
  var factor=1;
  if (y>0) for (; y >= 0; y--)
	     window.scrollByLines( 1);
  else for (; y <= 0; y++)
	 window.scrollByLines( -1);
}
function childids(el) {
    roll="";
    if (el.children) {
	for (var i=0;i<el.children.length;i++)
	    if (el.children[i].id)
		roll+=el.children[i].id+" ";
    }
    if (roll) roll="childids:"+roll;
    return roll;
}

//
// MutationObserver functions.           Eg, var obs=nodeInsertedListener(document,"div.results", myCBfunc);  function myCBfunc(foundArrayOfNodes, ancestorOfMutation);  Standard querySelector() syntax is used to find elements.
//
// Creates a new MutationObserver (a DOM object), then calls observe() on it which will invoke given callback after x mutations.
//
// nodeMutation here is the general function for nodes, 'type' passed to it will change that for which it listens.
// See https://www.w3.org/TR/dom/#mutationrecord for details of the object sent to the callback for each change. 
function nodeMutation(target, selector, callback, type, include_subnodes) {
    var new_node_obs=new MutationObserver(mutantNodesObserver);
    //log("Setup nodeMutation, selector="+selector+", type="+type+", on target "+nodeInfo(target)+ " nsels:" + document.querySelectorAll(selector).length);
    new_node_obs.observe(target, { subtree: true, childList: true } );
    return new_node_obs;

    function mutantNodesObserver(mutations, mu_obs) {
	var sel_find, muts, node, ditch;
	//log("mutations on "+selector+" "+mutations.length)
	//console.time("a");
	for(var i=0; i<mutations.length && !ditch; i++) {
	    if (type!=2) testNodes(mutations[i].addedNodes, mutations[i].target);
	    if (type!=1) testNodes(mutations[i].removedNodes);
	}
	//console.timeEnd("a"); // 32msec for 3900 mutations.
	//log(mutations.length+" mutations END. ");
	
	function testNodes(nodes, ancestor) {
	    if (ancestor && ! ancestor.querySelector(selector)) return; //assuming most do not match.   //if (!f.data("nmutfired")) {  //jq data, unlike DOM dataset, is removed with node removal (unless detach is used), it is stored on all elements that match at the time and not on new ones.
	    var results=[], exact=false;
	    for (var j=0,node; node=nodes[j], j<nodes.length && !ditch;j++) {
		//log("NewNode, test match to sel:"+selector+", node info:"+nodeInfo(node,true));
		if (node.nodeType!=1) continue;
		if (include_subnodes) //.innerHTML can add subnodes that do not get included in mutations, these lower nodes are checked here.
		    results=results.concat(Array.prototype.slice.call(node.querySelectorAll(selector)));
		if (node.matches(selector))
		    results.push(node);
	    }
	    if (results.length) {
		ditch=callback(results, ancestor);
	    }
	} //testNodes()
    };//mutantNodesObserver()
} //nodeMutation()

function nodeInsertedListener(target, selector, callback, include_subnodes) {
    return nodeMutation(target,selector,callback,1, include_subnodes);
}
function nodeRemovedListener(target, selector, callback, include_subnodes) {
    return nodeMutation(target,selector,callback,2, include_subnodes);
}
function nodeMutationListener(target, selector, callback, include_subnodes) {
    return nodeMutation(target,selector,callback,3,include_subnodes);
}

function attrModifiedListener(target, attr, callback) { //attr is array or not set.
    var attr_obs=new MutationObserver(attrObserver);
    var config={ subtree:true, attributes:true, attributeOldValue:true};
    if (attr) config.attributeFilter=attr;
    attr_obs.observe(target, config);
    function attrObserver(mutations) {
	for(var i=0, mut;mut=mutations[i], i<mutations.length; i++) {
	    if ( ! ( mut.attributeName=="id" && !mut.id ) ) //infinite loop w/o check for null, sizzle or such changes attrib to null as side effect.
		callback(mutations[i]);
	}
    }
    return attr_obs;
}
//
// End MutationObserver functions.
//

function nodeInfo(node, q){
    if (!node) return "";
    if (node instanceof Array) node.forEach(function(n){nodeInfo(n);});
    var p=node.parentNode;
    if (node.addClass)
	return node.map(function(){ return nodeInfo(this,q);}).get().join("\n");
    else return (node.tagName?node.tagName:node)
	+(node.id?"#"+node.id:"" )
	+(node.className?"."+node.className.replace(/\s+/g,"."):"" )+" nodeType:"+node.nodeType+"."
        +(q? "\nDescendents:"+kinship("down",node):"  No. of descendants:"+$(node).find("*").length)+"."
	+"\nAncestors: "+kinship("up",node)+"."
	+(node.href? "\n href="+node.href : "")
    	+(node.src? "\n src="+node.src : "");
}

function kinship(direction, el) {
    if(!window.$) return "";
    if (direction=="down")
	direction=$(el).find("*");
    else direction=$(el).parents();
    return direction.map(function(){
	return this.tagName
	    +(this.id?"#"+this.id:"")
	    +(this.className?"."+this.className.replace(/\s+/g,"."):"");
    }).get().join();
}

//
// End MutationObserver functions.
//

function calcFitting(container, ncols, quantity, margin, minHeight) {
    //log("calcFitting"+stringify(arguments));
    var w, ww=$(window).width()-container.position().left, h, wh=$(window).height(), device_size,
	total_margins, area, colmratio, nrows, rowmratio, new_margin=margin;
    ww*=0.95; //prevent scrollbar
    if (!quantity) {
	quantity=device_fit()*0.8;                                          // box sizing by default is content-box, padding, border and margin are excluded from width/height values (& their max'es), "box-sizing: border-box" includes all except margin.
	new_margin=margin*(quantity/margin); //eg, m=20 & q=20 gives factor = 1, margin reduced smaller for q.
    }
    if (!minHeight) minHeight=10;
    while (quantity>=2) {
	setDims();
	//log("Fitting "+(quantity|0)+" within container of WxH:"+(ww|0)+"x"+(wh|0)+", try width:"+(w|0)+", height:"+(h|0)+", margin:"+(new_margin|0)+", device:"+device_size);    //a container, eg, table, despite 'box-sizing:' its size is affected in reverse by margin size and not by padding size (box-sizing: excludes only margin fro size)
	if (h>=minHeight) break;
	quantity=quantity*.8|0;
	new_margin=margin*(quantity/margin);
    }
    function setDims() {
	area=ww*wh; colmratio=(ncols+1)/ncols;  nrows=quantity/ncols; rowmratio=(nrows+1)/nrows;
	total_margins=(ncols+1)*new_margin;
	w=(ww-total_margins)/ncols;
	h=((area/quantity)/(w+colmratio*new_margin))-rowmratio*new_margin;
    }//setDims()
    
    function device_fit() {
	var dw=innerWidth, dh=innerHeight;
	device_size=dw*dh/100000;
	return Math.exp(device_size*.0930525)*6.17212;
    }
    return {"width":w|0, "height":h|0, "winwidth":ww|0, "quantity":quantity|0, "margin":new_margin|0 };
}
function snippetFontSize(res,currentvalue) {
    if (currentvalue) return GM_getValue("ddgcrsfs",74);
    if (res==undefined ) {
    	var ddgcrsfs=GM_getValue("ddgcrsfs",false);
	if(ddgcrsfs) GM_addStyle2( ".result-snippet { font-size:"+ddgcrsfs+"%;}","ddgcrsfs");
    } else if (res!=0) {
	GM_addStyle2( ".result-snippet { font-size:"+res+"%;}","ddgcrsfs");
	GM_setValue("ddgcrsfs",res);
    } else if (res==0) { $("#ddgcrsfs").remove(); GM_deleteValue("ddgcrsfs"); }
}

function sprompt(pretext,initval,cb,cancelbtnText="Cancel",okbtnText="OK") { // "Cancel" has reply of false or null (if a prompt), "OK" gives reply of true or "", Escape key returns undefined reply.  undefined==null is true. but not for ""
    var input_tag, input_style="width:80%;font-size:small;";
    var confirm_prompt=initval===undefined;
    if (!confirm_prompt) input_tag=initval.length<50 ? "input" : (input_style="width:95%;height:100px;","textarea");
    if (!cb) cb=x=>x;
    var content=$("<div class=sfs-content tabindex=2 style='outline:none;white-space:pre-wrap;'>"
		  +"<div style='max-height:"+(window.innerHeight*0.72)+"px;'>"+pretext+"</div>"
		  +(initval!==undefined ? "<"+input_tag+" spellcheck='false' style='"+input_style+"'  tabindex='1'></"+input_tag+">":"")+"</div>");
    content.find("input:not(:checkbox),textarea").val(initval);
    content.resizable();
    var sp1=$(document).scrollTop();
    var dfunc=content.dialog.bind(content);
    var dialog=content.dialog({
	modal: true, width:"60%", // position: { my: "center", at: "center center-25%", of: window }, // Greater percent further to top.
	buttons: {
	    [cancelbtnText]: function(e) { if (confirm_prompt) cb(false); else cb(null, $(this).find("input,textarea").val()); dfunc("close"); return false;},
	    [okbtnText]: function(e) {  if (confirm_prompt) cb(true); else cb( $(this).find("input,textarea").val() || ""); dfunc("close"); return false;}
	},
	close: function(e) { dialog.off("keydown"); $(document).scrollTop(sp1); if (e.key=="Escape") cb(undefined); dfunc("destroy");}  // Called from jQ by Escape, trigger with Event("keydown")
    }).parent();
    if (cancelbtnText==-1) { dialog.find("button").each(function(){   if (this.textContent=="-1") $(this).remove(); }); }
    dialog.wrap("<div class=sfs-sprompt></div>"); // allows css rules to exclude other jqueryUi css on webpage from own settings, a
    dialog.keydown(function(e){	if (e.key == "Enter" && !/textarea/i.test(e.target.tagName)) $("button:contains("+okbtnText+")",this).click();  }); 
    dialog.css({"z-index":2147483647, position:"fixed", top: "50px" });
    dialog.find(".ui-dialog-titlebar").remove(); // No img in css for close 'x' at top right so remove.  Title bar not in normal confirm anyhow.
    dialog.draggable("option","handle", ".ui-dialog-buttonpane"); //
    dialog.resizable();
    setTimeout(function(){var ips=dialog.find("input,textarea");if (ips.length) ips.focus(); else content.focus();},100);
    return dialog; //.ui-dialog
}
function sconfirm(msg,cb,cancelbtnText,okbtnText) { return sprompt(msg,undefined,cb,cancelbtnText,okbtnText); }
function salert(msg,cb) { return sprompt(msg,undefined,cb,-1,"OK"); }

function chromeInit() {
    window.chrome=false;
    if (!this.GM_getValue || "Barychelidae"!=GM_getValue("arachnoidal","Barychelidae")){ //chromium
	console.info("DGY userscript in non GM_ mode for chrome/safari etc.",this);
	window.chrome=true; window.unsafeWindow=window;
	this.GM_getValue=function(a,b) { return localStorage[a]||b; };
	this.GM_setValue=function(a,b) { localStorage[a]=b; };
	this.GM_registerMenuCommand=x=>null;
	this.uneval=function(x) { return "("+JSON.stringify(x)+")";  }; //Diff is that uneval brackets string and json excludes code only data allowed in json.
	var xhr_queue=[], xhr=new XMLHttpRequest(), next_inqueue;
	xhr.onload=x=> { //arrow function means this remains window not xhr (as a function would).
	    eval.call(window,xhr.response);
	    if (next_inqueue=xhr_queue.shift()) {  xhr.open('GET', next_inqueue); xhr.send(); }
	    else loader.call(window);
	};
	xhr.onerror=e=>console.log("Error",e);
	xhr_queue.push("https://code.jquery.com/jquery-3.1.1.js");
	xhr_queue.push("https://github.com/SloaneFox/code/raw/master/GM_registerMenuCommand_Submenu_JS_Module.js");
	xhr_queue.push("https://code.jquery.com/ui/1.12.0/jquery-ui.js");
	
	xhr.open('GET', xhr_queue.shift()); xhr.send();
	
	return true;
    } else 
	return false;
} // chromeInit()

var jqueryui_dialog_css=(
    ""
	+".ui-dialog-content,.ui-dialog,.ui-dialog textarea { font-size: 12px; font-family: Arial,Helvetica,sans-serif; border: 1px solid #757575; "
    	+"    background:#002000; color:#ccc; padding:12px;margin:5px; } "
	+".ui-dialog-buttonpane { font-size: 10px; cursor:move; border: 1px solid #ddd; overflow:hidden; } "
	+".ui-dialog-buttonset { float:right; } "
	+".ui-widget-overlay { background: #aaaaaa none repeat scroll 0 0; opacity: 0.3;height: 100%; left: 0;position: fixed;  top: 0; width: 100%;}"
	+".ui-button,.ui-widget-content { text-align:left; border: solid 1px #757575; padding: 6px 13px;margin: 4px 3px 4px 0;} "
	+".ui-corner-all, .ui-dialog-buttonpane { border-radius: 5px; border-bottom-left-radius:30px; }"
	+".ui-button:hover { background-color: #ededed; } "
	+".ui-button { background-color: #f6f6f6;color:#333;}"
	+".ui-dialog {position:absolute;padding:3px;outline:none;}"
	+".ui-resizable-handle { position:absolute; cursor: url(data:image/svg+xml;base64,"
	+"iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAAAAACo4kLRAAAACXBIWXMAAAsTAAALEwEAmpwYAAABAUlEQVQY022RsWrCYACEvz9EK1HQCilYu+jWdNKlj9BNN1/Cp/IBFHTMExihdTCIm0sR26W6KNHkvw6lunjLjffdnXn7fG0/PzzeG0A/m+/Ve/REB3CL/laStn7RBTpOG0iTXgWg0ktSoO20DJDv5gBy3TxgWkQFAG+QSdnAAyhErMtuFSiN0nRUAqpuec2x2V/4YOr7fd2AH/ebR+zhbMOaCWJrF4GphfZ8sEhSNm3EVrJxY5pJkhGAkjtzNRxuyAGws2Ap0DKYWYDbQRek3e6K9A8/TNPhBf5mzbEBvDCTpCz0ADN25gJOkzPAeXICNL85spu8/N0B8LDafK0+ouQXfemVYVtdIewAAAAASUVORK5CYII="
	+") 10 10, row-resize; } .ui-resizable-sw {bottom:5px;left:5px;}"
	+".ui-resizable-w, .ui-resizable-e { width:10px;height:100%;top:-5px;} .ui-resizable-n, .ui-resizable-s { width:100%;height:10px;} .ui-resizable-n {top:-5px; } .ui-resizable-w {left:-1px; } .ui-resizable-e {right:-15px; }"
	+".ui-tooltip { font-size: 7px; }"
	+".sfswe-ticks * {font-size:11px;padding:0px;margin:2px;}"
	+".ui-dialog .sfs-content { position:static; overflow:auto;}"
    	+ (str=>str+str.replace(/-moz-/g,"-webkit-"))(
	    ".sfs-content :-moz-any(div) { font-size:13px;padding:6px;margin:4px 3px 4px 0;color:#ccc;}"
		+".sfs-content :-moz-any(textarea,input) { font-size:13px;padding:6px;margin:4px 3px 4px 0;color:#eee;background-color:#002a00;}"
		+".sfs-content :-moz-any(span) { font-size:13px;padding:0;margin:0;color:#ccc;}"
		+".sfs-content :-moz-any(a,a:visited) { color:#ccc;text-decoration:underline; padding:0;margin:0;}")
	+".sfs-content a:hover {opacity:0.5;}")
	.replace(/\.ui/g,".sfs-sprompt .ui"); //prefix classes with namespace prevent interference.