Telegram Web, preconfigured for usage in I2P.
http://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
11 KiB
321 lines
11 KiB
(function () { |
|
"use strict"; |
|
/** |
|
* Bindonce - Zero watches binding for AngularJs |
|
* @version v0.3.1 |
|
* @link https://github.com/Pasvaz/bindonce |
|
* @author Pasquale Vazzana <pasqualevazzana@gmail.com> |
|
* @license MIT License, http://www.opensource.org/licenses/MIT |
|
*/ |
|
|
|
var bindonceModule = angular.module('pasvaz.bindonce', []); |
|
|
|
bindonceModule.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 transclude = function (transcluder, scope) |
|
{ |
|
transcluder.transclude(scope, function (clone) |
|
{ |
|
var parent = transcluder.element.parent(); |
|
var afterNode = transcluder.element && transcluder.element[transcluder.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); |
|
}); |
|
}); |
|
}; |
|
|
|
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.checkBindonce(newValue); |
|
}, true); |
|
}, |
|
|
|
checkBindonce: function (value) |
|
{ |
|
var that = this, promise = (value.$promise) ? value.$promise.then : value.then; |
|
// since Angular 1.2 promises are no longer |
|
// undefined until they don't get resolved |
|
if (typeof promise === 'function') |
|
{ |
|
promise(function () |
|
{ |
|
that.runBinders(); |
|
}); |
|
} |
|
else |
|
{ |
|
that.runBinders(); |
|
} |
|
}, |
|
|
|
removeWatcher: function () |
|
{ |
|
if (this.watcherRemover !== undefined) |
|
{ |
|
this.watcherRemover(); |
|
this.watcherRemover = undefined; |
|
} |
|
}, |
|
|
|
runBinders: function () |
|
{ |
|
while (this.binders.length > 0) |
|
{ |
|
var binder = this.binders.shift(); |
|
if (this.group && this.group != binder.group) continue; |
|
var value = binder.scope.$eval((binder.interpolate) ? $interpolate(binder.value) : binder.value); |
|
switch (binder.attr) |
|
{ |
|
case 'boIf': |
|
if (toBoolean(value)) |
|
{ |
|
transclude(binder, binder.scope.$new()); |
|
} |
|
break; |
|
case 'boSwitch': |
|
var selectedTranscludes, switchCtrl = binder.controller[0]; |
|
if ((selectedTranscludes = switchCtrl.cases['!' + value] || switchCtrl.cases['?'])) |
|
{ |
|
binder.scope.$eval(binder.attrs.change); |
|
angular.forEach(selectedTranscludes, function (selectedTransclude) |
|
{ |
|
transclude(selectedTransclude, binder.scope.$new()); |
|
}); |
|
} |
|
break; |
|
case 'boSwitchWhen': |
|
var ctrl = binder.controller[0]; |
|
ctrl.cases['!' + binder.attrs.boSwitchWhen] = (ctrl.cases['!' + binder.attrs.boSwitchWhen] || []); |
|
ctrl.cases['!' + binder.attrs.boSwitchWhen].push({ transclude: binder.transclude, element: binder.element }); |
|
break; |
|
case 'boSwitchDefault': |
|
var ctrl = binder.controller[0]; |
|
ctrl.cases['?'] = (ctrl.cases['?'] || []); |
|
ctrl.cases['?'].push({ transclude: binder.transclude, element: binder.element }); |
|
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); |
|
break; |
|
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; |
|
} |
|
}; |
|
|
|
return ctrl; |
|
}], |
|
|
|
link: function (scope, elm, attrs, bindonceController) |
|
{ |
|
var value = attrs.bindonce && scope.$eval(attrs.bindonce); |
|
if (value !== undefined) |
|
{ |
|
bindonceController.checkBindonce(value); |
|
} |
|
else |
|
{ |
|
bindonceController.setupWatcher(attrs.bindonce); |
|
elm.bind("$destroy", bindonceController.removeWatcher); |
|
} |
|
} |
|
}; |
|
|
|
return bindonceDirective; |
|
}); |
|
|
|
angular.forEach( |
|
[ |
|
{ directiveName: 'boShow', attribute: 'show' }, |
|
{ directiveName: 'boHide', attribute: 'hide' }, |
|
{ directiveName: 'boClass', attribute: 'class' }, |
|
{ directiveName: 'boText', attribute: 'text' }, |
|
{ directiveName: 'boBind', 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' }, |
|
|
|
{ directiveName: 'boIf', transclude: 'element', terminal: true, priority: 1000 }, |
|
{ directiveName: 'boSwitch', require: 'boSwitch', controller: function () { this.cases = {}; } }, |
|
{ directiveName: 'boSwitchWhen', transclude: 'element', priority: 800, require: '^boSwitch' }, |
|
{ directiveName: 'boSwitchDefault', transclude: 'element', priority: 800, require: '^boSwitch' } |
|
], |
|
function (boDirective) |
|
{ |
|
var childPriority = 200; |
|
return bindonceModule.directive(boDirective.directiveName, function () |
|
{ |
|
var bindonceDirective = |
|
{ |
|
priority: boDirective.priority || childPriority, |
|
transclude: boDirective.transclude || false, |
|
terminal: boDirective.terminal || false, |
|
require: ['^bindonce'].concat(boDirective.require || []), |
|
controller: boDirective.controller, |
|
compile: function (tElement, tAttrs, transclude) |
|
{ |
|
return function (scope, elm, attrs, controllers) |
|
{ |
|
var bindonceController = controllers[0]; |
|
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 new Error("No bindonce controller: " + name); |
|
} |
|
} |
|
|
|
bindonceController.addBinder( |
|
{ |
|
element: elm, |
|
attr: boDirective.attribute || boDirective.directiveName, |
|
attrs: attrs, |
|
value: attrs[boDirective.directiveName], |
|
interpolate: boDirective.interpolate, |
|
group: name, |
|
transclude: transclude, |
|
controller: controllers.slice(1), |
|
scope: scope |
|
}); |
|
}; |
|
} |
|
}; |
|
|
|
return bindonceDirective; |
|
}); |
|
}) |
|
})(); |