var ddoc = {
_id: '_design/app',
language: 'javascript',
views: {},
lists: {},
shows: {},
lib: {/* see below */}
};
I can't find good documentation about what to put into ddoc.lib, eg:
Can I put functions: ddoc.lib.myHelper = function () {}; ?
Can I reference JavaScript files (CommonJS module?): ddoc.lib.math = 'math.js';
In case of 2. where to store math.js?
As far as I know the best solution for today is to use couchapp. It can create a sceleton that could be edited easily.
The best couchapp manager I have seen is http://kan.so/ I would just use this, but ...
To roughly answer your questions.
yes you can put functions in lib, but they must be turned into escaped strings. You want to just put them in like you would a file though not an anonymous function.
yes you can require just structure as
"lib": {
"math.js":"escaped source"
}
Related
I would like to include standard functionality in several views within an Ember app. The functionality includes things like setting the tagName and classNames of the views to be the same and keeping track of a property for each view.
The question in a nutshell: Should I use a mixin or extend a base view?
The expanded question...
Should one extend a base view to do this? For example:
App.BaseView = Em.View.extend({
tagName: 'section',
classNames: ['page_section', 'blue'],
willInsertElement: function() {
// Some functions called here that set properties
},
});
App.PageOneView = App.BaseView.extend({
// View specific stuff here
});
App.PageTwoView = App.BaseView.extend({
// View specific stuff here
});
... Or, should one use a Mixin to extend the functionality? For example:
App.BaseMixin = Em.Mixin.create({
tagName: 'section',
classNames: ['page_section', 'blue'],
willInsertElement: function() {
// Some functions called here that set properties
},
});
App.PageOneView = Em.View.extend(App.BaseMixin, {
// View specific stuff here
});
App.PageTwoView = Em.View.extend(App.BaseMixin, {
// View specific stuff here
});
I understand that views and mixins are both Ember objects, but does using either of them to extend standard functionality to other objects (e.g. views) affects how the objects and prototypes/instances (if they differ from the object) interact and whether properties get set on the instance of the view or the view object?
If the two examples above differ, would setting the properties on the mixin's init function change anything? For example:
App.BaseMixin = Em.Mixin.create({
tagName: null,
classNames: null,
init: function() {
this.set('tagName', 'section');
// And so forth...
},
});
However, if using a mixin and extending a view have the same affect on the views I am trying to add the standard functionality to (that is, they affect the views' objects and prototypes/instances in the same way), do you see an advantage to using one over the other (whether in terms of efficiency, maintainability, etc)?
Great question,
Short and simple, extend the view.
The hooks/bindings are view specific, so the mixin can't be applied to a controller, route etc, and depending on your team makeup, you don't want to give someone an opportunity to mix in code that doesn't belong.
Extending a class in Ember just makes the base class into a mixin and applies it to your class. https://github.com/emberjs/ember.js/blob/v1.2.0/packages/ember-runtime/lib/system/core_object.js#L488
So it's almost the exact same thing, only your base view makes more sense since it only really applies to views.
I'm trying to create a small EmberJS application, but I'm struggling about how to architecture it correctly. I have a main view called "library" which displays on a sidebar a list of folders. User can click on each folder and display the content at the center (while the sidebar is still active).
I therefore have a library resource, and nested resources to display the folders in this specific context:
this.resource('library', function() {
this.resource('libraryFolders', {path: 'folders'}, function() {
this.resource('libraryFolder', {path: ':folder_id'};
}
};
To be able to access the folders in the parent root, I set up a dependency:
App.LibraryController = Ember.Controller.extend({
needs: ["libraryFolders"],
folders: null,
foldersBinding: "controllers.libraryFolders"
});
App.LibraryRoute = Ember.Route.extend({
setupController: function(controller) {
controller.set('controllers.libraryFolders.model', App.Folder.find());
}
});
First question: is this a good way? I feel it a bit strange that a parent controller have a dependency to its children.
Now, another problem arises: what if I want to reuse folders in another context? All the methods I would write in LibraryFoldersController would be specific to this one, not really DRY. What I came up is adding a root "folders" resource, and add the dependency to this one instead:
this.resources('folders');
App.LibraryController = Ember.Controller.extend({
needs: ["Folders"],
folders: null,
foldersBinding: "controllers.folders"
});
App.LibraryRoute = Ember.Route.extend({
setupController: function(controller) {
controller.set('controllers.folders.model', App.Folder.find());
}
});
What do you think? Am I doing it wrong?
IMO it looks good so far. You are using the needs API which is the correct (ember) way to setup dependencies between controllers.
Maybe if you find yourself writing repeating code you could consider creating a Mixin for a more general controller an put there your logic, that should be agnostic to the use cases it handles.
For example defined a mixin:
App.ControllerMixin = Ember.Mixin.create({
// "use case" agnostic logic here
});
You mix mixins into classes by passing them as the first arguments to .extend.
App.LibraryController = Ember.ObjectController.extend(App.ControllerMixin, {
// now you can use here the logic defined in your mixin
// and add custom code as you please
});
Another possibility is to write a super class and then extend from it to inherit common logic:
Snippet taken from the docs:
App.Person = Ember.Object.extend({
helloWorld: function() {
alert("Hi, my name is " + this.get('name'));
}
});
var tom = App.Person.create({
name: 'Tom Dale'
});
tom.helloWorld(); // alerts "Hi, my name is Tom Dale".
One thing worth mentioning (though I think it's simply a typo) is: needs: ["Folders"] should be needs: ["folders"],
Hope it helps.
Is there a way to make this on a single function call?
var todo = function (req, res){};
app.get("/", todo);
app.get("/blabla", todo);
app.get("/blablablabla", todo);
Something like:
app.get("/", "/blabla", "/blablablabla", todo );
I know this is a syntax mess, but just for giving an idea of what I would like to achieve, an array of the routes would be awesome!
Anyone know how to do this?
I came across this question while looking for the same functionality.
#Jonathan Ong mentioned in a comment above that using arrays for paths is deprecated but it is explicitly described in Express 4, and it works in Express 3.x. Here's an example of something to try:
app.get(
['/test', '/alternative', '/barcus*', '/farcus/:farcus/', '/hoop(|la|lapoo|lul)/poo'],
function ( request, response ) {
}
);
From inside the request object, with a path of /hooplul/poo?bandle=froo&bandle=pee&bof=blarg:
"route": {
"keys": [
{
"optional": false,
"name": "farcus"
}
],
"callbacks": [
null
],
"params": [
null,
null,
"lul"
],
"regexp": {},
"path": [
"/test",
"/alternative",
"/barcus*",
"/farcus/:farcus/",
"/hoop(|la|lapoo|lul)/poo"
],
"method": "get"
},
Note what happens with params: It is aware of the capture groups and params in all of the possible paths, whether or not they are used in the current request.
So stacking multiple paths via an array can be done easily, but the side-effects are possibly unpredictable if you're hoping to pick up anything useful from the path that was used by way of params or capture groups. It's probably more useful for redundancy/aliasing, in which case it'll work very well.
Edit: Please also see #c24w's answer below.
Edit 2: This is a moderately popular answer. Please keep in mind that ExpressJS, as with most Node.js libraries, is a moveable feast. While the routing above does still work (I'm using it at the moment, a very handy feature), I cannot vouch for the output of the request object (it's certainly different from what I've described). Please test carefully to ensure you get the desired results.
app.get('/:var(bla|blabla)?', todo)
:var sets the req.param that you don't use. it's only used in this case to set the regex.
(bla|blabla) sets the regex to match, so it matches the strings bla and blablah.
? makes the entire regex optional, so it matches / as well.
You can actually pass in an array of paths, just like you mentioned, and it works great:
var a = ['/', '/blabla', '/blablablabla'];
app.get(a, todo);
Just to elaborate on Kevin's answer, this is from the 4.x docs:
The path for which the middleware function is invoked; can be any of:
A string representing a path.
A path pattern.
A regular expression pattern to match paths.
An array of combinations of any of the above.
They have some examples, including:
This will match paths starting with /abcd, /xyza, /lmn, and /pqr:
app.use(['/abcd', '/xyza', /\/lmn|\/pqr/], function (req, res, next) {
next();
});
I went for a:
['path', 'altPath'].forEach(function(path) {
app.get(path, function(req, res) { etc. });
});
For the sake of argument, say I want to load Zepto by default, but use jQuery instead for IE (all versions).
What would be a sensible way to do this when using Require.js?
There are two approaches: "proper" but long and "sleight of hand" but short.
"Proper" but long:
require.config({
paths: {
jquery:'path/to/jquery'
, zepto: 'path/to/zepto'
}
})
var iNeed = []
if (!('__proto__' in {})) {
// This is IE
iNeed.push('jquery')
} else {
// Everything else
iNeed.push('zepto')
}
require(iNeed, callback)
"Sleight of hand" but short:
var AMDConfig = {
paths: {
jquery:'path/to/zepto'
}
}
if (!('__proto__' in {})) {
// This is IE
AMDConfig.paths.jquery = 'path/to/jquery'
}
require.config(AMDConfig)
require(['jquery'], callback)
The reason the "sleight of hand" is not "proper" is that you are masking the real nature of what stands behind "jquery" As you grow your app, some jQuery plugins may come and not work over zepto, but it will not be immediately clear what the issue is.
The "proper" solution is also a problem in one respect - if you define the requirements array dynamically, the build tool like r.js will not be able to find other dependencies you put there.
Your pick..
I have a requirement to extend the YUI Panel with some custom functionality that will be in a new file and shared across multiple views.
I am at a bit of a loss as to how best to go about this, can anyone give me any pointers please?
Let's say you want to extend a Panel to create one that has a list in its body. I usually use Y.Base.create for this. It's a more declarative way of extending YUI classes than using a constructor and Y.extend. But I'll stay closer to your example in the YUI forums.
There are a couple of tricks dealing with WidgetStdMod (one of the components of Y.Panel), but mostly it's just about using Y.extend and following the YUI inheritance patterns. I'll try to answer with an example:
function MyPanel() {
MyPanel.superclass.constructor.apply(this, arguments);
}
// hack: call it the same so you get the same css class names
// this is good for demos and tests. probably not for real life
MyPanel.NAME = 'panel';
MyPanel.ATTRS = {
listItems: {
// YUI now clones this array, so all's right with the world
value: []
},
bodyContent: {
// we want this so that WidgetStdMod creates the body node
// and we can insert our list inside it
value: ''
}
};
Y.extend(MyPanel, Y.Panel, {
// always a nice idea to keep templates in the prototype
LIST_TEMPLATE: '<ul class="yui3-panel-list"></ul>',
initializer: function (config) {
// you'll probably want to use progressive enhancement here
this._listContainer = Y.Node.create(this.LIST_TEMPLATE);
// initializer is also the place where you'll want to instantiate other
// objects that will live inside the panel
},
renderUI: function () {
// you're inheriting from Panel, so you'll want to keep its rendering logic
// renderUI/bindUI/syncUI don't call the superclass automatically like
// initializer and destructor
MyPanel.superclass.renderUI.call(this);
// Normally we would append stuff to the body in the renderUI method
// Unfortunately, as of 3.5.0 YUI still removes all content from the body
// during renderUI, so we either hack it or do everything in syncUI
// Hacking WidgetStdModNode is doable but I don't have the code around
// and I haven't memorized it
//var body = this.getStdModNode('body');
},
syncUI: function () {
// same here
MyPanel.superclass.syncUI.call(this);
// insert stuff in the body node
var listContainer = this._listContainer.appendTo(this.getStdModNode('body'));
Y.Array.each(this.get('listItems'), function (item) {
listContainer.append('<li>' + item + '</li>');
});
}
});