Text on button doesn't change after doing innerHTML - javascript

When using JQuery, some ui elements such as dropdownboxes or buttons will NOT UPDATE their ui automatically if you change their value with javascript. Although the value is correctly updated, on screen it looks like nothing changed. To fix this, Jquery requires the use of a "refresh" method after changing the value. On this page you can find the info and syntax: http://jquerymobile.com/test/docs/forms/docs-forms.html (scroll down to "refreshing form elements)
I have problems with the text not updating correctly on some html elements, especially buttons and list boxes (select/option). It's supposed to do so automatically, but sometimes the text just stick to its previous value. The value of the text or innerHTML is correct though, it's just not visible.
Here is the problem with the button.I use Javascript to get the innerHTML and change it.
HTML markup:
<button id="btn" onclick"simple_function">A</button>
Javascript:
function simple_function()
{
var anArray = aFunctionThatReturnAnArray();
document.getElementById("btn").innerHTML = anArray[0];
}
By using alert messages I can see the values before and after a change. These alert messages are correct: the value after clicking is indeed the value of anArray[0], but the text of the button in my browser does not change, it stays on "A".
What's frustrating about this button is that sometimes the text does change, but only the first time I change the html (this happens right before the button is displayed the first time to the user). Additional calls of the function afterwards don't change the text anymore. However, the innerHTML IS changed, as verified by an alert message. So everything keeps 'working' but the users will not know what they're actually clicking on because the text of the button isn't visible changed.
I fixed this by using a < span > as the innerHTML for the button, and changing the innerHTML of the span to the value in the array. This works: everytime the innerHTML is changed, it is visible on the screen. Although I have a solution, it's only a work around and I'm curious as to what could cause this?
I have a similar problem with a list box. The default value is "daily". (See full code below).
document.getElementById("interval_list").selectedIndex
and
document.getElementById("interval_list").selectedIndex = 3;
Again, inside the functions the values are always correct, but the text of dropdown stays on daily even if the function says the selectedIndex is 3 (should be "never"). I cannot fix this by adding < span > anywhere, so here I'm stuck.
Some remarks:
There are no duplicate id's in the html (used find to check)
I don't have this problem with buttons in the footer and also never with paragraphs, spans or headers.
I've tried copying similar code in fiddle and wc3's tryit editor: it works there. So it must be something outside of the simple functions that bugs it out?
Checking for browsercompatability: that's not an issue (I don't use
IE).
Full code of list box:
<div class="ui-grid-a">
<div class="ui-block-a">
<p style="padding-right: 1em; padding-top: 0.4em;" align="right">AUTO REMIND</p>
<p style="padding-right: 1em; padding-top: 1em;" align="right">INTERVAL</p>
</div>
<div class="ui-block-b">
<div id="auto_remind_radio_buttons" data-role="controlgroup" data-type="horizontal">
<input type="radio" onclick="document.getElementById('interval_list').selectedIndex = 0;" name="auto_remind_button" id="auto_remind_on" value="male"/>
<label for="auto_remind_on"><img src="images/correct.png" alt="NO" width="26" height="21"></label>
<input type="radio" onclick="document.getElementById('interval_list').selectedIndex = 3;" name="auto_remind_button" id="auto_remind_off" value="female"/>
<label for="auto_remind_off"><img src="images/wrong.png" alt="NO" width="26" height="21"></label>
</div>
<select id="interval_list" name="Single-line ListBox example">
<option id="1" value="1">daily</option>
<option id="2" value="2">weekly</option>
<option id="3" value="4">monthly</option>
<option id="4" value="5">never</option>
</select>
</div>
</div>

document.getElementById("btn").innerHTML=
Watch your case- HTML should be in caps.

More comment than answer. Using the following code:
<button id="b0">b0</button>
<button id="b1" onclick="
document.getElementById('b0').innerHTML = 'foo';
">click me</button>
the innerHTML of the button changes in FF and IE 8, what browser are you using?
Same for your issue with the select, the following works in IE 8 and FF:
<select id="sel0">
<option>Sunday
<option>Monday
<option>Tuesday
<option>Wednesday
</select>
<button onclick="
document.getElementById('sel0').selectedIndex = 1;
">Select Monday</button>
<button onclick="
document.getElementById('sel0').selectedIndex = 3;
">Select Wednesday</button>

Related

Value is generated by onClick event, but it is not inserted into inner HTML. Why?

