I have an anchor tag element coming in the html like:
Now in the javascript function, I have written:
function handleEvent(sourceElement, txt) {
console.log(sourceElement);
}
the consoled element is coming as the window in this case.
I tried sourceElement.document.activeElement but it doesnt seem to work in chrome, where it is coming as body element.
I cannot change the structure of the anchor tag to 'onClick' function as this is coming from some other source.
Is there some way to find the calling element in this scenario?
The real answer here is to change the HTML, which you've said you can't do. I'd push back on that if you can. If you're writing the function, and the function name is in the HTML, how is it you can't change the HTML??
But if you really, really can't, you can update the DOM once it's loaded:
var list = document.querySelectorAll('a[href^="javascript:"]');
var x, link;
for (x = 0; x < list.length; ++x) {
link = list[x];
link.onclick = new Function(link.href.substring(11));
link.href = "javascript:;";
}
Live Copy | Live Source
This is fairly naughty, as it uses the Function constructor (which is very much like eval), but if you trust the source of the HTML, that should be okay.
Or of course, if you don't have to use whatever was in the href to start with, just hook up your event handler in the code above and don't use new Function.
try something like this, use jQuery
just select the link tag with your selector
$(function(){
var href = $('a').attr('href');
href = href.replace('javascript:','');
$('a').attr('href','#');
$('a').attr('onclick',href);
})
This is just workaround solution.
If you have access to the js, you could do something like this:
document.addEventListener('DOMContentLoaded', function(){
var link = document.querySelectorAll('a');
link[0].addEventListener('click', function(e){
console.log(e.target);
});
});
With this, you would be just not be doing anything with the inline href event and just be appending your own handler.
And if no other answer here works for you because you can't update the DOM after it's loaded (try doing any of them if you want to modify a squarespace lightbox - not saying it's impossible, but...), here's an out of the box thinking:
Sometimes there will be something hinting where the a href is. So you could use it.
<div class="hint current">
<a href="javascript:handleEvent('.hint')">
In my case, I even knew the hint without needing a parameter, which made things even simpler:
function handleEvent (hint) {
if(!hint) {
hint = $("div.current");
}
hrefElement = $(hint).find('a[href^=javascript]');
}
This of course will make sense if your DOM is constantly being changed by a script you have no access to.
But even if there is nothing hinting on the a href, you still could do something like this:
<a href="javascript:var x=1;handleEvent(1)">
function handleEvent (uniqueId) {
hrefElement = $('a[href^=javascript:var x='+uniqueId);
}
Related
I'll start by apologising as this may seem like or actually be a duplicate, but I've tried every solution I've encountered and none seem to be working for me.
In my HTML I have an iframe referencing another HTML document. With JavaScript, at the press of a list of buttons I insert text into the body of that iframe. I also use JavaScript to maintain focus on the iframe body. The problem is that nothing appears to work for me to get the cursor to move to the end of the text each time I press those buttons, it always moves to the beginning.
One of the solutions I've tried was to add this code to the function that handles my button presses:
iFrameBody.focus();
var content = iFrameBody.innerHTML;
iFrameBody.innerHTML = content;
so the function looks like this:
function typeIn(buttonId) {
var iFrameBody = document.getElementById("iFrame").contentWindow.document.body;
iFrameBody.innerHTML += buttonId;
iFrameBody.focus();
var content = iFrameBody.innerHTML;
iFrameBody.innerHTML = content;
}
Something else I tried was, in the HTML file referenced by my iframe I did:
<body onfocus="this.innerHTML = this.innerHTML;"></body>
I tried several other more complicated solutions that frankly I didn't even quite understand to be honest, all to no avail. Any help would be much appreciated.
I figured it out. The issue was that I was using a body element, writing to it's innerHTML and trying to set focus on the body. By simply using a textarea inside my iFrame instead it became very simple and it only required the simplest code.
This to set focus when the page loads:
window.onload = function () {
var iFrameTextArea = document.getElementById("iFrame").contentWindow.document.getElementById("iFrameTextArea");
iFrameTextArea.focus();
}
And then this to set the button to write to the textarea while maintaining focus:
function typeIn(buttonId) {
var iFrameTextArea = document.getElementById("iFrame").contentWindow.document.getElementById("iFrameInput");
iFrameTextArea.focus();
iFrameTextArea.value += buttonId;
}
Super easy!!
Instead of again using textarea in iframe, u can also solve this by using the following code.
var iframeElement = document.getElementById("iFrame").contentWindow.document.body;
iframeElement.focus();
var len = iframeElement.length ;
iframeElement.setSelectionRange(len, len);
i am working on a mobile website with html,js and css.i have created tag through HTML5 DOM & assigned functions to it. It's not working.
My html code(which i have tried thro' DOM method);
<script>
var addExhibits = document.getElementById('mycontent');
function mytest()
{
var div = document.createElement('div');
div.id = 'rateMe';
var anchor = document.createElement('a');
anchor.id="_1";
anchor.onclick = rateIt(this);
anchor.onmouseover=rating(this);
anchor.onmouseout=off(this);
div.appendChild(anchor);
addExhibits.appendChild(div);
}
</script>
<body><div id='mycontent' title="Rate Me..."></body>
Code(statically created tag - works fine)
<div id="rateMe" title="Rate Me...">
<a onclick="rateIt(this)" id="_1" onmouseover="rating(this)" onmouseout="off(this)"></a>
</div>
rate(this) is a function in external JS(http://reignwaterdesigns.com/ad/tidbits/rateme/)
Your event handler just assign the result of the respective function calls here:
anchor.onclick = rateIt(this);
anchor.onmouseover=rating(this);
anchor.onmouseout=off(this);
I assume you want them to execute in case of the event instead:
var that = this;
anchor.onclick = function(){ rateIt(that); };
anchor.onmouseover = function(){ rating(that); };
anchor.onmouseout= function(){ off(that); };
You don't call your mytest() function anywhere. That's the first thing I see. The other thing is that you are putting your script above your div (mycontent) so the div has not yet been created when your script is read. But I don't completely understand what your aim is here or what exactly your problem is.
You don't need to pass this.
you can access your element inside the function in many ways.
var addExhibits=document.getElementById('mycontent'),
rateIt=function(e){
e=e||window.event;
var target=e.target||e.srcElement;//polyfill for older browser
console.log(this,target);
},
rating=function(e){
console.log(this,e.target);
},
off=function(e){
console.log(this,e.target);
},
mytest=function(){
var div=document.createElement('div'),
a=document.createElement('a');
div.id='rateMe';
a.id="_1"; // id's shouldn't contain _ - & numbers(1st letter) even if it works.
a.onclick=rateIt;
a.onmouseover=rating;
a.onmouseout=off;
div.appendChild(a);
addExhibits.appendChild(div);
};
this way you also don't create memory leaks.
ps.: that external js example you using is written very bad.
to make your example work you need to change the strange me/num/sel variables in the external js with the proper one (this/e.target/e.srcElement).
I have a function to grab a video title from a YouTube json callback, which works - however I'm having issues inserting the variable into an element.
Here is the feed I'm grabbing:
<script type="text/javascript" src="http://gdata.youtube.com/feeds/api/videos/2WNrx2jq184?v=2&alt=json-in-script&callback=youtubeFeedCallback"></script>
The javascript function I'm using:
function youtubeFeedCallback(data) {
var info = data.entry.title.$t;
document.write(info);
}
This works fine, but I'd like to insert it into a div with the ID "box".
Usually I would use the following (and add it to the function - and remove the document.write):
var box = document.getElementById('box');
box.innerHTML = info;
I just cannot get this to work though. What would be the correct way to achieve what I'm trying to do? Thanks
http://jsfiddle.net/b3VYT/
Either make sure that the script is below the element or wrap your code in a document.ready callback so that it is not run until after the DOM is loaded.
http://jsfiddle.net/b3VYT/1
You need to make sure that the element that you are using is declared prior to your script executing:
<div id='test'></div>
<script>
function youtubeFeedCallback(data) {
document.getElementById('test').innerHTML = data.entry.title.$t;
}
</script>
Example
I'm trying my best to learn unobtrusive JavaScript. The code below is an attempt to change an existing practice piece I had with the getArrays function called from within the HTML tag. This is the only version I could get to work. While it's nice that it works, I feel like there may be some unnecessary parts and don't fully understand why I need the last line of code in there (kind of new to the addEventListener stuff). I was working off of the Mozilla DOM reference example and know how to do this in jQuery already. Thanks!
JavaScript:
<script>
function getArrays() {
var ddlValArray = new Array();
var ddlTextArray = new Array();
var ddl = document.getElementById("ddlFlavors");
for (i=0; i<ddl.options.length; i++) {
ddlValArray[i] = ddl.options[i].value;
ddlTextArray[i] = ddl.options[i].text;
alert(ddlValArray[i] + ' ' + ddlTextArray[i]);
}
}
function showArrays() {
var link = document.getElementById("clickHandler");
link.addEventListener("click", getArrays, false);
}
document.addEventListener("DOMContentLoaded", showArrays, false);
</script>
HTML
Select Flavor:
<select id='ddlFlavors'>
<option value="1">Vanilla</option>
<option value="2">Chocolate</option>
<option value="3">Strawberry</option>
<option value="4">Neopolitan</option>
</select>
<br/><br/>
<a id="clickHandler" href="#">Show Flavors</a>
You don't if you structure your HTML / JS correctly.
Move the script tag to the bottom of the body just before the </body> tag and you no longer need to wait for DOMContentLoaded event. The html above it will be parsed prior to the JS being executed.
This CAN cause other caveats but for your example it will work.
<body>
Select Flavor:
<select id='ddlFlavors'>
<option value="1">Vanilla</option>
<option value="2">Chocolate</option>
<option value="3">Strawberry</option>
<option value="4">Neopolitan</option>
</select>
<br/><br/>
<a id="clickHandler" href="#">Show Flavors</a>
<script>
function getArrays() {
var ddlValArray = new Array();
var ddlTextArray = new Array();
var ddl = document.getElementById("ddlFlavors");
for (i=0; i<ddl.options.length; i++) {
ddlValArray[i] = ddl.options[i].value;
ddlTextArray[i] = ddl.options[i].text;
alert(ddlValArray[i] + ' ' + ddlTextArray[i]);
}
}
function showArrays() {
var link = document.getElementById("clickHandler");
link.addEventListener("click", getArrays, false);
}
showArrays();
</script>
</body>
There are many other benefits to placing the scripts at the bottom as well. Read more about them here.
One thing to note: Even though the tags for iframes and images are parsed, the image itself might not be finished downloading, so you will have to wait for that. Also iframe content might not be loaded yet either. However DOMContentLoaded doesn't wait for these either. I just thought it would be nice to note.
Event listeners are crucial to JS. Every time a user interacts with your page, you need to pick-up on that event, and respond to it.
Of course, in this snippet, your functions are assuming there is an element with a given id in the DOM, ready, set and waiting. This might not be the case, that's why you have to wait until JS receives the OK (the DOMReady event).
That's just one, very simple, example of why might use addEventListener. But IMO, event-listeners really come into their own when you start using Ajax calls to add new content to your page as you go along:
Suppose the DOM is ready, but some elements might, or might not be requested later on (depending on user input). In jQuery, you'd use things like this:
$('#foo').on('click',functionRef);
This doesn't require the foo element to be available when this code is run, but as soon as the element is added to the dom, the click events will be dealt with as you desire.
In non-jQ, you'll use addEventListener for that. Because of the event model (see quirksmode for details on propagation and bubbling), the listener needn't be attached to the element directly:
document.body.addEventListener('click',function(e)
{
if ((e.target || e.srcElemet).id === 'foo')
{
//function that deals with clicks on foo element
}
},false);//last param is for bubbling/propagating events
This way, you can bind all events for elements that might be added to the dom asynchronously, without having to check each response of each ajax call...
Let's take it one step further even: delegation. As you can see, in the snippet above, we're listening for all click events that occure somewhere inside the body. That's as near as makes no difference: all clicks, so you don't need to add 101 distinct click listeners for 101 elements, just the one. The only thing you need to do, is write the handler in such a way that it deals with each element accordingly:
document.body.addEventListener('click',function(e)
{
e = e || window.event;
var elem = e.target || e.srcElement;
switch (true)
{
case elem.id === 'foo':
//either code here or:
return fooCallback.apply(elem,[e]);//use another function as though it were the handler
case elem.id.className.match(/\bsomeClass\b/):
return someClassCallback.apply(elem,[e]);//~= jQuery's $('.someClass').on('click',function);
case elem.type === 'text':
//and so on
}
},false);
Pretty powerful stuff. There is, of course, a lot more too it, and there are downsides too (mainly X-browser stuff), but the main benefits are:
Handling events for elements that are dynamically added/removed
A single event listener that deals with all events for all elements makes your code more efficient, sometimes boosting performance by a lot. here's a nice example of when delegation is in order, sadly, it also shows the pains that X-browser development brings to the party...
This line of code: document.addEventListener("DOMContentLoaded", showArrays, false); ensures that your function showArrays() doesn't start executing before the DOM is ready. In other words, the function showArrays() will start executing after the (X)HTML document has been loaded and parsed.
I'd recommend that you put your JavaScript code in a separate file and use the following HTML code in the head section: <script type="text/javascript" src="yourfilepath.js"></script>. Then you could also use window.onload and onclick events instead of the document.addEventListener() method.
When you do that, you can put the code within the showArrays function outside its body and remove the function.
For example:
window.onload = function()
{
var link = document.getElementById("clickHandler");
link.onclick = getArrays;
}
That is considered a much better practice.
Full Example
In script.js file:
//This is the beginning of the script...
function getArrays() {
var ddlValArray = new Array();
var ddlTextArray = new Array();
var ddl = document.getElementById("ddlFlavors");
for (i=0; i<ddl.options.length; i++) {
ddlValArray[i] = ddl.options[i].value;
ddlTextArray[i] = ddl.options[i].text;
alert(ddlValArray[i] + ' ' + ddlTextArray[i]);
}
}
window.onload = function()
{
var link = document.getElementById("clickHandler");
link.onclick = getArrays;
}
Inside your HTML head:
<script type="text/javascript" src="script.js"></script>
It's better to write JavaScript separate from the HTML file in most cases, just like CSS. That way, you make your HTML code look tidier and more organised.
First, the background:
I'm working in Tapestry 4, so the HTML for any given page is stitched together from various bits and pieces of HTML scattered throughout the application. For the component I'm working on I don't have the <body> tag so I can't give it an onload attribute.
The component has an input element that needs focus when the page loads. Does anyone know a way to set the focus to a file input (or any other text-type input) on page load without access to the body tag?
I've tried inserting script into the body like
document.body.setAttribute('onload', 'setFocus()')
(where setFocus is a function setting the focus to the file input element), but that didn't work. I can't say I was surprised by that though.
EDIT:
As has been stated, I do indeed need to do this with a page component. I ended up adding file-type inputs to the script we use for giving focus to the first editable and visible input on a page. In researching this problem I haven't found any security issues with doing this.
<script>
window.onload = function() {
document.getElementById('search_query').select();
//document.getElementById('search_query').value = '';
// where 'search_query' will be the id of the input element
};
</script>
must be useful i think !!!
This has worked well for me:
<script>
function getLastFormElem(){
var fID = document.forms.length -1;
var f = document.forms[fID];
var eID = f.elements.length -1;
return f.elements[eID];
}
</script>
<input name="whatever" id="maybesetmaybenot" type="text"/>
<!-- any other code except more form tags -->
<script>getLastFormElem().focus();</script>
you can give the window an onload handler
window.onload = setFocus;
I think you have a fundamental problem with your encapsulation. Although in most cases you could attach an event handler to the onload event - see http://ejohn.org/projects/flexible-javascript-events/ by John Resig for how to do this, setFocus needs to be managed by a page component since you can't have two components on your page requiring that they get the focus when the page loads.
Try play with tabstop attribute
First of all, the input file is no the same as the other inputs, you need to keep this in mind.... thats for security reasons. When the input file get focus it should be read only or the browser should popup a dialog to choose some file.
Now, for the other inputs you could try some onload event on some of your elements...(not only the body have the onload event) or you could use inline javascript in the middle of the html. If you put javascript code without telling that is a function it gets executes while the browser reads it. Something like:
<script type="text/javascript">
function yourFunction()
{
...;
};
alert('hello world!");
yourFunction();
</script>
The function will be executed after the alert just when the browser reads it.
If you can, you should use jQuery to do your javascript. It will make your live soooo much easy.... :)
With jQuery could be done like this:
$(function() {
$("input:file").eq(0).focus()
})
With plain javascript could be done like this:
var oldWindowOnload = window.onload; // be nice with other uses of onload
window.onload = function() {
var form = document.forms[0];
for(i=0; i < form.length; i++) {
if (form[i].type == "file") {
form[i].focus();
}
}
oldWindowOnload();
}
For more elaborate solution with plain javascript see Set Focus to First Input on Web Page on CodeProject.
Scunliffe's solution has a usability advantage.
When page scripts are loading slowly, calling focus() from "onLoad" event makes a very nasty page "jump" if user scrolls away the page. So this is a more user friendly approach:
<input id="..."></input>
... really small piece of HTML ...
<script>getTheDesiredInput().focus();</script>