The css
div.online:last-child {
color:green;
}
div.offline:last-child {
color:green;
}
JavaScipt
var x=navigator.onLine;
var div = document.createElement("div");
if (x==false) {
var divContent = document.createTextNode("sorry, you're offline");
divContent.className="offline:last-child";
div.appendChild(divContent);
var k = document.body.appendChild(div);
} else {
var divContent = document.createTextNode("you are online");
divContent.className="online:last-child";
div.appendChild(divContent);
var k = document.body.appendChild(div);
}
here I am using .className to change the style of last word using the last-child pseudo class (so only offline and online are styled). I'm guessing there is a problem with the naming of the class in my js code.
Before I took this approach I used setAttribute, but I had little idea how to go about using pseudo classes using that. What class name (and / or code) should I be using?
First, you can't assign a class to a text node, only to an element. Assign the online or offline class to the div, not its text content.
Second, you can't directly assign a pseudo-class like :last-child. Selectors with such a pseudo-class in CSS are used to target elements that are the last child of their parent in the DOM tree.
Related
I can easily toggle between classes using element.classList.toggle(). Thus, using bootstrap 4, for example, it's easy to change a class, and no extra css is necessary.
I was wondering if there is an equivalent method for toggling between different tags.
A use case would be toggle between "bootstrap 4" inline text tags https://getbootstrap.com/docs/4.5/content/typography/#inline-text-elements
Text decoration here is added by tags, and not by classes.
I did some previous research, and I've found other queries about toggle between divs. I also can figure out how to do it by creating a conditional statement.
But is there a way to toggle tags as easy as element.classList.toggle() using only javascript?
Swap from p to span and preserving attributes.
function swapTag(element, newTag) {
// New element with the desired tag
let newElement = document.createElement(newTag);
// Copy of all attributes
for(let attr of element.attributes) {
newElement.setAttribute(attr.name, attr.value);
}
// Replace
element.replaceWith(newElement);
}
// Create two elements
var parent = document.createElement("div");
var child = document.createElement("p");
// Assign some style
child.style.color = "red";
parent.appendChild(child);
// Before
console.log(parent.outerHTML);
// Do the magic
swapTag(child, "span");
// After
console.log(parent.outerHTML);
So I got into JavaScript and tried setting up the following scenario:
I have 2 Buttons on my Site (IDs are buttonWebdev and buttonUXUI), which should trigger an Action when they are hovered upon. If buttonWebdev is hovered upon, it should hide all p', h3's and imgs with the class "classWeb". I wrote this code to do it, but it doesn't work:
HTML:
<h3 class="classWeb">Editierbare Inhalte</h3>
<p class="classWeb">Test</p>
<button class="buttonImg" id="buttonWebdev"><img src="./img/buttonWebdev.png" /></button>
<script type="text/javascript">
var button = document.getElementById('buttonWebdev');
var classWeb = document.getElementsByClassName('classWeb');
button.onmouseover = function() {
classWeb.className = 'webdev';
}
CSS:
.classWeb.webdev {
display: none;
}
First, since there can be more than one element with a given class on a page, getElementsByClassName returns a list of elements instead of a single element. You’ll need to perform your action on every element of that list, with a for…of loop, for example:
for (let element of classWeb) {
element.className = 'webdev';
}
(for…of is relatively new, though, so you might have to use a regular for loop depending on your target browsers.)
After fixing this, you’ll run into another problem. When you assign to className like that, you’re setting the entire list of classes on an object. If the list of classes is 'webdev', it no longer includes 'classWeb'. Modern browsers support an API to add a class without affecting the rest:
for (let element of classWeb) {
element.classList.add('webdev');
}
The way to diagnose these sorts of problems is by opening up your browser’s developer tools, looking for JavaScript errors in the console, and looking at the state of the elements you’re trying to affect in the document tree.
document.getElementsByClassName('classWeb'); this gives collection & to add classes you need to iterate over them & then apply classes.
classWeb[0].className = 'webdev'; would reset class
either use classWeb[i].className += ' webdev'; or classWeb[i].classList.add('webdev');
See below working example
var button = document.getElementById('buttonWebdev');
var classWeb = document.getElementsByClassName('classWeb');
button.onmouseover = function() {
for (var i = 0; i < classWeb.length; i++)
classWeb[i].className += ' webdev';
}
.classWeb.webdev {
display: none;
}
<h3 class="classWeb">Editierbare Inhalte</h3>
<p class="classWeb">Test</p>
<button class="buttonImg" id="buttonWebdev">hover over me</button>
Firstly, the
document.getElementsByClassName('classWeb');
will give you a LIVE list of all the matched elements. That means that when you reassign the class like so:
classWeb[0].className = 'webdev';
the element will be removed from the list, as it no longer corresponds to the original command which was to find all elements with a specific class (which you overrode with 'webdev').
An easier and more friendly api is querySelectorAll which mimics the jQuery selector (which uses css selectors to find elements, thats why there is a # for an id and a . for a class name). The example below shows, how to use it.
var button = document.querySelector('#buttonWebdev');
var classWeb = document.querySelectorAll('.classWeb');
button.onmouseenter = function() {
for (var i = 0; i < classWeb.length; i++) {
classWeb[i].className = 'webdev';
}
}
ps. The querySelectorAll is not a live list, so items will not disappear after you change their class.
ps2. Use onmousenter instead of onmouseover as the onmouseenter is only called when the mouse starts hovering over an element, while onmouseover will be called on every mouse move over the element (even if already hovering).
Good luck!
It is a script in javascript that add a <div></div> and add an id, a class, html.. I want to add name attribut too and my code doesn't works, but I wonder why..
There https://developer.mozilla.org/fr/DOM/element I have seen that element.name = 'newname'; can edit it..
function newgroup() {
var e = document.getElementsByName('group');
var nb = e.length + 1
div = document.createElement("div");
div.id = 'group'+nb;
div.className = 'panel_drop';
div.name = '1';
div.innerHTML = '<h5>Group '+nb+'</h5>';
div.innerHTML += '<div class=\'drop_zone\'></div>';
document.getElementById('groups').appendChild(div);
}
The name attribute of an HTML element is not mapped to the name property of the corresponding DOM element for all elements, but only for certain types of elements, and DIV elements are not one of them.
You can check for which types of HTML elements the name attribute is specified here: http://www.whatwg.org/specs/web-apps/current-work/multipage//section-index.html#attributes-1
Since the HTML standard doesn't specify a name attribute for DIV elements, my recommendation is to not use such an attribute/property on DIV elements. If you need to attach additional information to your DIV elements, consider data-* attributes.
div.setAttribute('name', '1');
The fact that div.getAttribute('class') is also exported as a convenience function as the className property (with an impilicit setter and getter) doesn't mean that it is a consistent way to handle DOM node property names.
BTW, consider using a javascript framework, like jQuery, Prototype, MooTools or YUI, helps on the long run...
For example with Jquery you can have easily a finer control on attributes by changing them or removing them
I'm just wondering if the following is possible, lets say we have a dom element and we want to wrap this element in a div. So a div is inserted between the element and it's parent. Then the div becomes the element's new parent.
But to complicate things, elsewhere we have already done things like:
var testElement = document.getElementByID('testID')
where testID is a child of the element to be warapped in a div. So after we have done our insertion will testElement still be valid?
BTW: I'm not using jquery.
Any ideas?
Thanks,
AJ
You can use replaceChild [docs]:
// `element` is the element you want to wrap
var parent = element.parentNode;
var wrapper = document.createElement('div');
// set the wrapper as child (instead of the element)
parent.replaceChild(wrapper, element);
// set element as child of wrapper
wrapper.appendChild(element);
As long as you are not using innerHTML (which destroys and creates elements), references to existing DOM elements are not changed.
Assuming you are doing your manipulation using standard DOM methods (and not innerHTML) then — yes.
Moving elements about does not break direct references to them.
(If you were using innerHTML, then you would be destroying the contents of the element you were setting that property on and then creating new content)
You probably want something like:
var oldParent = document.getElementById('foo');
var oldChild = document.getElementById('bar');
var wrapper = document.createElement('div');
oldParent.appendChild(wrapper);
wrapper.appendChild(oldChild);
In pure JS you can try something like this...
var wrapper = document.createElement('div');
var myDiv = document.getElementById('myDiv');
wrapper.appendChild(myDiv.cloneNode(true));
myDiv.parentNode.replaceChild(wrapper, myDiv);
Here is another example, only the new element wraps around 'all' of its child elements.
You can change this as necessary to have it wrap at different ranges. There isn't a lot of commentary on this specific topic, so hopefully it will be of help to everyone!
var newChildNodes = document.body.childNodes;
var newElement = document.createElement('div');
newElement.className = 'green_gradient';
newElement.id = 'content';
for (var i = 0; i < newChildNodes.length;i++) {
newElement.appendChild(newChildNodes.item(i));
newChildNodes.item(0).parentNode.insertBefore(newElement, newChildNodes.item(i));
}
You will want to modify the 'document.body' part of the newChildNodes variable to be whatever the parent of your new element will be. In this example, I chose to insert a wrapper div. You will also want to update the element type, and the id and className values.
I'm trying to apply CSS to selected text. I tried the following and it doesn't work. I'm using Firefox.
$(document).keyup(function(){
savedRange = selection.getRangeAt(0);
$(savedRange).wrap('<span style="color:red"></span>');
});
I also tried
savedRange = selection.getRangeAt(0);
$(savedRange).css('color', 'red');
I can do this with contentEditable using execcommand, but execcommand applies html tags rather then inline styles. ex: <font/> instead of style="font..". I need to apply inline style and not deprecated html tags. I would like to use the jQuery css() property to apply styles.
I'd recommend the CSS class applier module of my Rangy library for this. It works in all major browsers and for any selection. It will also toggle CSS classes on and off.
Here's an example from another question: How do I wrap a text selection from window.getSelection().getRangeAt(0) with an html tag?
Example:
<style type="text/css">
span.red {
color: red;
}
</style>
<script type="text/javascript">
var redApplier;
window.onload = function() {
rangy.init();
redApplier = rangy.createCssClassApplier("red", true);
};
function makeSelectionRed() {
redApplier.applyToSelection();
}
</script>
UPDATE
If using classes isn't an option, you could still use a variation on this, although it's slightly roundabout: you could use Rangy to apply a class, and then use jQuery to find spans with this class and add your CSS to each. Here's an example:
function makeSelectionRed() {
var randomCssClass = "rangyTemp_" + (+new Date());
var classApplier = rangy.createCssClassApplier(randomCssClass, true);
classApplier.applyToSelection();
// Now use jQuery to add the CSS colour and remove the class
$("." + randomCssClass).css({"color": "red"}).removeClass(randomCssClass);
}
jsFiddle: http://jsfiddle.net/z2mdw/2/
This question thread about handling saved ranges may help. It doesn't specifically tell you how to add CSS, but it will help you wrap your range, and then you can probably chain a .css() function on top of that.
var range = window.getSelection().getRangeAt(0);
var newNode = document.createElement("span");
range.surroundContents(newNode);
Then you should be able to apply css to that span.
EDIT:
To apply CSS to the range selection, you can do the following. See my working example on jsfiddle.
You can set the CSS style on the span node directly with Javascript:
// Get the selection range
var range = window.getSelection().getRangeAt(0);
// create a new DOM node and set it's style property to red
var newNode = document.createElement('span');
newNode.style.color = "red";
// surround the selection with the new span tag
range.surroundContents(newNode);
Or just surround the range with a span tag, and select that span tag with jQuery to use a nicer .css() syntax.
// get the selection
var range = window.getSelection().getRangeAt(0);
// create a new span node and give it an id 'testing'.
var newNode = document.createElement('span');
newNode.id = "testing";
// wrap the selection range with the <span id="testing"></span> node.
range.surroundContents(newNode);
// select that new node with jquery and use the jQuery .css() method to apply styles.
$("#testing").css("color", "green");
Obviously this javascript is not ideal for reuse as I hard coded an ID into the 2nd example, but hopefully you get the idea for use for your own needs.
Cant you do it with CSS alone?
http://css-tricks.com/overriding-the-default-text-selection-color-with-css/