mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Merge new-contacts-api
New interface Contact storage move to plugin
This commit is contained in:
commit
efdca7ef77
44 changed files with 3454 additions and 1012 deletions
115
vendors/knockout-projections/README.md
vendored
Normal file
115
vendors/knockout-projections/README.md
vendored
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
knockout-projections
|
||||
============
|
||||
|
||||
Knockout.js observable arrays get smarter.
|
||||
|
||||
This plugin adds observable `map` and `filter` features to observable arrays, so you can transform collections in arbitrary ways and have the results automatically update whenever the underlying source data changes.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Download a copy of `knockout-projections-x.y.z.js` from [the `dist` directory](https://github.com/SteveSanderson/knockout-projections/tree/master/dist) and reference it in your web application:
|
||||
|
||||
<script src='knockout-x.y.z.js'></script> <!-- First reference KO itself -->
|
||||
<script src='knockout-projections-x.y.z.js'></script> <!-- Then reference knockout-projections -->
|
||||
|
||||
Be sure to reference it *after* you reference Knockout itself, and of course replace `x.y.z` with the version number of the file you downloaded.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
**Mapping**
|
||||
|
||||
More info to follow. For now, here's a simple example:
|
||||
|
||||
var sourceItems = ko.observableArray([1, 2, 3, 4, 5]);
|
||||
|
||||
There's a plain observable array. Now let's say we want to keep track of the squares of these values:
|
||||
|
||||
var squares = sourceItems.map(function(x) { return x*x; });
|
||||
|
||||
Now `squares` is an observable array containing `[1, 4, 9, 16, 25]`. Let's modify the source data:
|
||||
|
||||
sourceItems.push(6);
|
||||
// 'squares' has automatically updated and now contains [1, 4, 9, 16, 25, 36]
|
||||
|
||||
This works with any transformation of the source data, e.g.:
|
||||
|
||||
sourceItems.reverse();
|
||||
// 'squares' now contains [36, 25, 16, 9, 4, 1]
|
||||
|
||||
The key point of this library is that these transformations are done *efficiently*. Specifically, your callback
|
||||
function that performs the mapping is only called when strictly necessary (usually, that's only for newly-added
|
||||
items). When you add new items to the source data, we *don't* need to re-map the existing ones. When you reorder
|
||||
the source data, the output order is correspondingly changed *without* remapping anything.
|
||||
|
||||
This efficiency might not matter much if you're just squaring numbers, but when you are mapping complex nested
|
||||
graphs of custom objects, it can be important to perform each mapping update with the minumum of work.
|
||||
|
||||
**Filtering**
|
||||
|
||||
As well as `map`, this plugin also provides `filter`:
|
||||
|
||||
var evenSquares = squares.filter(function(x) { return x % 2 === 0; });
|
||||
// evenSquares is now an observable containing [36, 16, 4]
|
||||
|
||||
sourceItems.push(9);
|
||||
// This has no effect on evenSquares, because 9*9=81 is odd
|
||||
|
||||
sourceItems.push(10);
|
||||
// evenSquares now contains [36, 16, 4, 100]
|
||||
|
||||
Again, your `filter` callbacks are only called when strictly necessary. Re-ordering or deleting source items don't
|
||||
require any refiltering - the output is simply updated to match. Only newly-added source items must be subjected
|
||||
to your `filter` callback.
|
||||
|
||||
**Chaining**
|
||||
|
||||
The above code also demonstrates that you can chain together successive `map` and `filter` transformations.
|
||||
|
||||
When the underlying data changes, the effects will ripple out through the chain of computed arrays with the
|
||||
minimum necessary invocation of your `map` and `filter` callbacks.
|
||||
|
||||
How to build from source
|
||||
========================
|
||||
|
||||
First, install [NPM](https://npmjs.org/) if you don't already have it. It comes with Node.js.
|
||||
|
||||
Second, install Grunt globally, if you don't already have it:
|
||||
|
||||
npm install -g grunt-cli
|
||||
|
||||
Third, use NPM to download all the dependencies for this module:
|
||||
|
||||
cd wherever_you_cloned_this_repo
|
||||
npm install
|
||||
|
||||
Now you can build the package (linting and running tests along the way):
|
||||
|
||||
grunt
|
||||
|
||||
Or you can just run the linting tool and tests:
|
||||
|
||||
grunt test
|
||||
|
||||
Or you can make Grunt watch for changes to the sources/specs and auto-rebuild after each change:
|
||||
|
||||
grunt watch
|
||||
|
||||
The browser-ready output files will be dumped at the following locations:
|
||||
|
||||
* `dist/knockout-projections.js`
|
||||
* `dist/knockout-projections.min.js`
|
||||
|
||||
License - Apache 2.0
|
||||
====================
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
|
||||
342
vendors/knockout-projections/knockout-projections-1.0.0.js
vendored
Normal file
342
vendors/knockout-projections/knockout-projections-1.0.0.js
vendored
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
/*! Knockout projections plugin
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
(function(global, undefined) {
|
||||
'use strict';
|
||||
|
||||
var exclusionMarker = {};
|
||||
|
||||
function StateItem(ko, inputItem, initialStateArrayIndex, initialOutputArrayIndex, mapping, arrayOfState, outputObservableArray) {
|
||||
// Capture state for later use
|
||||
this.inputItem = inputItem;
|
||||
this.stateArrayIndex = initialStateArrayIndex;
|
||||
this.mapping = mapping;
|
||||
this.arrayOfState = arrayOfState;
|
||||
this.outputObservableArray = outputObservableArray;
|
||||
this.outputArray = this.outputObservableArray.peek();
|
||||
this.isIncluded = null; // Means 'not yet determined'
|
||||
this.suppressNotification = false; // TODO: Instead of this technique, consider raising a sparse diff with a "mutated" entry when a single item changes, and not having any other change logic inside StateItem
|
||||
|
||||
// Set up observables
|
||||
this.outputArrayIndex = ko.observable(initialOutputArrayIndex); // When excluded, it's the position the item would go if it became included
|
||||
this.mappedValueComputed = ko.computed(this.mappingEvaluator, this);
|
||||
this.mappedValueComputed.subscribe(this.onMappingResultChanged, this);
|
||||
this.previousMappedValue = this.mappedValueComputed.peek();
|
||||
}
|
||||
|
||||
StateItem.prototype.dispose = function() {
|
||||
this.mappedValueComputed.dispose();
|
||||
};
|
||||
|
||||
StateItem.prototype.mappingEvaluator = function() {
|
||||
var mappedValue = this.mapping(this.inputItem, this.outputArrayIndex),
|
||||
newInclusionState = mappedValue !== exclusionMarker;
|
||||
|
||||
// Inclusion state changes can *only* happen as a result of changing an individual item.
|
||||
// Structural changes to the array can't cause this (because they don't cause any remapping;
|
||||
// they only map newly added items which have no earlier inclusion state to change).
|
||||
if (this.isIncluded !== newInclusionState) {
|
||||
if (this.isIncluded !== null) { // i.e., not first run
|
||||
this.moveSubsequentItemsBecauseInclusionStateChanged(newInclusionState);
|
||||
}
|
||||
|
||||
this.isIncluded = newInclusionState;
|
||||
}
|
||||
|
||||
return mappedValue;
|
||||
};
|
||||
|
||||
StateItem.prototype.onMappingResultChanged = function(newValue) {
|
||||
if (newValue !== this.previousMappedValue) {
|
||||
if (this.isIncluded) {
|
||||
this.outputArray.splice(this.outputArrayIndex.peek(), 1, newValue);
|
||||
}
|
||||
|
||||
if (!this.suppressNotification) {
|
||||
this.outputObservableArray.valueHasMutated();
|
||||
}
|
||||
|
||||
this.previousMappedValue = newValue;
|
||||
}
|
||||
};
|
||||
|
||||
StateItem.prototype.moveSubsequentItemsBecauseInclusionStateChanged = function(newInclusionState) {
|
||||
var outputArrayIndex = this.outputArrayIndex.peek(),
|
||||
iterationIndex,
|
||||
stateItem;
|
||||
|
||||
if (newInclusionState) {
|
||||
// Shift all subsequent items along by one space, and increment their indexes.
|
||||
// Note that changing their indexes might cause remapping, but won't affect their
|
||||
// inclusion status (by definition, inclusion status must not be affected by index,
|
||||
// otherwise you get undefined results) so there's no risk of a chain reaction.
|
||||
this.outputArray.splice(outputArrayIndex, 0, null);
|
||||
for (iterationIndex = this.stateArrayIndex + 1; iterationIndex < this.arrayOfState.length; iterationIndex++) {
|
||||
stateItem = this.arrayOfState[iterationIndex];
|
||||
stateItem.setOutputArrayIndexSilently(stateItem.outputArrayIndex.peek() + 1);
|
||||
}
|
||||
} else {
|
||||
// Shift all subsequent items back by one space, and decrement their indexes
|
||||
this.outputArray.splice(outputArrayIndex, 1);
|
||||
for (iterationIndex = this.stateArrayIndex + 1; iterationIndex < this.arrayOfState.length; iterationIndex++) {
|
||||
stateItem = this.arrayOfState[iterationIndex];
|
||||
stateItem.setOutputArrayIndexSilently(stateItem.outputArrayIndex.peek() - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
StateItem.prototype.setOutputArrayIndexSilently = function(newIndex) {
|
||||
// We only want to raise one output array notification per input array change,
|
||||
// so during processing, we suppress notifications
|
||||
this.suppressNotification = true;
|
||||
this.outputArrayIndex(newIndex);
|
||||
this.suppressNotification = false;
|
||||
};
|
||||
|
||||
function getDiffEntryPostOperationIndex(diffEntry, editOffset) {
|
||||
// The diff algorithm's "index" value refers to the output array for additions,
|
||||
// but the "input" array for deletions. Get the output array position.
|
||||
if (!diffEntry) { return null; }
|
||||
switch (diffEntry.status) {
|
||||
case 'added':
|
||||
return diffEntry.index;
|
||||
case 'deleted':
|
||||
return diffEntry.index + editOffset;
|
||||
default:
|
||||
throw new Error('Unknown diff status: ' + diffEntry.status);
|
||||
}
|
||||
}
|
||||
|
||||
function insertOutputItem(ko, diffEntry, movedStateItems, stateArrayIndex, outputArrayIndex, mapping, arrayOfState, outputObservableArray, outputArray) {
|
||||
// Retain the existing mapped value if this is a move, otherwise perform mapping
|
||||
var isMoved = typeof diffEntry.moved === 'number',
|
||||
stateItem = isMoved ?
|
||||
movedStateItems[diffEntry.moved] :
|
||||
new StateItem(ko, diffEntry.value, stateArrayIndex, outputArrayIndex, mapping, arrayOfState, outputObservableArray);
|
||||
arrayOfState.splice(stateArrayIndex, 0, stateItem);
|
||||
if (stateItem.isIncluded) {
|
||||
outputArray.splice(outputArrayIndex, 0, stateItem.mappedValueComputed.peek());
|
||||
}
|
||||
|
||||
// Update indexes
|
||||
if (isMoved) {
|
||||
// We don't change the index until *after* updating this item's position in outputObservableArray,
|
||||
// because changing the index may trigger re-mapping, which in turn would cause the new
|
||||
// value to be written to the 'index' position in the output array
|
||||
stateItem.stateArrayIndex = stateArrayIndex;
|
||||
stateItem.setOutputArrayIndexSilently(outputArrayIndex);
|
||||
}
|
||||
|
||||
return stateItem;
|
||||
}
|
||||
|
||||
function deleteOutputItem(diffEntry, arrayOfState, stateArrayIndex, outputArrayIndex, outputArray) {
|
||||
var stateItem = arrayOfState.splice(stateArrayIndex, 1)[0];
|
||||
if (stateItem.isIncluded) {
|
||||
outputArray.splice(outputArrayIndex, 1);
|
||||
}
|
||||
if (typeof diffEntry.moved !== 'number') {
|
||||
// Be careful to dispose only if this item really was deleted and not moved
|
||||
stateItem.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
function updateRetainedOutputItem(stateItem, stateArrayIndex, outputArrayIndex) {
|
||||
// Just have to update its indexes
|
||||
stateItem.stateArrayIndex = stateArrayIndex;
|
||||
stateItem.setOutputArrayIndexSilently(outputArrayIndex);
|
||||
|
||||
// Return the new value for outputArrayIndex
|
||||
return outputArrayIndex + (stateItem.isIncluded ? 1 : 0);
|
||||
}
|
||||
|
||||
function makeLookupOfMovedStateItems(diff, arrayOfState) {
|
||||
// Before we mutate arrayOfComputedMappedValues at all, grab a reference to each moved item
|
||||
var movedStateItems = {};
|
||||
for (var diffIndex = 0; diffIndex < diff.length; diffIndex++) {
|
||||
var diffEntry = diff[diffIndex];
|
||||
if (diffEntry.status === 'added' && (typeof diffEntry.moved === 'number')) {
|
||||
movedStateItems[diffEntry.moved] = arrayOfState[diffEntry.moved];
|
||||
}
|
||||
}
|
||||
return movedStateItems;
|
||||
}
|
||||
|
||||
function getFirstModifiedOutputIndex(firstDiffEntry, arrayOfState, outputArray) {
|
||||
// Work out where the first edit will affect the output array
|
||||
// Then we can update outputArrayIndex incrementally while walking the diff list
|
||||
if (!outputArray.length || !arrayOfState[firstDiffEntry.index]) {
|
||||
// The first edit is beyond the end of the output or state array, so we must
|
||||
// just be appending items.
|
||||
return outputArray.length;
|
||||
} else {
|
||||
// The first edit corresponds to an existing state array item, so grab
|
||||
// the first output array index from it.
|
||||
return arrayOfState[firstDiffEntry.index].outputArrayIndex.peek();
|
||||
}
|
||||
}
|
||||
|
||||
function respondToArrayStructuralChanges(ko, inputObservableArray, arrayOfState, outputArray, outputObservableArray, mapping) {
|
||||
return inputObservableArray.subscribe(function(diff) {
|
||||
if (!diff.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var movedStateItems = makeLookupOfMovedStateItems(diff, arrayOfState),
|
||||
diffIndex = 0,
|
||||
diffEntry = diff[0],
|
||||
editOffset = 0, // A running total of (num(items added) - num(items deleted)) not accounting for filtering
|
||||
outputArrayIndex = diffEntry && getFirstModifiedOutputIndex(diffEntry, arrayOfState, outputArray);
|
||||
|
||||
// Now iterate over the state array, at each stage checking whether the current item
|
||||
// is the next one to have been edited. We can skip all the state array items whose
|
||||
// indexes are less than the first edit index (i.e., diff[0].index).
|
||||
for (var stateArrayIndex = diffEntry.index; diffEntry || (stateArrayIndex < arrayOfState.length); stateArrayIndex++) {
|
||||
// Does the current diffEntry correspond to this position in the state array?
|
||||
if (getDiffEntryPostOperationIndex(diffEntry, editOffset) === stateArrayIndex) {
|
||||
// Yes - insert or delete the corresponding state and output items
|
||||
switch (diffEntry.status) {
|
||||
case 'added':
|
||||
// Add to output, and update indexes
|
||||
var stateItem = insertOutputItem(ko, diffEntry, movedStateItems, stateArrayIndex, outputArrayIndex, mapping, arrayOfState, outputObservableArray, outputArray);
|
||||
if (stateItem.isIncluded) {
|
||||
outputArrayIndex++;
|
||||
}
|
||||
editOffset++;
|
||||
break;
|
||||
case 'deleted':
|
||||
// Just erase from the output, and update indexes
|
||||
deleteOutputItem(diffEntry, arrayOfState, stateArrayIndex, outputArrayIndex, outputArray);
|
||||
editOffset--;
|
||||
stateArrayIndex--; // To compensate for the "for" loop incrementing it
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unknown diff status: ' + diffEntry.status);
|
||||
}
|
||||
|
||||
// We're done with this diff entry. Move on to the next one.
|
||||
diffIndex++;
|
||||
diffEntry = diff[diffIndex];
|
||||
} else if (stateArrayIndex < arrayOfState.length) {
|
||||
// No - the current item was retained. Just update its index.
|
||||
outputArrayIndex = updateRetainedOutputItem(arrayOfState[stateArrayIndex], stateArrayIndex, outputArrayIndex);
|
||||
}
|
||||
}
|
||||
|
||||
outputObservableArray.valueHasMutated();
|
||||
}, null, 'arrayChange');
|
||||
}
|
||||
|
||||
// Mapping
|
||||
function observableArrayMap(ko, mapping) {
|
||||
var inputObservableArray = this,
|
||||
arrayOfState = [],
|
||||
outputArray = [],
|
||||
outputObservableArray = ko.observableArray(outputArray),
|
||||
originalInputArrayContents = inputObservableArray.peek();
|
||||
|
||||
// Initial state: map each of the inputs
|
||||
for (var i = 0; i < originalInputArrayContents.length; i++) {
|
||||
var inputItem = originalInputArrayContents[i],
|
||||
stateItem = new StateItem(ko, inputItem, i, outputArray.length, mapping, arrayOfState, outputObservableArray),
|
||||
mappedValue = stateItem.mappedValueComputed.peek();
|
||||
arrayOfState.push(stateItem);
|
||||
|
||||
if (stateItem.isIncluded) {
|
||||
outputArray.push(mappedValue);
|
||||
}
|
||||
}
|
||||
|
||||
// If the input array changes structurally (items added or removed), update the outputs
|
||||
var inputArraySubscription = respondToArrayStructuralChanges(ko, inputObservableArray, arrayOfState, outputArray, outputObservableArray, mapping);
|
||||
|
||||
// Return value is a readonly computed which can track its own changes to permit chaining.
|
||||
// When disposed, it cleans up everything it created.
|
||||
var returnValue = ko.computed(outputObservableArray).extend({ trackArrayChanges: true }),
|
||||
originalDispose = returnValue.dispose;
|
||||
returnValue.dispose = function() {
|
||||
inputArraySubscription.dispose();
|
||||
ko.utils.arrayForEach(arrayOfState, function(stateItem) {
|
||||
stateItem.dispose();
|
||||
});
|
||||
originalDispose.call(this, arguments);
|
||||
};
|
||||
|
||||
// Make projections chainable
|
||||
addProjectionFunctions(ko, returnValue);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
// Filtering
|
||||
function observableArrayFilter(ko, predicate) {
|
||||
return observableArrayMap.call(this, ko, function(item) {
|
||||
return predicate(item) ? item : exclusionMarker;
|
||||
});
|
||||
}
|
||||
|
||||
// Attaching projection functions
|
||||
// ------------------------------
|
||||
//
|
||||
// Builds a collection of projection functions that can quickly be attached to any object.
|
||||
// The functions are predefined to retain 'this' and prefix the arguments list with the
|
||||
// relevant 'ko' instance.
|
||||
|
||||
var projectionFunctionsCacheName = '_ko.projections.cache';
|
||||
|
||||
function attachProjectionFunctionsCache(ko) {
|
||||
// Wraps callback so that, when invoked, its arguments list is prefixed by 'ko' and 'this'
|
||||
function makeCaller(ko, callback) {
|
||||
return function() {
|
||||
return callback.apply(this, [ko].concat(Array.prototype.slice.call(arguments, 0)));
|
||||
};
|
||||
}
|
||||
ko[projectionFunctionsCacheName] = {
|
||||
map: makeCaller(ko, observableArrayMap),
|
||||
filter: makeCaller(ko, observableArrayFilter)
|
||||
};
|
||||
}
|
||||
|
||||
function addProjectionFunctions(ko, target) {
|
||||
ko.utils.extend(target, ko[projectionFunctionsCacheName]);
|
||||
return target; // Enable chaining
|
||||
}
|
||||
|
||||
// Module initialisation
|
||||
// ---------------------
|
||||
//
|
||||
// When this script is first evaluated, it works out what kind of module loading scenario
|
||||
// it is in (Node.js or a browser `<script>` tag), and then attaches itself to whichever
|
||||
// instance of Knockout.js it can find.
|
||||
|
||||
function attachToKo(ko) {
|
||||
ko.projections = {
|
||||
_exclusionMarker: exclusionMarker
|
||||
};
|
||||
attachProjectionFunctionsCache(ko);
|
||||
addProjectionFunctions(ko, ko.observableArray.fn); // Make all observable arrays projectable
|
||||
}
|
||||
|
||||
// Determines which module loading scenario we're in, grabs dependencies, and attaches to KO
|
||||
function prepareExports() {
|
||||
if (typeof module !== 'undefined') {
|
||||
// Node.js case - load KO synchronously
|
||||
var ko = require('knockout');
|
||||
attachToKo(ko);
|
||||
module.exports = ko;
|
||||
} else if ('ko' in global) {
|
||||
// Non-module case - attach to the global instance
|
||||
attachToKo(global.ko);
|
||||
}
|
||||
}
|
||||
|
||||
prepareExports();
|
||||
|
||||
})(this);
|
||||
10
vendors/knockout-projections/knockout-projections-1.0.0.min.js
vendored
Normal file
10
vendors/knockout-projections/knockout-projections-1.0.0.min.js
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/*! Knockout projections plugin
|
||||
------------------------------------------------------------------------------
|
||||
Copyright (c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
!function(a){"use strict";function b(a,b,c,d,e,f,g){this.inputItem=b,this.stateArrayIndex=c,this.mapping=e,this.arrayOfState=f,this.outputObservableArray=g,this.outputArray=this.outputObservableArray.peek(),this.isIncluded=null,this.suppressNotification=!1,this.outputArrayIndex=a.observable(d),this.mappedValueComputed=a.computed(this.mappingEvaluator,this),this.mappedValueComputed.subscribe(this.onMappingResultChanged,this),this.previousMappedValue=this.mappedValueComputed.peek()}function c(a,b){if(!a)return null;switch(a.status){case"added":return a.index;case"deleted":return a.index+b;default:throw new Error("Unknown diff status: "+a.status)}}function d(a,c,d,e,f,g,h,i,j){var k="number"==typeof c.moved,l=k?d[c.moved]:new b(a,c.value,e,f,g,h,i);return h.splice(e,0,l),l.isIncluded&&j.splice(f,0,l.mappedValueComputed.peek()),k&&(l.stateArrayIndex=e,l.setOutputArrayIndexSilently(f)),l}function e(a,b,c,d,e){var f=b.splice(c,1)[0];f.isIncluded&&e.splice(d,1),"number"!=typeof a.moved&&f.dispose()}function f(a,b,c){return a.stateArrayIndex=b,a.setOutputArrayIndexSilently(c),c+(a.isIncluded?1:0)}function g(a,b){for(var c={},d=0;d<a.length;d++){var e=a[d];"added"===e.status&&"number"==typeof e.moved&&(c[e.moved]=b[e.moved])}return c}function h(a,b,c){return c.length&&b[a.index]?b[a.index].outputArrayIndex.peek():c.length}function i(a,b,i,j,k,l){return b.subscribe(function(b){if(b.length){for(var m=g(b,i),n=0,o=b[0],p=0,q=o&&h(o,i,j),r=o.index;o||r<i.length;r++)if(c(o,p)===r){switch(o.status){case"added":var s=d(a,o,m,r,q,l,i,k,j);s.isIncluded&&q++,p++;break;case"deleted":e(o,i,r,q,j),p--,r--;break;default:throw new Error("Unknown diff status: "+o.status)}n++,o=b[n]}else r<i.length&&(q=f(i[r],r,q));k.valueHasMutated()}},null,"arrayChange")}function j(a,c){for(var d=this,e=[],f=[],g=a.observableArray(f),h=d.peek(),j=0;j<h.length;j++){var k=h[j],l=new b(a,k,j,f.length,c,e,g),n=l.mappedValueComputed.peek();e.push(l),l.isIncluded&&f.push(n)}var o=i(a,d,e,f,g,c),p=a.computed(g).extend({trackArrayChanges:!0}),q=p.dispose;return p.dispose=function(){o.dispose(),a.utils.arrayForEach(e,function(a){a.dispose()}),q.call(this,arguments)},m(a,p),p}function k(a,b){return j.call(this,a,function(a){return b(a)?a:p})}function l(a){function b(a,b){return function(){return b.apply(this,[a].concat(Array.prototype.slice.call(arguments,0)))}}a[q]={map:b(a,j),filter:b(a,k)}}function m(a,b){return a.utils.extend(b,a[q]),b}function n(a){a.projections={_exclusionMarker:p},l(a),m(a,a.observableArray.fn)}function o(){if("undefined"!=typeof module){var b=require("knockout");n(b),module.exports=b}else"ko"in a&&n(a.ko)}var p={};b.prototype.dispose=function(){this.mappedValueComputed.dispose()},b.prototype.mappingEvaluator=function(){var a=this.mapping(this.inputItem,this.outputArrayIndex),b=a!==p;return this.isIncluded!==b&&(null!==this.isIncluded&&this.moveSubsequentItemsBecauseInclusionStateChanged(b),this.isIncluded=b),a},b.prototype.onMappingResultChanged=function(a){a!==this.previousMappedValue&&(this.isIncluded&&this.outputArray.splice(this.outputArrayIndex.peek(),1,a),this.suppressNotification||this.outputObservableArray.valueHasMutated(),this.previousMappedValue=a)},b.prototype.moveSubsequentItemsBecauseInclusionStateChanged=function(a){var b,c,d=this.outputArrayIndex.peek();if(a)for(this.outputArray.splice(d,0,null),b=this.stateArrayIndex+1;b<this.arrayOfState.length;b++)c=this.arrayOfState[b],c.setOutputArrayIndexSilently(c.outputArrayIndex.peek()+1);else for(this.outputArray.splice(d,1),b=this.stateArrayIndex+1;b<this.arrayOfState.length;b++)c=this.arrayOfState[b],c.setOutputArrayIndexSilently(c.outputArrayIndex.peek()-1)},b.prototype.setOutputArrayIndexSilently=function(a){this.suppressNotification=!0,this.outputArrayIndex(a),this.suppressNotification=!1};var q="_ko.projections.cache";o()}(this);
|
||||
29
vendors/knockout-projections/package.json
vendored
Normal file
29
vendors/knockout-projections/package.json
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"name": "knockout-projections",
|
||||
"version": "1.0.0",
|
||||
"description": "Knockout.js observable arrays get smarter",
|
||||
"main": "knockout-projections.js",
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"dependencies": {
|
||||
"knockout": "~3.0.0",
|
||||
"jasmine-reporters": "~0.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-contrib-jshint": "~0.4.3",
|
||||
"grunt-contrib-uglify": "~0.2.0",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-watch": "~0.4.3",
|
||||
"grunt-jasmine-node": "~0.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": "",
|
||||
"author": "Microsoft Corporation",
|
||||
"licenses" : [
|
||||
{ "type" : "Apache 2.0", "url" : "http://www.apache.org/licenses/LICENSE-2.0.html" }
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue