Add bindonce and remove 50% of the watchers in the buffers
This commit is contained in:
parent
c88576fad2
commit
a78f49c0fc
3 changed files with 283 additions and 13 deletions
25
index.html
25
index.html
|
@ -20,6 +20,7 @@
|
|||
<script type="text/javascript" src="js/websockets.js"></script>
|
||||
<script type="text/javascript" src="js/models.js"></script>
|
||||
<script type="text/javascript" src="js/plugins.js"></script>
|
||||
<script type="text/javascript" src="js/bindonce.js"></script>
|
||||
<script type="text/javascript" src="js/favico-0.3.0.min.js"></script>
|
||||
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
|
||||
</head>
|
||||
|
@ -263,25 +264,25 @@ $ openssl req -nodes -newkey rsa:2048 -keyout relay.pem -x509 -days 365 -out rel
|
|||
</ul>
|
||||
</div>
|
||||
<table>
|
||||
<tbody ng-repeat="bufferline in (bufferlines = activeBuffer().lines)">
|
||||
<tbody bindonce ng-repeat="bufferline in (bufferlines = activeBuffer().lines)">
|
||||
<tr class="bufferline">
|
||||
<td ng-hide="notimestamp" class="time">
|
||||
<span class="date" ng-class="{'repeated-time': bufferline.shortTime==bufferlines[$index-1].shortTime}">
|
||||
<span class="cof-chat_time cob-chat_time coa-chat_time">{{ bufferline.date | date:'HH' }}</span><span class="cof-chat_time_delimiters cob-chat_time_delimiters coa-chat_time_delimiters">:</span><span class="cof-chat_time cob-chat_time coa-chat_time">{{ bufferline.date | date:'mm' }}</span>
|
||||
<td bo-hide="notimestamp" class="time">
|
||||
<span class="date" bo-class="{'repeated-time': bufferline.shortTime==bufferlines[$index-1].shortTime}">
|
||||
<span class="cof-chat_time cob-chat_time coa-chat_time" bo-text="bufferline.date|date:'HH'"></span><span class="cof-chat_time_delimiters cob-chat_time_delimiters coa-chat_time_delimiters">:</span><span class="cof-chat_time cob-chat_time coa-chat_time" bo-text="bufferline.date|date:'mm'">{{ bufferline.date | date:'mm' }}</span>
|
||||
</span>
|
||||
</td>
|
||||
<td class="prefix"><span ng-repeat="part in bufferline.prefix" ng-class="{{ part.classes }}">{{ part.text }}</span></td>
|
||||
<td class="prefix"><span bindonce ng-repeat="part in bufferline.prefix" bo-class="part.classes" bo-html="part.text"></span></td>
|
||||
<td class="message">
|
||||
<span ng-repeat="part in bufferline.content" class="text" ng-class="{{ part.classes }}" ng-bind-html="part.text|linky:'_blank'"></span>
|
||||
<span bindonce ng-repeat="part in bufferline.content" class="text" bo-class="part.classes" bo-html="part.text|linky:'_blank'"></span>
|
||||
|
||||
<div ng-repeat="metadata in bufferline.metadata">
|
||||
<div ng-show="metadata.visible">
|
||||
<button class="btn btn-primary pull-right" ng-click="metadata.visible = false">Hide {{ metadata.name }}</button>
|
||||
<div ng-bind-html="metadata.content"></div>
|
||||
<div bindonce ng-repeat="metadata in bufferline.metadata">
|
||||
<div bo-show="metadata.visible">
|
||||
<button class="btn btn-primary pull-right" bo-click="metadata.visible = false" bo-text="'Hide ' + metadata.name">Hide {{ metadata.name }}</button>
|
||||
<div bo-html="metadata.content"></div>
|
||||
|
||||
</div>
|
||||
<div ng-hide="metadata.visible">
|
||||
<button class="btn pull-right" ng-class="{'btn-warning': metadata.nsfw, 'btn-primary': !metadata.nsfw}" ng-click="metadata.visible = true">Show {{ metadata.name }}</button>
|
||||
<div bo-hide="metadata.visible">
|
||||
<button class="btn pull-right" bo-class="{'btn-warning': metadata.nsfw, 'btn-primary': !metadata.nsfw}" ng-click="metadata.visible = true">Show {{ metadata.name }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
|
269
js/bindonce.js
Normal file
269
js/bindonce.js
Normal 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;
|
||||
});
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
var weechat = angular.module('weechat', ['ngRoute', 'localStorage', 'weechatModels', 'plugins', 'ngSanitize']);
|
||||
var weechat = angular.module('weechat', ['ngRoute', 'localStorage', 'weechatModels', 'plugins', 'ngSanitize', 'pasvaz.bindonce']);
|
||||
|
||||
weechat.filter('toArray', function () {
|
||||
'use strict';
|
||||
|
|
Loading…
Reference in a new issue