Add my own function to Slickgrid DataView - javascript

I would like extends the Slickgrid DateView to add a getter for the filterArgs, see https://github.com/mleibman/SlickGrid/pull/775/files.
Example of wrong code... :
(function($) {
$.extend(Slick.Data.DataView, {
"getFilterArgs": function getFilterArgs() {
return filterArgs;
}
});
})(jQuery);
Do you know the right way? Thanks

It seems for me that the only possible way to fit your requirements is to use your own setter as well. Something like:
Extend DataView class with a new getFilterArgs method:
Slick.Data.DataView.prototype.getFilterArgs = function () {
return this._filterArgs;
}
Create your own setFilterArgsInternal method and use it:
Slick.Data.DataView.prototype.setFilterArgsInternal = function (args) {
this.setFilterArgs.call(this, args);
this._filterArgs = args;
}
Again, everywhere after that use setFilterArgsInternal instead of setFilterArgs.

Related

How to call "class method" from outside class in JavaScript?

I've got some code in JavaScript and I'm looking to trigger a ViewModel method using a keyboard shortcut. What is the correct syntax? Here's my code:
document.addEventListener('keydown', function(event) {
if (event.keyCode==27){
ViewModel.escapePressed();
}
}, true);
function ViewModel() {
this.escapePressed=function(){
// Code
};
}
If you are going to use that style of class, then you must first make an instance of it.
var a_view_model = new ViewModel();
a_view_model.escapePressed();
… but if you just want to have a static method, then you probably shouldn't be using a constructor function in the first place
var view_model = {
escapePressed: function () { };
}
and:
view_mode.escapePressed();

Knockout subscribe/event type system without observable?

I want to make use of the subscribe() function of knockout js to manually trigger an event at a certain point.
I could make an observable() and everytime put a GUID in there to trigger the scubscribe.
Is there a cleaner way within Knockout js to have a typical event-like structure?
Edit
Ok, apparently I can use observable.valueHasMutated() - might already a a bit cleaner that using a GUID.
Example
This is the behaviour that I'm looking for:
function Car()
{
var self = this;
self.onOpenDoor = ko.observable();
self.openDoor = function()
{
// using an observable / valueHasMutated for this feels a bit hacky
// is there an other way to use the underlying subscribe() system?
self.onOpenDoor.valueHasMutated();
}
}
var car = new Car();
// multiple subscribers
car.onOpenDoor.subscribe(function()
{
console.log('Do something');
})
car.o**nOpenDoor.subscribe(function()
{
console.log('Do something else');
})
car.openDoor();
I am aware this is not the default 'knockout' way to do stuff - that is not what this question is about.
Update
After #RoyJ's reference to Niemeyer's blog I went for this solution:
function Car()
{
var self = this;
self.onOpenDoor = new ko.subscribable();
self.openDoor = function()
{
self.onOpenDoor.notifySubscribers();
}
}
Update If you're just looking for clarity, you can use notifySubscribers instead of valueHasMutated. You might want to take a look at the base type of observables, ko.subscribable.
I would do it like this:
var vm = {
///...definitions...
openCount: ko.observable(0),
openDoor: function () {
vm.openCount(vm.openCount()+1);
}
};
vm.openCount.subscribe(function () {
///...do something
});
vm.openCount.subscribe(function () {
///...do something else
});
ko.applyBindings(vm);
Demo http://jsfiddle.net/uoqdfhdb/2/

how to override a returned nested method in javascript?

