Appending hotspots on top of an exisiting image. JS and JQ - javascript

What i'm trying to do is append hotspots on top of an existing image. As of right now this code appends the new div and image but does so next to the image and not on top of it. I'm new to javascript and jquery so any help is appreciated.
//build data structure to store coordinates and content.
var product_hotspots = new Array();
product_hotspots[0] = {x: 200, y:200, content: "This is test content"}
product_hotspots[1] = {x: 500, y:500, content: "This is more test content"}
product_hotspots[2] = {x: 400, y:400, content: "This is even more test content"}
//loop through each hotspot.
$(product_hotspots).each(function(idx) {
//append a new div to #product_image for each hotspot with the following format:
var $newdiv1 = $('<div id="bullet" style="position: absolute; top: product_hotspot[idx].x; left: product_hotspot[idx].y" data-content="product_hotspot[idx].content"></div>');
var $image1 = $('<img src="images/hotspot.png"/>');
$("#product_image").append($newdiv1,$image1);
});

Your concatenation of the properties taken from object is incorrect. You are missing quotes that tell javascript they aren't strings and values of a javascript object
Try
$('<div id="bullet" style="position: absolute; top:'+product_hotspot[idx].x+'px; left:'+product_hotspot[idx].y+'px" data-content="'+product_hotspot[idx].content+'"></div>');
Notice the syntax highlighting of the product_hotpsot items reflecting they are not string
NOTE: I believe you have x and y in wrong positions within the style. Normally x is left not top

Related

Overlapping image inside a table

Question: how 2 images can live in the same td ? how can I overlap the first one?
Bug: the images doesn't overlapping, sometimes the character's image is printed next to the tiles images instead to overlap it.
I will link to you the pen of this little program, try to random generate different times to occur in this bug.
penHere
After the first sections of customization a random map will generate the position of the characters.
I investigate over this bug, and i discover that it's not a problem of coordinates ( they are random generated with this function )
function coordinate(){
let rowCoord= map.length;
let cellCoord = map[1].length;
let coord = {
row: Math.floor(Math.random() * rowCoord),
cell: Math.floor(Math.random() * cellCoord)
}
return coord;
};
// this function will place the character if the coordinates are ok. Else we have a callback to the same function.
function placeCharAndItem(char){
let coord = coordinate();
// with this if you choose a walkable table to spawn, this is random generated
if(map[coord.row][coord.cell] === 0 ){
place(coord, char);
}
else{
placeCharAndItem(char);
}
};
The map is random generated too. It's something like this.
map = [[1,1,1,1,0],
[1,0,0,0,0],
[1,0,1,1,1],
[1,0,0,0,1],
[1,1,1,0,1]]
and this is the function that let the character image spawn on the right td
function place(coord, char){
var charImage = $("<img>").attr("src", char.image).addClass('char');
var row = $($("#tableGame tr")[coord.row]);
var cell = $($("td", row)[coord.cell]);
cell.append(charImage);
};
Thanks :)
If you just put two images in a table cell, they will be displayed one after the other by default, this is just how the HTML works.
To make overlap of two images you can explicitly set position of the second image relative to it's parent table cell. You can do it with CSS:
Apply position: relative; to the parent td;
Apply:
position: absolute;
top: 0;
left: 0;
to the second image (and all next images in the same cell, if you will have more).
Keep in mind that second image now will be out of the standard HTML flow, it will no longer affect the cell size, it will overlap anything. You may need to explicitly set the cell size.
Also you can set this styles dynamically with the JQuery:
// Get your table cell and image somehow.
const $cell = $(...);
const $image = $(...);
$cell.css('position', 'relative');
$image.css({
position: 'absolute',
top: 0,
left: 0,
});
Or with a plain JS:
const cell = document.querySelector(...);
const image = document.querySelector(...);
cell.style.position = 'relative';
image.style.position = 'absolute';
image.style.top = 0;
image.style.left = 0;

converting area element to div