When I return the value from the javascript function on the onClick event, it is getting inserted but the form refreshes again and I lose the selection and the values that I have inserted.
Why does this happen and how can i avoid it?
Below is a sample of my code:
<form id="lengthConvert">
<p><b>Enter a value : </b></p><input type="number" name="inputValue" />
<p><b>Convert from : </b></p>
<select name="fromUnit">
<option value="Centimeter">Centimeter</option>
<option value="Meter">Meter</option>
<option value="Kilometer">Kilometer</option>
<option value="Miles">Miles</option>
</select>
<p><b>Convert to : </b></p>
<select name="toUnit">
<option value="Centimeter">Centimeter</option>
<option value="Meter">Meter</option>
<option value="Kilometer">Kilometer</option>
<option value="Miles">Miles</option>
</select>
<br/><p id="Output"></p>
<button type="submit" form="lengthConvert" value="Submit" onclick="getElementById('Output').innerHTML=convert()">Convert</button>
</button>
</div>
</body>
</html>
<script>
function convert(){
var value = document.getElementsByName('inputValue')[0].value;
var fromUnit= document.getElementsByName('fromUnit')[0].value;
var toUnit= document.getElementsByName('toUnit')[0].value;
if(fromUnit==toUnit){
return value;
}
}
</script>
when I am returning the value from the javascript method on onclick event, it is getting inserrted but the form refreshes again and I am loosing all the selection and values which i have inserted.
Why? and how can i avoid that?
When you click the button you're submitting your form because you're not doing anything to stop the default behavior. Change
<button type="submit"...
to
<button type="button"...
As a side note, your HTML needs to be fixed as you have an extra </button>, no closing </form>, and an unopened </div>. Also, your function doesn't appear to do any actual conversion.
You need to do two things:
Pass event object from onclick() function
Prevent form submission inside convert function by using preventDefault();
function convert(e) {
e.preventDefault();
var value = document.getElementsByName('inputValue')[0].value;
var fromUnit = document.getElementsByName('fromUnit')[0].value;
var toUnit = document.getElementsByName('toUnit')[0].value;
if (fromUnit == toUnit) {
return value;
}
}
<form id="lengthConvert">
<p><b>Enter a value : </b></p><input type="number" name="inputValue" />
<p><b>Convert from : </b></p>
<select name="fromUnit">
<option value="Centimeter">Centimeter</option>
<option value="Meter">Meter</option>
<option value="Kilometer">Kilometer</option>
<option value="Miles">Miles</option>
</select>
<p><b>Convert to : </b></p>
<select name="toUnit">
<option value="Centimeter">Centimeter</option>
<option value="Meter">Meter</option>
<option value="Kilometer">Kilometer</option>
<option value="Miles">Miles</option>
</select>
<br/>
<button type="submit" form="lengthConvert" value="Submit" onclick="getElementById('Output').innerHTML=convert(event)">Convert</button>
<div id='Output'></div>
</form>
You are submitting your form, which causes the page to reload, thus wiping out whatever was updated on it prior to the submit. Instead, you'll want to use a regular button (<button type="button">).
But, beyond that, your code is very outdated and inefficient. .getElementsByName() is generally not recommended for performance reasons, but in your case it's even worse because you only want one element, so you're scanning the entire DOM, getting a set of matching elements and then throwing away all but one of them. Use the modern .querySelector() and .querySelectorAll() for most of your DOM searches.
Your HTML is also invalid because you have an extra closing button tag an no closing form tag.
Also, the use of inline event attributes (onclick) should not be used. This is a 25+ year old technique that just won't die because it's easy and people just copy/paste other code they've found that seems to work. There are a lot of reasons not to do this.
There are a number of other concerns in your code as well. Here's your solution, cleaned up and modernized (make sure to see the HTML, CSS, and JS comments):
/* We can style the rows any way we want: */
div.row { margin-top:1em; margin-bottom:1em; font-weight:bold; }
<form id="lengthConvert">
<!--
The us of <p> elements here is really not correct as they mean paragraph, which
itself means "thought or idea". You are just using them for vertical spacing, and
we should not be using HTML for presentation, that's for CSS. Along the same vein,
<b> isn't appropriate here either because you are just using it for presentation.
Instead, a semantically neutral tag like <div> should be used for rows.
CSS classes can be added to control the presentation
-->
<div class="row">Enter a value : </div>
<div class="row">
<!--
Don't use self-termination syntax <tag />.
That syntax is very old an only applies to XHTML, which is not used
very much these days. Adding that syntax buys you nothing.
-->
<input type="number" name="inputValue">
</div>
<div class="row">Convert from :</div>
<div class="row">
<!-- You don't need to set a value for an <option> when
you want the value of an <option> to be the same as
the text of the <option>. The text of the selected
<option> will become the value of the <select> by default.
-->
<select name="fromUnit">
<option>Centimeter</option>
<option>Meter</option>
<option>Kilometer</option>
<option>Miles</option>
</select>
</div>
<div class="row">Convert to :</div>
<div class="row">
<select name="toUnit">
<option>Centimeter</option>
<option>Meter</option>
<option>Kilometer</option>
<option>Miles</option>
</select>
</div>
<div class="row" id="Output"></div>
<!-- The form attribute is only used when a form element is placed outside of the
form it relates to.
Also, don't use inline HTML event attributes.
And, there is no need to add a value attribute unless you want the value
to be something different than the text of the element.
-->
<button type="button">Convert</button>
</form>
<script>
// Get all the element references you know you'll need
let btn = document.querySelector("button[type='button'");
let output = document.getElementById('Output');
// You only have one element with a name of "inputValue". Use
// .querySelector() with a valid CSS selector as an argument
// to find the first item that matches the selector.
// Also, don't assign variables to properties of an element because
// if you ever want to get a second property value, you'll have to
// scan the document all over again for the element. Just store a
// reference to the element itself, then you can access that as often
// as you like.
let input = document.querySelector("input[name='inputValue']");
let fromUnit = document.querySelector("select[name='fromUnit']");
let toUnit = document.querySelector("select[name='toUnit']");
// Set up your event handling in JavaScript, not HTML
btn.addEventListener("click", convert);
function convert(){
console.log(fromUnit.value, toUnit.value);
if(fromUnit.value == toUnit.value){
// Use .textContent when getting/setting text that
// does not contain any HTML. Its's quicker and
// safer.
output.textContent = input.value;
}
}
</script>

