jQuery return like this - javascript

I have problems with jQuery callbacks
I try to do like this.
MainController.js
mapController = $.fn.mapController();
getMapController = function() {
return mapController;
};
mapController.js
(function ( $ ) {
$.fn.mapController = function(options) {
let mapController = {};
let settings = $.extend({
save: function(data) {}
}, options);
mapController.openModal = function () {
//OPEN MODAL
}
return: mapController
}
}(jQuery));
nextController.js
function setPlace() {
getMapController({
save: function(data) {
console.log("TEST")
}
}).openMapModal();
}
So... I try get mapController in nextController from getMapController method but not workink callbacks...
How I can get callbacks in nextController.js?

It seems like you have introduced some confusion by naming a jQuery plugin with the same name as the object that plugin returns. Both are called mapController. This is not a problem on itself, but in setPlace you call mapController as if it it is the jQuery plugin (passing it options), but it is in fact the object returned by it (see MainController.js), which is not a function.
So I think you'll want to change the MainController code, and make the global mapController variable equal to the jQuery plugin:
mapController = $.fn.mapController;
// ^^^^^ remove parentheses.
Like mentioned already, make sure to remove the syntax error in the return statement in the MapController; it should not have a colon after it.

getMapController() returns a function, you have to call it with ():
function setPlace() {
getMapController({
save: function(data) {
console.log("TEST")
}
})().openMapModal();
}
Also, you have an erroneous : on this line:
return: mapController
It should just be:
return mapController

Related

How can I expose a public api from this specific IIFE JS structure?

In AspNetZero/ABP, the default index.js for an entity looks like the following:
(function () {
$(function () {
var _$formulationFrequenciesTable = $('#FormulationFrequenciesTable');
var _formulationFrequenciesService = abp.services.app.formulationFrequencies;
function additionalFilter() {
return {
nameFilter: // something
prop2: // something else
};
}
// more code
});
})();
We are using Telerik's AspNetCore Kendo on the Razor, so we define the grid like so:
Html.Kendo().Grid<PatientManagement.Formulations.Dtos.GetFormulationFrequencyForViewDto>()
.Name("gridFormulationFrequencies")
.DataSource(d =>
{
d.Custom()
.Type("aspnetmvc-ajax")
.ServerFiltering(true)
.ServerPaging(true)
.ServerSorting(true)
.Schema(s => s.Aggregates("aggregateResults").Data("data").Errors("errors").Total("total").Model(model => model.Id(m => m.Id)))
.Transport(t => t.Read(read => read.Action("FormulationFrequency_Read", "FormulationFrequencies", new { area = "App" }).Data("additionalData").Type(HttpVerbs.Get)));
})
.Deferred(true).Render();
How can I make additionalData "public" so that I can use it in the grid definition? I understand that the first line of the js is IIFE, and the second is short hand js for jQuery(document).ready().
I've been having issues trying to define a public API because everything is defined within the scope of the document ready, and IIFE examples I've seen don't include this curveball.
One way would be to assign a reference to the function to a window property.
If you have to do this often you could have a global object of your own in window namespace and assign as a property to that object instead
(function () {
$(function () {
var _$formulationFrequenciesTable = $('#FormulationFrequenciesTable');
var _formulationFrequenciesService = abp.services.app.formulationFrequencies;
function additionalFilter() {
return {
nameFilter: // something
prop2: // something else
};
}
// add to global window namespace
window.additionalFilter = additionalFilter;
// more code
});
})();

Access angular2 variables in jquery

