How to select 2 class as a droppable? - jquery-ui

I really need help here. I can't find a solution on how to select class="cell active"
for droppable. You can see my code below.
$('.cell').droppable({
drop: function(event, ui) {
var pieceValue = ui.helper.data('value');
var toBoard = $(this).data('square');
var splitResult = toBoard.split(',')
board[splitResult[0]][splitResult[1]] = pieceValue;
$(this).append(ui.draggable);
}
});
I want to use class="cell active" for droppable, but what should my selector be?
http://jsfiddle.net/4KLHs/

If I understand what you're looking for then your selector will be: $('.cell.active')
$('.cell.active').droppable({
drop: function(event, ui) {
var pieceValue = ui.helper.data('value');
var toBoard = $(this).data('square');
var splitResult = toBoard.split(',');
board[splitResult[0]][splitResult[1]] = pieceValue;
$(this).append(ui.draggable);
}
});
Looking at your code in the jsFiddle this is what I would suggest:
// Use this function to add the active class and tie the droppable interaction to
function makeDroppable(element) {
element.addClass('active');
element.droppable({
drop: function (event, ui) {
var pieceValue = ui.helper.data('value');
var toBoard = $(this).data('square');
var splitResult = toBoard.split(',')
board[splitResult[0]][splitResult[1]] = pieceValue;
$(this).append(ui.draggable);
}
});
}
Then I would cause the div's to be passed to the above function as shown below:
$('.draggable').each(function (index, div) {
$(div).draggable({
snap: '#board',
revertDuration: 500,
cursor: 'move',
opacity: 0.50,
helper: 'clone',
containment: '#board',
revert: function (event, ui) {
$(this).data("value").originalPosition = {
top: 0,
left: 0
};
return !event;
},
start: function () {
var from = $(this).parent().attr('data-square');
var splitSquare = from.split(',');
splitSquare[0] = splitSquare[0];
splitSquare[1] = splitSquare[1] - 2 + 2;
var joinSquare = splitSquare.join();
var div1 = $("div[data-square='" + joinSquare + "']");
makeDroppable(div1); //<- pass in the element to the function
splitSquare[0] = splitSquare[0];
splitSquare[1] = splitSquare[1] - 2 + 3;
var joinSquare = splitSquare.join();
var div2 = $("div[data-square='" + joinSquare + "']");
makeDroppable(div2); //<- pass in the element to the function
splitSquare[0] = splitSquare[0];
splitSquare[1] = splitSquare[1] - 2;
var joinSquare = splitSquare.join();
var div3 = $("div[data-square='" + joinSquare + "']");
makeDroppable(div3); //<- pass in the element to the function
splitSquare[0] = splitSquare[0] - 2 + 3;
splitSquare[1] = splitSquare[1] - 2 + 3;
var joinSquare = splitSquare.join();
var div4 = $("div[data-square='" + joinSquare + "']");
makeDroppable(div4); //<- pass in the element to the function
splitSquare[0] = splitSquare[0] - 2;
splitSquare[1] = splitSquare[1];
var joinSquare = splitSquare.join();
var div5 = $("div[data-square='" + joinSquare + "']");
makeDroppable(div5); //<- pass in the element to the function
}
});
});
http://jsfiddle.net/4KLHs/1/

Related

How to add start time variable to Lite YouTube Embed code created by Amit Agarwal

