Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML: onload 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 completely. 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 onclicks and onmousedowns 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?

like image 482
Li Haoyi Avatar asked Apr 10 '12 00:04

Li Haoyi


People also ask

Does onload only work on body?

onload is most often used within the <body> element to execute a script once a web page has completely loaded all content (including images, script files, CSS files, etc.). However, it can be used on other elements as well (see "Supported HTML tags" below).

Which HTML elements support onload?

onload is an event specific to the body , frame , iframe , img , link , and script elements.

Can I use onload with Div?

The onload event can only be used on the document(body) itself, frames, images, and scripts. In other words, it can be attached to only body and/or each external resource. The div is not an external resource and it's loaded as part of the body, so the onload event doesn't apply there. Save this answer.

Can we use onload for input?

No, there is no such event. In most cases, however, it is best to use the document-wide load (or DOMReady , or jQuery's . ready() ) to start any script operations. The DOM will be fully ready then.


2 Answers

There'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 completely 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.org/en/DOM/Mutation_events

http://help.dottoro.com/ljfvvdnm.php#additionalEvents

http://help.dottoro.com/ljmcxjla.php

http://help.dottoro.com/ljimhdto.php

http://www.bennadel.com/blog/1623-Ask-Ben-Detecting-When-DOM-Elements-Have-Been-Removed-With-jQuery.htm

like image 60
Kamyar Nazeri Avatar answered Oct 13 '22 00:10

Kamyar Nazeri


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 comments 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="comment" >
    <h1> Comment #1 </h1>
   <p> blah blah blah blah blah </p>
    <input  /> <button >Reply </button>
</div>
<div class="comment" >
    <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 .comment > input.

After that the JS appears by itself

$(document).ready(function(){
    var inputs=$('.comment > 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

like image 34
rtpg Avatar answered Oct 13 '22 02:10

rtpg