How to write flexible and generic javascript module or plugin - javascript

I want to write a javascript/jquery plugin so that it is generic enough to be used in any framework such as angularjs, backbonejs, ember etc. I should be generic enough so that it should use directives if it is used with angular and backbone native functionality when it is used with backbone. Is it possible if yes then could someone guide me how?

The most natural way I can think of is just to write it in vanilla JS. That will make it work in every framework without needing to worry about it.
If you want to go ahead with this route though, I'd use a driver-style implementation where you pipe everything to a specific driver for a particular framework. You'd define every method you want for each Driver, then the calls get forwarded on automatically to the correct Driver.
var myPlugin;
(function() {
myPlugin = function(framework) {
var me = {},
framework = framework || 'angular';
me.frameworks = {
angular: new AngularDriver,
backbone: new BackboneDriver,
ember: new EmberDriver
};
// Call a method framework-agnostically
me.fire = function(method, args) {
if (!me.frameworks.hasOwnProperty(framework)) {
console.log('Error: Framework not recognised.');
return;
}
if (!me.frameworks[framework].hasOwnProperty(method)) {
console.log('Error: Method not found in ' + framework + '.');
return;
}
me.frameworks[framework][method].apply(this, args);
}
return me;
}
function AngularDriver() {
var me = {};
me.test = function() {
console.log('Hello from the Angular Driver');
}
return me;
}
function BackboneDriver() {
var me = {};
me.test = function() {
console.log('Hello from the Backbone Driver');
}
return me;
}
function EmberDriver() {
var me = {};
me.test = function(arg) {
console.log('Hello from the ' + arg + ' Ember Driver');
}
return me;
}
})();
var instance = new myPlugin();
instance.fire('test');
instance = new myPlugin('ember');
instance.fire('test', ['best']);
It's entirely possible that there's a slightly cleaner way to implement the myPlugin.fire function, if anyone else can improve that bit so the syntax of instance.fire('test', ['best']) is a bit cleaner, feel free :-)

Related

How to create simple global event/message bus in javascript?

