Merge pull request #2371 from bachue/add-angular-bindonce-0-2-2

Add angular-bindonce.js v0.2.2
This commit is contained in:
Thomas Davis
2013-12-27 00:33:19 -08:00
3 changed files with 299 additions and 0 deletions
+269
View File
@@ -0,0 +1,269 @@
'use strict';
/**
* Bindonce - Zero watches binding for AngularJs
* @version v0.2.2 - 2013-05-07
* @link https://github.com/Pasvaz/bindonce
* @author Pasquale Vazzana <pasqualevazzana@gmail.com>
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
angular.module('pasvaz.bindonce', [])
.directive('bindonce', function()
{
var toBoolean = function(value)
{
if (value && value.length !== 0)
{
var v = angular.lowercase("" + value);
value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
}
else
{
value = false;
}
return value;
}
var msie = parseInt((/msie (\d+)/.exec(angular.lowercase(navigator.userAgent)) || [])[1], 10);
if (isNaN(msie))
{
msie = parseInt((/trident\/.*; rv:(\d+)/.exec(angular.lowercase(navigator.userAgent)) || [])[1], 10);
}
var bindonceDirective =
{
restrict: "AM",
controller: ['$scope', '$element', '$attrs', '$interpolate', function($scope, $element, $attrs, $interpolate)
{
var showHideBinder = function(elm, attr, value)
{
var show = (attr == 'show') ? '' : 'none';
var hide = (attr == 'hide') ? '' : 'none';
elm.css('display', toBoolean(value) ? show : hide);
}
var classBinder = function(elm, value)
{
if (angular.isObject(value) && !angular.isArray(value))
{
var results = [];
angular.forEach(value, function(value, index)
{
if (value) results.push(index);
});
value = results;
}
if (value)
{
elm.addClass(angular.isArray(value) ? value.join(' ') : value);
}
}
var ctrl =
{
watcherRemover : undefined,
binders : [],
group : $attrs.boName,
element : $element,
ran : false,
addBinder : function(binder)
{
this.binders.push(binder);
// In case of late binding (when using the directive bo-name/bo-parent)
// it happens only when you use nested bindonce, if the bo-children
// are not dom children the linking can follow another order
if (this.ran)
{
this.runBinders();
}
},
setupWatcher : function(bindonceValue)
{
var that = this;
this.watcherRemover = $scope.$watch(bindonceValue, function(newValue)
{
if (newValue == undefined) return;
that.removeWatcher();
that.runBinders();
}, true);
},
removeWatcher : function()
{
if (this.watcherRemover != undefined)
{
this.watcherRemover();
this.watcherRemover = undefined;
}
},
runBinders : function()
{
var i, max;
for (i = 0, max = this.binders.length; i < max; i ++)
{
var binder = this.binders[i];
if (this.group && this.group != binder.group ) continue;
var value = binder.scope.$eval((binder.interpolate) ? $interpolate(binder.value) : binder.value);
switch(binder.attr)
{
case 'if':
if (toBoolean(value))
{
binder.transclude(binder.scope.$new(), function (clone)
{
var parent = binder.element.parent();
var afterNode = binder.element && binder.element[binder.element.length - 1];
var parentNode = parent && parent[0] || afterNode && afterNode.parentNode;
var afterNextSibling = (afterNode && afterNode.nextSibling) || null;
angular.forEach(clone, function(node)
{
parentNode.insertBefore(node, afterNextSibling);
});
});
}
break;
case 'hide':
case 'show':
showHideBinder(binder.element, binder.attr, value);
break;
case 'class':
classBinder(binder.element, value);
break;
case 'text':
binder.element.text(value);
break;
case 'html':
binder.element.html(value);
break;
case 'style':
binder.element.css(value);
break;
case 'src':
binder.element.attr(binder.attr, value);
if (msie) binder.element.prop('src', value);
case 'attr':
angular.forEach(binder.attrs, function(attrValue, attrKey)
{
var newAttr, newValue;
if (attrKey.match(/^boAttr./) && binder.attrs[attrKey])
{
newAttr = attrKey.replace(/^boAttr/, '').replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
newValue = binder.scope.$eval(binder.attrs[attrKey]);
binder.element.attr(newAttr, newValue);
}
});
break;
case 'href':
case 'alt':
case 'title':
case 'id':
case 'value':
binder.element.attr(binder.attr, value);
break;
}
}
this.ran = true;
this.binders = [];
}
}
return ctrl;
}],
link: function(scope, elm, attrs, bindonceController)
{
var value = (attrs.bindonce) ? scope.$eval(attrs.bindonce) : true;
if (value != undefined)
{
bindonceController.runBinders();
}
else
{
bindonceController.setupWatcher(attrs.bindonce);
elm.bind("$destroy", bindonceController.removeWatcher);
}
}
};
return bindonceDirective;
});
angular.forEach(
[
{directiveName:'boShow', attribute: 'show'},
{directiveName:'boIf', attribute: 'if', transclude: 'element', terminal: true, priority:1000},
{directiveName:'boHide', attribute:'hide'},
{directiveName:'boClass', attribute:'class'},
{directiveName:'boText', attribute:'text'},
{directiveName:'boHtml', attribute:'html'},
{directiveName:'boSrcI', attribute:'src', interpolate:true},
{directiveName:'boSrc', attribute:'src'},
{directiveName:'boHrefI', attribute:'href', interpolate:true},
{directiveName:'boHref', attribute:'href'},
{directiveName:'boAlt', attribute:'alt'},
{directiveName:'boTitle', attribute:'title'},
{directiveName:'boId', attribute:'id'},
{directiveName:'boStyle', attribute:'style'},
{directiveName:'boValue', attribute:'value'},
{directiveName:'boAttr', attribute:'attr'}
],
function(boDirective)
{
var childPriority = 200;
return angular.module('pasvaz.bindonce').directive(boDirective.directiveName, function()
{
var bindonceDirective =
{
priority: boDirective.priority || childPriority,
transclude: boDirective.transclude || false,
terminal: boDirective.terminal || false,
require: '^bindonce',
compile: function (tElement, tAttrs, transclude)
{
return function(scope, elm, attrs, bindonceController)
{
var name = attrs.boParent;
if (name && bindonceController.group != name)
{
var element = bindonceController.element.parent();
bindonceController = undefined;
var parentValue;
while (element[0].nodeType != 9 && element.length)
{
if ((parentValue = element.data('$bindonceController'))
&& parentValue.group == name)
{
bindonceController = parentValue
break;
}
element = element.parent();
}
if (!bindonceController)
{
throw Error("No bindonce controller: " + name);
}
}
bindonceController.addBinder(
{
element : elm,
attr : boDirective.attribute,
attrs : attrs,
value : attrs[boDirective.directiveName],
interpolate : boDirective.interpolate,
group : name,
transclude : transclude,
scope : scope
});
}
}
}
return bindonceDirective;
});
});
@@ -0,0 +1 @@
"use strict";angular.module("pasvaz.bindonce",[]).directive("bindonce",function(){var a=function(a){if(a&&0!==a.length){var b=angular.lowercase(""+a);a=!("f"==b||"0"==b||"false"==b||"no"==b||"n"==b||"[]"==b)}else a=ls;return a},b=parseInt((/msie (\d+)/.exec(angular.lowercase(navigator.userAgent))||[])[1],10);isNaN(b)&&(b=parseInt((/trident\/.*; rv:(\d+)/.exec(angular.lowercase(navigator.userAgent))||[])[1],10));var c={restrict:"AM",controller:["","","","",function(c,d,e,f){var g=function(b,c,d){var e="show"==c?"":"none",f="hide"==c?"":"none";b.css("display",a(d)?e:f)},h=function(a,b){if(angular.isObject(b)&&!angular.isArray(b)){var c=[];angular.forEach(b,function(a,b){a&&c.push(b)}),b=c}b&&a.addClass(angular.isArray(b)?b.join(" "):b)},i={watcherRemover:void 0,binders:[],group:e.boName,element:d,ran:!1,addBinder:function(a){this.binders.push(a),this.ran&&this.runBinders()},setupWatcher:function(a){var b=this;this.watcherRemover=c.(a,function(a){void 0!=a&&(b.removeWatcher(),b.runBinders())},!0)},removeWatcher:function(){void 0!=this.watcherRemover&&(this.watcherRemover(),this.watcherRemover=void 0)},runBinders:function(){var c,d;for(c=0,d=this.binders.length;d>c;c++){var e=this.binders[c];if(!this.group||this.group==e.group){var i=e.scope.(e.interpolate?f(e.value):e.value);switch(e.attr){case"if":a(i)&&e.transclude(e.scope.(),function(a){var b=e.element.parent(),c=e.element&&e.element[e.element.length-1],d=b&&b[0]||c&&c.parentNode,f=c&&c.nextSibling||null;angular.forEach(a,function(a){d.insertBefore(a,f)})});break;case"hide":case"show":g(e.element,e.attr,i);break;case"class":h(e.element,i);break;case"text":e.element.text(i);break;case"html":e.element.html(i);break;case"style":e.element.css(i);break;case"src":e.element.attr(e.attr,i),b&&e.element.prop("src",i);case"attr":angular.forEach(e.attrs,function(a,b){var c,d;b.match(/^boAttr./)&&e.attrs[b]&&(c=b.replace(/^boAttr/,"").replace(/([a-z])([A-Z])/g,"-").toLowerCase(),d=e.scope.(e.attrs[b]),e.element.attr(c,d))});break;case"href":case"alt":case"title":case"id":case"value":e.element.attr(e.attr,i)}}}this.ran=!0,this.binders=[]}};return i}],link:function(a,b,c,d){var e=c.bindonce?a.(c.bindonce):!0;void 0!=e?d.runBinders():(d.setupWatcher(c.bindonce),b.bind("",d.removeWatcher))}};return c}),angular.forEach([{directiveName:"boShow",attribute:"show"},{directiveName:"boIf",attribute:"if",transclude:"element",terminal:!0,priority:1e3},{directiveName:"boHide",attribute:"hide"},{directiveName:"boClass",attribute:"class"},{directiveName:"boText",attribute:"text"},{directiveName:"boHtml",attribute:"html"},{directiveName:"boSrcI",attribute:"src",interpolate:!0},{directiveName:"boSrc",attribute:"src"},{directiveName:"boHrefI",attribute:"href",interpolate:!0},{directiveName:"boHref",attribute:"href"},{directiveName:"boAlt",attribute:"alt"},{directiveName:"boTitle",attribute:"title"},{directiveName:"boId",attribute:"id"},{directiveName:"boStyle",attribute:"style"},{directiveName:"boValue",attribute:"value"},{directiveName:"boAttr",attribute:"attr"}],function(a){var b=200;return angular.module("pasvaz.bindonce").directive(a.directiveName,function(){var c={priority:a.priority||b,transclude:a.transclude||!1,terminal:a.terminal||!1,require:"^bindonce",compile:function(b,c,d){return function(b,c,e,f){var g=e.boParent;if(g&&f.group!=g){var h=f.element.parent();f=void 0;for(var i;9!=h[0].nodeType&&h.length;){if((i=h.data(""))&&i.group==g){f=i;break}h=h.parent()}if(!f)throw Error("No bindonce controller: "+g)}f.addBinder({element:c,attr:a.attribute,attrs:e,value:e[a.directiveName],interpolate:a.interpolate,group:g,transclude:d,scope:b})}}};return c})});
+29
View File
@@ -0,0 +1,29 @@
{
"name": "angular-bindonce",
"filename": "angular-bindonce.min.js",
"version": "0.2.2",
"description": "Zero watchers binding directives for AngularJS",
"homepage": "https://github.com/Pasvaz/bindonce",
"author": "Pasquale Vazzana <pasqualevazzana@gmail.com>",
"repository": {
"type": "git",
"url": "https://github.com/Pasvaz/bindonce.git"
},
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"components"
],
"dependencies": {
"angular": ">=1.0.6"
},
"keywords": [
"angularjs",
"angular",
"directive",
"binding",
"watcher",
"bindonce"
]
}