$(this) and scope - passing a specific element - javascript

I have a variety of .img-drop-zones and upon drop a file is read, I wish to display it on top of the specific drop zone it was placed on, but how do I get it? $(this) does not work because of scope, how can I pass it through?
$('.img-drop-zone').on('drop', function(e){
var files = e.originalEvent.dataTransfer.files;
$.each(files, function(index, file){
p.file.read(file, function(content) {
//how can I get the img-drop zone here?
});
})
});

Just declare an additional variable in the outer scope that you can refer to within the $.each closure:
var $this = $(this);
$.each(..., function() {
// use $this here to refer to the img-drop-zone
});
When referring to an object to something that isn't a jQuery object it's more common to use self or that.

$(this) is what you need
$('.img-drop-zone').on('drop', function(e){
var files = e.originalEvent.dataTransfer.files;
var dropJone = $(this);
$.each(files, function(index, file){
p.file.read(file, function(content) {
//how can I get the img-drop zone here?
//use dropJone here
});
})
});

Related

Update element text when clicked

$("#readMain").delegate("span", "click", function() {
var toSend = $(this).text();
$(this).text(function() {return "test1";});
$.post('/render/', {'word': toSend}, function(data){
$(this).text(data);
alert(data); //for testing
});
});
I'm trying to have the word clicked updated. It works fine the first time (it changes to 'test1'), but after the post call, it doesn't work anymore?
What am I doing wrong
this doesn't refers to span element in $.post() callback method, store the reference of $(this) in a variable and use it wherever required.
//Store the reference
var _this = $(this);
$.post('/render/', {'word': toSend}, function(data){
//Use it later
_this.text(data);
alert(data); //for testing
});
Additionally, delegate() is deprecated use .on()
$("#readMain").on("click", "span", function() {
//Store the reference
var _this = $(this);
var toSend = _this.text();
_this.text("test1");
$.post('/render/', {'word': toSend}, function(data){
_this.text(data);
alert(data); //for testing
});
});
This in that context refers the first time to the "span", the second time it refers to the window object.
Besides that, delegate is old jQuery, you can use '.on' now.
You'll nee to update the function like this:
$("#readMain").on("click", "span", function() {
var span = $(this);
var toSend = span.text();
$.post('/render/', {'word': toSend}, function(data){
span.text(data);
alert(data); //for testing
});
});
this is only valid in the current scope which means every function, class, closure, ..., has it's on this. Save a reference to your first this in a var to access it later.
$("#readMain").delegate("span", "click", function() {
var span = $(this);
var toSend = span.text();
span.text(function() {return "test1";});
$.post('/render/', {'word': toSend}, function(data){
span.text(data);
alert(data); //for testing
});
});
The context in $.post callback will be changed. You can declare a variable and set the context. See the code below.
$("#readMain").on("span", "click", function() {
var self = $(this),
toSend = self.text();
self.text(function() {return "test1";});
$.post('/render/', {'word': toSend}, function(data){
self.text(data);
alert(data); //for testing
});
});

Optimizing JQuery

I have Jquery code that looks like this. Is there a way to optimize this code? What happens if the image doesn't have a title attribute? Should I insert a case for using the value of the alt attribute as a backup and If I'm chaining the .attr() function multiple times, then it'd be cleaner code I you just ran the .attr() function a single time passing a value pair object of all my properties to the function. How can I do this ?
$(function() {
$('.component-individual-detail-profile').each(function() {
var $self = $(this), $images = $self.find('.photos');
$images.find('li').click(function(e) {
e.preventDefault();
var thumb = $(this);
$images.find('.selected')
.attr('src', thumb.find('img').attr('src'))
.attr('alt', thumb.find('img').attr('alt'))
.attr('title', thumb.find('img').attr('title'));
});
});
});
You can store the attributes in a array, and cache the $thumb.find('img') selector:
$('.component-individual-detail-profile').each(function() {
var $self = $(this);
var $images = $self.find('.photos');
$images.find('li').click(function(e) {
e.preventDefault();
var $thumb = $(this).find('img');
var $selected = $images.find('.selected');
$.each(['src', 'alt', 'title'], function(index, attrName){
$selected.attr(attrName, $thumb.attr(attrName));
});
});
});
Have you considered var thumb = $(this).find("img") for starters? Anywhere your code repeats function calls, you're probably doing something wrong.
Regarding "what if there is no attribute", you can do thumb.attr('title') || thumb.attr('alt'), using the logical or (||) to provide a value if the first one doesn't exist.
According to the documentation, you can do...
$images.find('.selected').attr({
src: thumb.attr('src'),
alt: thumb.attr('alt'),
title: thumb.attr('title') || thumb.attr('alt')
});

how to get last clicked event data in entire javascript scope

function my_fun(){
var data = $(this).data();
// this is undefined
console.log(data.crm);
}
$(document).on('click', '#add_image', (function() {
var data = $(this).data();
// this works
console.log(data.crm);
my_fun();
}));
<a class="add_img" href="#" data-crm="1" id="add_image">Add Image</a>
Basically I want to access html link set data (i.e. value of dataset crm) in my_fun() without sending parameter to my_fun().
How to access click events html set data in the entire scope of javascript.
javascript.
Global variable in javascript
function my_fun() {
console.log(data.crm);
}
$(document).on('click', '#add_image', (function(e) {
e.preventDefault();
data = $(this).data();
console.log(data.crm);
my_fun();
}));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<a class="add_img" href="#" data-crm="1" id="add_image">Add Image</a>
function my_fun(event){
var data = $(event.target).data();
console.log(data.crm);
}
$(document).on('click', '#add_image', my_fun);
or
function my_fun(event){
var data = $(event.target).data();
console.log(data.crm);
}
$(document).on('click', '#add_image', function(e){
my_fun(e);
});
You have to pass a context to your function by call method:
my_fun.call(this);
jsFiddle
There's a limited number of ways to do this. One is to pass arguments to the called function.
Another is to just reference the function, and you'll keep the this value
function my_fun(){
var data = $(this).data();
// this is undefined
console.log(data.crm);
}
$(document).on('click', '#add_image', my_fun);
Lastly, there's bind, apply or call
my_fun.bind(this)();
// or
my_fun.call(this);
// or
my_fun.apply(this, arguments);

