Change attributes of an element dynamically in javascript/jQuery - javascript

Say I have an element like :
var myElem='<div class="oldClass" style="color:green;" id="oldId"><span>This DIV has some
innerHTML as well</span></div>'
And a JSON like:
var myJson = {
"class": "myClass",
"id": "myId",
"style": "border: 1px solid black; color: red; font-size:20px;"
};
Now I need to update myElem with data in JSON.
What I tried is:
for(var key in myJson){
var attrName = key;
var attrValue = myJson[key];
console.log('attrName ', attrName);
console.log('attrValue ', attrValue);
$(myElem).removeAttr(attrName);
$(myElem).attr(attrName, attrValue);
}
My expectation from this code:
myElem = '<div class="myClass" style="border: 1px solid black; color: red; font-size:20px;" id="myId"><span>This DIV has some innerHTML as well</span></div>'
However, this is not working.myElem remains what it was initially.
myElem and myJson both are dynamic and not static
Can anyone please tell what am I doing wrong? (I know I'm doing something wrong but I'm unable to find it)!

You can pass the whole myJson object to attr and don't have to use a loop:
var myElem = '<div class="myClass" style="border: 1px solid black; color: red; font-size:20px;" id="myId"><span>This DIV has some innerHTML as well</span></div>';
var myJson = {
"class": "myClass",
"id": "myId",
"style": "border: 1px solid black; color: red; font-size:20px;"
};
var elem = $(myElem).attr(myJson);
But if you want, it's even possible in a loop. I don't know why you want to, but it's possible. Just define your element outside the loop and here you go:
var elem = $(myElem);
for( var key in myJson ) {
if( myJson.hasOwnProperty(key) ) {
elem.attr(key, myJson[key]);
}
}

Problem
You're not editing the myElem but the temporary jquery instances of it.
Explication
In every iteration in your for loop you're creating a new instance of jquery object $(myElem) and when the .attr() and .removeAttr() execute they will change the attributes inside this new instance and every change will be overridden in the next iteration of the loop because it will create a new instance, so you are not editing myElem variable but the temporary jquery object instances of it.
jQuery Solution
If you want to edit the attribute of object using jquery function attr() you have two choices :
Using the for loop : create a jquery object and let the function change the attributes, it will works fine check example bellow :
var myElemJQueryInstance = $(myElem);
for(var key in myJson){
myElemJQueryInstance.attr(key, myJson[key]);
}
/*
NOTE : Your code will be more clear/efficient if you use just function .attr()
(no need for removeAttr()) because it will override the old value in the
attribute if is exist.
*/
By passing JavaScript object : You could pass a plain JavaScript object. Each key-value pair in the object adds or modifies an attribute (in your case the object is myJson) :
$(myElem).attr(myJson);
JavaScript Solution
You could achieve that using pure js by the method setAttribute() :
for(var key in myJson){
myElem = myElem.setAttribute(key, myJson[key]);
}
Hope this helps.
var myElem = '<div class="oldClass" style="color:green;" id="oldId"><span>This DIV has some innerHTML as well</span></div>'
var myJson = {
"class": "myClass",
"id": "myId",
"style": "border: 1px solid black; color: red; font-size:20px;"
};
var myElemJQueryInstance = $(myElem);
for(var key in myJson){
myElemJQueryInstance.attr(key, myJson[key]);
}
$('body').append(myElemJQueryInstance);
$('body').append(myElem);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

JavaScript replace works in console, but not on the website

