cbox-videos

Open youtube links in a dialog in cbox chats

// ==UserScript==
// @author       @leoncastro
// @namespace    https://github.com/leoncastro
// @name         cbox-videos
// @version      0.01
// @description  Open youtube links in a dialog in cbox chats
// @include      https://my.cbox.ws/*
// @include      /(https?:)?//(www\d\.)cbox\.ws\/box/
// @compatible   firefox+greasemonkey
// @compatible   chrome+tampermonkey
// @grant        none
// @run-at       document-end
// ==/UserScript==
//
(function($){
 // @part-name         @desktop
 // @part-author       https://github.com/leoncastro
 // @part-license      Private use only
 // @part-description  desktop with moveable and resizable dialogs
 // @part-version      beta-0.3 (partial content)
 // <@desktop>
 var minW = 50, minH = 50, minX = 0, maxX = 9999, minY = 0, maxY = 9999,
 ks = '-', kh = '#', kp = '.', kc = ',', kn = '>',
 prefix_main = 'wdlg',
 selector_main = prefix_main + ks + 'main',
 selector_tool = prefix_main + ks + 'tool',
 selector_head = prefix_main + ks + 'head',
 selector_text = prefix_main + ks + 'text',
 selector_ctrl = prefix_main + ks + 'ctrl',
 selector_exit = prefix_main + ks + 'exit',
 selector_body = prefix_main + ks + 'body',
 selector_pane = prefix_main + ks + 'pane',
 selector_foot = prefix_main + ks + 'foot',
 selector_grip = prefix_main + ks + 'grip';
 var template_css = `
<style id="###0###" type="text/css">
.wdlg-tool{position:absolute;background-color:#F4F4F4;z-index:910;-moz-box-shadow:3px 3px 8px #818181;-webkit-box-shadow:3px 3px 8px #818181;box-shadow:3px 3px 8px #818181;cursor:default}
.wdlg-tool.selected{z-index:911}
.wdlg-tool>.wdlg-head{display:block;position:relative;height:24px;line-height:24px;padding:8px 32px 0 8px;cursor:move;color:black;background-color:darkgray;font-size:130%;font-weight:normal;overflow:hidden}
.wdlg-tool.selected>.wdlg-head{background-color:white}
.wdlg-tool>.wdlg-head>.wdlg-text{display:block;position:absolute;left:0;right:0;margin:0 32px 0 8px;overflow:hidden}
.wdlg-tool>.wdlg-head>.wdlg-ctrl{display:block;position:absolute;top:0;right:0}
.wdlg-tool>.wdlg-head>.wdlg-ctrl>div{display:block;float:right;width:32px;height:16px;padding:8px;text-align:center;cursor:pointer;color:white;filter:alpha(opacity=50);opacity:0.5;}
.wdlg-tool>.wdlg-head>.wdlg-ctrl>div:hover{filter:alpha(opacity=100);opacity:1}
.wdlg-tool>.wdlg-head>.wdlg-ctrl>.wdlg-exit:hover{background-color:red}
.wdlg-tool>.wdlg-head>.wdlg-ctrl>.wdlg-exit:hover>svg>path{stroke:white}
.wdlg-tool>.wdlg-body{display:block;position:relative;width:100%;margin:0;padding:0;overflow:hidden}
.wdlg-tool>.wdlg-body>.wdlg-pane{display:block;position:relative;width:100%;height:100%;margin:0;padding:0;overflow:hidden}
.wdlg-tool>.wdlg-foot{display:block;position:relative;padding-right:16px}
.wdlg-tool>.wdlg-foot>.wdlg-grip{display:block;position:absolute;bottom:0;right:0;width:16px;height:16px;cursor:se-resize}
</style>
`;
 var template_dlg =`
<div id="###1###" class="wdlg-tool" style="width:###2###;height:###3###;left:###4###;top:###5###;">
 <div class="wdlg-head">
  <div class="wdlg-text"></div>
  <div class="wdlg-ctrl">
   <div class="wdlg-exit">
    <svg width="16" height="16" overflow="hidden"><path d="M 2 2 L 13 13 M 13 2 L 2 13" stroke="#000" stroke-opacity="1" stroke-width="2" fill="none"></path></svg>
   </div>
  </div>
 </div>
 <div class="wdlg-body">
  <div class="wdlg-pane">
###0###
  </div>
 </div>
 <div class="wdlg-foot">
  <div class="wdlg-grip">
   <svg width="16" height="16" overflow="hidden"><path d="M 13 2 L 2 13 M 13 6 L 6 13 M 13 10 L 10 13 Z" stroke="#FFF" stroke-opacity="1" stroke-width="0.6" fill="none"></path></svg>
  </div>
 </div>
</div>
`;
 var template_frm = `<iframe frameborder="0" scrolling="no" width="100%" height="100%" src="###0###"></iframe>`;
 // Function call:
 function safeCall(o,a){if(o[a])o[a]();}
 // Node:
 function nodeCreate(o,n,c,t){t=t||'div';var e=document.createElement('div');if(n)e.id=n;if(c)e.className=c;if(o)o.appendChild(e);return e;}
 function nodeSelect(n,o){return'string'==typeof n?(o||document).querySelector(n):n;}
 function nodeInsert(n,t,o){n=nodeSelect(n,o);if(n)n.insertAdjacentHTML('beforeEnd',t);}
 function nodeRemove(n,o){n=nodeSelect(n,o);if(n){n.innerHTML='';if(n.parentNode)n.parentNode.removeChild(n);}}
 // Class:
 function classInsert(n,c){n=nodeSelect(n);if(n){n.className=(n.className?n.className+' ':'')+c;}}
 function classRemove(n,c){n=nodeSelect(n);if(n&&n.className){n.className=(' '+n.className+' ').split(' '+c+' ').join(' ').trim();}}
 // Event:
 function eventInsert(e,n,fn){n=nodeSelect(n);return n.addEventListener(e,fn,0);}
 function eventRemove(e,n,fn){n=nodeSelect(n);return n.removeEventListener(e,fn,0);}
 function eventCancel(e,c){e.returnValue=!1;safeCall(e,'preventDefault');if(c){e.keyCode=0;e.cancelBubble=!0;e.retainFocus=!0;safeCall(e,'stopPropagation');}}
 function eventFilter(e){return((e.which&&(e.which==1))||(e.button&&(e.button==1)));}
 // Helpers:
 function getFreeId(){var i=1,j;while(document.getElementById(j=(selector_main+ks+([1e4]+i).slice(-4))))i++;return j;}
 function getPixels(s){return s+'px';}
 function getToolX(n){return parseInt(n.style.left);}
 function getToolY(n){return parseInt(n.style.top);}
 function getToolW(n){return n.offsetWidth;}
 function getToolH(n){return n.offsetHeight;}
 // Template:
 function templateBuild()
 {
  var t = null;
  if(arguments.length)
  {
   t = arguments[0];
   for(var i = 1; i< arguments.length; i++)
    t = t.replace('###' + (i - 1) + '###', arguments[i]);
  }
  return t;
 }
 // Desktop:
 var desktop = function(n)
 {
  n = n || document.body;
  this.handleDesk = n;
  this.selectTool = null;
  this.selectItem = null;
  this.x = 0;
  this.y = 0;
  this.w = 0;
  this.h = 0;
  this.cx = 0;
  this.cy = 0;
  this.mx = 0;
  this.my = 0;

  var it = this;
  eventInsert('mousedown', n, function(e){it.onMouseDn(e);});
  eventInsert('mousemove', n, function(e){it.onMouseMv(e);});
  eventInsert('mouseup'  , n, function(e){it.onMouseUp(e);});

  this.insertWindowHTML = function(html, opt, cx, cy, x, y)
  {
   var t = prefix_main + ks + 'style';
   if( !nodeSelect(kh + t) )
    nodeInsert(this.handleDesk, templateBuild(template_css, t));

   var n = getFreeId();
   opt = opt || {};
   opt.title = opt.title || n;
   this.w = this.w || 320; // 320, 400, 480, 640, 800, 1024 // TODO
   this.h = this.h || 204; // 180, 224, 270, 360, 450,  576 // TODO
   cx = cx || opt.cx || opt.height || this.w;
   cy = cy || opt.cy || opt.width  || this.h - 24;
   x  = x  || opt.x  || opt.left   || Math.random() * (getToolW(this.handleDesk) - cx);
   y  = y  || opt.y  || opt.top    || Math.random() * (getToolH(this.handleDesk) - cy);

   nodeInsert(this.handleDesk, templateBuild(template_dlg, html, n,
              getPixels(cx), getPixels(24 + cy), getPixels(x), getPixels(y)));
   if(this.selectTool)
    this.selectLeave(1);
   this.selectEnter(nodeSelect(kh + n));
   var it = this,
   c = kh + n + kp + selector_tool + kn + kp + selector_head + kn +
       kp + selector_ctrl + kn + kp + selector_exit;
   if(nodeSelect(c))
    eventInsert('click', c, function(e){
     if(it.b)
      it.selectLeave(1);
     nodeRemove(kh + n);
     eventCancel(e, 1);
    });
   this.onMouseUp();
   return n;
  };
  this.insertWindowLink = function(link, opt, cx, cy, x, y)
  {
   var html = templateBuild(template_frm, link);
   opt = opt || {};
   opt.link = link;
   this.insertWindowHTML(html, opt, cx, cy, x, y);
  };
  this.deleteWindowTool = function(n)
  {
   nodeRemove(kh + n);
  };
 };
 var fn = desktop.prototype;
 // Mouse:
 fn.onMouseDn = function(e)
 {
  var o = e.target || e.srcElement, n = null, h = null;
  while(o)
  {
   if(o.className)
   {
    if( !h && (
        ~String.prototype.indexOf.call(o.className, selector_grip) ||
        ~String.prototype.indexOf.call(o.className, selector_head)) )
     h = o;
    if( ~String.prototype.indexOf.call(o.className, selector_tool) )
    {
     n = o;
     break;
    }
   }
   o = o.parentNode;
  }
  if(this.selectTool && (this.selectTool != n))
  {
   this.selectLeave(1);
  }
  if(n && (!this.selectTool || (n == this.selectTool)))
  {
   if(h)
    eventCancel(e);
   this.selectEnter(n);
   if(eventFilter(e))
    this.selectItem = h;
  }
 };
 fn.onMouseMv = function(e)
 {
  var mx = e.pageX || e.clientX + document.documentElement.scrollLeft;
  var my = e.pageY || e.clientY + document.documentElement.scrollTop;
  var x = mx - this.mx + this.cx;
  var y = my - this.my + this.cy;
  this.cx = this.cy = 0;
  this.mx = mx;
  this.my = my;
  if(!this.selectItem)
   return true;
  if(this.resizeStep(x, y))
  {
   if(this.selectTool)
   {
    var b = nodeSelect(kp + selector_body, this.selectTool);
    if(b)
    {
     b.style.width = getPixels(getToolW(this.selectTool));
     b.style.height = getPixels(getToolH(this.selectTool) -
                      getToolH(nodeSelect(kp + selector_head, this.selectTool)));
    }
   }
  }
  else
  {
   var dX = x, dY = y;
   if(this.x + dX < minX)
    this.cx = (dX - (x = minX - this.x));
   else if(this.x + this.w + dX > maxX)
    this.cx = (dX - (x = maxX - this.x - this.w));
   if(this.y + dY < minY)
    this.cy = (dY - (y = minY - this.y));
   else if(this.y + this.h + dY > maxY)
    this.cy = (dY - (y = maxY - this.y - this.h));
   this.x += x;
   this.y += y;
  }
  this.selectTool.style.left   = getPixels(this.x);
  this.selectTool.style.top    = getPixels(this.y);
  this.selectTool.style.width  = getPixels(this.w);
  this.selectTool.style.height = getPixels(this.h);

  eventCancel(e);
 };
 fn.onMouseUp = function(e)
 {
  if(this.selectTool)
  {
   var b = nodeSelect(kp + selector_body, this.selectTool);
   if(b)
   {
    b.style.width = getPixels(getToolW(this.selectTool));
    b.style.height = getPixels(getToolH(this.selectTool) -
                     getToolH(nodeSelect(kp + selector_head, this.selectTool)));
   }
  }
  this.selectLeave(0);
 };
 // Select:
 fn.selectEnter = function(n)
 {
  if(n && (n != this.selectTool))
  {
   this.resizeInit(n);
   this.x = getToolX(n);
   this.y = getToolY(n);
   this.w = getToolW(n);
   this.h = getToolH(n);
  }
 };
 fn.selectLeave = function(e)
 {
  if(e)
   this.resizeInit(null);
  this.selectItem = null;
  this.cx = 0;
  this.cy = 0;
 };
 // Resize:
 fn.resizeInit = function(n)
 {
  var s = 'selected';
  if(n)
  {
   this.selectTool = n;
   classInsert(this.selectTool, s);
  }
  else
  {
   classRemove(this.selectTool, s);
   this.selectTool = n;
  }
 };
 fn.resizeStep = function(x, y)
 {
  var h = '';
  if(this.selectItem && this.selectItem.className)
  {
   if(this.selectItem.className === selector_grip)
    h = 'br';
  }
  var dX = x, dY = y, r = 0;
  if(~h.indexOf('b'))
  {
   if(this.h + dY < minH)
    this.cy = (dY - (y = minH - this.h));
   else if(this.y + this.h + dY > maxY)
    this.cy = (dY - (y = maxY - this.y - this.h));
   this.h += y;
   r = 1;
  }
  if(~h.indexOf('r'))
  {
   if(this.w + dX < minW)
    this.cx = (dX - (x = minW - this.w));
   else if(this.x + this.w + dX > maxX)
    this.cx = (dX - (x = maxX - this.x - this.w));
   this.w += x;
   r = 1;
  }
  return r;
 };
 // </@desktop>

 // <@cbox-videos>
 var yt_video = '//www.youtube.com/embed/###?wmode=opaque&autoplay=1&modestbranding=1&rel=0&showinfo=1';
 var yt_regex = /(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((?:\w|-){11})(?:\S+)?/i;
 var deskctrl = new desktop();

 var addVideo = function(txt, x, y)
 {
  var yt_urlid = txt && txt.match(yt_regex);
  if( yt_urlid && (yt_urlid = yt_urlid[1]) )
  {
   deskctrl.insertWindowLink(yt_video.replace('###', yt_urlid), {}, null, null, x, y);
   return 1;
  }
  return 0;
 };

 document.addEventListener('click', function(e){
  e = window.event ? event : e;
  var url, obj = window.event ? event.srcElement : e.target;
  if( (obj.tagName == 'A'   && obj.className && ~obj.className.indexOf('autoLink') && (url = obj.href)) ||
      (obj.tagName == 'DIV' && obj.className && ~obj.className.indexOf('body') &&
       obj.parentNode && ~obj.parentNode.className.indexOf('msg') && obj.innerHTML &&
       (url = obj.innerHTML.match(yt_regex)) && (url = url[0])) )
  {
   if(addVideo(url, e.clientX, e.clientY))
    e.preventDefault();
  }
 });
 // </@cbox-videos>

})();