I am using the event listener structure like below to do some stuff when the input box loses focus.
But it won't work. What event should I listen to, to get the moment the input box loses the cursor inside it (i.e. user clicks outside of it)?
document.getElementById('div inside which input is located')
.addEventListener( 'blur', function(e){
if(event.target.className=='editInput'){
doStuff(event.target);
}
} , false );
The correct event is onBlur. Look at this code:
<!DOCTYPE html>
<html>
<head>
<title>element</title>
<script type="text/javascript">
function message() {
var text = document.getElementById("test").value;
alert(text);
}
</script>
</head>
<body>
<input type="text" name="test" id="test">
<script type="text/javascript">
document.getElementById("test").onblur=message;
</script>
</body>
</html>
It works and prints the content of the input when it loses focus. Maybe your error is that you attached the event to the div and not to the input?
var input = document.getElementsByTagName('input')[0];
input.onfocus = function() {
this.className = 'highlight';
}
input.onblur = function() {
this.className = '';
}
Setting a handler for the blur event using vanilla Javascript:
You could set the blur event's handler for the specific element "test" in vanilla jQuery using code such as this
document.getElementById("test").onblur= yourEventHandler
You can use the event handler in your question without any modifications. That's that part covered. However, I believe there is more to be said here.
The big picture:
The blur/focus events on text inputs are among the least troublesome events to work with in terms of compatibility across browsers. But if you are going to do any serious development I recommend using a framework such as jQuery, YUI, Dojo, MooTools etc. These will both help you write nicer code and will shield you from compatibility problems.
Unfortunately, the reality web developers have to face is that of many browsers with similar, but not identical behaviours. It is not enough to find a solution that happens to work on a browser we happen to be using at the moment we test the piece of code we have just written. We need to ensure our code works correctly across all browsers our application is targetting. So what happens if you suddenly discover that your way of assigning the blur even does not work on some browser for some specific element but another one does? Do you go everywhere in your code and put if's there? Are you sure you haven't missed anything if you go this route? And then, if you find another problem with another browser do you add another if' and so on and so forth? Maybe you decide to define a function setBlurEventHandler that does what it says on the box and use it everywhere in your code instead of statements such as the above. Do you do that just for the blur event or for pretty much everything you do? It makes sense to do it for other things too. Great. You now have a framework for writting code that is compatible across browsers. If all of us kept our frameworks to ourselves we would be spending a lot of time re-discovering and fixing the same problems. Enter open-source Javascript frameworks. You can just use them taking advantage of the hours of hard labour others put into them, but you can also contribute by reporting bugs, writing code and documentation. Doesn't this make more sense? (Or if at some point in the future you are sure you have a framework based on some very clever ideas, however incomplete, by all means put it out there and see both what you can offer to the community and what the community can do for you ... )
To better drive this point home, let me show you some comments taken from jQuery's source. As I said before, the blur/focus events on text inputs are among the least troublesome events to work with in terms of compatibility across browsers. But how confident are you that you are aware (or remember!) the various browser peculiarities your code has to deal with when the handling of even the most basic and least troublesome events comes with such inline code documentation?
// IE<9 dies on focus/blur to hidden element (#1486)
// IE doesn't fire change on a check/radio until blur; trigger it on click
// This still fires onchange a second time for check/radio after blur.
For the reasons outlined above I recomment against working with the DOM directly.
A better approach using jQuery:
Suppose you had a div called formDiv with three input elements only one of which initially had the editInput class.
<div id=formDiv>
<input type="text" name="test1" id="test1" />
<input type="text" name="test2" id="test2" class='editInput' />
<input type="text" name="test3" id="test3" />
</div>
Using jQuery, you could simply do something like (I copied the actual logic of the event handler from your code):
("#formDiv input").blur(function(){
if(this.className=='editInput'){
doStuff(this.target);
}
});
which I believe is closer to what you wanted to do, than other solutions here. (In your code you were trying to attach the event to the div containing the inputs. I may have misinterpreted your intentions but I thought this was what you wanted.)
You can try this solution with this jsFiddle: http://jsfiddle.net/r7tuT/3/
Some parting thoughts:
There are people that will tell you that this or that framework is better and they may be right. I will only comment that jQuery is the most popular one and is pretty decent. The choice is yours, but as I said I believe you should start using one of these frameworks sooner than later as it will improve the quality of your work, let you do certain things in a blink of an eye and change the way you approach problems. When a framework or programming language does this to you, is a great moment in your life as a coder :-)
Try onblur instead of blur.
blur is a method which causes an object to lose focus, whereas onblur is an event that is raised when the object loses focus.
Related
I tried to have a title that match the context I want my answer for.
I explain myself.
After writting thousand of javascript lines of code (with or without jquery) I finally asked myself if I'm doing it wrong.
Mainly thanks to jQuery adding event/delegating to an element is very easy, but all the example are quiet "easy"; meaning it doesn't take into account that you have a page full of list, button, dynamic things...
So my questions, is:
Once again for a complexe website, with hundred of dynamic pages, ajax navigation, millions of user...
Is there any advantage (beside simplicity) to place a global listener (body or whatever) and let all events bubble up ?
When I look at angular it seems they listen 'ng-click' globally, but I can missthink.
Contexte
<body>
<div>
<ul>
<li><span click="myFunc"></span></li>
</ul>
</div>
</body>
-
Sidenot: I'm using jQuery for presentation/simplicity, but it's global question about js
// Standard binding example
$('span').on('click', func)
vs
// Standard delegation example
$('ul').on('click', 'span', func)
vs
// Dispatcher for 'block'
$('ul').on('click', localDispatcher)
vs
// One (and only one) Global Listener for all click
$(body).on('click', globalDispatcher)
With this example, the 3 first one need to be placed manually, on a dedicated js for this page.
Vs
The last one is just a simple event listener, that will use click attribute to dispatch and can be set just once and for all.
I find the last one very cool, because it remove all the hassle to manage click/selector/dom management. Also I don't have to .off every listener when I change page (ajax navigation).
But I wonder about performance or maybe another problems I can think about (that's why I ask the question :D).
I really wonder how "big web startup" manage this kind of Javascript.
Thanks :)
I'd say no to a global listener since it will make things incredibly confusing and frustrating to organize once the app grows into a considerable size.
Also the performance should be really bad since you are involving elements that will be ignored otherwise.
So stick with element or block level event delegation if you want to feel good about yourself in the future!
Is there a way to change the defalt behaviour of TimyMCE, so that when you insert a link, it renders something like this:
<span onclick="window.open('http://google.com', '_blank', 'location=yes');"></span>
instead of
Ideally, I would like this to be done by the Link button, but it could be done onSubmit.
ADDED:
The reason for doing this (as I know it seems like bad practice) is to be able to port to PhoneGap (using the InAppBrowser plugin), as is not intended for browser use.
Overlooking that this really isn't a good practice, I will assume you have a valid use case for wanting to do such black magic.
But before, a few things to consider:
I would advise you to keep links as links while working in TinyMCE. That way, your users will be able to insert and edit them as usual. Changing them to span elements inside the editor will practically eliminate the ability to edit them without editing the full source. You should probably convert them to span elements outside the editor.
If you're the stubborn type and don't care about #1 or your users, you should note that the default TinyMCE 4 configuration doesn't allow onclick attributes, so you'll need to update extended_valid_elements, otherwise they will be removed during the cleanup process.
There is probably a better way to do what you're trying to do. As #Vic suggested, an event listener would probably be a better option.
Nevertheless, I will humor you. Below is an overview of the process with a working example.
Overview
If you are developing with TinyMCE 3.x, you'll want to tap into the onSaveContent event. If you are using 4.x, use the saveContent event. In both cases, the concept is the same.
This event gets fired whenever the content of the editor is "saved". This happens automatically if TinyMCE is submitted as part of a form, but you can also use tinymce.triggerSave() to force it on all editors at once.
So, simply setup your callback function to replace all links with the evil span alternative. You can use pure JS or TinyMCE's built-in DOM utilities (probably only a good idea if you're already familiar with them), but for clarity (and sanity) it's much easier with jQuery.
Working Example
TinyMCE Fiddle: http://fiddle.tinymce.com/mAdaab/1
This example uses TinyMCE 4
Open your browser's console to see the output
After TinyMCE loads, press the Save button
The resulting HTML will appear in your console
Do with it what you wish, but remember that there probably is a better way.
What you are proposing is a really bad practice (as in not using anchor tags for links) wouldnt it be easier to actually give your link an id or class and attach event listener with javascript and on click prevent default behavour grab the href attribute and use your window.open?
I've inherited someone else's project and am building a work flow diagram for it. Without getting into too many details the person who left was the only person in the web department with advanced programming skills (most people there do production work and some HTML/CSS stuff). The project I inherited was developed in CodeIgniter and leans heavily on JQuery, AJAX and JSON. The flow is a bit confusing hence my outlining it. (I'm getting to the question, bear with me)
Anyway, the manager of this department, let's refer to him as The Tool, won't allow his people to learn any of this stuff. He asked me the other day how it was coming and I said fine except I can't find where one variable is being set, the original developer is using jquery to call some form value to set a path to files (he using #id.val()) but I can't find #id anywhere in the code. The manager replies, eh, I thought you were the PHP guru. As I said, we shall refer to him as The Tool.
Anyway, to stick it to him somewhat I've decided to share these flow pages with people in his group, make them very descriptive and hopefully educational. I'm explaining how when a change is made from a select menu jquery/javascript recognizes that change and fires off related code in JS.
Then it dawned on me that I really didn't know how JS/JQ knew the change had been made. I know the code ($("#id").change()...I have an AppleScript background and in that language there's an idle command, you basically can have a script sit in the background observing and waiting for X to happen (say the user launches Photoshop) and when that event happens the rest of the code is run. Does JS do something similar?
This code:
$("#id").change()
tells jQuery (the "$") to find the element whose "id" value is (in this case) "id", and then to trigger a "change" event on the element. That will cause event handlers registered to look for such events on that element to be run. That's the basis of just about everything you do with JavaScript in a browser: responses to events.
Somewhere, there's probably one of these:
$("#id").change(function() { ... })
$("#id").live('change', function() { ... })
$("#id").bind('change', function() { ... })
There are many ways for the element to have been identified for setting up the event handlers, however, so it may be tricky to find.
In newer versions of chrome you can inspect a html element, and this will also show 'classic' events that are bound to it.
Increasingly good developers are moving to event delegates such as:
http://developer.yahoo.com/yui/3/event/#delegate
Which will likely not show up in Chrome, but should be readable from the code.
How would I go about creating a cross-browser script, that would intercept all events firing on
a page/browser window/DOM-tree (regardless of browser)?
What I'm hoping to accomplish is basically to get a better understanding of the different handling
of events in different browsers; I know the basic theory, but need to see to believe...
ADDED
I'm pretty well versed in both using frameworks, and working with "pure" Javascript.
What I want is sort of :
document.addEventListener('*', function(e){
alert(e.type + ' is happening on ' + e.target), false);
};
The only thing that you can do to play around with is find out all events that exist and create a list of controls each with a different event and then label them accordingly and some alert boxes.
Then you can start firing the events and see how they are executing based on the alert boxes.
In future coding you could also use a JavaScript library that basically changes almost every existing JS code and functions so they they are all cross-browser.
Examples are(order of preference):
MooTools
JQuery
Not required but make life much simpler when it comes to cross-browser and creating fancy controls.
I want to make a form in which I want to automatically give focus to a field. In the old days I learned to always wait doing any DOM manipulation till window.onload has fired, as the DOM might not be ready. Since JQuery the DOMContentReady event has grown famous, which fires (in compliant browsers) somewhat earlier than window.onload.
That still gives a delay between the moment the field is shown and the moment it gets focus (by using document.getElementById("inputfield").focus() in window.onload or after DOMContentReady has been triggered). To minimize that delay, some people suggest using focus() directly after the element in your page, like:
<form name="f">
<input id="q" autofocus>
<script>
if (!("autofocus" in document.createElement("input"))) {
document.getElementById("q").focus();
}
</script>
<input type="submit" value="Go">
</form>
(Example from Dive Into HTML5)
Also, the Google Closure team advices this practice: "the preferred way is to use inline scripts as soon as possible", like another answer on SO states.
I don't want to debate whether this is bad practice or not (in general, I agree with the opinion that content and behaviour should be separated, preferably in separate files). My question is: can this be harmful? For instances, causing error messages in some browsers because the field might still not have been rendered properly (and don't forget mobile browsers). Any advice is appreciated.
No, it is not harmful and it is the (subjective) best way to do it.
Reasons it is the best:
Code executes as soon as successfully possible (instead of waiting for whole DOM, it waits until it reaches a certain element)
Does not rely on DOM events (which still have yet to be standardized)
Reasons it sucks:
Lack of behavioral separation
Difficult to maintain because code will be scattered all over the place
Increased overall page size due to existense of several <script> tags
To be honest, I'd have thought that if you are seeing a delay between the page popping up and the element getting the focus, then that does suggest that your page might just be too large, so reducing that would be your first port of call. I know that I'd be very unhappy if I saw inline code like that. As Josh says, it would be a maintainability nightmare.
However, on the question of it being harmful, I'd have thought that if the browser has processed the script node to run the javascript, then it will also have processed the input node, so it should be available to the code. Therefore I wouldn't expect an error.