$(this).parent().find() is not working - javascript

I am making a Wordpress widget showing an image, and to upload/change this image I use the Wordpress media uploader.
This is the admin form markup I'm using:
<p class="media-control"
data-title="Choose an image"
data-update-text="Choose image">
<input class="image-url" name="image-url" type="hidden" value="">
<img class="image-preview" src=""><br>
<a class="button" href="#">Pick image</a>
</p>
When I click ".media-control a" the uploader appears and I can pick an image. But when I've picked an image ".image-preview" and ".image-url" isn't updated.
Here's my javascript: http://jsfiddle.net/etzolin/DjADM/
Everything is working as intended except these lines:
jQuery(this).parent().find('.image-url').val(attachment.url);
jQuery(this).parent().find('.image-preview').attr('src', attachment.url);
When I write them like this, input value is set and image preview is updated:
jQuery('.media-control .image-url').val(attachment.url);
jQuery('.media-control .image-preview').attr('src', attachment.url);
But since I use more than one of these widgets it updates the input value and image preview in every widget.
How can I set the input value and update the image preview only in the widget I'm editing? What am I doing wrong?

Inside the event handler for the media frame this is not the clicked element
var media_frame;
jQuery('.media-control a').live('click', function (event) {
var self = this;
event.preventDefault();
if (media_frame) {
media_frame.open();
return;
}
media_frame = wp.media.frames.media_frame = wp.media({
title: jQuery(self).parent().data('title'),
button: {
text: jQuery(self).parent().data('update-text'),
},
multiple: false
});
media_frame.on('select', function () {
attachment = media_frame.state().get('selection').first().toJSON();
jQuery(self).parent().find('.image-url').val(attachment.url); // set .image-url value
jQuery(self).parent().find('.image-preview').attr('src', attachment.url); // update .image-preview
// ^^ this is not the element from the click handler but the media frame
});
media_frame.open();
});
and you should be using on() as live() is deprecated and removed from jQuery

Related

Remove Button is deleting all img tags and not the selected one

