I have this following jquery on my view:
$(document).ready(function() {
$(function() {
$('#link1').click(function() {
$('#link2').show();
$('#link1').hide();
$('#frame').attr('src', 'http://google.com/');
});
});
});
$(document).ready(function() {
$(function() {
$('#link2').click(function() {
$('#link1').show();
$('#link2').hide();
$('#frame').attr('src', 'http://yahoo.com/');
});
});
});
On pageload, the link2 is set to hide. What the jQuery does is: when the link with id link1 is clicked, it will show the link with idlink2 and hide itself. And vice versa.
My problem is it seems that my jQuery code can still be simplified. Is there other ways I can do what I wanted with simpler version? Thanks for the help!
Working example : http://jsfiddle.net/cuJBm/
$(document).ready(function() {
$(function() {
var linkSet = $('#link1').add('#link2')
linkSet.click(function() {
linkSet.toggle();
});
});
});
The add method allows you to add a different selector to the set of matchers, thus binding both clicks simultaneously. By saving the constructed set to a variable (linkSet), it stops you from having to traverse the DOM twice.
The only two assumption made here, are
1) That in the initial state only one is visible.
2) That the id structure is meaningful, useful, and classes will not suffice.
http://jsfiddle.net/cuJBm/1/
To answer your second question about setting an attribute on #frame. There are numerous ways of doing this. Perhaps the simplest is to add the following to your .click handler (after the toggle).
if ($(this).attr('id')=='link1'){
$('#frame').attr('src', 'www.google.com');
} else if ($(this).attr('id')=='link2'){
$('#frame').attr('src', 'www.yahoo.com');
}
Personally, I would probably add a custom attribute to your link elements, something like:
<a id='link1' iframe-source='www.google.com'>
<a id='link2' iframe-source='www.yahoo.com'>
And then: (again, just after the toggle):
source = $(this).attr('iframe-source');
$('#frame').attr(src, source);
The reason for saving source if is that if you attempt to get $(this) within the .attr on $('frame'), it will (as always) return the currently matched element, ie $('#frame').
Alternately (and very similiarly to the above approach), you could use the innerHTML of the link. For example:
<a id='link1'>link1<span style="display:none">www.google.com</span></a>
<a id='link2'>link2<span style="display:none">www.yahoo.com</span></a>
And then: (again, just after the toggle):
source = $(this).find('span').text();
$('#frame').attr(src, source);
Personally, I dislike this last method as it pollutes the DOM structure, leading to slightly more expensive rendering times, and (in my opinion) less readable code. Practically, all three methods work just fine.
<p class="link" style="display:none;" data-link="http://google.com/">sfdf</p>
<p class="link" data-link="http://yahoo.com/">ee</p>
$('.link').click(function() {
$('.link').toggle();
$('#frame').text($(this).data("link"));
});
jsfiddle :http://jsfiddle.net/xqDus/1/
Use jQuery toggle()
just add this
Google
Yahoo
target is id of the frame
$(function() {
$('#link1, #link2').click(function() {
$('#link1, #link2').toggle();
});
});
Related
I'm new to jQuery and found the toggle function really attractive. I wanted an image to switch to different image after a click and back again, like this:
$(document).ready(function() {
$("#expand").toggle(function(){
$(this).attr("src","images/expandWidget.png");
},function(){
$(this).attr("src", "images/minimizeWidget.png");
});
}); // end ready
And the image itself is declared like this:
<img id="expand" src="images/minimizeWidget.png"></img></div>
I notice that when I ran this through Chrome, the image changed to:
<img id="expand" src="images/minimizeWidget.png" style="display: none;">
And my image did not show. Why did Chrome do that? If I instead change the toggle to click(), my image shows without a problem and I can switch to a different image, but not back of course. I have no errors in the console and the page doesn't import other styles that would affect img. Am I using the toggle incorrectly? Please let me know if you need more information.
Thanks
Instead of toggle use .click()
LIVE DEMO
var images = ["images/expandWidget.png", "images/minimizeWidget.png"], c=0;
$("#expand").click(function(){
this.src = images[++c%2];
});
You've misunderstood what jQuery toggle does.
It 'toggles' the visibility of an element, hence it disappearing. It's not the greatest name admittedly, but we all used to have to write our own version of the toggle method inside .click().
See the documentation:
http://api.jquery.com/toggle/
You probably want something like:
$("#expand").click(function(){
if($(this).attr("src") == "images/expandWidget.png") {
$(this).attr("src", "images/minimizeWidget.png");
} else {
$(this).attr("src","images/expandWidget.png");
}
});
I'm using jquery data() to attach the name of a div I'd like to show when another div (.panel_button) is clicked. I'm doing the attaching of this div's id to the button when the document is ready. Is this an okay way to do this? Or is it too resource intensive and unprofessional-looking?
$(document).ready(function(){
$('#sample_button').data('panel', 'sample_kit_container');
$('#mail_button').data('panel', 'mail_container');
$('#mbillboard_button').data('panel', 'mbillboard_container');
$('.panel_button').on('click', function(){
$('.secondary_panel').hide();
var panel = $(this).data('panel');
$('#' + panel).show();
});
});
Yeah, that should work just fine. As an alternate, you could store the actual element itself (assuming it already exists) rather than finding it each time:
$('#sample_button').data('panel', $('#sample_kit_container'));
$('#mail_button').data('panel', $('#mail_container'));
$('#mbillboard_button').data('panel', $('#mbillboard_container'));
$('.panel_button').on('click', function(){
$('.secondary_panel').hide();
var panel = $(this).data('panel');
panel.show();
});
Another option would be to store the actual jQuery element in the data property, so no need to do a second selection:
$(function(){
$('#sample_button').data('panel', $('#sample_kit_container'));
$('#mail_button').data('panel', $('#mail_container'));
$('#mbillboard_button').data('panel', $('#mbillboard_container'));
$('.panel_button').on('click', function(){
$('.secondary_panel').hide();
var panel = $(this).data('panel');
panel.show();
});
});
#thomas, in my opnion, your solution is actually better than those in the other answers.
Including the whole object inside the data attribute may not always work. For example, what if the $('#sample_kit_container') object doesn't exist on load, but rather ofter an ajax load.
...
Only one tiny comment! why don't you call the data object: panelId. It would be more a bit intuitive.
I want to change all the links in a div such that they no longer refer to a page, but run a JavaScript function when being clicked. To do so, I wrote this function:
function buildPageInDiv(htmlString){
console.log(typeof htmlString);
$div = $(htmlString).children("div#myDiv");
$div.children("a").each(function(i, element){toJavascriptLinks(element)});
document.getElementById("targetDiv").innerHTML = $div[0].innerHTML;
}
calling this function:
function toJavascriptLinks(element){
element.href="#";
element.onclick = function(){console.log('Yeah!')};
console.log(element);
}
Now, when I run buildPageInDiv, 'string' is printed on the console, all the "href" are changed to "#" and for every <a> within the div the console prints the element:
<a href="#">
No sign of the onclick here, and clicking on the link does not show anything on the console.
What am I missing here?
Edit:
I was seeking in the wrong place. The problem was that I was running toJavascriptLinks(element) before attaching the innerHTML to targetDiv. That was no problem for the href attribute, but it was for the onclick attribute. Solution is simply to put it in targetDiv first and than run toJavascriptLinks(element) on targetDiv :
function buildPageInDiv(htmlString){
console.log(typeof htmlString);
var content = $(htmlString).children("div#myDiv")[0].innerHTML;
document.getElementById("targetDiv").innerHTML = content;
$("div#targetDiv").children("a").each(function(i, element) toJavascriptLinks(element)});
}
Although the problem was not in the code I originally posted, the comprehensive answers below led me to the solution.
First: All type of selectors in jQuery, start with the dollar sign and parentheses: $()
Secondly: you need to close your statements with ;
Lastly: it is good practice to define your functions BEFORE you call them, instead of relying on javascript to hoist them to the top for you. This will also make jslint validate, whereas the other way round wouldn't!
So your code without your errors would look like:
function toJavascriptLinks(element){
element.href="#";
element.onclick = function(){alert('Yeah!');};
console.log(element);
}
$('div').children("a").each(function(i, element){toJavascriptLinks(element);});
See this fiddle for a working demo.
Good Luck!!
ABOUT YOUR UPDATED QUESTION:
That's quite an update to your question.
You don't see your onclick in console.log because you set the onclick event in the dom. If you wanted to see the onclick in console.log, you would add the function STRING using:
element.setAttribute('onclick', 'your function string');
Suppose in your html you have:
<a id="link_a" href="http://www.google.com">link 1</a>
<a id="link_b" href="http://www.duckduckgo.com">link 2</a>
And you have this javascript:
var lnkA=document.getElementById("link_a");
var lnkB=document.getElementById("link_b");
lnkA.onclick=function(){alert(this.innerHTML);};
lnkB.setAttribute('onclick','alert(this.innerHTML);');
console.log(lnkA.outerHTML);
console.log(lnkB.outerHTML);
Then console.log will contain:
<a id="link_a" href="http://www.google.com">link 1</a>
<a onclick="alert(this.innerHTML);" id="link_b" href="http://www.duckduckgo.com">link 2</a>
See this fiddle for a live example of this explanation.
I also think you are already using some form of jQuery (without you knowing it) because of your use of .children("div#myDiv"). To my knowledge this no plain vanilla javascript. And I think both plain vanilla javascript and jQuery would not select those divs with id 'myDiv' out of a plain html-string, so the code in your update would not do the job.
Finally, to adjust my answer to your updated question and expectation of the onclick-event being visible in the parsed html-source:
var htmlString='<div id="myDiv">link 1link 2</div><div id="otherDiv">link 3link 4</div>';
function toJavascriptLinks(element){
element.href="#";
element.setAttribute('onclick','console.log("Yeah!");');
console.log(element.outerHTML);
}
//no innerHTML on documentFragment allowed, yet on it's children it's allowed
var frag = document.createDocumentFragment().appendChild( document.createElement('div') );
frag.innerHTML=htmlString;
var $div = $(frag).children('div#myDiv');
$($div).children("a").each(function(i, element){toJavascriptLinks(element);});
var outp=document.getElementById("output");
outp.innerHTML=frag.innerHTML;
See this updated fiddle to see it in action.
That leaves the question: why on earth are you placing 'ninja' $-signs front of your variable names?
That's just the way the debugger displays an HTML element. It doesn't show all attributes - especially since you are setting the DOM property onclick to a function reference, which can't be displayed as the HTML attribute onclick which takes a string (which AFAIK can't be set with JavaScript see Luc's comment).
Try console.log(element.onclick); instead, it should display something like function() {...}.
Or doesn't the event handle work?
BTW, any reason you don't use jQuery to set the href and the handler?
$div.children("a").attr('href', '#').click(function(){console.log('Yeah!')});
One more thing: In most consoles you can click on <a href="#"> and it will display the DOM properties, which should include the event handler.
I would really use jQuery for this, it's quite simple.
$(function() {
$("div > a ").attr("href", "#").click(function(e) {
e.preventDefault();
doSomething();
});
});
var doSomething = function() {
alert("Woah, it works!");
}
See the following jsfiddle for it in action: http://jsfiddle.net/SsXtt/1/
Are you sure the element is correct? This works for me.
<a id="mylink">Test</a>
<script>
document.getElementById("mylink").onclick = function() {
alert("Works");
};
</script>
Function needs to be inside a string, try adding quotes?
Note: This question was marked as solved once, but it figured out that upgrading to the latest jQuery was fixed only one issue. Please see the updated question below for the remaining issue.
Hi all,
I have just run into a weird issue with jQuery.Tipsy.
Here's a simplified demo fiddle: http://jsfiddle.net/6nWtx/7/
As you can see, the lastly added a.tipsy2 element does not get tipsyfied. The .tipsy2 elements are being tipsyfied within a jQuery.each() function and at this point I have the problem. Without the each() it works. Unfortunately, I need .each() to iterate through the elements to do some other stuff before I call tipsy().
Any suggestion?
Here's the source code of Tipsy: https://github.com/jaz303/tipsy/blob/master/src/javascripts/jquery.tipsy.js
IMHO the problem is using the combination of jQuery.each() and Tipsy option live:true
Update:
The other stuff I want to do before calling .tipsy() is checking for some optional configuration.
For example: Help"
In this example I will add the following option to Tipsy: delayIn:1000 If there is no delayed class associated to the element this parameter will be delayIn:0.
Using the same logic, I want to specify the following classes as well: show-top, show-left, show-right, show-bottom for the Tipsy option called gravity.
Example: Help"
The full code:
$(".tipsyfy").each(function () {
var a = "s",
b = 0;
if ($(this).hasClass("show-left")) a = "w";
else if ($(this).hasClass("show-down")) a = "n";
else if ($(this).hasClass("show-right")) a = "e";
if ($(this).hasClass("delayed") && $(this).attr("data-delayIn") != null) b = $(this).attr("data-delayIn");
$(this).tipsy({
gravity: a,
fade: true,
live: true,
delayIn: b
})
})
And here is a full jsFiddle demo with all the stuffs I want to do: http://jsfiddle.net/xmLBG/1/
If you use jQuery 1.7.1 instead of 1.6.4 it will work. Maybe that live feature is relying on something buggy with the older versions, or some not-yet-implemented feature.
Update: from what I understood, you want the tipsy plugin to be called to every element with the .tipsyfy class, present now or added in the future. You don't want to (or can't) call it explicitly before insertion. You're trying to accomplish that using the live option of the plugin. Is that right?
If that's the case I can offer a workaround. I tried to use on (since jQuery's live is deprecated) to bind some code to the load event, but it didn't work, so I bound it to mouseenter and checked whether or not the plugin was already built for that element. If not, it builds it and re-triggers the event.
$(document).on("mouseenter", ".tipsyfy", function(e) {
if ( !$(this).data("tipsy") ) {
e.preventDefault();
var a = "s",
b = 0;
if ($(this).hasClass("show-left")) a = "e";
else if ($(this).hasClass("show-down")) a = "n";
else if ($(this).hasClass("show-right")) a = "w";
if ($(this).hasClass("delayed") && $(this).attr("data-delayIn") != null) b = $(this).attr("data-delayIn");
$(this).tipsy({
gravity: a,
fade: true,
live: true,
delayIn: b
}).trigger("mouseenter");
return false;
}
});
Live example at jsFiddle.
For a small optimization, if the sole purpose of the .tispsyfy class is to instruct the plugin creation, and you don't need it afterwards, you can remove it prior to re-triggering the mouseenter. This way the checking code won't be called over and over again:
$(this).tipsy({...}).removeClass("tipsyfy").trigger("mouseenter");
As far as I can see, you don't need to iterate the nodelist. It looks like tipsy does that for you (see this jsfiddle, where in the first list every element gets its own tooltip (1,2,3).
KooiInc is right,
<a class="tipsy1" href="#" title="Tipsy">TipsyLink</a>
<a class="tipsy1" href="#" title="Tipsy">TipsyLink</a>
<a class="tipsy1" href="#" title="Tipsy">TipsyLink</a>
<br />
<div id="container"></div>
<input id="add" type="button" value="ok">
And
$(".tipsy1").tipsy({live:true,fade:true});
$(".tipsy2").tipsy({live:true});
$("#add").click(function() {
$("#container").append('<a class="tipsy2" href="#" title="Tipsy">TipsyLink</a>');
});
That will work fine
My guess is that Tipsy are uses some kind of direct mapping to the result, not using the live (in 1.6) or on in newer versions of jQuery.
So when your trying to apply the plugin to the links with the class tipsy2 it cant find any (cause your adding it to the DOM at a later stage in your code). The easiest fix to this is just to run the tipsy function at a later stage, perhaps on document.ready.
// this works
$(".tipsy1").tipsy({live:true,fade:true});
// add new tipsy element (ok)
$(document.body).append('<a class="tipsy1" href="#" title="TipsyAjax">AjaxTipsy1</a><br/>');
// add new tipsy element (not ok)
$(document.body).append('<a class="tipsy2" href="#" title="Tipsy">TipsyLink</a>');
$(document).ready(function () {
$(".tipsy2").each(function(){
// I'm doing some other logic here before I call .tipsy()
$(this).tipsy({live:true,fade:true});
})
});
(http://jsfiddle.net/8dg6S/7/)
Can't you do this instead? It is what you are asking.
$(".tipsy1,.tipsy2").tipsy({live:true,fade:true});
$(".tipsy2").each(function() {
//do your stuff
});
I have a new site build on corecommerce system which does not have much access to HTML and non to PHP. Only thing I can use is JavaScript. Their system is currently not great on page load speed so I wanted at least customers to know something is happening while they wait 5-8 seconds for a page to load. So I found some pieces of code and put them together to show an overlay loading GIF while page is loading. Currently it will run if you click anywhere on the page but I want it to run only when a link (a href) on the site is clicked (any link).
I know you can do a code that will run while page loading but this isn't good enough as it will execute too late (after few seconds)
Anyway, this is my website www.cosmeticsbynature.com and this is the code I use. Any help will be great.
<div id="loading"><img src="doen'tallowmetopostanimage" border=0></div>
<script type="text/javascript">
var ld=(document.all);
var ns4=document.layers;
var ns6=document.getElementById&&!document.all;
var ie4=document.all;
if (ns4)
ld=document.loading;
else if (ns6)
ld=document.getElementById("loading").style;
else if (ie4)
ld=document.all.loading.style;
jQuery(document).click(function()
{
if(ns4){ld.visibility="show";}
else if (ns6||ie4)
var pb = document.getElementById("loading");
pb.innerHTML = '<img src="http://www.cosmeticsbynature.com/00222-1/design/image/loading.gif" border=0>';
ld.display="block";
});
</script>
Doing this will be easier if you include jQuery in your pages. Once that is done, you can do:
$('a').click(function() {
// .. your code here ..
return true; // return true so that the browser will navigate to the clicked a's href
}
//to select all links on a page in jQuery
jQuery('a')
//and then to bind an event to all links present when this code runs (`.on()` is the same as `.bind()` here)
jQuery('a').on('click', function () {
//my click code here
});
//and to bind to all links even if you add them after the DOM initially loads (`on()` is the same as `.delegate()` here; with slightly different syntax, the event and selector are switched)
jQuery(document).on('click', 'a', function () {
//my click code here
});
Note: .on() is new in jQuery 1.7.
what you are doing is binding the click handler to the document so where ever the user will click the code will be executed, change this piece of code
jQuery(document).click(function()
to
jQuery("a").click(function()
$("a").click(function(){
//show the busy image
});
How about this - I assume #loading { display:none}
<div id="loading"><img src="http://www.cosmeticsbynature.com/00222-1/design/image/loading.gif" border=0></div>
<script type="text/javascript">
document.getElementById('loading').style.display='block'; // show the loading immediately
window.onload=function()
document.getElementById('loading').style.display='none'; // hide the loading when done
}
</script>
http://jsfiddle.net/vol7ron/wp7yU/
A problem that I see in most of the answers given is that people assume click events only come from <a> (anchor) tags. In my practice, I often add click events to span and li tags. The answers given do not take those into consideration.
The solution below sniffs for elements that contain both events, which are created with jQuery.click(function(){}) or <htmlelement onclick="" />.
$(document).ready(function(){
// create jQuery event (for test)
$('#jqueryevent').click(function(){alert('jqueryevent');});
// loop through all body elements
$('body *').each(function(){
// check for HTML created onclick
if(this.onclick && this.onclick.toString() != ''){
console.log($(this).text(), this.onclick.toString());
}
// jQuery set click events
if($(this).data('events')){
for (key in($(this).data('events')))
if (key == 'click')
console.log( $(this).text()
, $(this).data('events')[key][0].handler.toString());
}
});
});
Using the above, you might want to create an array and push elements found into the array (every place you see console.log