I'm working on a gallery that pulls up a full image inside a tooltip when hovering over thumbnails. The problem is, these full images commonly go outside the viewfinder. To remedy this, I'm moving the tooltip if the image will go outside the window boundaries, which requires immediately knowing the images dimensions (to avoid the tooltip jumping around).
However, the images take a bit to load (.gifs) so I can't wait on DOM in order to get the dimensions. So, I'm calling a PHP script to return the the image dimensions before they load.
The problem I'm having is that there's no response from my $.get call. I know the PHP script is working fine, but I'm not getting any data back from it through jquery. Any help would be greatly appreciated. Thanks!!
hover.js:
this.imagePreview = function(){
$("a.preview").hover(function(e){
var viewHeight = $(window).height() + $(window).scrollTop();
var viewWidth = $(window).width();
var xOffset=e.pageX+40;
var yOffset=e.pageY+40;
var url = 'http://mysite.com/i/' + this.href.slice(20);
var w = 0;
var h = 0;
$("body").append("<div id='preview'><img src=" + url +" id='img'/></div>");
$.get("getDimensions.php/?img=" + url, function(data){
w = data.w;
h = data.h;
$("body").append("INFO ABOUT IMAGE DIMENSIONS TRIGGERED: " + w + h);
});
$("#preview")
.css("top",yOffset + "px")
.css("left",xOffset + "px")
.fadeIn("fast");
$('#img').load(function() {
if((e.pageX+img.width)>viewWidth) { xOffset=e.pageX-img.width-70; }
if((e.pageY+img.height)>viewHeight) { yOffset=e.pageY-img.height-70; }
$("#preview")
.css("top",yOffset + "px")
.css("left",xOffset + "px")
.fadeIn("fast");
});
},
function(){
$("#preview").remove();
});
};
// starting the script on page load
$(document).ready(function(){
imagePreview();
});
getDimensions.php:
<?php
list($width, $height, $type, $attr) = getimagesize($img);
echo json_encode(array("w"=>$width,"h"=>$height));
?>
$("body").append("<div id='preview'><img src=" + url +" id='img'/></div>");
when u append the img which have src prop,that will not fire load event any more.That's the problem is.
Have you tried..
var rand = Math.floor(Math.random()*11);
$.get("getDimensions.php/?img=" + url + "&r=" + rand, function(data){
w = data.w;
h = data.h;
$("body").append("INFO ABOUT IMAGE DIMENSIONS TRIGGERED: " + w + h);
},"json");
( Also, I would strongly recommend .ajax over .get)
Can you view what you are getting back from getDimensions.php (in firebug)?
My guess is that jQuery has no way of knowing that the data returned from getDimensions.php is JSON (as opposed to plain old text), and it isn’t trying to parse it.
What's the value of data (if you print it out to the console)?
If this is the problem, you can solve it by adding this line to the PHP script, before echo:
header('Content-Type: application/json');
Related
I'll try to keep this simple and clear. I'm pretty new to using API's but I'm using the Flickr API to search for and display photos on my website based on a certain tag. For a simple, static web page this is quite simple and I've already got it working as intended. This is the jquery script I found to use:
$(function() {
var apiKey = 'MY_API_KEY_IS_IN_HERE';
var tag = '%23FFLIVE2014-09-03';
var perPage = '25';
var showOnPage = '6';
$.getJSON('http://api.flickr.com/services/rest/?format=json&method='+
'flickr.photos.search&api_key=' + apiKey +
'&tags=' + tag + '&per_page=' + perPage + '&jsoncallback=?',
function(data){
var classShown = 'class="lightbox"';
var classHidden = 'class="lightbox hidden"';
$.each(data.photos.photo, function(i, rPhoto){
var basePhotoURL = 'http://farm' + rPhoto.farm + '.static.flickr.com/'
+ rPhoto.server + '/' + rPhoto.id + '_' + rPhoto.secret;
var thumbPhotoURL = basePhotoURL + '_s.jpg';
var mediumPhotoURL = basePhotoURL + '.jpg';
var photoStringStart = '<a ';
var photoStringEnd = 'title="' + rPhoto.title + '" href="'+
mediumPhotoURL +'"><img src="' + thumbPhotoURL + '" alt="' +
rPhoto.title + '"/></a>;'
var photoString = (i < showOnPage) ?
photoStringStart + classShown + photoStringEnd :
photoStringStart + classHidden + photoStringEnd;
$(photoString).appendTo("#flickr");
});
$("a.lightbox").lightBox();
});
});
Create a #flickr div on a page and load that script, photos tagged #FFLIVE2014-09-03 would be displayed, if there are any. My problem is that the site/page I want to show the photos on is dynamic with data generated from a database. So website.com/page.php is the single page, in the database is data for a certain date and a performance that happened on it (For a band).
So what I'm struggling with is how to dynamically edit the tags searched for in the script. With the above script placed in my page.php obviously page.php?id=1 and page.php?id=261 will show the same photos, because the tags searched will be the same when in fact they should be different, based on the date for the data.
So, is there some way to do this? Generate the correct date tag to search for based on the database data? I can generate the correct tag inside the PHP file itself quite easily, just echo the first part of the tag then the date. But how would I do that in relation to the javascript? I gather it is possible to use PHP within Javascript but that would be outside the database, so it wouldn't know what it was generating.
I hope that makes sense!
Ok, here's my issue. The following code works as intended, but I have this nagging feeling that I should be able to solve the problem more succinctly. I'm writing a script that will allow a person to pan/tilt/zoom an IP camera using custom controls on an html page. I've layed out the direction icons in a numberpad-style arrangement representing up, down, left-up etc... like so:
1 2 3
4 _ 6
7 8 9
When the user holds the mousedown on an icon, the img is swapped out for an active version and the command to begin the action is sent to a php cURL script, along with the respective direction (icon id). When the mouse is released the image is again swapped for the inactive version and the command is sent to the cURL script to stop moving in that same direction.
This works as long as the mouse is kept hovering over the same icon that was initially selected. If the person let the mouse leave the icon and then releases it, the second function checks to see if any of the directions are currently activated, inactivating them and sending a respective stop command to the cURL script.
Is there a way to actually accomplish this using one function?
// PTZ MOVEMENT / IMAGE SWAP
$('.nav-control').on('mousedown mouseup', '.ptz-cmd', function(e){
var thisCmd = $(this).attr('id'); // 1 - 9, designating numberpad style of movement
var thisAction = $(this).attr('action') // pantilt or zoom
if (e.type == 'mousedown') {
$(this).attr('src','img/' + thisCmd + 'h.png'); // example: 1h.png = active icon, 1b.png = inactive icon
$('#ptz').load("ptz.php?action=" + thisAction + "&cmd=" + thisCmd); // movement is handled by php cURL script and 'loaded' into a hidden div
} else {
$(this).attr('src','img/' + thisCmd + 'b.png');
$('#ptz').load("ptz.php?action=" + thisAction + "&cmd=stop"); // stop the movement or zoom for this direction...
}
});
// CANCEL MOVEMENT AND REPLACE IMAGE IF MOUSE LEAVES ICON AND IS RELEASED
$('.nav-control').on('mouseleave', '.ptz-cmd', function(e){
$('#ptz').load("ptz.php?action=pantilt&cmd=stop");
$('.ptz-cmd:not([action=preset])').each(function(){
if($(this).attr('src').substring(5) == "h.png"){
var whichDirection = $(this).attr('src').substring(0,5);
$(this).attr('src',whichDirection + 'b.png')
}
});
});
Absolutely:
var $ptz = $('#ptz');
$('.nav-control').on({
mousedown:function(){
var self = this,
thisCmd = self.id,
thisAction = self.action;
self.src = 'img/' + thisCmd + 'h.png';
$ptz.load("ptz.php?action=" + thisAction + "&cmd=" + thisCmd);
},
mouseup:function(){
var self = this,
thisCmd = self.id,
thisAction = self.action;
self.src = 'img/' + thisCmd + 'b.png';
$ptz.load("ptz.php?action=" + thisAction + "&cmd=stop");
},
mouseleave:function(){
$ptz.load("ptz.php?action=pantilt&cmd=stop");
$('.ptz-cmd').filter(':not([action=preset])').each(function(){
var self = this,
src = self.src;
if(src.substring(5) === 'h.png'){
self.src = src.substring(0,5) + 'b.png';
}
});
}
},'.ptz-cmd');
Changes:
By using the object form of .on(), you can consolidate these three events into a single binding
By splitting mousedown and mouseup, there is less runtime parsing (no checking events, less code per run of each, etc)
Using vanilla JS vs jQuery is faster, used for items like src,id, and action.
Use of === instead of == is more strict, and therefore more standards-compliant
Caching of $('#ptz') at top will save extra DOM scrapes
This isn't tested, but the theory behind it is sound. Even if you only take away the first point, you will have consolidated all your event bindings into a single call, and delegated appropriately.
Alternative:
var $ptz = $('#ptz');
$('.nav-control').on({
'mousedown mouseup':function(e){
var self = this,
cmdImg = self.id,
thisAction = self.action,
img = 'h',
thisCmd = cmdImg;
if(e.type === 'mouseup'){
img = 'b';
thisCmd = 'stop';
}
self.src = 'img/' + cmdImg + img + '.png';
$ptz.load("ptz.php?action=" + thisAction + "&cmd=" + thisCmd);
},
mouseleave:function(){
$ptz.load("ptz.php?action=pantilt&cmd=stop");
$('.ptz-cmd').filter(':not([action=preset])').each(function(){
var self = this,
src = self.src;
if(src.substring(5) === 'h.png'){
self.src = src.substring(0,5) + 'b.png';
}
});
}
},'.ptz-cmd');
This just maintains the mouseup and mousedown combination, checking the event type to see which it is. Its every-so-slightly slower, but consolidates the codebase into a single function, making maintenance a bit easier. Notice in this option when you have two different events you need to make it a string, e.g. 'mouseup mousedown' vs mouseup mousedown ... you can only use the object names if there is a single object.
Either one of these options should put you on the right track.
I have a vanilla flexslider installation on my site. The slider operates by cycling through list items in an unordered list. You can add captions simply by adding a caption container after the list item. This works well with hard coded images.
The problem I am facing is that my site has multiple sections, with a different slide show for each section. Instead of hard coding the li elements, I'm generating them with php, so that when a user visits a page, the php figures out which page the user is viewing, and passes that through to the slideshow. The slideshow then finds the proper image directory and loads all of the images in that directory whether there be two or twenty. It's much easier than hard coding each slideshow, and it works beautifully.
<?php
$dh = "image/slideShows/$slideShow/";
$images = glob($dh . "*.jpg");
foreach($images as $image){
?><li><img src="<?php echo $image;?>" alt="caption text" /></li><?php
}
closedir($dh);
?>
I need to get flexslider to read the alt text for each dynamically generated image, and then place it in a caption container:
<p class="caption">The alt text should show up here.</p>
I've tried using:
$(window).load(function() {
$('.flexslider').flexslider({
animation: "fade",
controlsContainer: "#slideShowContainer",
start: function(slider) {
$('.caption').html(this.alt);
},
});
});
and playing around with flexslider's current.slide to no avail. I've been searching on this all night and I can't seem to figure this one out. I'm hoping someone here can provide the missing link for me.
Thanks in advance.
EDIT: I figured this out, and it was seriously a matter of over-complication. All I had to do was call the EXIF data that I was using for the "alt" attribute inside of the caption. I have no idea why it took me so long to realize this. Thank you both for your help!
start: function(slider) {
var slideNumber = slider.currentSlide;
var alt = $('.slides img').eq(slideNumber + 1).attr('alt');
$('.caption').html('<p>' + alt + '</p>');
},
before: function(slider) {
var slideNumber = (slider.currentSlide + 1);
var alt = $('.slides img').eq(slideNumber + 1).attr('alt');
$('.caption').html('<p>' + alt + '</p>');
}
It sounds like you have only one .caption box? And you want its contents to change with each slide?
I would try something like:
before: function(slider) {
var slideNumber = slider.currentSlide;
var alt = $('.slides img').eq(slideNumber).attr('alt');
$('.caption').html('<p>' + alt + '</p>');
});
},
note that before runs at each slide transition, not just once like start
Edit
OP adjusted the above code (see comments below), but still has the "issue mentioned in the comment where the first image doesn't get a caption on it's second and subsequent scrolls"
Perhaps we should be using after instead of before? That way we don't need to do slideNumber+1 (since before was making this the previous slide.. You can perhaps remove the start function in favor of just doing this above the flexslider call
in $(window).load(function(){ or (document).ready(){:
var alt = $('.slides img').eq(0).attr('alt');
$('.caption').html('<p>' + alt + '</p>');
and within flexslider()
after:function(slider) {
var slideNumber = slider.currentSlide;
var alt = $('.slides img').eq(slideNumber).attr('alt');
$('.caption').html('<p>' + alt + '</p>');
},
Could do with some help I have a simple ajax powered stickies app (with jquery UI and PHP) in development, my code below stores X, Y for dragged items posts it to a database and loops results back to a div. I have successfully built code for a text version (akin to post it notes) but I am trying to do a draggable/scalable version to hold images. But when I do this my positions are being stored in the database looped out into a #projbaord div but not being used to correctly position the HTML elements (i have checked the page source and the style: is showing correct x, y but this is not reflected on screen).
I think the problem must be in the loop out of the PHP and style of the position x, y but cannot seem to fathom it out! Any ideas or another way of achieving same result?
I thought this maybe a position:relative/absolute problem but that seems to be okay - I am stumped at present! Hope you can genius can help!
Javascript to handle behaviour and store values in database:
function imageStickyDragXYUpdate(){
$(".imagesticky").each(function(index){
var resizethese = $(this).children();
$(this).draggable({
cursor: 'move',
stack: '.imagesticky',
opacity: '0.5',
containment: '#projboard',
scrollspeed: '40',
scrollSensitivity: '10',
stop:function(){
var coord=$(this).position();
var coordLeft = coord.left;
var coordTop = coord.top;
var imageStickyid = $(this).attr('imagestickyid');
//alert('x='+ coordTop + 'y=' + coordLeft + 'id=' +imageStickyid);
var datastring = 'xupdateimg='+ coordTop + '&y=' + coordLeft + '&imgstickyid=' +imageStickyid + '&projid=' + proj_id + '&uid=' + uid;
//alert(datastring);
$.ajax({
type: "POST",
url: "uploaddata.php",
data: datastring,
success: function(data){
$("#projboardresults").html(data);
textStickyDragXYUpdate();//not important other function for working text stickies
imageStickyDragXYUpdate();
}
});
}
});
});
}
PHP to show results
<?php
$user_id= $_POST['uid'];
$proj_id=$_POST['projid'];//to be validated as int
$get_imgsticky_query = "SELECT * FROM imagesticky WHERE user_id = $user_id AND project_id=$proj_id";
$get_imgsticky_result=mysql_query($get_imgsticky_query);
while($row=mysql_fetch_assoc($get_imgsticky_result)){
$x = $row['imagesticky_x'];
$y = $row['imagesticky_y'];
$imagesticky_w = $row['imagesticky_w'];
$imagesticky_h = $row['imagesticky_h'];
$imagesticky_url = $row['imagesticky_url'];
$imagesticky_id = $row['imagesticky_id'];
echo '<div class="imagesticky" imagestickyid="'.$imagesticky_id.'" style="position: absolute; left:'.$x.'px; top:'.$y.'px;">
<a class = "clickaddimage" href="addimage.php"><img src="images/clicktoadd.png" alt="add image" title="Click to add image"</a>
<img src="'.$imagesticky_url.'" width="'.$imagesticky_w.'" height="'.$imagesticky_h.'"/>
<img src="images/closey.png" title="delete" alt="delete"/>
</div>';
}
?>
var datastring = 'xupdateimg='+ coordTop + '&y=' + coordLeft + '&imgstickyid=' +imageStickyid + '&projid=' + proj_id + '&uid=' + uid;
This line was the problem, I had the X variable storing the Y value and the Y coordinate storing the X variable! So my code appeared to be placing items in the wrong place, but was actually working perfectly. That is what you get for being a new father and trying to code! Why did I could not spot this yesterday? LOL!
I'm working on a GMaps application to retrieve images, via getJSON(), and to populate a popup marker.
The following is the markup which I add to the marker dynamically:
<div id="images"></div>
<div id="CampWindow" style="display:none;width:550px;height:500px;">
<h4 id="camp-title"></h4>
<p>View... (all links open in new windows)</p>
<ul>
<li><a id="camp-hp-link" target="_blank" href="">camp home page</a></li>
<li>information: <a id="camp-av-link" target="_blank" href="">availability</a> | <a id="camp-vi-link" target="_blank" href="">vital information</li>
</ul>
<p id="message"></p>
I've been clawing out my eyes and woohoo for the past couple of days, trying to get the images to show inside the CampWindow . Then, I decided to think laterally and to see if the images were being retrieved at all. I then moved the images outside and sure as Bob (Hope), the images were being retrieved and refreshed with every click.
So, I decided to the keep the images outside and then once loaded, append it to the CampWindow . It's not working still; when I append the div to the main CampWindow div, the images won't show. I check in Firebug with the pointer thingy and it shows me the images as empty. I try it again with the images outside and it shows the images. I've tried before append and appendTo with no success. Am I missing something here?
I have no more woohoo to claw out. Please, please help.
marker.clicked = function(marker){
$("#images").html('');
$('#camp-title').text(this.name);
$('#camp-hp-link').attr('href', this.url);
$('#camp-av-link').attr('href', this.url + '/tourism/availability.php');
$('#camp-vi-link').attr('href', this.url + '/tourism/general.php');
// get resort images via jQuery AJAX call - includes/GetResortImages.inc.php
$.getJSON('./includes/GetResortImages.inc.php', { park: this.park_name, camp: this.camp_name }, RetrieveImages);
function RetrieveImages (data)
{
if ('failed' == data.status)
{
$('#messages').append("<em>We don't have any images for this rest camp right now!</em>");
}
else
{
if ('' != data.camp)
{
$.each(data, function(key,value){
$("<img/>").attr("src", value).appendTo('#images');
});
}
}
}
//.append($("#images"));
$("#CampWindow").show();
var windowContent = $("<html />");
$("#CampWindow").appendTo(windowContent);
var infoWindowAnchor = marker.getIcon().infoWindowAnchor;
var iconAnchor = marker.getIcon().iconAnchor;
var offset = new google.maps.Size(infoWindowAnchor.x-iconAnchor.x,infoWindowAnchor.y-iconAnchor.y);
map.openInfoWindowHtml(marker.getLatLng(), windowContent.html(), {pixelOffset:offset});
}
markers.push(marker);
});
When you add the <html> tag to your page it confuses the browser and is most likely the problem. I would suggest to either do as Pointy said and use window.open() to make a popup window (check out this tutorial), or better yet try out one of the many jQuery light box plugins.
I'm not sure what you are doing with the google maps, so I decided to just go with a basic example for you. With this script, if you click on an image inside the #image div, it'll open a popup window the same size as the image.
$(document).ready(function(){
$('#images img').click(function(){
var padding = 20;
var w = $(this).width() + padding;
var h = $(this).height() + padding;
var popup = '\
<html>\
<head>\
<link type="text/css" href="popup-style.css" rel="stylesheet" />\
<scr'+'ipt type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></scr'+'ipt>\
</head>\
<body>\
<img src="' + $(this).attr('src') + '">\
</body>\
</html>';
var pop = window.open('','Image View','toolbar=0,location=0,status=0,width=' + w + ',height=' + h + ',scrollbars=1,resizable=1');
pop.document.write(popup);
pop.document.close();
})
});
NOTE: When adding a script tag inside a string, make sure you break up the word "script" otherwise you will get an error.
Update #2:
Ok, since you want to work with what you have, try doing this:
Remove the <html> tag from your campwindow, then position your campwindow using CSS and/or javascript. Add something like:
var w = $(window).width();
var h = $(window).height();
// Add overlay and make clickable to hide popup
// you can remove the background color and opacity if you want to make it invisible
var $overlay = $('<div/>', {
'id': 'overlay',
css: {
position : 'absolute',
height : h + 'px',
width : w + 'px',
left : 0,
top : 0,
background : '#000',
opacity : 0.5,
zIndex : 99
}
}).appendTo('body');
// Position your popup window in the viewport
$('#CampWindow').css({
position: 'absolute',
top : $(window).scrollTop() + 50 + 'px',
left : w/2 - $('#CampWindow').width()/2 + 'px', // centers the popup
zIndex : 100
})
.fadeIn('slow');
// Click overlay to hide popup
$('#overlay').click(function(){
$('#CampWindow').hide();
$(this).remove(); // remove the overlay
})