This probably is a duplicate but I don't know how to express what is happening in a title description.
I have an image element which i delete and re-create with the click of a button, basically i apply filters with php to an image, and delete the previous element to replace it with the new image to display the new filter.
the code to create the element:
function pictureReset(data) {
$( ".filteredImg" ).remove();
var elem = document.createElement("img");
elem.setAttribute("class", "filteredImg");
elem.setAttribute("height", "328");
elem.setAttribute("alt", "");
elem.src = 'contest/filtered_'+tempFilePath;
document.getElementById("filteredImgContainer").appendChild(elem);
}
the code to apply the filter: (i have several filters but the code is the same, they just call a different php file
$('#sepia').click(function () {
var filePathName = tempFilePath;
$.ajax({
type: 'POST',
url: 'php/sepia.php',
dataType : 'text',
data: {
FilePath : filePathName
},
success: function (data) {
pictureReset();
}
}).done(function(response){console.log(response);});
});
now the problem is although it works fine on chrome, i.e. when i click the button the old image is removed and replaced with the new filtered image, on firefox although it refreshes, somehow it retrieves the old image (even though it doesn't exist because on the server if i retrieve the image the filter is applied), and displays the old filter instead of the new one. Any ideas as to why this is happening??
Apart from adding the parameters, you can also improve the code. Since you are already using jQuery.
You can replace this code:
function pictureReset(data) {
$( ".filteredImg" ).remove();
var elem = document.createElement("img");
elem.setAttribute("class", "filteredImg");
elem.setAttribute("height", "328");
elem.setAttribute("alt", "");
elem.src = 'contest/filtered_'+tempFilePath;
document.getElementById("filteredImgContainer").appendChild(elem);
}
With:
function pictureReset(data) {
var elem = $('<img class="filteredImg" alt="" style="height:328px;" src="contest/filtered_' + tempFilePath + '?t="' + $.now() + ' />');
$("#filteredImgContainer img.filteredImg").replaceWith(elem);
}
I used jQuery replaceWith for this code.
Related
I've looked at numerous other answers regarding this but haven't found a solution that has worked. I'm using a PHP page that contains some HTML code, with Javascript working some functions. Ideally I would select an image on the page, the image will become colored green as it is selected. I would then like to deselect the image and have it return to the original state. I can only get half-way there however. What am I missing? Is it something with post back?
Here's some code examples:
The HTML:<div onclick="changeImage(1)" id="toolDiv1"><img id="imgCh1" src="/images/Tooling/1.png"></div>
The Javascript function:
function changeImage(var i){
var img = document.getElementById("imgCh" + i + ".png");
if (img.src === "images/Tooling/" + i + ".png"){
img.src = "images/Tooling/" + i + "c.png";
}
else
{
img.src = "images/Tooling/" + i + ".png";
}
}`
The "1c.png" image is the one that is selected and should replace "1.png". There are multiple divs on this page that hold multiple images, which are named 2/2c, 3/3c, which is why the var i is included. Any insight? Thanks in advance.
You could do it something like this, it would also allow for different file names.
<img class="selectable" src="/images/Tooling/1.png"
data-original-source="/images/Tooling/1.png"
data-selected-source="/images/Tooling/1c.png">
<img class="selectable" src="/images/Tooling/2.png"
data-original-source="/images/Tooling/2.png"
data-selected-source="/images/Tooling/2c.png">
var images = document.getElementsByClassName('selectable');
for (var image of images) {
image.addEventListener('click', selectElementHandler);
}
function selectElementHandler(event) {
var image = event.target,
currentSrc = image.getAttribute('src'),
originalSrc = image.getAttribute('data-original-source'),
selectedSrc = image.getAttribute('data-selected-source'),
newSrc = currentSrc === originalSrc ? selectedSrc : originalSrc;
image.setAttribute('src', newSrc);
}
With comments:
// find all images with class "selectable"
var images = document.getElementsByClassName('selectable');
// add an event listener to each image that on click runs the "selectElementHandler" function
for (var image of images) {
image.addEventListener('click', selectElementHandler);
}
// the handler receives the event from the listener
function selectElementHandler(event) {
// the event contains lots of data, but we're only interested in which element was clicked (event.target)
var image = event.target,
currentSrc = image.getAttribute('src'),
originalSrc = image.getAttribute('data-original-source'),
selectedSrc = image.getAttribute('data-selected-source'),
// if the current src is the original one, set to selected
// if not we assume the current src is the selected one
// and we reset it to the original src
newSrc = currentSrc === originalSrc ? selectedSrc : originalSrc;
// actually set the new src for the image
image.setAttribute('src', newSrc);
}
Your problem is that javascript is returning the full path of the src (you can try alert(img.src); to verify this).
You could look up how to parse a file path to get the file name in javascript, if you want the most robust solution.
However, if you're sure that all your images will end in 'c.png', you could check for those last 5 characters, using a substring of the last 5 characters:
function changeImage(var i){
var img = document.getElementById("imgCh" + i);
if (img.src.substring(img.src.length - 5) === "c.png"){
img.src = "images/Tooling/" + i + ".png";
}
else
{
img.src = "images/Tooling/" + i + "c.png";
}
}
Say my page has loaded successfully.
There is an img element in the document like this:
<div class="pro_list_imgbox">
<img src="http://XXXX.com/bazinga.jpg" />
</div>
And I have backbone.js code like this:
events: {
'click .pro_list_imgbox': 'loadPic',
},
loadPic: function (e) {
var target = $(e.target),
pic = target[0].nodeName === 'IMG' ? target : target.find('img');
if (!pic.data('loadState')) {
pic.attr('src', pic[0].src += '?t' + new Date().getTime());
}
},
My question is how can I re-render this img element after I clicked it?
Will my loadPic function works? with a random num as suffix of src
And maybe something else I should do?
Looks like you're retrieving your image from a back-end controller, and that image is tagged according to the DateTime recorded upon retrieval.
To retrieve the same image, you'd have to save the source you used to retrieve that image. Given the code you already have, I'd say the most immediate answer would be to store the image source in the <img> element for the image, using $.data(), like this
loadPic: function (e) {
var target = $(e.target),
pic = target[0].nodeName === 'IMG' ? target : target.find('img');
if (!pic.data('loadState')) {
var picSource = pic[0].src += '?t' + new Date().getTime();
pic.data({ source: picSource });
pic.attr('src', picSource);
}
}
The <img> element that was clicked will now have the last source string for that image and can be recalled using
var imageSource = $('img-selector').data(source);
What I'm trying to do is create a dynamic wall of images.
What I'm doing is this:
Call an API to get some response. Create an array of objects based on response
Based on the array, make HTML elements for each object where there's an img in it too.
When all of these HTML elements are created, attach it to the DOM, and call a final function.
This is what I have so far (truncated to get the point across):
EDIT: code has changed a bit. scroll to bottom of question for link to current code.
// based on one post, construct the html and return it
function getOneHtml(post, w) {
console.log("getting one html");
var outerDiv = $("<div>", {class: "brick"});
outerDiv.width(w);
var img = $("<img />");
img.attr("src", post.img_src);
img.on('load', function() {
console.log("img loaded");
var ratio = this.width / w;
h = this.height / ratio;
$(this).css({'height': h});
// ...
// ...
// create the element
// an alternative I'm using for now is directly append
// the created HTML onto the page, but that results
// in a kinda messy interface.
return outerDiv[0].outerHTML;
});
}
// queries an api and then calls callback after everything is done
function requestData(subreddit, callback) {
// array of objects with link to image, post title, link to reddit
posts = [];
var w = $(window).innerWidth() / 3,
html = ''; // holds all of the inner HTML for all elements
$.get("url here", function(data) {
var arr = data.data.children;
arr.forEach(function(res_post) {
console.log("looping in requestData");
// prepare a post object
// ...
// ...
html += getOneHtml(post, w); // get the HTML for this post
});
// this should happen after everything else is done
console.log("calling callback");
callback(html);
});
}
// complete the DOM
function makeWall(html) {
console.log("making wall");
// do stuff
}
Now the trace of the program in console is this:
looping in requestData
getting one html
looping in requestData
getting one html
... // bunch of times
calling callback
making wall
(20) img loaded
So now the problem is that the HTML isn't prepared until each image is loaded, and so it doesn't actually get attached to the DOM.
How can I make sure that things happen in order in which I want them to? I tried refactoring code into more of an async style but that didn't work (not my strongest point).
I also tried looking at $.Deferred but I don't understand it, and how to integrate it into my code.
Any help is appreciated.
EDIT:
I think it might help to see what I'm doing: http://karan.github.io/griddit/
When you load, I want the images to load first, and then fade in. Currently, they show up, then hide and then fade in. Here's the source: https://github.com/karan/griddit/blob/gh-pages/js/main.js.
Also, if you scroll down one or two pages, then scroll back up, some images show up behind others.
You can use .done(), as explained in the jQuery API documentation on .done() specifically explains how to use .done() with $.get().
It's as simple as:
$.get( "test.php" ).done(function() {
alert( "$.get succeeded" );
});
Concretely...
As the API documentation link provided above indicates, you can daisy chain .done() calls together.
$.get(url,handler).done(function(){console.log('calling callback')},callback);
Note, Not certain about functionality of included plugins, i.e.g., #grid layout,
css, etc. image width, height and #grid layout not addressed, save for existing pieces re-composed in attempt at flow clarity.
Piece below solely to fulfill // Do something when all dynamically created images have loaded requirement. See console at jsfiddle
Note also, piece at jsfiddle format issue. In order to test piece, drew in 2 plugins from links at original post. Tried jsfiddle's TidyUp feature, which inserted linebreaks.
Piece may need some re-formatting; though current jsfiddle does provide callback functionality, as per original post. Again, see console. Thanks for sharing.
updated
$(function() {
// the name of the last added post
var last_added = '';
// to control the flow of loading during scroll var scrollLoad = true;
var q = 'cats';
var callbacks = $.Callbacks();
// callback,
// Do something when all dynamically created images have loaded
var callback = function (cb) {
return console.log( cb||$.now() )
};
callbacks.add(callback);
function getOneHtml(post, w, count){
var img = $("<img>", {
"src" : post.img_src,
"width" : w
});
img.on('load', function(e) {
var ratio = e.target.width / w;
h = e.target.height / ratio;
$(e.target).css('height',h)
});
var link = $("<a>", {
"href" : post.permalink,
"target" : "_blank",
"html" : img
});
var outerDiv = $("<div>", {
"class" : "brick",
"style" : "width:" + w
});
$.when($(outerDiv).appendTo("#grid"),
$(link),
count)
.then(function(div, _link, _count) {
// `image` `fadeIn`; adjustable
$(_link).appendTo($(div)).hide(0).fadeIn(2000);
return _count
})
.always(function(_count){
callbacks.fireWith(window, [_count + " images appended to grid at " + $.now()])
});
};
function requestData(subreddit,callback) {
//array of objects with link to image, post title,link to reddit
posts=[];
var w = $(window).innerWidth() / 3;
html = '';
$.ajax({
type : 'get',
url : "http://api.reddit.com/r/" + subreddit + "/hot.json?&after=" + last_added,
beforeSend : function () {
$("#searchterm").addClass("loadinggif");
},
complete : function () {
$("#searchterm").removeClass("loadinggif");
},
success : function (data) {
var arr = data.data.children;
var count = null;
arr.forEach(function(res_post) {
if(!res_post.data.is_self&&(/\.(gif|jpg|jpeg|tiff|png)$/i).test(res_post.data.url)) {
// `images` count
++count;
var post = {
'title' : res_post.data.title,
'img_src': res_post.data.url,
'name' : res_post.data.name,
'permalink': 'http://reddit.com' + res_post.data.permalink
};
getOneHtml(post, w, count);
}
last_added = res_post.data.name;
});
scrollLoad = true;
// callback,
// Do something when all dynamically created images have loaded
// see `console`; adjustable
callbacks.fireWith( window, [$(".brick img").size() + " appended to grid, callback at " + $.now()]);
}});
}
// function makeWall() {}
})
jsfiddle http://jsfiddle.net/guest271314/ggsY9/
I've the following code which will take an array and append to the page dynamically a QR code with the text being an element in the array.
$(document).ready(function () {
var list = ['dog', 'cat', 'mouse', 'hippo', 'ox'];
var qrUrl = 'https://chart.googleapis.com/chart?';
//functions
function getQrCodes(array) {
$.each(array, function (ix, val) {
//options gets chl property redefined for each element
//in the array
var options = {
cht: 'qr',
chs: '300x300',
chl: array[ix]
}
qrOptionArray.push(options);
console.log('this qr should be: ' + array[ix]);
console.log(qrUrl + $.param(options));
var $img = $('img').attr('src', qrUrl + $.param(options)).appendTo('body');
});
}
getQrCodes(list);
});
You can see the console output from the fiddle here although for some reason the QR codes don't appear in the fiddle window, they do on my local machine. The problem I've got is that the last regardless of the fact that you can see the console output change for each element in the array, the only QR code I get is the last element in the array repeated X number of times. Each of those QR cans will scan and print 'ox', even though the console output is correct. What's going on here?
The selector where you append the image to the body is wrong. You are selecting all existing img elements, whereas you want to create a new one. Try this:
var $img = $('<img />').attr('src', qrUrl + $.param(options)).appendTo('body');
Example fiddle
Note: $('<img />') not $('img').
I am struggling with my jquery hover combined with $.post.
My goal was to create a bunch of select buttons and if I hover it an image would change(a path to this image would load by $.post). The image would change to its default on mouseout.
And if the select button is clicked it would change the image permanently.
The issue is that the image is sometimes changed permanently even on hover.
Try it yourselves at link text
Try to hover over the selects furiously for a while and the image won't change back.
How can I fix this please?
var origpic;
var klik;
var inputval;
var newpic;
var origbnazev;
var cesta = "/ajaxobrazek.php";
$("input[name='barva']").hover(function() {
klik = 0;
inputval = $(this).val();
origbnazev = $("#bnazev").text();
origpic = $("#kocarekimg").attr("src");
$.post(cesta, {dodavatel_id : "<?php echo $row['dodavatel_id']?>", barva_cislo : inputval},
function(data){
$("#kocarekimg").attr("src","/images/maly-"+data+".jpg");
});
$.post("/ajaxbarva.php", {barva_cislo : inputval}, function(data){
$("#bnazev").text(data);
});
},function(){
if (klik == 0) {
$("#bnazev").text(origbnazev);
$("#kocarekimg").attr("src",origpic);}
});
$("input[name='barva']").click(function() {
klik = 1;
$.post(cesta, {dodavatel_id : "<?php echo $row['dodavatel_id']?>", barva_cislo : inputval},
function(data){
$("#kocarekimg").attr("src","/images/maly-"+data+".jpg");
origpic = "/images/maly-"+data+".jpg";
});
});
//thumbnails
$(".imgtn").hover(function() {
origpic = $("#kocarekimg").attr("src");
newpic = $(this).attr("src");
newpic = newpic.replace("tn-","maly-");
$("#kocarekimg").attr("src",newpic);
},function(){
$("#kocarekimg").attr("src",origpic);
});
I don't have any problem in Chrome, nor in Firefox and IE. The only thing I see is that the site is not as responsive as it should, and - frankly speaking - I don't understand why you're not caching the images refs once they're loaded.
Your script makes an ajax call at every single hover, that's nonsense.