-angular.module('egGridMod', ['egCoreMod', 'egListMod', 'egUiMod', 'ui.bootstrap'])
+angular.module('egGridMod',
+ ['egCoreMod', 'egListMod', 'egUiMod', 'ui.bootstrap', 'ui.scroll.jqlite', 'ui.scroll'])
-.directive('egGrid', function() {
+.directive('egGrid', function($window) {
return {
restrict : 'AE',
transclude : true,
// link() is called after page compilation, which means our
// eg-grid-field's have been parsed and loaded. Now it's
// safe to perform our initial page load.
- scope.fetchData();
+ //scope.fetchData();
},
templateUrl : '/eg/staff/parts/t_autogrid', // TODO: avoid abs url
controller : // TODO: reqs list
- function($scope, $timeout, $modal, $document, $window, egIDL, egAuth, egNet, egList) {
+ function($scope, $timeout, $element, egIDL, egAuth, egNet, egList, egGridData) {
var self = this;
+ self.egGridData = egGridData;
// setup function. called at the end of the controller
this.init = function() {
- self.limit = 25;
- self.ofset = 0;
+ self.limit = 10;
+ self.offset = 0;
$scope.indexFlex = 1;
$scope.selectorFlex = 1;
self.compileAutoFields();
$scope.list.indexField = $scope.idField;
+
+ self.egGridData.configure({
+ idlClass : $scope.idlClass,
+ query : $scope.query,
+ list : $scope.list
+ });
}
// column-header click quick sort
} else {
$scope.sort = [col_name];
}
- $scope.fetchData();
+ egGridData.sort = $scope.sort;
+ egGridData.reset();
+ //$scope.fetchData();
}
// maps numeric sort priority to flattener sort blob
// handled externally.
if ($scope.egList) return;
- $scope.list.resetPageData();
-
+ //$scope.list.resetPageData();
var queryFields = {}
angular.forEach($scope.list.allColumns, function(field) {
$scope.$apply(); // needed
}
+ $scope.fetchMoreData = function() {
+ console.log('fetchMoreData');
+ self.offset += self.limit;
+ $scope.fetchData();
+ }
+
this.init();
}
};
};
})
+.factory('egGridData', ['egNet','egAuth',
+
+ function(egNet, egAuth) {
+ var service = {};
+
+ service.configure = function(params) {
+ console.log('configure');
+ service.idlClass = params.idlClass;
+ service.query = params.query;
+ service.list = params.list;
+ }
+
+ service.reset = function() {
+ service.list.resetPageData();
+ service._rev = Math.random();
+ }
+
+ service.revision = function() {
+ return service._rev;
+ }
+
+ service.get = function(index, count, success) {
+ var queryFields = {}
+ console.log('service.get()');
+ index -= 1; // we like zero-based
+ if (index < 0) return success([]); // hrm??
+
+ angular.forEach(service.list.allColumns, function(field) {
+ if (service.list.displayColumns[field.name])
+ queryFields[field.name] = field.path || field.name;
+ });
+
+ egNet.request(
+ 'open-ils.fielder',
+ 'open-ils.fielder.flattened_search',
+ egAuth.token(), service.idlClass, queryFields,
+ service.query,
+ { sort : service.sort,
+ limit : count,
+ offset : index
+ }
+ ).then(
+ function() { // oncomplete
+ console.log(index + ' : ' + count);
+ success(service.list.items.slice(index, index + count));
+ },
+ null, // onerror
+ function(item) { // onmessage
+ service.list.items.push(item);
+ }
+ );
+ }
+
+ return service;
+ }
+])
+
/** Simplified dnd directives for grid column controls.
* Extract these out if the can be made generic enough
*/
require : '^egGrid',
link : function(scope, element, attrs, egGridCtrl) {
element.bind('dragover', function(e) {
- console.log('dragover');
e.stopPropagation();
e.preventDefault();
//e.dataTransfer.dropEffect = 'copy';
var col = angular.element(e.target).attr('column');
+ console.log('dragover ' + col);
egGridCtrl.onColumnDragOver(col);
});
}
--- /dev/null
+'use strict';
+
+angular.module('ui.scroll.jqlite', ['ui.scroll']).service('jqLiteExtras', [
+ '$log', '$window', function(console, window) {
+ return {
+ registerFor: function(element) {
+ var convertToPx, css, getMeasurements, getStyle, getWidthHeight, isWindow, scrollTo;
+ css = angular.element.prototype.css;
+ element.prototype.css = function(name, value) {
+ var elem, self;
+ self = this;
+ elem = self[0];
+ if (!(!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style)) {
+ return css.call(self, name, value);
+ }
+ };
+ isWindow = function(obj) {
+ return obj && obj.document && obj.location && obj.alert && obj.setInterval;
+ };
+ scrollTo = function(self, direction, value) {
+ var elem, method, preserve, prop, _ref;
+ elem = self[0];
+ _ref = {
+ top: ['scrollTop', 'pageYOffset', 'scrollLeft'],
+ left: ['scrollLeft', 'pageXOffset', 'scrollTop']
+ }[direction], method = _ref[0], prop = _ref[1], preserve = _ref[2];
+ if (isWindow(elem)) {
+ if (angular.isDefined(value)) {
+ return elem.scrollTo(self[preserve].call(self), value);
+ } else {
+ if (prop in elem) {
+ return elem[prop];
+ } else {
+ return elem.document.documentElement[method];
+ }
+ }
+ } else {
+ if (angular.isDefined(value)) {
+ return elem[method] = value;
+ } else {
+ return elem[method];
+ }
+ }
+ };
+ if (window.getComputedStyle) {
+ getStyle = function(elem) {
+ return window.getComputedStyle(elem, null);
+ };
+ convertToPx = function(elem, value) {
+ return parseFloat(value);
+ };
+ } else {
+ getStyle = function(elem) {
+ return elem.currentStyle;
+ };
+ convertToPx = function(elem, value) {
+ var core_pnum, left, result, rnumnonpx, rs, rsLeft, style;
+ core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source;
+ rnumnonpx = new RegExp('^(' + core_pnum + ')(?!px)[a-z%]+$', 'i');
+ if (!rnumnonpx.test(value)) {
+ return parseFloat(value);
+ } else {
+ style = elem.style;
+ left = style.left;
+ rs = elem.runtimeStyle;
+ rsLeft = rs && rs.left;
+ if (rs) {
+ rs.left = style.left;
+ }
+ style.left = value;
+ result = style.pixelLeft;
+ style.left = left;
+ if (rsLeft) {
+ rs.left = rsLeft;
+ }
+ return result;
+ }
+ };
+ }
+ getMeasurements = function(elem, measure) {
+ var base, borderA, borderB, computedMarginA, computedMarginB, computedStyle, dirA, dirB, marginA, marginB, paddingA, paddingB, _ref;
+ if (isWindow(elem)) {
+ base = document.documentElement[{
+ height: 'clientHeight',
+ width: 'clientWidth'
+ }[measure]];
+ return {
+ base: base,
+ padding: 0,
+ border: 0,
+ margin: 0
+ };
+ }
+ _ref = {
+ width: [elem.offsetWidth, 'Left', 'Right'],
+ height: [elem.offsetHeight, 'Top', 'Bottom']
+ }[measure], base = _ref[0], dirA = _ref[1], dirB = _ref[2];
+ computedStyle = getStyle(elem);
+ paddingA = convertToPx(elem, computedStyle['padding' + dirA]) || 0;
+ paddingB = convertToPx(elem, computedStyle['padding' + dirB]) || 0;
+ borderA = convertToPx(elem, computedStyle['border' + dirA + 'Width']) || 0;
+ borderB = convertToPx(elem, computedStyle['border' + dirB + 'Width']) || 0;
+ computedMarginA = computedStyle['margin' + dirA];
+ computedMarginB = computedStyle['margin' + dirB];
+ marginA = convertToPx(elem, computedMarginA) || 0;
+ marginB = convertToPx(elem, computedMarginB) || 0;
+ return {
+ base: base,
+ padding: paddingA + paddingB,
+ border: borderA + borderB,
+ margin: marginA + marginB
+ };
+ };
+ getWidthHeight = function(elem, direction, measure) {
+ var computedStyle, measurements, result;
+ measurements = getMeasurements(elem, direction);
+ if (measurements.base > 0) {
+ return {
+ base: measurements.base - measurements.padding - measurements.border,
+ outer: measurements.base,
+ outerfull: measurements.base + measurements.margin
+ }[measure];
+ } else {
+ computedStyle = getStyle(elem);
+ result = computedStyle[direction];
+ if (result < 0 || result === null) {
+ result = elem.style[direction] || 0;
+ }
+ result = parseFloat(result) || 0;
+ return {
+ base: result - measurements.padding - measurements.border,
+ outer: result,
+ outerfull: result + measurements.padding + measurements.border + measurements.margin
+ }[measure];
+ }
+ };
+ return angular.forEach({
+ before: function(newElem) {
+ var children, elem, i, parent, self, _i, _ref;
+ self = this;
+ elem = self[0];
+ parent = self.parent();
+ children = parent.contents();
+ if (children[0] === elem) {
+ return parent.prepend(newElem);
+ } else {
+ for (i = _i = 1, _ref = children.length - 1; 1 <= _ref ? _i <= _ref : _i >= _ref; i = 1 <= _ref ? ++_i : --_i) {
+ if (children[i] === elem) {
+ angular.element(children[i - 1]).after(newElem);
+ return;
+ }
+ }
+ throw new Error('invalid DOM structure ' + elem.outerHTML);
+ }
+ },
+ height: function(value) {
+ var self;
+ self = this;
+ if (angular.isDefined(value)) {
+ if (angular.isNumber(value)) {
+ value = value + 'px';
+ }
+ return css.call(self, 'height', value);
+ } else {
+ return getWidthHeight(this[0], 'height', 'base');
+ }
+ },
+ outerHeight: function(option) {
+ return getWidthHeight(this[0], 'height', option ? 'outerfull' : 'outer');
+ },
+ offset: function(value) {
+ var box, doc, docElem, elem, self, win;
+ self = this;
+ if (arguments.length) {
+ if (value === void 0) {
+ return self;
+ } else {
+ return value;
+
+ }
+ }
+ box = {
+ top: 0,
+ left: 0
+ };
+ elem = self[0];
+ doc = elem && elem.ownerDocument;
+ if (!doc) {
+ return;
+ }
+ docElem = doc.documentElement;
+ if (elem.getBoundingClientRect) {
+ box = elem.getBoundingClientRect();
+ }
+ win = doc.defaultView || doc.parentWindow;
+ return {
+ top: box.top + (win.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),
+ left: box.left + (win.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
+ };
+ },
+ scrollTop: function(value) {
+ return scrollTo(this, 'top', value);
+ },
+ scrollLeft: function(value) {
+ return scrollTo(this, 'left', value);
+ }
+ }, function(value, key) {
+ if (!element.prototype[key]) {
+ return element.prototype[key] = value;
+ }
+ });
+ }
+ };
+ }
+]).run([
+ '$log', '$window', 'jqLiteExtras', function(console, window, jqLiteExtras) {
+ if (!window.jQuery) {
+ return jqLiteExtras.registerFor(angular.element);
+ }
+ }
+]);
--- /dev/null
+'use strict';
+/*
+
+ List of used element methods available in JQuery but not in JQuery Lite
+
+ element.before(elem)
+ element.height()
+ element.outerHeight(true)
+ element.height(value) = only for Top/Bottom padding elements
+ element.scrollTop()
+ element.scrollTop(value)
+ */
+
+angular.module('ui.scroll', []).directive('ngScrollViewport', [
+ '$log', function() {
+ return {
+ controller: [
+ '$scope', '$element', function(scope, element) {
+ return element;
+ }
+ ]
+ };
+ }
+ ]).directive('ngScroll', [
+ '$log', '$injector', '$rootScope', '$timeout', function(console, $injector, $rootScope, $timeout) {
+ return {
+ require: ['?^ngScrollViewport'],
+ transclude: 'element',
+ priority: 1000,
+ terminal: true,
+ compile: function(elementTemplate, attr, linker) {
+ return function($scope, element, $attr, controllers) {
+ var adapter, adjustBuffer, adjustRowHeight, bof, bottomVisiblePos, buffer, bufferPadding, bufferSize, clipBottom, clipTop, datasource, datasourceName, enqueueFetch, eof, eventListener, fetch, finalize, first, insert, isDatasource, isLoading, itemName, loading, match, next, pending, reload, removeFromBuffer, resizeHandler, scrollHandler, scrollHeight, shouldLoadBottom, shouldLoadTop, tempScope, topVisiblePos, viewport;
+ match = $attr.ngScroll.match(/^\s*(\w+)\s+in\s+(\w+)\s*$/);
+ if (!match) {
+ throw new Error('Expected ngScroll in form of "item_ in _datasource_" but got "' + $attr.ngScroll + '"');
+ }
+ itemName = match[1];
+ datasourceName = match[2];
+ isDatasource = function(datasource) {
+ return angular.isObject(datasource) && datasource.get && angular.isFunction(datasource.get);
+ };
+ datasource = $scope[datasourceName];
+ if (!isDatasource(datasource)) {
+ datasource = $injector.get(datasourceName);
+ if (!isDatasource(datasource)) {
+ throw new Error(datasourceName + ' is not a valid datasource');
+ }
+ }
+ bufferSize = Math.max(3, +$attr.bufferSize || 10);
+ bufferPadding = function() {
+ return viewport.height() * Math.max(0.1, +$attr.padding || 0.1);
+ };
+ scrollHeight = function(elem) {
+ console.log(elem[0].scrollHeight, elem[0].document);
+ if( !elem[0].scrollHeight && !elem[0].document ) {
+ throw new Error('Could not determine scrollHeight of your viewport; make sure it has a constrained height (not height:auto)');
+ }
+ return elem[0].scrollHeight || elem[0].document.documentElement.scrollHeight;
+ };
+ adapter = null;
+ linker(tempScope = $scope.$new(), function(template) {
+ var bottomPadding, createPadding, padding, repeaterType, topPadding, viewport;
+ repeaterType = template[0].localName;
+ if (repeaterType === 'dl') {
+ throw new Error('ng-scroll directive does not support <' + template[0].localName + '> as a repeating tag: ' + template[0].outerHTML);
+ }
+ if (repeaterType !== 'li' && repeaterType !== 'tr') {
+ repeaterType = 'div';
+ }
+ viewport = controllers[0] || angular.element(window);
+ viewport.css({
+ 'overflow-y': 'auto',
+ 'display': 'block'
+ });
+ padding = function(repeaterType) {
+ var div, result, table;
+ switch (repeaterType) {
+ case 'tr':
+ table = angular.element('<table><tr><td><div></div></td></tr></table>');
+ div = table.find('div');
+ result = table.find('tr');
+ result.paddingHeight = function() {
+ return div.height.apply(div, arguments);
+ };
+ return result;
+ default:
+ result = angular.element('<' + repeaterType + '></' + repeaterType + '>');
+ result.paddingHeight = result.height;
+ return result;
+ }
+ };
+ createPadding = function(padding, element, direction) {
+ element[{
+ top: 'before',
+ bottom: 'after'
+ }[direction]](padding);
+ return {
+ paddingHeight: function() {
+ return padding.paddingHeight.apply(padding, arguments);
+ },
+ insert: function(element) {
+ return padding[{
+ top: 'after',
+ bottom: 'before'
+ }[direction]](element);
+ }
+ };
+ };
+ topPadding = createPadding(padding(repeaterType), element, 'top');
+ bottomPadding = createPadding(padding(repeaterType), element, 'bottom');
+ tempScope.$destroy();
+ return adapter = {
+ viewport: viewport,
+ topPadding: topPadding.paddingHeight,
+ bottomPadding: bottomPadding.paddingHeight,
+ append: bottomPadding.insert,
+ prepend: topPadding.insert,
+ bottomDataPos: function() {
+ return scrollHeight(viewport) - bottomPadding.paddingHeight();
+ },
+ topDataPos: function() {
+ return topPadding.paddingHeight();
+ }
+ };
+ });
+ viewport = adapter.viewport;
+ first = 1;
+ next = 1;
+ buffer = [];
+ pending = [];
+ eof = false;
+ bof = false;
+ loading = datasource.loading || function() {};
+ isLoading = false;
+ removeFromBuffer = function(start, stop) {
+ var i, _i;
+ for (i = _i = start; start <= stop ? _i < stop : _i > stop; i = start <= stop ? ++_i : --_i) {
+ buffer[i].scope.$destroy();
+ buffer[i].element.remove();
+ }
+ return buffer.splice(start, stop - start);
+ };
+ reload = function() {
+ first = 1;
+ next = 1;
+ removeFromBuffer(0, buffer.length);
+ adapter.topPadding(0);
+ adapter.bottomPadding(0);
+ pending = [];
+ eof = false;
+ bof = false;
+ return adjustBuffer(false);
+ };
+ bottomVisiblePos = function() {
+ return viewport.scrollTop() + viewport.height();
+ };
+ topVisiblePos = function() {
+ return viewport.scrollTop();
+ };
+ shouldLoadBottom = function() {
+ return !eof && adapter.bottomDataPos() < bottomVisiblePos() + bufferPadding();
+ };
+ clipBottom = function() {
+ var bottomHeight, i, itemHeight, overage, _i, _ref;
+ bottomHeight = 0;
+ overage = 0;
+ for (i = _i = _ref = buffer.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
+ itemHeight = buffer[i].element.outerHeight(true);
+ if (adapter.bottomDataPos() - bottomHeight - itemHeight > bottomVisiblePos() + bufferPadding()) {
+ bottomHeight += itemHeight;
+ overage++;
+ eof = false;
+ } else {
+ break;
+ }
+ }
+ if (overage > 0) {
+ adapter.bottomPadding(adapter.bottomPadding() + bottomHeight);
+ removeFromBuffer(buffer.length - overage, buffer.length);
+ next -= overage;
+ return console.log('clipped off bottom ' + overage + ' bottom padding ' + (adapter.bottomPadding()));
+ }
+ };
+ shouldLoadTop = function() {
+ return !bof && (adapter.topDataPos() > topVisiblePos() - bufferPadding());
+ };
+ clipTop = function() {
+ var item, itemHeight, overage, topHeight, _i, _len;
+ topHeight = 0;
+ overage = 0;
+ for (_i = 0, _len = buffer.length; _i < _len; _i++) {
+ item = buffer[_i];
+ itemHeight = item.element.outerHeight(true);
+ if (adapter.topDataPos() + topHeight + itemHeight < topVisiblePos() - bufferPadding()) {
+ topHeight += itemHeight;
+ overage++;
+ bof = false;
+ } else {
+ break;
+ }
+ }
+ if (overage > 0) {
+ adapter.topPadding(adapter.topPadding() + topHeight);
+ removeFromBuffer(0, overage);
+ first += overage;
+ return console.log('clipped off top ' + overage + ' top padding ' + (adapter.topPadding()));
+ }
+ };
+ enqueueFetch = function(direction, scrolling) {
+ if (!isLoading) {
+ isLoading = true;
+ loading(true);
+ }
+ if (pending.push(direction) === 1) {
+ return fetch(scrolling);
+ }
+ };
+ insert = function(index, item) {
+ var itemScope, toBeAppended, wrapper;
+ itemScope = $scope.$new();
+ itemScope[itemName] = item;
+ toBeAppended = index > first;
+ itemScope.$index = index;
+ if (toBeAppended) {
+ itemScope.$index--;
+ }
+ wrapper = {
+ scope: itemScope
+ };
+ linker(itemScope, function(clone) {
+ wrapper.element = clone;
+ if (toBeAppended) {
+ if (index === next) {
+ adapter.append(clone);
+ return buffer.push(wrapper);
+ } else {
+ buffer[index - first].element.after(clone);
+ return buffer.splice(index - first + 1, 0, wrapper);
+ }
+ } else {
+ adapter.prepend(clone);
+ return buffer.unshift(wrapper);
+ }
+ });
+ return {
+ appended: toBeAppended,
+ wrapper: wrapper
+ };
+ };
+ adjustRowHeight = function(appended, wrapper) {
+ var newHeight;
+ if (appended) {
+ return adapter.bottomPadding(Math.max(0, adapter.bottomPadding() - wrapper.element.outerHeight(true)));
+ } else {
+ newHeight = adapter.topPadding() - wrapper.element.outerHeight(true);
+ if (newHeight >= 0) {
+ return adapter.topPadding(newHeight);
+ } else {
+ return viewport.scrollTop(viewport.scrollTop() + wrapper.element.outerHeight(true));
+ }
+ }
+ };
+ adjustBuffer = function(scrolling, newItems, finalize) {
+ var doAdjustment;
+ doAdjustment = function() {
+ console.log('top {actual=' + (adapter.topDataPos()) + ' visible from=' + (topVisiblePos()) + ' bottom {visible through=' + (bottomVisiblePos()) + ' actual=' + (adapter.bottomDataPos()) + '}');
+ if (shouldLoadBottom()) {
+ enqueueFetch(true, scrolling);
+ } else {
+ if (shouldLoadTop()) {
+ enqueueFetch(false, scrolling);
+ }
+ }
+ if (finalize) {
+ return finalize();
+ }
+ };
+ if (newItems) {
+ return $timeout(function() {
+ var row, _i, _len;
+ for (_i = 0, _len = newItems.length; _i < _len; _i++) {
+ row = newItems[_i];
+ adjustRowHeight(row.appended, row.wrapper);
+ }
+ return doAdjustment();
+ });
+ } else {
+ return doAdjustment();
+ }
+ };
+ finalize = function(scrolling, newItems) {
+ return adjustBuffer(scrolling, newItems, function() {
+ pending.shift();
+ if (pending.length === 0) {
+ isLoading = false;
+ return loading(false);
+ } else {
+ return fetch(scrolling);
+ }
+ });
+ };
+ fetch = function(scrolling) {
+ var direction;
+ direction = pending[0];
+ if (direction) {
+ if (buffer.length && !shouldLoadBottom()) {
+ return finalize(scrolling);
+ } else {
+ return datasource.get(next, bufferSize, function(result) {
+ var item, newItems, _i, _len;
+ newItems = [];
+ if (result.length === 0) {
+ eof = true;
+ adapter.bottomPadding(0);
+ console.log('appended: requested ' + bufferSize + ' records starting from ' + next + ' recieved: eof');
+ } else {
+ clipTop();
+ for (_i = 0, _len = result.length; _i < _len; _i++) {
+ item = result[_i];
+ newItems.push(insert(++next, item));
+ }
+ console.log('appended: requested ' + bufferSize + ' received ' + result.length + ' buffer size ' + buffer.length + ' first ' + first + ' next ' + next);
+ }
+ return finalize(scrolling, newItems);
+ });
+ }
+ } else {
+ if (buffer.length && !shouldLoadTop()) {
+ return finalize(scrolling);
+ } else {
+ return datasource.get(first - bufferSize, bufferSize, function(result) {
+ var i, newItems, _i, _ref;
+ newItems = [];
+ if (result.length === 0) {
+ bof = true;
+ adapter.topPadding(0);
+ console.log('prepended: requested ' + bufferSize + ' records starting from ' + (first - bufferSize) + ' recieved: bof');
+ } else {
+ clipBottom();
+ for (i = _i = _ref = result.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
+ newItems.unshift(insert(--first, result[i]));
+ }
+ console.log('prepended: requested ' + bufferSize + ' received ' + result.length + ' buffer size ' + buffer.length + ' first ' + first + ' next ' + next);
+ }
+ return finalize(scrolling, newItems);
+ });
+ }
+ }
+ };
+ resizeHandler = function() {
+ if (!$rootScope.$$phase && !isLoading) {
+ adjustBuffer(false);
+ return $scope.$apply();
+ }
+ };
+ viewport.bind('resize', resizeHandler);
+ scrollHandler = function() {
+ if (!$rootScope.$$phase && !isLoading) {
+ adjustBuffer(true);
+ return $scope.$apply();
+ }
+ };
+ viewport.bind('scroll', scrollHandler);
+ $scope.$watch(datasource.revision, function() {
+ return reload();
+ });
+ if (datasource.scope) {
+ eventListener = datasource.scope.$new();
+ } else {
+ eventListener = $scope.$new();
+ }
+ $scope.$on('$destroy', function() {
+ eventListener.$destroy();
+ viewport.unbind('resize', resizeHandler);
+ return viewport.unbind('scroll', scrollHandler);
+ });
+ eventListener.$on('update.items', function(event, locator, newItem) {
+ var wrapper, _fn, _i, _len, _ref;
+ if (angular.isFunction(locator)) {
+ _fn = function(wrapper) {
+ return locator(wrapper.scope);
+ };
+ for (_i = 0, _len = buffer.length; _i < _len; _i++) {
+ wrapper = buffer[_i];
+ _fn(wrapper);
+ }
+ } else {
+ if ((0 <= (_ref = locator - first - 1) && _ref < buffer.length)) {
+ buffer[locator - first - 1].scope[itemName] = newItem;
+ }
+ }
+ return null;
+ });
+ eventListener.$on('delete.items', function(event, locator) {
+ var i, item, temp, wrapper, _fn, _i, _j, _k, _len, _len1, _len2, _ref;
+ if (angular.isFunction(locator)) {
+ temp = [];
+ for (_i = 0, _len = buffer.length; _i < _len; _i++) {
+ item = buffer[_i];
+ temp.unshift(item);
+ }
+ _fn = function(wrapper) {
+ if (locator(wrapper.scope)) {
+ removeFromBuffer(temp.length - 1 - i, temp.length - i);
+ return next--;
+ }
+ };
+ for (i = _j = 0, _len1 = temp.length; _j < _len1; i = ++_j) {
+ wrapper = temp[i];
+ _fn(wrapper);
+ }
+ } else {
+ if ((0 <= (_ref = locator - first - 1) && _ref < buffer.length)) {
+ removeFromBuffer(locator - first - 1, locator - first);
+ next--;
+ }
+ }
+ for (i = _k = 0, _len2 = buffer.length; _k < _len2; i = ++_k) {
+ item = buffer[i];
+ item.scope.$index = first + i;
+ }
+ return adjustBuffer(false);
+ });
+ return eventListener.$on('insert.item', function(event, locator, item) {
+ var i, inserted, temp, wrapper, _fn, _i, _j, _k, _len, _len1, _len2, _ref;
+ inserted = [];
+ if (angular.isFunction(locator)) {
+ temp = [];
+ for (_i = 0, _len = buffer.length; _i < _len; _i++) {
+ item = buffer[_i];
+ temp.unshift(item);
+ }
+ _fn = function(wrapper) {
+ var j, newItems, _k, _len2, _results;
+ if (newItems = locator(wrapper.scope)) {
+ insert = function(index, newItem) {
+ insert(index, newItem);
+ return next++;
+ };
+ if (angular.isArray(newItems)) {
+ _results = [];
+ for (j = _k = 0, _len2 = newItems.length; _k < _len2; j = ++_k) {
+ item = newItems[j];
+ _results.push(inserted.push(insert(i + j, item)));
+ }
+ return _results;
+ } else {
+ return inserted.push(insert(i, newItems));
+ }
+ }
+ };
+ for (i = _j = 0, _len1 = temp.length; _j < _len1; i = ++_j) {
+ wrapper = temp[i];
+ _fn(wrapper);
+ }
+ } else {
+ if ((0 <= (_ref = locator - first - 1) && _ref < buffer.length)) {
+ inserted.push(insert(locator, item));
+ next++;
+ }
+ }
+ for (i = _k = 0, _len2 = buffer.length; _k < _len2; i = ++_k) {
+ item = buffer[i];
+ item.scope.$index = first + i;
+ }
+ return adjustBuffer(false, inserted);
+ });
+ };
+ }
+ };
+ }
+ ]);