jQuery events on external objects - javascript

I have a problem.
I'm looking for document-wide click events, but large chunks of my site is loaded through a div with an innerHTML object.
<div id="contentHolder">
<script>
document.getElementById("contentHolder").innerHTML='<object type="text/html" id="content" data="article.html"></object>';
</script>
</div>
A listener like this:
$(document).on("click", function (event){
alert("Click");
});
Only registers clicks on elements outside of the ContentHolder.
I realise that the loaded content probably has its own document.
Do any of you know of a way I can refer to this content inside the Object? :)
I read up on jQuery delegation, but it didn't seem to offer a solution to my problem.
I set up a semi-working example on Codepen. It doesn't seem to allow loading external pages, understandably so - but the problem persists even without any actual loading. The example works locally.
Edit
I solved the problem myself. Instead of using an HTML Object for a container, you can use jQuery append and the listeners will remain active not only from the sub-document's events but also the parent's.
$.get('document.html', function(result) {
$('#container').append(result);
});`

You can try this:
$('#contentHolder').on('click', '.class-to-be-named', function() {
// do your click stuff
});
It will bind the click event on #contentHolder and whenever you click within #contentHolder it will lookup if element #contentHolder was clicked, when is it calls the callback.

I solved the problem myself. Instead of using an HTML Object for a container, you can use jQuery append and the listeners will remain active not only from the sub-document's events but also the parent's.
$.get('document.html', function(result) {
$('#container').append(result);
});

Related

jQuery link instead of button trigger

So, i have this code snippet that opens a modal:
<button id="trigger-overlay" class="order">Open Overlay</button>
Now, i wanted to include it in Wordpress menu, but i cant add button tag there, so i added:
Open Overlay
And i am using jquery to add a ID to that link, like this:
$('.order').attr('id','trigger-overlay');
ID is added, but link doesnt open anything, aka, it links to "#" instead of opening a modal...
How could i fix this to make it work?
Thanks!
This thing may causing due to events binging order. So, your code $('.order').attr('id','trigger-overlay'); is executing right after click's binding event (I think that event looks like this one: $('#trigger-overlay').click(function() { ... });.
If you have ability to change that binding, please use jquery.on method: http://api.jquery.com/on/
So that code will looks like: $(document).on('click', '#trigger-overlay', function() { ... });.
Also you can just move $('.order').attr('id','trigger-overlay'); above the script with that event binding.
Based on your
<button id="trigger-overlay" class="order>Open Overlay</button>
I'm not sure how you got a modal to trigger, since it is not connected to an event handler like:
<button onclick="turnOverlayOn()">Demo Button</button>
In this case, there would be a function that targets the overlay/modal and turns its CSS display property from none to block or inline-block (however you would like to display it):
var turnOverlayOn = function () {
$('targetOverlayId').css('display','block')
}
I suggest focusing on attaching an onClick event that triggers a function that does what you want to make the overlay appear.
The function used to turn the overlay off could be:
var turnOverlayOff = function () {
$('targetOverlayId').css('display','none')
}
You could attach this to a different anchor tag or button to turn the overlay off.
Note: the event should work the same for an anchor tag as it does for a button.
In my understanding you want to trigger the button click event. Using the a tag with class order.
try
jQuery(document).on('click','.order',function(){
jQuery('#trigger-overlay').click();
});
You can trigger the click event using jquery. Since I have no knowledge of your DOM structure jQuery(document).on('click','.order',function().. will work even if your elements are dynamic (added to the DOM after the script execution) because the click event is bind to the document.
NOTE:
When using wordpress always use jQuery instead of $ to avoid conflicts.

Is there a way to do global event binding on dynamic HTML loaded via jQuery .load()?

I have an HTML page that uses jQuery .load() to pull in HTML from other files. I do this mostly for readability purposes.
I ran into a problem whereby code that is loaded via .load() is not "visible" to other javascript loaded later in the module because .load() is asynchronous. This was solved in another StackOverflow question of mine with very good results, by doing the .click() binding in the .load() callback. S.O. shone through like it always does!
Now, I have another question that is also related.
HTML:
<div class="mainContent" style="color:white; overflow-y: auto; position:fixed; top:210px; bottom:60px;">
<div class="linkContent" id="contentAboutUs" style="display:none"></div>
<div class="linkContent" id="contentAboutUsCompany" style="display:none"></div>
<div class="linkContent" id="contentAboutUsVerify" style="display:none"></div>
<div class="linkContent" id="contentAboutUsSelf" style="display:none"></div>
<div class="linkContent" id="contentAboutUsHow" style="display:none"></div>
</div>
jQuery ready() function:
$("#contentAboutUs").load("contentAboutUs.html");
$("#contentAboutUsCompany").load("contentAboutUsCompany.html");
$("#contentAboutUsVerify").load("contentAboutUsVerify.html");
$("#contentAboutUsSelf").load("contentAboutUsSelf.html", function () { $(".saveButton").click(function () { saveForm(); }) });
$("#contentAboutUsHow").load("contentAboutUsHow.html");
You will notice that on the AboutUsSelf .load(), a callback binds the click event of the ".saveButton" to a function called saveForm(). This works perfectly, and was the answer I got from my previous S.O. question.
As you see, ".saveButton" is a class, and in fact, this button will be on MANY pages of the form; which is why it is a class and not an ID.
The question then is this: I do not want to do this click() binding on every section that contains one of these buttons. Is there a way to dynamically .load() this HTML, and yet apply this click() binding globally instead of doing it in the .load() callback individually in every case where it is needed?
Since you are loading these inside a container, you can use that.
$('.mainContent').on('click','.saveButton', function(){
saveForm();
});
Event handlers bound this way bind to the container and it "looks within" for the selector of the button. You cannot directly bind to the class for the button as it has nothing to bind to until it is loaded and in the DOM.
Bind to the closest container (not document for instance) that you can to avoid the deep "look within" impact with a super large DOM.
Note that one thing you also experience here is multiple hits to your sever - i.e. you would benefit from the cache of the HTML if it were in the page already and it only hits the page once that way. That being said, dynamic page portions are a good candidate for this type binding at the container level.
With ASP.NET MVC for instance these can be put in partial views and get in the page prior to hitting the browser.
You did not ask but I would also move the style to a CSS file and not put it in the markup - this then makes your markup much cleaner and easier to modify.
I believe what you are looking for is event delegation.
Essentially, what you can do is bind your event listener, using on(), to a containing element instead of directly on the element you're listening to. Relevant info:
If we were to click our newly added item, nothing would happen. This is because of the directly bound event handler that we attached previously. Direct events are only attached to elements at the time the .on() method is called. In this case, since our new anchor did not exist when .on() was called, it does not get the event handler.
Example:
$("#container-of-some-sort").on("click", ".saveButton", function(){
saveForm();
});
Take a look at ajaxComplete - should be able to attach your click event there and have it apply to all the new buttons loaded in

jQuery on click works when executed in console but not when page loads

I use the following jquery in my page.
var j = jQuery.noConflict();
j(document).ready(function(){
console.log(j("#label_19"));
j("#label_19").on("click",function(){
alert("Clicked");
});
});
When document loads, the element (it's a checkbox) appears in the console. But when I click the checkbox, the alert is not thrown. But when I copy the same code (as below)
j("#label_19").on("click",function(){
alert("Clicked");
});
in console panel and press run. Now when I click the checkbox, the alert is thrown. What could be the issue in this case?
Updated:
What I observe in console is:
Object[input#label_19.document_label attribute value = "Check-In"]
The HTML markup is
<input id="label_19" class="document_label" type="checkbox" value="Check-In" name="label[19]">
The only explanation that fits the facts you've presented is that there is code running after your ready callback but before you click the element that replaces the element in question. Some kind of ajax callback or similar.
You'll need to look through your code to find the place where that's happening. Things to look for are any html calls on elements that contain the #label_19 element, or (if there's a mix of jQuery and non-jQuery code) assignments to innerHTML.
You can use event delegation to solve this, which may or may not be the best answer depending on what your code is doing. That looks like this:
var j = jQuery.noConflict();
j(document).ready(function(){
console.log(j("#label_19"));
j(document).on("click", "#label_19", function(){ // This is the changed line
alert("Clicked");
});
});
There, instead of hooking click on the actual element, we're hooking it on document but then asking jQuery to only tell us about clicks that pass through elements matching the selector we give it as they bubble. That way, the fact that something is destroying and recreating the #label_19 element doesn't matter, because we're not hooking a handler on that element. We're hooking the handler on document and checking, when the event occurs, if it passed through something that matches that selector.
But I wouldn't just blindly use event delegation, I'd find out what's really happening with that element.
Without seeing the rest of your code—including HTML and related DOM elements—have you considered using j(window).load() instead of j(document).ready()
var j = jQuery.noConflict();
j(window).load(function(){
console.log(j("#label_19"));
j("#label_19").on("click",function(){
alert("Clicked");
});
});
As explained here:
The window load event executes a bit later when the complete page is fully loaded, including all frames, objects and images. Therefore functions which concern images or other page contents should be placed in the load event for the window or the content tag itself.
I had a similar issue, it got resolved after i wrapped it in a window.load
(function ($) {
$(window).on('load', function () {
//MY click calls inside here
});
})(jQuery);
Hope it helps!

jquery event functions not working properly

I have a page where the contents displayed from database using jquery and ajax. There are lot of processes in the page like Adding new content and image, Editing, Deletion etc and all are using ajax. But now some of event functions like click , mouseenter are not working in the content which where displayed from the database.
for example: This is how i display images in the page
for(var i=0;i<images.length;i++)
{
$("#content").append("<img src='"+images[i]+"' class='img' width='300' height='200' />");
}
Images are displayed properly. but when trying to do somthing on click event in images like this, its not working
$("#content .img").on('click',function()
{
//here comes my process, but its not working
}
Please help me to solve this problem.
Try:
$("#content").on("click", ".img", function() {
});
The problem is that $("#content img") creates a jQuery collection of elements that exist at the time it is run. When you start dynamically adding new elements, they don't have the event listener applied to them automatically.
What $("#content").on("click", ".img") does is provide for event delegation. So what's really happening is an event listener that is applied to $("#content") but only fired when that event comes from a descendant with a matching selector (.img in this case).
More info at http://api.jquery.com/on/.
Try like this
$(document).on('click', '#content .img',function()
{
...
});
This problem will always arise when you are trying to add some dynamic content. So,to resolve this always keep in mind some point.
All use some static element to reference the dynamic you are trying to apply event on.
Example : in your case try using
$("#content").on('click', 'img', function(){
//try using this way make your code works fine.!
});

JQuery if statement for .is(':visible') not working

I have a div that when the page is loaded is set to display:none;. I can open it up using this simple code:
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").css({'display':'block'});
});
Once it's opened, I'd like the user to be able to close it so I tried using the .is(':visible') function and then wrapping my original code in an if statment but this time using display:none;
if($('.field-group-format-wrapper').is(':visible')){
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").css({'display':'none'});
});
}
This does not seem to work though and I am not getting any syntax errors that I know of.
I also tried this:
if ($('.field-group-format-wrapper').is(':visible'))
$(".field-group-format-toggler").click(function () {
$(".field-group-format-wrapper").css({'display':'none'});
});
... but that did not work either.
You can just use the toggle function:
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").toggle();
});
This will show the '.field-group-format-wrapper' elements if they are currently hidden and hide them if they're currently visible.
FYI the reason your code snippet in your question wasn't working is because you're only checking the visibility of the elements on dom ready, rather than on each click - so the event handler to show the elements will never be attached.
I guess your function is only being called on page load at which time all divs are hidden.
Why not check the visibility in the click event handler?
$('.field-group-format-toggler').click(function(){
var $wrapper = $('.field-group-format-wrapper'); //Maybe $(this).parent()?
if($wrapper.is(':visible'))
$wrapper.hide();
else
$wrapper.show();
As already mentioned, you can use the toggle function to achieve what you want.
To add a bit of extra information, when attaching events like you're doing, you're actually using a subscription model.
Registering an event puts it in a queue of events subscribed to that handler. In this case, when you add the second event to change the CSS, you're adding an event, not overwriting the first one.
Whilst thing isn't actually causing your problem, it's worth being aware of.

Categories

Resources