JQuery .replaceWith() suddenly putting new element in the wrong place?

This one is really baffling me. I'm using replaceWith() to "clear" a file input field. However, when it replaces it, it puts it back in the wrong place, and I have no idea why. I used the term "suddenly" in the title because what's even more mysterious is that when I stopped working for the weekend the replacement was working exactly as expected. Now I get back to work and suddenly it's not.
Here's the source HTML before calling replaceWith():
<label>Audio</label>
<i style="color:#888888;">MP3 or OGG format recommended</i>
<br>
<button id="clear_audio_input" style="display:none;">Clear</button>
<input type="file" value="" name="source_audio" style="width:300px;">
<br>
<div style="margin-top:15px;">
<b>Current: </b>
<i id="current_audio_source">1360954394_121RuleOfRosePianoEtudeI.mp3</i>
<br>
<input id="source_audio_value" class="required_media" type="hidden" value="1360954394_121RuleOfRosePianoEtudeI.mp3" name="source_audio">
<span id="current_audio_info_a"><input type="checkbox" style="position:relative;top:3px;margin-left:0px;" value="yes" name="source_audio_delete">
Delete current audio?
Current audio will be replaced
Note the location of the FILE input field, named "source_audio". It's immediately after the "Clear" button.
Now, after I call replaceWith(), the HTML looks like this:
<label>Audio</label>
<i style="color:#888888;">MP3 or OGG format recommended</i>
<br>
<button id="clear_audio_input" style="display: none;">Clear</button>
<br>
<div style="margin-top:15px;">
<b>Current: </b>
<i id="current_audio_source">1360954394_121RuleOfRosePianoEtudeI.mp3</i>
<br>
<input type="file" value="" name="source_audio" style="width:300px;">
<input id="source_audio_value" class="required_media" type="hidden" value="1360954394_121RuleOfRosePianoEtudeI.mp3" name="source_audio">
<span id="current_audio_info_a" style="display: inline;"><input type="checkbox" style="position:relative;top:3px;margin-left:0px;" value="yes" name="source_audio_delete">
Delete current audio?
Current audio will be replaced
Notice that it is now several lines down and inside another DIV.
Here is the script that controls the "Clear" button's actions:
$("#clear_audio_input").live("click", function() {
$("input[name='source_audio']").replaceWith($("input[name='source_audio']").val('').clone(true));
$("#source_audio_value").val($("#current_audio_source").text());
$(this).hide();
$("#current_audio_info_a").show();
$("#current_audio_info_b").hide();
checkRequiredMedia();
return false;
});
Here's the basic intended workflow. On load, the clear button is hidden because there is nothing yet to clear. After the user has selected a file, the clear button appears. Clicking the button will clear the file input (by replacing it) and then the button will hide again, essentially returning the form to the same state it was in on load.
Any reason why this oddity is happening (especially since it wasn't happening a few days ago, and I haven't changed anything since then)?
The issue is because you have two inputs with the name source_audio. To get around this, you will need to either give the two inputs fields an id, or change the name.
For example:
$('#my_file_input').replaceWith('<input id="my_file_input" type="file" name="source_audio" />');
$('#my_hidden_file_input').val('');