I've been trying to create a list of tags and separate them using commas. I'm using Webflow and sadly it's not possible in their cms.
I thought of a workaround where I would replace the commas with code using JavaScript.
Here's the code:
function tags() {
var tag = document.getElementById("tag__wrap").innerHTML;
str = tag.replace(/,/g, '</p><p class="tag__wrap">');
}
tags();
console.log(str);
For some reason the code works fine when I look it up in the console, but doesn't actually show anything on the actual website.
Any thoughts?
If your goal is to create multiple elements in place of the single element (that has the comma separated tags), then you need to manipulate the DOM. It is not enough to assign HTML to a string variable.
There are many ways to do this. Here is one:
function tags() {
var elem = document.getElementById("tag__wrap");
var tags = elem.textContent.match(/[^,\s]+/g) || [];
elem.textContent = tags.shift();
for (let text of tags) {
var newElem = elem.cloneNode();
newElem.textContent = text;
elem.insertAdjacentElement("afterend", newElem);
elem = newElem;
}
}
// Delay the change, so you can see before & after in the snippet
setTimeout(tags, 1000);
#tag__wrap {
background: lightblue;
display: inline-block;
margin: 5px;
padding: 3px 8px;
border-radius: 4px;
}
<p id="tag__wrap">algorithm,javascript,html,css</p>

Select not working for dynamically created Select Elements. Always selecting last option.

