Conditional addClass not working for each elements with same class - javascript

Les say I have some buttons with same class. On page load I am checking some value using ajax for each button. Depending on returned value of ajax request I want to add some class to the buttons, but it is not working,
$(document).ready(function(){
$('.add-remove-permissoion').each(function(){
var child = $(this).val();
var parent = $('#parent-name').text();
$.get('my-url', function(data){
if(data == 1){
$(this).addClass('glyphicon glyphicon-ok');
}else{
$(this).addClass('emptybox-blank');
}
});
});
});
I have checked that my ajax request is returning correct data. What is that I am doing wrong here?

The problem is the this reference inside the ajax callback, in the success callback this refers to the jqXHR object not the dom element reference that is why it is not working.
You can use a closure variable as given below to fix the problem
$(document).ready(function () {
$('.add-remove-permissoion').each(function () {
var $this = $(this),
child = $this.val();
var parent = $('#parent-name').text();
$.get('my-url', {}, function (data) {
if (data == 1) {
$this.addClass('glyphicon glyphicon-ok');
} else {
$this.addClass('emptybox-blank');
}
});
});
});

this in the context of the $.get handler doesn't refer to the element of the current iteration. Each function has it's own this value. You have several options.
Use the second parameter of the each callback.
$('.add-remove-permissoion').each(function(index, element) {
Use $.proxy or Function.prototype.bind method for setting the this value of the handler.
$.get('my-url', function(data) {
// ...
}.bind(this));
Cache the this value of the each handler and use it in your $.get handler.
var elem = this;
$.get('my-url', function(data) {
// ...
$(elem)...
});
Also note that there is a syntax error in your code:
$.get('my-url'}, function(data){
// -----------^

Problem is $(this) within ajax call does not refer to the button clicked.
Replace $(this).addClass with myElement.addClass. Create myElement within click event just before the ajax call: var myElement = $(this).

Related

how to use this incomplete javascript object in HTML

I got this javascript code to solve in a manner to use inner function but not able to use it. Please try to help me to use inner functions or do i need to modify this. I want to use inner functions on click on html element such as view and remove respectively;
var App = function(){
var url = 'api';
function view(event) {
var id = '??'; //here i have to receive id of the element(data-id)
$.ajax({
url: url + '/view/' +id,
data: data
}).done( function (data){
});
}
function remove(event) {
var id = '??'; //please determine the id
$.ajax({
url: url + '/remove/' + id ,
data: data
}).done( function (data){
});
}
function initialize() {
//
}
return {
//
}
}();
Try doing this:
For id you can do one thing, Save the id in data-id attribute of the element on which you want onClick listener and access it using Event-Delegation in javascript.
To use the inner method you don't need to return anything. Just do it this way :
var App = function(){
var url = 'api';
function view(event) {
//access the id attribute of event.target
}
function remove(event) {
//same
}
function initialize() {
//
}
App.view = view;
App.remove = remove;
};
//EDIT : instead of making it self-invoking, call the app function
App();
//to access it outside:
App.view("your_parameter");
App.remove("your_parameter");
EDIT : Instead of making it self-invoking, call the app function
Well it's pretty simple, use the $("#caller").click() function of our beloved
jQuery
Then inside the .click() function you can easily retrieve your id
Here you can find more on the .click() function
It will be something like this
$( "#view" ).click(function() {
id = document.getElementById("id").id;
//Here paste the code of your view function
});

Select from json on click

I'm trying to select a row from a json array using jquery. This is what i have:
$(document).ready(function() {
$.getJSON( "js/collectie.json", function(data) {
jsoncollectie = data;
})
$( "#collectie li" ).click(function(){
var thumb_id = $(this).data("id");
for(var i = 0; i < jsoncollectie.stoelen.length; i++){
if(jsoncollectie.stoelen[i].ref == thumb_id){
$("#detailimage").attr('src', jsoncollectie.stoelen[i].image);
$("#detailimage").attr('title', jsoncollectie.stoelen[i].title);
$("#title").html('<h4> '+jsoncollectie.stoelen[i].naam+' </h4>');
$("#secondaryimage").attr('src', jsoncollectie.stoelen[i].secondaryimage);
$("#secondaryimage").attr('title', jsoncollectie.stoelen[i].secondarytitle);
$("#description").html('<p> '+jsoncollectie.stoelen[i].description+' </p>');
}
}
});
});
Now when i click on a list item (#collectie li) the console outputs "ReferenceError: jsoncollectie is not defined". I don't know why it's doing that and i'm pretty sure it worked two weeks ago. Don't know much about javascript/jquery yet, but i'm slowly learning.
$(document).ready(function()
{
// Provide access to data outside of the getJSON call
var m_oJsonCollectie = null;
// Get the data
$.getJSON( "js/collectie.json", function(data)
{
// Set the data
m_oJsonCollectie = data;
// Apply the click handler
$( "#collectie li" ).click(function()
{
var thumb_id = $(this).data("id");
for(var i = 0; i < m_oJsonCollectie.stoelen.length; i += 1)
{
if(m_oJsonCollectie.stoelen[i].ref == thumb_id)
{
$("#detailimage") .attr('src', m_oJsonCollectie.stoelen[i].image);
$("#detailimage") .attr('title', m_oJsonCollectie.stoelen[i].title);
$("#title") .html('<h4> '+ m_oJsonCollectie.stoelen[i].naam+' </h4>');
$("#secondaryimage").attr('src', m_oJsonCollectie.stoelen[i].secondaryimage);
$("#secondaryimage").attr('title', m_oJsonCollectie.stoelen[i].secondarytitle);
$("#description") .html('<p> '+ m_oJsonCollectie.stoelen[i].description+' </p>');
}
}
});
});
});
JS have block level scope, so you wont get the values outside of the function unless you provide access to them or they are declared in global scope (which is considered bad practice).
This pattern should help you keep your data accessible, and only applies the click handler if the getJSON call is successful.
Check that your getJSON request is being received and returned by using deferred methods
// Syntax that will shed light to your issue :
$.getJSON
(
"js/collectie.json",
function (oJSON) { /*success*/ }
)
.done(function() { /* succeeded */ })
.fail(function() { /* failed */ })
.always(function() { /* ended */ });
I came to this conclusion due to comments and the fact that a variable only declared in the success handler for getJSON was undefined. Since the JSON containing variable was undefined, the success handler must never have been called. Chances are that the path to the JSON you are trying to get is incorrect.
Documentation for the methods to accomplish :
getJSON
done
fail
always
UPDATE
Knowing that the response is 304, and the results are undefined are the important details here. This issue has been addressed by jQuery already here
This is actually correct, given the ifModified header has not been set to false.
To fix this issue, use ajaxSetup() to modify the header.
NOTE : the use of this method is not recommended by jQuery, but in this case it works.
// place this is document ready handler before making any calls.
$.ajaxSetup({ ifModified : false });

Uncaught TypeError: Cannot read property 'toLowerCase' of undefined

I'm getting this error and it is originating from jquery framework.
When i try to load a select list on document ready i get this error.
I can't seem to find why i'm getting this error.
It works for the change event, but i'm getting the error when trying to execute the function manually.
Uncaught TypeError: Cannot read property 'toLowerCase' of undefined -> jquery-2.1.1.js:7300
Here is the code
$(document).ready(function() {
$("#CourseSelect").change(loadTeachers);
loadTeachers();
});
function loadTeachers() {
$.ajax({
type: 'GET',
url: '/Manage/getTeachers/' + $(this).val(),
dataType: 'json',
cache: false,
success:function(data) {
$('#TeacherSelect').get(0).options.length = 0;
$.each(data, function(i, teacher) {
var option = $('<option />');
option.val(teacher.employeeId);
option.text(teacher.name);
$('#TeacherSelect').append(option);
});
},
error: function() {
alert("Error while getting results");
}
});
}
When you call loadTeachers() on DOMReady the context of this will not be the #CourseSelect element.
You can fix this by triggering a change() event on the #CourseSelect element on load of the DOM:
$("#CourseSelect").change(loadTeachers).change(); // or .trigger('change');
Alternatively can use $.proxy to change the context the function runs under:
$("#CourseSelect").change(loadTeachers);
$.proxy(loadTeachers, $('#CourseSelect'))();
Or the vanilla JS equivalent of the above, bind():
$("#CourseSelect").change(loadTeachers);
loadTeachers.bind($('#CourseSelect'));
I had the same problem, I was trying to listen the change on some select and actually the problem was I was using the event instead of the event.target which is the select object.
INCORRECT :
$(document).on('change', $("select"), function(el) {
console.log($(el).val());
});
CORRECT :
$(document).on('change', $("select"), function(el) {
console.log($(el.target).val());
});
This Works For me !!!
Call a Function without Parameter
$("#CourseSelect").change(function(e1) {
loadTeachers();
});
Call a Function with Parameter
$("#CourseSelect").change(function(e1) {
loadTeachers($(e1.target).val());
});
It causes the error when you access $(this).val() when it called by change event this points to the invoker i.e. CourseSelect so it is working and and will get the value of CourseSelect. but when you manually call it this points to document. so either you will have to pass the CourseSelect object or access directly like $("#CourseSelect").val() instead of $(this).val().
It fails "when trying to execute the function manually" because you have a different 'this'. This will refer not to the thing you have in mind when invoking the method manually, but something else, probably the window object, or whatever context object you have when invoking manually.
your $(this).val() has no scope in your ajax call, because its not in change event function scope
May be you implemented that ajax call in your change event itself first, in that case it works fine.
but when u created a function and calling that funciton in change event, scope for $(this).val() is not valid.
simply get the value using id selector instead of
$(#CourseSelect).val()
whole code should be like this:
$(document).ready(function ()
{
$("#CourseSelect").change(loadTeachers);
loadTeachers();
});
function loadTeachers()
{
$.ajax({ type:'GET', url:'/Manage/getTeachers/' + $(#CourseSelect).val(), dataType:'json', cache:false,
success:function(data)
{
$('#TeacherSelect').get(0).options.length = 0;
$.each(data, function(i, teacher)
{
var option = $('<option />');
option.val(teacher.employeeId);
option.text(teacher.name);
$('#TeacherSelect').append(option);
});
}, error:function(){ alert("Error while getting results"); }
});
}

How to save "title" attribute of "a" with jQuery?

How can I save the value of the title for a row? These are the values of the title=%s:
<a class="false" title=1106 href="/useradminpage?main_id=%s&display=false"><span class="small">(hide)</span></a>
<a class="false" title=1153 href="/useradminpage?main_id=%s&display=false"><span class="small">(hide)</span></a>
<a class="false" title=1175 href="/useradminpage?main_id=%s&display=false"><span class="small">(hide)</span></a>
...
I've tried countless variations but none of them work. This is what I have now:
<script>
$(document).ready(function() {
console.log("ready");
$("a.false").click(function(e) {
$(this).closest("tr.hide").hide("slow");
var main_id = a.title;
var display = "false";
e.preventDefault();
});
$("a.false").click(function() {
$.ajax({
url: "/useradminpage?main_id=%s&display=false",
data: {main_id: "main_id", display: "display"},
success: function(data) {
display_false()
alert("4 - returned");
}
});
});
});
</script>
This is the third question on this topic. I appreciate any help. Thanks.
instead of
var main_id = a.title;
try
var main_id = $(this).attr('title');
because if I'm not wrong, "a" isn't defined
I think what you're trying to do is pass the value of the title attribute along in your AJAX request. If that's the case, the easiest thing to do will be to do it all in one event handler (is there a reason you're binding 2 different handlers to the same event?):
$("a.false").click(function(e) {
$(this).closest("tr.hide").hide("slow");
var main_id = this.title;
var display = "false";
e.preventDefault();
$.ajax({
url: "/useradminpage",
data: {main_id: main_id, display: display},
success: function(data) {
display_false();
alert("4 - returned");
}
});
});
Your problem currently is that main_id and display are not in the scope of the second event listener, so will be undefined (and they shouldn't be quoted, otherwise you're just passing in strings). As you're passing in a data object to the ajax function, you don't really need to add the query string to the URL either.
Aside from that, when you assign a value to main_id, you're using a.title. In this case a is undefined, and you will need to use this, which will be a reference to the clicked element.
I suspect that I might be missing something, but I suspect that your problem is using a.title instead of this.title:
$("a.false").click(function(e) {
$(this).closest("tr.hide").hide("slow");
var main_id = this.title; // or you could use the jQuery object approach: $(this).attr('title') instead
var display = "false";
e.preventDefault();
});
The problem in your original approach is that a would be parsed as a variable, which hasn't been assigned a value, nor has it been declared, so that it would return undefined or null (at best). Within the scope of the each() method, you're iterating over individual nodes; so to access the properties/attributes of that node use this.
To access any attribute of a DOM element through jQuery, you can use the .attr() function.
In your particular case you would do.
var main_id = $(this).attr('title');

jQuery slideToggle() callback function

Here is the jQuery slideToggle function:
$('.class').click(function() {
$(this).parent().next().slideToggle('slow', function() {
// how can I access $('.class') that was clicked on
// $(this) returns the $(this).parent().next() which is the element
// that is currently being toggled/slided
});
});
In the callback function I need to access current .class element (the one being clicked on). How can I do that?
Take a reference to the element outside of the callback, you can then use this inside the callback function.
$('.class').click(function() {
var $el = $(this);
$(this).parent().next().slideToggle('slow', function() {
//use $el here
});
});

Categories

Resources