Get child element by HTML Object - javascript

I'm attempting to reuse the variable "startGame", variable through which I declare an "a" element to be appended to the "table" element, in order to test for its own presence posteriorly. The code I've written for doing so is the following:
//Helper function to set HTML Tags attributes
function setAttributes(element, attributes)
{ for (var key in attributes) { element.setAttribute(key, attributes[key]); } }
//Opening screen
var startGame = document.createElement("a");
setAttributes(startGame,
{
"style" : "float:left; width: 100%; text-align: center;",
"onclick" : "dealHands()"
});
startGame.appendChild(document.createTextNode("Play"));
var table = document.getElementById("table");
table.appendChild(startGame);
function dealHands()
{
if (table.childNodes[0].nodeValue == startGame)
{ table.removeChild(startGame); }
...
}
So far, the code fails to perceive "startGame" and nothing happens.

You cannot set the style attributes using this:
"style" : "float:left; width: 100%; text-align: center;"
they have to be set individually. But IE doesn't support changing style in this way. You need:
element.style.cssFloat = "left"; // etc.
Discussed here
Also, I wouldn't use table as an ID.

I just had to remove the ".nodeValue" from the if statement in order to make a comparison between two HTML elements instead of comparing a value with a HTML element.

Related

Add input field onclick with new name [duplicate]

This question already has answers here:
info on javascript document.createElement()
(4 answers)
Closed 12 months ago.
I want to display a new input field with a new name everytime a button is clicked. how do I achieve that? I found solutions to adding the input but none mentions adding a new name to it.
HTML:
Add a keyword
<div id="fieldContainer"></div>
Javascript:
function addKeywordFields() {
var mydiv = document.getElementById("fieldContainer");
mydiv.appendChild(document.createTextNode("<input type='text' name=''>"))
}
You should not use document.createTextNode to create an input. This will only create a text element with content specified inside it.
Instead you should create an input using document.createElement('input') and specify its type and name.
Since you need a dynamic name, you have to integrate a dynamic name generation logic. Here I used (new Date()).toISOString() since this will e unique each time. Instead you have to use your own logic.
Working Fiddle
function addKeywordFields() {
var mydiv = document.getElementById("fieldContainer");
const input = document.createElement('input');
input.type = 'text';
input.name = (new Date()).toISOString(); // Some dynamic name logic
mydiv.appendChild(input);
}
<a onclick="addKeywordFields()">Add a keyword</a>
<div id="fieldContainer"></div>
There's a ton of DOM methods designed to create, destroy, move, etc. There's generally three ways to create a DOM element programmatically:
clone an element with .cloneNode() and .append()
parse a string that represents HTML (aka htmlString) use .insertAdjacentHTML() instead of .innerHTML
create an element with .createElement() and .append()
Assigning attributes/properties to an element can be done initially with .setAttribute() once an attribute has been assigned to an element, it is technically a property. This distinction between attribute and property is blurry because methods seem to work 100% as does assigning properties. jQuery is not so flexible in this instance, .attr() and .prop() have silently failed on me when I forget about attribute/property quirks.
I rarely use methods to assign attributes, properties are terse and simple to use, here's a few common ones:
obj.id = "ID", obj.className = "CLASS", obj.name = "NAME"❉,
obj.type = "TEXT", obj.dataset.* = "*"
❉This is the property you use to set/get name attribute
I always add a <form> if there's multiple form controls. There are special features and terse syntax if you use interfaces like HTMLFormElement✤ and HTMLFormControlsCollection✼. Moreover having a <form> you can use it to listen for events for everything within it❉ and also take advantage of special form events like "input", "change", "submit", etc.
HTMLFormElement.elements collects all form controls (listed below)
<button>, <fieldset>, <input>, <object>, <output>, <select>, <textarea>.
From the .elements property, any form control can be referenced by #id or [name]. If there is a group of form controls that share a [name] they can be collected into a HTMLCollection.
References
HTMLFormElement✤
HTMLFormControlsCollection✼
Events
Event Delegation❉
Further details are commented in example below
// Reference the form (see HTMLFormElement)
const UI = document.forms.UI;
// Register form to click event
UI.addEventListener('click', makeInput);
// Define a counter outside of function
let dataID = 0;
// Pass Event Object
function makeInput(e) {
/*
"this" is the form
.elements property is a collection of all form controls
(see HTMLFormsCollection)
*/
const io = this.elements;
// Event.target points to the tag user clicked
const clk = e.target;
/*
This is the fieldset containing the inputs it's in bracket notation
instead of dot notation because it's a hyphenated property
*/
const grp = io['form-group'];
// This is the static input
const inp = io.data;
// if the clicked tag is a button...
if (clk.matches('button')) {
// ...increment the counter
dataID++;
/*
This switch() delegates what to do by the clicked button's [name].
Each case is a different way to create an element and assign a unique
[name] by concatenating the "data" with the current number of dataID
*/
switch (clk.name) {
case 'clone':
const copy = inp.cloneNode(true);
copy.name = 'data' + dataID;
grp.append(copy);
break;
case 'html':
const htmlStr = `
<input name="data${dataID}">`;
grp.insertAdjacentHTML('beforeEnd', htmlStr);
break;
case 'create':
const tag = document.createElement('input');
tag.name = 'data' + dataID;
grp.append(tag);
break;
default:
break;
}
}
};
form {
display: flex;
}
fieldset {
display: inline-flex;
flex-direction: column;
justify-content: flex-startd;
max-width: 90%;
}
input,
button {
display: inline-block;
width: 80px;
margin-bottom: 4px;
}
input {
width: 150px;
}
button {
cursor: pointer;
}
<form id='UI'>
<fieldset name='btn-group'>
<button name='clone' type='button'>Clone Node</button>
<button name='html' type='button'>Parse htnlString</button>
<button name='create' type='button'>Create Element</button>
</fieldset>
<fieldset name='form-group'>
<input name='data'>
</fieldset>
</form>

