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 |