JavaScript Scope of Vaadin's "AbstractJavaScriptComponent" - javascript

I have integrated some HTML/JS Code into my Vaadin WebApplication by creating an AbstractJavaScriptComponent. The Component almost works as intended.
How do I call the passInfo() method defined in the "connector.js" without having to manually click the Button defined in the innerHTML of the "chessControll.JsLabel" Component in "chessControll.js". My Goal is to pass Information, when the onChange Event of the init() function is called, which is located in the same file "chessControll.js", but not part of the Component.
I have already tried to create a Custom Event and then dispatch it whenever onChange() in the init() function is called, it worked as long as I didn't listen for the Event inside of my Component (chessControll.js, chessControll.JsLabel). It seems it can only be accessed in a static way.
How can I access the chessControll.JsLabel in "chessControll.js" from the init() function and then dispatch the button click or listen for events inside the component to achieve the same?
connector.js:
com_*myname*_*applicationName*_JsLabel = function() {
var mycomponent = new chessControll.JsLabel(this.getElement());
connector = this;
this.onStateChange = function() {
mycomponent = this.getState().boolState;
};
mycomponent.click = function() {
connector.passInfo(true);
};
};
chessControll.js:
var chessControll = chessControll || {};
chessControll.JsLabel = function (element) {
element.innerHTML =
"<input type='button' value='Click'/>";
// Getter and setter for the value property
this.getValue = function () {
return element.
getElementsByTagName("input")[0].value;
};
var button = element.getElementsByTagName("input")[0];
var self = this;
button.onclick = function () {
self.click();
};
};
var init = function() {
var onChange = function() {
/*Click Button defined in JsLabel Component */
};
};$(document).ready(init);

I figured out what the problem was.
The architecture of Java Web Applications doesn't allow a simple communication like i did in my example. The JavaScript made a call from the Client Side to the Server Side Vaadin Component.
I integrated the whole JavaScript, including the init function, as a Component. This way i can call the method from the init function because everything is known on the Server Side.
edited chessControll.js :
var chessControll = chessControll || {};
chessControll.JsLabel = function (element) {
element.innerHTML =
"<input type='button' value='Click'/>";
// Getter and setter for the value property
this.getValue = function () {
return element.
getElementsByTagName("input")[0].value;
};
var button = element.getElementsByTagName("input")[0];
var self = this;
//deleted bracket here
var init = function() {
var onChange = function() {
self.click();
};
};$(document).ready(init);
} //<-- that Simple

Related

Basic ES6 Javascript Plugin - reuse variable between functions

