Avoid flickering when changing existing DOM elements on page load event - javascript

I have the following DOM element change function using vanilla JavaScript where I change the span element that contains some text string of the DOM with a page load event.
With the following code, the DOM elements are changed as expected. However, they still see a minimal fraction of flickering before the DOM element change for the variable desktop and mobile.
Example of the flickering scenario:
I see the tag span "Text I want to change" for a fraction of second.
I see the changed tag span "text1 changed" after the content has fully loaded.
I think this is happening because the DOM changes are applied when the DOM content of the page is fully loaded. I would like to hide the existing tag elements until the changes have been applied and then display them.
The elements structure for desktop and mobile I want to manipulate is like the following:
<span class="first-headline target-span">Text I want to change</span>
See the concept below:
var changesObj = {
"us": {
title: "text1 changed"
},
"eu": {
title: "text2 changed"
}
};
function changes() {
var webshop = changesObj[window.location.pathname.split('/')[1]];
console.log(webshop);
var changesText;
if (!webshop) {
console.log('webshop not found');
}
changesText = webshop.title;
if (document.querySelector('.target-span').innerText.length > 0) {
var desktop = document.querySelector('.target-span');
console.log(desktop);
desktop.innerText = changesText;
console.log(desktop.innerText);
console.log("applied changes for dekstop");
}
if (document.querySelector('.target-span').innerText.lenght > 0) {
var mobile = document.querySelector('.target-span');
mobile.innerText = changesText;
console.log(mobile.innerText);
console.log("applied changes for mobile");
}
}
function invokeChanges() {
document.addEventListener("DOMContentLoaded", function () {
changes();
});
}
invokeChanges();
Is there a way to initially hide the DOM element until the change to the existing element has been applied and then show it?
I was thinking of using something inline CSS rules like the following:
Set .style.visbility='hidden' and when the text content is changed to show it with .style.visbility='visble'.
But I'm not sure how this solution should be appropriately implemented in my code.

There are a few reasons as to why it's flickering, but two preventative steps you can take:
Use defer on your script tag <script defer>, as this lets the browser handle the order your scripts are run instead of DOMContentLoaded. You also get to avoid the changes wrapper function.
As suggested by this question (and your own reasoning) attach inline CSS / a CSS file to the page to set the text as invisible, then mark it as visible
If it doesn't affect the layout of your page too much, you can also opt to dynamically generate the element instead.
However, do note that regardless of any of these, these still require JS to be executed and may still have a delay. If you are able to use it, you may be interested in prerendering your webpage - from your JS code, it looks for the route name if its eu or us, which means your page is pre-renderable.

Quick & Dirty:
Place the script tag just below your span tag:
<span class="first-headline target-span">Text I want to change</span>
<script>
var changesObj = {
"us": {
title: "text1 changed"
},
"eu": {
title: "text2 changed"
}
};
function changes() {
var webshop = changesObj[window.location.pathname.split('/')[1]];
console.log(webshop);
var changesText;
if (!webshop) {
console.log('webshop not found');
}
changesText = webshop.title;
if (document.querySelector('.target-span').innerText.length > 0) {
var desktop = document.querySelector('.target-span');
console.log(desktop);
desktop.innerText = changesText;
console.log(desktop.innerText);
console.log("applied changes for dekstop");
}
if (document.querySelector('.target-span').innerText.lenght > 0) {
var mobile = document.querySelector('.target-span');
mobile.innerText = changesText;
console.log(mobile.innerText);
console.log("applied changes for mobile");
}
}
changes();
</script>
This way you avoid the asynchronous code part.