I am a beginner in Javascript/jQuery. Thank you for reading!
EDIT:
Here is a jsfiddle with all of the code (annotated) https://jsfiddle.net/sfs1926/n1sopf79/
It does not work, but here is a working example video of what my code does so far: https://www.youtube.com/watch?v=N67Bx9jgPFo
The context is: I am trying to model layers of electronics (represented as rectangles) on a graph. There are 10,000 overlapping rectangles (each representing the position of a piece of electronics). I write these area elements in line by line from a text file that contains the coordinates of each rectangle and its title. I associate each area element with its title using an overlay id. My goal: When I mouse over a pixel on the graph, I want to display ALL rectangles associated with that pixel and their overlay id's (to the side, off the graph). So far I am able to do all of this besides displaying the rectangles.
Right now I have a HTML map 'demo' containing many area elements (all rectangles). I want to use jQuery to push each of those area elements into the array elementPositions. This I do successfully below, but with one exception: I want to create the identifier 'element' to be that area element written as a div with css. This is because I want to show and hide rectangles belonging to elementPositions using the .show() method. That is why I am converting the area elements to be divs.
Can someone help me with the syntax for how to do this conversion? I think the reason why no rectangle will 'show' is because I have not set the display or the background attribute of the div, but I'm not sure how to do this.
if( $('#demo').length >0 ) {
var elementPositions = [];
$('#demo area').each(function() {
var offset = this.coords;
var coordarray = offset.split(",");
var left = coordarray[0];
var top = coordarray[1];
var right = coordarray[2];
var bottom = coordarray[3];
var id = this.id;
var wid = right - left;
var hei = bottom - top;
var hoveredElements = [];
elementPositions.push({
element: $('<div class="area"></div>')
.css({position: 'absolute', left: left, top: top}).
width(wid).height(hei), // attempt so far!
top: top,
bottom: bottom,
left: left,
right: right,
id: id,
});
Then I hope to do something like:
$("body").mousemove(function(e) {
elementPositions.forEach( function(item) {
item.element.show();
});
}
you need to append your div before show it, append to body for example :
var elementDiv = $('<div class="area"></div>')
.css({position: 'absolute', left: left, top: top}).
width(wid).height(hei);
$("body").append(elementDiv );
elementDiv.hide();
elementPositions.push({
element: elementDiv ,
top: top,
bottom: bottom,
left: left,
right: right,
id: id,
});

Line break in C3 generated SVG chart via JavaScript

I need a help on generating line break in html.
Javascript
var x = "jun";
var y = "2015";
var calculate= x + "<br>" + y;
Html returns like below
<div>jan <br> 2015</div>
expected result: i need a line break in html but should not render <br> tag.
Update: what i want is "jan" in first line and next line "2015"
I am using these values in c3 chart x values.
JSFIDDLE
Thanks in Advance.
Your question statement was a bit unprecise : You are using C3.js which will produce svg element.
So the markup returned was actually <tspan dx="0" dy=".71em" x="0">0<br>2014</tspan>.
C3 will use the textContent property of the tspan to append the text content returned by your function.
As already said in other questions, you can't add a line break into <tspan> elements.
So the solution is effectively to create a new tspan just under the other one, in the same <text> element.
Unfortunately, there is no way to get these precise elements except by looping through all others tspans, so this may sounds like a real hack but here is a script that will do what you want...
// get our svg doc
var svg = document.querySelector('svg');
// get our tspans element
var tspans = svg.querySelectorAll('tspan');
// transform it to an array so the clones don't add to the list
var ts = Array.prototype.slice.call(tspans);
for(var i = 0; i<ts.length; i++){
// get the content
var cont = ts[i].textContent.split('\n');
// that wasn't the good one...
if(cont.length<2) continue;
// create a clone
var clone = ts[i].cloneNode(1);
// set the text to the new line
clone.textContent = cont[1];
// space it a litlle bit more
clone.setAttribute('dy', '0.9em')
// set the good text to the upperline
ts[i].textContent = cont[0];
// append our clone
ts[i].parentNode.insertBefore(clone, ts[i].nextSibling)
};
var chart = c3.generate({
data: {
json: [{
date: '2014-01-01',
upload: 200,
download: 200,
total: 400
}, {
date: '2014-01-02',
upload: 100,
download: 300,
total: 400
}, {
date: '2014-02-01',
upload: 300,
download: 200,
total: 500
}, {
date: '2014-02-02',
upload: 400,
download: 100,
total: 500
}],
keys: {
x: 'date',
value: ['upload', 'download']
}
},
axis: {
x: {
type: 'timeseries',
tick: {
format: function (x) {
if (x.getDate() === 1) {
return x.getMonth() + '\n' + x.getFullYear();
}
}
}
}
}
});
// get our svg doc
var svg = document.querySelector('svg');
// get our tspans element
var tspans = svg.querySelectorAll('tspan');
// transform it to an array so the clones don't add to the list
var ts = Array.prototype.slice.call(tspans);
for(var i = 0; i<ts.length; i++){
// get the content
var cont = ts[i].textContent.split('\n');
// that wasn't the good one...
if(cont.length<2) continue;
// create a clone
var clone = ts[i].cloneNode(1);
// set the text to the new line
clone.textContent = cont[1];
// space it a litlle bit more
clone.setAttribute('dy', '0.9em')
// set the good text to the upperline
ts[i].textContent = cont[0];
// append our clone
ts[i].parentNode.insertBefore(clone, ts[i].nextSibling)
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://rawgit.com/masayuki0812/c3/master/c3.js"></script>
<link href="https://rawgit.com/masayuki0812/c3/master/c3.css" rel="stylesheet">
<div id="chart"></div>
You need to create new <tspan> for each new line. Reason is that <tspan> is usually found inside <text> element. Which has certain coordinates.
You cannot go "against" those coordinates.
The only thing you can do is create another <tspan> with different set of coordinates and position it as you like.
Because SVG Text Elements are rendered using the same rendering methods as the rest of the SVG Graphical Elements, the same coordinate
system, transformations, ... etc also apply.
The SVG Text Element renders the first character at the initial
current text position.
This position is defined by the 'x' and 'y' attributes of the SVG Text
Element.
Within a <text> element, text and font properties and the current text
position can be adjusted with absolute or relative coordinate values
by including a <tspan> element.
Perhaps that's what you need:
var calculate= '<pre>' + x + '\n' + y + '</pre>';
You have to put the whole thing in pre-tags that the \n is interpreted as a line break.
About: http://www.sitepoint.com/everything-need-know-html-pre-element/
Demo on CodePen: http://codepen.io/mizech/pen/gPOrEz
i have tried following code in abc.html and it's working.please try.
<!DOCTYPE html>
<html>
<body>
<div id="demo"></div>
<script>
var x = "jun";
var y = "2015";
document.getElementById("demo").innerHTML =x+"<br>"+y;
</script>
</body>
</html>

Setting div Background using Trianglify

I have some problems using the Trianglify plugin. I would like to use it to set the background of a div. How can I do this? I couldn't find a proper example.
Here's my sample code:
<script>
var pattern = Trianglify({
width: window.innerWidth,
height: window.innerHeight
});
document.body.appendChild(pattern.canvas())
</script>
Also, can I have divs with different backgrounds that come from Trianglify?
One DIV
Here is an example of setting a DIV background to a Trianglify pattern. It cheats a bit and sets the DIV child node to the pattern but it should work for you.
var something = document.getElementById('something');
var dimensions = something.getClientRects()[0];
var pattern = Trianglify({
width: dimensions.width,
height: dimensions.height
});
something.appendChild(pattern.canvas());
The DIV has an id of something and the CSS styles are set on the div for height and width.
Working example JSFiddle: http://jsfiddle.net/u55cn0fh/
Multiple DIVs
We can easily expand this for multiple DIVs like so:
function addTriangleTo(target) {
var dimensions = target.getClientRects()[0];
var pattern = Trianglify({
width: dimensions.width,
height: dimensions.height
});
target.appendChild(pattern.canvas());
}
JSFiddle: http://jsfiddle.net/u55cn0fh/1/
Multiple DIVs as a true background-image
The above are simply appending the pattern to the DIV as a child node instead of setting it as a background. The good news is that we can indeed use the background-image CSS property like so:
function addTriangleTo(target) {
var dimensions = target.getClientRects()[0];
var pattern = Trianglify({
width: dimensions.width,
height: dimensions.height
});
target.style['background-image'] = 'url(' + pattern.png() + ')';
}
JSFiddle: http://jsfiddle.net/abL2kc2q/
I'm pretty late to this answer, but I think it's still valuable:
If you aren't satisfied with using pattern.png() to generate a PNG version (like I wasn't), then you can also use pattern.svg() to set a SVG background with a little more work.
I always tend to lean towards using SVG backgrounds as typically they are crisper. In a test case I ran, using the SVG version also saved bits (although it's relative because sending a Trianglify background is a bit of a burden to begin with).
Characters in the base64 SVG encoding: 137284
Characters in the base64 PNG encoding: 195288
Converting the SVG to a base64 encoding then setting it as the background image can be achieved as follows:
// Create the Trianglify pattern
var pattern = Trianglify({
cell_size: 30,
variance: 0.75,
x_colors: 'random',
y_colors: 'match_x',
palette: Trianglify.colorbrewer,
stroke_width: 1.51,
});
// Serialize the SVG object to a String
var m = new XMLSerializer().serializeToString(pattern.svg());
// Perform the base64 encoding of the String
var k = window.btoa(m);
// Query the element to set the background image property
var element = document.getElementsByTagName('header')[0];
// Set the background image property, including the encoding type header
element.style.backgroundImage = 'url("data:image/svg+xml;base64,' + k + '")';
Hope this helps!
IN my case I had to use a class to use multiple instances of the same background image :
var obj = {
'trianglifiedlightblue': ['#a5cade', '#b7d5e5', '#d5e6f0', '#006ab4', '#e8f2f7', '#cee2ed'],
'trianglifiedbleu': ['#004e83', '#005f9f', '#004879', '#006ab4', '#004777', '#005f9f'],
'trianglifiedviolet': ['#680036', '#830447', '#e62f8e', '#c76c9b'],
'trianglifiedrouge': ['#5f0308', '#851117', '#cf363f', '#e86d74']
};
function addTriangle(classname) {
targets = document.getElementsByClassName(classname);
for (i = 0; i < targets.length; i++) {
target = targets[i];
if (target != null) {
var dimensions = target.getClientRects()[0];
var pattern = Trianglify({
width: dimensions.width,
height: dimensions.height,
x_colors: obj[classname],
cell_size: 100 + Math.random() * 200
});
target.style['background-image'] = 'url(' + pattern.png() + ')';
}
}
}
addTriangle('trianglifiedlightblue');
addTriangle('trianglifiedbleu');
addTriangle('trianglifiedviolet');
addTriangle('trianglifiedrouge');
div {
height: 100px;
width: 500px;
margin:10px;
float:left;
background:#efefef;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/trianglify/0.2.1/trianglify.min.js"></script>
<div class="trianglifiedlightblue"></div>
<div class="trianglifiedbleu"></div>
<div class="trianglifiedviolet"></div>
<div class="trianglifiedrouge"></div>
or if you prefer to keep an ID you can try this :
http://jsfiddle.net/thecpg/Lecdhce6/10/

Create any number of divs inside a main div and asssign positions at runtime using jQuery

I want to place many divs in a form of a circle. I will use relative positioning for the divs. For a start I am trying to place four divs around the circle
div 1 - top 50,
left 100
div 2 - top 100,
left 150
div3 -
top 150,
left 100
div 4 -
top 100,
left 50
I will be calculating the values in the actual case and setting them but for now it does not matter.Is it possible to create four divs (in an actual case it will be a large number)inside an outer div. But I need to assign differenet sequential ids to these divs and place them at the positions menntioned.
I will have to calculate and then assign top and left positions using script. So could you show how to assign these values using script.
This is really a nice question, as it requires also some math backgrounds.
So, first, let's say what we are going to do:
0. you must decide the center of the circle and its radius
1. we must decide at which angle, on a circle, we should put our divs
2 we should then make a function which, given the angle, gives you the position of the div
So, what do we do wth all that?
decide which should be the center of the circle (if it has to stay in the center of the page
decide the radius (could be calculated as well according to windows dimension)
some trigonometry: to understand the angle iterval, just divide 360° by the number of divs: if you have two divs, then you angle interval is 360/2=180 (ugly). If you have 10 divs your intrval is 36°
Very good, now we're ready to code.
get center: I just redirect you to t it at this stackoverflow link
use the same code to decide tha radius
the function which takes, as input, the number of divs, the radius, the center, and gives you back an array with the divs coord. the center is a 2 places array (x and y). In the function we make some adjustment to output the actual postion of the div.
.
function getCoords(divNum, radius, center){
var num= divNum;
var angleInt= (6.28/num);
var outArray=[];
for (i=0;i<divNum;i++){
outArray.push([(Math.cos(angleInt*i)*radius+center[0]),(Math.sin(angleInt*i)*radius+center[1])]);
}
return outArray;
}
Well, it's done, now you can place your divs with any jquery method, like in this example:
var localization=getCoords(10,200,[400,400]);
var i=1;
for (var element in localization){
var posTop=localization[element][0];
var posLeft=localization[element][1];
var element= $("<div class='inner'>"+i+"</div>");
$(element).css({ position: "absolute",
marginLeft: 0, marginTop: 0,
top: posTop, left: posLeft });
$("body").append(element);
i=i+1;
}
hope this helps
<script>
$(document).ready(function() {
"use strict";
var NR_OF_ITTERATIONS = 4,
RADIUS = 40,
i,
$wrapper = $("#wrapper");
for(i=0;i<NR_OF_ITTERATIONS;i+=1) {
$wrapper.append(
$("<div/>")
.css({
top: /* Top position */,
left: /* Left position */
});
);
}
};
</script>
<style>
​#wrapper > div {
position: absolute;
border: 1px solid black;
width: 40px;
height: 40px;
}​
</style>
<div id="wrapper"></div>
Here is the code to generate divs. Put your top and left style in style attr of the div. You can ignore the random number. I used it just as place holder.
<div id="outterDiv" class="outterDivision"> </div>​
var html = '';
var i;
for(i=0;i<=4;i++) {
var Random_Number = Math.ceil(Math.random()*500+i);
html +='<div id="inner'+i+'" class="anything" style="top:50px; left:100px;">'+Random_Number+'</div>';
}
$('#outterDiv').html(html);

Categories