I have a pretty simple function that seems to work fine in Chrome, Firefox, and Safari, but in IE it's breaking. I'm actually trying to load this as a Windows 8 Web App, but from what I've read, that uses a more forgiving version of IE10 to output.
Say I have a <div> (or an <a> with an href...I've tried this as well) like so:
<div onClick="showSection('myTemplate.html');"></div>
This is my function:
function showSection(loca) {
$("#optionView").show();
$("#bookMenu").hide();
$("#optionView").load('settings/'+loca);
$("#settingsButton").attr("onClick","showSettingsMain();");
}
Why wouldn't this work specifically in IE?
A better option, especially since you are using jQuery, is to not use inline event handlers.
Instead, use this HTML:
<div id="main_div"></div>
And use this Javascript:
$(document).ready(function () {
$("#main_div").on("click", function () {
showSection("myTemplate.html");
});
});
This may not solve your problem with IE10, but it's considered better practice...and should work consistently with all browsers.
A few other suggestions:
Instead of using .attr to set the onclick attribute of #settingsButton, you might as well use on again:
$("#settingsButton").on("click", function () {
showSettingsMain();
});
Although I'm not exactly sure if that would have any effect on what the problem is.
Nonetheless, here's an explanation on the difference between attr and prop - .prop() vs .attr()
Also, if you need to specify exactly what URL to use, even on a per-<div> basis, you could use a data-* attribute. Say this is your HTML:
<div class="trigger-div" data-target-url="myTemplate.html"></div>
<div class="trigger-div" data-target-url="myTemplate2.html"></div>
Then you could use:
$(document).ready(function () {
$(".trigger-div").on("click", function () {
var $this = $(this);
var target_url = $this.attr("data-target-url"); // or $this.data("target-url")
showSection(target_url);
});
});
Clicking the first div will use "myTemplate.html", while clicking the second will use "myTemplate2.html".
This way, your data is embedded in your HTML, but your Javascript is unobtrusive.
You are using jQuery wrong, here:
First, bind the event to the div, you'll need to add a class or id for that:
<div id="myEvent"></div>
Then, bind the event:
$('#myEvent').on('click', showSection( 'myTemplate.html') );
And your function:
function showSection(loca) {
$("#optionView").show();
$("#bookMenu").hide();
$("#optionView").load('settings/'+loca);
}
Try that way.
Related
The following is a simple test case to demonstrate what I'm trying to do:
<html>
<head>
<title>Test</title>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
$(":target").css('color', 'red');
});
</script>
<ul>
<li id="one">One</li>
<li id="two">Two</li>
<li id="three">Three</li>
</ul>
</body>
</html>
The idea is to do something through jQuery/Javascript to the targetted item, when something is targetted (for example, test.html#two).
This works as I expect it to in Firefox and IE 10, but not in Chrome, Opera or Safari, which leaves me wondering if this is a bug in some browsers, if what I'm trying to do is somehow wrong, or if I've run afoul of an inadequately precise part of some specification or other.
If I change the jQuery code to do
alert($(":target").length);
it becomes apparent that Chrome, Opera and Safari can't find the :target element during document.ready(), but calling the same code later (via console or function attached to a click event) does find the elements.
When should :target become accessible to JS?
This was posted as a comment but was later removed, you can try waiting for the window load event:
$(window).on('load hashchange', function(){
$(':target').css('color', 'red');
});
This for me produced mixed results on Chrome, it worked when doing a page refresh (F5) but not when hitting enter in the address bar.
I don't know if there's any way to handle this correctly on page load using the :target selector but you could always get the hash value and use it as your selector:
$(window).on('load hashchange', function(){
var target = window.location.hash;
$(target).css('color', 'red');
});
UPDATE
I've been doing some research on the issue plus some tests and I have a couple of insights to share:
First off, we need to understand that when calling $(':target') jQuery internally makes use of querySelectorAll(':target') which means it's directly related to the CSS specification of the pseudo-class, but why isn't working inside document.ready()?
Well, I found that wrapping the code inside setTimeout(fn,0) actually makes the selector available:
$(document).ready(function(){
setTimeout(function(){
$(':target').css('color', 'red'); //THIS WORKS
},0);
});
You can read this answer for an explanation on how adding a zero-ms timeout actually makes a difference, but basically it allows the browser to complete other non-javascript related tasks (in which we would find making the actual CSS pseudo-class available for query). I believe Firefox somehow manages its internal processes differently and that's why the code works there without the need for a timeout.
Now I also discovered that jQuery's internal sizzle selector engine provides a fallback for browsers that do not support CSS :target pseudo-class, which you can use inside document.ready() without issue:
$(document).ready(function(){
$(':target()').css('color', 'red');
});
This works because instead of relying on the CSS class it is a javascript implementation that makes use of the hash property on the window.location object, internally it is defined as follows:
"target": function( elem ) {
var hash = window.location && window.location.hash;
return hash && hash.slice( 1 ) === elem.id;
}
The only think you should note is that this function will go through every element on the page if it's not passed a selector like :target(div), so I believe using the workaround I provided earlier would still be a better option than this.
Because the page is not been reloaded. You need bind it to hashchange:
$(window).on('hashchange', function(){
$(":target").css('color', 'red');
});
http://jsfiddle.net/sXsYx/
Notice that you have much more work to make it right, maybe combine it with $(document).ready
you can use css3 target selector for styling work
:target
{
color:red;
}
Since there is no specialized logic in your example (if statements or such), why don't you just do the styling in CSS? The :target pseudo-class is a CSS3 selector.
:target {
color: red;
}
Note that this will work in all modern browsers, and even some very old browsers (Chrome 1 and Firefox 1.3, for instance), but with Internet Explorer it is only supported starting from version 9.
You can also do it in both places if you wish (CSS and JavaScript), however the JavaScript would seem redundant unless you specifically need IE <= 8 compatibility.
I've noticed that you are using jQuery version 1.10.1, which retains support for IE <= 8. Is that important? If not you can also move to jQuery 2.0.2 (latest version at time of writing).
You should do like this
$("li:target")
This will select the element. This is the better way
Refer this please,
http://api.jquery.com/target-selector/
Or you should remove document ready and put the script at the end of the html document
After a long struggle, I've finally found the only way to clear autofill styling in every browser:
$('input').each(function() {
var $this = $(this);
$this.after($this.clone()).remove();
});
However, I can’t just run this in the window load event; autofill applies sometime after that. Right now I’m using a 100ms delay as a workaround:
// Kill autofill styles
$(window).on({
load: function() {
setTimeout(function() {
$('.text').each(function() {
var $this = $(this);
$this.after($this.clone()).remove();
});
}, 100);
}
});
and that seems safe on even the slowest of systems, but it’s really not elegant. Is there some kind of reliable event or check I can make to see if the autofill is complete, or a cross-browser way to fully override its styles?
If you're using Chrome or Safari, you can use the input:-webkit-autofill CSS selector to get the autofilled fields.
Example detection code:
setInterval(function() {
var autofilled = document.querySelectorAll('input:-webkit-autofill');
// do something with the elements...
}, 500);
There's a bug open over at http://code.google.com/p/chromium/issues/detail?id=46543#c22 relating to this, it looks like it might (should) eventually be possible to just write over the default styling with an !important selector, which would be the most elegant solution. The code would be something like:
input {
background-color: #FFF !important;
}
For now though the bug is still open and it seems like your hackish solution is the only solution for Chrome, however a) the solution for Chrome doesn't need setTimeout and b) it seems like Firefox might respect the !important flag or some sort of CSS selector with high priority as described in Override browser form-filling and input highlighting with HTML/CSS. Does this help?
I propose you avoiding the autofill in first place, instead of trying to trick the browser
<form autocomplete="off">
More information: http://www.whatwg.org/specs/web-forms/current-work/#the-autocomplete
If you want to keep the autofill behaviour but change the styling, maybe you can do something like this (jQuery):
$(document).ready(function() {
$("input[type='text']").css('background-color', 'white');
});
$(window).load(function()
{
if ($('input:-webkit-autofill'))
{
$('input:-webkit-autofill').each(function()
{
$(this).replaceWith($(this).clone(true,true));
});
// RE-INITIALIZE VARIABLES HERE IF YOU SET JQUERY OBJECT'S TO VAR FOR FASTER PROCESSING
}
});
I noticed that the jQuery solution you posted does not copy attached events. The method I have posted works for jQuery 1.5+ and should be the preferred solution as it retains the attached events for each object. If you have a solution to loop through all initialized variables and re-initialize them then a full 100% working jQuery solution would be available, otherwise you have to re-initialize set variables as needed.
for example you do: var foo = $('#foo');
then you would have to call: foo=$('#foo');
because the original element was removed and a clone now exists in its place.
The javascript code below is about half way on my php page, I can't directly modify the radio buttons with IDs q_251_789 and q_251_790 on my page unfortunately, hence why I'm using JS to add attributes to those two radio buttons:
<script><!--
$("#q_249_249").hide();
$("#q249").hide();
$("#q_251_789").attr("onClick","yesClicked();");
$("#q_251_790").attr("onClick","noClicked();");
function yesClicked()
{
$("#q_249_249").show();
$("#q249").show();
$("#addressTable").show();
};
function noClicked()
{
$("#q_249_249").hide();
$("#q249").hide();
$("#addressTable").hide();
};
//--></script>
In Chrome (dev), FF (3.6), and IE8 this all works fine.
In IE6 and IE7 the following two lines of the script do not work but are not producing any errors (According to IE dev tools -> JS debugger):
$("#q_251_789").attr("onClick","yesClicked();");
$("#q_251_790").attr("onClick","noClicked();");
Any ideas what I'm doing wrong?
Or a workaround to achieve the same goal?
Instead of setting an event handler .attr() attach the .click() handlers the unobtrusive way, like this:
$("#q_251_789").click(yesClicked);
$("#q_251_790").click(noClicked);
Or, use anonymous functions like this (the combined selectors is just a shortcut, but unrelated):
$("#q_251_789").click(function () {
$("#q_249_249, #q249, #addressTable").show();
});
$("#q_251_790").click(function () {
$("#q_249_249, #q249, #addressTable").hide();
});
How would I change the below to jquery? It works in IE but not Firefox so I am hoping if I change it to jquery it will work for both.
THIS
function subform() {
if (parent.option_view.document.vform_.dispatchEvent('onsubmit') != false) {
parent.option_view.document.vform_.submit();
}
}
AND THIS
img class="save_bttn" src="/images/save.gif" height="16" width="16" border="0" onclick="subform()"
IS INSIDE ONE CHILD FRAME
and
It is trying to init in another child frame that is why its going to parent option_view.
*note: I was not trying to scream with the caps I was just trying to show where talking was and where the javascript is
Maybe:
$("#vform_").submit();
?
fireEvent is a IE only feature. I don't think including JQuery just to fix this is the best solution. (why add more download time/process time if you can avoid it). Switch to using The W3C equivalent: dispatchEvent.
Take a look at http://www.howtocreate.co.uk/tutorials/javascript/domevents on how to use EventListener...
There are two ways I would suggest you do this, the first with jquery, the second without:
$('.save_bttn').bind('click', function(e) {
if (parent.option_view.document.vform_.dispatchEvent('onsubmit') != false) {
parent.option_view.document.vform_.submit();
}
});
The other is:
<img class="save_bttn" id='somebutton' ... />
document.getElementById('somebutton').onclick = function(e) {
// if(...)
}
I would think that your using this subform() function means that there is something flawed in your approach. I am not certain why you have needed dispatchEvent, as you could have just submitted directly from the onclick event handler, but these should work, or, at least, be close enough so that someone here can correct me. :)
I'd like to change the value of the onclick attribute on an anchor. I want to set it to a new string that contains JavaScript. (That string is provided to the client-side JavaScript code by the server, and it can contains whatever you can put in the onclick attribute in HTML.) Here are a few things I tried:
Using jQuery attr("onclick", js) doesn't work with both Firefox and IE6/7.
Using setAttribute("onclick", js) works with Firefox and IE8, but not IE6/7.
Using onclick = function() { return eval(js); } doesn't work because you are not allowed to use return is code passed to eval().
Anyone has a suggestion on to set the onclick attribute to to make this work for Firefox and IE 6/7/8? Also see below the code I used to test this.
<html>
<head>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var js = "alert('B'); return false;";
// Set with JQuery: doesn't work
$("a").attr("onclick", js);
// Set with setAttribute(): at least works with Firefox
//document.getElementById("anchor").setAttribute("onclick", js);
});
</script>
</head>
<body>
Click
</body>
</html>
You shouldn't be using onClick any more if you are using jQuery. jQuery provides its own methods of attaching and binding events. See .click()
$(document).ready(function(){
var js = "alert('B:' + this.id); return false;";
// create a function from the "js" string
var newclick = new Function(js);
// clears onclick then sets click using jQuery
$("#anchor").attr('onclick', '').click(newclick);
});
That should cancel the onClick function - and keep your "javascript from a string" as well.
The best thing to do would be to remove the onclick="" from the <a> element in the HTML code and switch to using the Unobtrusive method of binding an event to click.
You also said:
Using onclick = function() { return eval(js); } doesn't work because you are not allowed to use return in code passed to eval().
No - it won't, but onclick = eval("(function(){"+js+"})"); will wrap the 'js' variable in a function enclosure. onclick = new Function(js); works as well and is a little cleaner to read. (note the capital F) -- see documentation on Function() constructors
BTW, without JQuery this could also be done, but obviously it's pretty ugly as it only considers IE/non-IE:
if(isie)
tmpobject.setAttribute('onclick',(new Function(tmp.nextSibling.getAttributeNode('onclick').value)));
else
$(tmpobject).attr('onclick',tmp.nextSibling.attributes[0].value); //this even supposes index
Anyway, just so that people have an overall idea of what can be done, as I'm sure many have stumbled upon this annoyance.
One gotcha with Jquery is that the click function do not acknowledge the hand coded onclick from the html.
So, you pretty much have to choose. Set up all your handlers in the init function or all of them in html.
The click event in JQuery is the click function $("myelt").click (function ....).
just use jQuery bind method !jquery-selector!.bind('event', !fn!);
See here for more about events in jQuery
If you don't want to actually navigate to a new page you can also have your anchor somewhere on the page like this.
<a id="the_anchor" href="">
And then to assign your string of JavaScript to the the onclick of the anchor, put this somewhere else (i.e. the header, later in the body, whatever):
<script>
var js = "alert('I am your string of JavaScript');"; // js is your string of script
document.getElementById('the_anchor').href = 'javascript:' + js;
</script>
If you have all of this info on the server before sending out the page, then you could also simply place the JavaScript directly in the href attribute of the anchor like so:
Click me
Note that following gnarf's idea you can also do:
var js = "alert('B:' + this.id); return false;";<br/>
var newclick = eval("(function(){"+js+"});");<br/>
$("a").get(0).onclick = newclick;
That will set the onclick without triggering the event (had the same problem here and it took me some time to find out).
Came up with a quick and dirty fix to this. Just used <select onchange='this.options[this.selectedIndex].onclick();> <option onclick='alert("hello world")' ></option> </select>
Hope this helps