I'm attempting to build a basic JS plugin that can be called after a click event to disable a button (to prevent users firing multiple API calls) and to give feedback that something is loading/happening. Here is how it looks:
This works great on an individual basis, but I want to re-write it as a plugin so I can reuse it across the site.
Here is a cut down version of the JS from file loader.plugin.js.
let originalBtnText;
export function showBtnLoader(btn, loadingText) {
const clickedBtn = btn;
const spinner = document.createElement('div');
spinner.classList.add('spin-loader');
originalBtnText = clickedBtn.textContent;
clickedBtn.textContent = loadingText;
clickedBtn.appendChild(spinner);
clickedBtn.setAttribute('disabled', true);
clickedBtn.classList.add('loading');
return this;
}
export function hideBtnLoader(btn) {
const clickedBtn = btn.target;
clickedBtn.textContent = originalBtnText;
clickedBtn.removeAttribute('disabled');
clickedBtn.classList.remove('loading');
return this;
}
export function btnLoader() {
showBtnLoader();
hideBtnLoader();
}
And here is an example of how I would like to use it.
import btnLoader from 'loaderPlugin';
const signupBtn = document.getElementById('signup-btn');
signupBtn.addEventListener('click', function(e) {
e.preventDefault();
btnLoader.showBtnLoader(signupBtn, 'Validating');
// Call API here
});
// Following API response
hideBtnLoader(signupBtn);
The issue I have is that I want to store the originalBtnText from the showBtnLoader function and then use that variable in the hideBtnLoader function. I could of course achieve this in a different way (such as adding the value as a data attribute and grabbing it later) but I wondered if there is a simple way.
Another issue I have is that I don't know the correct way of calling each individual function and whether I am importing it correctly. I have tried the following.
btnLoader.showBtnLoader(signupBtn, 'Validating');
btnLoader(showBtnLoader(signupBtn, 'Validating'));
showBtnLoader(signupBtn, 'Validating');
But I get the following error:
Uncaught ReferenceError: showBtnLoader is not defined
at HTMLButtonElement.<anonymous>
I have read some good articles and SO answers such as http://2ality.com/2014/09/es6-modules-final.html and ES6 export default with multiple functions referring to each other but I'm slightly confused as to the 'correct' way of doing this to make it reusable.
Any pointers would be much appreciated.
I would export a function that creates an object with both show and hide functions, like this:
export default function(btn, loadingText) {
function show() {
const clickedBtn = btn;
const spinner = document.createElement('div');
spinner.classList.add('spin-loader');
originalBtnText = clickedBtn.textContent;
clickedBtn.textContent = loadingText;
clickedBtn.appendChild(spinner);
clickedBtn.setAttribute('disabled', true);
clickedBtn.classList.add('loading');
}
function hide() {
const clickedBtn = btn.target;
clickedBtn.textContent = originalBtnText;
clickedBtn.removeAttribute('disabled');
clickedBtn.classList.remove('loading');
}
return {
show,
hide,
};
}
Then, to use it:
import btnLoader from 'btnloader';
const signupBtn = document.getElementById('signup-btn');
const signupLoader = btnLoader( signupBtn, 'Validating' );
signupBtn.addEventListener('click', function(e) {
e.preventDefault();
signupLoader.show();
// Call API here
});
// Following API response
signupLoader.hide();
If you need to hide it from a different file from where you showed it, then you can export the instance:
export const signupLoader = btnLoader( signupBtn, 'Validating' );
And later import it.
import { signupLoader } from 'signupform';
function handleApi() {
signupLoader.hide();
}
Youre maybe overriding the Element.prototype, to make it accessible right from that element. However, i wouldnt set values onto that element, i would rather return an object with all the neccessary stuff:
export function implementBtnLoader(){
Element.prototype.showBtnLoader=function( loadingText) {
const clickedBtn = this;
const spinner = document.createElement('div');
spinner.classList.add('spin-loader');
var originalBtnText = clickedBtn.textContent;
clickedBtn.textContent = loadingText;
clickedBtn.appendChild(spinner);
clickedBtn.setAttribute('disabled', true);
clickedBtn.classList.add('loading');
return {
text:originalBtnText,
el:this,
hideBtnLoader: function() {
const clickedBtn = this.target;
clickedBtn.textContent = this.text;
clickedBtn.removeAttribute('disabled');
clickedBtn.classList.remove('loading');
return this;
}
};
};
}
export function btnLoader() {
implementBtnLoader();
}
When imported, and implementBtnLoader was called, one can do:
var loader=document.getElementById("test").showBtnLoader();
console.log(loader.text);
loader.hideBtnLoader();

Calling events in modular JavaScript

I'm only learning how to work with the modules in JavaScript, so I have three separate .js files: main, listener and fileHandler
Simply this is a program that for every selected or dropped file(image) from computer gets appended to the page. Functions are working when I drag and drop files to the page, but when I select them through inputBox button files even files are stored in inputBox.files, they are not getting appended to the page.
var uploader = {};
uploader.init = function () {
this.inputBox = document.getElementById('uploadButton');
this.dropbox = document.getElementById('dropbox');
this.listener();
}
and listener method as:
probably I'm calling 'change' event wrongly here, that files are not appended.
uploader.listener = function () {
uploader.inputBox.addEventListener('change', uploader.fileHandler.addFiles(uploader.inputBox.files));
this.dropbox.addEventListener('drop', this.fileHandler.drop.bind(this));
}
one another constructor is:
uploader.fileHandler = new function () {
var uploadHandler = function () {...}
this.addFiles = function (files) {
Object.keys(files).forEach(function (key) {
var file = files[key];
uploadHandler(files[key]);
});
};
this.drop = function (event) {
event.stopPropagation();
event.preventDefault();
var files = event.dataTransfer.files;
this.fileHandler.addFiles(files);
};
}
EDIT
I see another issue. When you do this:
uploader.inputBox.addEventListener('change', uploader.fileHandler.addFiles(uploader.inputBox.files));
You are calling uploader.fileHandler.addFiles(uploader.inputBox.files) immediately and passing it's return value to .addEventListener(). Probably what you want instead is this:
uploader.inputBox.addEventListener('change', function() {
uploader.fileHandler.addFiles(uploader.inputBox.files)
});
Here you are passing an anonymous function reference which can be called later by the event handler.
This construct:
uploader.fileHandler = new function () {
this.addFiles = function (files) {
Object.keys(files).forEach(function (key) {
var file = files[key];
uploadHandler(files[key]);
});
};
}
only assigns a function to uploader.fileHandler. It does not define uploader.fileHandler.addFiles until you actually call that function (which you do not show).
I don't know why you're trying to nest your function definitions (that usually just causes more complexity than benefit in Javascript), but if you really wanted to define them that way, you could do this:
uploader.fileHandler = {
addFiles: function (files) {
Object.keys(files).forEach(function (key) {
var file = files[key];
uploadHandler(files[key]);
});
},
drop: function(...) {...}
};
This would then define both of these functions:
uploader.fileHandler.addFiles()
uploader.fileHandler.drop()

