Passing object and its methods to onchange function in Javascript - javascript

I am using TableExport.js script to export an html table, and I need to export the data after I've filtered it by hiding the rows I don't want. TableExport's method .update() comes in really useful here, but I am having some problems to call it every time the data is filtered, which is associated to an onchange event. Here are the relevant pieces of my code:
$(function () {
var exportedTable = $("#taskListTable").tableExport();
exportedTable.update({
// some options
});
$('body').on('change', '.filter', function (exportedTable) {
// some code for filtering
tableUpdate(exportedTable);
});
})
function tableUpdate(table) {
table.update({
ignoreCSS: ["tr.tableexport-ignore", "tr.tableexport-ignore>td",
"tr.tableexport-ignore>th", "tr.hidden", "tr.hidden>td"]
});
}
I keep getting an error of the type Uncaught TypeError: Cannot read property 'update' of undefined. I've been reading lots of threads (like this: Javascript passing object to function) and other info to understand the difference between passing by value and reference, but the more I read and try the more chaotic my mind is getting. So can anyone see what it is failing in my approach? - It's partly legacy code though, but I'm open to re-structure most of it if necessary.
I guess this is more a problem of JS misuse, so I hope this question will be useful both for people working with TableExport and people with similar JS issues. So I summon thee, JavaScript Jedis!

Event handler functions are called with an event object as the parameter. You probably just wanted to access exportedTable from the scope, rather than accepting it as an argument.

As #guest said, you simply have to remove exportedTable from parameters:
$('body').on('change', '.filter', function () {
# some code for filtering
tableUpdate(exportedTable);
});

Related

TypeError: this._url is undefined at Dojo FilteringSelect onChange callback

