| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- /**
- * Durandal 2.1.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved.
- * Available via the MIT license.
- * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details.
- */
- /**
- * The binder joins an object instance and a DOM element tree by applying databinding and/or invoking binding lifecycle callbacks (binding and bindingComplete).
- * @module binder
- * @requires system
- * @requires knockout
- */
- define(['durandal/system', 'knockout'], function (system, ko) {
- var binder,
- insufficientInfoMessage = 'Insufficient Information to Bind',
- unexpectedViewMessage = 'Unexpected View Type',
- bindingInstructionKey = 'durandal-binding-instruction',
- koBindingContextKey = '__ko_bindingContext__';
- function normalizeBindingInstruction(result){
- if(result === undefined){
- return { applyBindings: true };
- }
- if(system.isBoolean(result)){
- return { applyBindings:result };
- }
- if(result.applyBindings === undefined){
- result.applyBindings = true;
- }
- return result;
- }
- function doBind(obj, view, bindingTarget, data){
- if (!view || !bindingTarget) {
- if (binder.throwOnErrors) {
- system.error(insufficientInfoMessage);
- } else {
- system.log(insufficientInfoMessage, view, data);
- }
- return;
- }
- if (!view.getAttribute) {
- if (binder.throwOnErrors) {
- system.error(unexpectedViewMessage);
- } else {
- system.log(unexpectedViewMessage, view, data);
- }
- return;
- }
- var viewName = view.getAttribute('data-view');
- try {
- var instruction;
- if (obj && obj.binding) {
- instruction = obj.binding(view);
- }
- instruction = normalizeBindingInstruction(instruction);
- binder.binding(data, view, instruction);
- if(instruction.applyBindings){
- system.log('Binding', viewName, data);
- ko.applyBindings(bindingTarget, view);
- }else if(obj){
- ko.utils.domData.set(view, koBindingContextKey, { $data:obj });
- }
- binder.bindingComplete(data, view, instruction);
- if (obj && obj.bindingComplete) {
- obj.bindingComplete(view);
- }
- ko.utils.domData.set(view, bindingInstructionKey, instruction);
- return instruction;
- } catch (e) {
- e.message = e.message + ';\nView: ' + viewName + ";\nModuleId: " + system.getModuleId(data);
- if (binder.throwOnErrors) {
- system.error(e);
- } else {
- system.log(e.message);
- }
- }
- }
- /**
- * @class BinderModule
- * @static
- */
- return binder = {
- /**
- * Called before every binding operation. Does nothing by default.
- * @method binding
- * @param {object} data The data that is about to be bound.
- * @param {DOMElement} view The view that is about to be bound.
- * @param {object} instruction The object that carries the binding instructions.
- */
- binding: system.noop,
- /**
- * Called after every binding operation. Does nothing by default.
- * @method bindingComplete
- * @param {object} data The data that has just been bound.
- * @param {DOMElement} view The view that has just been bound.
- * @param {object} instruction The object that carries the binding instructions.
- */
- bindingComplete: system.noop,
- /**
- * Indicates whether or not the binding system should throw errors or not.
- * @property {boolean} throwOnErrors
- * @default false The binding system will not throw errors by default. Instead it will log them.
- */
- throwOnErrors: false,
- /**
- * Gets the binding instruction that was associated with a view when it was bound.
- * @method getBindingInstruction
- * @param {DOMElement} view The view that was previously bound.
- * @return {object} The object that carries the binding instructions.
- */
- getBindingInstruction:function(view){
- return ko.utils.domData.get(view, bindingInstructionKey);
- },
- /**
- * Binds the view, preserving the existing binding context. Optionally, a new context can be created, parented to the previous context.
- * @method bindContext
- * @param {KnockoutBindingContext} bindingContext The current binding context.
- * @param {DOMElement} view The view to bind.
- * @param {object} [obj] The data to bind to, causing the creation of a child binding context if present.
- * @param {string} [dataAlias] An alias for $data if present.
- */
- bindContext: function(bindingContext, view, obj, dataAlias) {
- if (obj && bindingContext) {
- bindingContext = bindingContext.createChildContext(obj, typeof(dataAlias) === 'string' ? dataAlias : null);
- }
- return doBind(obj, view, bindingContext, obj || (bindingContext ? bindingContext.$data : null));
- },
- /**
- * Binds the view, preserving the existing binding context. Optionally, a new context can be created, parented to the previous context.
- * @method bind
- * @param {object} obj The data to bind to.
- * @param {DOMElement} view The view to bind.
- */
- bind: function(obj, view) {
- return doBind(obj, view, obj, obj);
- }
- };
- });
|