In trying to call a method on the CodeMirror javascript code editor. I'm new to javascript and trying to understand how object oriented stuff works. I'm having problems calling what I believe are methods. For instance,
var editor = CodeMirror.fromTextArea('code', options);
editor.grabKeys(function(e) { alert("Key event");});
This gives the Uncaught TypeError: Cannot call method 'grabKeys' of undefined. Looking at the editor object reveals that grabKeys seems to be located at editor.__proto__.grabKeys.
How should I be thinking about this?
Probably yoour code should be something like this:
var editor = new CodeMirror.fromTextArea('code', options);
editor.grabKeys(function(e) { alert("Key event");});
Notice the 'new' operator..
Here is a good explanation of what prototype method calls are for:
http://www.javascriptkit.com/javatutors/proto.shtml
Related
I’m tinkering around, trying to better understand how I’d go about building a custom jQuery plugin. I’ve never built my own library or plugin, so I’m kind of the bull in the china shop right now.
I have successfully managed to attach my library to the jquery object, however I’m not understanding a few things.
Within my library, I create a method on the prototype chain called checker. This works fine when I call it in my code. However, when I try instantiating the new object FunkyLib with some parameters, it says that FunkyLib is not a constructor, and I’m not sure why.
Here’s the code:
console.log('FuNkY Test');
(function ($, window, document, undefined) {
function FunkyLib (options) {
this.settings = options;
}
FunkyLib.prototype = {
checker: function() { alert('Purake'); }
};
$.fn.funky = new (FunkyLib);
}(jQuery, window, document));
If I were to try instantiating with some parameters with the constructor, I get an error in the console saying that FunkyLib is not a constructor.
For instance:
$.fn.funky = new (FunkyLib('Parameter'));
or
$.fn.funky = new (FunkyLib());
of even in the jquery call:
$('my-class').funky('param')
This works though:
$('my-class').funky.checker();
I’m pretty sure that my structure is just plain wrong. I have some material I’m reading, one of them being a tutorial on creating jQuery plugins. But I was hoping someone could give me a bit of 'to the point' advice on my errors here.
Thanks!
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);
});
I have tried to include a FireBreath plugin object in an AngularJS view, however when I try to render the view I get this error:
TypeError: Cannot read property 'nodeName' of undefined
I am able to successfully include the object in the view with $compile like this:
$("body").append($compile('<object id="plugin" type="application/x-firebreathplugin" width="0" height="0></object>')($scope));
However, after including the object like this I cannot get my plugin to fire an event in the JS.
Doing something like this:
plugin = document.getElementById('plugin');
console.log(plugin);
Returns
TypeError
In the Chrome console. But I can still do:
plugin.callFunction();
And have a FireBreath method execute. The issue is when I try to get an event to fire in the JS. No matter what I try, I cannot get the event to fire. So this code will never execute:
var addEvent = function(obj, name, func) {
obj.addEventListener(name, func, false);
}
addEvent(document.getElementById('plugin'), 'firebreathEvent', function(data) {
console.log('data ' + data);
});
var plugin = document.getElementById('plugin');
plugin.functionThatTriggersFireBreathEvent();
Does anybody know if it has something to do with accessing the object after calling $compile? I noticed that in regular HTML (before using AngularJS) logging the plugin in the console returns this :
<JSAPI-Auto Javascript Object>
So I am thinking that whatever I am getting with document.getElementById after using $compile is not the same.
What would be easier is is if I could just include the <object> tag in the view.html file and have it display in <body class='ng-view'> but I get the top TypeError, so if anyone has any ideas for that, that would be preferred.
Any help is appreciated. Thanks.
If anyone is interested, because I could not get the event to fire, I followed along to this link:
http://colonelpanic.net/2010/12/firebreath-tips-asynchronous-javascript-calls/
(which I think is your blog #taxilian) to get the data back to the JS.
Plugin Code: Great example in the link.
JS Code:
//attach FireBreath Object to AngularJS View
$("body").append($compile('<object id="plugin" type="application/x-firebreathplugin" width="1" height="1"><param name="onload" value="pluginLoaded"/></object>')($scope));
var callback = function(data) {
//data is an object
console.log(data.resultFromFireBreath);
}
plugin = document.getElementById("plugin");
plugin.getData(callback);
This will have to work for now until someone can figure out how to attach an event to the plugin object after $compile.
I ran into the same problem and was able to make the problem go away by creating a read-only nodeName property in my plugin object. I asked about this in a firebreath forum post and taxilian suggested adding this to JSAPIAuto.cpp, which also worked, so I submitted a pull request with the change.
I once spent about 6 hours trying to make FireBreath plugins work with jquery; it was really educational, but ultimately I determined that it wasn't worth the work.
Long story short is that it's not worth it; particularly since even if you could make it work, it would break on IE9 where FireBreath doesn't support addEventListener (IE never gives it the even info, so it's a little hard to support) and you would need to use attachEvent anyway.
i apologize if my terminology is off, my actionscript skills are pretty weak sauce.
so, i have some actionscript that makes a
ExternalInterface.call('someFunction');
call.
is it possible to reference the html object that made the call to someFunction directly using the ExternalInterface.call call?
Assume that the object that makes the call also has some Callbacks (via ExternalInterface.addCallback) that are accessible via javascript.
Currently:
Actionscript source
ExternalInterface.call("someFunction");
ExternalInterface.addCallback("someCallback",someASfunction);
Javascript source
function someFunction(){
document.getElementById('idOfSWFObject').someCallback();
}
I'm thinking there must be a way of:
Actionscript source
ExternalInterface.call("someFunction",THE_OBJECT_MAKING_THE_CALL);
ExternalInterface.addCallback("someCallback",someASfunction);
Javascript source
function someFunction(o){
o.someCallback();
}
once again, sorry about the terminology. tried to lace it with as many keywords for future searches.
thanks!
I guess you are talking about ExternalInterface.objectID. This property returns an id associated with flash container in object or embed tag.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html?filter_flex=4.1&filter_flashplayer=10.2&filter_air=2.en#objectID
I suggest that you should also pass the name of "someCallback" to you JS method. This way there will be no need to hardcode it in JS.
Here's an example
// Actionscript source
const jsMethodName:String = "someFunction";
const asCallbackName:String = "someCallback";
ExternalInterface.call(jsMethodName+"(document.getElementById("++")"++");");
ExternalInterface.addCallback(asCallbackName,someASfunction);
// Javascript source
function someFunction(flashId, callbackName)
{
var flashContainer = document.getElementById(flashId);
flashContainer["callbackName"]();
}
EDIT: If you really want to get a reference to flash DOM object in someFunction arguments, you may achieve it in a bit tricky way (I would rather not, but just for your interest).
// Actionscript source
const jsMethodName:String = "someFunction";
const asCallbackName:String = "someCallback";
ExternalInterface.addCallback(asCallbackName,someASfunction);
ExternalInterface.call(
"function(){"+
jsMethodName+"("+
"document.getElementById('"+ExternalInterface.objectID+"'),"+
"'"+asCallbackName+"'"+
");"+
"}"
);
// Javascript source
function someFunction(flashContainer, callbackName)
{
flashContainer[callbackName]();
}
This way you inject some JS code from flash into js. It works, but looks messy.
My Javascript knowledge is less experienced, so I might use wrong descriptions in the following.
I have an object in a static .js file:
var Info = {
methodA: function() {
// Call methodB.
this.methodB('test');
},
methodB: function(value) {
// Do stuff
}
}
Now, in an .aspx file, I create a function methodC(value) with varying contents (depending on some data), which I want to insert instead of the above definition of methodB(value):
...
var methodC = function(value) {
// Do different stuff
}
...
My idea has so far been to replace methodB with methodC in the following fashion:
...
Info.methodB = methodC;
...
Using IE's buildin developer tool, I get the following error when calling this.methodB('test'); from Info.methodA():
Object doesn’t support this property
or method
Removing the 'this' from this.methodB('test') results in the error:
Object expected
I don't get any errors using FireBug - probably because I use various frameworks, which might catch the error.
How should I do this or should I use a completely different approach?
Regards, Casper
It should work, you are doing it the right way. The problem lays elsewhere.
update:
This should still work as long as you call methodA on an object, eg Info.methodA().
Maybe you are not understanding the error messages ?
"Object doesn’t support this property or method" means that in the expression "this.methodB()", this doesn't have a property named "methodB". So it means that this is not Info when the code of methodA is executed.
"Object expected" means that the variable methodB is unknown in the current execution context. Of course it is, since methodB is never a variable, only a property of Info.
To debug your problem, you need to know what is this when a code is executed, and why it's not what you think it should be. When you call Info.methodA(), this is set to be Info when methodA begins its execution.