Html div on load event for a dynamically added div element - javascript

How i can make some thing like this?
<div id='myDiv' onload='fnName()'></div>
can't use
window.onload = function () {
fnName();
};
or
$(document).ready(function () {fnName();});
the div element is dynamic. The div content is generated by xml xsl.
Any ideas?

You can use DOM Mutation Observers
It will notify you every time the dom changes, e.g. when a new div is inserted into the target div or page.
I'm copy/pasting the exmple code
// select the target node
var target = document.querySelector('#some-id');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true }
// pass in the target node, as well as the observer options
observer.observe(target, config);
// later, you can stop observing
observer.disconnect();

The onload attribute probably wouldn't fire on the <div> if you're injecting it dynamically (as the document is likely already loaded, but maybe it'd still work...?). However you could either poll for the element by simply doing something like this (similar to YUI's onContentAvailable):
// when the document has loaded, start polling
window.onload = function () {
(function () {
var a = document.getElementById('myDiv');
if (a) {
// do something with a, you found the div
}
else {
setTimeout(arguments.callee, 50); // call myself again in 50 msecs
}
}());
};
Or you could change the markup (I know nothing about XSL) to be something like this:
Earlier on in the page:
<script type="text/javascript">
function myDivInserted() {
// you're probably safe to use document.getElementById('myDiv') now
}
</script>
The markup you generate with XSL:
<div id="myDiv"></div>
<script type="text/javascript">
myDivInserted();
</script>
It's a bit hacky but it should work.

If you're not already using jQuery there's no reason to start using it just for this, you can write:
window.onload = function () {
fnName();
};

You could use jQuery. The following code would be place in your <head> tags.
$(document).ready(function() {
// Your fnNamt function here
});
EDIT
Kobi makes a good point
You could also write
$(document).ready(function(){fnNamt();});,
or more simply,
$(document).ready(fnNamt);, or even
$(fnNamt)

Without jQuery with plain JS eg:
<script type="text/javascript">
function bodyOnLoad() {
var div = document.getElementById('myDiv');
// something with myDiv
...
}
</script>
<body onload="bodyOnLoad()">
....
<div id='myDiv'></div>
....
</body>

I had the same Issue, and after searching I found this.
In my case, the javascript appends the head of the index html to load a tab content html file, and onload I want to add that tab to the dom, display it and make other js stuff to change the tabs style.
I added the line with .onload = function(event) {...}
var link = document.createElement('link');
link.rel = 'import';
link.href = 'doc.html'
link.onload = function(event) {...};
link.onerror = function(event) {...};
document.head.appendChild(link);
This worked like a charm, and maybe it helps some other researcher :)
I found it on HTML5 Imports: Embedding an HTML File Inside Another HTML File

How about using jQuery/ready(..) for this?
Like here: http://api.jquery.com/ready#fn
In the context of your question,
$(document).ready(function () {fnNamt();});

I would suggest you to use jQuery.
Steps:
1. Download Jquery library from here http://code.jquery.com/jquery-1.5.min.js .
2. in your HTML, head section create a script tag and use this code below.
$(document).ready(function() {
// write your code here..
});

I'd suggest circle-style func:
SwitchFUnc = false;
function FuncName(div_id) {
var doc = window!=null ? window.document : document;
var DivExists = doc.getElementById(div_id);
if (DivExists) {
//something...
SwitchFunc = true; //stop the circle
}
}
while (SwitchFunc!=true) {
FuncName('DivId');
}

Related

Call user defined jQuery function with JS