How do I change an attribute or class using only Javascript?

I would like to change the styling attribute values of all elements that have the class "post-feature" and contain an attribute value of "http"
So the div element will look like the following:
<div class="post-feature" style="backgroundimage:url(http://local.test.com/test_image.jpg);">
So far the http check works. But I am not able to set the attribute value.
I have the following code
var features = document.getElementsByClassName(".post-feature")
[0].getAttribute("style");
if (features.includes("http")) {
features.setAttribute("background-color", "orange");
} else {
alert('no change');
}
You can use querySelectorAll('.post-feature[style*="http"]') to find those elements.
Then simply iterate through them and i.e. set their background color with
element.style.backgroundColor = 'orange';
Now, if you want to make sure you only target elements having a background-image and http, you can use this selector:
querySelectorAll('.post-feature[style*="http"][style*="background-image"]')
Also, by adding an i (or I) just before the end bracket [style*="http"i], the value will be compared case-insensitively.
window.addEventListener('load', function() {
var elements = document.querySelectorAll('.post-feature[style*="http"]');
for (var i = 0; i < elements.length; i++) {
elements[i].style.backgroundColor = 'orange'; /* add propert value */
/* replace class
elements[i].className = 'myClass';
*/
/* add a class
elements[i].classList.add('myClass');
*/
}
/* temp log */
console.log('Found ', elements.length,' element(s)');
})
div {
height: 40px;
background-color: gray;
}
div + div {
margin-top: 10px;
}
<div class="post-feature" style="background-image:url(http://local.test.com/test_image.jpg);"></div>
<div class="post-feature"></div>
<div class="post-feature" style="background-image:url(http://local.test.com/test_image.jpg);"></div>
<div class="post-feature"></div>
Updated
To only change styling, like colors etc., you don't even need a script, you can use CSS alone
div {
height: 40px;
background-color: gray;
}
div + div {
margin-top: 10px;
}
/* for elements that contain "http" and "background-image" */
.post-feature[style*="http"i][style*="background-image"i] {
background-color: orange;
}
<div class="post-feature" style="background-image:url(http://local.test.com/test_image.jpg);"></div>
<div class="post-feature"></div>
<div class="post-feature" style="background-image:url(HTTP://local.test.com/test_image.jpg);"></div>
<div class="post-feature"></div>
As a note, and as discussed in a few comments, if to make sure it is the background-image property that also contain the http in its url(), you can adjust the selector to this, which as well can be used without any script, as a CSS rule
.post-feature[style*="background-image:url(http"i] {
background-color: orange;
}
The above selector can of course also be used in the first sample, like this
querySelectorAll('.post-feature[style*="background-image:url(http"i]')
First, you can use querySelctorAll() with a CSS query that selects the elements with the class you desire and, in most cases, you should use this instead of getElementsByClassName() as that returns a "live node list" that causes the DOM to be re-scanned every time you access it.
Next, setAttribute() is for setting HTML element attributes. You are asking to change the value of a CSS property. While that could be accomplished with setAttribute('style', value), it is very "old-school" and not the best approach, nor is getAttribute('style') the best way to read a CSS property value (it won't work if the CSS was set from a style sheet).
Also, your code is trying to access: backgroundimage, but the property is accessed as background-image when working in CSS and backgroundImage when accessing it via JavaScript.
To access the inline styles applied to an HTML element, just access the style property of that element, followed by the name of the CSS property you are interested in. For example:
var bColor = element.style.backgroundColor;
If the style has been applied to the element from an internal style sheet or an external style sheet, the above approach won't work for you and you'll need to get it another way, via window.getComputedStyle():
var bColor = window.getComputedStyle(element, null).backgroundColor;
But, note that getComputedStyle() doesn't always return the same value that you set - - it's the value after the browser has computed all factors. In this case, even paths that you wrote as relative references (without the "http") will be returned as absolute paths (with the http).
So, here is a modern approach that correctly checks only the background-image CSS property for the presence of http.
NOTE: This solution tests for http specifically in the background-image property. Unlike most of the other answers given, this code will correctly ignore http in other CSS properties besides background-image. Examine the CSS of the last div to see this in action.
// querySelectorAll() is more efficient than getElementsByClassName()
var features = document.querySelectorAll(".post-feature");
// Loop over the list
for(var i = 0; i < features.length; i++){
// Get access to the background-image property (called backgroundImage from JavaScript) value,
// convert that value to lower case and check to see if "http" is in that value
if(features[i].style.backgroundImage.toLowerCase().indexOf("http") > -1){
// Set the CSS background-color property (called "backgroundColor" in JavaScript) to orange:
features[i].style.backgroundColor = "orange";
// Just for testing:
features[i].textContent = features[i].style.backgroundImage;
} else {
alert("No change");
}
}
.post-feature { width:100%; height:50px; border:1px solid black; background-color:gray; color:yellow; }
<!-- The correct CSS property is "background-image", not "backgroundimage" -->
<div class="post-feature" style="background-image:url(http://local.test.com/test_image.jpg);"></div>
<div class="post-feature" style="background-image:url(test_image.jpg);"></div>
<div class="post-feature" style="background-image:url(http://local.test.com/test_image.jpg);"></div>
<div class="post-feature"
style="border-image: url('http:///images/border.png') 30 30 repeat;background-image:url(test_image.jpg);">I have "http" in one of my CSS properties, but not "background-image", so I shouldn't be orange.</div>
i think some wrong in your code, try this code
element.setAttribute("style", "background-color: orange;"); // bad
or
element.style.backgroundColor = "orange"; // good
Use element.style.backgroundColor and indexOf
var features = document.getElementsByClassName(".post-feature")[0].getAttribute("style");
if (features.indexOf("http") > -1) {
features.style.backgroundColor = "orange";
} else {
alert('no change');
}
check this fiddle
https://jsfiddle.net/vywk72j8/2/
<div class="post-feature" style="background-image:url(http://local.test.com/test_image.jpg);">
tt</div>
var feature = document.getElementsByClassName("post-feature")[0];
if (feature.style.backgroundImage.indexOf("http") !== -1) {
feature.style.backgroundColor = "orange";
} else {
alert('no change');
}
In your code, you are fetching the attribute value in features
var features = document.getElementsByClassName(".post-feature")
[0].getAttribute("style");
Here features is a string containing attribute value, not an element so you cannot use it to set value.

Achieve "::-moz-focus-inner {border:0;}" in javascript

I'd like to remove the ugly focus outline on an input button in firefox. I've tried adding ::-moz-focus-inner {border:0;} as style in my html, which works initially, but not when button elements are re-created via javascript.
I've tried:
cell.style.mozFocusInner.border = "0";
cell.style["-moz-focus-inner"] = "{border:0}";
cell.style["-moz-focus-inner"]["border"] = "0";
etc.
In general, how do I "map" css to javascript?
According to the CSS property to IDL attribute algorithm, a -moz-focus-inner would be camelCased to MozFocusInner. So you could use one of
element.style.MozFocusInner = value;
element.style.setPropertyValue('-moz-focus-inner', value);
element.style.setProperty('-moz-focus-inner', value);
element.style.setProperty('-moz-focus-inner', value, '!important');
But there is a big problem: -moz-focus-inner is not a CSS property, is a pseudo-element.
Given an element, you can read the computed styles of its pseudo-elements via getComputedStyle:
getComputedStyle(element, '::-moz-focus-inner').borderTopWidth; // 1px
However, you can't set them directly. If you want to do that, you can:
Conditionally set the desired styles in a stylesheet, and use JS to trigger that condition whenever you want. For example, add a class.
document.getElementById('enable').addEventListener('click', function() {
document.getElementById('target').classList.remove('no-focus-inner');
});
document.getElementById('disable').addEventListener('click', function() {
document.getElementById('target').classList.add('no-focus-inner');
});
.no-focus-inner::-moz-focus-inner {
border: none;
}
<ol>
<li><button id="enable">Enable inner outline</button> or <button id="disable">Disable inner outline</button></li>
<li>Press Tab key</li>
<li><button id="target">Focus me to check if I have inner outline</button></li>
</ol>
Create a new stylesheet with the desired rulesets, and append it to the document.
var styleSheet = document.createElement('style');
styleSheet.textContent = '#target::-moz-focus-inner { border: none; }';
document.getElementById('enable').addEventListener('click', function() {
if(styleSheet.parentNode) document.head.removeChild(styleSheet);
});
document.getElementById('disable').addEventListener('click', function() {
document.head.appendChild(styleSheet);
});
<ol>
<li><button id="enable">Enable inner outline</button> or <button id="disable">Disable inner outline</button></li>
<li>Press Tab key</li>
<li><button id="target">Focus me to check if I have inner outline</button></li>
</ol>
Maybe this works without javascript: https://css-tricks.com/forums/topic/button-padding-issue/
::moz-focus-inner is a pseudo-element. In this link are several ways how to modify pseudo-elements dynamically (with javascript) http://pankajparashar.com/posts/modify-pseudo-elements-css/
cited from http://pankajparashar.com/posts/modify-pseudo-elements-css/ :
<p class="red">Hi, this is a plain-old, sad-looking paragraph tag.</p>
.red::before {
content: 'red';
color: red;
}
Method 1
Write separate classes attached with pseudo element for each style and then using JavaScript or jQuery toggle between these classes.
.green::before {
content: 'green';
color: green;
}
$('p').removeClass('red').addClass('green');
...
Common css-styles (not pseudo-elements) can be modified using javascript like this:
cited from https://www.kirupa.com/html5/setting_css_styles_using_javascript.htm :
Every HTML element that you access via JavaScript has a style object. This object allows you to specify a CSS property and set its value. For example, this is what setting the background color of an HTML element whose id value is superman looks like:
var myElement = document.querySelector("#superman");
myElement.style.backgroundColor = "#D93600";
To affect many elements, you can do something as follows:
var myElements = document.querySelectorAll(".bar");
for (var i = 0; i < myElements.length; i++) {
myElements[i].style.opacity = 0;
}
In a nutshell, to style elements directly using JavaScript, the first step is to access the element. I am using the querySelector method to make that happen. The second step is just to find the CSS property you care about and give it a value. Remember, many values in CSS are actually strings. Also remember that many values require a unit of measurement like px or em or something like that to actually get recognized.

Trying to change colors, but not sure how to change div element from JavaScript

New to JavaScript and CSS and I am trying to give the user a button that will change the background color of a game board (set up with div) randomly when pressed.
<style type="text/css">
div.conway {
overflow: hidden;
font-family: courier;
float: left;
width: 800px;
height: 488px;
background-color: green;
font-size: 10px;
color: gold;
}
</style>
and inside my script tag I have the following:
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
my.changeBackgroundColor = function () {
document.getElementById(conway).style.background-color = getRandomColor();
}
But the DOM is not letting me assign the new color. What am I doing wrong?
background-color should be backgroundColor:
document.getElementById(conway).style.backgroundColor = getRandomColor();
or this is allowed as well:
document.getElementById(conway).style["background-color"] = getRandomColor();
In JavaScript, you can refer to an object property using dotted notation and a property name literal (obj.foo), or using bracketed notation and a property name string (obj["foo"]). A property name literal has to be a valid JavaScript identifier, and obviously you can't have a - in an identifier, it looks like a minus sign. So instead, camelCase is used where hyphens would normally be in the style object.
Side note: You haven't shown your HTML, or the content of your conway variable, but I assume you have an id on the element in question, and that the conway variable contains that id. E.g.:
<div id="cell23">...</div>
and
conway = "cell23"
Try using backgroundColor instead off of style.
JS is treating - as the minus operator.
The problem is that you are trying to access the DOM element by ID using document.getElementById(conway) but conway is a class. So you either have to give the targeted div an ID or use document.getElementsByClassName('conway'); which will effectively get all of the element that have a class name conway. Not sure if that is what you want.
You are calling the wrong property. It should be:
my.changeBackgroundColor = function() {
document.getElementById(conway).style.backgroundColor = getRandomColor();
}
Here is working js fiddle example
You had few problems within your code,
Line:
document.getElementById(conway).style.background-color = getRandomColor();
Should be defined as: (see how backgroundColor is written and usage of "" for id).
document.getElementById("conway").style.backgroundColor = getRandomColor();
Also, remember to apply your styles to id element (can't see whether your div has a class conway defined or not.)
div#conway { .. }
After that it works great.
I also recommend that you check CSS properties reference which lists formats used for giving css attributes using javascript. In other words, the problem which you had.!
Cheers.

Class CSS property return

How would one return a class computed CSS property/property array?
Like, if I have a class defined in CSS:
.global {
background-color: red;
color: white;
text-shadow: 0px 1px 1px black;
}
It's applied on the go with javascript to an element. Now I want to change this elements childrens' color to parents' (.global) element background-color.
And is there a way to read CSS properties from a previously defined class in a style tag or externally included *.css?
Something like, getCSSData([span|.global|div > h1]); (where the passed variable is a CSS selector, that gets data for exactly matching element) that would return an object with each property in it's own accessible variable?
Something like:
cssdata = {
selector : '.global',
properties : {
backgroundColor : 'red',
color : 'white',
textShadow : '0px 1px 1px black'
// plus inherited, default ones (the ones specified by W3..)
}
}
And the usage for my previously explained example would be:
// just an example to include both, jQuery usage and/or native javascript
var elements = $('.global').children() || document.getElementsByClassName('.global')[0].children;
var data = $('.global').getCSSData() || document.getCSSData('.global');
return elements.css('color', data.properties.backgroundColor) || elements.style.backgroundColor = data.properties.backgroundColor;
Is there a function built in already in javascript/jquery and I've overlooked it?
If not, what should I look for to make one?
P.S. Can be DOM Level 3 too.. (HTML5'ish..)
If you want to grab the background color of the parent element and then apply that color to the font of all of it's children you could use the following code.
$(document).ready(function(){
var global = $('.global');
var bgColor = global.css('background-color');
global.children().css('color', bgColor);
};
Here's an example on jsFiddle.net
You can access the computedStyle of an element which includes all inherited style values, here is a example that outputs the computed style of a div element in the console.
<script type="text/javascript">
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", listComputedStyles, false);
}
function listComputedStyles() {
var element = document.getElementById("myDiv");
var properties = window.getComputedStyle(element, null);
for (var i = 0; i < properties.length; i++)
{
var value = window.getComputedStyle(element, null).getPropertyValue(properties[i]);
console.log(properties[i], value);
}
}
</script>
<div id="myDiv" style="background-color: blue; height: 500px;"></div>
You can find more information here: http://help.dottoro.com/ljscsoax.php
If I understand your question correctly, you'd like to find a general approach to modifying a class; and to have that modifcation affect all of the instantiations of that class. This was the subject of another detailed discussion on SO over here.
There turned out to be an extremely interesting and useful treatment of classes that works in almost all browsers, notably excepting IE8 and below.

Categories