I am writing vanilla javascript project. I have multiple independent components. I like them to communicate without coupling them. Event based message bus is ideal for me. I implemented something trivial like following and I would like to ask whether is there any existing library that can do this more efficiently or whether language itself provides any capabilities to achieve this or not?
PS: I do not have any dom events in this case. I would like to create my own events so that I can write components pretty generic and clean way. I think React has similar concept and I will check that later on but for now I like to use vanilla javascript.
Thanks!
// event message bus interface
define(function(require) {
"use strict";
function CustomEventDispatcher() {
this._subscribers = {}
CustomEventDispatcher.prototype.on = function(event, callback) {
if(!this._subscribers[event])
this._subscribers[event] = [];
this._subscribers[event].push(callback);
}
CustomEventDispatcher.prototype.trigger = function(event, params) {
if (this._subscribers[event]) {
for (let i in this._subscribers[event]) {
this._subscribers[event][i](params);
}
}
}
CustomEventDispatcher.Instance = null;
CustomEventDispatcher.GetInstance = function () {
if (!CustomEventDispatcher.Instance) {
CustomEventDispatcher.Instance = new CustomEventDispatcher();
}
return CustomEventDispatcher.Instance;
}
return CustomEventDispatcher;
});
// UI interaction triggers or backend worker triggers event
let params = {
new_dir : '/dat',
};
CustomEventDispatcher.GetInstance().trigger('onUpdateDataSource', params);
// Directory Module registers directory update events and updates itself
function DirectorLister() {
CustomEventDispatcher.GetInstance().on('onUpdateDirectoryListing', (params) => this.change_content(params));
}

Inheritance in JavaScript: How can I call the object parent?

I'm building a multi-source audio player in JavaScript and my goal is to code several providers classes (for Youtube, Soundcloud, etc.) that would extend a base class, so each provider would have the same methods and properties, but I would be able to customize them for each provider.
Here's a simplified example.
The base class looks like this :
function Player_Provider(slug) {
this.slug = slug;
console.log("Player_Provider init: " + this.slug);
};
Player_Provider.prototype.loadUrl = function(url) {
console.log("provider "+this.slug+" - load URL: " + url);
};
I "extend" this class for providers; for example:
function Player_Provider_Youtube() {
Player_Provider.call(this, 'youtube');
}
Player_Provider_Youtube.prototype = Object.create(Player_Provider.prototype); //inherit methods
Player_Provider_Youtube.prototype.constructor = Player_Provider_Youtube; //fix constructor
Player_Provider_Youtube.prototype.loadUrl = function(url) {
Player_Provider.prototype.loadUrl(url);
}
And then I register it like this:
var providers = [];
providers.youtube = new Player_Provider_Youtube();
providers.youtube.loadUrl("https://www.youtube.com/watch?v=5SIQPfeUTtg");
Which outputs in the console:
Player_Provider init: youtube
provider undefined - load URL: https://www.youtube.com/watch?v=5SIQPfeUTtg
As you can see, the console outputs:
"provider undefined - load URL..."
when I would like it to output:
"provider youtube - load URL..."
The idea here is that in each function of the provider (which would every time override a function from the base class), I would call the "parent" function first, at least to output a console message like here; and eventually to run some code - in the idea of having the most clean code possible.
I'm more comfortable with PHP and it's the first time I'm trying to do that kind of stuff using JavaScript.
How would you do this and why is my variable undefined?
In ES5 and earlier, it's a pain. You use call or apply, and as you've found, it's really verbose.
Player_Provider_Youtube.prototype.loadUrl = function(url) {
Player_Provider.prototype.loadUrl.call(this, url);
// ------------------------------^^^^^^^^^^^
}
I found that painful enough I wrote a library to deal with it (here), but it's obsolete now.
But, here in 2017, you don't do that anymore; instead, you use ES2015's class syntax and transpile (with something like Babel) so it runs on older JavaScript engines:
class Parent {
method() {
console.log("Parent method");
}
}
class Child extends Parent {
method() {
console.log("Child method");
super.method();
}
}
new Child().method();
That handles all the nasty plumbing for you. It's still the same prototypical inheritance + constructor functions that it was before ES2015, it's just much simpler syntax for it. (And enables a couple of things we couldn't do with the old syntax.)
I was just doing a JSFiddle and T.J.Crowder beat me to it!
function Player_Provider(slug) {
this.slug = slug;
console.log("Player_Provider init: " + this.slug);
};
Player_Provider.prototype.loadUrl = function(url) {
console.log("provider "+this.slug+" - load URL: " + url);
};
function Player_Provider_Youtube() {
Player_Provider.call(this, 'youtube');
}
Player_Provider_Youtube.prototype = Object.create(Player_Provider.prototype); //inherit methods
Player_Provider_Youtube.prototype.constructor = Player_Provider_Youtube; //fix constructor
Player_Provider_Youtube.prototype.loadUrl = function(url) {
Player_Provider.prototype.loadUrl.call(this, url);
}
var providers = [];
providers.youtube = new Player_Provider_Youtube();
providers.youtube.loadUrl("https://www.youtube.com/watch?v=5SIQPfeUTtg");
https://jsfiddle.net/4Lmkuwts/

Prototypal Inheritence in Node JS

Being from the classical Inheritance Background(C#,Java etc.) , I am struggling with the Prototypal Way of doing it.
I am not understanding the basics also . Please explain and correct me on the following code block.
var util = require ('util');
function Student(choiceOfStream) {
this.choiceOfStream = choiceOfStream;
}
Student.prototype.showDetails = function() {
console.log("A student of "+this.choiceOfStream+" has a major in "+this.MajorSubject);
}
function ScienceStudent() {
Student.call(this,"Science");
}
function ArtsStudent() {
Student.call(this,"Arts");
}
util.inherits(ScienceStudent,Student);
util.inherits(ArtsStudent,Student);
var ArtsStudent = new ArtsStudent();
var ScienceStudent = new ScienceStudent();
ScienceStudent.prototype.MajorSubject = "Math";
ArtsStudent.prototype.MajorSubject = "Literature";
console.log(ArtsStudent.showDetails());
console.log(ScienceStudent.showDetails());
But the error I am getting is
What was I missing ?
There is no standard this.super_ property so I'm not sure where you got that from. If you're using util.inherits(), you can see a nice simple example of how to use it in the nodejs doc for util.inherits().
And, here's how your code could work:
var util = require ('util');
function Student(choiceOfStream) {
this.choiceOfStream = choiceOfStream;
}
Student.prototype.showDetails = function() {
console.log("A student of "+this.choiceOfStream+" has a major in "+this.MajorSubject);
}
function ScienceStudent() {
Student.call(this, "Science");
this.majorSubject = "Math";
}
function ArtsStudent() {
Student(this,"Arts");
this.majorSubject = "Literature";
}
util.inherits(ScienceStudent,Student);
util.inherits(ArtsStudent,Student);
FYI, in ES6 syntax, there is a super keyword which is part of a new way of declaring Javascript inheritance (still prototypal) you can read about here.

correct javascript app structure

I've wrote a small example for readability.. I'm trying to get my head around proper js app structure.
I'm new to writing larger js apps. Right now, I've got a constructor, and a whole bunch of prototype functions. I always thought you're NOT supposed to call (or return) from one function to another. But now, at the bottom of my app, I'm instantiating my constructor, then having to call a bunch of functions, as well as build in conditional statements to handle the execution, which seems totally wrong.
This is the idea I've been doing:
function TodaysFood(b, l)
{
this.breakfast = b;
this.lunch = l;
}
TodaysFood.prototype.firstMeal = function()
{
return console.log(this.breakfast);
}
TodaysFood.prototype.secondMeal = function()
{
return console.log(this.lunch);
}
var app = new TodaysFood("eggs", "sandwich");
app.firstMeal();
app.secondMeal();
I'm wondering if this function "linking" is proper?
function TodaysFood(b, l)
{
this.breakfast = b;
this.lunch = l;
}
TodaysFood.prototype.firstMeal = function()
{
return this.secondMeal(this.breakfast);
}
TodaysFood.prototype.secondMeal = function(firstMeal)
{
var twoMeals = [firstMeal, this.lunch];
return this.whatIAte(twoMeals);
}
TodaysFood.prototype.whatIAte = function(twoMeals)
{
return console.log(twoMeals);
}
var app = new TodaysFood("eggs", "sandwich");
app.firstMeal();
Stupid example, but I'm trying to understand how an app should flow. Should I be able to write my whole app in separate, but linked functions, then just kick the whole thing off by instantiating the constructor, and maybe calling one function. Or is the first example more correct -- writing independent functions, then handling the interaction between them after you've instantiate the constructor?
Thanks for any help.
You may want to make it modular, Ala Node.js or within the browser using RequireJS
Here is a slight variation of the second example you could consider, view fiddle
var TodaysFood = function (b, l) {
var self = this;
this.breakfast = b;
this.lunch = l;
this.firstMeal = function () {
console.log(this.breakfast);
return self;
};
this.secondMeal = function () {
console.log(this.lunch);
return self;
}
this.allMeals = function () {
return this.firstMeal().secondMeal();
};
}
var food = new TodaysFood('eggs', 'sandwich');
food.firstMeal().secondMeal().allMeals();
If you plan to use node.js or RequireJS then the above could be modularized by replacing the last two test lines of code with,
module.exports = TodaysFood;
If this is made modular then you would remove the constructor var TodaysFood = function(b, l) { ... and instead accept arguments for b & l within your individual methods like firstMeal & secondMeal. This would make it static and prevent collisions with the constructor values.

JavaScript OOP Models Formula

Working on creating a dirt simply MVC framework for one of my own projects. Rather than using one that is public, I decided to create one since my needs are very unusual.
I've got my structure down for the Controllers and Views, however, I'm having some issues creating my model structure.
This is what I have for my model structure:
model.models = function(args){
init: function(){
this.on_init();
},
on_init: args.on_init || noop,
data: args.data || {},
};
So then, I would call this as a basic formula for all of the models I want to create. For example, I want to create employees, notifications and some other models using this as a basic blueprint, then make some basic adjustments.
I call:
model.employees = new model.models({
on_init: function(){
//something specific
},
data: {
//defaults
}
});
And we're all good up to this point, but here is where I'm having troubles. Now, when I want to create my end result, the model, I cannot create a new object from an object.. it must be a function.
The only thing I can think of is creating a return function for the second method, but that renders some issues in itself. I have done some research looking at other MVC code, but I was unable to wrap my head around it.
Any help would be very much appreciated!
is this what you want ?
model.models = function(args){
var noop = function(){};
var o = {};
var init = args.on_init || noop;
var data = args.data || {};
init();
//handle other initialization
//o.a = xx;
//o.b = xx;
//o.c = data.xxx;
//....
return o;
}
then you can use the new, and it can't appear syntax error
Did a lot of fiddling, came up with this:
var blueprint = function(args){
return {
data: args.data,
on_init: args.on_init,
create: function(args){
this.on_init();
return {
data: this.data,
whatever: function(){
console.log(args);
}
};
}
};
};
var notifs = new blueprint({
on_init: function(){
console.log('init');
},
data: {
test: 'test'
}
});
var res = notifs.create('test');
console.log(blueprint);
console.log(notifs);
console.log(res);
It comes out with a main function that works, the notifs function is customizable for each individual object type, then calling the create method will create the end method.
Boom!

Categories

Resources