2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 12:49:34 +00:00
fhem-mirror/fhem/www/pgm2/svg.js
rudolfkoenig bd08150bd9 FHMWEB_JS_UMBAU: fixing longpollSVG
git-svn-id: https://svn.fhem.de/fhem/trunk@7514 2b470e98-0d58-463d-a4d8-8e2adae1ed80
2015-01-11 09:43:59 +00:00

290 lines
8.2 KiB
JavaScript

"use strict";
var svgNS = "http://www.w3.org/2000/svg";
var svg_b64 ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var svg_initialized={};
// Base64 encode the xy points (12 bit x, 12 bit y).
function
svg_compressPoints(pointList)
{
var i, x, y, lx = -1, ly, ret = "";
var pl_arr = pointList.replace(/^ */,'').split(/[, ]/);
for(i = 0; i < pl_arr.length; i +=2) {
x = parseInt(pl_arr[i]);
y = parseInt(pl_arr[i+1]);
if(pl_arr.length > 500 && lx != -1 && x-lx < 2) // Filter the data.
continue;
ret = ret+
svg_b64.charAt((x&0xfc0)>>6)+
svg_b64.charAt((x&0x3f))+
svg_b64.charAt((y&0xfc0)>>6)+
svg_b64.charAt((y&0x3f));
lx = x; ly = y;
}
return ret;
}
function
svg_uncompressPoints(cmpData)
{
var i = 0, ret = "";
while(i < cmpData.length) {
var x = (svg_b64.indexOf(cmpData.charAt(i++))<<6)+
svg_b64.indexOf(cmpData.charAt(i++));
var y = (svg_b64.indexOf(cmpData.charAt(i++))<<6)+
svg_b64.indexOf(cmpData.charAt(i++));
ret += " "+x+","+y;
}
return ret;
}
function
svg_getcookie()
{
var c = document.cookie;
if(c == null)
return [];
var results = c.match('fhemweb=(.*?)(;|$)' );
return (results ? unescape(results[1]).split(":") : []);
}
function
svg_prepareHash(el)
{
var obj = { y_mul:0,y_h:0,y_min:0, decimals:0, x_mul:0,x_off:0,x_min:0 };
for(var name in obj)
obj[name] = parseFloat($(el).attr(name));
return obj;
}
function
svg_click(evt)
{
var t = evt.target;
var o = svg_prepareHash(t);
var y_org = (((o.y_h-evt.clientY)/o.y_mul)+o.y_min).toFixed(o.decimals);
var d = new Date((((evt.clientX-o.x_min)/o.x_mul)+o.x_off) * 1000);
var ts = (d.getHours() < 10 ? '0' : '') + d.getHours() + ":"+
(d.getMinutes() < 10 ? '0' : '') + d.getMinutes();
var tl = t.ownerDocument.getElementById('svg_title');
tl.firstChild.nodeValue = t.getAttribute("title")+": "+y_org+" ("+ts+")";
}
function
sv_menu(evt, embed)
{
var label = evt.target;
var svg = $(label).closest("svg");
var svgNode = $(svg).get(0);
var lid = $(label).attr("line_id");
var data = svg_getcookie();
var sel = $(svg).find("#"+lid);
var selNode = $(sel).get(0);
var tl = $(svg).find("#svg_title");
var par = svgNode.par;
FW_menu(evt, label,
["Copy", "Paste",
svgNode.isSingle ? "Show all lines":"Hide other lines",
selNode.showVal ? "Stop displaying values" : "Display plot values" ],
[undefined, data.length==0, undefined, selNode.nodeName!="polyline"],
function(arg) {
//////////////////////////////////// copy
if(arg == 0) {
document.cookie="fhemweb="+
$(sel).attr("y_min")+":"+$(sel).attr("y_mul")+":"+
svg_compressPoints($(sel).attr("points"));
}
//////////////////////////////////// paste
if(arg == 1) {
var doc = $(svg).get(0).ownerDocument;
var o=doc.createElementNS(svgNS, "polyline");
o.setAttribute("class", "pasted");
o.setAttribute("points", svg_uncompressPoints(data[2]));
var h = parseFloat($(sel).attr("y_h"));
var ny_mul = parseFloat(data[1]);
var ny_min = parseInt(data[0]);
var y_mul = parseFloat($(sel).attr("y_mul"));
var y_min = parseInt($(sel).attr("y_min"));
var tr =
"translate(0,"+ (h/y_mul+y_min-h/ny_mul-ny_min)*y_mul +") "+
"scale(1, "+ (y_mul/ny_mul) +") ";
o.setAttribute("transform", tr);
doc.documentElement.appendChild(o);
}
//////////////////////////////////// hide/show lines
if(arg == 2) {
if(svgNode.isSingle) {
delete(svgNode.isSingle);
$(sel).attr("stroke-width", 1);
$(tl).text($(tl).attr("hiddentitle"));
showOtherLines(0, 1);
} else {
svgNode.isSingle = 1;
$(sel).attr("stroke-width", 3);
$(tl).attr("hiddentitle", $(tl).text());
if($(sel).attr("points") != null)
$(tl).text($(label).attr("title"));
showOtherLines(1, 0);
}
}
//////////////////////////////////// value display
if(arg == 3) {
var hadShowVal = selNode.showVal;
$(svg).find("[id]").each(function(){delete($(this).get(0).showVal)});
$(svg).off("mousemove");
if(par && par.circle) {
$(par.circle).remove();
$(par.div).remove();
}
if(!hadShowVal) {
selNode.showVal = true;
$(svg).mousemove(mousemove);
svgNode.par = par = svg_prepareHash(selNode);
par.circle =
$(svg).get(0).ownerDocument.createElementNS(svgNS, "circle");
$(par.circle).attr("id", "svgmarker").attr("r", "8");
$(svg).append(par.circle);
par.div = $('<div id="svgmarker">');
par.divoffY = $(embed ? embed : svg).offset().top -
$("#content").offset().top-50;
$("#content").append(par.div);
var pl = selNode.points;
if(pl.length > 2)
mousemove({pageX:pl[pl.length-2].x});
}
}
}, embed);
function
mousemove(e)
{
var xRaw = e.pageX, pl = selNode.points, l = pl.length, i1;
if(!embed)
xRaw -= $(svg).offset().left;
for(i1=0; i1<l; i1++)
if(pl[i1].x > xRaw)
break;
if(i1==l || i1==0)
return;
var pp=pl[i1-1], pn=pl[i1];
var xR = (xRaw-pp.x)/(pn.x-pp.x); // Compute interim values
var yRaw = pp.y+xR*(pn.y-pp.y);
var y = (((par.y_h-yRaw)/par.y_mul)+par.y_min).toFixed(par.decimals);
var d = new Date((((xRaw-par.x_min)/par.x_mul)+par.x_off) * 1000);
var ts = (d.getHours() < 10 ? '0' : '') + d.getHours() + ":"+
(d.getMinutes() < 10 ? '0' : '') + d.getMinutes();
$(par.circle).attr("cx", xRaw).attr("cy", yRaw);
var yd = Math.floor((yRaw+par.divoffY) / 20)*20;
$(par.div).html(ts+" "+y)
.css({ left:xRaw-20, top:yd });
}
function
showOtherLines(currval, maxval)
{
$(svg).find("[id]").each(function(){
var id = $(this).attr("id");
if(id.indexOf("line_") != 0 || id == lid)
return;
var h = parseFloat($(this).attr("y_h"));
$(this).attr("transform", "translate(0,"+h*(1-currval)+") "+
"scale(1,"+currval+")");
});
if(currval != maxval) {
currval += (currval<maxval ? 0.02 : -0.02);
currval = Math.round(currval*100)/100;
setTimeout(function(){ showOtherLines(currval,maxval) }, 10);
}
}
}
function
svg_init_one(embed, svg)
{
var sid = $(svg).attr("id");
if(svg_initialized[sid])
return;
svg_initialized[sid] = true;
$("text.legend", svg).click(function(e){sv_menu(e, embed)});
}
function
svg_init(par) // also called directly from perl, in race condition
{
$("embed").each(function(){
var e = this;
var src = $(e).attr("src");
var ed = e.getSVGDocument();
if(src.indexOf("SVG_showLog") < 0 || !ed)
return;
var sTag = $("svg", ed)[0];
if((par && $(sTag).attr("id") != par))
return;
svg_init_one(e, sTag);
});
}
$(document).ready(function(){
svg_init(); // <embed><svg>
$("svg[id]").each(function(){ // <svg> (direct)
if($(this).attr("id").indexOf("SVGPLOT") == 0)
svg_init_one(undefined, this);
});
});
// longpollSVG code below
function
FW_svgUpdateDevs(devs)
{
// if matches, refresh the SVG by removing and readding the embed tag
var embArr = document.getElementsByTagName("embed");
for(var i = 0; i < embArr.length; i++) {
var svg = embArr[i].getSVGDocument();
if(!svg || !svg.firstChild || !svg.firstChild.nextSibling)
continue;
var flog = svg.firstChild.nextSibling.getAttribute("flog");
if(!flog)
continue;
log("longpollSVG filter:"+flog);
for(var j=0; j < devs.length; j++) {
var ev = devs[0]+":"+devs[1];
if(ev.match(flog)) {
var e = embArr[i];
var newE = document.createElement("embed");
for(var k=0; k<e.attributes.length; k++)
newE.setAttribute(e.attributes[k].name, e.attributes[k].value);
e.parentNode.insertBefore(newE, e);
e.parentNode.removeChild(e);
break;
}
}
}
}
FW_widgets.SVG = { updateDevs:FW_svgUpdateDevs };