In any case you need to wait until the DOM has been loaded before you can manipulate it. Using an even listener for DOMContentLoaded would be the way to go. So, three things need to happen:
Wait for the DOM to load
Find the elements and change the text
Make the elements visible. You can either use the property visibility: hidden or display: none. Difference is that with visibility: hidden the element will still take up space. So, the choice depends on the context.
In the first example I add a timeout so that you can see what the page looks like just before the text is changed. I also styled the <p> (display: inline-block) so that you can see the size of the hidden span.
window.location.hash = "us"; // for testing on SO
var changesObj = {
"us": { title: "text1 changed" },
"eu": { title: "text2 changed" }
};
function changes(e) {
//let webshop = changesObj[window.location.pathname.split('/')[1]];
let webshop = changesObj[window.location.hash.substring(1)]; // for testing on SO
if (webshop) {
[...document.querySelectorAll('.target-span')].forEach(span => {
span.textContent = webshop.title;
span.classList.add('show');
});
}
}
document.addEventListener('DOMContentLoaded', e => {
setTimeout(changes, 1000);
});
p {
border: thin solid black;
display: inline-block;
}
.target-span {
visibility: hidden;
}
.target-span.show {
visibility: visible;
}
<p>
<span class="first-headline target-span">Text I want to change</span>
</p>
<p>
<span class="first-headline target-span">Text I want to change</span>
</p>
In the second example I combined all the code into one HTML page. Notice that the style is defined in the header. So, when the DOM is passed the CSS will be passed as well without having to load a external style-sheet (well, there are tricks for that as well, but out of scope for this answer).
<html>
<head>
<style>
p {
border: thin solid black;
}
.target-span {
visibility: hidden;
}
.target-span.show {
visibility: visible;
}
</style>
<script>
window.location.hash = "us"; // for testing on SO
var changesObj = {
"us": {title: "text1 changed"},
"eu": {title: "text2 changed"}
};
function changes(e) {
//let webshop = changesObj[window.location.pathname.split('/')[1]];
let webshop = changesObj[window.location.hash.substring(1)]; // for testing on SO
if (webshop) {
[...document.querySelectorAll('.target-span')].forEach(span => {
span.textContent = webshop.title;
span.classList.add('show');
});
}
}
document.addEventListener('DOMContentLoaded', changes);
</script>
</head>
<body>
<p>
<span class="first-headline target-span">Text I want to change</span>
</p>
<p>
<span class="first-headline target-span">Text I want to change</span>
</p>
</body>
</html>

Related

Javascript function works on html onclick but doesn't work html onload [duplicate]

