Require.js and reusable UI functions - javascript

I'm working on a project written using Require.js. There are a number of reused functions that are currently being called from the global scope. These functions involve ui transitions, hide/show, and general on hover events. I want to organize these functions right into require, but not quite sure where/how to include them.
For example let's say in the app there are multiple spots that may call a common function of showDropdown(). And let's say it requires jQuery for the animation. Where or how would be the best place to store the showDropdown function?
Say a simple function like:
function showDropdown(id) {
var thisdropdown = $(id).find('.dropdown');
$(thisdropdown).slideDown();
}
I could create a UI folder, with the different js functions all being their own file. Then simply require them on any other files that are dependent on them. But regardless, those files will need to export their function to the global scope to be accessible correct?
I feel there is an obvious answer/setup as this must be fairly common item.
In addition, I am writing this in a backbone app, but I don't believe that has any direct impact, more of a require.js question.

Create a util library or something like that:
// util.js
define({
showDropdown: function(id) {
var thisdropdown = $(id).find('.dropdown');
thisdropdown.slideDown();
}
});
Then use it elsewhere:
require(['util'], function(util) {
util.showDropdown('my-id');
});

Related

Load requirejs module with data-bind (knockout.js)?

What I want to do is load js using the data-bind attribute. I am fairly new to requirejs and knockout and I'm not sure how to go out this.
Right now I have my js split into different require modules for each type of component I have. For example, I have a file that deals with the header dropdown (header.js):
define('headerDropdown',['jquery', 'bootstrap']),function(jquery, bootstrap){
var $menu = $(".menu");
var $dropdown = $menu.find("ul");
$menu.on("click", function () {
$dropdown.toggle("fast");
});
};
What I want to do is:
<div class="header" data-bind="headerDropdown">...</div>
And load the respective js.
Most of my js modules are UI changes based on clicks (show and hiding stuff on click) but I only want the js to load is the html block is on the page.
Hopefully this makes sense!
How can I do this using requirejs and knockout?
Looks like you are mixing concepts. First let's see the define() definition (suppose the file is headerDropdown.js):
define('headerDropdown',['jquery', 'bootstrap']),function(jquery, bootstrap){
var $menu = $(".menu");
var $dropdown = $menu.find("ul");
$menu.on("click", function () {
$dropdown.toggle("fast");
});
};
Require.js does not recommend to define a module expliciting their name ('headerDropdown'); you can get the name based on the filename. That's because require has a tool for optimization of the javascript in production: you can concatenate and minimize the output JS. The optimizer uses the filename to define the module name. Please, avoid defining with name.
If you look at the code, you are requiring ['jquery'] but inside the module definition you're using the global jQuery variable. That's OK because jQuery define their module as a global variable, but the convention is to receive in the function the jquery reference:
define('headerDropdown',['jquery', 'bootstrap']),function($, bootstrap)
You are defining a module that manipulates DOM directly, which goes against the DOM update procedure of knockout. In your case, you are using a data-bing="headerDropwodn" so the headerDropdown is a bindingHandler rather than a simple module. Please check: http://knockoutjs.com/documentation/custom-bindings.html
You can load on require as you pointed on the question. You just need to change your codes:
Load in your HTML an app.js script (for example). This app.js requires knockout and your headerDropdown bindingHandler. In the function declaration you define the ko.applyBindings and that's all.
Greetings!

How do I get my helper functions to load first? (Meteor, Node framework)

In my Meteor projects I have several helper functions of the sort
helpers.js
var tagStr = function () { return this.tags.join(', '); };
articles.js
Template.articles.tags = tagStr;
listing.js
Template.listing.tags = tagStr;
Now, I can define the function in either articles.js or listing.js, and it won't work in the other one. Or i can define it in helpers.js and it will work in neither..
So, how would I go about loading my helper functions before the rest of the scripts? Preferably in "the right way".
Thanks!
i think what you are looking for is a globally available handlebars helper - i keep mine in client/lib/handlebars.js - the contents of the 'lib' folder will get loaded first
define each helper like so:
Handlebars.registerHelper("joinArray", function(array) {
if(array)
return array.join(', ');
});
you would then use this in any template html file like so:
{{joinArray tags}}
you can read more about handlebars helpers here handlebarsjs.com/block_helpers.html
this is the 'right' way IMO, but if you want to use normal javascript functions and not handlebars helpers, that works also
you'll need to place the commonly used javascript function in a file like client/lib/helpers.js and do NOT use the 'var' declaration prefix
like so:
thisIsAGloballyAvailableFunction = function(){...};
not like:
var thisFunctionIsOnlyAvailableInThisFile = function(){...};
meteor does a slightly strange thing to control scoping. anything with 'var' is local to the scope of the file it occurs in, anything declared without 'var' is globally available across the app
The answer by nate-strauser was correct and helped me find the right solution but now (Meteor 1.0) Handlebars.registerhelper() is deprecated.
Now it works this way (if anyone is still interested):
Template.registerHelper()
The rest as explained by nate-strauser.

