onclick attribute not working as expected - javascript

I have a jquery file as follow :
$('.font').click(function(){
for(i=0;i<FontArray.length;i++){
var font = FontArray[i];
$('#view_container').append("<button class='b_font' id='"+font+"' onclick='saveMe("+font+");'>"+font+"</button>");
$('.'+font).css('font-family',font);
}
// event.preventDefault();
});
And the function saveMe is defined as follow :
function saveMe(font){
alert(font);
}
But when i click any of the button i get the following error :
Uncaught ReferenceError: saveMe is not defined
Can anyone help me on this ?
Thanks in advance!

The line
onclick='saveMe("+font+");'
renders as
onclick='saveMe(arial);'
So when you click on it, it is looking for a variable arial not the string "arial". You need to quote it.
onclick='saveMe(\""+font+"\");'
Now for saveMe not being defined, that needs to have more context. When is saveMe defined? If it is inside of a document ready/window onload method, than you need to put it outside of it so it is available in window scope.
And the line
$('.'+font).css('font-family',font);
Should probably be
$('#'+font).css('font-family',font);

The most important thing is where the saveMe function is defined. onclick has only access to global scope and that's there the fuction would have to be for this solution to work.
That'd be a quick workaround:
window.saveMe = function (font){
alert(font);
}
However, you should note that cluttering global scope is usually undesirable and quickly leads to errors. It's better to attach events to selected elements by using .click(). In your code - you can attach the element and then bind click event to it.
var $button = $("<button class='b_font' id='"+font+"' onclick='saveMe("+font+");'>"+font+"</button>");
$('#view_container').append($button);
$button.click(function () {
alert($(this).attr('id'));
});
EDIT: As epascarello also pointed out - the string is not escaped properly

I'm guessing saveMe is out of scope, you probably put it inside the DOM ready handler.
As you're using jQuery, why not use it, and get rid of those inline event handlers
$(function() {
$('.font').click(function() {
$('#view_container').append(
$.map(FontArray, function(index, font) {
return $('<button />', {
'class' : 'b_font',
id : font,
on : { click : saveMe },
css : { fontFamily : font }
})
})
)
});
function saveMe() {...}
});

You could simply add this code and get rid of the code in the markup:
$('#view_container').on('click','.b_font',function(){
saveMe($(this).text());
});
OR perhaps better make this change:
$('#view_container').append("<button class='b_font' id='"+font+"' data-fontsave='"+font+"'>"+font+"</button>");
then this works and is less prone to error perhaps:
$('#view_container').on('click','.b_font',function(){
saveMe($(this).data('fontsave'));
});

Related

jQuery : "this" property is not working on $(document) click

I want to change my clicked image src. I tried it using this. The reason is I am using $(document) for click function. The code I am using is shown below. It will change without using this property. But I need to work it using this property.
$document.on('click', 'img.flagImg', function () {
_flag();
})
var _flag = (function(){
$(this).attr('src',"images/flag.jpg")
})
but its not getting. can any one suggest another option for getting a good solution.
When you call a function like that, _flag(), this is set to the global object (in loose mode) or undefined (in strict mode).
Just let jQuery set this for you:
$document.on('click', 'img.flagImg', _flag);
But if you want to avoid jQuery passing it the event argument, you can use call to set this explicitly instead:
$document.on('click', 'img.flagImg', function() {
_flag.call(this);
});

Using $(this) & event in named handler function

I have this function:
function showPost(event){
event.preventDefault();
$(this).parent('article').animate({width:'100%'}, 'slow');
}
I am attempting to use it like so:
$('.article-header').click(function(event){showPost(event);});
When I use it in the above manner, the event property is passed just fine, however $(this) doesn't work within the function. If I attempt to include this as a parameter in the .click method, it returns an error claiming this is undefined. I have even gone so far as to set var ths = $(this); to no avail.
Please, what is the proper way to make this function happen?
Just use the function directly:
$('.article-header').click(showPost);
You're loosing this because you're calling the function "naked", with no object receiver. You could do this too (but don't because there's no point here):
$('.article-header').click(function(event) { showPost.call(this, event); });

Javascript Namespace + onchange = impossible?