Reflux actions global debugging

Is there a way how to globally console.log() all the fired actions in Reflux? Ideally prints theirs parameters at the same time.
Like Cory Danielson said, Reflux uses EventEmitter. And you can insert your own EventEmitter-implementation like this:
Reflux.setEventEmitter(require('events').EventEmitter);
So you want to inject an EventEmitter constructor there that has debugging enabled, something like this:
var EventEmitter = require('events').EventEmitter;
function DebugEventEmitter() {
var realEmitter = new EventEmitter();
var origEmit = realEmitter.emit;
realEmitter.emit = function () {
console.log('emitting', arguments);
return origEmit.apply(realEmitter, arguments);
};
return realEmitter;
}
Reflux.setEventEmitter(DebugEventEmitter);
This only hijacks the emit method which is used to emit events, but you can of course hijack any other method on EventEmitter and add logging.
EDIT
Since Reflux doesn't pass the action name to the emitted event, here's another solution which is way more hackish, but it should work for debugging purposes.
var Reflux = require('reflux');
// Do this before any code is calling Reflux
var origCreateAction = Reflux.createAction;
Reflux.createAction = function () {
var action = origCreateAction.apply(Reflux, arguments);
var wrapper = function () {
console.log(action.actionName, 'called with args: ', arguments);
return action.apply(action, arguments);
};
for (var key in action) {
wrapper[key] = action[key];
}
return wrapper;
};
// Example using actions and triggering them, which logs
// with our wrapper
var Actions = Reflux.createActions([
'statusUpdate',
'statusEdited',
'statusAdded'
]);
Actions.statusUpdate.listen(function () {
console.log('status update called');
});
Actions.statusUpdate({test: 1});

Referencing another function in array of functions

