How to Separate Two jQuery Functions - javascript

I want to separate these functions. They should both work separately on click events:
FIRST FUNCTION
$("ul.nav li").delegate("a", "click", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if (newHash) {
ACTION A
});
$(window).trigger('hashchange');
});
SECOND FUNCTION
$("ul.subnav li").delegate("a", "click", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if (newHash) {
ACTION B
});
$(window).trigger('hashchange');
});
This is what happend in ACTION A:
$mainContent
.find(".maincontent")
.fadeOut(200, function() {
$mainContent.hide().load(newHash + " .maincontent", function() {
$mainContent.fadeIn(200, function() {
$pageWrap.animate({
height: baseHeight + $mainContent.height() + "px"
});
});
$(".nav a").removeClass("active");
$(".nav a[href="+newHash+"]").addClass("active");
});
});
The Problem is that if I click the Link of the Second function always the the first function fires.
Details of what I'm trying to do:
First, I build my site on .php to serve poeple without JavaScript. Now I want to load the "maincontent" dynamically. So I found this script I'm using:
http://css-tricks.com/6336-dynamic-page-replacing-content/
It does do a great job if you only want to load "maincontents".
But my site has sub-navigation on some pages where I want to load the sub-content. In .php these sites use includes. So I get my content by: href="page2.php?page=sub1"
So, when I click on the sub-links now they load also dynamically but the script also on the whole maincontent loading area. So it doesn't really load content by .load() but the sub-content of the includes do appear.
So what I thought was just to separate this function. The first to simply load the maincontents and a second one for the sub-navigation to refresh only the sub-content area. I don't even understand how this script loads the include content dynamically since the link is the straight page2.php?page=sub1 link. All dynamic loaded content usually looks like "#index", without the ending ".php".
Some quick history:
I'm trying to get the best page structure. Deliver .php for non JavaScript user and then put some dynamic loading stuff over it. Always with the goal to keep the browser navigation and the browser links (for sharing) for each page in tact.
I'm not an jQuery expert. All I have learned so far was by trial and error and some logical thinking. But of course, I have a lack of fundamental knowledge in JavaScript.
So my "logical" question:
How can I tell the "nav" links to perform only their "$(window).bind"-Event and to tell the "subnav" links only to perfom their "$(window).bin"-event.
Is this the right thinking?
Since I've already been trying to solve it for nearly the last 18h, I'll appreciate any kind of help.
Thank you.
IMPORTANT:
With the first function I not just only load the maincontent but also I'm changing a div on the page with every link. So for any solution that might want to put it together in one, it won't work, cause they should do different things on different areas on the page. That's why I really need to call on the window.bind with each nav/subnav click.
Can anyone show me how?

Melros,
In your second function, you are binding to the event hashchange2, which is incorrect. Instead, you STILL want to bind to hashchange. Instead of:
$(window).bind('hashchange2', function() {
...
});
Try:
$(window).bind('hashchange', function() {
...
});
If you want to namespace your event subscriptions, you can suffix the ending of the event you are binding to with a period (.) and then the namespace:
$("#test").bind("click.namespace1", function() { });
$("#test").bind("click.namespace2", function() { });

Ok, it seems that you want to execute action A when a link inside .nav is clicked, and action B when a link inside .subnav is clicked.
You can just put these actions inside the event handlers. Furthermor, if .subnav is nested inside .nav, you have to restrict your selector:
// consider only direct children
$("ul.nav > li").delegate("a", "click", function() {
var href = $(this).attr("href");
if(window.location.hash !== href) {
Action A
window.location.hash = $(this).attr("href");
}
return false;
});
// consider only direct children
$("ul.subnav > li").delegate("a", "click", function() {
var href = $(this).attr("href");
if(window.location.hash !== href) {
Action B
window.location.hash = $(this).attr("href");
}
return false;
});
I don't think listening to the hashchange event will help you here, as this event is triggered in both cases and you cannot know which element was responsible (you probably can somehow, but why make it overly complicated?).

Here's by the way the solution I came to:
After understanding that the haschange-event doesn't have to do anything with it (as long as you don't want to make the subcontent bookmarkable too) I just added a new load function for the subcontent:
$(function(){
$("ul.linkbox li a").live('click', function (e) {
newLink = $(this).attr("href");
e.preventDefault();
$(".textbox").find(".subcontent").fadeTo(200,0, function() {
$(".textbox").load(newLink + " .subcontent" , function() {
$(".subcontent").fadeTo(200,1, function() {
});
});
$("#wrapper").css("height","auto");
$("ul.linkbox li a").removeClass("activesub");
$("ul.linkbox li a[href='"+newLink+"']").addClass("activesub");
});
});
});

Related

Ajax content loading issues