This is my image uploader:
My Code for adding an image which works perfect:
jQuery(function($){
// Set all variables to be used in scope
var frame, selections, attachment,
metaBox = $('#gallery-meta-box.postbox'), // Your meta box id here
addImgLink = metaBox.find('.upload-custom-img'),
delImgLink = metaBox.find('.delete-custom-img'),
imgContainer = metaBox.find('.custom-img-container'),
imgIdInput = metaBox.find('.custom-img-id' );
// Add image from frame
addImgLink.on( 'click', function( event ){
event.preventDefault();
// If the media frame already exists, reopen it
if ( frame ) {
frame.open();
return;
}
// Create a new media frame
frame = wp.media({
title: 'Select Images',
button: {
text: 'Add Image'
},
multiple: true
});
// When an image is selected in the media frame
frame.on( 'select', function() {
// Get media attachments details from the frame state
selections = frame.state().get('selection');
selections.map(function(attachment){
attachment = attachment.toJSON();
// Send the attachment URL to our custom image input field
imgContainer.append(
'<li>'
+ '<img data-attachment-id="id-media-1993'+attachment.id+'" src="'+attachment.url+'" class="gallery-thumbnail" alt="'+attachment.title+'" style="max-width:150px; max-height:150px;"/>'
+ '<a class="delete-custom-img" href="#">Remove Image</a>'
+ '</li>');
// Send the attachment id to our hidden input
imgIdInput.val(attachment.id);
console.log(attachment);
});
});
// Finally, open the modal on click
frame.open();
});
// MY DELETE BUTTON :
imgContainer.on( 'click', delImgLink, function(event){
event.preventDefault();
var galleryThumbnail = $(this).find('img');
console.log(galleryThumbnail);
});
});
When you do watch the image uploader you can see the remove links. When I click on the remove and it doesn't matter which one of the remove button it's giving my the id's of both and same for the src.
see result:
When I click on the remove link, I want information about the current image, not all the images inside my div element.
Hopefully someone can explain it.
The issue is that, while you are using event delegation to handle dynamic elements, the delegation is pre-determined, so does not pick up the elements correctly
delImgLink = metaBox.find('.delete-custom-img'),
Change
imgContainer.on( 'click', delImgLink, ...
to
imgContainer.on('click', 'a.delete-custom-img',
then this will be the button and you can find the relevant image either with .closest().find() or .prevAll("img").first() (or other method):
imgContainer.on('click', 'a.delete-custom-img', function(event){
event.preventDefault();
var galleryThumbnail = $(this).closest("li").find('img');
console.log(galleryThumbnail);
});
In your original code, if this was the delete button then
$(this).find('img')
would not find anything as find find child items and there are no child items under your delete anchor, so this must be referring to something else, higher up.
You need jquery closet() to find nearest img and then delete it.
Or you can do it by
$(this).parent().find('img');
To achieve expected reult, use below option of adding event to imageContainer images and $(this) will provide the details of selected image
$(".imgContainer img").on( 'click', function(event){
event.preventDefault();
var galleryThumbnail = $(this);
console.log(galleryThumbnail[0].id);
});
https://codepen.io/nagasai/pen/VQJoZj

How to load Photoswipe with Ajax to get server side pictures?

I'm searching for a gallery library and I see PhotoSwipe. Actually I just made the tutorial in the documentation.
I don't see any tutorial to load my server side pictures dynamically.
I need to load them with Ajax because I have a datatables, and inside each row I set an icon. The user can click on this icon and it will appears a bootstrap modal. In this modal I have to show the thumbnails related with the clicked row. And when the user click on the thumbnails I need to show the gallery.
It's possible to load dynamically server side pictures ?
I think you can achieve this by initiating the gallery from the click event. If you make this a delegated event, it will also get triggered on newly created images. Then you only need to create the image array upon triggering the click event and fire up the gallery.
Your images should be added like this:
<img class="myAjaxLoadedImage" src="myAjaxLoadedImage1_thumbnail.jpg" alt=""
data-img-title="My title 1" data-img-src="myAjaxLoadedImage1.jpg"
data-img-width="800" data-img-height="600">
<img class="myAjaxLoadedImage" src="myAjaxLoadedImage2_thumbnail.jpg" alt=""
data-img-title="My title 2" data-img-src="myAjaxLoadedImage2.jpg"
data-img-width="400" data-img-height="700">
...
And the JS would then be:
(function($) {
var pswp;
$(function() {
pswp = $('.pswp')[0];
setGalleryClickEvents();
});
function setGalleryClickEvents() {
$(document).on('click','.myAjaxLoadedImage',function(e) {
if (pswp) {
var options = {
index: $(this).index()
// + other PhotoSwipe options here...
}
var images = [];
$('.myAjaxLoadedImage').each(function() {
var $img = $(this);
images.push({
src: $img.data('imgSrc'),
w: $img.data('imgWidth'),
h: $img.data('imgHeight'),
title: $img.data('imgTitle')
});
});
var gallery = new PhotoSwipe(pswp, PhotoSwipeUI_Default, images, options);
gallery.init();
}
});
}
})(jQuery);

jQuery Lightbox gallery only working once

I am trying to build my own simple jQuery lightbox gallery. My logic behind it is as follows: Only thumbnails will be shown & created at first. These link to the full size images.
<section class="gallery-set">
<a href="img/about/gallery/a1.1.jpg">
<img src="img/about/gallery/thumb1.1.jpg" alt=""
height="192" width="383">
</a>
<a href="img/about/gallery/a1.jpg">
<img src="img/about/gallery/thumb1.jpg" alt=""
height="192" width="383">
</a>
<a href="img/about/gallery/a2.1.jpg">
<img src="img/about/gallery/thumb2.1.jpg" alt=""
height="192" width="383">
</a>
</section>
Therefore, when you click on any of these thumbnails, I dynamically create an overlay-lightbox and all full size images, showing only the one that links to the thumbnail you clicked. Although the rest of the images has been created too, these are hidden for now.
function lightBox() {
var gallery = $('.gallery-set'),
overlay = $('<div/>', {id: 'overlay'});
overlay.appendTo('body').hide();
gallery.on('click', 'a', function(event) {
event.preventDefault();
var clickedThumb = $(this),
clickedThumbPath = $(this).attr('href'),
clickedImg = $('<img>', {src: clickedThumbPath, alt: 'fullSizeImage', class: 'current'}),
prevThumbs = clickedThumb.prevAll(),
nextThumbs = clickedThumb.nextAll();
prevThumbs.each(function() {
var prevImg = $('<img>', {src: $(this).attr('href'), class: 'prev non-current'});
prevImg.appendTo(overlay);
});
clickedImg.appendTo(overlay);
nextThumbs.each(function() {
var nextImg = $('<img>', {src: $(this).attr('href'), class: 'next non-current'});
nextImg.appendTo(overlay);
});
overlay.show();
})
.....
.....
}
Now, when you click the second thumbnail, jQuery dynamically creates all the fullsize images and this is how HTML structure looks like:
Now that I have this structure, I can easily traverse the full sized images by left and right arrows. The current image gets hidden and the next one gets shown. For this logic I am using two classes, current and non-current where the first one has set display to block and the second one to none. This piece of code is within the lightbox() function:
$(document).on('keyup', function(event) {
var pressed = event.keyCode || event.which,
arrow = {left: 37, right: 39};
switch(pressed) {
case arrow.left:
var curr = overlay.find('.current'),
prev = curr.prev();
if(curr.hasClass('current')) {
curr.removeClass('current').addClass('non-current');
} else {
curr.addClass('non-current');
}
if(prev.hasClass('non-current')) {
prev.removeClass('non-current').addClass('current');
} else {
prev.addClass('current');
}
break;
case arrow.right:
var curr = overlay.find('.current'),
next = curr.next();
curr.removeClass('current').addClass('non-current');
next.removeClass('non-current').addClass('current');
break;
}
});
overlay.on('click', function() {
overlay.hide();
overlay.find('img').remove();
});
});
Everything works fine the first time. However, once I close the lightbox and try to open it again, the correct image opens but the arrows functionality is gone. I do not understand why - since I am dynamically creating the full sized images everytime user clicks on the gallery and putting event listeners (arrows) only once these have been created.
Just for the record, I am calling this lightbox() function from the HTML file right before the closing tag.
Any ideas much appreciated. Also, if there's a simpler / better way of doing this, please do let me know! I don't want to use any plugin as I think this is pretty simple and straightforward. Or, I thought it WOULD BE SIMPLE I should rather say.