Cleaning up a large piece of Javascript code

I am writing an application in Titanium for Android. I have a lot of code in a single JS file. I would like to know if there is any function like php's include to break the code into multiple files and then just include them.
Thanks
Use the CommonJS / RequireJS approach, specifically the require command. This is the (strongly) recommended way for dealing with large systems in Titanium, and is well documented on their website, along with many best practices for dealing with JavaScript modularization specific to Titanium. Here is the documentation from Titanium on this.
For example, to create a module that encapsulates a 'view' of some kind, put it in a file named MyCustomView.js with this content:
// MyCustomView.js
function MyCustomView(message) {
var self = Ti.UI.createView({
backgroundColor : 'red'
});
var label = Ti.UI.createLabel({
text : message,
top : 15,
.... // Other initialization
});
// ... Other initialization for your custom view, event listeners etc.
return self;
}
module.exports = MyCustomView;
Now you can easily use this module in another class, lets assume you put this in your /Resources folder, lets load the module inside app.js and add it to the main window.
// app.js
var MyCustomView = require('MyCustomView');
var myView = new MyCustomView('A message!');
Titanium.UI.currentWindow.add(myView);
You can use this approach to make custom views, libraries of reusable code, and anything else you would like. Another common thing would be to have a Utility class that has many different helper functions:
// Utility.js
exports.cleanString = function(string) {
// Replace evil characters
var ret = string.replace(/[|&;$%#"<>()+,]/g, "");
// replace double single quotes
return ret.replace(/"/g, "''");
}
This method can be easily used like this:
// app.js
var Utility = require('Utility.js');
Ti.API.info(Utility.cleanString('He##o W&orld$'));
Another common method I use it for is to implement the Singleton pattern as each module loaded is its own functional context, so if you like, you can have values that persist:
// ManagerSingleton.js
var SpriteManager = {
count : 0
};
exports.addSprite = function() {
SpriteManager.count++;
}
exports.removeSprite = function() {
SpriteManager.count--;
}
You would load and use this much the same way as Utility:
// app.js
var ManagerSingleton = require('ManagerSingleton');
ManagerSingleton.addSprite();
This is something of a more elegant solution instead of using global variables. These methods are by no means perfect, but they have saved me a lot of time and frustration, and added depth, elegance, and readability to my Titanium code for Apps of all sizes and types.
There are two dominant module systems in the Javascript world.
One is the CommonJS and the second is AMD. There is a lot of discussion about which one is best and for what purpose. CommonJS is more widely used for server side JS while AMD is used mostly for browser JS.
RequireJS (requirejs.org) seems to be the most popular AMD system.
For information on JS module systems please read here: http://addyosmani.com/writing-modular-js/

Use of prototype for single instance functions in JavaScript

For performance optimization I'm using a single JavaScript file to handle all the pages of the website I'm working on.
The basic structure I'm using is as followed:
(function($) {
// Shared functions ...
// A function for every page
function Page1() {
}
Page1.prototype = {
init: function() {
//...
},
//more functions
};
// more pages
$(document).ready(function() {
if ($('#page1uniqueidentifier').length) {
var page1 = new Page1();
page1.init();
}
// more pages
}
}) (jQuery);
I'm not an experienced JavaScript programmer so I've been searching a lot about best practices and different ways of structuring my code and I've ended up choosing this one but I'm not really sure about it and I have a few questions:
Is it worth it to use prototype if I'm never gonna have more than a single instance of a page? I think I understand how prototype works and that I'm not gaining any performance there. But I'm using it just as a best practice because in the case different instances would exist, these functions would be the same in every instance.
Is there a better way to structure the code?
Should I put the call of the init function inside the constructor and then only call new Page1()?
function Page1() {
this.init();
}
if ($('#page1uniqueidentifier').length) {
new Page1();
}
For performance optimization I'm using a single JavaScript file to
handle all the pages of the website I'm working on
That makes no sense. You should separate code into files, and then run all your js files thru a minimizer/concatenator to package it up.
Anyway, to answer your questions,
if you are only going to have 1, then prototype won't buy you anything. However, if you are going to use more than 1, would you go back and change it? Plus, using prototype wont hurt you either, so you might as well do it for learning.
You should create the files that make sense according to the functionality implemented. I would separate your object definition into its own file, for example, so when you look at that file, all you see is the code for that object.
If you have a constructor function, you don't really need init, do you?

JavaScript structure, right way?

Iam trying to get better in javascript coding. Away from 1000 lines of code in one file. But iam not sure if this is the "right" way:
RequireJS to load files when needed inside "boot.js":
require([
"library/jquery.form/jquery.form",
"app/eventManager",
"app/myapp"
], function() {
$(function() {
MyApp.init();
});
});
MyApp.js
var MyApp = {
init: function() {
MyApp.mainController();
},
// this is our controller, only load stuff needed..
mainController: function() {
//controller = set from php/zendframework
switch (controller) {
case 'admin':
MyApp.initAdmin();
break;
default:
break;
}
},
// action for admin controller
initAdmin: function() {
//lazy load
require(["app/admin/admin"], function(){
MyApp.admin.init();
});
}};
MyApp.admin.js
MyApp.admin = {
init : function() {
if (permisson != 'admin') {
console.log('Permission denied.');
return false;
}
MyApp.admin.dashboard.init();
}
};
MyApp.admin.dashboard = {
init: function() {
MyApp.admin.dashboard.connectEventHandlers();
MyApp.admin.dashboard.connectEvents();
MyApp.admin.dashboard.getUserList('#admin-user-list');
},
connectEvents: function () {
EventManager.subscribe("doClearCache", function() {
MyApp.admin.dashboard.doClearCache(url);
});
EventManager.subscribe("doDeleteUser", function() {
MyApp.admin.dashboard.doDeleteUser(url);
});
},
What other "styles" are common? or this a goodway to structure code? THere a lot of examples in the net, but i was not able to find "real life" code..
And one of biggest "problems" when does i need ".prototype" ?
JavaScript Patterns is a good reference for various ways of structuring code.
It would also be a good idea to study the source code of libraries such as jQuery.
One change I would make to your code is to avoid repeating 'event' strings everywhere.
You could reduce this by doing something like:
var app = {
events : {
someEvent : "someEvent"
}
}
EventManager.subscribe(app.events.someEvent, someFn);
EventManager.publish(app.events.someEvent);
I would also avoid calling console.log directly and use a wrapper such as this which provides a fallback if not console is available
N.B Angus Croll has a decent blog where he mentions js structure/namespacing etc
and there is some really good knowledge being shared over at JsMentors from well versed js ninjas
I defer to Douglass Crockford on all matters pertaining to JavaScript best practices.
Here is his homepage: http://javascript.crockford.com/.
Here is a great book on what to do and what not to do in JavaScript. http://www.amazon.com/exec/obidos/ASIN/0596517742/wrrrldwideweb
Here is his amazing tool which can automatically tell you if you are employing any worst practices. http://www.jslint.com/
As to the prototype question, you use prototype when you want to employ prototypal inheritance, or create a "static" class function which will be present for all instances of that class without consuming memory for each instance.
Require.js is great tool, you can use it also on the client side. But be careful when you use it on mobile. In such case you should either use the editor to navigate better in one file or use thing like sprocket. It is a "precompiler", does not put any additional library to your code.
I passed through your sliced up code. Probably you should define the different parts as modules, read the requirejs documentation for defining modules, it gives good assistance.
But think twice whether you really need for organizing your code an extra library.
In case you are building something more complex, for example with multiple product modules and sub modules, I recommend creating a context hierachy for your modules. Also make the UI components to be self-contained so that you have templates, css, logic, assets, localization etc for a particular UI component in a single place.
If you need to refer a reference architecture for large scale js development see http://boilerplatejs.org. I'm the main author of it and it demonstrates a lot of patterns that are useful in complex product development.

Categories