I use Amit Agarwal code from https://www.labnol.org/internet/light-youtube-embeds/27941/ in my website to lite embeded youtube video.
Is there any way to add start time to the script so that I could load each video with different start time.
<div class="youtube-player" data-id="VIDEO_ID" start-id="TIME"></div>
His complete script are as follows:
<script>
function labnolIframe(div) {
var iframe = document.createElement('iframe');
iframe.setAttribute('src', 'https://www.youtube.com/embed/' + div.dataset.id + '?autoplay=1&rel=0');
iframe.setAttribute('frameborder', '0');
iframe.setAttribute('allowfullscreen', '1');
iframe.setAttribute('allow', 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture');
div.parentNode.replaceChild(iframe, div);
}
function initYouTubeVideos() {
var playerElements = document.getElementsByClassName('youtube-player');
for (var n = 0; n < playerElements.length; n++) {
var videoId = playerElements[n].dataset.id;
var div = document.createElement('div');
div.setAttribute('data-id', videoId);
var thumbNode = document.createElement('img');
thumbNode.src='//i.ytimg.com/vi/ID/hqdefault.jpg'.replace('ID', videoId);
div.appendChild(thumbNode);
var playButton = document.createElement('div');
playButton.setAttribute('class', 'play');
div.appendChild(playButton);
div.onclick = function () {
labnolIframe(this);
};
playerElements[n].appendChild(div);
}
}
document.addEventListener('DOMContentLoaded', initYouTubeVideos);
</script>
I have added timeId var into the mix hoping that I could use start-id value to let embed video to start at specific time. It still start at 0 sec of the video.
function labnolIframe(div) {
var iframe = document.createElement('iframe');
iframe.setAttribute('src', 'https://www.youtube.com/embed/' + div.dataset.id + '?start='+ div.dataset.id + '&autoplay=1&rel=0');
iframe.setAttribute('frameborder', '0');
iframe.setAttribute('allowfullscreen', '1');
iframe.setAttribute('allow', 'accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture');
div.parentNode.replaceChild(iframe, div);
}
function initYouTubeVideos() {
var playerElements = document.getElementsByClassName('youtube-player');
for (var n = 0; n < playerElements.length; n++) {
var videoId = playerElements[n].dataset.id;
var timeId = playerElements[n].dataset.id;
var div = document.createElement('div');
div.setAttribute('data-id', videoId);
div.setAttribute('start-id', timeId);
var thumbNode = document.createElement('img');
thumbNode.src = '//i.ytimg.com/vi/ID/hqdefault.jpg'.replace('ID', videoId);
div.appendChild(thumbNode);
var playButton = document.createElement('div');
playButton.setAttribute('class', 'play');
div.appendChild(playButton);
div.onclick = function () {
labnolIframe(this);
};
playerElements[n].appendChild(div);
}
}
document.addEventListener('DOMContentLoaded', initYouTubeVideos);
Just change:
iframe.setAttribute('src', 'https://www.youtube.com/embed/' + div.dataset.id + '?autoplay=1&rel=0');
to:
iframe.setAttribute('src', 'https://www.youtube.com/embed/' + div.dataset.id + '?start=YOUR_START_TIME_IN_SECONDS&autoplay=1&rel=0');
Note the added start=YOUR_START_TIME_IN_SECONDS& in the URL.

firefox can't follow the link, in other browsers all right

Ggo to https://codepen.io/anon/pen/pVGXZG hover mouse on NAV and try click on "firefox"
Other browser when you click on "firefox" following link without problem
var btn = document.getElementById("main-btn");
btn.addEventListener("mouseover", function (e) {
var nav = document.getElementById("main-nav");
var sub_btns = document.getElementsByClassName("sub-btn");
var pos = [];
e.className += "main-hover";
console.log(e)
nav.addEventListener("mouseover", function (e) {
var total =0;
for(var x = 0;x<sub_btns.length;x++) {
if(x <2) {
sub_btns[x].style.left = "-"+((x+1)*30)+"%";
pos[x] = ((x+1)*20);
} else {
sub_btns[x].style.right = "-"+((x-1)*30)+"%";
pos[x] = ((x-1)*280);
}
sub_btns[x].style.opacity = "1";
}
nav.style.width = 50+"%";
});
nav.addEventListener("mouseout", function(){
nav.style.width = "100px";
for(var x = 0;x<sub_btns.length;x++) {
sub_btns[x].style.left = "0";
sub_btns[x].style.right = "0";
sub_btns[x].style.opacity = "0";
}
})
});
Spec says, that inside of you can have only phrasing content. That is, the element inside won't be interactive (clickable).

Rails Nested complex Form

I'am looking a good ideas to build a cacsade forms.
what Iam looking for is to build a form to construct a config yml data.
for example to build key value form and the value field can be string or hash or array.
config --> Items --> has key and value --> can be String, Array or Hash.
Any Idea please?
what i did is to generate a graphe using 3djs and make editabe a node and handle add/ remove a node. I share whith you what I did for persons want do the same thing... (flare.json is the action to retrive json file )
var root;
treeJSON = d3.json("flare.json", function(error, treeData) {
// Calculate total nodes, max label length
var totalNodes = 0;
var maxLabelLength = 0;
// variables for drag/drop
var selectedNode = null;
var draggingNode = null;
// panning variables
var panSpeed = 200;
var panBoundary = 20; // Within 20px from edges will pan when dragging.
// Misc. variables
var i = 0;
var duration = 750;
// var root;
// size of the diagram
var viewerWidth = $('#d3view').width();
var viewerHeight = 800;
var tree = d3.layout.tree()
.size([viewerHeight, viewerWidth]);
// define a d3 diagonal projection for use by the node paths later on.
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});
// A recursive helper function for performing some setup by walking through all nodes
function visit(parent, visitFn, childrenFn) {
if (!parent) return;
visitFn(parent);
var children = childrenFn(parent);
if (children) {
var count = children.length;
for (var i = 0; i < count; i++) {
visit(children[i], visitFn, childrenFn);
}
}
}
// Call visit function to establish maxLabelLength
visit(treeData, function(d) {
totalNodes++;
maxLabelLength = Math.max(d.name.length, maxLabelLength);
}, function(d) {
return d.children && d.children.length > 0 ? d.children : null;
});
// sort the tree according to the node names
function sortTree() {
tree.sort(function(a, b) {
return b.name.toLowerCase() < a.name.toLowerCase() ? 1 : -1;
});
}
// Sort the tree initially incase the JSON isn't in a sorted order.
sortTree();
// Define the zoom function for the zoomable tree
function zoom() {
$('.btn-form').remove()
svgGroup.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
// define the zoomListener which calls the zoom function on the "zoom" event constrained within the scaleExtents
var zoomListener = d3.behavior.zoom().scaleExtent([0.1, 1.5]).on("zoom", zoom);
// define the baseSvg, attaching a class for styling and the zoomListener
var baseSvg = d3.select("#d3view").append("svg")
.attr("width", viewerWidth)
.attr("height", viewerHeight)
.attr("class", "overlay")
.call(zoomListener);
// Function to center node when clicked/dropped so node doesn't get lost when collapsing/moving with large amount of children.
function centerNode(source) {
scale = 0.3;//zoomListener.scale();
x = -source.y0;
y = -source.x0;
x = x * scale + viewerWidth / 20;
y = y * scale + viewerHeight / 2.5;
d3.select('g').transition()
.duration(duration)
.attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")");
zoomListener.scale(scale);
zoomListener.translate([x, y]);
}
// Toggle children function
function toggleChildren(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else if (d._children) {
d.children = d._children;
d._children = null;
}
return d;
}
// Toggle children on click.
function click(d) {
if (d3.event.defaultPrevented) return; // click suppressed
d = toggleChildren(d);
update(d);
// centerNode(d);
}
function remove_link(d){
a = d3.event
a.preventDefault()
p = d.parent
parent_array = [p]
depth = d.depth - 1
for(var i=1; i<depth; i++){
parent_1 = p
parent_2 = parent_1.parent
parent_array.push(parent_2)
p = parent_2
}
parent_array[0].children.splice($.inArray(d, parent_array[0].children), 1)
update(d);
$('#editme').tree('loadData', [root]);
}
function make_editable(d)
{
// console.log("make_editable", arguments);
this
.on("mouseover", function() {
$('.btn-form').remove();
$('.input-form').remove();
d3.selectAll('text').style('fill', null)
d3.select(this).style("fill", "red");
var p = this.parentNode;
var xy = this.getBBox();
var p_xy = p.getBBox();
xy.x -= p_xy.x;
xy.y -= p_xy.y;
xy.x += 25;
xy.y -= 50;
var el = d3.select(this);
var p_el = d3.select(p);
var frm = p_el.append("foreignObject");
var inp = frm
.attr('class', 'btn-form')
.attr("x", xy.x)
.attr("y", xy.y)
.attr("width", 145)
.attr("height", 60)
.append("xhtml:form")
.append('a').text('Add').attr('class', 'btn btn-primary').attr('style', 'width:50px;height:30px;margin-right:2%;').on('click', add_link)
frm.select('form').append('a').text('Remove').attr('class', 'btn btn-danger remove-btn').attr('style', 'width:70px;height:30px;').on('click', remove_link)
frm.on('mouseover', function(){
$('.btn-form').closest('g').find('text').attr("fill", 'red');
})
.on('mouseout', function(){
$('.btn-form').closest('g').find('text').attr("fill", null);
})
})
.on("mouseout", function() {
d3.select(this).style("fill", null);
})
.on("click", function(d, event) {
e = d3.event;
e.preventDefault();
$('.btn-form').remove();
var p = this.parentNode;
// console.log(this, arguments);
// inject a HTML form to edit the content here...
// bug in the getBBox logic here, but don't know what I've done wrong here;
// anyhow, the coordinates are completely off & wrong. :-((
var xy = this.getBBox();
var p_xy = p.getBBox();
xy.x -= p_xy.x;
xy.y -= p_xy.y;
var el = d3.select(this);
var p_el = d3.select(p);
var frm = p_el.append("foreignObject");
var inp = frm
.attr('class', 'input-form')
.attr("x", xy.x)
.attr("y", xy.y)
.style("z-index", 99999)
.attr("width", 300)
.attr("height", 25)
.append("xhtml:form")
.append("input")
.attr("value", function() {
// nasty spot to place this call, but here we are sure that the <input> tag is available
// and is handily pointed at by 'this':
this.focus();
return el.text();
})
.attr("style", "width: 110px;")
// make the form go away when you jump out (form looses focus) or hit ENTER:
.on("blur", function() {
// console.log("blur", this, arguments);
var txt = inp.node().value;
el.text(function(d) { return txt; });
d.name = el.text();
// Note to self: frm.remove() will remove the entire <g> group! Remember the D3 selection logic!
p_el.select("foreignObject").remove();
})
.on("keypress", function() {
// console.log("keypress", this, arguments);
// IE fix
if (!d3.event)
d3.event = window.event;
var e = d3.event;
if (e.keyCode == 13)
{
if (typeof(e.cancelBubble) !== 'undefined') // IE
e.cancelBubble = true;
if (e.stopPropagation)
e.stopPropagation();
e.preventDefault();
var txt = inp.node().value;
el.text(function(d) { return txt; });
p_el.attr('data-name', txt);
d.name = el.text();
$('#editme').tree('loadData', [root]);
}
});
});
}
function add_link(d){
d3.event.preventDefault();
var p = $(this).closest('form')
var xy = $(this).closest('.btn-form')[0].getBBox();
if($(".add-link").length == 0){
var frm = p.append("<div><input type='text' class='add-link' style='width:130px;'></input></div>");
var inp = frm.on('keypress', function(event){
var e = event;
if (e.keyCode == 13)
{
e.preventDefault();
var txt = $('.add-link').val();
var event = document.createEvent('Event');
event.initEvent('click', true, true);
if(d.children){
d.children.push({name: txt})
}else if(d._children){
d._children.push({name: txt})
}else{
d.children = [{name: txt}]
}
$('text[fill="red"]').attr('fill', null);
update(root);
$(".btn-form").hide();
$('#editme').tree('loadData', [root]);
}
})
.on('click', function(event){ event.preventDefault();})
$('.add-link').focus()
}
}
function update(source) {
// Compute the new height, function counts total children of root node and sets tree height accordingly.
// This prevents the layout looking squashed when new nodes are made visible or looking sparse when nodes are removed
// This makes the layout more consistent.
var levelWidth = [1];
var childCount = function(level, n) {
if (n.children && n.children.length > 0) {
if (levelWidth.length <= level + 1) levelWidth.push(0);
levelWidth[level + 1] += n.children.length;
n.children.forEach(function(d) {
childCount(level + 1, d);
});
}
};
childCount(0, root);
var newHeight = d3.max(levelWidth) * 25; // 25 pixels per line
tree = tree.size([newHeight, viewerWidth]);
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Set widths between levels based on maxLabelLength.
nodes.forEach(function(d) {
d.y = (d.depth * (maxLabelLength * 10)); //maxLabelLength * 10px
// alternatively to keep a fixed scale one can set a fixed depth per level
// Normalize for fixed-depth by commenting out below line
// d.y = (d.depth * 500); //500px per level.
});
// Update the nodes…
node = svgGroup.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
// .call(dragListener)
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on('click', click);
nodeEnter.append("circle")
.attr('class', 'nodeCircle')
.attr("r", 0)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
});
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? -10 : 10;
})
.attr("dy", ".35em")
.attr('class', 'nodeText')
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
})
.style("fill-opacity", 0)
.call(make_editable);
// phantom node to give us mouseover in a radius around it
// nodeEnter.append("circle")
// .attr('class', 'ghostCircle')
// .attr("r", 30)
// .attr("opacity", 0.2) // change this to zero to hide the target area
// .style("fill", "red")
// .attr('pointer-events', 'mouseover');
// .on("mouseover", function(node) {
// overCircle(node);
// })
// .on("mouseout", function(node) {
// outCircle(node);
// });
// Update the text to reflect whether node has children or not.
node.select('text')
.attr("x", function(d) {
return d.children || d._children ? -10 : 10;
})
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
});
// Change the circle fill depending on whether it has children and is collapsed
node.select("circle.nodeCircle")
.attr("r", 4.5)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
});
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
// Fade the text in
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.y + "," + source.x + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 0);
nodeExit.select("text")
.style("fill-opacity", 0);
// Update the links…
var link = svgGroup.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
function expand(d) {
if (d._children) {
d.children = d._children;
d.children.forEach(expand);
d._children = null;
}else if(d.children) {
d.children.forEach(expand);
}
}
// Append a group which holds all nodes and which the zoom Listener can act upon.
var svgGroup = baseSvg.append("g");
// Define the root
root = treeData;
root.x0 = viewerHeight / 2;
root.y0 = 0;
// Layout the tree initially and center on the root node.
update(root);
centerNode(root);
});

