Buttons not displaying images - html

My website was working fine before I added more code and features.
It may be because of the tags around the code.
I would like to know how to fix the buttons with numbers (the Cool Music button works fine).
My website is here
<script>
function btnClicked()
{
var audio = new Audio('http://a.tumblr.com/tumblr_lkfhhpM4M41qcmhugo1.mp3');
audio.playbackRate = 2.5;
audio.loop = true;
audio.play();
}
function changeImage1()
{
document.getElementById("image").src= "https://media0.giphy.com/media/sIIhZliB2McAo/200.gif";
}
function changeImage2()
{
document.getElementById("image").src= "https://www.clicktorelease.com/code/gif/1.gif";
}
function changeImage3()
{
document.getElementById("image").src= "http://www.kizoa.com/img/e8nZC.gif";
}
function changeImage4()
{
document.getElementById("image").src= "http://www.netanimations.net/flying_pig_by_rutabaga.gif";
}
</script>
<button onclick="btnClicked()">
Cool Music
</button>
<button onclick="changeImage1()">1</button>
<button onclick="changeImage2()">2</button>
<button onclick="changeImage3()">3</button>
<button onclick="changeImage4()">4</button>

This is not exactly an answer. But this could lead you to the answer.
You have document.getElementById("image").src="<some url>"; in your changeImage functions. But you don't have any DOM element with ID as image. Please check your console and you can find the error yourself.

You're trying to access an element called Image, but from looking through your code I can't find an element with the id of Image.
In the console it shows: "Uncaught TypeError: Cannot set property 'src' of null". This means that it couldn't find the DOM element you are referencing.

You are using document.getElementById("image") but looking at your source code, there is no element with the ID image.

Related

Setting inner html of a DIV after it is added to body tag

I am working on a form widget on Elementor on WordPress, when the user submits the submit button of the form, it will show a pop-up which is created by elementor. The pop-up actually is a DIV tag including my HTML code which I wrote in an HTML widget into the pop-up, as below, and this DIV will be added by some Elementor function to the body tag of the page dynamically when user presses submit button.
<div id="calenderchooser01" style="min-height:100px;"></div>
<script>
function calenderchooser(){
var calenderhtml="";
var numofunits = document.getElementById("form-field-field_numberunits");
if(numofunits.value>=15){
calenderhtml = "<div class='calendly-inline-widget' style='min-width:320px;width:100%;height:650px;'>over 15</div>";
}else if(numofunits.value<15){
calenderhtml = "<div class='calendly-inline-widget' style='min-width:320px;width:100%;height:650px;'>less than 15</div>";
}
document.getElementById("calenderchooser01").innerHTML = calenderhtml;
console.log(calenderhtml);
}
document.getElementById("thisisanidcustom").addEventListener("click",
calenderchooser
);
</script>
thisisanidcustom is the id of submit button form. Also, I tested it with assigning showing of this pop-up to a normal button.
In both cases when I press the button it shows error on the Chrome console:
Uncaught TypeError: Cannot set property 'innerHTML' of null
at HTMLAnchorElement.calenderchooser (9a48896437a750ba11b18d8323f96ea7.js:59)
it references this line :
document.getElementById("calenderchooser01").innerHTML = calenderhtml;
and I think it says that the div#calenderchooser01 does not exist.
I think maybe the function call occurs before adding the DIV to the body tag. but I have not access to Elementor default functions to edit them and say after popup occurs call the calenderchooser(). so in this situation how can I call the function calenderchooser() right after popups shows up. I also thought of something like an event listener on DIV existing change state if available but found nothing.
this worked for me using window.setTimeout() method:
<div id="over15" class='calendly-inline-widget' style='min-width:320px;width:100%;height:650px;display:none'>over 15</div>
<div id="less15" class='calendly-inline-widget' style='min-width:320px;width:100%;height:650px;display:none'>less than 15</div>
<script>
function functionCall(){
setTimeout(calenderchooser, 100);
}
function calenderchooser(){
var numofunits = document.getElementById("form-field-field_numberunits");
if(numofunits.value>=15){
document.getElementById("over15").style.display = "block";
console.log("over15");
}else if(numofunits.value<15){
document.getElementById("less15").style.display = "block";
console.log("less15");
}
}
document.getElementById("thisisanidcustom").addEventListener("click", functionCall
);
</script>