Live HTML/CSS preview from a div tag and not a text area tag

I want to create a live HTML/CSS preview on a page.
But the code will not be given using textareas. The code is going to be fixed in the page (div).
I want the user to be able to alter the code and that will reflect on the live preview box.I have created the page where you can change parts of the script text (for amateurs). You can preview that here :
http://apolosiskos.co.uk/HTML-CSS-EDITOR/index3.html
01) The live preview does not work if I replace the textarea with a div.
02) Even if I use the textareas, the live preview does not work because in my HTML script I am using the codeand the xmp tags.
--> Snippet that works with a textarea but not with a div :
var wpcomment = document.getElementById('WPComment');
wpcomment.blur = wpcomment.onkeypress = function(){
document.getElementById('prevCom').innerHTML = this.value;
}
#prevCom
{
background:#124;
color:#fff;
min-width:20px;
min-height:50px;
font-size:25pt;
}
<textarea name="WPcomment" id="WPComment" placeholder="Add comments:">aaaaa</textarea>
<div id="prevCom"></div>
with no success. Is there any other addEventListener() method I can replace keyup with?
Yes, blur
If you would like to add keydown events on a <div> element, you can do the following:
First, you need to set the tabindex attribute:
<div id="a-div" tabindex="1" />
Then,
(2) Bind to keydown:
$('#mydiv').bind('keydown', function(event) {
//console.log(event.keyCode);
});
If you would like your div to be "focused" from the start:
$(function() {
$('#mydiv').focus();
});
You should place your preview code it within a function, then you can simply call it once the document has loaded.
https://jsfiddle.net/michaelvinall/4053oL1x/1/
The separate issue of your preview only rendering when you press the enter key, is because of the following if statement:
if(e.which == 13 && $(this).val().length > 0)
The e.which == 13 within your if is specifying that the code within the block should only be ran if the key pressed by the user was the enter key (code 13). By removing this portion of each if statement, any key pressed will execute the code within the block:
if($(this).val().length > 0)
Your function is call when keyup is trigger, but no after page load.
You must do it : Define function to call them when 2 different event are fired.
$(function() {
function GetHtml(){
var html = $('.html').val();
return html;
}
function GetCss(){
var Css = $('.css').val();
return Css;
}
var previewRendering = function(){
console.log('kikou');
var targetp = $('#previewTarget')[0].contentWindow.document;
targetp.open();
targetp.close();
var html = GetHtml();
var css = GetCss();
$('body',targetp).append(html);
$('head', targetp).append('<style>' + css + '</style>');
};
$('.innerbox').on("keyup",function(){
previewRendering();
});
$(document).ready(function() {
previewRendering();
});
});
This code can not work because load event is only compatible with this list of HTML tags: body, frame, iframe, img, input type="image", link, script, style
$('.innerbox').load(function()

How to make an event on one element cause a bootstrap popover on another element?

Am trying to create a picture upload button with js, that will have the following functionality....
1)Pop up file chooser on click (accomplished)
2)Preview image selected inside a bootstrap popover when the image is selected from file chooser...
The button contains an input tag of type file, with a css class(.file-inputs) that applies a display of none on the element, so I cant add the popover to the input tag since popovers don't work on hidden elements, how can I make the popover display on the visible button when the value of the input tag is changed
Maybe something like so
$('#photo').change()(function(){
if(!($("#photo").val() == '')){
//Use bootstrap popover to show image over button
});
});
Here is the button code
<button class="btn btn-default" rel="popover" id="btn-photo">
<i class="glyphicon glyphicon-picture"></i>
<input class="file-inputs" type="file" name="photo" id="photo" />
</button>
And here is the js
$(document).ready(function() {
var img = '';
//Event to display file chooser
$('.post-box').on('click', '#btn-photo', function() {
event.preventDefault();
var elem = document.getElementById('photo');
if (elem && document.createEvent) {
var evt = document.createEvent("MouseEvents");
// Event(event_type:String, bubbles:Boolean, cancelable:Boolean)
evt.initEvent("click", false, true);
elem.dispatchEvent(evt);
}
});
// Show popover on button
$("#btn-photo").popover({
placement: 'top',
trigger: 'click',
title: 'Add a picture to your post! :)',
content: img,
html: true
});
// });
});
A fast answer is something like this:
$("#yourbutton").on("yourevent", function(){$("#otherbutton").trigger("click");});

Categories

Resources