I want to be able to rightclick a Div, and then find it's margin's value. The Div's are created like this.
//create spaces//
var addLeft=75;
var addTop=105;
var vert = 1;
var horz = 1;
var selectedunit = "";
for (var i = 1; i<26; i++) {
$("#background").append("<div class='areas' id = 'space" + vert + horz + "' style ='position: absolute; LEFT: " + addLeft + "px; Top:" + addTop + "px'></div>");
if (addLeft < 600) {
addLeft += 150;
vert+=1;
} else {
horz+=1;
addTop += 150;
addLeft = 75;
vert=1;
}
}
And I try to find the div's margin with this.
$('.areas').mousedown(function(e) {
if(e.button === 2 ){
var style = window.getComputedStyle(this);
var futureleft = style.marginLeft;
$('#Status').append(futureleft);
}
})
Status is just a box that should give me the Div's left value, but it always gives 0PX. Any suggestions?
Since you're using jQuery, why not do
var futureleft = $(this).css("marginLeft");
You are not setting any margin. You are assigning a left value:
"LEFT: " + addLeft + "px;
But asking for the marginLeft value, which was not defined in the generated divs:
var style = window.getComputedStyle(this);
var futureleft = style.marginLeft;
Either you set the margin-left on the generated divs, or you request the correct property:
var style = window.getComputedStyle(this);
var futureleft = style.left;
Related
I'm using vanilla JavaScript to create a photo carousel; reading in values from an external JSON file, then looping through the JSON data to dynamically add thumbnails, a title, and an onclick to the carousel div. All the images and titles work fine, but the onclick passes only the last value used regardless of which thumbnail is clicked.
Here's the JSON file
var Scenes = {
"Title":["St. Mary Magdalene","Black Mountains","Pen Twyn Glas","Carreg Yr Ogof Cave","Beinn Narnain"],
"Thumbnail":["TNStMary.jpg","TNMountains.jpg","TNPenTwynGlas.jpg","TNCarregYrOgof.jpg","TNBeinnNarnain.jpg"],
"PanoSet":["001x","145+","183+","400x","500x"]
};
Here's the code that is dynamically adding the thumbnails, titles, and onclick.
var Scenes = {
"Title":["St. Mary Magdalene","Black Mountains","Pen Twyn Glas","Carreg Yr Ogof Cave","Beinn Narnain"],
"Thumbnail":["TNStMary.jpg","TNMountains.jpg","TNPenTwynGlas.jpg","TNCarregYrOgof.jpg","TNBeinnNarnain.jpg"],
"PanoSet":["001x","145+","183+","400x","500x"]
};
var Repeat = (Scenes.Title.length);
for (i = 0; i < Repeat; i++) {
NewDiv = document.createElement('div');
NewDiv.id = 'Scene' + i;
document.getElementById('Carousel').appendChild(NewDiv);
document.getElementById('Scene' + i).className = "Scene";
document.getElementById('Scene' + i).style.position = "absolute";
document.getElementById('Scene' + i).style.top = "5px";
document.getElementById('Scene' + i).style.left = 5 + (170 * i) + "px";
document.getElementById('Scene' + i).onclick = function() {
addScene(Scenes.PanoSet[i]);
};
NewDiv = document.createElement('div');
NewDiv.id = 'SceneThumbnail' + i;
document.getElementById('Scene' + i).appendChild(NewDiv);
document.getElementById("SceneThumbnail" + i).className = "SceneThumbnail";
document.getElementById("SceneThumbnail" + i).style.backgroundImage = "url(" + Scenes.Thumbnail[i] + ")";
NewDiv = document.createElement('div');
NewDiv.id = 'SceneTitle' + i;
document.getElementById('Scene' + i).appendChild(NewDiv);
document.getElementById("SceneTitle" + i).className = "SceneTitle";
document.getElementById('SceneTitle' + i).innerHTML = Scenes.Title[i];
}
<div id='Carousel'><div>
This is the line that appears to be the problem (I included all above so as to give context)
document.getElementById('Scene'+i).onclick = function() {addScene(Scenes.PanoSet[i]);};
Which ever of the newly created divs I click on, the code "500x" is passed to my addScene function.
I'm expecting that I've over looked something simple. Can someone offer a solution?
Classic JS gotcha. Do this:
document.getElementById('Scene'+i).onclick = ((id) => () =>addScene(Scenes.PanoSet[id]))(i);
You need to bind in the value of i, rather than a reference. The handler code doesn't get evaluated until it gets executed, so the value of i at that time will be the value it has when the loop has completed.
Doing it using an IIFE (immediately-invoked function expression) creates a context with the correct static value of i bound into the scope of the handler that it returns.
You can find index like below. Inside onclick using this you will get clicked div. Then get id with this.getAttribute('id') and replace Scene with ''.
let x = this.getAttribute('id').replace('Scene', '');
Try it below.
let Scenes = {
"Title":["St. Mary Magdalene","Black Mountains","Pen Twyn Glas","Carreg Yr Ogof Cave","Beinn Narnain"],
"Thumbnail":["TNStMary.jpg","TNMountains.jpg","TNPenTwynGlas.jpg","TNCarregYrOgof.jpg","TNBeinnNarnain.jpg"],
"PanoSet":["001x","145+","183+","400x","500x"]
};
var Repeat = (Scenes.Title.length);
for (i = 0; i < Repeat; i++) {
NewDiv = document.createElement('div');
NewDiv.id = 'Scene' + i;
document.getElementById('Carousel').appendChild(NewDiv);
document.getElementById('Scene' + i).className = "Scene";
document.getElementById('Scene' + i).style.position = "absolute";
document.getElementById('Scene' + i).style.top = "5px";
document.getElementById('Scene' + i).style.left = 5 + (170 * i) + "px";
document.getElementById('Scene' + i).onclick = function() {
let x = this.getAttribute('id').replace('Scene', '');
console.log(x);
addScene(Scenes.PanoSet[x]);
};
NewDiv = document.createElement('div');
NewDiv.id = 'SceneThumbnail' + i;
document.getElementById('Scene' + i).appendChild(NewDiv);
document.getElementById("SceneThumbnail" + i).className = "SceneThumbnail";
document.getElementById("SceneThumbnail" + i).style.backgroundImage = "url(" + Scenes.Thumbnail[i] + ")";
NewDiv = document.createElement('div');
NewDiv.id = 'SceneTitle' + i;
document.getElementById('Scene' + i).appendChild(NewDiv);
document.getElementById("SceneTitle" + i).className = "SceneTitle";
document.getElementById('SceneTitle' + i).innerHTML = Scenes.Title[i];
}
<div id='Carousel'></div>
I am trying use below code (found from a forum) as JavaScript initialization code in Oracle APEX Donut chart to display total value in middle. But the result showing up only the Text "Total" in middle of the chart and does not show any numerical value. Can anyone help me out in spotting the error from the below code ? I am new to Javascript and have very less knowledge about the same.
function( options ){
var total;
this.pieSliceLabel = function(dataContext){
var series_name;
percent = Math.round(dataContext.value/dataContext.totalValue*100);
total = Math.round(dataContext.totalValue);
if ( dataContext.seriesData ) {
series_name = dataContext.seriesData.name;
} else {
series_name = 'Other';
}
document.getElementById("myDiv").innerHTML = Math.round(dataContext.totalValue);
return series_name + " " + percent + "% ( " + dataContext.value + " )";
}
// Set chart initialization options
options.dataLabel = pieSliceLabel;
this.centerCallback = function(dataContext){
var pieElem = document.createElement('div');
pieElem.innerHTML =
'<div id="myDiv" style="position:absolute;text-align:center;font-size:16px;">' +
'Total' +' '+ total +
'</div>';
var outerDiv = pieElem.children[0];
var innerBounds = dataContext.innerBounds;
// Outer bounds
outerDiv.style.top = innerBounds.y + "px";
outerDiv.style.left = innerBounds.x + "px";
outerDiv.style.height = innerBounds.height + "px";
outerDiv.style.width = innerBounds.width + "px";
outerDiv.style.lineHeight = innerBounds.height + "px";
return pieElem;
}
options.pieCenter = {
renderer : centerCallback
}
return options;
}
if I correct understood, try to fix it, add to centerCallback,
var value = dataContext.totalValue;
pieElem.innerHTML =
'<div id="myDiv" style="position:absolute;text-align:center;font-size:16px;">' +
'Total ' + value +
'</div>';
Could you try this
function( options ){
// will hold the total value, must be global variable
var total;
Add below statement in this.pieSliceLabel = function(dataContext){}
percent = Math.round(dataContext.value/dataContext.totalValue*100);
total = dataContext.totalValue; //assign to global variable
Update the below innerHTML code in this.centerCallback = function(dataContext){}
//updated element
pieElem.innerHTML =
'<div id="myDiv" style="position:absolute;text-align:center;font-size:16px;">' +
'Total' + total +
'</div>';
// T duplicates the selected element(s).
case 116:
elementSel = document.querySelectorAll("div.selected");
var elementClone,
tmp = getBrowserWidth(),
bww = tmp[0],
bwh = tmp[1];
for (i = 0; i < elementSel.length; i++) {
elementClone = elementSel[i].cloneNode(true);
elementClone.id = "boxID" + Math.floor((1 + Math.random()) * 0x10000);
elementClone.zIndex = "+1";
var posx = getRandomInt(1, bww) - elementSel[i].offsetWidth;
var posy = getRandomInt(1, bwh) - elementSel[i].offsetHeight;
elementClone.style.left = posx + " px";
elementClone.style.top = posy + " px";
elementSel[i].appendChild(elementClone);
elementSel[i].classList.toggle("selected");
console.log("Created " + elementSel.length + " elements.");
}
I am stuck doing a school assignment. I have tried to read similar questions but I do not get any further. The problem is elementClone.style.left/.top not getting assigned new values. Why?
Related answer:
It is working for me, may be the reason is you need to change the position and float attributes.
Ok, I solved it. The problem was " px". Crappé!
I've been trying to get a smooth scroll animation for a while now, but mainly in JS..
This hasn't been working out that well so I decided to try in CSS3.
Now I want to make this animation responsive by calling a JS function which adds the CSS rules for the animation responsive to the object the animation is for. Here is the JS code I've got so far. I'll also leave a Fiddle, but I'm new to that so things might not work right away.
function getTexts() {
var element = document.getElementsByClassName('toplink');
for (x = 0, len = element.length; x < len; x++){
var ID = element[x].textContent.toLowerCase();
var object = document.getElementById(ID);
console.log(object);
addCSSAnimator(ID);
}
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = document.getElementById(el);
var Class = DOM.getAttribute("class");
var Parent = DOM.parentElement.getAttribute("id");
var rect = DOM.getBoundingClientRect();
var rule = ".toplink[ id= '"+el+"' ]:target - #"+Parent+" div."+Class+" {\n" +
"-webkit-transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"}";
console.log("Stylesheet: ",sheet," object: ",DOM," Class: ",Class," offset X&Y:",rect.x," ",rect.y);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
https://jsfiddle.net/dtj46c64/
You may try moving to jquery for this solution. Use document.ready and window.resize functions to handle the animation and also instead of for loop. use the jquery .each() function to get the elements. Try working around the following code i changed for you to go along with. Hope this puts you in the right direction to achieve your goal:
<script>
function getTexts() {
$(".toplink").each(function () {
let ID = $(this)
console.log(ID);
addCSSAnimator(ID);
});
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = el;
var Class = DOM.attr("class");
var Parent = DOM.parent().attr("id");
var rect = DOM[0].getBoundingClientRect();
var rule = ".toplink[ id= '" + el + "' ]:target - #" + Parent + " div." + Class + " {\n" +
"-webkit-transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"}";
console.log("Stylesheet: ", sheet, " object: ", DOM, " Class: ", Class, " offset X&Y:", rect.left, " ", rect.top);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
$(window).on('resize', function () {
getTexts();
});
$(document).ready(function () {
getTexts();
});
</script>
Notice i changed the rect.y to rect.top as on some browsers the getBoundingClientRect fucntion does not return x and y values but left and top are always filled.
Also dont know why you are getting id of the parent of the object as there is no id set to the parent of the anchor class="toplink" so it will always return as null or empty.
Sorry for not a 100% answer as got busy but i hope the solution so far i suggested will help you tweak and find what your looking for.
I have created 64 color buttons in dom by js. they have class name like this:
c1
c2
c3
c4
and so on..
I have created this by this codes:
var eg_color_ul_1 = $('.eg-ul-1');
var eg_color_ul_2 = $('.eg-ul-2');
for (var linum = 1; linum < 65; linum++) {
var Cselector = ".c" + linum;
var colorMenu = $(Cselector).css( "background-color" );
eg_color_ul_1.append("<a class=\"c" + linum + "\" color-code=\""+ colorMenu +"\"></a>"),
eg_color_ul_2.append("<a class=\"c" + linum + "\" color-code=\""+ colorMenu +"\"></a>");
}
I have already set all color in css style sheet.
like this:
.c1 {
background-color: #F44336;
}
.c2 {
background-color: #E91E63;
}
.c3 {
background-color: #9C27B0;
}
.c4 {
background-color: #673AB7;
}
Now i dont get the color in dom.
it show color-code="undefined"
How can I fix it?
I am sorry for the title. I can't understand what should be the title. So I put this.
Edit:
Due to a answer from #Abdul I have corrected my js. But still it shows color-code="undefined". When I console log this it shows
rgb(244, 67, 54) main.js:10
63 undefined main.js:10
this line is wrong:
var colorMenu = $(Cselector).css( "background-color" );
should be:
var colorMenu = $('.' + Cselector).css( "background-color" );
OR keep your line but change this:
var Cselector = ".c" + linum;
^ notice the period
see this fiddle
I would also refactor your code:
https://jsfiddle.net/6551a0ku/2/
var eg_color_ul_1 = $('.eg-ul-1');
var eg_color_ul_2 = $('.eg-ul-2');
for (var linum = 1; linum < 5; linum++) {
var className = 'c' + linum;
var Cselector = '.' + className;
var colorMenu = $(Cselector).css( "background-color" );
eg_color_ul_1.append(getATag(className, colorMenu)),
eg_color_ul_2.append(getATag(className, colorMenu));
}
function getATag(className, colorMenu) {
var aTag = "<a class='"
+ className
+ "' color-code='"
+ colorMenu
+ "'>a</a>";
return aTag;
}
I think there is a misunderstanding of where jQuery will pull the background-color property from. The DOM/jQuery doesn't have a direct understanding of the CSS properties you set down until you associate them with a DOM element either in the actual DOM, or in a Document Fragment.
var eg_color_ul_1 = $('.eg-ul-1');
var eg_color_ul_2 = $('.eg-ul-2');
for (var linum = 1; linum < 65; linum++) {
var Cselector = ".c" + linum;
// the problem is here, at this point, there are no dom elements that match .cN so there is no value to return
var colorMenu = $(Cselector).css( "background-color" );
eg_color_ul_1.append("<a class=\"c" + linum + "\" color-code=\""+ colorMenu +"\"></a>"),
eg_color_ul_2.append("<a class=\"c" + linum + "\" color-code=\""+ colorMenu +"\"></a>");
}
You can fix this by appending the anchor tags to the DOM first and then assigning the color code attribute.
var eg_color_ul_1 = $('.eg-ul-1');
var eg_color_ul_2 = $('.eg-ul-2');
for (var linum = 1; linum < 65; linum++) {
eg_color_ul_1.append("<a class=\"c" + linum + "\"></a>"),
eg_color_ul_2.append("<a class=\"c" + linum + "\"></a>");
}
for (var linum = 1; linum < 65; linum++) {
var domElement = $(".c" + linum)
var colorMenu = domElement.css("background-color")
domElement.attr('color-code', colorMenu)
}
I am unfamiliar with JQuery but if element.css("property") is the equivalent of element.style.property then that's your problem, the style there is referring to the inline style attribute and, as you are using a stylesheet, this is returning nothing.
The solution is to instead use getComputedStyle(), like so:
var eg_color_ul_1=$(".eg-ul-1");
var eg_color_ul_2=$(".eg-ul-2");
for(var linum=1;linum<65;linum++){
var colorMenu=window.getComputedStyle($(".c"+linum),null).getPropertyValue("background-color");
eg_color_ul_1.append("<a class=\"c"+linum+"\" data-color-code=\""+colorMenu+"\"></a>");
eg_color_ul_2.append("<a class=\"c"+linum+"\" data-color-code=\""+colorMenu+"\"></a>");
}
I'd also suggest using data attributes rather than custom attributes to avoid any potential issues.