Why customized radio buttons are not getting disabled?

I am using this plugin to customize check boxes and radio buttons on a page.
These radio buttons are in a div#Main element which comprise of some other HTML elements also. I need to disable everything in this div on a button click (I am using jQuery). For this I have the following code,
HTML
<input type="button" id="DisableElements" value="Disable elements" />
<div id="Main">
<input type="radio" class="styled" name="reg-all"/>
<input type="radio" class="styled" name="reg-all"/>
<select id="MyList">
<option value="1">Choice-1</option>
<option value="2">Choice-2</option>
</select>
<textarea id="Comments" rows="4" cols="5"></textarea>
</div>
Script
$(function(){
$('#DisableElements').click(function(){
$('#Main').find('*').attr('disabled', 'disabled');
});
});
Issue: Everything got disabled correctly except the radio buttons.
Behind the scenes, the plugin script hides the actual radio button and
put a span over the radio buttons like a blanket. This span has
got a background image sprite with different states (on and off) which
gets updated accordingly on radio button selection. This was the
working of this plugin.
I could have used the inbuilt method of the plugin to disable/destroy the functionality but I did not find any method for this.
images loads with little delay after the DOM has finished loading,
so you can try calling your function in $(window).load().
hope it will help.
The solution i made can be thought of as a patch but works nice (for my scenario at least). What should have been the right approach for this would be using some existing API method to reflect the change, something like disable() or similar but i did not find such method or something like this.
Solution: Making the radio buttons appear like disable (non clickable).
Because i do not want to dig into the plugin js file. For this i made a transparent div with some width and height enough to cover the radio buttons and place it over them like a layer between radio buttons and cursor. This div is hidden by default and show this while making controls disable. keeping it short and sweet, here are the code changes.
HTML
<input type="button" id="DisableElements" value="Disable elements" />
<div id="Main">
<div id="Blanket"></div>
<input type="radio" class="styled" name="reg-all"/>
<input type="radio" class="styled" name="reg-all"/>
<select id="MyList">
<option value="1">Choice-1</option>
<option value="2">Choice-2</option>
</select>
<textarea id="Comments" rows="4" cols="5"></textarea>
</div>
CSS - for blanket div
#Blanket
{
position:absolute; /*Imp: otherwise it will disturb the UI*/
width:100px;
height:100px;
display:none;
/* top/left adjustments, if required! */
}
Script
$(function(){
$('#DisableElements').click(function(){
$('#Blanket').show();
$('#Main').find('*').attr('disabled', 'disabled');
});
});
This solution however needed to drop the fear of what if someone using developer tools to out smart the application but that does not matter any way. Besides, you can-not 100% block the user from using such tools.
Another solution which worked and looks more appropriate: Placing invisible blanket over input controls sounds like a patch and can be easily snapped. The plugin script adds a CSS class named styled and requires to add following styles to achieve customized look and feel.
input.styled
{
display: none; // hides the parent input element
}
Because of this, even if we switch button states to disable, the changes did not reflect because the parent element was hidden making the other listeners difficult to attach. By changing the styles to following, everything worked.
input.styled
{
position: absolute;
opacity: 0;
}
It makes the parent input element invisible but completely active on DOM behind the scenes.

How do I make a drop down list selection update an image on a web page?

