mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-03 19:45:44 -05:00
Implement a new strategy for importing JSON, where it is imported into the item itself, not its children list, if the class match.
This commit is contained in:
parent
70ae7486e9
commit
c76dae5b06
2 changed files with 40 additions and 28 deletions
|
@ -390,46 +390,51 @@ Base.inject(/** @lends Base# */{
|
||||||
* deserializable types through Base.exports, and the values following
|
* deserializable types through Base.exports, and the values following
|
||||||
* in the array are the arguments to their initialize function.
|
* in the array are the arguments to their initialize function.
|
||||||
* Any other value is passed on unmodified.
|
* Any other value is passed on unmodified.
|
||||||
* The passed data is recoursively traversed and converted, leaves first
|
* The passed json data is recoursively traversed and converted, leaves
|
||||||
|
* first
|
||||||
*/
|
*/
|
||||||
deserialize: function(obj, data) {
|
deserialize: function(json, target, _data) {
|
||||||
var res = obj;
|
var res = json;
|
||||||
// A data side-car to deserialize that can hold any kind of 'global'
|
// A _data side-car to deserialize that can hold any kind of
|
||||||
// data across a deserialization. It's currently just used to hold
|
// 'global' data across a deserialization. It's currently only used
|
||||||
// dictionary definitions.
|
// to hold dictionary definitions.
|
||||||
data = data || {};
|
_data = _data || {};
|
||||||
if (Array.isArray(obj)) {
|
if (Array.isArray(json)) {
|
||||||
// See if it's a serialized type. If so, the rest of the array
|
// See if it's a serialized type. If so, the rest of the array
|
||||||
// are the arguments to #initialize(). Either way, we simply
|
// are the arguments to #initialize(). Either way, we simply
|
||||||
// deserialize all elements of the array.
|
// deserialize all elements of the array.
|
||||||
var type = obj[0],
|
var type = json[0],
|
||||||
// Handle stored dictionary specially, since we need to
|
// Handle stored dictionary specially, since we need to
|
||||||
// keep is a lookup table to retrieve referenced items from.
|
// keep is a lookup table to retrieve referenced items from.
|
||||||
isDictionary = type === 'dictionary';
|
isDictionary = type === 'dictionary';
|
||||||
if (!isDictionary) {
|
if (!isDictionary) {
|
||||||
// First see if this is perhaps a dictionary reference, and
|
// First see if this is perhaps a dictionary reference, and
|
||||||
// if so return its definition instead.
|
// if so return its definition instead.
|
||||||
if (data.dictionary && obj.length == 1 && /^#/.test(type))
|
if (_data.dictionary && json.length == 1 && /^#/.test(type))
|
||||||
return data.dictionary[type];
|
return _data.dictionary[type];
|
||||||
type = Base.exports[type];
|
type = Base.exports[type];
|
||||||
}
|
}
|
||||||
res = [];
|
res = [];
|
||||||
// Skip first type entry for arguments
|
// Skip first type entry for arguments
|
||||||
for (var i = type ? 1 : 0, l = obj.length; i < l; i++)
|
for (var i = type ? 1 : 0, l = json.length; i < l; i++)
|
||||||
res.push(Base.deserialize(obj[i], data));
|
res.push(Base.deserialize(json[i], null, _data));
|
||||||
if (isDictionary) {
|
if (isDictionary) {
|
||||||
data.dictionary = res[0];
|
_data.dictionary = res[0];
|
||||||
} else if (type) {
|
} else if (type) {
|
||||||
// Create serialized type and pass collected arguments to
|
// Create serialized type and pass collected arguments to
|
||||||
// constructor().
|
// constructor().
|
||||||
var args = res;
|
var args = res;
|
||||||
res = Base.create(type.prototype);
|
// If a target is provided and its of the right type,
|
||||||
|
// import right into it.
|
||||||
|
res = target instanceof type
|
||||||
|
? target
|
||||||
|
: Base.create(type.prototype);
|
||||||
type.apply(res, args);
|
type.apply(res, args);
|
||||||
}
|
}
|
||||||
} else if (Base.isPlainObject(obj)) {
|
} else if (Base.isPlainObject(json)) {
|
||||||
res = {};
|
res = {};
|
||||||
for (var key in obj)
|
for (var key in json)
|
||||||
res[key] = Base.deserialize(obj[key], data);
|
res[key] = Base.deserialize(json[key], null, _data);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
|
@ -438,9 +443,9 @@ Base.inject(/** @lends Base# */{
|
||||||
return JSON.stringify(Base.serialize(obj, options));
|
return JSON.stringify(Base.serialize(obj, options));
|
||||||
},
|
},
|
||||||
|
|
||||||
importJSON: function(json) {
|
importJSON: function(json, target) {
|
||||||
return Base.deserialize(
|
return Base.deserialize(
|
||||||
typeof json === 'string' ? JSON.parse(json) : json);
|
typeof json === 'string' ? JSON.parse(json) : json, target);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1306,9 +1306,9 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
// Insert is true by default.
|
// Insert is true by default.
|
||||||
if (insert || insert === undefined)
|
if (insert || insert === undefined)
|
||||||
copy.insertAbove(this);
|
copy.insertAbove(this);
|
||||||
// Only copy over these fields if they are actually defined in 'this'
|
// Only copy over these fields if they are actually defined in 'this',
|
||||||
// TODO: Consider moving this to Base once it's useful in more than one
|
// meaning the default value has been overwritten (default is on
|
||||||
// place
|
// prototype).
|
||||||
var keys = ['_locked', '_visible', '_blendMode', '_opacity',
|
var keys = ['_locked', '_visible', '_blendMode', '_opacity',
|
||||||
'_clipMask', '_guide'];
|
'_clipMask', '_guide'];
|
||||||
for (var i = 0, l = keys.length; i < l; i++) {
|
for (var i = 0, l = keys.length; i < l; i++) {
|
||||||
|
@ -1649,15 +1649,22 @@ var Item = Base.extend(Callback, /** @lends Item# */{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports (deserializes) the stored JSON data into this item's
|
* Imports (deserializes) the stored JSON data into this item. If the data
|
||||||
* {@link Item#children} list.
|
* describes an item of the same class or a parent class of the item, the
|
||||||
* Note that the item is not cleared first. You can call
|
* data is imported into the item itself. If not, the imported item is added
|
||||||
* {@link Item#removeChildren()} to do so.
|
* to this item's {@link Item#children} list. Note that not all type of
|
||||||
|
* items can have children.
|
||||||
*
|
*
|
||||||
* @param {String} json the JSON data to import from.
|
* @param {String} json the JSON data to import from.
|
||||||
*/
|
*/
|
||||||
importJSON: function(json) {
|
importJSON: function(json) {
|
||||||
return this.addChild(Base.importJSON(json));
|
// Try importing into `this`. If another item is returned, try adding
|
||||||
|
// it as a child (this won't be successful on some classes, returning
|
||||||
|
// null).
|
||||||
|
var res = Base.importJSON(json, this);
|
||||||
|
return res !== this
|
||||||
|
? this.addChild(res)
|
||||||
|
: res;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue