Using Jquery, I've managed to make a dropdown login form triggered by clicking a button. However, I am also trying to change the direction of the arrow next to it by replacing the src image, and it appears to do nothing.
$("#login_panel").slideToggle(200).toggle(
function() { $("#arrow").attr('src', '/src/east.gif';) },
function() { $("#arrow").attr('src', '/src/south.gif';) }
);
This can be seen at:
http://dev.mcmodcenter.net (The 'Login' button)
$(document).ready(function() {
$("#login_panel").slideToggle(200).toggle(
function() { $("#arrow").attr('src', '/src/east.gif';) },
function() { $("#arrow").attr('src', '/src/south.gif';) }
);
for (var i = 0; i < 2; i++) {
$(".mod").clone().insertAfter(".mod");
}
$(".mod").lazyload({
effect: "fadeIn"
});
});
You can directly access this.src - no need to create a new jQuery object for that:
$('#arrow').toggle(
function() { this.src = '/src/south.gif'; },
function() { this.src = '/src/east.gif'; }
);
And if you prefer to do it via .attr() at least use $(this) (DRY - don't repeat yourself - in this case, don't specify the selector more often than necessary)
$("#arrow").toggle(
function(){$("#arrow").attr("src", "/src/south.gif");},
function(){$("#arrow").attr("src", "/src/east.gif");}
);
You left off the "#" in the handler functions. By just referring to "arrow", you were telling jQuery to look for (presumably absent) <arrow> tags.
Now, as to the larger situation, what you're setting up there is something that'll make the image change when the image itself is clicked. Your description of your goal makes me think that that's not quite what you want, but it's hard to tell. If you want some other element to control the changes to the image, then you'd attach the handler(s) elsewhere.
Is the image you want to change that little black arrow next to the login button? If so, then what should happen is that the code to set the image should be added to the existing handler that slides the login form up and down. (By the way, in Chrome the login box shows up in what seems like an odd place, far to the left of the button.)
looks like you forget to put the # before the arrow in $("arrow")
it should be like this
$("#arrow").toggle(
function(){$("#arrow").attr("src", "/src/south.gif");},
function(){$("#arrow").attr("src", "/src/east.gif");}
);
$("arrow") will match <arrow>, you lost the #
Also, the toggle method does not take two functions as its arguments, it works in a completely different way to what you are trying to do with it. Yes, it does, there are two different toggle methods for jQuery (insert rant about awful API design)
And now you have completely edited the code…
Your code now immediately assigns strings to the this.src (where this is (I think) the document object), and then passes those two strings as arguments to the toggle method (which are not acceptable arguments for it)
And now you have completely edited it again…
This code should work:
$('#login_button').click(function() {
$(this).find('#arrow').attr('src', function(i, v) {
return v.indexOf('east.gif') < 0 ? '/src/east.gif' : '/src/south.gif';
});
$('#login_panel').slideToggle(200);
});
Related
I'm trying at the moment to target multiple instances of the same div class (.overlay) - the basic idea I'm trying to execute is that each div contains a HTML5 video inside another wrapped div which on mouseenter reveals itself, sets the video timeline to 0 and plays, and on mouseout resets the video to 0 again.
The problem I'm having is that only the first item of my grid works at the moment with nothing happening on the rollover of the others. This is my Javascript:
$(document).ready(function() {
$('.overlay').mouseenter(function(){
$('#testvideo').get(0).play();
}).mouseout(function() {
$('#testvideo').get(0).pause();
$('#testvideo').get(0).currentTime = 0;
})
});
I've also tried the following
$(document).ready(function() {
$('.overlay').mouseenter.each(function(){
$('#testvideo').get(0).play();
}).mouseout(function() {
$('#testvideo').get(0).pause();
$('#testvideo').get(0).currentTime = 0;
})
});
but that simply broke the functionality all together!
Here is a fiddle showing what should happen: http://jsfiddle.net/jameshenry/ejmfydfy/
The only difference between this and the actual site is that there are multiple grid items and thumbnails. I also don't want the behaviour to by asynchronous but rather individual - does anyone have any idea where I'm going wrong (I'm guessing my javascript!)
The problem is that you're using always $('#testvideo'), independent on the div you're entering the mouse. Since the HTML's id property must be unique, only the first element that you set the id testvideo will work the way you expect.
You should be using the video tag referenced by the div.overlay, or you could add a CSS class to the video tags, so you could use that class to find the video.
The code below will get the overlayed video, independent of which it is.
$(document).ready(function() {
$('.overlay').hover(function() {
$(this).parent().find('video').get(0).play();
}, function() {
var video = $(this).parent().find('video').get(0);
video.pause();
video.currentTime = 0;
});
});
Take a look at your updated fiddle.
The first way you did it should work, the second one not. But, you shouldn't use an id like #testvideo if there are a lot of videos (one on each .overley element). Having multiple instances of the same id produce unexpected behaviuor, like "only working on the first item".
You should change your #testvideo with .testvideo and change your code to something like this:
$(document).ready(function() {
$('.overlay').mouseenter(function(){
$(this).find('.testvideo').play();
}).mouseout(function() {
$(this).find('.testvideo').pause();
$(this).find('.testvideo').currentTime = 0;
})
});
I'm fairly new to Javascript, and am trying to get an 'on click enlarge' kind of effect, where clicking on the enlarged image reduces it again. The enlarging happens by replacing the thumbnail by the original image. I also want to get a slideshow using images from my database later on.
In order to do that, I made a test where I replace the id which indicates enlarging is possible by a class and I also use a global variable so that I can keep a track of the url I'm using. Not sure this is the best practice but I haven't found a better solution.
The first part works fine, my image gets changed no problem, values are also updated according to the 'alert' statement. However, the second part, the one with the class never triggers.
What am I doing wrong (apart from the very likely numerous bad practices) ?
If instead of changing the class I change the id directly (replacing .image_enlarged by #image_enlarged, etc.), it seems to call the first function, the one with the id, yet outputs the updated id, which is rather confusing.
var old_url = "";
$(function(){
$('#imageid').on('click', function ()
{
if($(this).attr('class')!='image_enlarged'){
old_url = $(this).attr('src');
var new_url = removeURLPart($(this).attr('src'));
$(this).attr('src',new_url); //image does enlarge
$(this).attr('class',"image_enlarged");
$(this).attr('id',"");
alert($(this).attr('class')); //returns updated class
}
});
$('.image_enlarged').on('click', function (){
alert(1); //never triggered
$(this).attr('src',old_url);
$(this).attr('class',"");
$(this).attr('id',"imageid");
});
});
function removeURLPart(e){
var tmp = e;
var tmp1 = tmp.replace('thumbnails/thumbnails_small/','');
var tmp2 = tmp1.replace('thumbnails/thumbnails_medium/','');
var tmp3 = tmp2.replace('thumbnails/thumbnails_large/','');
return tmp3;
}
As for the html, it's really simple :
<figure>
<img src = "http://localhost/Project/test/thumbnails/thumbnails_small/image.jpg" id="imageid" />
<figcaption>Test + Price thing</figcaption>
</figure>
<script>
document.write('<script src="js/jquery-1.11.1.min.js"><\/script>');
</script>
<script type="text/javascript" src="http://localhost/Project/js/onclickenlarge.js"></script>
From the API: http://api.jquery.com/on/
The .on() method attaches event handlers to the currently selected
set of elements in the jQuery object.
When you do $('.image_enlarged').on(...) there is no element with that class. Therefore, the function is not registered in any element.
If you want to do so, then you have to register the event after changing the class.
Here's an example based on your code: http://jsfiddle.net/8401mLf4/
But this registers the event multiple times (every time you click) and it would be wrong. So I would do something like:
$('#imageid').on('click', function () {
if (!$(this).hasClass('image_enlarged')) {
/* enlarge */
} else {
/* restore */
}
}
JSfiddle: http://jsfiddle.net/8401mLf4/2/
Try using:
addClass('image-enlarged')
instead of:
.attr('class',"image_enlarged");
the best way to do this would be to have a small-image class and a large image class that would contain the desired css for both and then use addClass() and removeClass depending on which you wanted to show.
This is probably basic to most reading, but I can't seem to figure it out.
I have a little test function that I want to execute if under a certain width. When the screen rotates or gets resized above that width, I want the function to cease to work. Here is some example code for simplicity sake.
enquire.register("screen and (max-width:500px)",{
match : function() {
$(".block .block-title").click(function(){
alert("Hello World!");
});
}
}).listen();
So if the page loads above 500px, it works as intended. Clicking won't execute. If the page loads at 500px or below, the click function executes. Only problem is that if you resize the viewport or change orientation to something above 500px, the function still executes. I'd like to be able to disable that.
The real world scenario I'm actually trying to do here is I have an un-ordered list of 4 items. Above a certain width they are displayed right away. If under a certain width, I just want to hide them and on click show them. I know there are a few ways to do it (.toggle(), .toggleClass("myclass"), etc).
I have done this a bunch of times but I always get caught with the entering / exiting break points and things not being reset, or working as intended. Usually it doesn't matter, but lately in some of my use cases it has mattered.
I know of the unmatch option but I'm not sure how to really kill the matched function above.
enquire.register("screen and (max-width:500px)",{
match : function() {
$(".block .block-title").click(function(){
alert("Hello World!");
});
},
{
unmatch : function() {
// what do I do here do kill above?
}
}
}).listen();
Any help would be appreciated. I am pretty sure it will help my current situation but will also help me expand my knowledge of enquire.js for other things.
Thanks.
edit: I forgot to mention... if you load the page under 500px, then resize or orientate wider then 500px, then go BACK under 500px, the click function won't work again.. which confuses me also. I basically was hoping it would work no matter what when under 500px, and not work at all when over 500px.
I'm the author of enquire.js, so hopefully I'll be able to help you ;-)
Basically, you want to add an event handler on match and remove event handler on unmatch. You seem to have the gist of how to do this above, but you've got the syntax a little wrong. Once the syntax is corrected it's just some jQuery knowledge to remove the click handler.
So let's look at how the syntax should be:
enquire.register("screen and (max-width:500px)", {
match: function() {
//match code here
},
unmatch: function() {
//unmatch code here
}
}).listen();
Notice that match and unmatch are part of a single object supplied to register.
Ideally you should be putting this in your document ready callback. To assign your click handler use jQuery's on method, as this allows you to use the off method to unassign:
$(".block .block-title").on("click", function() {
alert("hello");
});
$(".block .block-title").off("click");
This is great because you can even namespace your events, read up on the jQuery docs for more details on this. So to put it all together, we would have this:
$(document).ready(function() {
var $target = $(".block .block-title");
enquire.register("screen and (max-width:500px)", {
match: function() {
$target.on("click", function() {
alert("Hello World!");
});
},
unmatch: function() {
$target.off("click");
}
}).listen();
});
You can find a working example here: http://jsfiddle.net/WickyNilliams/EHKQj/
That should then be all you need :) Hope that helps!
Thought I'd post here. My first hour on jQuery, actually first programing ever done. Would love to learn whats not right and how it could be better.
$(function() {
function hide_me()
//A place to specify which elements you want hidden, on page load.
{
$("li.credentials").hide();
}
function first_bow()
//The div right_column takes a bow on initial load.
{
$("div#right-column").show("drop");
}
function bigpeek()
//The third column toggles in/out. All elements under div right_column.
{
$("div#right-column").toggle("drop", "fast");
}
function smallpeek()
//Smaller snippets like credentials or user assignment flying in/out.
{
$("li.credentials").toggle("drop", "fast");
}
$(document).ready(function() {
$("*").ready(hide_me);
$("*").ready(first_bow);
$(".btn-new-email").click(bigpeek);
$(".button").click(smallpeek);
$(".icon-delete").mouseover(function() {
$(this).effect("bounce", "fast");
});
});
});
The best thing to learn about programming is how to effectively re-use code. In your code, you have set up some functions that you yourself claim will do a bunch of the same thing. So instead, you could make it better by only writing code to do the repeated task once.
For one example, instead of creating a function where you place a bunch of things that need to be hidden, I would add a class to the elements that should be hidden, and then hide all those elements:
function hide_me()
//Hides anything with the "hide-me-onload" class
{
$(".hide-me-onload").hide();
}
$(function () {
...
}
is the same as
$(document).ready(function() {
...
}
So you can move the method calls from inside your $(document).ready() to be inside your $(function(){}). Also try to use IDs instead of class names wherever possible. Something like this will go through the entire DOM to look for an element
$(".item")
Be more specific
$("#itemID") // use IDs instead of Classes
//If you have to use class name then you can speed up the selector by adding the element tag before it
$("div.item")
Using $("*").ready() within $(document).ready() is redundant... you already know using all of the elements are ready! Also, in general using the universal selector $('*') is very inefficient.
So, the first two lines of your $(document).ready() can just be:
hide_me();
first_bow();
Other than that and a couple of issues with organization and nomenclature you're off to a great start, keep it up!
I want to provide a method for my web app that allows a user to call my function anywhere within his code (inside script tags) that will display a fade-in/fade-out message. What I don't know how to do is determine where I am at in the DOM without having a starting reference point.
Function:
function displayMessage(message) {
// Display a notification if the submission is successful.
$('<div class="save-alert">' + message + '</div>')
.insertAfter($('')) // Do not know how to know where to put the message.
.fadeIn('slow')
.animate({ opacity: 1.0 }, 2000)
.fadeOut('slow', function () {
$(this).remove();
});
}
The HTML:
<!-- Some HTML -->
<div>
<script type="text/javascript">
displayMessage("My message.");
</script>
</div>
<!-- Some more HTML. -->
There isn't any reliable way to get this information. You should do what most other libraries do -- have the user pass in the ID or reference of an element to your displayMessage function so that you can use it.
Generally there are two ways, one, as Casablanca noted you provide a div in the DOM to append the message. Second, and this is the one I think you want, is to create a div node on the DOM itself. That way you have total control. After all it is going to fade out when you're done. Might as well kill it from the dom as well. This is what fancylightbox (and I am sure many others) does with the DOM. You'd want to place it right at the beginning of the body, so there are no other containing elements, and style it as you wish - likely so it floats somewhere near the middle of the page like a lightbox/dialog box.
Unless you want to take in a css selector or an id as argument there is also an alternative to create a jQuery widget. This way you can use it like:
$("#msgArea").messageWidget("displayMessage");
or even reuse it many times
$("#msgArea").messageWidget("displayMessage", "message to display");
Sample boilerplate widget:
(function( $ ) {
$.widget("ui.messageWidget", {
// default options
options: { message: undefined},
// constructor
_create: function() {
if (this.options.message !== undefined) {
this.displayMessage(this.options.message);
}
},
// Displays the message
displayMessage: function() {
this.element.append("your div's and messages");
},
// Allows constructor/setter arguments
_setOption: function( key ) {
$.Widget.prototype._setOption.apply( this, arguments );
}
});
}(jQuery));
You probably want to use fixed positioning to put your box at a place relative to the browser's viewport, regardless of where a user has scrolled to in the document.