"document.getElementbyId" isn't working for me

I have a button in my page
<button onclick="document.getElementById('donation').style.visibility='visible'">Support</button>
That I want to have linked to making a hidden div (donation) visible. I'm not sure if the getElementById works with divs, but I couldn't find out either, because when I changed the Id to h1, with a simple color change for style, it didn't work either.
Is there a problem with my button or syntax?
You can still work this with an inline onclick.
Andrei is correct about the id needing to be an individual.
<button onclick="document.getElementById('donation').style.visibility='visible'">Support</button>
<div style="background-color: gray; width: 50px; height: 50px; visibility: hidden;" id="donation"></div>
Technically though, it's better to keep your css and javascript in the head tag or outside of the html.
In order for document.getElementById('donation') to return a DOM element this condition would need to be true
there should be one html element and only one with id="donation" in your page. For example: <div id="donation"></div>
It's possible that your function works flawlessly (you can easily tell if it is by looking at your browser console after you pushed the button) but your element would still remain not visible. For example, if its display property is set to none. There are many possible reasons why an element might not be rendered by the browser. The fastest way to pinpoint the reason would be for you to create a minimal, complete and verifiable example (using the <> button) where we could experience the issue.
For me, I think separating the codes will keep things clearer and readable.
<button id="donation_btn">Support</button>
The javascript
function enableDonation( button, donationElement ) {
// check if the button is defined
if ( button != undefined
&& button != null ) {
button.addEventListener( "click", function () {
donationElement.style.display = "block";
});
}
// execute the code on document load
window.addEventListener( "load", function () {
enableDonation(
document.getElementById( "donation_btn" ),
document.getElementById( "donation" )
);
});

One page html static mutlilanguage

I have a school assignment to create a one page html static.
I want to have some buttons to change the language but I don't want any addition like "index.html/en/" or "index.html?lang=en". I prefer to have it with CSS only but I don't know whether it is possible or not.
In short I just want a simply bilingual "index.html" and have buttons to change the content text.
I am new in html scripting so I'm looking for some sample code or some detailed tutorial will be help.
I suggest using JS/jQuery for that:
Have language mapping for each element that will be translated:
// Translations object:
var translations = {
'en': {
'home': 'Home',
'back': 'Back'
/* ... */
},
'lt': {
'home': 'Pradžia',
'back': 'Atgal'
/* ... */
}
};
// wait for all DOM elements to load
$(document).ready(function() {
// when button is clicked
$('.lang-btn').click(function() {
// take translations subset
var lang = translations[$(this).data('lang')];
// for each element that has "data-key" attribute
$('[data-key]').each(function() {
// change it's content to other language
$(this).text(lang[$(this).data('key')]);
})
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="my-page">
Language:
<button class="lang-btn" data-lang="en">En</button>
<button class="lang-btn" data-lang="lt">Lt</button>
<hr/>
Home
<button data-key="back">Back</button>
</div>
This code is not checking if there is such translation or not. You can improve this algo with fallback to English.
For SEO reasons I'd prefer to use /en/. Use a .htaccess file with mod_rewrite.
See here Create beautiful url’s with mod_rewrite
If it is just one page, so I assume the contain is not much. Try something simpler like:
function en() {
document.getElementById("content").innerHTML = "Example";
}
function de() {
document.getElementById("content").innerHTML = "Beispiel";
}
<div id="content">sample</div>
<button onclick="en()">English</button>
<button onclick="de()">German</button>

Disabled button is clickable on Edge browser

I have problem with Edge browser. In my web site I have buttons with span tags inside them. In this span tags I bind text and icons. So far I had no problem but on Edge browser it is possible to click on disabled buttons. After investigating problem I found out that, when button contains span tags inside, it is possible to click on button. Here is how it looks on my web site:
<button id="btnRefresh" type="button" class="btn btn-primary" ng-click="refresh()" ng-disabled="performingAction">
<span ng-class="performingAction && action == 'refresh' ? 'fa fa-cog fa-spin' :'fa fa-refresh'"></span>
<span>{{ refresh }}</span>
</button>
Here is example to testing:
<button type="button" disabled="disabled" onclick='alert("test");'>
<span>Click me!</span>
</button>
One option would be to hide buttons instead of disabling, but I prefer to disable them. Please suggest solution to over come this issue.
Just set
pointer-events: none;
for disabled buttons.
Here's CSS to disable all disabled elements everywhere:
*[disabled] {
pointer-events: none !important;
}
pointer-events documentation
This is a bug in Microsoft Edge. Disabled buttons accept clicks if they contain any HTML elements (i.e. if they contain anything else than just text).
Reported multiple times via Microsoft Connect:
Event bubbles from child element into element (by SO user Ryan Joy)
Bootstrap/Jquery disabled buttons generate click events and show tooltips even disabled
The bug was still present in Build 10565 (16 October 2015).
It was fixed in the November update, Build 10586.
A possible (but ugly) workaround is to call some Javascript in onclick for every button, which then checks if the button is disabled and returns false (thus suppressing the click event).
One work around I've come up with using angularjs is inspired by Ben Nadel's blog here
So for example:
angular.module('myModule').directive(
"span",
function spanDirective() {
return ({
link: function (scope, element, attributes) {
element.bind('click', function (e) {
if (e.target.parentNode.parentNode.disabled || e.target.parentNode.disabled) {
e.stopPropagation();
}
})
},
restrict: "E",
});
}
);
Since you're not always going to be using a span element and probably don't want to create a new directive for every element type, a more general workaround would be to decorate the ngClick directive to prevent the event from reaching the real ngClick's internal event handler when the event is fired on a disabled element.
var yourAppModule = angular.module('myApp');
// ...
yourAppModule.config(['$provide', function($provide) {
$provide.decorator('ngClickDirective', ['$delegate', '$window', function($delegate, $window) {
var isEdge = /windows.+edge\//i.test($window.navigator.userAgent);
if (isEdge) {
var directiveConfig = $delegate[0];
var originalCompileFn = directiveConfig.compile;
directiveConfig.compile = function() {
var origLinkFn = originalCompileFn.apply(directiveConfig, arguments);
// Register a click event handler that will execute before the one the original link
// function registers so we can stop the event.
return function linkFn(scope, element) {
element.on('click', function(event) {
if (event.currentTarget && event.currentTarget.disabled) {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
}
});
return origLinkFn.apply(null, arguments);
};
};
}
return $delegate;
}]);
}]);

How to remove a shadow root from an HTML element adorned with a Shadow DOM from a template?

I'm exploring imports, templates, shadow DOM and custom elements in Chrome Canary (33.0.1712.3). In a grid layout I have a particular content element (region of the display) that will display different web components or cloned light DOM fragments imported from files.
However, I'm unable to redisplay ordinary HTML DOM once a shadow DOM has been added because I don't know how to remove the shadow root. Once created, the shadow root remains and interferes with the rendering of ordinary DOM. (I've looked at various W3C specs such as intro to web components, shadow DOM, templates, Bidelman's articles on HTML5 Rocks, etc.) I've isolated the problem in a simple example below:
Click "show plain old div"; click "show shadowed template"; click "show plain old div". Inspect in devtools after each click. After the third click, there is no output below the buttons and in devtools I am seeing:
<div id="content">
#document-fragment
<div id="plaindiv">Plain old div</div>
</div>
What do I need to add to removeShadow() to remove the shadow root and fully reset the content element to its initial state?
removing_shadows.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<template id="shadowedTemplateComponent">
<style>
div { background: lightgray; }
#t { color: red; }
</style>
<div id="t">template</div>
<script>console.log("Activated the shadowed template component.");</script>
</template>
<template id="plainDiv">
<div id="plaindiv">Plain old div</div>
</template>
</head>
<body>
<div>
<input type="button" value="show plain old div" onclick="showPlainOldDiv()"/>
<input type="button" value="show shadowed template" onclick="showShadowTemplate()"/>
<div id="content"></div>
</div>
<script>
function removeChildren(elt) {
console.log('removing children: %s', elt);
while (elt.firstChild) {
elt.removeChild(elt.firstChild);
}
}
function removeShadow(elt) {
if (elt.shadowRoot) {
console.log('removing shadow: %s', elt);
removeChildren(elt.shadowRoot); // Leaves the shadow root property.
// elt.shadowRoot = null; doesn't work
// delete elt.shadowRoot; doesn't work
// What goes here to delete the shadow root (#document-fragment in devtools)?
}
}
function showPlainOldDiv() {
console.log('adding a plain old div');
var host = document.querySelector('#content');
removeChildren(host);
removeShadow(host);
var template = document.querySelector('#plainDiv');
host.appendChild(template.content.cloneNode(true));
}
function showShadowTemplate() {
console.log('adding shadowed template component');
var host = document.querySelector('#content');
removeChildren(host);
removeShadow(host);
var template = document.querySelector('#shadowedTemplateComponent');
var root = host.shadowRoot || host.webkitCreateShadowRoot();
root.appendChild(template.content.cloneNode(true));
}
</script>
</body>
</html>
The spec of Shadow DOM moved from v0 to v1.
One of the changes is that in v1 there is no way to create shadow root on itself and the host element may contain only one shadow root.
So it seems like the answer of replacing the shadow root with a new blank shadow root is not valid anymore.
Solution paths:
if the host element self (div in your example) has no special value beside holding that Shadow DOM, one can just replace the host element as a whole
if one still likes to preserve the host, clearing the Shadow DOM with something like e.shadowRoot.innerHTML = '' might be sufficient
You can't remove a shadow root once you add it. However, you can replace it with a newer one.
As mentioned here, http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-301/, the newest shadow root "wins" and becomes the rendered root.
You can replace your shadow root with a new shadow root that only contains the <content> pseudo-element to insert everything from the light DOM back into the shadow DOM. At that point, as far as I know it will be functionally equivalent to having no shadow DOM at all.
rmcclellan is correct that you cannot truely "remove" a ShadowRoot v2. But, you can fake it.
The OuterHTML PARTIAL Solution
elementWithShadowDOMv2.outerHTML = elementWithShadowDOMv2.outerHTML;
HOWEVER, there is a major caveat: although there is no visual change, elementWithShadowDOMv2 still refers to the destroyed element with the ShadowDOMv2 as if elementWithShadowDOMv2.parentNode.removeChild( elementWithShadowDOMv2 ) were called. This also "removes" event listeners on the element. Observe the demo below.
var addShadowHere = document.getElementById("add-shadow-here");
addShadowHere.addEventListener("mouseenter", function() {
addShadowHere.style.border = '2em solid blue';
});
addShadowHere.addEventListener("mouseleave", function() {
addShadowHere.style.border = '';
});
var shadow = addShadowHere.attachShadow({mode:"open"});
var button = shadow.appendChild(document.createElement("button"));
button.textContent = "Click Here to Destroy The ShadowDOMv2";
button.addEventListener("click", function() {
addShadowHere.outerHTML = addShadowHere.outerHTML;
update();
});
update();
function update() {
// This just displays the current parent of the addShadowHere element
document.getElementById("parent-value").value = "" + (
addShadowHere.parentNode &&
addShadowHere.parentNode.cloneNode(false).outerHTML
);
}
<div id="add-shadow-here">Text Hidden By Shadow DOM</div>
addShadowHere.parentNode => <input readonly="" id="parent-value" />
Notice how the blue border stops working after you remove the ShadowDOM. That is because the event listeners are no longer registered on the new element: the event listeners remain registered on the old element that has now been removed from the DOM.
Thus, you must refresh any references to the element and reattach any event listeners. Here is an example of how you could reobtain a reference to the new element.
function removeShadowWithCaveat(elementWithShadow) {
if (!elementWithShadow.parentNode) return elementWithShadow.cloneNode(true);
var parent = elementWithShadow.parentNode;
var prior = elementWithShadow.previousSibling;
elementWithShadow.outerHTML = elementWithShadow.outerHTML;
return prior.nextSibling || parent.firstChild;
}
If you need access to the elements which are naturally hidden by the existing shadow root and which will become exposed after the expulsion of the shadow root, then here is an alternative method that will perfectly preserve these nodes.
function removeShadowWithCaveat(elementWithShadow) {
if (!elementWithShadow.parentNode) return elementWithShadow.cloneNode(true);
var ref = elementWithShadow.cloneNode(true);
while (elementWithShadow.lastChild) ref.appendChild( elementWithShadow.lastChild );
elementWithShadow.parentNode.replaceChild(elementWithShadow, elementWithShadow);
return ref;
}
Working Solution
var createShadowProp = (
"createShadowRoot" in Element.prototype ? "createShadowRoot" : "webkitCreateShadowRoot"
);
function removeChildren(elt) {
console.log('removing children: %s', elt);
while (elt.firstChild) {
elt.removeChild(elt.firstChild);
}
}
function removeShadowWithCaveat(elementWithShadow) {
if (!elementWithShadow.parentNode) return elementWithShadow.cloneNode(true);
var ref = elementWithShadow.cloneNode(true);
while (elementWithShadow.lastChild) ref.appendChild( elementWithShadow.lastChild );
elementWithShadow.parentNode.replaceChild(elementWithShadow, elementWithShadow);
return ref;
}
function showPlainOldDiv() {
console.log('adding a plain old div');
var host = document.querySelector('#content');
removeChildren(host);
// Remove the shadow
host = removeShadowWithCaveat(host);
var template = document.querySelector('#plainDiv');
host.appendChild(template.content.cloneNode(true));
}
function showShadowTemplate() {
console.log('adding shadowed template component');
var host = document.querySelector('#content');
removeChildren(host);
// Remove the shadow
host = removeShadowWithCaveat(host);
var template = document.querySelector('#shadowedTemplateComponent');
var root = host.shadowRoot || host[createShadowProp]({
"open": true
});
root.appendChild(template.content.cloneNode(true));
}
<div>
<input type="button" value="show plain old div" onclick="showPlainOldDiv()"/>
<input type="button" value="show shadowed template" onclick="showShadowTemplate()"/>
<div id="content"></div>
</div>
<template id="shadowedTemplateComponent" style="display:none">
<style>
div { background: lightgray; }
#t { color: red; }
</style>
<div id="t">template</div>
<script>console.log("Activated the shadowed template component.");</script>
</template>
<template id="plainDiv" style="display:none">
<div id="plaindiv">Plain old div</div>
</template>
Also note the misuse of vendor prefixes (a problem that far too many developers have issues with). You are correct that, at the time that this question was asked, there was only the prefixed version of createShadowRoot (which was webkitCreateShadowRoot). Nevertheless, you must ALWAYS check to see if the unprefixed createShadowRoot version is available in case if browsers standardize the API in the future (which is now the case). It might be nice to have your code working today, but it's awesome to have your code working several years from now.
In Chrome:
Press F12, DevTool will open
Click gear icon in DevTool
Uncheck "show user agent shadow DOM" checkbox
Enjoy !