I am using a namespace for my javascript code, and I think I have hit a brick wall with a onchange attribute for a select element. When I attempt to call a function with (or without) my namespace the error console is reporting that the function is not found.
var MYNS = {}; //namespace
MYNS.modifySearchPage = function () {
....
var eSelect = document.createElement("select")
.....
eSelect.setAttribute('onchange', 'MYNS.handleChange(this)');
.....
//set up the options (value, textcontent, eSelect.appendChild(theOption)
...
// add the eSelect to the DOM
}
MYNS.handleChange = function (select) {
//parse the select options
}
The result I get in the console when I select an item from the dropdown list is:
Uncaught ReferenceError: MYNS is not defined
I have attempted to add the namespace to the windows but that does not seem to help (and I'm not convinced that is a safe thing to do).
I have tried adding a onclick handler to the select element but obviously that is a bad idea as select does not handle onclicks.
Stripping the MYNS from both the call and function definition also didn't help.
Any ideas?
Thanks,
mwolfe
Don't use attributes to attach handlers - use properties:
eSelect.onchange = function() {
MYNS.handleChange(this);
};
More generically you could also use the standard and more recommended addEventListener:
function changeHandler() {
MYNS.handleChange(this);
}
if (eSelect.addEventListener) {
eSelect.addEventListener('change', changeHandler, false);
} else if (eSelect.attachEvent) {
eSelect.attachEvent('onchange', changeHandler); // fallback for IE
}
It's also worth noting that you can call
eSelect.addEventListener('change', MYNS.handleChange, false);
You will need to modify your callback though - the argument passed will be an event object and this inside the function will refer to the element that triggered the event.
You just code a different word of wrong case MyNS.handleChange, it should be MYNS.handleChange. In JavaScript variables are case sensitive.

Uncaught Reference Error with inline javascript

I have the following function:
if ($(this).find('#sel').length == 0) {
var before = $(this).text();
var title_id = $(this).parent().attr('id');
$(this).html("<select id='sel' onchange='selectdone(this, title_id=title_id)>
...</select>");
}
From this I get Uncaught ReferenceError: title_id is not defined. Why isn't the onchange function inside on line 4 not picking up on the variable that I've defined previously? How would I rewrite the above correctly?
Did you mean this?
$(this).html("<select id='sel' onchange='selectdone(this, "+title_id+");'>...</select>");
Use string concatenation here:
$(this).html("<select id='sel' onchange='selectdone(this, title_id=" + title_id +");'>...
It's happening because you're defining the "change" handler as part of a string, so the language has no idea that there's code in there.
Try this:
$(this).html($("<select/>", {
id: 'sel',
change: function() { selectdone(this, title_id) }
}));
Since you're using jQuery anyway, you should get in the habit of managing your event handlers via the library instead of with "onfoo" attributes.

Javascript scope help

I am relatively new to javascript so please be patient if what i am asking is completely stupid!
I am trying to make a simple module. Inside the module i want to have a config object that holds settings for the module. I am also using jquery. The jquery selectors work only when in a function directly in the main object/module.
I understand that javascript has functional scope so I am suprised that I cannot use the jquery selectors anywhere inside the module.
EDIT:
I want to be able to directly set all of my configs inside the configs object using jquery selectors. This way i keep all the messy stuff inside one place and can then access configs.whatever throughout the rest of the module. At the moment jquery selectors do not work inside the configs module.
var OB = function() {
var configs = {
'mode' : 'test',
'numOfSelects' : $('.mySelect').find('select').length, // This doesnt work
}
var getMode = function() {
return configs.mode;
}
function init() {
alert(configs.numOfSelects); // This alerts 0 until the following line
alert($('.mySelect').find('select').length); // This correctly alerts 2
};
var handlers = {
successHandler : function() {
alert("Success");
},
errorHandler : function() {
alert("error");
}
}
return {
init : init,
getMode : getMode
}
}( );
$(document).ready(function(){
OB.init();
});
It isn't that jQuery isn't in scope — that's that the code isn't executing when you think it is. The variable config is defined when that anonymous function (var OB = function() {}()) is executed. The DOM isn't ready yet, so that DOM traversal doesn't find anything. When you do the DOM traversal in init(), that isn't executed until it's explicitly called inside the $(document).ready() handler, at which point that DOM is set up. That's the difference you're seeing.
OB() needs to be called after the DOM has completely loaded. Hence the answer by Marcelo, which calls OB() in the ready() method.
EDIT: It's funny that my original answer below was incorrect because I didn't notice two little parentheses at the end of the definition of OB, and it turns out that these are the culprit. You define and then immediately invoke OB, which is before the DOM has been fully loaded. Remove those parentheses and make the change I suggest below.
Calling OB() returns an object with init and getMode, but you haven't called OB(), you've only referred to OB. Try this instead:
$(document).ready(function(){
OB().init();
});
Also, I assume you want to later refer to getMode. In particular, you will to get the copy of getMode that has access to the same local scope that your init() call had access to. To achieve this, you will need to store the result of calling OB() for later use:
var ob;
$(document).ready(function(){
ob = OB();
ob.init();
});
function some_other_function() {
... ob.getMode() ...;
}

Categories

Resources