OLD | NEW |
| (Empty) |
1 <!-- | |
2 Copyright 2014 The Chromium Authors. All rights reserved. | |
3 Use of this source code is governed by a BSD-style license that can be | |
4 found in the LICENSE file. | |
5 --> | |
6 | |
7 <link rel="import" href="sugar.html"> | |
8 | |
9 <script> | |
10 | |
11 var updateUtil = updateUtil || {}; | |
12 | |
13 (function () { | |
14 'use strict'; | |
15 | |
16 // Returns true if |updateLeft| can do a field-wise merge from |source| to |targ
et|. | |
17 // We assume |target| and |source| have the same type. | |
18 // If they're arrays, true if the elements have a |key| property. | |
19 // If they're objects, true if they're not null. (null should be assigned). | |
20 // Otherwise, false. | |
21 function canUpdateLeft(target, source) { | |
22 if (Array.isArray(target)) { | |
23 // If |source| is empty, we'll return an empty array regardless. | |
24 return source.length !== 0 && source[0].key !== undefined; | |
25 } else if (target === null || source === null) { | |
26 return false; | |
27 } else if (typeof target === 'object') { | |
28 return true; | |
29 } | |
30 return false; | |
31 }; | |
32 | |
33 // |target| and |source| must have the same type, which must return true from | |
34 // canUpdateLeft() (see above). An array is treated like a dictionary where the | |
35 // key of an object is its |key| property, except that no effort is made to | |
36 // preserve the object identity of arrays. This function will: | |
37 // | |
38 // * Ignore elements listed in an object's constructor's |transientProperties|
array. | |
39 // * Remove elements from |target| whose key isn't in |source|. | |
40 // * Copy elements from |source| whose key isn't in |target| or which are !canU
pdateLeft(). | |
41 // In particular, we copy |null| rather than trying to merge it. | |
42 // * If a matching element defines an |updateLeft| method, call that to let typ
es customize the update process. | |
43 // This method must return the updated object. | |
44 // * Call updateLeft recursively for other matching elements. | |
45 // | |
46 // You have to call this as "target = updateLeft(target, source);" because it | |
47 // won't always update |target| in-place. | |
48 updateUtil.updateLeft = function(target, source) | |
49 { | |
50 if (!canUpdateLeft(target, source)) { | |
51 return source; | |
52 } | |
53 | |
54 if (target.updateLeft) { | |
55 return target.updateLeft(source); | |
56 } | |
57 | |
58 if (Array.isArray(target)) { | |
59 return updateLeftArray(target, source); | |
60 } else { | |
61 return updateLeftObject(target, source); | |
62 } | |
63 }; | |
64 | |
65 // |target| and |source| must be arrays of objects with a |key| property. | |
66 function updateLeftArray(target, source) { | |
67 var oldElemByKey = {}; | |
68 target.forEach(function(elem) { | |
69 oldElemByKey[elem.key] = elem; | |
70 }) | |
71 // Polymer doesn't pay attention to array identity when deciding to recreate | |
72 // elements, just object identity. | |
73 return source.map(function(value) { | |
74 return updateUtil.updateLeft(oldElemByKey[value.key], value); | |
75 }); | |
76 }; | |
77 | |
78 // |target| and |source| must be objects. |target|'s properties will be updated | |
79 // to match |source|'s except for properties listed in its constructor's | |
80 // |transientProperties| array. | |
81 function updateLeftObject(target, source) { | |
82 // Prepare to filter out properties that reflect local UI | |
83 // state that wasn't loaded from the server. | |
84 var transientProperties = target.constructor.transientProperties; | |
85 function isTransientProperty(name) { | |
86 return transientProperties && transientProperties.indexOf(name) !== -1; | |
87 }; | |
88 | |
89 // Remove elements from |target| that aren't in |source|. | |
90 Object.keys(target, function(key) { | |
91 if (!source.hasOwnProperty(key) && !isTransientProperty(key)) | |
92 delete target[key]; | |
93 }); | |
94 | |
95 // Recursively update or assign properties that are in |source|. | |
96 Object.keys(source, function(key, sourceValue) { | |
97 if (!isTransientProperty(key)) | |
98 target[key] = updateUtil.updateLeft(target[key], source[key]); | |
99 }); | |
100 return target; | |
101 }; | |
102 | |
103 })(); | |
104 | |
105 </script> | |
OLD | NEW |