How do you add an onload event to an element?
Can I use:
<div onload="oQuickReply.swap();" ></div>
for this?
No, you can't. The easiest way to make it work would be to put the function call directly after the element
Example:
...
<div id="somid">Some content</div>
<script type="text/javascript">
oQuickReply.swap('somid');
</script>
...
or - even better - just in front of </body>:
...
<script type="text/javascript">
oQuickReply.swap('somid');
</script>
</body>
...so it doesn't block the following content from loading.
You can trigger some js automatically on an IMG element using onerror, and no src.
<img src onerror='alert()'>
The onload event can only be used on the document(body) itself, frames, images, and scripts. In other words, it can be attached to only body and/or each external resource. The div is not an external resource and it's loaded as part of the body, so the onload event doesn't apply there.
onload event it only supports with few tags like listed below.
<body>, <frame>, <iframe>, <img>, <input type="image">, <link>, <script>, <style>
Here the reference for onload event
Try this! And never use trigger twice on div!
You can define function to call before the div tag.
$(function(){
$('div[onload]').trigger('onload');
});
DEMO: jsfiddle
I just want to add here that if any one want to call a function on load event of div & you don't want to use jQuery(due to conflict as in my case) then simply call a function after all the html code or any other code you have written including the function code and
simply call a function .
/* All Other Code*/
-----
------
/* ----At the end ---- */
<script type="text/javascript">
function_name();
</script>
OR
/* All Other Code*/
-----
------
/* ----At the end ---- */
<script type="text/javascript">
function my_func(){
function definition;
}
my_func();
</script>
I needed to have some initialization code run after a chunk of html (template instance) was inserted, and of course I didn't have access to the code that manipulates the template and modifies the DOM. The same idea holds for any partial modification of the DOM by insertion of an html element, usually a <div>.
Some time ago, I did a hack with the onload event of a nearly invisible <img> contained in a <div>, but discovered that a scoped, empty style will also do:
<div .... >
<style scoped="scoped" onload="dosomethingto(this.parentElement);" > </style>
.....
</div>
Update(Jul 15 2017) -
The <style> onload is not supported in last version of IE. Edge does support it, but some users see this as a different browser and stick with IE. The <img> element seems to work better across all browsers.
<div...>
<img onLoad="dosomthing(this.parentElement);" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" />
...
</div>
To minimize the visual impact and resource usage of the image, use an inline src that keeps it small and transparent.
One comment I feel I need to make about using a <script>is how much harder it is to determine which <div> the script is near, especially in templating where you can't have an identical id in each instance that the template generates. I thought the answer might be document.currentScript, but this is not universally supported. A <script> element cannot determine its own DOM location reliably; a reference to 'this' points to the main window, and is of no help.
I believe it is necessary to settle for using an <img> element, despite being goofy. This might be a hole in the DOM/javascript framework that could use plugging.
Avoid using any interval-based methods (as they are not performant and accurate) and use MutationObserver targeting a parent div of dynamically loaded div for better efficiency.
Update: Here's a handy function I wrote. Use it like this:
onElementLoaded("div.some_class").then(()=>{}).catch(()=>{});
/**
*
* Wait for an HTML element to be loaded like `div`, `span`, `img`, etc.
* ex: `onElementLoaded("div.some_class").then(()=>{}).catch(()=>{})`
* #param {*} elementToObserve wait for this element to load
* #param {*} parentStaticElement (optional) if parent element is not passed then `document` is used
* #return {*} Promise - return promise when `elementToObserve` is loaded
*/
function onElementLoaded(elementToObserve, parentStaticElement) {
const promise = new Promise((resolve, reject) => {
try {
if (document.querySelector(elementToObserve)) {
console.log(`element already present: ${elementToObserve}`);
resolve(true);
return;
}
const parentElement = parentStaticElement
? document.querySelector(parentStaticElement)
: document;
const observer = new MutationObserver((mutationList, obsrvr) => {
const divToCheck = document.querySelector(elementToObserve);
if (divToCheck) {
console.log(`element loaded: ${elementToObserve}`);
obsrvr.disconnect(); // stop observing
resolve(true);
}
});
// start observing for dynamic div
observer.observe(parentElement, {
childList: true,
subtree: true,
});
} catch (e) {
console.log(e);
reject(Error("some issue... promise rejected"));
}
});
return promise;
}
Implementation details:
HTML:
<div class="parent-static-div">
<div class="dynamic-loaded-div">
this div is loaded after DOM ready event
</div>
</div>
JS:
var observer = new MutationObserver(function (mutationList, obsrvr) {
var div_to_check = document.querySelector(".dynamic-loaded-div"); //get div by class
// var div_to_check = document.getElementById('div-id'); //get div by id
console.log("checking for div...");
if (div_to_check) {
console.log("div is loaded now"); // DO YOUR STUFF!
obsrvr.disconnect(); // stop observing
return;
}
});
var parentElement = document.querySelector("parent-static-div"); // use parent div which is already present in DOM to maximise efficiency
// var parentElement = document // if not sure about parent div then just use whole 'document'
// start observing for dynamic div
observer.observe(parentElement, {
// for properties details: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit
childList: true,
subtree: true,
});
we can use MutationObserver to solve the problem in efficient way adding a sample code below
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
#second{
position: absolute;
width: 100px;
height: 100px;
background-color: #a1a1a1;
}
</style>
</head>
<body>
<div id="first"></div>
<script>
var callthis = function(element){
element.setAttribute("tabIndex",0);
element.focus();
element.onkeydown = handler;
function handler(){
alert("called")
}
}
var observer = new WebKitMutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
for (var i = 0; i < mutation.addedNodes.length; i++)
if(mutation.addedNodes[i].id === "second"){
callthis(mutation.addedNodes[i]);
}
})
});
observer.observe(document.getElementById("first"), { childList: true });
var ele = document.createElement('div');
ele.id = "second"
document.getElementById("first").appendChild(ele);
</script>
</body>
</html>
In November 2019, I am seeking a way to create a (hypothetical) onparse EventListener for <elements> which don't take onload.
The (hypothetical) onparse EventListener must be able to listen for when an element is parsed.
Third Attempt (and Definitive Solution)
I was pretty happy with the Second Attempt below, but it just struck me that I can make the code shorter and simpler, by creating a tailor-made event:
let parseEvent = new Event('parse');
This is the best solution yet.
The example below:
Creates a tailor-made parse Event
Declares a function (which can be run at window.onload or any time) which:
Finds any elements in the document which include the attribute data-onparse
Attaches the parse EventListener to each of those elements
Dispatches the parse Event to each of those elements to execute the Callback
Working Example:
// Create (homemade) parse event
let parseEvent = new Event('parse');
// Create Initialising Function which can be run at any time
const initialiseParseableElements = () => {
// Get all the elements which need to respond to an onparse event
let elementsWithParseEventListener = document.querySelectorAll('[data-onparse]');
// Attach Event Listeners and Dispatch Events
elementsWithParseEventListener.forEach((elementWithParseEventListener) => {
elementWithParseEventListener.addEventListener('parse', updateParseEventTarget, false);
elementWithParseEventListener.dataset.onparsed = elementWithParseEventListener.dataset.onparse;
elementWithParseEventListener.removeAttribute('data-onparse');
elementWithParseEventListener.dispatchEvent(parseEvent);
});
}
// Callback function for the Parse Event Listener
const updateParseEventTarget = (e) => {
switch (e.target.dataset.onparsed) {
case ('update-1') : e.target.textContent = 'My First Updated Heading'; break;
case ('update-2') : e.target.textContent = 'My Second Updated Heading'; break;
case ('update-3') : e.target.textContent = 'My Third Updated Heading'; break;
case ('run-oQuickReply.swap()') : e.target.innerHTML = 'This <code><div></code> is now loaded and the function <code>oQuickReply.swap()</code> will run...'; break;
}
}
// Run Initialising Function
initialiseParseableElements();
let dynamicHeading = document.createElement('h3');
dynamicHeading.textContent = 'Heading Text';
dynamicHeading.dataset.onparse = 'update-3';
setTimeout(() => {
// Add new element to page after time delay
document.body.appendChild(dynamicHeading);
// Re-run Initialising Function
initialiseParseableElements();
}, 3000);
div {
width: 300px;
height: 40px;
padding: 12px;
border: 1px solid rgb(191, 191, 191);
}
h3 {
position: absolute;
top: 0;
right: 0;
}
<h2 data-onparse="update-1">My Heading</h2>
<h2 data-onparse="update-2">My Heading</h2>
<div data-onparse="run-oQuickReply.swap()">
This div hasn't yet loaded and nothing will happen.
</div>
Second Attempt
The First Attempt below (based on #JohnWilliams' brilliant Empty Image Hack) used a hardcoded <img /> and worked.
I thought it ought to be possible to remove the hardcoded <img /> entirely and only dynamically insert it after detecting, in an element which needed to fire an onparse event, an attribute like:
data-onparse="run-oQuickReply.swap()"
It turns out, this works very well indeed.
The example below:
Finds any elements in the document which include the attribute data-onparse
Dynamically generates an <img src /> and appends it to the document, immediately after each of those elements
Fires the onerror EventListener when the rendering engine parses each <img src />
Executes the Callback and removes that dynamically generated <img src /> from the document
Working Example:
// Get all the elements which need to respond to an onparse event
let elementsWithParseEventListener = document.querySelectorAll('[data-onparse]');
// Dynamically create and position an empty <img> after each of those elements
elementsWithParseEventListener.forEach((elementWithParseEventListener) => {
let emptyImage = document.createElement('img');
emptyImage.src = '';
elementWithParseEventListener.parentNode.insertBefore(emptyImage, elementWithParseEventListener.nextElementSibling);
});
// Get all the empty images
let parseEventTriggers = document.querySelectorAll('img[src=""]');
// Callback function for the EventListener below
const updateParseEventTarget = (e) => {
let parseEventTarget = e.target.previousElementSibling;
switch (parseEventTarget.dataset.onparse) {
case ('update-1') : parseEventTarget.textContent = 'My First Updated Heading'; break;
case ('update-2') : parseEventTarget.textContent = 'My Second Updated Heading'; break;
case ('run-oQuickReply.swap()') : parseEventTarget.innerHTML = 'This <code><div></code> is now loaded and the function <code>oQuickReply.swap()</code> will run...'; break;
}
// Remove empty image
e.target.remove();
}
// Add onerror EventListener to all the empty images
parseEventTriggers.forEach((parseEventTrigger) => {
parseEventTrigger.addEventListener('error', updateParseEventTarget, false);
});
div {
width: 300px;
height: 40px;
padding: 12px;
border: 1px solid rgb(191, 191, 191);
}
<h2 data-onparse="update-1">My Heading</h2>
<h2 data-onparse="update-2">My Heading</h2>
<div data-onparse="run-oQuickReply.swap()">
This div hasn't yet loaded and nothing will happen.
</div>
First Attempt
I can build on #JohnWilliams' <img src> hack (on this page, from 2017) - which is, so far, the best approach I have come across.
The example below:
Fires the onerror EventListener when the rendering engine parses <img src />
Executes the Callback and removes the <img src /> from the document
Working Example:
let myHeadingLoadEventTrigger = document.getElementById('my-heading-load-event-trigger');
const updateHeading = (e) => {
let myHeading = e.target.previousElementSibling;
if (true) { // <= CONDITION HERE
myHeading.textContent = 'My Updated Heading';
}
// Modern alternative to document.body.removeChild(e.target);
e.target.remove();
}
myHeadingLoadEventTrigger.addEventListener('error', updateHeading, false);
<h2>My Heading</h2>
<img id="my-heading-load-event-trigger" src />
use an iframe and hide it iframe works like a body tag
<!DOCTYPE html>
<html>
<body>
<iframe style="display:none" onload="myFunction()" src="http://www.w3schools.com"></iframe>
<p id="demo"></p>
<script>
function myFunction() {
document.getElementById("demo").innerHTML = "Iframe is loaded.";
}
</script>
</body>
</html>
Since the onload event is only supported on a few elements, you have to use an alternate method.
You can use a MutationObserver for this:
const trackElement = element => {
let present = false;
const checkIfPresent = () => {
if (document.body.contains(element)) {
if (!present) {
console.log('in DOM:', element);
}
present = true;
} else if (present) {
present = false;
console.log('Not in DOM');
}
};
const observer = new MutationObserver(checkIfPresent);
observer.observe(document.body, { childList: true });
checkIfPresent();
return observer;
};
const element = document.querySelector('#element');
const add = () => document.body.appendChild(element);
const remove = () => element.remove();
trackElement(element);
<button onclick="add()">Add</button>
<button onclick="remove()">Remove</button>
<div id="element">Element</div>
we can use all these tags with onload
<body>, <frame>, <frameset>, <iframe>, <img>, <input type="image">, <link>, <script> and <style>
eg:
function loadImage() {
alert("Image is loaded");
}
<img src="https://www.w3schools.com/tags/w3html.gif" onload="loadImage()" width="100" height="132">
I really like the YUI3 library for this sort of thing.
<div id="mydiv"> ... </div>
<script>
YUI().use('node-base', function(Y) {
Y.on("available", someFunction, '#mydiv')
})
See: http://developer.yahoo.com/yui/3/event/#onavailable
This is very simple solution and 100% working.
Just load an <img> tag inside the div or at last line of div, if you think you want to execute javascript, after loading all data in div.
As <img> tag supports onload event, so you can easily call javascript here like below:
<div>
<img onLoad="alert('Problem Solved');" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" />
</div>
This above image will show only a single Dot(.), which you even cant see normally.
Try it.
First to answer your question: No, you can't, not directly like you wanted to do so.
May be a bit late to answer, but this is my solution, without jQuery, pure javascript.
It was originally written to apply a resize function to textareas after DOM is loaded and on keyup.
Same way you could use it to do something with (all) divs or only one, if specified, like so:
document.addEventListener("DOMContentLoaded", function() {
var divs = document.querySelectorAll('div'); // all divs
var mydiv = document.getElementById('myDiv'); // only div#myDiv
divs.forEach( div => {
do_something_with_all_divs(div);
});
do_something_with_mydiv(mydiv);
});
If you really need to do something with a div, loaded after the DOM is loaded, e.g. after an ajax call, you could use a very helpful hack, which is easy to understand an you'll find it ...working-with-elements-before-the-dom-is-ready.... It says "before the DOM is ready" but it works brillant the same way, after an ajax insertion or js-appendChild-whatever of a div. Here's the code, with some tiny changes to my needs.
css
.loaded { // I use only class loaded instead of a nodename
animation-name: nodeReady;
animation-duration: 0.001s;
}
#keyframes nodeReady {
from { clip: rect(1px, auto, auto, auto); }
to { clip: rect(0px, auto, auto, auto); }
}
javascript
document.addEventListener("animationstart", function(event) {
var e = event || window.event;
if (e.animationName == "nodeReady") {
e.target.classList.remove('loaded');
do_something_else();
}
}, false);
I am learning javascript and jquery and was going through all the answer,
i faced same issue when calling javascript function for loading div element.
I tried $('<divid>').ready(function(){alert('test'}) and it worked for me. I want to know is this good way to perform onload call on div element in the way i did using jquery selector.
thanks
As all said, you cannot use onLoad event on a DIV instead but it before body tag.
but in case you have one footer file and include it in many pages. it's better to check first if the div you want is on that page displayed, so the code doesn't executed in the pages that doesn't contain that DIV to make it load faster and save some time for your application.
so you will need to give that DIV an ID and do:
var myElem = document.getElementById('myElementId');
if (myElem !== null){ put your code here}
I had the same question and was trying to get a Div to load a scroll script, using onload or load. The problem I found was that it would always work before the Div could open, not during or after, so it wouldn't really work.
Then I came up with this as a work around.
<body>
<span onmouseover="window.scrollTo(0, document.body.scrollHeight);"
onmouseout="window.scrollTo(0, document.body.scrollHeight);">
<div id="">
</div>
Link to open Div
</span>
</body>
I placed the Div inside a Span and gave the Span two events, a mouseover and a mouseout. Then below that Div, I placed a link to open the Div, and gave that link an event for onclick. All events the exact same, to make the page scroll down to bottom of page. Now when the button to open the Div is clicked, the page will jump down part way, and the Div will open above the button, causing the mouseover and mouseout events to help push the scroll down script. Then any movement of the mouse at that point will push the script one last time.
You could use an interval to check for it until it loads like this:
https://codepen.io/pager/pen/MBgGGM
let checkonloadDoSomething = setInterval(() => {
let onloadDoSomething = document.getElementById("onloadDoSomething");
if (onloadDoSomething) {
onloadDoSomething.innerHTML="Loaded"
clearInterval(checkonloadDoSomething);
} else {`enter code here`
console.log("Waiting for onloadDoSomething to load");
}
}, 100);
When you load some html from server and insert it into DOM tree you can use DOMSubtreeModified however it is deprecated - so you can use MutationObserver or just detect new content inside loadElement function directly so you will don't need to wait for DOM events
var ignoreFirst=0;
var observer = (new MutationObserver((m, ob)=>
{
if(ignoreFirst++>0) {
console.log('Element add on', new Date());
}
}
)).observe(content, {childList: true, subtree:true });
// simulate element loading
var tmp=1;
function loadElement(name) {
setTimeout(()=>{
console.log(`Element ${name} loaded`)
content.innerHTML += `<div>My name is ${name}</div>`;
},1500*tmp++)
};
loadElement('Michael');
loadElement('Madonna');
loadElement('Shakira');
<div id="content"><div>
You can attach an event listener as below. It will trigger whenever the div having selector #my-id loads completely to DOM.
$(document).on('EventName', '#my-id', function() {
// do something
});
Inthis case EventName may be 'load' or 'click'
https://api.jquery.com/on/#on-events-selector-data-handler
Here is a trick that worked for me,
you just need to put your div inside a body element
<body>
<!-- Some code here -->
<body onload="alert('Hello World')">
<div ></div>
</body>
<!-- other lines of code -->
</body>
Use the body.onload event instead, either via attribute (<body onload="myFn()"> ...) or by binding an event in Javascript. This is extremely common with jQuery:
$(document).ready(function() {
doSomething($('#myDiv'));
});
You cannot add event onload on div, but you can add onkeydown and trigger onkeydown event on document load
$(function ()
{
$(".ccsdvCotentPS").trigger("onkeydown");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<div onkeydown="setCss( );"> </div>`
Try this.
document.getElementById("div").onload = alert("This is a div.");
<div id="div">Hello World</div>
Try this one too. You need to remove . from oQuickReply.swap() to make the function working.
document.getElementById("div").onload = oQuickReplyswap();
function oQuickReplyswap() {
alert("Hello World");
}
<div id="div"></div>

Is there a way to have active/inactive state on a single link?

I will need to put 2 different actions on a single link which would have an active/inactive state, right now I only know how to do one at the time, something like this (active):
State One
And I would like to have another one on same click (inactive), is there a way to have this dynamically changed? The label shouldn't change, except for color for example - style.
On the other side, it would be a great thing if I could show the list of active items as well, something like:
Active states: State one, State two, State ...
I recommend something other than an A tag for what you're doing. I also recommend the modern equivalent of an onclick, an event listener. I also recommend assigning and toggling the class.
State One
I have removed your onclick and put it into an event listener. I've added a class, so you can toggle it.
function classToggle() {
this.classList.toggle('class123');
this.classList.toggle('class456');
}
This toggles your class, thus allowing you to change the behavior of the link based on the class. Active/Inactive or Class123/Class456 whatever you want to use will work.
document.querySelector('#myDiv').addEventListener('click', classToggle);
This is your listener. It applies the classToggle function on click. You can do this with a div/button/whatever. Personally I'd change the A tag to a Div.
<div id="myElem" class="class123">click here</div>
And here is an example of this stuff working and changing based on the toggle and classes.
function classToggle() {
this.classList.toggle('class123');
this.classList.toggle('class456');
}
document.querySelector('#myElem').addEventListener('click', classToggle);
document.querySelector('#myElem').addEventListener('click', mogrify);
function mogrify(){
if (document.querySelector('#myElem').classList.contains('class123')) {
document.querySelector('#myElem').style.backgroundcolor = "#54C0FF"
document.querySelector('#myElem').innerText = "State Two";
} else {
document.querySelector('#myElem').style.backgroundcolor = "#FF8080"
document.querySelector('#myElem').innerText = "State One";
}
}
.class123 {
color: #f00;
}
.class456 {
color: #00f;
}
State One
I think I got it to work, here's my code, please let me know if good enough.
A href:
State One
js:
<script>
function toggleState(a) {
if ( a.className === 'visible' ) {
HideOneState('state_One', gameInstance);
a.className = '';
} else {
ShowOneState('state_One', gameInstance);
a.className = 'visible';
}
}
</script>
#shandoe2020 has a good answer but here is the "old way" which is pretty easy to understand too. It can be adapted to links (or anything else) quite easily.
<!DOCTYPE html>
<html>
<head>
<style>
.my-button { width:150px; height:150px; }
.my-red { background-color:#ff0000; }
.my-blue { background-color:#0000ff; }
</style>
<script>
/* toggle the state of my-red and my-blue class */
function toggle()
{
/* yeah yeah, hardcoding the item to change is bad */
var elem = document.getElementById("btn")
elem.classList.toggle("my-red")
elem.classList.toggle("my-blue")
}
</script>
</head>
<body>
<div>
<p><button id="btn" class="my-button my-red" onclick="toggle()">Button</button></p>
</div>
</body>
</html>

How to specify with multiple objects in JS?

So I'm trying to make a code that allows me to change the image once I hover over it.
The initial code works. But I have 72 other images to go through with this feature. I'm trying to call each one individually so I don't have to repeat so much code.
I want a simple html code like
<img id="seal" src="img/seal/dantalion.png" onmouseover="rollover(dantalion)"
onmouseout="rollaway(dantalion)" />
<img id="seal" src="img/seal/vassago.png" onmouseover="rollover(vassago)"
onmouseout="rollaway(vassago)" />
Here is the code that works.
function rollover(img) {img.src = "img/seal/hover/vassago.png";}
function rollaway(img) {img.src = "img/seal/vassago.png";}
Here is what I want to do. Keep in mind please, I'm new to this sort of thing.
function rollover() {
dantalion.src = "img/seal/hover/dantalion.png";
vassago.src = "img/seal/hover/vassago.png";
}
function rollaway() {
dantalion.src = "img/seal/dantalion.png";
vassago.src = "img/seal/vassago.png";
}
How do I individually call the object in the HTML code?
This is a simple solution to your problem. On mouseover of the wrapper div #images we check if you are hovering an image and if so, update the image src with the hover url.
On mouseout or if you hover on a different image the images are reset back to the original src
var images = document.getElementById('images');
var prevEl;
function resetImages() {
if (prevEl) {
prevEl.src = prevEl.src.replace('/hover', '');
prevEl = null;
}
}
images.addEventListener('mouseover', function(e) {
resetImages();
if (e.target && e.target.nodeName == "IMG") {
prevEl = e.target;
e.target.src = e.target.src.replace('/seal', '/seal/hover');
}
});
images.addEventListener('mouseout', resetImages);
<div id="images">
<img src="img/seal/dantalion.png">
<img src="img/seal/vassago.png">
</div>
Here's an example using event delegation. I've tried to use only core JS APIs because you didn't mention any libraries but if you were using a library there's a good chance it would be able to do some of this for you.
document.body.addEventListener('mouseover', function(ev) {
var target = ev.target,
cls = target.classList;
if (!cls.contains('seal')) {
return;
}
cls.add('seal-over');
target.innerHTML = target.innerHTML.replace('/seal/', '/seal/hover/');
});
document.body.addEventListener('mouseout', function(ev) {
var target = ev.target,
cls = target.classList;
if (!cls.contains('seal')) {
return;
}
cls.remove('seal-over');
target.innerHTML = target.innerHTML.replace('/hover', '');
});
.seal {
border: 1px dotted #777;
height: 70px;
margin: 10px;
width: 200px;
}
.seal-over {
background: #eee;
}
<div class="seal">img/seal/dantalion.png</div>
<div class="seal">img/seal/vassago.png</div>
While my example changes the innerHTML you would change the src instead - I didn't have your images so I couldn't easily use img tags. The id attribute has to be unique so I've changed it to using a class instead. Adding the seal-over class isn't required, I just thought it made the example more interesting: you'd probably use a CSS :hover pseudo-class for that if this were real code.
One of many guides to delegation, you can find others with a quick search online:
https://davidwalsh.name/event-delegate
The idea is to add a single listener on an element higher up the tree. Events propagate up so you can react to events on descendent elements. The event target refers to the element on which the actual event occurred. The code checks whether this element is one of the elements we care about and then makes the changes accordingly.

Disable/Enable CSS on webpage using Javascript

According to This page I was able to remove all the CSS preloaded and added on the webpage using that. I wanted to implement a button system where "onclick" = enable/disable webpage CSS even the ones pre-loaded by my web-host. I would like to eliminate the style tags to prevent lags for my website users. I prefer using the script that I have linked above unless there is another alternative that works better. Is it possible to enable CSS onclick the same button to disable? If not is it possible, can it be done with this quick? example with the preferred script below:
if (disable) {
style = "disable";
} else {
location.reload();
}
PREFERRED SCRIPT:
function removeStyles(el) {
el.removeAttribute('style');
if(el.childNodes.length > 0) {
for(var child in el.childNodes) {
/* filter element nodes only */
if(el.childNodes[child].nodeType == 1)
removeStyles(el.childNodes[child]);
}
}
}
removeStyles(document.body);
What about a different aproach?
Add initially a class to a body called 'styled' for example
<body class="styled">
use it as a main selector in your css definitions
<style>
.styled a { ... }
.styled h1 { .... }
</style>
then an example jquery script to toggle the class:
<script>
$(function() {
$('#myswitch').click(function() {
$('body').toggleClass('styled');
});
});
</script>
when class is present, the page will be styled, when absent there will be no styling.
Of coures there could be better aproach, but this is the first thing which pops up in my mind
To remove all style on an element, you could do
function removeStyles(el) {
el.style = {};
}
If you want to enable/disable the CSS on the page, then the goal is not to merely remove all the styles on the page, but you will need to save them somewhere also so they can be recalled when the user re-clicks the button. I would recommend having jQuery to help you with this, and it could be done the following way:
var style_nodes = $('link[rel="stylesheet"], style');
style_nodes.remove();
$('*').each(function(num, obj) {
var style_string = $(obj).attr("style");
if (style_string) {
$(obj).data("style-string", style_string);
$(obj).attr("style", "");
}
});
Now you've saved the stylesheets and style DOM nodes inside of style_nodes, and the actual style attribute inside of a jQuery data attribute for that specific DOM node. When you click to add the CSS back to the page, you can do the following:
$('head').append(style_nodes);
$('*').each(function(num, obj) {
if ($(obj).data("style-string"))
$(obj).attr("style", $(obj).data("style-string"));
});
Check out this JS Fiddle I put together to demonstrate it:
https://jsfiddle.net/5krLn3w1/
Uses JQuery, but I'm sure most frameworks should give you similar functionality.
HTML:
<h1>Hello World</h1>
Turn off CSS
Turn on CSS
JS:
$(document).ready(function() {
$('a#turn_off').click(function(evt) {
evt.preventDefault();
var css = $('head').find('style[type="text/css"]').add('link[rel="stylesheet"]');
$('head').data('css', css);
css.remove();
});
$('a#turn_on').click(function(evt) {
evt.preventDefault();
var css = $('head').data('css');
console.info(css);
if (css) {
$('head').append(css);
}
});
});
CSS:
body {
color: #00F;
}
h1 {
font-size: 50px;
}

hide one div when another is showing in jQuery?

I am trying to hide a div when another one is visible.
I have div 1 and div 2.
If div 2 is showing then div 1 should hide and if div 2 is not showing then div 1 should be visible/unhide.
The function would need to be function/document ready upon page load.
I've tried this but I'm not having any luck, can someone please show me how I can do this.
<script>
window.onLoad(function () {
if ($('.div2').is(":visible")) {
$(".div1").fadeOut(fast);
} else if ($('.div2').is(":hidden")) {
$('.div1').fadeIn(fast);
}
});
</script>
Add a class of hidden to each div, then toggle between that class using jQuery. By the way, window.onload is not a function, it expects a string like window.onload = function() {}. Also, put fast in quotations. I don't know if that's required, but that's how jQuery says to do it.
<div class="div1"></div>
<div class="div2 hidden"></div>
.hidden { display: none }
$(document).ready(function() {
if($(".div1").hasClass("hidden")) {
$(".div2").fadeIn("fast");
}
else if($(".div2").hasClass("hidden")) {
$(".div1").fadeIn("fast");
}
});
You should pass a string to the .fadeIn() and .fadeOut() methods.
Instead of .fadeIn(fast) it'll be .fadeIn("fast"). Same for .fadeOut().
And in general since you're already using jQuery it's better to wrap your code like this:
$(function () {
// Code goes here
});
It looks like you're using jquery selectors (a javascript library). If you're going to use jquery make sure the library is loaded properly by including it in the document header (google makes this easy by hosting it for you <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>)
With jQuery loaded you can do it like this
$(document).ready(function(){
if ($('.div1').is(":visible")) {
$('div2').hide();
}
else if ($('.div2').is(":visible")) {
$('div1').hide();
}
});
WORKING EXAMPLE: http://jsfiddle.net/HVDHC/ - just change display:none from div 2 to div 1 and click 'run' to see it alternate.
You can use setTimeout or setInterval to track if these divs exists
$(function() {
var interval = window.setInterval(function() {
if($('#div2').hasClass('showing')) {
$('#div1').fadeOut('fast');
}
if($('#div2').hasClass('hidden')) {
$('#div1').fadeIn('fast');
}
}, 100);
// when some time u don't want to track it
// window.clearInterval(interval)
})
for better performance
var div1 = $('#div1')
, div2 = $('#div2')
var interval ....
// same as pre code

Categories

Resources