Following is my code which I am using to load contents dynamically. The issues which I am facing are the following:
Following code has now disabled CTRL+CLICK shortcode to open a url in a new tab. The new CSS and JS are not applying if they are not already exist in the previous page. Kindly let me know how can I resolve above mentioned issues?
$(document.body).on("click", "nav a", function () {
topen = $(this).attr("href");
window.location.hash = $(this).attr("href");
$("#main_wrapper").load( topen +" #main_wrapper > *");
return false;
});
What you want to do is modify the handler to use prevent default instead of returning false. Then you can check how the user activated the button and can act accordingly.
$(document).ready(function() {
$('a').on('click', function(e) {
if(e.ctrlKey || e.button === 1) {
return;
}
e.preventDefault();
// Do the stuff when the anchor is just clicked.
});
});
You can examine the Fiddle
In terms of the JS and CSS not applying we would need a working example of this to be of more assistance.

Loading JS functions on dynamically loaded pages

I am using CSS-Tricks dynamic page script found here.
http://css-tricks.com/dynamic-page-replacing-content/
$(function() {
var newHash = "",
$mainContent = $("#main-content"),
$pageWrap = $("#page-wrap"),
baseHeight = 0,
$el;
$pageWrap.height($pageWrap.height());
baseHeight = $pageWrap.height() - $mainContent.height();
$("nav").delegate("a", "click", function() {
window.location.hash = $(this).attr("href");
return false;
});
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if (newHash) {
$mainContent
.find("#guts")
.fadeOut(200, function() {
$mainContent.hide().load(newHash + " #guts", function() {
$mainContent.fadeIn(200, function() {
/*
$pageWrap.animate({
height: baseHeight + $mainContent.height() + "px"
});
*/
});
$("nav a").removeClass("current");
$("nav a[href="+newHash+"]").addClass("current");
});
});
};
});
$(window).trigger('hashchange');
});
Body
<body onload="onLoad()">
I am using a number generating script (below) on one of my pages, but I am having trouble getting it to only show on one, single page. When placed in the head of the document or my includes/scripts.php that is loaded on every page, it shows on every page. When only included on the page I want, it does not work.
<script>
function counter() {
var num = 0;
for (num = 0; num < 500; num++) {
document.write(num + ' ');
}
}
counter();
</script>
I have tried a few different things but can't seem to get it to only appear on a single page. Is there any way around this without ditching the CSS-Tricks Dynamic Page?
What if you insert your code into dynamicpage.js like this?
$(window).bind('hashchange', function(){
newHash = window.location.hash.substring(1);
if(newHash === 'somePage') { // the page you want to implement the effect
// your code
}
/*
....
*/
});
You might try adding a class to your <body> tag (or other near-to-top level wrapper if you're just dynamically loading to the HTML attribute of your body tag in the first place) that lets the script distinguish between pages that ought to use the function and those that don't, something like:
$(document).ready( function() {
$(`body.usesCounter`).on(eventToBeCounted, counterFuncAsCallback);
}
But the fact that it's not working when only loaded on a single page does suggest you've got something else going on. Can you give us the header for the single page, the script block (and where it is on the page), and some sense of how/when it's called?
Are you loading the single page dynamically? If you are, the script tags won't be accessible unless you reload the DOM somehow or else do some funky binding via jQuery's $.on() or something similar that listens for changes to the DOM.
UPDATE
Looking at the tutorial you are trying to emulate, the general problem you're facing is that the JS on that page you're loading isn't going to be registered with the DOM. I've had to write code that can read dynamically lodaded JS like this, and if you want to do it both effectively and securely, it's quite a lot of effort. The point of JS-based page loading is to be fetching "view-like" content; assets, html, etc.. In a single-page environment, any required logic should—generally—exist on that page.
I highly recommend you include the code in your initial page, and then conditionally call it when the appropriate page arrives. There are lots and lots of ways to do that, basically find some distinguishing feature of the page(s) where your counter should be run, and, after having loaded the page, look for said features and, if found, allow your code to run. You might have something as simple as a variable, isCounterPage set, by default, to false. Then, after a dynamic page load occurs, if the inspection fires and this var remains false, don't execute code associated with the counter. Otherwise, let it do its thing.

Using jquery to control the iframe URL [duplicate]

I have an iframe on a page, coming from a 3rd party (an ad). I'd like to fire a click event when that iframe is clicked in (to record some in-house stats). Something like:
$('#iframe_id').click(function() {
//run function that records clicks
});
..based on HTML of:
<iframe id="iframe_id" src="http://something.com"></iframe>
I can't seem to get any variation of this to work. Thoughts?
There's no 'onclick' event for an iframe, but you can try to catch the click event of the document in the iframe:
document.getElementById("iframe_id").contentWindow.document.body.onclick =
function() {
alert("iframe clicked");
}
EDIT
Though this doesn't solve your cross site problem, FYI jQuery has been updated to play well with iFrames:
$('#iframe_id').on('click', function(event) { });
Update 1/2015
The link to the iframe explanation has been removed as it's no longer available.
Note
The code above will not work if the iframe is from different domain than the host page. You can still try to use hacks mentioned in comments.
I was trying to find a better answer that was more standalone, so I started to think about how JQuery does events and custom events. Since click (from JQuery) is just any event, I thought that all I had to do was trigger the event given that the iframe's content has been clicked on. Thus, this was my solution
$(document).ready(function () {
$("iframe").each(function () {
//Using closures to capture each one
var iframe = $(this);
iframe.on("load", function () { //Make sure it is fully loaded
iframe.contents().click(function (event) {
iframe.trigger("click");
});
});
iframe.click(function () {
//Handle what you need it to do
});
});
});
Try using this : iframeTracker jQuery Plugin, like that :
jQuery(document).ready(function($){
$('.iframe_wrap iframe').iframeTracker({
blurCallback: function(){
// Do something when iframe is clicked (like firing an XHR request)
}
});
});
It works only if the frame contains page from the same domain (does
not violate same-origin policy)
See this:
var iframe = $('#your_iframe').contents();
iframe.find('your_clicable_item').click(function(event){
console.log('work fine');
});
You could simulate a focus/click event by having something like the following.
(adapted from $(window).blur event affecting Iframe)
$(window).blur(function () {
// check focus
if ($('iframe').is(':focus')) {
console.log("iframe focused");
$(document.activeElement).trigger("focus");// Could trigger click event instead
}
else {
console.log("iframe unfocused");
}
});
//Test
$('#iframe_id').on('focus', function(e){
console.log(e);
console.log("hello im focused");
})
None of the suggested answers worked for me. I solved a similar case the following way:
<iframe id="iframe_id" src="http://something.com" allowtrancparency="yes" frameborder="o"></iframe>
The css (of course exact positioning should change according to the app requirements):
#iframe-wrapper, iframe#iframe_id {
width: 162px;
border: none;
height: 21px;
position: absolute;
top: 3px;
left: 398px;
}
#alerts-wrapper {
z-index: 1000;
}
Of course now you can catch any event on the iframe-wrapper.
You can use this code to bind click an element which is in iframe.
jQuery('.class_in_iframe',jQuery('[id="id_of_iframe"]')[0].contentWindow.document.body).on('click',function(){
console.log("triggered !!")
});
This will allow you to target a specfic element in the iframe such as button or text fields or practically anything as on method allows you to put selector as an argument
$(window).load(function(){
$("#ifameid").contents().on('click' , 'form input' , function(){
console.log(this);
});
});
Maybe somewhat old but this could probably be useful for people trying to deal with same-domain-policy.
let isOverIframe = null;
$('iframe').hover(function() {
isOverIframe = true;
}, function() {
isOverIframe = false;
});
$(window).on('blur', function() {
if(!isOverIframe)
return;
// ...
});
Based on https://gist.github.com/jaydson/1780598
You may run into some timing issues depending on when you bind the click event but it will bind the event to the correct window/document. You would probably get better results actually binding to the iframe window though. You could do that like this:
var iframeWin = $('iframe')[0].contentWindow;
iframeWin.name = 'iframe';
$(iframeWin).bind('click', function(event) {
//Do something
alert( this.name + ' is now loaded' );
});
This may be interesting for ppl using Primefaces (which uses CLEditor):
document.getElementById('form:somecontainer:editor')
.getElementsByTagName('iframe')[0].contentWindow
.document.onclick = function(){//do something}
I basically just took the answer from Travelling Tech Guy and changed the selection a bit .. ;)
Solution that work for me :
var editorInstance = CKEDITOR.instances[this.editorId];
editorInstance.on('focus', function(e) {
console.log("tadaaa");
});
You can solve it very easily, just wrap that iframe in wrapper, and track clicks on it.
Like this:
<div id="iframe_id_wrapper">
<iframe id="iframe_id" src="http://something.com"></iframe>
</div>
And disable pointer events on iframe itself.
#iframe_id { pointer-events: none; }
After this changes your code will work like expected.
$('#iframe_id_wrapper').click(function() {
//run function that records clicks
});