I'm using jQuery for some things in my angular2 projects. But I can't manage to use variables I've declared in angular2 to use in jQuery. I have something like this:
export class AddExerciseComponent implements OnInit {
parameters:Array<string> = ["FU"];
constructor() { }
ngOnInit() {
$('.chips').on('chip.add', function(e, chip){
this.parameters.push(chip.data);
console.log(this.selectedValue);
});
}
This would get me an error that parameters is not defined. I guess it's because I use this. What else can I do?
You need to use an arrow function expression (() => {}) to keep this in scope. Try:
export class AddExerciseComponent implements OnInit {
parameters:Array<string> = ["FU"];
constructor() { }
ngOnInit() {
// removed function keyword and added () => {} syntax
$('.chips').on('chip.add', (e, chip) => {
this.parameters.push(chip.data);
console.log(this.selectedValue);
});
}
When you passed your callback as a regular old function, JavaScript doesn't consider your callback to be within the scope of the calling function, leaving this unusable for calling data from the scope you thought you were in. By using an Arrow function, the scope is saved and this is usable for accessing data as expected.
If you are looking to use angular variables in jquery animate ON-Complete function call back,that's how you do it:
$('#myDiv').animate({top: 70+"%"},{
queue: false,
duration: 1000,
complete: () => {
//this is you angular variable of the class
this.angularVar = 0;
$("#myDiv").hide();
//this is you angular variable of the class
this.showAnimation = false;
//this is you angular class function
this.angularFunction();
console.log("animation complete");
}
});
Assign angular's this(instance) to Jquery's this(instance) to use the angular variable inside JQuery
let jQueryInstance = this; // This line will assign all the angular instances to jQueryInstance variable.
$('.chips').on('chip.add', (e, chip) => {
/* this.parameters.push(chip.data); */
// Instead of the above line we have to use like below
jQueryInstance.parameters.push(chip.data); // instead of "this", "jQueryInstance" is used
// console.log(this.selectedValue);
console.log(jQueryInstance.selectedValue);
});

Reactive variable is undefined when it is defined

I would like to get some help debugging a situation where a Reactive Variable is undefined, when it has been defined already.
This code is attaching a Reactive Variable to the template instance, and using the variable in template.autorun().
Template.home.onCreated(function () {
this.limit = new ReactiveVar(15);
this.autorun(function () {
this.subscribe('recent-topics', this.limit.get());
});
});
When I load the template for the first time, I expect the template to subscribe to recent-topics with an argument 15. However, the code throws an error:
Uncaught TypeError: Cannot read property 'get' of undefined
Any ideas why?
Just an answer for the sake of spreading the joys of ES6:
Template.home.onCreated(function () {
this.limit = new ReactiveVar(15);
this.autorun(() => {
this.subscribe('recent-topics', this.limit.get());
});
});
Make sure you add the grigio:babel package, and your Javascript file ends in .es6.js, .es6, or .jsx.
Explanation
In ES6 (aka ECMAScript 6), there's a new "fat arrow" syntax which is very similar to CoffeeScript's implementation. In ES6, when you do something like this:
someFunc = function () {
anotherThing((var1, var2) => {
this.thing = true;
});
};
It's the same as doing this:
someFunc = function () {
var self = this;
anotherThing(function (var1, var2) {
self.thing = true;
});
};
This is a scoping issue.
Inside of your Tracker.autorun, this no longer refers to the template, but the autorun's callback function. Inside of the autorun, try calling Template.instance().limit.get().
Better than using Template.instance().limit.get() (ryan's answer)
You should do something like this:
Template.home.onCreated(function () {
var self = this;
self.limit = new ReactiveVar(15);
self.autorun(function () {
self.subscribe('recent-topics', self.limit.get());
});
});

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);
});

how call a TinyMCE plugin function?

how can I call a tinymce plugin function?
tinymce.activeEditor.plugins.customplugin.customfunction(customvar);
not working!
tinymce.activeEditor.plugins.customplugin.customfunction(customvar);
is the correct way to call such a function.
Be aware that tinymce.activeEditor needs to be set already in order to use it.
tinymce.activeEditor gets set when the user clicks into the editor for example.
Otherwise use
tinymce.get('your_editor_id_here').plugins.customplugin.customfunction(customvar);
There might be another reason for your function call not to work:
The function you want to call needs to be defined like the functions getInfo, _save and _nodeChange in the save plugin (see the developer build of tinymce to inspect this plugin in the plugins directory).
The save plugin shortened here:
(function() {
tinymce.create('tinymce.plugins.Save', {
init : function(ed, url) {
...
},
getInfo : function() {
...
},
// Private methods
_nodeChange : function(ed, cm, n) {
...
},
// Private methods
...
_save : function() {
}
});
// Register plugin
tinymce.PluginManager.add('save', tinymce.plugins.Save);
})();
You may call the getInfo function of this plugin using the following javascript call:
tinymce.get('your_editor_id_here').plugins.save.getInfo();
Put the function you want to expose to the outside world in self.
tinymce.PluginManager.add('myplugin', function(editor) {
var self = this;
var self.myFunction = myFunction(); // Put function into self!
function myFunction() {
console.log('Hello world!');
}
}
Then:
tinymce.get('your_editor_id_here').plugins.myplugin.myFunction();

Categories