I use a jQuery window libray https://github.com/humaan/Modaal
which triggers events this way $("class of element").modaal({arg1, arg2,...});
--- I updated my question here to make it more general and used an iframe / Html instead of an external svg ---
To trigger an element e.g. in an external Html which is loaded within an iframe, I applied the following code to the iframe:
<iframe src="External.html" id="mainContent" onload="access()"></iframe>
which calls this function:
function access() {
var html = document.getElementById("mainContent").contentDocument.getElementById("IDofDIVelement");
html.addEventListener('click', function() {clicker();});
}
function clicker()
{
// console.log('hooray!');
$("#mainContent").contents().find("IDofDIVelement").modaal({});
//return false;
}
Actually it will only work on every second click. Any idea what I did not consider properly?
Best
You do not need to wait windows loading but iframe only:
$(function() {
$("#mainContent").bind("load",function(){
var myIframeElement = $(this).contents().find(".modaal");
myIframeElement.modaal({
content_source: '#iframe-content',
type: 'inline',
});
});
});
The reason why it did not work was that the iframe was not completely loaded, while jQuery tried to attach the function. As $(document).ready(function(){} did not work, the workaround was to initialize it with
$( window ).on( "load",function() {
$("#mainContent").contents().find("IDofDIVelement").modaal({});
});
This worked properly to attach the functionallity to an element within the iframe.
Actually modaal will vanish the envent handler after the overlay was opened and closed again.
So maybe someone wants to trigger an iframe element for modaal, too, here is a setup which would solve this issue.
(It can be optimised by #SvenLiivaks answer):
$(window).on("load", function() {
reload();
});
function reload() {
var length = $("#iframeID").contents().find("#IDofDIVelement").length;
// The following check will return 1, as the iframe exists.
if (length == 0) {
setTimeout(function() { reload() }, 500);
} else {
$("#iframeID").contents().find("#IDofDIVelement").modaal({
content_source: '#modalwrapper',
overlay_close: true,
after_close: function reattach() {
reload();
}
});
}
}

cache a DOM element inside an instantaneus function with JQuery [duplicate]

I am having some trouble accessing cached DOM element from the namespace variable. My FeedManager config variable is like this:
var FeedManager = {
config : {
$feedContainer : $('#feedContainer'),
feedUrl : 'http://rss......',
feedLimit : 10
},....
Here the $feedContainer is the ul element in the html. I wanted to add li elements built from the feed. I have a funciton init() inside FeedManager object. But somehow it can not add the child element.
init: function(){
var feed = new google.feeds.Feed(FeedManager.config.feedUrl);
......
......
// this is not working
FeedManager.config.$feedContainer.append(li);
but if inside init() function,I again get the feedContainer element ,it works !
var feedContainer = $('#feedContainer');
feedContainer.append(li);
What can be the problem? and how can I use cached dom element initialzied in my config object.
You'd need to make sure the $('#feedContainer') has already been loaded.
An analogous example:
<script type="text/javascript">
$(function() {
var Manager = {
config: {
$p: $("p#hello")
},
init: function() {
var label = Manager.config.$p.html();
console.log(label);
}
};
Manager.init();
});
</script>
Is your #feedContainer element present in your HTML or is it fetched later? If it is fetched later than you can't cache the element, you'd have to use just a selector string like
feedContainer: '#feedContainer'`
in your FeedManager object and then use something like
$(FeedManager.config.feedContainer).append(li);
If it is present in HTML then make sure that you define your FeedManager object after the DOM is ready, ie. inside of a
$(document).ready(function () {
// ...
});
or $(function () { ... });

Javascript different variable scope on AJAX call

I have a problem with my variable scope in a simple slider script that I´ve written (I don't want to use a readymade solution because of low-bandwidth). The slider script is called on statically loaded pages (http) as well as on content loaded through AJAX. On the statically loaded page (so no AJAX) the script seems to work perfect. However when called through AJAX the methods called can't find the elements of the DOM, which halts the necessay animation that is needed for the slider.
All the events are handled through even delegation (using jQuery's on() function), this however provided no solution. I'm quite sure it has something to do with the structure and variable scope of the script, but am unable to determine how to change the structure. So I'm looking for a solution that works in both situations (called normal or through AJAX).
I tried to declare the needed variables in every function, this however resulted in some akward bugs, like the multiplication of the intervals I set for the animation, because of the function scope. Hope somebody can help me in the right direction.
// Slider function
(function (window, undefined) {
var console = window.console || undefined, // Prevent a JSLint complaint
doc = window.document,
Slider = window.Slider = window.Slider || {},
$doc = $(doc),
sliderContainer = doc.getElementById('slider_container'),
$sliderContainer = $(sliderContainer),
$sliderContainerWidth = $sliderContainer.width(),
slider = doc.getElementById('slider'),
$slider = $(slider),
$sliderChildren = $slider.children(),
$slideCount = $sliderChildren.size(),
$sliderWidth = $sliderContainerWidth * $slideCount;
$sliderControl = $(doc.getElementById('slider_control')),
$prevButton = $(doc.getElementById('prev')),
$nextButton = $(doc.getElementById('next')),
speed = 2000,
interval,
intervalSpeed = 5000,
throttle = true,
throttleSpeed = 2000;
if (sliderContainer == null) return; // If slider is not found on page return
// Set widths according to the container and amount of children
Slider.setSliderWidth = function () {
$slider.width($sliderWidth);
$sliderChildren.width($sliderContainerWidth);
};
// Does the animation
Slider.move = function (dir) {
// Makes use of variables such as $sliderContainer, $sliderContainer width, etc.
};
// On ajax call
$doc.on('ajaxComplete', document, function () {
Slider.setSliderWidth();
});
// On doc ready
$(document).ready(function () {
Slider.setSliderWidth();
interval = window.setInterval('Slider.move("right")', intervalSpeed);
});
// Handler for previous button
$doc.on('click', '#prev', function (e) {
e.preventDefault();
Slider.move('left');
});
// Handler for next button
$doc.on('click', '#next', function (e) {
e.preventDefault();
Slider.move('right');
});
// Handler for clearing the interval on hover and showing next and pervious button
$doc.on('hover', '#slider_container', function (e) {
if (e.type === 'mouseenter') {
window.clearInterval(interval);
$sliderControl.children().fadeIn(400);
}
});
// Handler for resuming the interval and fading out the controls
$doc.on('hover', '#slider_control', function (e) {
if (e.type !== 'mouseenter') {
interval = window.setInterval('Slider.move("right")', intervalSpeed);
$sliderControl.children().fadeOut(400);
}
});
})(window);
The HTML example structure:
<div id="slider_control">
<a id="next" href="#next"></a>
<a id="prev" href="#prev"></a>
</div>
<div id="slider_container">
<ul id="slider">
<li style="background-color:#f00;">1</li>
<li style="background-color:#282">2</li>
<li style="background-color:#ff0">3</li>
</ul>
</div>
I notice you have
Slider.setSliderWidth = function() {
$slider.width($sliderWidth);
$sliderChildren.width($sliderContainerWidth);
};
which is called on ajax complete.
Does you ajax update the DOM giving a new DOM element that you could get to by doc.getElementById('slider')? Then your var slider and jquery var $slider are likely pointing to things that no longer exist (even if there is a dom element with slider as the id). To rectify, whenever the ajax is invoked that replaces that element, reinitialize slider and $slider to point to the new jquery wrapped element using the same initialization you have.
slider = doc.getElementById('slider');
$slider = $(slider);
Edit:
I'm not sure where you're going with the variable scope issue, but take a look at this example.
<pre>
<script>
(function(){
var a = "something";
function x (){
a += "else";
}
function y() {
a = "donut";
}
function print (){
document.write(a +"\n");
}
print ();
x();
print ();
y();
print ();
x();
print ();
})();
document.write(typeof(a) + "\n");
</script>
</pre>
It outputs into the pre tag
something
somethingelse
donut
donutelse
undefined
This isn't all that different from what you're already doing. As long as a is not a parameter of a method and is not declared with var in a nested scope, all references to a in code defined within your function(window,undefined){ ...} method will refer to that a, given that a is defined locally by var to that method. Make sense?
To begin, surely you can replace all the getElementById using a jQuery approach. i.e. replace $(doc.getElementById('next')) with $('#next')
I think that when you use on it doesn't search the element for the selector as you are assuming. So you would have to use:
$doc.on('click', '#slider_control #prev',function(e){
e.preventDefault();
Slider.move('left');
});
Wait, what gets loaded through Ajax? The slider-html code? In that case, the Slider has already been 'created' and a lot of your variables will point to nowhere (because these DOM elements did not existed when the variables were initialized). And they will never do so either.

How can I use jQuery and Javascript from firefox add-on?

I can't create a new element in the page. I check the page and domain when the page is onload, that's work, but I don't know how can I create a new element in the correct window page.
window.addEventListener("load", function() { myExtension.init(); }, false);
var myExtension = {
init: function() {
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
},
onPageLoad: function(aEvent) {
var unsafeWin = aEvent.target.defaultView;
if (unsafeWin.wrappedJSObject) unsafeWin = unsafeWin.wrappedJSObject;
var locationis = new XPCNativeWrapper(unsafeWin, "location").location;
var hostis = locationis.host;
//alert(hostis);
if(hostis=='domain.com')
{
var pathnameis=locationis.pathname;
if(pathnameis=='/index.php')
{
$("#left .box:eq(0)").after('<div id="organic-tabs" class="box"></div>'); // this code somewhy doesn't working, but if I copy to FireBug it't work.
}
}
}
}
My question is: How can I use Javascript and jQuery from firefox addon when I want to manipulate html in the correct window content? What is need from here
$("#left .box:eq(0)").after('<div id="organic-tabs" class="box"></div>');
for working.
This code has a bunch of issues. For one, appcontent is not the browser, gBrowser is. So it should be:
init: function() {
gBrowser.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
},
Then, using wrappedJSObject is absolutely unnecessary (and also not safe the way you do it).
var wnd = aEvent.target.defaultView;
var locationis = wnd.location;
Finally, you are trying to select an element in the browser document (the document that your script is running in), not in the document loaded into the tab. You need to give jQuery an explicit context to work on:
$("#left .box:eq(0)", wnd.document)
But you shouldn't use jQuery like that, it defines a number of global variables that might conflict with other extensions. Instead you should call jQuery.noConflict() and create an alias for jQuery within myExtension:
var myExtension = {
$: jQuery.noConflict(true),
....
myExtension.$("#left .box:eq(0)", wnd.document)
Here is a template you can use that incorporates your sample code. I also added an additional statement so you could see another use of jQuery. Important points:
You must load jQuery before you can use it. You should myplace the jQuery library file you want to use in Chrome, for example, in the chrome/content directory.
Use window.content.document as the context for every jQuery
operation on the contents of the Web page
Use this as the context of a successful search result to help you
insert code in the correct spot.
window.addEventListener('load', myExtension.init, false);
var myExtension = {
jq : null,
init : function() {
var app;
// Load jQuery
var loader = Components.classes["#mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://myExtension/content/jquery-1.5.2.min.js");
myExtension.jq = jQuery.noConflict();
// Launch extension
if ((app = document.getElementById("appcontent"))) {
app.addEventListener("DOMContentLoaded", myExtension.run, true);
}
},
run : function() {
// make sure this is the correct Web page to change
var href = event.originalTarget.location.href;
if (href && href.match(/http:\/\/(www\.)?domain\.com\/(index\.php)/i)) {
changeScreen();
}
},
changeScreen : function() {
// make changes to the screen
// note the "window.content.document) in the first jQuery selection
myExtension.jq("#left .box:eq(0)", window.content.document).after('');
// note the use of "this" to use the search results as the context
myExtension.jq("#right", window.content.document).each(function() {
myExtension.jq("tr td", this).append('MATCH!');
});
}
}

how to rewrite this this inline javascript with jquery?

I have the following markup with inline javascript and would like to change it to Jquery. Any help would be appreciated.
<a title="823557" href="/PhotoGallery.asp?ProductCode=471823557" id="product_photo_zoom_url">
<img border="0" onload="vZoom.add(this, '/v/vspfiles/photos/471823557-2.jpg');"
alt="823557"
src="/v/vspfiles/photos/471823557-2T.jpg" id="product_photo"></a>
I guess I would need to use this?
$(function(){
<---- somecode---->
});
$(function () {
$("#product_photo").load(function (e) {
vZoom.add(this, this.src.replace('T.', '.'));
})
})();
If $ doesn't work for some reason, this should also work. I incorporated Kranu's advice since that library most likely only needs the DOM loaded as a prerequisite, rather than the load event:
jQuery(function ($) {
$("#product_photo").each(function () { // in case there is more than one
vZoom.add(this, this.src.replace('T.', '.'));
});
});
Note that there is no need to put a separate bind event on the img because the $(function() { }) waits until the body loads.
$(function(){
vZoom.add(document.getElementById('product_photo'),'/v/vspfiles/photos/471823557-2.jpg');
});
Not exactly sure what you are trying to do, but essentially you would remove the image from the HTML and dynamically load it using JS. Once loaded, you would inject it in the DOM and set the onload event.
var jsImg = new Image();
jsImg.onload = function(){
vZoom.add(this,'/v/vspfiles/photos/471823557-2.jpg');
var img = document.createElement('IMG');
img.setAttribute('id','product_photo');
img.setAttribute('alt','823557');
img.setAttribute('src','/v/vspfiles/photos/471823557-2T.jpg');
img.style.border = 'none';
//inject image now in the DOM whereever you want.
};
jsImg.src = '/v/vspfiles/photos/471823557-2T.jpg';

Categories