I'm using require.js and have a library of functions I use in multiple places. I define the functions thusly:
define(function (require) {
"use strict";
var $ = require('jquery');
var UsefulFuncs = {};
UsefulFuncs.hideAlert = function() {
$('.alert').hide();
};
UsefulFuncs.loadURL = function (url){
navigator.app.loadUrl(url, { openExternal:true });
return false;
};
UsefulFuncs.linkClicked = function (e) {
e.preventDefault();
var url = $(e.currentTarget).attr("rel");
this.loadURL(url);
};
return UsefulFuncs;
});
Then, in my backbone view, I call a function from the library with:
UsefulFuncs = require('app/utils/useful_func'),
....
UsefulFuncs.linkClicked
This works fine for any standalone function in the library e.g. hideAlert(). However when one function in the library refers to another, such as linkClicked() calling loadURL(), I get an error:
Uncaught TypeError: Object [object Object] has no method 'loadURL'.
Any ideas how I can reference loadUrl()?
I would assume you set UsefulFuncs.linkClicked as a handler for an event.
If you were to use it like this:
UsefulFuncs.linkClicked()
, this inside the function would refer to UsefulFuncs, so this.loadURL() would be valid.
However, since you set it as a handler for an event, it can be called in other ways, and this is set to some other object (probably the element which triggered the event). To avoid the event handling mechanism changing your this, you can bind the function when you assign it:
element.onclick = UsefulFuncs.linkClicked.bind(UsefulFuncs);
Another way to go around it is to avoid using this in the handler, like so:
UsefulFuncs.linkClicked = function (e) {
e.preventDefault();
var url = $(e.currentTarget).attr("rel");
UsefulFuncs.loadURL(url);
};
This creates a closure over UsefulFuncs (the first method does as well, but it's more standardized).
Try something like this:
define(function (require) {
"use strict";
var $ = require('jquery');
var hideAlert = function() {
$('.alert').hide();
};
var loadURL = function (url){
navigator.app.loadUrl(url, { openExternal:true });
return false;
};
var linkClicked = function (e) {
e.preventDefault();
var url = $(e.currentTarget).attr("rel");
loadURL(url);
};
return {
hideAlert : hideAlert,
loadURL : loadURL,
linkClicked : linkClicked
};
});

"Hello World" in MVC Pattern

In an interview for some company, I was asked this question.
What design patterns do you know...then I was told to write simplest "hello world" application based on MVC Design Pattern.
I came up with a JavaScript program
var arr = ["a","b","c","d"]; // this is an array, same as store or model
alert(arr[0]); // this is controller
//and browser alert is a view.
later I was told that alert is a view. The basic concept about MVC I know is any changes in Model are reported to View. And there is a controller in between to call the methods.
Can you correct my approach, or come up with an alternate solution for hello world MVC application. Also explain subtle aspects of MVC.
Thanks.
var M = {}, V = {}, C = {};
M.data = "hello world";
V.render = function (M) { alert(M.data); }
C.handleOnload = function () { V.render(M); }
window.onload = C.handleOnLoad;
Controller (C) listens on some kind of interaction/event stream. In this case it's the page's loading event.
Model (M) is an abstraction of a data source.
View (V) knows how to render data from the Model.
The Controller tells to View to do something with something from the Model.
In this example
the View knows nothing about the Model apart from it implements some interface
the Model knows nothing of the View and the Controller
the Controller knows about both the Model and the View and tells the View to go do something with the data from the Model.
Note the above example is a severe simplification for demonstrating purposes. For real "hello world" examples in the JS MVC world go take a look at todoMVC
Better Example
var M = {}, V = {}, C = {};
/* Model View Controller Pattern with Form Example */
/* Controller Handles the Events */
M = {
data: {
userName : "Dummy Guy",
userNumber : "000000000"
},
setData : function(d){
this.data.userName = d.userName;
this.data.userNumber = d.userNumber;
},
getData : function(){
return data;
}
}
V = {
userName : document.querySelector("#inputUserName"),
userNumber : document.querySelector("#inputUserNumber"),
update: function(M){
this.userName.value = M.data.userName;
this.userNumber.value = M.data.userNumber;
}
}
C = {
model: M,
view: V,
handler: function(){
this.view.update(this.model);
}
}
document.querySelector(".submitBtn").addEventListener("click", function(){
C.handler.call(C);
});
/* Model Handles the Data */
/* View Handles the Display */
MVC Architecture
I have written an article about MVC architecture. Here is only some code present,hope anyone finds it helpful.
//Modal
var modal = { data: "This is data"};
//View
var view = { display : function () {
console.log ("////////////////////////////");
console.log ( modal.data);
console.log ("////////////////////////////");
}
};
//Controller
var controller = ( function () {
view.display();
})();
From the above example just understand that there are three different units in this design where each has a specific job to perform. Let's build the MVC design from the above infra structure .There can be more than one view and Observer, here only another view is created first.
// Modal
var modal = { data: "This is data"};
// View
var slashView = { display : function () {
console.log ("////////////////////////////");
console.log ( modal.data);
console.log ("////////////////////////////");
}
};
var starView = { display : function () {
console.log ("****************************");
console.log ( modal.data);
console.log ("****************************");
}
};
// Controller
var controller = ( function () {
slashView.display();
starView.display();
})();
What is understood here is that the modal must not be dependent upon either the view or viewers or the operations performed on the data. The data modal can stand alone but the view and controller are required because one needs to show the data and the other needs to manipulate it. Thus view and controller are created because of the modal and not the other way round.
//Modal
var modal = {
data : ["JS in object based language"," JS implements prototypal inheritance"]
};
// View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("***********************************");
console.log(this.modal.data[0]);
console.log("***********************************");
};
}
function Controller(v){
this.view = v;
this.informView = function(){
// update the modal
this.view.display();
};
}
// Test
var consoleView = new View(modal);
var controller = new Controller(consoleView);
controller.informView();
From the above it can be seen that there has been a link established between view and the controller. And this is one of the requirement of MVC pattern. To demonstrate the change in the modal let's change the program and observe that change in the state of modal is done independently and reflects in view.
//Modal
function Modal(){
this.state = 0;
this.data = ["JS is object based language","JS implements prototypal inheritance"];
//
this.getState = function (){
return this.state;
};
this.changeState = function (value) {
this.state = value;
};
}
// View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("***********************************");
console.log(this.modal.data[modal.getState()]);
console.log("***********************************");
};
}
//controller is created with the view
function Controller(v){
this.view = v;
this.updateView = function(){
// update the view
this.view.display();
};
}
// Test
var modal = new Modal();
var consoleView = new View(modal);
var controller = new Controller(consoleView);
controller.updateView();
// change the state of the modal
modal.changeState(1);
controller.updateView();
When the state of the modal is changed the controller has sent the message to the view to update itself. It is fine, but still one main concept is left to be implemented and that is the observer or controller needs to be identified by the modal . In order to see this happening, there has to be a link between modal and the controller so that any number of controller can show the interest in the modal, this is considered as registering the observer to the modal. This relation ship is implemented using the concept that observer does not exist in the air. Its existence come because of having interest in the modal thus when it is created it has to be created using the modal that it needs to show interest or in other words it has an access to the modal. Let's look at the example below and see how this MVC design pattern is achieved simply and elegantly using JavaScript.
function Modal(){
var stateChanged = false;
var state = 0;
var listeners = [];
var data = ["JS is object based language","JS implements prototypal inheritance"];
// To access the data
this.getData = function(){
return data;
};
// To get the current state
this.getState = function (){
return state;
};
// For simplicity sake we have added this helper function here to show
// what happens when the state of the data is changed
this.changeState = function (value) {
state = value;
stateChanged = true;
notifyAllObservers();
};
// All interested parties get notified of change
function notifyAllObservers (){
var i;
for(i = 0; i < listeners.length; i++){
listeners[i].notify();
}
};
// All interested parties are stored in an array of list
this.addObserver = function (listener){
listeners.push(listener);
};
}
// View class, View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("***********************************");
var data = this.modal.getData();
console.log(data[modal.getState()]);
console.log("***********************************");
};
}
// Controller or Observer class has access to both modal and a view
function Controller(m,v){
this.view = v;
this.modal = m;
this.modal.addObserver(this);
// update view
this.updateView = function(){
this.view.display();
};
// Receives notification from the modal
this.notify = function(){
// state has changed
this.updateView();
};
}
// Test
var modal = new Modal();
var consoleView = new View(modal);
var controller = new Controller(modal,consoleView);
// change the state of the modal
modal.changeState(1);
modal.changeState(0);
modal.changeState(1);
modal.changeState(0);
From the above it can be seen that the observer has register itself using modal addObsever function and establishes a link to the modal. Once all instances are created. Modal state was changed manually to show the effect in the view. Typically in GUI environment, the change is usually done either with a user pressing any button or from any other external input. We can simulate the external input from the random generator and observe the effect. Here in the example below, some more elements are added in the data to show the effect clearly.
function Modal(){
var stateChanged = false;
var state = 0;
var listeners = [];
var data = [
"JS is object based language","JS implements prototypal inheritance",
"JS has many functional language features", "JS is loosely typed language",
"JS still dominates the Web", "JS is getting matured ","JS shares code
through prototypal inheritance","JS has many useful libraries like JQuery",
"JS is now known as ECMAScript","JS is said to rule the future of Web for
many years"];
//
this.getData = function(){
return data;
};
//
this.getState = function (){
return state;
};
this.changeState = function (value) {
state = value;
stateChanged = true;
notifyAllObservers();
};
function notifyAllObservers (){
var i;
for(i = 0; i < listeners.length; i++){
listeners[i].notify();
}
}
this.addObserver = function (listner){
listeners.push(listner);
};
}
// View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("****************************************************");
var data = this.modal.getData();
console.log(data[modal.getState()]);
};
//Adding external simulation of user sending input
this.pressButton = function(){
var seed = 10;
var number = Math.round(Math.random() * seed) ;
// change the state of modal
this.modal.changeState(number);
};
}
// Controller class needs modal and view to communicate
function Controller(m,v){
this.view = v;
//console.log(this.view.display);
this.modal = m;
this.modal.addObserver(this);
this.updateView = function(){
// update the view
//console.log(this.view);
this.view.display();
};
this.notify = function(){
// state has changed
this.updateView();
};
}
// Test
var modal = new Modal();
var consoleView = new View(modal);
var controller = new Controller(modal,consoleView);
// change the state of the modal
for ( var i = 0 ; i < 10; i++){
consoleView.pressButton();
}
The above example demonstrates the use of MVC frame work where a modal is kept independent of the view and and the controller. The modal representing the data is responsible of notifying all the interested parties that has shown the interest and registered themselves with the modal. As soon as any change happens notification is send to the parties and action is left upon them. The example below is slightly different from the above where only newly added data is shown by the observer.
function Modal(){
var stateChanged = false;
var listeners = [];
var data = ["JS is object based language"];
// To retrieve the data
this.getData = function(){
return data;
};
// To change the data by any action
this.modifyData = function (string) {
( data.length === 1 )? data.push(string): data.unshift(string);
stateChanged = true;
notifyAllObservers();
};
// Notifies all observers
function notifyAllObservers (){
var i;
for(i = 0; i < listeners.length; i++){
listeners[i].notify();
}
}
// Requires to register all observers
this.addObserver = function (listener){
listeners.push(listener);
};
}
// View is created with modal
function View(m) {
this.modal = m;
this.display = function () {
console.log("****************************************************");
var data = this.modal.getData();
console.log(data[0]);
console.log("****************************************************");
};
//Adding external simulation of user sending input
this.pressButton = function(string){
// change the state of modal
this.modal.modifyData(string);
};
}
// View class
function Controller(m,v){
this.view = v;
this.modal = m;
this.modal.addObserver(this);
// Updates the view
this.updateView = function(){
this.view.display();
};
// When notifies by the modal send the request of update
this.notify = function(){
// state has changed
this.updateView();
};
}
// Test
var modal = new Modal();
var consoleView = new View(modal);
var controller = new Controller(modal,consoleView);
consoleView.pressButton();
consoleView.pressButton("JS dominates the web world");
consoleView.pressButton("JQuery is a useful library of JS");
The last thing which one may like to add is to delete the observer when not needed.This can be done through adding a method called removeObserver(object) in the modal calls. The above MVC design pattern can be more refined by using subcalssing and having common function present in the top class making the design as simple as possible but it is left on some other article. Hope it helps.
MVC is a design pattern that should be used to structure your application. MVC stands for Model, View, Control. It basically sais that you should separate your business-logic (Model) from your User Interface (View) and your Control-Logic.
For example:
You have a user class, that loads users from the database, can save em. This is your model.
You have a Controller that uses the User class to log a user in.
After the controller is done, it displays a Template containing the Text "Welcome $username".
Also, the Model should not know about the View and the Controller, the View should not know about the Controller, whereas the Controller knows about the Model and the View.
Wikipedia on MVC: http://de.wikipedia.org/wiki/Model_View_Controller
I think you're kind of missing the point here.
MVC is a pattern you'd use for designing an application. I think at the minimum you'd expect to be able to change the model, and see the change reflected in the view.
You'd typically have an object to represent the model, a different object to represent the "view" (which would probably mediate between the model and the HTML objects that you're using as the view) and a controller, which would take inputs from your HTML objects and update the model.
So you change an edit field, the edit field tells the controller, the controller updates the model, the model fires events that the controller uses to update any other view components that depend on this data.
It'd be a few more lines to implement a "hello world" version, but I think this is what I'd be looking for from an interview question like this.
So I made a simple example MVC with data output at console.log().
let model = {
data: {
text: "Hello World",
},
};
let view = {
init: function () {
this.render();
},
render: function () {
console.log(model.data.text);
},
};
let controller = {
init: function () {
view.init();
},
};
controller.init();

Categories

Resources