$(this).html not working in jquery

<globemedia id="1"></globemedia>
<script type="text/javascript">
$("globemedia").each(function(index, value) {
var globeIDxMedia = $(this).attr("id");
$.get("getmedia.jsp?mediaID="+globeIDxMedia,function(a){
$(this).html(a);
});
});
</script>
The above Script i use to load content to my customized tag say <getmedia id="1"></getmedia>
script works fine till getting data from the page getmedia.jsp but when i use $(this).html(a); its not loading the data.
Got Answer from jquery forum
It'll work with custom tag as well
<script type="text/javascript">
$(document).ready(function(){
$("div[data-globalmedia]").each(function(index, value) {
var globeIDxMedia = $(this).attr("id");
$(this).load("getmedia.jsp?mediaID="+globeIDxMedia);
});
});
</script>
jQuery expert gave me solution you have to use $(document).ready(function(){}); and it works like a charm
Keep a reference to $(this) outside the $.get() function.
<script type="text/javascript">
$("globemedia").each(function(index, value) {
var globeIDxMedia = $(this).attr("id");
var self = $(this);
$.get("getmedia.jsp?mediaID="+globeIDxMedia,function(a){
$(self).html(a);
});
});
</script>
The meaning of this is different within the callback of $.get than it is within the callback of the outer $().each. You can read more about the semantics of this here: http://www.sitepoint.com/javascript-this-gotchas/
As a rule, if you want to refer to the "outer" value of this within a callback function, you first have to bind it to a variable that is accessible within the callback (in this case, I've used the common convention of a variable named self).
You can't this ( which refers to globemedia ) within $.get() callback function scope. Within $.get() callback function this refers to something else but not globemedia.
So, get keep reference of this outside of $.get() which refers to globalmedia like following:
$("globemedia").each(function(index, value) {
var globeIDxMedia = $(this).attr("id");
// keep referece to this
// ie. globemedia
var media = $(this);
$.get("getmedia.jsp?mediaID="+globeIDxMedia,function(a){
// here self refers to
// globemedia element
media.html(a);
});
});
Note
I think $("globemedia") should be $(".globemedia"). That means you should use a class selector.
You can't make your own custom HTML tag. See HERE
As you can't create you own HTML tag (here, globalmedia), instead of that you can use data attribute to them. For example:
<div data-globalmedia="media1" id="id_1">Media 1</div>
<div data-globalmedia="media2" id="id_2">Media 2</div>
and so on. And for jQuery you can use:
$('[data-globalmedia]').each(function() {
var globeIDxMedia = $(this).attr("id");
// keep referece to this
// ie. globemedia
var self = $(this);
$.get("getmedia.jsp?mediaID=" + globeIDxMedia, function(a) {
// here self refers to
// globemedia element
self.html(a);
});
});
Working sample

Reference JS object to DOM element

How can I reference specific DOM element to specific JS object?
For example, i have an array of customers. Using jQuery, for each customer I create LI with checkbox and span for customers name. When checkbox is clicked, I need to do some processing on that customer JS object. The question, how i can get this JS object an easy way.
Currently I have following:
$(customers).each(function(){
$("<li>").append($("<input type=\"checkbox\"").attr("id","chk_" + this.ID)).append($("<span>").text(this.Name)).appendTo("#ulCustomers");
});
$("#ulCustomers input[type=checkbox]").bind("click",function(){
var customerId = $(this).attr("id").replace("chk_","");
var CustomerObj = $(customers).filter(function () { return this.ID == customerId }).get(0);
myProcess(CustomerObj); //Two above two lines are just for select correct customer from array.
});
I believe in world of JS and jQuery exists more elegant way to do it.
Thanks
You can use jquery data function
$(customers).each(function() {
var elem = $("<li><input type='checkbox'><span>" + this.Name + "</span></li>").appendTo("#ulCustomers");
elem.find("input").data("customer", this);
});
$("#ulCustomers input[type=checkbox]").click(function() {
var CustomerObj = $(this).data("customer");
myProcess(CustomerObj);
});
Could you not bind the click event to a closure with a reference to the relevant Customer object?
like this
$(customers)
.each(function(){
var custObj = this;
$("<li>")
.append(
$("<input type=\"checkbox\"")
.append($("<span>")
.text(this.Name))
.appendTo("#ulCustomers")
.bind("click", function(){
myProcess(custObj);
})
});
I would use jQuery data, just like this:
$("checkbox").data('customer', this.ID);
To retrieve the data:
$("#ulCustomers input[type=checkbox]").bind("onchange",function(){
var customerId = $(this).data("customer");
var CustomerObj = $(customers).filter(function () { return this.ID == customerId }).get(0);
myProcess(CustomerObj); //Two above two lines are just for select correct customer from array.
});
Additionally, don't use click event on check-boxes, use onchange event ;)

Categories