|
angular.module('pixinote') |
|
|
|
/* Notes/Deliberations |
|
* |
|
* ? wrap view contents in an element with a class of the same name, so that we can... |
|
* ? scope all view styles to the view class? (gulp would modify the view scss file directly to wrap all rules) |
|
* |
|
* */ |
|
|
|
.directive('pxView', ['$compile', function($compile){ |
|
/* <div px-view="myView"></div> where scope.myView = 'login' |
|
* |
|
* results in |
|
* |
|
* <div px-view="myView"> |
|
* <px-login></px-login> |
|
* </div> |
|
* |
|
* Currently, does not support transference of attributes. |
|
*/ |
|
|
|
var module = angular.module('pixinote'); |
|
|
|
var insertView = function(scope, el, viewName){ |
|
viewName = viewName.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); |
|
var html = angular.element('<px-' + viewName + '></' + viewName + '>'); |
|
el.append(html); |
|
$compile(html)(scope); |
|
} |
|
|
|
return { |
|
restrict: 'A', |
|
link: function(scope, el, attrs){ |
|
window.el = window.el || el; |
|
if(!attrs.pxView[0].match('["\']')){ |
|
scope.$watch(attrs.pxView, function(viewName){ |
|
if(viewName) insertView(scope, el, viewName); |
|
}); |
|
} else { |
|
insertView(scope, el, attrs.pxView); |
|
} |
|
} |
|
} |
|
}]) |
|
|
|
|
|
/* |
|
* Extends the pixinote module with a function `view` that makes directive |
|
* definition a little sweeter (using a naming convention to save |
|
* naming templates explicitly) and a little more powerful. |
|
* |
|
* Compose views in html like this: |
|
* |
|
* <px-my-view></px-my-view> |
|
* <div px-view="'myView'"></div> |
|
* <div px-view="myViewExpr"></div> |
|
* |
|
* The last pattern is used for creating modal dialogs. See views/modals/modals.js |
|
* |
|
* The expectation is that all UI components outside of a minimal index.html |
|
* are defined with `view`. |
|
* |
|
* NB: I find myself preferring '&' in scope bindings and $eval in link functions |
|
* to avoid incurring {{ expr }} notation inside directive attributes. This |
|
* necessitates attr="'strings'", which is a bit odd, and maybe worse for being |
|
* subtler and easy to forget. Keep an eye out. |
|
* |
|
*/ |
|
|
|
.view = function(name, viewDef){ |
|
var module = angular.module('pixinote'); |
|
module.views = module.views || {}; |
|
viewDef = viewDef || {}; |
|
|
|
// Handle the shorthand signature `function view(name, controller)`. |
|
var controller; |
|
if(typeof viewDef == 'function' || (viewDef.slice !== undefined)){ |
|
controller = viewDef; |
|
viewDef = {controller: controller}; |
|
} |
|
|
|
// If the template isn't specified, assume it's named after the view. |
|
if(!viewDef.template && !viewDef.templateUrl){ |
|
viewDef.templateUrl = 'views/' + name + '/' + name + '.html'; |
|
} |
|
|
|
// Default to creating a child scope. |
|
viewDef.scope = viewDef.scope === undefined ? true : viewDef.scope; |
|
viewDef.priority = viewDef.priority === undefined ? viewDef.priority : 1; |
|
/* TODO: resolve the double wrapper syndrome that arises from the view tag |
|
including an html template that itself is wrapper in a div. e.g., |
|
viewController.html. |
|
- seems highly desirable to define directives on the view from inside |
|
it's own template (again, see viewController). |
|
- counter to that is the simplicity of defining the view's contents |
|
alone inside its template, and allowing the directive to be its only |
|
wrapper in markup. |
|
- one resolution would be to use replace on the directive, but that would |
|
force the inclusion of a wrapper inside the template, something |
|
that would quickly feel like boilerplate in 90% of views (that don't need |
|
to define directives or classes on themselves) |
|
- possible and slightly cray compromise would be to use replace only if |
|
the template doesn't include its own wrapper. would require inspecting |
|
the template at view definition time. |
|
- alternative: automagically wrap the template contents in a tag by the |
|
view's name and always use replace. |
|
|
|
RELATED: autoscope view styles to their owner tags |
|
*/ |
|
|
|
// Catalog the view by name and create a directive prefixed with px. |
|
module.views[name] = viewDef; |
|
module.directive('px' + name[0].toUpperCase() + name.slice(1), |
|
function(){ |
|
return viewDef; |
|
}); |
|
|
|
return module; |
|
}; |