Say I'm using a library with the code that looks like below:
(function($)
{
function Library(el, options)
{
return new Library.prototype.init(el, options);
}
Library.fn = $.Library.prototype = {
init: function(el, options) {
this.$elm.on('keydown.library', $.proxy(this.keydown.init, this));
}
keydown: function() {
return {
init: function(e) {
... somecode
},
checkStuff: function(arg1, arg2) {
...someCode
}
}
};
}
})(jQuery);
It has a plugin system that provides access to this where this is an Object {init: function, keydown: function...}. I want to override the keydown.init function. Normally I could see using something like _.wrap to do it:
somefunc = _.wrap(somefuc, function(oldfunc, args) {
donewstuff();
oldfunc.call(this.args);
});
but that doesn't seem to work on the returned nested method e.g.:
this.keydown.init = _.wrap(this.keydown.init, function(oldfunc, args) {
donewstuff();
oldfunc.call(this.args);
});
The question might be answered on here but I don't really know the right words to use to describe this style of coding so its hard to search. Bonus points if you let me know if it is even correct to call it a nested returned method?
This pattern is called a module. The best thing you can do here is cache the method you want to override and call the cached method inside your override:
somefunc._init = somefunc.init;
somefunc.init = function () {
doStuff();
this._init();
};
I checked _.wrap and it does the same thing, what your missing as pointed out by another answer is you're losing the context of somefunc. In order to prevent that you can do:
somefunc.init = _.wrap(_.bind(somefunc.init, somefunc), function (oldRef, args) {
doStuff();
oldRef.call(this.args);
});
You will need to decorate (read: wrap) the keydown function so that you can wrap the init method of the object it returns:
somefunc.keydown = _.wrap(somefunc.keydown, function(orig) {
var module = orig(); // it doesn't seem to take arguments or rely on `this` context
module.init = _.wrap(module.init, function(orig, e) {
donewstuff();
return orig.call(this, e);
});
return module;
});
The problem is that your method is run out of context.
You need to set its this context (use .bind() for this)
somefunc.init = _.wrap(somefuc.init.bind(somefunc), function(oldfunc, args) {
donewstuff();
oldfunc.call(this.args);
});

Adding a function to a JavaScript object

In my JavaScript I have an object instance called "View". I want to add a function to this object. The function looks something like
function csiSelectValueRestriction (columnName) {
//... <a rather long and involved function>
}
Ultimately I want to be able to use the function in the following way:
var result = View.csiSelectValueRestriction ("bldgs");
What is the simplest way to accomplish this?
Just assign the function to the property;
View.csiSelectValueRestriction = csiSelectValueRestriction;
This should work if you want to add a function to an existing instance
View['csiSelectValueRestriction'] = function (columnName) { ... ... }
var View = {
someProperty: 'someVal',
csiSelectValueRestriction: function(columnName) {
//JS logic
}
};
or View.csiSelectValueRestriction = function(columnName) { ... }

Need Help extending a javascript object

Let's say I have a javascript object...
app.dooDad = {}
(function (O) {
O.magicStuff = function() {
alert("LOL!");
}
...other methods...
})(app.doodad)
Now let's say I make a deep copy of this object...
app.specialDooDad = jQuery.extend(true, {}, app.dooDad);
(function (O) {
O.magicStuff = function() {
alert("LOL!");
alert("Cats!");
}
})(app.doodad)
I am wondering: Is there a better way to do this? That is, is there a better way to to extend the method magicStuff with additional commands in specialDooDad, without rewriting it?
thanks (in advance) for your help.
Correct me if I'm wrong, but I believe you can do something like this in Javascript:
app.specialDooDad = jQuery.extend(true, {}, app.dooDad);
(function (O) {
O.oldMagicStuff = O.magicStuff;
O.magicStuff = function() {
//Additional stuff you want to do
alert("Cats!");
O.oldMagicStuff();
}
})(app.doodad)
That only works well if you are just adding on an additional thing or two, either before or after the "original" function would run. If you need to add things into the middle, I believe you just have to rewrite the function.
I'm assuming you want to do this to maintain backward compatibility with an existing codebase (such as an open source library)?
function DooDad() {
this.magicStuff = function() {
alert("LOL!");
}
}
app.dooDad = new ConstructorA();
function SpecialDooDad() {
var o = new DooDad;
this.magicStuff = function() {
o.magicStuff.apply(this, arguments);
alert("Cats!");
}
}
app.specialDooDad = new SpecialDooDad;
I prefer this way of extending. It's more functional. You create new objects through composition and extension.

Categories