I have this code that changes the url every time a user clicks a button in the page.
That works great in safari,chrome,firefox but not in IE 7,8,9.
What could be the problem ?
function setNewNavigationUrls(){
var musicParameter;
if (isMusicOn) {
musicParameter='1';
}else{
musicParameter='0';
}
$("a[href='/']").attr('href', '/?music='+musicParameter);
$("a[href='/collection-glamour-feeling']").attr('href', '/collection-glamour-feeling?music='+musicParameter);
$("a[href='/collection-poetic-moments']").attr('href','/collection-poetic-moments?music='+musicParameter);
$("a[href='/about.html']").attr('href','/about.html?music='+musicParameter);
$("a[href='/contact.html']").attr('href', '/contact.html?music='+musicParameter);
}
Thanks
Shani
You probably should be using ".prop()" instead of ".attr()" to set the "href" of your <a> elements.
$("a[href='/']").prop('href', '/?music='+musicParameter);
// ... etc. ...
With jQuery 1.6, the semantics of "attr()" changed considerably. The "href" attribute becomes a property of the DOM node for the element, and therefore it should be set as a property. The "attr()" method now concerns itself with attributes (via "setAttribute()" and "getAttribute()"). Boolean properties like "checked" and "disabled" are treated in a backwards-compatible fashion following jQuery 1.6.1.
You might want to try and replace: if (isMusicOn) to if (typeof isMusicOn !== "undefined") to be sure the statement gets evaluated correctly.
Related
I am trying to target multiple IDs with JavaScript so that I can disable the input field for them. It seems to be pretty straight forward using the following script, but I noticed that on pages where the middle Element does not exist, the script does not disable the 3rd one (as though it just stops working when not finding the second element).
<script>
document.getElementById("id_1").disabled = true;
document.getElementById("id_2").disabled = true;
document.getElementById("id_3").disabled = true;
</script>
So on pages when all 3 IDs exist, the script works perfectly. But on pages where either "id_1" or "id_2" does not exist, the remaining elements are not disabled even if they do exist.
Is there any way around that? Note that I can not create separate scripts for each page because this will go in the footer which is the same for all pages.
Thanks!
You should test for the existence first, then disable it if it exists. I also put the id's in an array to simplify the code.
var ids = ['id_1','id_2','id_3'];
for (var i = 0; i < ids.length; i++) {
var el = document.getElementById(ids[i]);
el && (el.disabled = true);
}
<input id="id_1" value="id_1">
<input id="id_3" value="id_3">
This is because document.getElementById returns null when the element has not been found, so effectively you're causing an exception while trying to set disabled on null. This would be the case when one of the elements are not set in the DOM. What you will have to do is check whether the element has been found correctly then set the element or loop through them all.
TL;DR:
The reason that the script stops working is that it is throwing an error when you try to disable an element that doesn't exist.
In Detail:
document.getElementById() will return null if the element that you tried to find does not exist (Here's the MDN page).
When you try to set the .disabled property to true on null JavaScript will throw a TypeError. Unless you handle that error with a try/catch block it will cause your script to stop executing and the later input elements will not become disabled.
Solution
To fix this you'll want to check that your element actually is an element before trying to set it to disabled. Something like this:
var el = document.getElementById('id_1');
if ('null' !== typeof el) {
el.disabled = true;
}
Is there a way in <select> list, for example, to make onClick activate a JavaScript function that will show the title of the element just as pattern in HTML 5 does?
I want to do that when you click on the <select>, it will activate a JavaScript function that under some condition (doesn’t matter—some if expression) will show a sentence (that I wrote) in a bubble like place (the place that the pattern shows the title when something isn’t according to the pattern (pattern in HTML5)).
You can set a custom validity error on a select element by calling the setCustomValidity method, which is part of the constraint validation API in HTML5 CR. This should cause an error to be reported, upon an attempt at submitting the form, in a manner similar to reporting pattern mismatches. Example:
<select onclick="this.setCustomValidity('Error in selection');
title="Select a good option">
(In practice, you would probably not want to use onclick but onchange. But the question specifically mentions onClick.)
There are problems, though. This only sets an error condition and makes the element match the :invalid selector, so some error indicator may happen, but the error message is displayed only when the form data is being validated due to clicking on a submit button or something similar. In theory, you could use the reportValidity method to have the error shown immediately, but browsers don’t support it yet.
On Firefox, the width of the “bubble” is limited by the width of the select element and may become badly truncated if the longest option text is short. There is a simple CSS cure to that (though with a possible impact on the select menu appearance of course).
select { min-width: 150px }
You might also consider the following alternative, which does not affect the select element appearance in the normal state but may cause it to become wider when you set the custom error:
select:invalid { min-width: 150px }
There is also the problem that Firefox does not include the title attribute value in the bubble. A possible workaround (which may or may not be feasible, depending on context) is to omit the title attribute and include all the text needed into the argument that you pass to setCustomValidity.
A possible use case that I can imagine is a form with a select menu such that some options there are not allowed depending on the user’s previous choices. Then you could have
<select onchange="if(notAllowed(this)) setCustomValidity('Selection not allowed')" ...>
where notAllowed() is a suitable testing function that you define. However, it is probably better usability to either remove or disable options in a select as soon as some user’s choices make them disallowed. Admittedly, it might mean more coding work (especially since you would need to undo that if the user changes the other data so that the options should become allowed again).
In my opinion Jukka's solution is superior however, its fairly trivial to do something approaching what you're asking for in JavaScript. I've created a rudimentary script and example jsFiddle which should be enough to get you going.
var SelectBoxTip = {
init : function(){
SelectBoxTip.createTip();
SelectBoxTip.addListeners();
},
addListeners : function(){
var selects = document.getElementsByTagName("select");
for (var i = 0; i < selects.length; i++){
var zis = selects[i];
if(zis.getAttribute('title')){//only if it has a title
zis.addEventListener("focus", SelectBoxTip.showTip, false);
zis.addEventListener("blur", SelectBoxTip.hideTip, false);
}
}
},
createTip : function(){
tip = document.createElement("div");
tip.id = "tip";
tip.style.position = "absolute";
tip.style.bottom = "100%";
tip.style.left = "0";
tip.style.backgroundColor = "yellow";
document.body.appendChild(tip);
},
showTip : function(e){
this.parentNode.appendChild(tip);
tip.innerHTML=this.title;
tip.style.display="block";
},
hideTip : function(e){
tip.style.display="none";
}
};
SelectBoxTip.init();
I'm currently making a google chrome extension and am using this javascript to change dynamically the background color of the hovered element:
var bindEvent = function(elem ,evt,cb) {
//see if the addEventListener function exists on the element
if ( elem.addEventListener ) {
elem.addEventListener(evt,cb,false);
//if addEventListener is not present, see if this is an IE browser
} else if ( elem.attachEvent ) {
//prefix the event type with "on"
elem.attachEvent('on' + evt, function(){
/* use call to simulate addEventListener
* This will make sure the callback gets the element for "this"
* and will ensure the function's first argument is the event object
*/
cb.call(event.srcElement,event);
});
}
};
bindEvent(document,'mouseover', function(event)
{ var target = event.target || event.srcElement;
/* getting target.style.background and inversing it */
});
bindEvent(document,'mouseout', function(event)
{ var target = event.target || event.srcElement;
/* getting target.style.background and inversing it */
});
and when used with static values, like target.style.background = #FFFFFF; when the cursor hover an element and target.style.background = #00000; when the cursor leave the element, it works perfectly. However, when I try to get the value of target.style.background or even target.style.backgroundColor, I always get rgb(255,255,255), no matter what the background color of the element is.
I know how to convert rgb to hexa and how to inverse it, but if I can't get the initial value of the background, it's useless.
So, my question is: why do var foo = target.style.backgroundColor; always return rgb(255, 255, 255) and how do I get the correct value?
Additional notes: the extension will be ported to other browsers later, so a cross-browser solution would be nice if it is possible.
In my experience, target.style is only populated with inline styling. To get style including css definitions just use the getComputedStyle method. For example
//instead of this
target.style.backgroundColor
//try this
getComputedStyle(target).backgroundColor
*Note that using the getComputedStyle method returns a read-only object, and target.style should still be used to set the background color.
You can't use .style to get settings that haven't been defined using .style or style="". Most browsers implement other ways for getting at current style calculations, these are a minefield of oddities however.
Internet explorer has .currentStyle, whereas the rest tend to implement .getComputedStyle. It would be a good idea to read up on these two subjects, to see their implementation — however, as I have said retrieving style settings is a much more complicated process than it first seems.
Even jQuery's css method only returns settings that have been specifically determined on that element i.e. no inheritance.
The following could be of use however:
http://upshots.org/javascript/jquery-get-currentstylecomputedstyle
The only reliable way I know of is to associate a CSS class or ID with a colour, then extract that from an anchor in a hidden element, or simply from empty anchor tag with the class applied. Otherwise it really is about knowing what that colour is and having it already stored as a value somewhere. My HTML would be the following for this solution:
<style>
a:hover,
a#yourChosenIdName {
background-color:#00FF00;
}
</style>
<!-- -->
<script>
var el = document.getElementById('yourChosenIdName'),
getStyle = el.currentStyle ? el.currentStyle : getComputedStyle(el),
hoverBackgroundColor = getStyle.backgroundColor;
//do something with background-color
</script>
My javascript is
function changeImage(imgID) {
var baseurl = "media/images/";
if (document.getElementById(imgID).src == baseurl+"selection-off.png") {
alert('Success');
document.getElementById(imgID).src = baseurl+"selection-no.png"; }
else {
alert('Fail'); } }
and my HTML is
<div id="mustard" class="checkbox"><img id="mustard-img" class="no-off" src="media/images/selection-off.png" alt="checkbox" onClick="changeImage('mustard-img')" /></div>
I always get Fail when clicking the image. I must be missing something really elementary.
Some browsers convert the img src to the full url (including http://www....)
try alerting it to make sure..
You could use the
document.getElementById(imgID).src.indexOf( baseurl+"selection-off.png" ) >= 0
which checks if one string is contained in the other..
Alert string document.getElementById(imgID).src. It might be taking complete path i.e. including host name while the string you are comparing with has relative path.
I tried your code on my own server.
Result:
document.getElementById(mustard-img).src is
'http://localhost/webfiles/media/images/selection-off.png'
baseurl+"selection-off.png" is 'media/images/selection-off.png'
baseurl seems to show the relative url only.
So that is the reason why "Fail" gets alerted.
Try with the following code:
<div id="mustard" class="checkbox"><img id="mustard-img" class="no-off" src="media/images/selection-off.png" alt="checkbox" onClick="changeImage(this)" /></div>
<script>
function changeImage(img) {
if (img.src.indexOf('selection-off.png')) {
alert('Success');
img.src.replace(/selection-off.png/, 'selection-no.png');
}else{
alert('Fail');
}
}
</script>
The differences with your code:
passing the img reference: this instead of the id in the onclick function
use indexOf instead of ==, for relative paths
Are you sure the DOM is built when the script is loaded ?
It's because the src attribute is changed by the browser. Don't do it that way, the proper way to check and change the css class or style attribute instead.
Image-based checkboxes are quite common, but here is the full solution.
1) Render actual checkboxes first. These work for 100% of browsers.
2) When the page loads, place your "image checkbox" next to the checkbox and hide the checkbox
3) When the image is clicked, toggle the checkbox and use the hidden checkbox to ascertain the state of the image.
When the form is POST-ed, the checkboxes will act like normal checkboxes. If JavaScript is disabled or otherwise not available the form is still usable.
I'm having an impossibly hard time finding out to get the actual DOMElement from a jQuery selector.
Sample Code:
<input type="checkbox" id="bob" />
var checkbox = $("#bob").click(function() { //some code } )
and in another piece of code I'm trying to determine the checked value of the checkbox.
if ( checkbox.eq(0).SomeMethodToGetARealDomElement().checked )
//do something.
And please, I do not want to do:
if ( checkbox.eq(0).is(":checked"))
//do something
That gets me around the checkbox, but other times I've needed the real DOMElement.
You can access the raw DOM element with:
$("table").get(0);
or more simply:
$("table")[0];
There isn't actually a lot you need this for however (in my experience). Take your checkbox example:
$(":checkbox").click(function() {
if ($(this).is(":checked")) {
// do stuff
}
});
is more "jquery'ish" and (imho) more concise. What if you wanted to number them?
$(":checkbox").each(function(i, elem) {
$(elem).data("index", i);
});
$(":checkbox").click(function() {
if ($(this).is(":checked") && $(this).data("index") == 0) {
// do stuff
}
});
Some of these features also help mask differences in browsers too. Some attributes can be different. The classic example is AJAX calls. To do this properly in raw Javascript has about 7 fallback cases for XmlHttpRequest.
Edit: seems I was wrong in assuming you could not get the element. As others have posted here, you can get it with:
$('#element').get(0);
I have verified this actually returns the DOM element that was matched.
I needed to get the element as a string.
jQuery("#bob").get(0).outerHTML;
Which will give you something like:
<input type="text" id="bob" value="hello world" />
...as a string rather than a DOM element.
If you need to interact directly with the DOM element, why not just use document.getElementById since, if you are trying to interact with a specific element you will probably know the id, as assuming that the classname is on only one element or some other option tends to be risky.
But, I tend to agree with the others, that in most cases you should learn to do what you need using what jQuery gives you, as it is very flexible.
UPDATE: Based on a comment:
Here is a post with a nice explanation: http://www.mail-archive.com/jquery-en#googlegroups.com/msg04461.html
$(this).attr("checked") ? $(this).val() : 0
This will return the value if it's checked, or 0 if it's not.
$(this).val() is just reaching into the dom and getting the attribute "value" of the element, whether or not it's checked.