I have the code below where I am creating dynamic Select Elements. The control is displayed on the browser with no issues. However, the option I select is not the one selected on the screen. The screen always shows the last item.
What is odd is if I View Source, the “select” property is on the option I selected. However, the last option is being shown.
I tried using .attr("selected", value === selectOption.SelectedValue)) and that does not even add the “selected” property on the option element.
The only thing that seems to work is selecting the value after the Select Element has been appended to my div tag (commonSubjectivesWindow). But that seems hacky to me.
Been Googling this problem for hours. Any suggestions would be helpful.
function createSelectElement(commonSubjective, selectOption) {
var name = "select" + commonSubjective.Id;
var selectElement = $("<select>").attr("name", name);
//Tried, does not work
//$.each(selectOption.Options, function (key, value) {
// selectElement.append($("<option>").val(value).text(value).prop("selected", value === selectOption.SelectedValue));
//});
$.each(selectOption.Options, function (key, value) {
selectElement.append($("<option>").val(value).text(value).attr("selected", value === selectOption.SelectedValue));
});
return selectElement;
}
function formatCommonSubjectiveText(commonSubjective) {
if (commonSubjective.SelectOptions.length > 0) {
var i = 0;
$.each(commonSubjective.SelectOptions, function() {
var selectElement = createSelectElement(commonSubjective, this);
var placeHolder = "{" + i + "}";
commonSubjective.Text = commonSubjective.Text.replace(placeHolder, selectElement.prop("outerHTML"));
i++;
});
}
return commonSubjective.Text;
}
function loadCommonSubjectives() {
var commonSubjectivesJson = JSON.parse($("#commonSubjectivesHidden").val());
$.each(commonSubjectivesJson, function () {
$("#commonSubjectivesWindow").append($("<span>").append(formatCommonSubjectiveText(this)).prepend(
$("<input>").attr("name", "CommonSubjectivities").attr("type", "checkbox").val(this.Id).prop("checked", this.IsSelected)
).after("</br></br>"));
});
}
Strange, just made a fiddle ... added a selectbox dynamically (just one) and selected an item ... even if appended after setting the value.
Fiddle here
Just set the value with:
selectElement.val('val2');
From jquery docs
val() allows you to pass an array of element values. This is useful
when working on a jQuery object containing elements like , , and s inside of a
.
I'm not 100% sure what you want, so I'll simplify the answer, then you let me know if it is or isn't what you meant.
What I understand:
Creating a <select> dynamically
Having trouble adding the selected attribute to an <option>
Ok, for this example, I'm using plain JS, it can be easily adapted into jQuery. The biggest challenge there is to remember which objects are normal ones and which are jQuery objects.
function makeSelect(ele, len, att) {
var sel = document.createElement("select");
var tgt = document.querySelector(ele);
sel.id = "selectList";
tgt.appendChild(sel);
for (var i = 1; i < len + 1; i++) {
var opt = document.createElement("option");
opt.text = i;
opt.value = i;
sel.appendChild(opt);
}
sel.selectedIndex = att - 1;
}
makeSelect('#set', 10, 5);
body {
background: #111;
}
#set {
border-radius: 8px;
width: 5em;
background: #222;
border: 2px inset #FC3;
}
legend {
font: small-caps 400 21px/1.5 "Palatino Linotype";
color: #FC3
}
<fieldset id="set">
<legend>DynSelect</legend>
</fieldset>
Usage makeSelect(ele, len, att)
ele: The selector of the element that the <select> will append to. (i.e. selectors - #id, .class, tag).
len: The number of options.
att: The index of the selected option.
The heart of this post concerning your question can be summarized with this:
Use .selectedIndex
Forgive me for using a W3School reference, MDN doesn't have it listed. If anyone has found a better reference please notify me in comments.

How to write css code in javascript? (Uncaught TypeError: Cannot set property "height" of undefined)

How to write css code in javascript? (Uncaught TypeError: Cannot set property "height" of undefined)
javascript
document.getElementById("slideshow").getElementsByClassName("arrow").style.height = "86px";
css
#slideshow .arrow{
height:86px;
width:60px;
position:absolute;
background:url('arrows.png') no-repeat;
top:50%;
margin-top: -43px;
cursor: pointer;
z-index: 5000;
}
The key here is the pluralisation of getElementsByClassName - elements. This method returns an array-like object of elements, not just one element.
To apply the style to each, you need to loop through this array-like object and add the styles to each individual element returned:
var elems = document.getElementById("slideshow").getElementsByClassName("arrow");
for (var i = 0; i < elems.length; i++)
elems[i].style.height = "86px";
document.getElementsByClassName returns an array.
You have to loop through it, or if you know the index, do this:
document.getElementById("slideshow").getElementsByClassName("arrow")[0].style.height = "86px";
or
document.getElementById("slideshow").getElementsByClassName("arrow")[i].style.height = "86px";
i being your loop variable.
A bit of theory:
Changing HTML Style
To change the style of an HTML element, use this syntax:
document.getElementById(id).style.property=new style
Here is the example:
// JavaScript demonstration
var changeBg = function (event) {
console.log("method called");
var me = event.target
, square = document.getElementById("square");
square.style.backgroundColor = "#ffaa44";
me.setAttribute("disabled", "disabled");
setTimeout(clearDemo, 2000);
}
function clearDemo(button) {
var square = document.getElementById("square");
square.style.backgroundColor = "transparent";
button.removeAttribute("disabled");
}
var button = document.querySelector("button");
button.addEventListener("click", changeBg);
console.log(button);
#square {
width: 20em;
height: 20em;
border: 2px inset gray;
margin-bottom: 1em;
}
button {
padding: .5em 2em;
}
<h1>JavaScript sample</h1>
<div id="square"></div>
<button>Click Me</button>
JavaScript-Based Style Sheets - http://www.w3.org/Submission/1996/1/WD-jsss-960822
Mozzila's Web Developer guide - https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/JavaScript
While I've started with explanation and theory #James Donnelly already provided my answer, which I've wanted to use:
var elements = document.getElementById("slideshow").getElementsByClassName("arrow");
for (var i = 0; i < elems.length; i++) {
elems[i].style.height = "86px";
.
As someone already pointed out,
document.getElementsByClassName returns an array (N Objects)
while
document.getElementById returns an element (ONE object)
This is because N elements can have the same class but only ONE item can have a particular ID.
Since you can't edit more items' attribute at once, you must cycle them and edit the attribute of each one by one
document.getElementById("slideshow").getElementsByClassName("arrow")[0].style.height = "86px";
document.getElementById("slideshow").getElementsByClassName("arrow")[1].style.height = "86px";
document.getElementById("slideshow").getElementsByClassName("arrow")[2].style.height = "86px";
.....
document.getElementById("slideshow").getElementsByClassName("arrow")[N].style.height = "86px";
This can be achieved by using a for cycle or a each one.

Add CSS Class Property through Javascript

I have an HTML page having css class for a control with following definition:
.ms-crm-Inline-Edit select.ms-crm-SelectBox {
border: 1px solid #CCCCCC;
font-size: 12px;
margin: 1px 0 0 1px;
width: 100%;
}
I need to add a new attribute to this class as follows:
height: "120px !important";
This has to be done through Javascript. I can't modify origional class definition that's why I have to add Javascript function which does this job. For that purpose I have written Jscript method but its not working.
function CustomizePicklistHeight ()
{
document.getElementsByClassName('ms-crm-Inline-Edit select.ms-crm-SelectBox').style.height = '120px !important';
}
I guess, first we have to add height attribute to this class but I dont know how to do that in JScript. Please suggest.
document.getElementsByClassName returns an array of all items with that class.
Try this:
function CustomizePicklistHeight()
{
// Store elements for each class differently. Just in case :)
var elements1 = document.getElementsByClassName('ms-crm-Inline-Edit');
var elements2 = document.getElementsByClassName('ms-crm-SelectBox');
// Since you cant affect the array directly, you use a loop to do the operation on each individual element
for (var i = 0; i < elements1.length; i++)
{
element1[i].style.height = '120px !important';
};
for (var j = 0; j < elements2.length; j++)
{
element1[j].style.height = '120px !important';
};
}​
Hope this helps.. :)
var matches = document.querySelectorAll(".ms-crm-Inline-Edit, select.ms-crm-SelectBox");
for(i=0; i<matches.length; i++)
{
matches[i].style.height = '120px !important';
}
Reference: https://developer.mozilla.org/en-US/docs/Web/API/Document.querySelectorAll
ClassName means "class name" (ms-crm-SelectBox) not "Entire selector". (querySelector and querySelectorAll let you use complete selectors though.
Elements means "elements" (plural) not "Element". It returns a NodeList, which you can loop over like an array.
If, on the other hand, you want to the modify the CSS rule-set instead of the styles applied directly to the HTML elements, then you need to look at document.styleSheets instead.
you will have to make a loop by setting each item, and if you have not "! important" earlier you do not need it.

Add css before appending child

So I have a div (with the id of "thecolor2") that I want to append to an unordered list, but before I append it, I want to set its background color to a variable which has the value of a hex code. However, for some reason, it doesn't take in the color.
Here is the CSS:
#thecolor2{
height: 50px;
width: 50px;
border-radius: 100px;
border: 1px solid yellow;
position: relative;
bottom: 635px;
}
Her is the HTML:
<ul id = "allposts"></ul>
And here is the JS:
var thestream = document.getElementById('allposts');
var oneofpost = document.createElement('li');
var thecolor2 = document.createElement('div');
thecolor2.id = "thecolor2";
$("#thecolor2").css("background-color", color);
thestream.appendChild(oneofpost);
thestream.appendChild(thecolor2);
You cant use a jQuery ID selector to match a node which hasn't been added to the document tree. You can simply use plain DOM to set its inline CSS style like this:
thecolor2.style.backgroundColor = color
As described by Carlo in another answer, you cannot use the jQuery selector to select elements that haven't been added. You can however, turn a created DOM element into a jQuery object by doing:
var thecolor2 = $(document.createElement('div'));
However, if you're going to be using jQuery then I suggest writing everything in jQuery, otherwise stick with using pure JavaScript for everything.
jQuery
var thestream = $('#allposts');
var oneofpost = $('<li></li>');
var thecolor2 = $('<div></div>');
thecolor2.prop('id', "thecolor2")
.css({
backgroundColor: color
}).appendTo(oneofpost);
thestream.append(oneofpost);
See jsFiddle
JavaScript
var thestream = document.getElementById('allposts');
var oneofpost = document.createElement('li');
var thecolor2 = document.createElement('div');
thecolor2.id = "thecolor2";
thecolor2.style.backgroundColor = color;
oneofpost.appendChild(thecolor2);
thestream.appendChild(oneofpost);
See jsFiddle
Also I'm assuming you're trying to append a list item to the ul, so I corrected the code you had there with appendChild.

Categories