I keep getting following error: TypeError: this._url is undefined at the callback of a Dojo FilteringSelect.
I simplified my code to this:
var testFeatures = [
{ "id": 1, "Adresa": "Pyšvejcova 6, Kotěhůlky"},
...
];
var filteringSelect = new FilteringSelect({
id: "testSelect",
autoComplete: false,
searchAttr: "Adresa",
store: new Memory({ data: testFeatures }),
onChange: this.onSelected
}, "testSelect");
filteringSelect.startup();
//end of the function, still in the same define callback
onSelected: function () {
//custom processing
var queryTask = new esri.tasks.QueryTask(this.serviceUrl);
var query = new esri.tasks.Query();
query.outFields = ["OBJECTID"];
query.where = "Adresa=" + dojo.byId("testSelect").value;
query.returnGeometry = true;
queryTask.execute(query, this.zoomToSelected);
}
zoomToSelected: function (featureSet) {
//custom map processing
}
and HTML:
<input id="testSelect" data-dojo-attach-point="testSelect" />
I have no idea where's the problem, Google found no case similar to mine. FireBug says the error occurs in init.js. Console says line 199, but the code in question (...nction(){},onExecuteForCountComplete:function(){},onExecuteForExtentComplete:fun...) is on line 256.
One possible cause of problems might be ArcGIS JavaScript API or Web AppBuilder - this seems not to be one of the "ArcGIS-heavy" parts of the code, but I don't know for sure. It's ArcGIS JS API 3.15 (Dojo 1.10) and Web AppBuilder for developers version 1.4.
EDIT: with help of #KenFranqueiro and this post I made some progress. I can't say that I fully understand the onChange callbacks, but I learnt to omit the parentheses while calling a named function. The onSelected still wasn't called, but modifying the input data to include id solved this. But it didn't solve the main problem...
Now the old good TypeError: this._url is undefined occurs at queryTask.execute, or between it and start of zoomToSelected method. The exact place where the error occurs changed to line 256, column 351, with following referenced code:
...e:function(a,b,c,d,f){var m=f.assembly;a=this._encode(n.mixin({},this._url.query...
There is a pointer at the = after "a", so the error seems to be to the right of it, trying to mixin something non-existent to something else. I have no idea what the this in the init.js should mean. Unfortunately, dojo core code is almost undebuggable without some de-obfuscation. Is this my only option, or does anybody know how to solve it?
So debugging the init.js wasn't so hard, it takes QueryTask as this. As far as I know, this shouldn't have a _url attribute. So I must have some mistake in the queryTask as well.
Obsolete part of the question, archived:
I wonder whether the problem might be caused by the onChange callback's argument, which I don't really understand. I've read several examples of Dojo FilteringSelect with onChange event set, like the official one. Usually it has some argument, but I don't know what does it mean and where it gets from. In the official example it corresponds to the div id and nothing else. However, how is the id translated to a variable and even whether my assumption that it's the id is correct. The detailed documentation is not much helpful in this case.
Older EDIT: testSelect is an object. Seems it was created implicitly with the dom - it's a childnode of this.domNode. So now I understand where it comes from, but not how to prepare another function to be called on change and why the correct syntax is what it is.
Also, I don't know where exactly is the problematic undefined this._url supposed to exist. In my example, this refers to the dijit, but I have no idea what is the scope of the part of init.js where the problem occurs.
I'm not sure how much related are the two subquestions (confusion in the onChange callback and identification of this in init.js), I only suppose they are symptoms of the same issue since the error is thrown at the onChange event in my code.
The problem at the query was caused by this.serviceUrl either missing as a part of wrong coontext, or being an object instead of a URL string. So the final step was to make sure the correct context is used (by lang/hitch) and then setting this.serviceUrl to be what I originally thought, one of the attributes of the object referenced as serviceUrl before.

Javascript / jQuery basic function issue

I am trying to display a div on click. The function that is supposed to make the magic happen is:
$(document).ready(function showGogoasa() {
$('.gogoasa-newsletter').show();
});
Unfortunately, it does nothing. Which makes me scratch my head for hours as I have done small things like this in the past and they worked. I am trying to make this modification on the website of a client.
When I check the firebug console it says the following: ReferenceError: showGogoasa is not defined
I tried looking on Google for this kind of error but the similar cases had this kind of issue for not declaring a variable. Well, I do not have any variables.
I am trying to display a div on click.
Your code is running the function on a ready event and doesn't give the error you describe.
Presumably (it would have helped if you had provided a complete test case) you are also trying to bind the function as a click handler, but you can't do that because you have defined it using a function expression and not a function declaration (so it doesn't create a variable called showGogoasa outside of its own scope).
Define the function separately, then assign call it and bind it as a click event handler on the ready event.
$(document).ready(function ready_handler() {
function showGogoasa() { // Define it as a variable in the current scope
$('.gogoasa-newsletter').show();
}
showGogoasa(); // call it now
$("button").on("click", showGogoasa); // call it then
});
Well, I do not have any variables.
That's the problem :)
Functions are first class objects and when you say showGogoasa() that means "Get the value of showGogoasa and call it as a function".
Using jsfiddle or providing more code would have been helpful.
One issue is that you are missing the click event handler. For example when the user clicks on X then Y should happen/show. The following simple example may help you to see how it works:
http://jsfiddle.net/fionaredmond/1vbagj12/
$(document).ready(function(){
$("#showGogoasa").click(function(){
$(".gogoasa-newsletter").show();
});
});
$(document).ready(function() {
$('#idOfYourClickerElement').on('click', function(){
$('.gogoasa-newsletter').show();
});
});

Updating object within function

Anybody suggest why the button doesn't work here? I must have a syntax error but the console is showing no errors and the JS is valid. http://jsfiddle.net/FZ6K6/20/
self.msg = function () {
self.msgbox = {
status: "information",
message: "Enter some info"
};
You're passing a constructor function to applyBindings().
Since the function itself has no useful properties, nothing happens.
You probably want to pass an instance of that function using new.
There are a couple issues here, including the lack of an instance of your View Model.
Check out the notes I posted on this updated fiddle:
http://jsfiddle.net/FZ6K6/22/
ko.applyBindings(new FormViewModel(),document.getElementById('domElementToBind'));
Not only are we 'new-ing' up an instance of FormViewModel, but we're also specifically assigning a DOM element to apply the bindings to...which is good practice.

extend a javascript option to add functionality

I need to call "MyOtherFunction" when "MyFunction"(which creates an element) completes, without MyFunction knowing what MyOtherFunction is.
The reason I need this is for extension of a jquery powered fileupload User Control that is used in several places with different functionality. A specific page shows a header and file count for it, and when the upload completes, I need to modify the file count according to how many files are displayed(by created elements) I thought :
$(UserControl).on(MyFunction, UploadElem, MyOtherFunction);
but this route is not accomplishing anything. The most I can alter the User Control is add in a function call, but without effecting the original user control functionality.
I'm not sure if because MyFunction isn't an event and doesn't bubble up or if it just isn't possible to use a defined function as a parameter of .on() is the reason I cannot get this code to work. Any suggestions?
Easiest way I can think of, is duck punching respectively hooking that method:
var _oldMyFunction = MyFunction;
MyFunction = function() {
_oldMyFunction.apply( this, arguments );
MyOtherFunction();
};
I managed to solve my own issue, but the context is important for the answer:
// Using a Global JavaScript object I created:
GlobalNameSpace.ExtensionFunction = function(oParam1, oParam2, oParam3)
{
/// <summary>All parameters are optional</summary>
return; // For instances when it is not being overwritten, simply return
}
//In the Code for the user control:
GlobalNameSpace.UploadControl.UploadComplete(oSender, oArgs)
{
///<summary>Handles the Upload process</summary>
// process the upload
GlobalNameSpace.ExtensionFunction(oSender, oArgs);
}
//and finally in the code to extend the functionality
GlobalNameSpace.Page.Init
{
///<summary>Initializes the page</summary>
// redefine the extension function
GlobalNameSpace.ExtensionFunction = function(oSender, oArgs)
{
GlobalNameSpace.Page.Function(oSender, oArgs);
}
}
This allows me to extend anything I need it to without polluting my objects, and having something generic already existing to call on to make my changes. This solution solves my problem of needing a onCreate function for the elements I create to represent my uploaded items to trigger the header displaying the number of files. Very useful

Get value of current event handler using jQuery

I can set the onclick handler using jQuery by calling
$('#id').click(function(){
console.log('click!');
});
Also using jQuery, how can I get a reference to the function which is currently handling the click() event?
The reason is that I have another object and want to set its click handler to the same one as #id.
Update
Thank you for all the suggestions. The problem is that I do not know which function is currently handling the clicks. Keeping track of it would add state to an already complicated template-editing system.
jQuery's .click(function) method adds the function to a queue that is executed on the click event~
So actually pulling out a reference to the given function would probably be hairy-er than you expect.
As noted by others, it would be better to pass in a reference to the function; and then you already have the reference you need.
var clicky = function () { /* do stuff */ };
$('#id').click(clicky);
// Do other stuff with clicky
Update
If you really really need to get it out, try this:
jQuery._data(document.getElementById('id')).events.click[0].handler
Depending on your version of jQuery that may or may not work~ Try playing around with
jQuery._data(document.getElementById('id'))
and see what you get.
Got the idea from this section of the source:
https://github.com/jquery/jquery/blob/master/src/event.js#LC36
if you dont know the name of the function you can use
args.callee
https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee
function clickHandle(e){
if($(e.target) == $('#id')) {
$(newTarget).bind('click', clickHandle);
}
}
$('#id').bind('click',clickHandle);
I think this would be the most symantic way of going about it

Categories