How to animate a line string between 2 points in OpenLayers 3 map?

I want to draw a line between multiple points from an array of coordinates.
My code looks like :
<button onclick="drawAnimatedLine(new ol.geom.Point(6210355.674114,2592743.9994331785), new ol.geom.Point(8176927.537835015,2255198.08252584), 50, 2000);">Draw Line</button>
And my js looks like :
function drawAnimatedLine(startPt, endPt, steps, time, fn) {
var style = {
strokeColor: "#0500bd",
strokeWidth: 15,
strokeOpacity: 0.5,
strokeColor: '#0000ff'
};
var directionX = (endPt.x - startPt.x) / steps;
var directionY = (endPt.y - startPt.y) / steps;
var i = 0;
var prevLayer;
var lineDraw = setInterval(function () {
console.log("Inside Animate Line");
if (i > steps) {
clearInterval(lineDraw);
if (fn)
fn();
return;
}
var newEndPt = new ol.geom.Point(startPt.x + i * directionX, startPt.y + i * directionY);
var line = new ol.geom.LineString([startPt, newEndPt]);
var fea = new ol.Feature({
geometry:line,
style: style
});
var vec = new ol.layer.Vector();
vec.addFeatures([fea]);
map.addLayer(vec);
if(prevLayer)
{
map.removeLayer(prevLayer);
}
prevLayer = vec;
i++;
}, time / steps);
}
Note : Coordinates will be dynamic but for testing I've passed the sample data in onclick of the button. Please do try to sort out this issue as soon as possible.