On the site http://www.gofundme.com/sign-up/ they have the cool ability to select your currency underneath where you enter an amount. When you change the currency it changes the symbol beside the amount you type in.
I'd like to do something similar with my website but don't have much of a clue about how to even go about it. Can anyone point me in the right direction?
Go easy on me guys; I've done a bit of website making before but never anything too spectacular.
The code on that site is all client-side, and is fairly simple.
You click the link, it invokes Javascript that shows the selection popup div.
When you select an item on the selection popup div, it also calls Javascript. That javascript modifies:
The original div's label text for the amount field (i.e. the big €)
The text below that describes your currently selected currency type (the one that pops up the div)
The data in the hidden form field, with the selected currency type
...and closes the popup div.
Edit: Apparently you also need the jQuery library in order to use the code in my answer :) You could substitute your own Javascript code, and get identical results, but it wouldn't look exactly like the code below.
Here is the code, ripped straight off "view source":
The amount box:
<div class="amt_box bg_white">
<label class="currency-display">$</label>
<input type="text" name="Funds[goalamount]" value="" class="big-field"
tabindex="1" />
</div>
The link that opens the popup div:
<h4>Display: US Dollars</h4>
The popup div:
<div class="currency currency-select-div" style="position:absolute; display:none;margin-left:45px;">
<ul>
<li>$ USD Dollar</li>
<li>$ CAD Dollar</li>
<li>$ AUD Dollar</li>
<li>£ GBP Pound</li>
<li>€ EUR Euro</li>
</ul>
</div>
The hidden form field:
<input type="hidden" id="currencyfield" value="USD" name="Organizations[currencycode]" />
The Javascript (jQuery) code that binds it all together:
$('.currency-select').click(function() {
$('.currency-select-div').show();
return false;
});
$('.currency-item').click(function() {
$('.currency-select-div').hide();
$('.currency-display').text($(this).attr('title'));
$('.currency-select').text($(this).text());
$('#currencyfield').val($(this).attr('code'));
You're going to want to uniquely identify the text that you're trying to change with your drop-down list first.
<span id="currencySymbol">$</span>
Then you're going to want to create a drop-down list that has the values you want.
<select id="currencySelect">
<option value="$">Dollars</option>
<option value="£">Pounds</option>
<option value="€">Euros</option>
</select>
Then you need to use JavaScript to change the value of the text based on the value of the drop-down.
document.getElementById('currencySelect').onchange = function(){
document.getElementById('currencySymbol').innerHTML = this.value;
}

Change value of display:none input?

Is it possible to change the value of an <input type="text"> that has been hidden with a style of display:none? I have some JS that seems to work when the input is <input type="hidden"> but not when it's hidden with display:none. And AFAIK, you can't change an input's type with JS either.
Basically, I want to replace an <input> with a <select>, so I'm trying to hide it and append the <select> element.
Take a look at http://jsfiddle.net/5ZHbn/
Inspect the <select> element with firebug. Look at the hidden input beside it. Change the select's value. The hidden input doesn't change. Is Firebug lying to me?
If you uncomment the other lines of code, then it works.
Actually... I'm pretty sure it is a bug in Firebug now. Most other things correctly update, but firebug doesn't show the updated value when I inspect it.
I think it's a Firebug bug.
That's because if i query (via the console) the value of the input-text field it is in fact updated, it's simply that Firebug doesn't reflect the updated value in the html-tab.
In fact, using the dom-tab the new value is there, even if the actual node's value in the html-tab was not updated.
This seems to happen if you use a "normally visible" element (like an input type="text") or similar. If you, instead, use an "normally hidden" element (like an input type="hidden"), Firebug update its value normally.
I think it's a bug in Firebug, that seems to not update an element's value if it is normally visible but now hidden with css: i'm saying specifically this, because an input with type="hidden" and display:none is updated nonetheless, so it's not simply a problem of elements hidden via display:none .
Hope this helps, i'm about to issue this bug to the Firebug guys.
UPDATE: i'm using Firebug 1.8.4 on Firefox 8 on Win Srv 2K3.
Changing a field's value should work as expected, regardless of any CSS styling. The issue is likely elsewhere.
You can change it as usual:
document.getElementById( 'myinput' ).value = 'Hello';
I got this problem when customizing a magento custom option field, I made some rules from some custom select inputs and needed to save the final value to a hidden custom option text field. For some reason, it didn't work if the field was 'display:none' (maybe due some magento's js?), but it worked when I changed to "visibility: hidden;"
I know my answer is to especific, I tried to make a comment but don't have enough reputation. Hope it helps someone.
One option you have is putting the input box inside a div and then using javascript to change the contents of the div. For example:
<html>
<head>
<title>Input Text To Dropdown Box</title>
<script type="text/javascript">
function swap() {
document.getElementById("contentswap").innerHTML = "<select><option value='cats'>Cats</option><option value='dogs'>Dogs</option></select>";
}
</script>
<style>
#contentswap {
display:inline;
}
</style>
</head>
<body
<div id="contentswap">
<input type="text" name="original">
</div>
<br />
<input type="button" value="Input To Select" onClick="swap()">
</body>
</html>
To make changes visible, you can set the value by SetAttribute
var inputs = document.querySelectorAll('input');
var select = document.querySelector('select');
select.onchange = function () {
inputs[0].value = select.value;
inputs[1].setAttribute('value', select.value);
console.log('changed by input.value: ', inputs[0]);
console.log('changed by input.setAttribute: ', inputs[1]);
};
<input type="text" style="display: none;" value="">
<input type="text" style="display: none;" value="">
<select>
<option>Select value</option>
<option value="1">Value 1</option>
<option value="2">Value 2</option>
</select>

Categories