My normal way of performing javascript transforms on lots of elements in via JQuery:
<div class="cow"></div>
<script> $(".cow").doStuff() </script>
However, this operation is fragile and brittle: it works on the assumption that the page is all loaded only once. Once you start getting into Ajax and partial reloads, this sort of global transform breaks down pletely. It also doesn't work if the server wants to do a different transform to each element based on some serverside data.
I know the actual onload
event for non-body
elements doesn't work. One solution is to give all the elements IDs/classes and reference them immediately using JQuery:
<div id="cow"></div>
<script> $("#cow").doStuff() </script>
However, that is really messy; I do not like it at all, partly because every element I give an ID pollutes the global I namespace. I am currently giving the element an effectively non-collidable ID
<div id="id877gN0icYtxi"></div>
<script> $("#id877gN0icYtxi").doStuff() </script>
based on random base64 numbers. However, this all seems like a giant hack: I can give the elements onclick
s and onmousedown
s and such very simply using their respective attributes, which then call a function to transform the given this
.
Now, I know onload
doesn't work. However, is there any way to simulate its functionality? Specifically, I want to be able to run javascript code referencing a particular tag using this
without having to assign the tag an ID to them.
EDIT: Essentially I want something like
<input onclick="alert('moo')"/>
but for oncreate; my current use case is to fill an input
or textarea
with text, and I am currently doing:
<input id="id877gN0icYtxi"/>
<script>$("#id877gN0icYtxi").val(...)</script>
where the ...
is different for every input box, and thus cannot be done easily using a "global" jquery transform. On the other hand, I cannot just set the value
or attribute of the input
when i create it, as it may be a textarea
, and i wouldn't know. I want to do something like:
<input onload="$(this).val(...)"/>
Which doesn't work, but I wish it did. Again, the ...
is set by the server and different for every input
tag on the page.
EDIT2:
I'm well aware of hour JQuery is typically used to do whole-document transforms on lots of elements in the same way. The issue is that in this case, each element is being transformed in a way specific to that element, dictated by the server. The specific use case is each field has its contents pre-filled in by $().val()
, and naturally every field will be filled with different contents. Giving each element a unique ID and using JQuery to do a global search to find that element again seems like an incredibly roundabout way of doing things, and of course breaks when you start Ajaxing parts of your page in and out.
EDIT3:
In short, i want to be able to write
<div onload="javascriptFunction(this)"/>
and have javascriptFunction()
be run on when the <div>
is created (whether it is on the initial page or inserted via ajax) and be passed the <div>
as a parameter. Just as onclick
would run javascriptFunction()
with <div>
as a parameter when the div is clicked, I want the same thing to happen, but when the <div>
is created/inserted into the DOM.
I'm willing to accept any amount of setup scripts in the <head>
in order to make this happen. For reasons mentioned above, I am not willing to add any <script>
tags after the <div>
, or to add a class
or id
to the <div>
. Given these limitations, what's the best that can be done to simulate an onload
attribute for non-body elements?
My normal way of performing javascript transforms on lots of elements in via JQuery:
<div class="cow"></div>
<script> $(".cow").doStuff() </script>
However, this operation is fragile and brittle: it works on the assumption that the page is all loaded only once. Once you start getting into Ajax and partial reloads, this sort of global transform breaks down pletely. It also doesn't work if the server wants to do a different transform to each element based on some serverside data.
I know the actual onload
event for non-body
elements doesn't work. One solution is to give all the elements IDs/classes and reference them immediately using JQuery:
<div id="cow"></div>
<script> $("#cow").doStuff() </script>
However, that is really messy; I do not like it at all, partly because every element I give an ID pollutes the global I namespace. I am currently giving the element an effectively non-collidable ID
<div id="id877gN0icYtxi"></div>
<script> $("#id877gN0icYtxi").doStuff() </script>
based on random base64 numbers. However, this all seems like a giant hack: I can give the elements onclick
s and onmousedown
s and such very simply using their respective attributes, which then call a function to transform the given this
.
Now, I know onload
doesn't work. However, is there any way to simulate its functionality? Specifically, I want to be able to run javascript code referencing a particular tag using this
without having to assign the tag an ID to them.
EDIT: Essentially I want something like
<input onclick="alert('moo')"/>
but for oncreate; my current use case is to fill an input
or textarea
with text, and I am currently doing:
<input id="id877gN0icYtxi"/>
<script>$("#id877gN0icYtxi").val(...)</script>
where the ...
is different for every input box, and thus cannot be done easily using a "global" jquery transform. On the other hand, I cannot just set the value
or attribute of the input
when i create it, as it may be a textarea
, and i wouldn't know. I want to do something like:
<input onload="$(this).val(...)"/>
Which doesn't work, but I wish it did. Again, the ...
is set by the server and different for every input
tag on the page.
EDIT2:
I'm well aware of hour JQuery is typically used to do whole-document transforms on lots of elements in the same way. The issue is that in this case, each element is being transformed in a way specific to that element, dictated by the server. The specific use case is each field has its contents pre-filled in by $().val()
, and naturally every field will be filled with different contents. Giving each element a unique ID and using JQuery to do a global search to find that element again seems like an incredibly roundabout way of doing things, and of course breaks when you start Ajaxing parts of your page in and out.
EDIT3:
In short, i want to be able to write
<div onload="javascriptFunction(this)"/>
and have javascriptFunction()
be run on when the <div>
is created (whether it is on the initial page or inserted via ajax) and be passed the <div>
as a parameter. Just as onclick
would run javascriptFunction()
with <div>
as a parameter when the div is clicked, I want the same thing to happen, but when the <div>
is created/inserted into the DOM.
I'm willing to accept any amount of setup scripts in the <head>
in order to make this happen. For reasons mentioned above, I am not willing to add any <script>
tags after the <div>
, or to add a class
or id
to the <div>
. Given these limitations, what's the best that can be done to simulate an onload
attribute for non-body elements?
- 2 How, exactly, do you intend to identify the tag you're trying to address? There are several ways to translate your criteria into code, but to help you figure out the code, we need to know your criteria first. – dragon Commented Apr 10, 2012 at 0:56
- This stuff docs.jquery./Plugins/livequery claims to do what you want: "Live Query also has the ability to fire a function (callback) when it matches a new element and another function (callback) for when an element is no longer matched." I have not tested it myself. – Alfred Godoy Commented Apr 10, 2012 at 1:07
-
@dragon:
onclick="alert(this)"
is an example of identifying the tag I'm addressing without IDs. I want something similar to reference the element when it is loaded, rather than just when it is clicked – Li Haoyi Commented Apr 10, 2012 at 1:14 - the jquery `live stuff looks interesting; does anyone have any experience using it? – Li Haoyi Commented Apr 10, 2012 at 1:19
-
jquery.live()
is deprecated. Tryjquery.on()
instead. In this case,$('document').on('click', 'a', handler)
– dragon Commented Apr 11, 2012 at 6:48
4 Answers
Reset to default 10 +100There's no such onload
event in DOM spec, however DOM Level 2 spec provides Mutation event types, to allow notification of any changes to the structure of a document, including attr and text modifications, currently only modern browsers support such events and it is buggy in Internet Explorer 9!
However you could use DOMNodeInserted event
to monitor the document for any change:
$(document).live("DOMNodeInserted", function(e){
$(e.target).val(...);
});
You should be careful using Mutation events, at least try to be updated! According to W3C:
Mutation event types has not yet been pletely and interoperably implemented across user agents, A new specification is under development with the aim of addressing the use cases that mutation events solves, but in more performant manner.
I guess if you google the matter, you might find some cross browser/jquery plugin for this, just in case, these links migh help:
https://developer.mozilla/en/DOM/Mutation_events
http://help.dottoro./ljfvvdnm.php#additionalEvents
http://help.dottoro./ljmcxjla.php
http://help.dottoro./ljimhdto.php
http://www.bennadel./blog/1623-Ask-Ben-Detecting-When-DOM-Elements-Have-Been-Removed-With-jQuery.htm
All this depends on what sort of tags you want to work with.
One thing to know is that jQuery lets you select a lot of items at once, so when you do something like $('p')
, that object refers to all the p
nodes.
Doing something like $('p').hide()
hides all the p
nodes.
jQuery selectors are (at least) as powerful as CSS selectors, so you can do some pretty semantic things in single lines.
Imagine if you had something like a list of reply boxes for a ments section or something:
-----------------------------------------
Comment #1
blah blah blah blah blah
[ Text field ] (Reply)
-----------------------------------------
Comment #2
nyark nyark nyark nyark
[ Text field ] (Reply)
-----------------------------------------
Comment #3
ubadabuba
[ Text field ] (Reply)
-----------------------------------------
Comment #4
eeeeeeeeeeeeeeeeeeeeeeeeee?
[ Text field ] (Reply)
So your DOM layout might look something like
<div class="ment" >
<h1> Comment #1 </h1>
<p> blah blah blah blah blah </p>
<input /> <button >Reply </button>
</div>
<div class="ment" >
<h1> Comment #2 </h1>
<p> nyark nyark nyark nyark </p>
<input /> <button >Reply </button>
</div>
so if you want to update all your input fields, to put in a default text, you just need to see that the CSS selector for your fields is .ment > input
.
After that the JS appears by itself
$(document).ready(function(){
var inputs=$('.ment > input ');//references all the input fields defined by this selector
inputs.attr('value','default text');//set the value of the text in the input
})
Example shown here
Giving elements an ID doesn't "pollute the global namespace", it's just a mechanism for referencing elements. You only need an ID for an element that you intend referencing by ID. Giving IDs to other elements isn't harmful, just unnecessary.
You can reference elements by a number of criteria, including class and their position in the DOM (any method in the CSS selectors pool and also DOM relationships—parent, child, sibling, etc.). The method you chose may have advantages and disadvantages depending on how you are using it, there is no inherently "good" or "best" way to do it, just that some methods will suit some cases better than others.
If you want to replace, say, listeners after replacing elements in the DOM, then your for replacing the elements needs to account for that. Event delegation is one strategy, there are others.
What about window.onload()
?