How to setup Flot for iOS retina display

I have tested this on an iPad (3 generation). The line chart appears perfectly smooth.
http://justindarc.github.com/flot.touch/example/index.html
I have tried diffing the code with my flot code and cannot see any significant difference that would cause it to run in retina mode. My flot is version 0.7, same as his code. No matter what I try my own chart runs in non-retina mode.
What is the trick in running retina mode?
My setup code is rather long.
function setup_chart0(setup_options) {
var point_data = [];
if(setup_options.use_sample_data_for_chart0) {
point_data = generate_dummy_data(
setup_options.timestamp_generate_min,
setup_options.timestamp_generate_max
);
}
var average_data = henderson23(point_data);
var datasets = make_chart0_datasets(point_data, average_data);
if(is_dualaxis_detail_mode) {
datasets = make_chart0_dual_datasets(
[],
[],
[],
[]
);
}
var options = default_plot_options();
options.xaxis.min = setup_options.timestamp_visible_min;
options.xaxis.max = setup_options.timestamp_visible_max;
options.xaxis.panRange = [setup_options.timestamp_pan_min, setup_options.timestamp_pan_max];
options.yaxis.min = -0.025;
options.yaxis.max = 1.025;
options.yaxis.panRange = [-0.025, 1.025];
options.legend = { container: '#legend0', noColumns: 2 };
options.grid.markings = compute_markings_with_alertlevels;
if(is_dualaxis_detail_mode) {
options.y2axis = {};
options.y2axis.position = "right";
options.y2axis.min = -0.025;
options.y2axis.max = 1.025;
options.y2axis.panRange = [-0.025, 1.025];
options.legend = { container: '#legend_hidden', noColumns: 2 };
}
//save_as_file({ samples: point_data, average: average_data });
var el_placeholder0 = $("#placeholder0");
if(el_placeholder0.length){
//console.log('plotting chart 0');
var fade = false;
var el = el_placeholder0;
var el_outer = $("#placeholder0_outer");
var original_offset = el_outer.offset();
if(fade) {
el_outer.offset({ top: -5000, left: 0 }); // move plot container off screen
}
chart0 = $.plot(el, datasets, options);
if(fade) {
el.hide(); // hide plot - must do *after* creation
el_outer.offset(original_offset); // put plot back where it belongs
el.fadeIn('slow'); // fade in
}
/*var s = ' width: ' + chart0.width() + ' height: ' + chart0.height();
$('#label0').append(s);*/
if(solo_pan_mode) {
el.bind('plotpan', function (event, plot) {
set_data_should_redraw_chart0 = true;
set_data_should_redraw_chart1 = false;
set_data_should_redraw_chart2 = false;
fetch_data_for_chart(chart0, setup_options.timestamp);
show_loading_empty('#loader1');
show_loading_empty('#loader2');
});
el.bind('plotpanend', function (event, plot) {
set_data_should_redraw_chart0 = true;
set_data_should_redraw_chart1 = true;
set_data_should_redraw_chart2 = true;
copy_min_max(chart0, chart1, '#placeholder1');
copy_min_max(chart0, chart2, '#placeholder2');
hack_hide_loading_wheels = true;
maybe_hide_loading_wheels();
});
} else {
el.bind('plotpan', function (event, plot) {
fetch_data_for_chart(chart0, setup_options.timestamp);
sync_with_chart0();
});
}
}
}
I have modified jquery.flot.js like this:
In the top I have added
retinaMode = (window.devicePixelRatio > 1),
I have extended these functions
function makeCanvas(skipPositioning, cls) {
var c = document.createElement('canvas');
c.className = cls;
c.width = canvasWidth;
c.height = canvasHeight;
if (!skipPositioning)
$(c).css({ position: 'absolute', left: 0, top: 0 });
$(c).appendTo(placeholder);
if(retinaMode) {
c.width = canvasWidth * 2;
c.height = canvasHeight * 2;
c.style.width = '' + canvasWidth + 'px';
c.style.height = '' + canvasHeight + 'px';
}
if (!c.getContext) // excanvas hack
c = window.G_vmlCanvasManager.initElement(c);
// used for resetting in case we get replotted
c.getContext("2d").save();
if (retinaMode) {
c.getContext("2d").scale(2,2);
}
return c;
}
function getCanvasDimensions() {
canvasWidth = placeholder.width();
canvasHeight = placeholder.height();
if (canvasWidth <= 0 || canvasHeight <= 0)
throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight;
}
function resizeCanvas(c) {
// resizing should reset the state (excanvas seems to be
// buggy though)
if (c.width != canvasWidth) {
c.width = canvasWidth;
if(retinaMode) {
c.width = canvasWidth * 2;
}
c.style.width = '' + canvasWidth + 'px';
}
if (c.height != canvasHeight) {
c.height = canvasHeight;
if(retinaMode) {
c.height = canvasHeight * 2;
}
c.style.height = '' + canvasHeight + 'px';
}
// so try to get back to the initial state (even if it's
// gone now, this should be safe according to the spec)
var cctx = c.getContext("2d");
cctx.restore();
// and save again
cctx.save();
if(retinaMode) {
cctx.scale(2, 2);
}
}

Resources