jQuery click event with class selector only fires once

I'm using classed links to change FlowPlayer content. Here is a working version: http://jsfiddle.net/r9fAj/
In my actual page using the same code the first link clicked works fine. The second one does not fire the click function at all. Even if I comment out everything but the console.log()...
$('.playerLink').click( function() {
audioPlayer.unload();
initAudioPlayer();
$('#player').css('display', 'block');
$('#player').animate({"height":"50px"}, 1000);
var newClip = {'url':$(this).attr('ajax-data'),'autoplay':true};
audioPlayer.play(newClip);
console.log('playing ' + $(this).attr('ajax-data'));
});
HTML like so
Listen
Listen
<a id="flowplayer" href="/audio/episodes/09_27_2013_Happy_Hour_88509726.mp3"></a>
And the player initialized like so:
var audioPlayer;
var initAudioPlayer = function () {
$f("flowplayer", "/player/flowplayer-3.2.16.swf", {
plugins: {
controls: {
fullscreen: false,
autoHide: false,
}
},
clip: {
autoPlay: false,
url: "",
}
});
audioPlayer = $f();
};
initAudioPlayer();
Since the jsFiddle works over and over I assume something else in my page is preventing the second click() from working but the console has no errors for me.
So my question is, short of posting the whole site's code how do I pursue debugging this?
So it sounds like your .click() event handler is only being fired for the first link you click and not for additional clicks. For general debugging, you could take your page that is not working and gradually comment out / remove other part of the JS and HTML until you are able to make it work correctly. Or start with the minimal amount that is working (the fiddle) and gradually add in the rest to see when it stops working.
So this is the first site I have done where content is delivered via AJAX and internal links are caught by
$("a:not([href^='http://'])").click( function(e) {
var url = $(this).attr("href");
var title = ($(this).attr("title")) ? ': ' + $(this).attr("title") : '';
e.preventDefault();
if(url!=window.location){
window.history.pushState({path:url},title,url);
$('#contentMain').load(url);
document.title = "It's New Orleans" + title;
}
});
For some reason it does work once to click a link with the class but the second time gets preventDefault()ed.
Listen
The fix was adding [href^='#'] to not() e.g.
$("a:not([href^='http://'],[href^='#'])").click( function(e) {

How to exclude JQuery/Javascript fade in & out function on certain links?

I'm using this fade in and out JQuery/Javascript effect on my site to have each page fade in and out when a link is clicked. It's working great when the link that is clicked leads to a different page, but it is causing problems when the link leads to a different part of the page (such as my back to top link), when a mailto link is clicked, and when a link that is suppose to open up in a new page or tab is clicked. When these type of links are clicked they just lead to a blank white page because they don't lead to a new page. Here is the script:
$(document).ready(function() {
//Fades body
$("body").fadeIn(1500);
//Applies to every link
$("a").click(function(event){
event.preventDefault();
linkLocation = this.href;
$("body").fadeOut(1000, redirectPage);
});
//Redirects page
function redirectPage() {
window.location = linkLocation;
}
});
Because of this I'm trying to figure out if there is a way where I can exclude this fade in/out function from certain links (such as the back to top link), but I don't know how to do it. I know that rather than set all the links to fade in/out I can set the fade in/out effect to a specific class that way it doesn't effect every link. However because the site is rather large, it would be extremely tedious and difficult to add that class to every link. So rather than do that I'm wondering if theres a way to define a no-fade class that would exclude this fade in/out function? That way I could apply that class to these few links that are having problems and make those links behave normally.
It seems like a simple thing to do, but because I'm still not very fluent in javascript/jquery I don't know how to do it. Any help would be much appreciated!
*EDIT: Here is the solution incase anybody else has a similar issue. Thanks to David for the missing piece!
$(document).ready(function() {
//Fades body
$("body").fadeIn(1500);
//Applies to every link EXCEPT .no-fade class
$("a").not(".no-fade").click(function(event){
event.preventDefault();
linkLocation = this.href;
$("body").fadeOut(1000, redirectPage);
});
//Redirects page
function redirectPage() {
window.location = linkLocation;
}
});
Yup, you could indeed define a class that when applied to an anchor would exclude it from performaing your fade out and redirect.
So if you had an anchor you wanted your default fade-out behaviour to apply to then simply leave it as is.If you didn't want this behaviour then you could apply a class (we'll call it *no-fade") to the anchor.
HTML
Another page
Back to top
jQuery
<script type="text/javascript>
$(document).ready(function() {
$("body").fadeIn(1500);
$("a").not(".no-fade").click(function(event){
event.preventDefault();
linkLocation = this.href;
$("body").fadeOut(1000, redirectPage);
});
// Redirects page
function redirectPage() {
window.location = linkLocation;
}
});
</script>
The only thing I've edited from your code is the selection of the anchors which I changed from:
$("a")
to
$("a").not(".no-fade")
The unobtrusive way would be to look for the hash symbol (#) or mailto:, etc. to prevent those types of links from fading out:
working fiddle
$("a").click(function (event) {
event.preventDefault();
linkLocation = $(this).attr('href');
if(linkLocation.indexOf('#') != -1 || linkLocation.indexOf('mailto:') != -1)
{redirectPage();}
else if($(this).attr('target') && $(this).attr('target').indexOf('_') != -1) window.open(linkLocation);
else $("body").fadeOut(1000, redirectPage);
});
Also, linkLocation = this.href should be linkLocation = $(this).attr('href')

Categories