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.
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;
})
});
So I'm trying to use ajax to put content into a div, and trying to have it change all internal links before it adds the content so that they will use the funciton and load with ajax instead of navigating to another page. My function is supposed to get the data with ajax, change the href and onclick attributes of the link, then put it into the div... However, all it's doing is changing the href and not adding an onclick attribute at all. Here's what I was using so far:
function loadHTML(url, destination) {
$.get(url, function(data){
html = $(data);
$('a', html).each(function(){
if ( $.isUrlInternal( this.href )){
this.onclick = loadHTML(this.href,"forum_frame"); // I've tried using both a string and just putting the function here, neither seem to work.
this.href = "javascript:void(0)";
}
});
$(destination).html(html);
});
};
Also, I'm using jquery-urlinternal. Just thought that was relevant.
You can get the effect you want with less effort by doing this on your destination element ahead of time:
$(destination).on("click", "A", function(e) {
if ($.isUrlInternal(this.href)) {
e.preventDefault();
loadHTML(this.href, "forum_frame");
}
});
Now any <a> that ends up inside the destination container will be handled automatically, even content added in the future by DOM manipulations.
When setting a function to onclick through js it will not show on the markup as an attribute. However in this case it is not working because the function is not being set correctly. Easy approach to make it work,
....
var theHref=this.href;
this.onclick = function(){loadHTML(theHref,"forum_frame");}
....
simple demo http://jsbin.com/culoviro/1/edit
I have this JavaScript (with jQuery):
var g_files_added, socket, cookie, database = null;
var file_contents = [];
function viewFile(key, filename) {
$('#title-filename').text(filename);
$('.prettyprint').text(file_contents[key]);
$('#viewFileModal').modal('show');
}
$(document).ready(function() {
$(document).on('shown', '#viewFileModal', function(event) {
prettyPrint();
});
});
// Variables have been set in code not shown, irrelevant to problem.
// prettyPrint() is called everytime the #viewFileModal is shown,
// but its effect is only felt once.
So prettyPrint() is invoked every time the viewFileModal modal box (courtesy of Bootstrap) is shown, it's just that it only seems to have an effect once per page load.
I have tried commenting out prettyPrint() and entering at the JS console after making the modal box appear. It indeed only has an effect the first time the box is shown (per page load).
Any ideas? I have been stuck on this a while. I also tried putting the call to prettyPrint() in the viewFile function; but the effect is the same.
Thanks a lot.
Sam.
Calling "prettyPrint()" adds a class to your PRE tags named "prettyPrinted" after it has been prettified. The line below will remove all instances of the "prettyPrinted" class on your page so that the prettyPrint() function can re-prettify you're PRE tags. This can be done without dynamically adding PRE tags to DIVs.
$('.prettyprinted').removeClass('prettyprinted');
Thanks to Matei. Solution was to change to be like this.
That is, add whole pre dynamically rather than just text.
var g_files_added, socket, cookie, database = null;
var file_contents = [];
function viewFile(key, filename) {
$('#title-filename').text(filename);
$('#fileblock').html('<pre class="prettyprint">' + file_contents[key] + '</pre>'); // fileblock is a div.
$('#viewFileModal').modal('show');
}
$(document).ready(function() {
$(document).on('shown', '#viewFileModal', function(event) {
prettyPrint();
});
});
:)
Joseph Poff answer is correct but you have to be careful. prettPrint() wraps everything in scan tags. If you remove the prettyprinted class, you aren't removing the scan tags. Unless you are clearing the contents of your pre (or stripping out all the scan tags), every time you recall prettyPrint() you will be adding scan tags, which will wrap your old scan tags. It can get out of control really quickly.
how can i alert the user if there are any changes inside the object field
i''m trying to detect the changes on this div inside the object
if it's normal the code would be this:
<div id="HeaderNewMessageIcon" class="BrosixContactNewMessage" style="display:none;">
</div>
but if there are changes it will look like this:
<div id="HeaderNewMessageIcon" class="BrosixContactNewMessage" style="display: block; ">
</div>
i want to alert the user if there are changes inside the object, either via alert or using an image.
is there any way for me to achieve this?
and another thing, i have no access to the code inside the object, i can only view it but not edit it.
I believe there must be some JavaScript code which changing your html you can call your method from there. Other way you can use setInterval.
You can use jQuery plugin Mutation Events plugin for jQuery . see thread
var a = document.getElementsByClassName('HeaderNewMessageIcon')[0];
var oldTitle = a.title;
setInterval(function(){
if(a.title !== oldTitle){
alert("Title change");
oldTitle = a.title;
}
},100);
jsfiddle
You have to detect the changes when throught user interaction such as click, mouseover, mousedown, etc... then you can attach a function to see if its attributes or anything inside it changes.
//detect inputs change
$('#HeaderNewMessageIcon').find(':input').change(function(){ alert(...)});
//detect attributes change
$('#HeaderNewMessageIcon').click(function(){
detectChange(this);
});
As for detectChange to work, you must save the attributes when page just loaded
var attrs = $('#HeaderNewMessageIcon').get(0).attributes;
function detectChange(obj){
//pseudo-code, you need to find a function on the web to commpare 2 objetcs
if (obj.attributes === attrs){
alert(...);
}
//the same comparison for the children elements $(obj).children()
}
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);
});