<commit_before>
var _Deserializer = (function () {
    /**
     * @param {boolean} isEditor - if false, property with Fire.EditorOnly will be discarded
     */
    function _Deserializer(jsonObj, result, target, isEditor, classFinder) {
        this._editor = isEditor;
        this._classFinder = classFinder;
        // @ifndef PLAYER
        this._target = target;
        // @endif
        this._idList = [];
        this._idObjList = [];
        this._idPropList = [];
        this.result = result || new Fire._DeserializeInfo();

        if (Array.isArray(jsonObj)) {
            var jsonArray = jsonObj;
            var refCount = jsonArray.length;
            this.deserializedList = new Array(refCount);
            // deserialize
            for (var i = 0; i < refCount; i++) {
                if (jsonArray[i]) {
                    var mainTarget;
                    // @ifndef PLAYER
                    mainTarget = (i === 0 && target);
                    // @endif
                    this.deserializedList[i] = _deserializeObject(this, jsonArray[i], mainTarget);
                }
            }
            this.deserializedData = refCount > 0 ? this.deserializedList[0] : [];

            //// callback
            //for (var j = 0; j < refCount; j++) {
            //    if (referencedList[j].onAfterDeserialize) {
            //        referencedList[j].onAfterDeserialize();
            //    }
            //}
        }
        else {
            this.deserializedList = [null];
            this.deserializedData = jsonObj ? _deserializeObject(this, jsonObj, target) : null;
            this.deserializedList[0] = this.deserializedData;

            //// callback
            //if (deserializedData.onAfterDeserialize) {
            //    deserializedData.onAfterDeserialize();
            //}
        }

        // dereference
        _dereference(this);
    }

    var _dereference = function (self) {
        // 这里不采用遍历反序列化结果的方式，因为反序列化的结果如果引用到复杂的外部库，很容易堆栈溢出。
        var deserializedList = self.deserializedList;
        for (var i = 0, len = self._idList.length; i < len; i++) {
            var propName = self._idPropList[i];
            var id = self._idList[i];
            self._idObjList[i][propName] = deserializedList[id];
        }
    };

    // 和 _deserializeObject 不同的地方在于会判断 id 和 uuid
    function _deserializeObjField (self, obj, jsonObj, propName, target) {
        var id = jsonObj.__id__;
        if (typeof id === 'undefined') {
            var uuid = jsonObj.__uuid__;
            if (uuid) {
                // @ifndef PLAYER
                // 这里不做任何操作，因为有可能调用者需要知道依赖哪些 asset。
                // 调用者使用 uuidList 时，可以判断 obj[propName] 是否为空，为空则表示待进一步加载，
                // 不为空则只是表明依赖关系。
                //if (target && target[propName] && target[propName]._uuid === uuid) {
                //    console.assert(obj[propName] === target[propName]);
                //    return;
                //}
                // @endif
                self.result.uuidList.push(uuid);
                self.result.uuidObjList.push(obj);
                self.result.uuidPropList.push(propName);
            }
            else {
                // @ifdef PLAYER
                obj[propName] = _deserializeObject(self, jsonObj);
                // @endif
                // @ifndef PLAYER
                obj[propName] = _deserializeObject(self, jsonObj, target && target[propName]);
                // @endif
            }
        }
        else {
            var dObj = self.deserializedList[id];
            if (dObj) {
                obj[propName] = dObj;
            }
            else {
                self._idList.push(id);
                self._idObjList.push(obj);
                self._idPropList.push(propName);
            }
        }
    }

    function _deserializePrimitiveObject (self, instance, serialized) {
        for (var propName in serialized) {
            if (serialized.hasOwnProperty(propName)) {
                var prop = serialized[propName];
                if (typeof prop !== 'object') {
                    if (propName !== '__type__'/* && k != '__id__'*/) {
                        instance[propName] = prop;
                    }
                }
                else {
                    if (prop) {
                        if ( !prop.__uuid__ && typeof prop.__id__ === 'undefined' ) {
                            // @ifdef PLAYER
                            instance[propName] = _deserializeObject(self, prop);
                            // @endif
                            // @ifndef PLAYER
                            instance[propName] = _deserializeObject(self, prop, self._target && instance[propName]);
                            // @endif
                        }
                        else {
                            // @ifdef PLAYER
                            _deserializeObjField(self, instance, prop, propName);
                            // @endif
                            // @ifndef PLAYER
                            _deserializeObjField(self, instance, prop, propName, self._target && instance);
                            // @endif
                        }
                    }
                    else {
                        instance[propName] = null;
                    }
                }
            }
        }
    }

    function _deserializeTypedObject (self, instance, serialized) {
        //++self.stackCounter;
        //if (self.stackCounter === 100) {
        //    debugger;
        //}
        for (var propName in instance) {    // 遍历 instance，如果具有类型，才不会把 __type__ 也读进来
            var prop = serialized[propName];
            if (typeof prop !== 'undefined' && serialized.hasOwnProperty(propName)) {
                if (typeof prop !== 'object') {
                    instance[propName] = prop;
                }
                else {
                    if (prop) {
                        if ( !prop.__uuid__ && typeof prop.__id__ === 'undefined' ) {
                            // @ifdef PLAYER
                            instance[propName] = _deserializeObject(self, prop);
                            // @endif
                            // @ifndef PLAYER
                            instance[propName] = _deserializeObject(self, prop, self._target && instance[propName]);
                            // @endif
                        }
                        else {
                            // @ifdef PLAYER
                            _deserializeObjField(self, instance, prop, propName);
                            // @endif
                            // @ifndef PLAYER
                            _deserializeObjField(self, instance, prop, propName, self._target && instance);
                            // @endif
                        }
                    }
                    else {
                        instance[propName] = null;
                    }
                }
            }
        }
        //--self.stackCounter;
    }

    function _deserializeFireClass(self, obj, serialized, klass, target) {
        var props = klass.__props__;
        if (!props) {
            return;
        }
        for (var p = 0; p < props.length; p++) {
            var propName = props[p];
            var attrs = Fire.attr(klass, propName);
            // assume all prop in __props__ must have attr
            var rawType = attrs.rawType;
            if (!rawType) {
                if (attrs.serializable === false) {
                    continue;   // skip nonSerialized
                }
                if (!self._editor && attrs.editorOnly) {
                    continue;   // skip editor only if not editor
                }
                var prop = serialized[propName];
                if (typeof prop !== 'undefined') {
                    if (typeof prop !== 'object') {
                        obj[propName] = prop;
                    }
                    else {
                        if (prop) {
                            if (!prop.__uuid__ && typeof prop.__id__ === 'undefined') {
                                // @ifdef PLAYER
                                obj[propName] = _deserializeObject(self, prop);
                                // @endif
                                // @ifndef PLAYER
                                obj[propName] = _deserializeObject(self, prop, target && target[propName]);
                                // @endif
                            }
                            else {
                                // @ifdef PLAYER
                                _deserializeObjField(self, obj, prop, propName);
                                // @endif
                                // @ifndef PLAYER
                                _deserializeObjField(self, obj, prop, propName, target && obj);
                                // @endif
                            }
                        }
                        else {
                            obj[propName] = null;
                        }
                    }
                }
            }
            else {
                // always load raw objects even if property not serialized
                if (self.result.rawProp) {
                    Fire.error('not support multi raw object in a file');
                    // 这里假定每个asset都有uuid，每个json只能包含一个asset，只能包含一个rawProp
                }
                self.result.rawProp = propName;
            }
        }
        if (props[props.length - 1] === '_$erialized') {
            // save original serialized data
            obj._$erialized = serialized;
            // parse the serialized data as primitive javascript object, so its __id__ will be dereferenced
            _deserializePrimitiveObject(self, obj._$erialized, serialized);
        }
    }

    /**
     * @param {object} serialized - The obj to deserialize, must be non-nil
     * @param {object} [target=null]
     */
    var _deserializeObject = function (self, serialized, target) {
        var propName, prop;
        var obj = null;     // the obj to return
        var klass = null;
        if (serialized.__type__) {

            // Type Object (including FireClass)

            klass = self._classFinder(serialized.__type__);
            if (!klass) {
                Fire.error('[Fire.deserialize] unknown type: ' + serialized.__type__);
                return null;
            }
            // @ifdef PLAYER
            // instantiate a new object
            obj = new klass();
            // @endif
            // @ifndef PLAYER
            if (target) {
                // use target
                if ( !(target instanceof klass) ) {
                    Fire.warn('Type of target to deserialize not matched with data: target is %s, data is %s',
                               JS.getClassName(target), klass);
                }
                obj = target;
            }
            else {
                obj = new klass();
            }
            // @endif

            if ( Fire._isFireClass(klass) ) {
                _deserializeFireClass(self, obj, serialized, klass, target);
            }
            else {
                _deserializeTypedObject(self, obj, serialized);
            }
        }
        else if ( !Array.isArray(serialized) ) {

            // embedded primitive javascript object

            // @ifdef PLAYER
            obj = {};
            // @endif
            // @ifndef PLAYER
            obj = target || {};
            // @endif

            _deserializePrimitiveObject(self, obj, serialized);
        }
        else {

            // Array

            // @ifdef PLAYER
            obj = new Array(serialized.length);
            // @endif
            // @ifndef PLAYER
            if (target) {
                target.length = serialized.length;
                obj = target;
            }
            else {
                obj = new Array(serialized.length);
            }
            // @endif
            for (var i = 0; i < serialized.length; i++) {
                prop = serialized[i];
                if (typeof prop === 'object' && prop) {
                    if (!prop.__uuid__ && typeof prop.__id__ === 'undefined') {
                        // @ifdef PLAYER
                        obj[i] = _deserializeObject(self, prop);
                        // @endif
                        // @ifndef PLAYER
                        obj[i] = _deserializeObject(self, prop, target && target[i]);
                        // @endif
                    }
                    else {
                        // @ifdef PLAYER
                        _deserializeObjField(self, obj, prop, '' + i);
                        // @endif
                        // @ifndef PLAYER
                        _deserializeObjField(self, obj, prop, '' + i, target && target[i]);
                        // @endif
                    }
                }
                else {
                    obj[i] = prop;
                }
            }
        }
        return obj;
    };

    return _Deserializer;
})();

/**
 * Deserialize json to Fire.Asset
 * 当指定了 target 选项时，如果 target 引用的其它 asset 的 uuid 不变，则不会改变 target 对 asset 的引用，
 * 也不会将 uuid 保存到 result 对象中。
 *
 * @param {(string|object)} data - the serialized Fire.Asset json string or json object.
 *                                 Note: If data is an object, it will be modified.
 * @param {Fire._DeserializeInfo} [result] - additional loading result
 * @param {object} [options=null]
 * @return {object} the main data(asset)
 */
Fire.deserialize = function (data, result, options) {
    var isEditor = (options && 'isEditor' in options) ? options.isEditor : Fire.isEditor;
    var classFinder = (options && options.classFinder) || JS._getClassById;
    var createAssetRefs = (options && options.createAssetRefs) || Fire.isEditorCore;
    var target;
    // @ifndef PLAYER
    target = (options && options.target);
    // @endif

    // @ifndef PLAYER
    if (Fire.isNode && Buffer.isBuffer(data)) {
        data = data.toString();
    }
    // @endif

    if (typeof data === 'string') {
        data = JSON.parse(data);
    }

    if (createAssetRefs && !result) {
        result = new Fire._DeserializeInfo();
    }

    Fire._isCloning = true;
    var deserializer = new _Deserializer(data, result, target, isEditor, classFinder);
    Fire._isCloning = false;

    if (createAssetRefs) {
        result.assignAssetsBy(Fire.serialize.asAsset);
    }

    return deserializer.deserializedData;
};

/**
 * 包含反序列化时的一些信息
 * @class Fire._DeserializeInfo
 */
Fire._DeserializeInfo = function () {

    //this.urlList = [];
    //this.callbackList = [];

    // uuids(assets) need to load

    /**
     * @property {string[]} uuidList - list of the depends assets' uuid
     */
    this.uuidList = [];
    /**
     * @property {object[]} uuidObjList - the obj list whose field needs to load asset by uuid
     */
    this.uuidObjList = [];
    /**
     * @property {string[]} uuidPropList - the corresponding field name which referenced to the asset
     */
    this.uuidPropList = [];

    // raw objects need to load
    // (不用存rawList因为它的uuid可以从asset上获得)

    /**
     * @property {string} rawProp - the corresponding field name which referenced to the raw object
     */
    this.rawProp = '';
    ///**
    // * @property {Fire.Asset[]} rawObjList - the obj list whose corresponding raw object needs to load
    // */
    //this.rawObjList = [];
    ///**
    // * @property {string[]} rawPropList - the corresponding field name which referenced to the raw object
    // */
    //this.rawPropList = [];
};

Fire._DeserializeInfo.prototype.reset = function () {
    this.uuidList.length = 0;
    this.uuidObjList.length = 0;
    this.uuidPropList.length = 0;
    this.rawProp = '';
    //this.rawObjList.length = 0;
    //this.rawPropList.length = 0;
};

Fire._DeserializeInfo.prototype.getUuidOf = function (obj, propName) {
    for (var i = 0; i < this.uuidObjList.length; i++) {
        if (this.uuidObjList[i] === obj && this.uuidPropList[i] === propName) {
            return this.uuidList[i];
        }
    }
    return "";
};

Fire._DeserializeInfo.prototype.assignAssetsBy = function (callback) {
    for (var i = 0, len = this.uuidList.length; i < len; i++) {
        var uuid = this.uuidList[i];
        var asset = callback(uuid);
        if (asset) {
            var obj = this.uuidObjList[i];
            var prop = this.uuidPropList[i];
            obj[prop] = asset;
        }
        else {
            Fire.error('Failed to assign asset: ' + uuid);
        }
    }
};
<commit_msg>update DeserializeInfo.assignAssetsBy<commit_after>
var _Deserializer = (function () {
    /**
     * @param {boolean} isEditor - if false, property with Fire.EditorOnly will be discarded
     */
    function _Deserializer(jsonObj, result, target, isEditor, classFinder) {
        this._editor = isEditor;
        this._classFinder = classFinder;
        // @ifndef PLAYER
        this._target = target;
        // @endif
        this._idList = [];
        this._idObjList = [];
        this._idPropList = [];
        this.result = result || new Fire._DeserializeInfo();

        if (Array.isArray(jsonObj)) {
            var jsonArray = jsonObj;
            var refCount = jsonArray.length;
            this.deserializedList = new Array(refCount);
            // deserialize
            for (var i = 0; i < refCount; i++) {
                if (jsonArray[i]) {
                    var mainTarget;
                    // @ifndef PLAYER
                    mainTarget = (i === 0 && target);
                    // @endif
                    this.deserializedList[i] = _deserializeObject(this, jsonArray[i], mainTarget);
                }
            }
            this.deserializedData = refCount > 0 ? this.deserializedList[0] : [];

            //// callback
            //for (var j = 0; j < refCount; j++) {
            //    if (referencedList[j].onAfterDeserialize) {
            //        referencedList[j].onAfterDeserialize();
            //    }
            //}
        }
        else {
            this.deserializedList = [null];
            this.deserializedData = jsonObj ? _deserializeObject(this, jsonObj, target) : null;
            this.deserializedList[0] = this.deserializedData;

            //// callback
            //if (deserializedData.onAfterDeserialize) {
            //    deserializedData.onAfterDeserialize();
            //}
        }

        // dereference
        _dereference(this);
    }

    var _dereference = function (self) {
        // 这里不采用遍历反序列化结果的方式，因为反序列化的结果如果引用到复杂的外部库，很容易堆栈溢出。
        var deserializedList = self.deserializedList;
        for (var i = 0, len = self._idList.length; i < len; i++) {
            var propName = self._idPropList[i];
            var id = self._idList[i];
            self._idObjList[i][propName] = deserializedList[id];
        }
    };

    // 和 _deserializeObject 不同的地方在于会判断 id 和 uuid
    function _deserializeObjField (self, obj, jsonObj, propName, target) {
        var id = jsonObj.__id__;
        if (typeof id === 'undefined') {
            var uuid = jsonObj.__uuid__;
            if (uuid) {
                // @ifndef PLAYER
                // 这里不做任何操作，因为有可能调用者需要知道依赖哪些 asset。
                // 调用者使用 uuidList 时，可以判断 obj[propName] 是否为空，为空则表示待进一步加载，
                // 不为空则只是表明依赖关系。
                //if (target && target[propName] && target[propName]._uuid === uuid) {
                //    console.assert(obj[propName] === target[propName]);
                //    return;
                //}
                // @endif
                self.result.uuidList.push(uuid);
                self.result.uuidObjList.push(obj);
                self.result.uuidPropList.push(propName);
            }
            else {
                // @ifdef PLAYER
                obj[propName] = _deserializeObject(self, jsonObj);
                // @endif
                // @ifndef PLAYER
                obj[propName] = _deserializeObject(self, jsonObj, target && target[propName]);
                // @endif
            }
        }
        else {
            var dObj = self.deserializedList[id];
            if (dObj) {
                obj[propName] = dObj;
            }
            else {
                self._idList.push(id);
                self._idObjList.push(obj);
                self._idPropList.push(propName);
            }
        }
    }

    function _deserializePrimitiveObject (self, instance, serialized) {
        for (var propName in serialized) {
            if (serialized.hasOwnProperty(propName)) {
                var prop = serialized[propName];
                if (typeof prop !== 'object') {
                    if (propName !== '__type__'/* && k != '__id__'*/) {
                        instance[propName] = prop;
                    }
                }
                else {
                    if (prop) {
                        if ( !prop.__uuid__ && typeof prop.__id__ === 'undefined' ) {
                            // @ifdef PLAYER
                            instance[propName] = _deserializeObject(self, prop);
                            // @endif
                            // @ifndef PLAYER
                            instance[propName] = _deserializeObject(self, prop, self._target && instance[propName]);
                            // @endif
                        }
                        else {
                            // @ifdef PLAYER
                            _deserializeObjField(self, instance, prop, propName);
                            // @endif
                            // @ifndef PLAYER
                            _deserializeObjField(self, instance, prop, propName, self._target && instance);
                            // @endif
                        }
                    }
                    else {
                        instance[propName] = null;
                    }
                }
            }
        }
    }

    function _deserializeTypedObject (self, instance, serialized) {
        //++self.stackCounter;
        //if (self.stackCounter === 100) {
        //    debugger;
        //}
        for (var propName in instance) {    // 遍历 instance，如果具有类型，才不会把 __type__ 也读进来
            var prop = serialized[propName];
            if (typeof prop !== 'undefined' && serialized.hasOwnProperty(propName)) {
                if (typeof prop !== 'object') {
                    instance[propName] = prop;
                }
                else {
                    if (prop) {
                        if ( !prop.__uuid__ && typeof prop.__id__ === 'undefined' ) {
                            // @ifdef PLAYER
                            instance[propName] = _deserializeObject(self, prop);
                            // @endif
                            // @ifndef PLAYER
                            instance[propName] = _deserializeObject(self, prop, self._target && instance[propName]);
                            // @endif
                        }
                        else {
                            // @ifdef PLAYER
                            _deserializeObjField(self, instance, prop, propName);
                            // @endif
                            // @ifndef PLAYER
                            _deserializeObjField(self, instance, prop, propName, self._target && instance);
                            // @endif
                        }
                    }
                    else {
                        instance[propName] = null;
                    }
                }
            }
        }
        //--self.stackCounter;
    }

    function _deserializeFireClass(self, obj, serialized, klass, target) {
        var props = klass.__props__;
        if (!props) {
            return;
        }
        for (var p = 0; p < props.length; p++) {
            var propName = props[p];
            var attrs = Fire.attr(klass, propName);
            // assume all prop in __props__ must have attr
            var rawType = attrs.rawType;
            if (!rawType) {
                if (attrs.serializable === false) {
                    continue;   // skip nonSerialized
                }
                if (!self._editor && attrs.editorOnly) {
                    continue;   // skip editor only if not editor
                }
                var prop = serialized[propName];
                if (typeof prop !== 'undefined') {
                    if (typeof prop !== 'object') {
                        obj[propName] = prop;
                    }
                    else {
                        if (prop) {
                            if (!prop.__uuid__ && typeof prop.__id__ === 'undefined') {
                                // @ifdef PLAYER
                                obj[propName] = _deserializeObject(self, prop);
                                // @endif
                                // @ifndef PLAYER
                                obj[propName] = _deserializeObject(self, prop, target && target[propName]);
                                // @endif
                            }
                            else {
                                // @ifdef PLAYER
                                _deserializeObjField(self, obj, prop, propName);
                                // @endif
                                // @ifndef PLAYER
                                _deserializeObjField(self, obj, prop, propName, target && obj);
                                // @endif
                            }
                        }
                        else {
                            obj[propName] = null;
                        }
                    }
                }
            }
            else {
                // always load raw objects even if property not serialized
                if (self.result.rawProp) {
                    Fire.error('not support multi raw object in a file');
                    // 这里假定每个asset都有uuid，每个json只能包含一个asset，只能包含一个rawProp
                }
                self.result.rawProp = propName;
            }
        }
        if (props[props.length - 1] === '_$erialized') {
            // save original serialized data
            obj._$erialized = serialized;
            // parse the serialized data as primitive javascript object, so its __id__ will be dereferenced
            _deserializePrimitiveObject(self, obj._$erialized, serialized);
        }
    }

    /**
     * @param {object} serialized - The obj to deserialize, must be non-nil
     * @param {object} [target=null]
     */
    var _deserializeObject = function (self, serialized, target) {
        var propName, prop;
        var obj = null;     // the obj to return
        var klass = null;
        if (serialized.__type__) {

            // Type Object (including FireClass)

            klass = self._classFinder(serialized.__type__);
            if (!klass) {
                Fire.error('[Fire.deserialize] unknown type: ' + serialized.__type__);
                return null;
            }
            // @ifdef PLAYER
            // instantiate a new object
            obj = new klass();
            // @endif
            // @ifndef PLAYER
            if (target) {
                // use target
                if ( !(target instanceof klass) ) {
                    Fire.warn('Type of target to deserialize not matched with data: target is %s, data is %s',
                               JS.getClassName(target), klass);
                }
                obj = target;
            }
            else {
                obj = new klass();
            }
            // @endif

            if ( Fire._isFireClass(klass) ) {
                _deserializeFireClass(self, obj, serialized, klass, target);
            }
            else {
                _deserializeTypedObject(self, obj, serialized);
            }
        }
        else if ( !Array.isArray(serialized) ) {

            // embedded primitive javascript object

            // @ifdef PLAYER
            obj = {};
            // @endif
            // @ifndef PLAYER
            obj = target || {};
            // @endif

            _deserializePrimitiveObject(self, obj, serialized);
        }
        else {

            // Array

            // @ifdef PLAYER
            obj = new Array(serialized.length);
            // @endif
            // @ifndef PLAYER
            if (target) {
                target.length = serialized.length;
                obj = target;
            }
            else {
                obj = new Array(serialized.length);
            }
            // @endif
            for (var i = 0; i < serialized.length; i++) {
                prop = serialized[i];
                if (typeof prop === 'object' && prop) {
                    if (!prop.__uuid__ && typeof prop.__id__ === 'undefined') {
                        // @ifdef PLAYER
                        obj[i] = _deserializeObject(self, prop);
                        // @endif
                        // @ifndef PLAYER
                        obj[i] = _deserializeObject(self, prop, target && target[i]);
                        // @endif
                    }
                    else {
                        // @ifdef PLAYER
                        _deserializeObjField(self, obj, prop, '' + i);
                        // @endif
                        // @ifndef PLAYER
                        _deserializeObjField(self, obj, prop, '' + i, target && target[i]);
                        // @endif
                    }
                }
                else {
                    obj[i] = prop;
                }
            }
        }
        return obj;
    };

    return _Deserializer;
})();

/**
 * Deserialize json to Fire.Asset
 * 当指定了 target 选项时，如果 target 引用的其它 asset 的 uuid 不变，则不会改变 target 对 asset 的引用，
 * 也不会将 uuid 保存到 result 对象中。
 *
 * @param {(string|object)} data - the serialized Fire.Asset json string or json object.
 *                                 Note: If data is an object, it will be modified.
 * @param {Fire._DeserializeInfo} [result] - additional loading result
 * @param {object} [options=null]
 * @return {object} the main data(asset)
 */
Fire.deserialize = function (data, result, options) {
    var isEditor = (options && 'isEditor' in options) ? options.isEditor : Fire.isEditor;
    var classFinder = (options && options.classFinder) || JS._getClassById;
    var createAssetRefs = (options && options.createAssetRefs) || Fire.isEditorCore;
    var target;
    // @ifndef PLAYER
    target = (options && options.target);
    // @endif

    // @ifndef PLAYER
    if (Fire.isNode && Buffer.isBuffer(data)) {
        data = data.toString();
    }
    // @endif

    if (typeof data === 'string') {
        data = JSON.parse(data);
    }

    if (createAssetRefs && !result) {
        result = new Fire._DeserializeInfo();
    }

    Fire._isCloning = true;
    var deserializer = new _Deserializer(data, result, target, isEditor, classFinder);
    Fire._isCloning = false;

    if (createAssetRefs) {
        result.assignAssetsBy(Fire.serialize.asAsset);
    }

    return deserializer.deserializedData;
};

/**
 * 包含反序列化时的一些信息
 * @class Fire._DeserializeInfo
 */
Fire._DeserializeInfo = function () {

    //this.urlList = [];
    //this.callbackList = [];

    // uuids(assets) need to load

    /**
     * @property {string[]} uuidList - list of the depends assets' uuid
     */
    this.uuidList = [];
    /**
     * @property {object[]} uuidObjList - the obj list whose field needs to load asset by uuid
     */
    this.uuidObjList = [];
    /**
     * @property {string[]} uuidPropList - the corresponding field name which referenced to the asset
     */
    this.uuidPropList = [];

    // raw objects need to load
    // (不用存rawList因为它的uuid可以从asset上获得)

    /**
     * @property {string} rawProp - the corresponding field name which referenced to the raw object
     */
    this.rawProp = '';
    ///**
    // * @property {Fire.Asset[]} rawObjList - the obj list whose corresponding raw object needs to load
    // */
    //this.rawObjList = [];
    ///**
    // * @property {string[]} rawPropList - the corresponding field name which referenced to the raw object
    // */
    //this.rawPropList = [];
};

Fire._DeserializeInfo.prototype.reset = function () {
    this.uuidList.length = 0;
    this.uuidObjList.length = 0;
    this.uuidPropList.length = 0;
    this.rawProp = '';
    //this.rawObjList.length = 0;
    //this.rawPropList.length = 0;
};

Fire._DeserializeInfo.prototype.getUuidOf = function (obj, propName) {
    for (var i = 0; i < this.uuidObjList.length; i++) {
        if (this.uuidObjList[i] === obj && this.uuidPropList[i] === propName) {
            return this.uuidList[i];
        }
    }
    return "";
};

Fire._DeserializeInfo.prototype.assignAssetsBy = function (callback) {
    var success = true;
    for (var i = 0, len = this.uuidList.length; i < len; i++) {
        var uuid = this.uuidList[i];
        var asset = callback(uuid);
        if (asset) {
            var obj = this.uuidObjList[i];
            var prop = this.uuidPropList[i];
            obj[prop] = asset;
        }
        else {
            Fire.error('Failed to assign asset: ' + uuid);
            success = false;
        }
    }
    return success;
};
<|endoftext|>


<commit_before>/**
 *
 *
 **/

var Shortkutz = {

  displayedShortcuts : [],
  keys : [],
  lastKeydownHandler : null,

  onLoad : function() {
    this.initializated = true;
  },

  display : function() {
    if( this.displayedShortcuts.length == 0 ) {
      this.collectAndShow();
    }
    this.lastKeydownHandler = window.onkeypress;
    window.onkeydown = this.keyDown;
    window.setTimeout( this.hide, 3000, this );
  },

  hide : function( instance ) {
    while( element = instance.displayedShortcuts.pop() ) {
      element.parentNode.removeChild( element );
    }
    window.onkeydown= this.lastKeydownHandler;
  },

  keyDown : function( event ) {
    key_pressed = String.fromCharCode(event.keyCode);
    if( Shortkutz.keys[key_pressed] != null ) {
      Shortkutz.simulateClick( Shortkutz.keys[key_pressed] );
    }
  },

  simulateClick : function(element) {
    var evt = document.createEvent("MouseEvents");
    evt.initMouseEvent("click", true, true, window,
      0, 0, 0, 0, 0, false, false, false, false, 0, null);
    var canceled = !element.dispatchEvent(evt);
    if(canceled) {
      // A handler called preventDefault
    } else {
      // None of the handlers called preventDefault
    }
  },

  collectAndShow : function() {
    this.displayedShortcuts = new Array(0);
    this.keys = new Array(0);
    var links = content.document.getElementsByTagName("a");
    for( var i=0; i<links.length; i++ ) {
      var letter = this.defineLetterAccessKey( links[i].innerHTML );
      if( letter ) {
        div = this.drawLetter( links[i], letter );
        href = links[i].getAttribute("href");
        this.keys[letter] = links[i];
        this.displayedShortcuts.push( div );
      }
    }
  },

  defineLetterAccessKey : function( title ) {
    for( var i=0; i<title.length; i++ ) {
      var letter = title.charAt(i).toUpperCase();
      if( letter.match("[A-Z0-9]") != null && this.keys[letter] == null ) {
        return letter;
      }
    }
    return false;
  },

  drawLetter : function( ref_element, letter ) {
    var div = content.document.createElement("div");
    div.innerHTML = letter;
    div.setAttribute("style", "background: #ffe849; border:solid 1px #000;" +
          "color:#000; font-size:90%; position:absolute; display:inline;" +
          "padding:1px; margin:1px; width:auto; min-width:15px;" +
          "text-align:center;");
    div.top = ref_element.top;
    div.left = ref_element.left;
    return ref_element.parentNode.insertBefore( div, ref_element );
  }

}

window.addEventListener("load", function(e) { Shortkutz.onLoad(e); }, false);

function dumpit(msg) {
  var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
                        .getService(Components.interfaces.nsIConsoleService);
  consoleService.logStringMessage("Shortkutz: " + msg);
}
<commit_msg>comment refering to the license<commit_after>/**
 * Shortkutz Firefox Extension
 * Author: Alvaro Gil, zevarito@gmail.com
 * Licensed under MIT license, see license.txt
 *
 **/

var Shortkutz = {

  displayedShortcuts : [],
  keys : [],
  lastKeydownHandler : null,

  onLoad : function() {
    this.initializated = true;
  },

  display : function() {
    if( this.displayedShortcuts.length == 0 ) {
      this.collectAndShow();
    }
    this.lastKeydownHandler = window.onkeypress;
    window.onkeydown = this.keyDown;
    window.setTimeout( this.hide, 3000, this );
  },

  hide : function( instance ) {
    while( element = instance.displayedShortcuts.pop() ) {
      element.parentNode.removeChild( element );
    }
    window.onkeydown= this.lastKeydownHandler;
  },

  keyDown : function( event ) {
    key_pressed = String.fromCharCode(event.keyCode);
    if( Shortkutz.keys[key_pressed] != null ) {
      Shortkutz.simulateClick( Shortkutz.keys[key_pressed] );
    }
  },

  simulateClick : function(element) {
    var evt = document.createEvent("MouseEvents");
    evt.initMouseEvent("click", true, true, window,
      0, 0, 0, 0, 0, false, false, false, false, 0, null);
    var canceled = !element.dispatchEvent(evt);
    if(canceled) {
      // A handler called preventDefault
    } else {
      // None of the handlers called preventDefault
    }
  },

  collectAndShow : function() {
    this.displayedShortcuts = new Array(0);
    this.keys = new Array(0);
    var links = content.document.getElementsByTagName("a");
    for( var i=0; i<links.length; i++ ) {
      var letter = this.defineLetterAccessKey( links[i].innerHTML );
      if( letter ) {
        div = this.drawLetter( links[i], letter );
        href = links[i].getAttribute("href");
        this.keys[letter] = links[i];
        this.displayedShortcuts.push( div );
      }
    }
  },

  defineLetterAccessKey : function( title ) {
    for( var i=0; i<title.length; i++ ) {
      var letter = title.charAt(i).toUpperCase();
      if( letter.match("[A-Z0-9]") != null && this.keys[letter] == null ) {
        return letter;
      }
    }
    return false;
  },

  drawLetter : function( ref_element, letter ) {
    var div = content.document.createElement("div");
    div.innerHTML = letter;
    div.setAttribute("style", "background: #ffe849; border:solid 1px #000;" +
          "color:#000; font-size:90%; position:absolute; display:inline;" +
          "padding:1px; margin:1px; width:auto; min-width:15px;" +
          "text-align:center;");
    div.top = ref_element.top;
    div.left = ref_element.left;
    return ref_element.parentNode.insertBefore( div, ref_element );
  }

}

window.addEventListener("load", function(e) { Shortkutz.onLoad(e); }, false);

function dumpit(msg) {
  var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
                        .getService(Components.interfaces.nsIConsoleService);
  consoleService.logStringMessage("Shortkutz: " + msg);
}
<|endoftext|>


<commit_before>/**
 * controller
 * @return
 */
module.exports = Controller("Home/BaseController", function(){
  "use strict";
  var Service = require("../../Service/Service");
  return {
    indexAction: function(){
      var self = this;
      Service.getAllCourses({ _desc:true ,_ordertype : 'int'}).then(function(data){
        self.assign({
          courses : data,
          section : 'course',
          userInfo : self.userInfo,
          navLinks : navLinks,
          title : "课程"
        });
        self.display();
      })
    },

    tagAction : function(){
      var self = this;
      Service.getCoursesByTag({
        tag : self.post("tag")
      }).then(function(data){
        self.success(data)
      })
    },

    searchAction : function(){
      var self = this;
      Service.searchCourses({
        wd : self.post('wd')
      }).then(function(data){
        self.success(data)
      })
    },

    viewAction: function(){
      var self = this;
      if(self.isGet()){
        var course_id = self.get('id');
        if(!course_id){
          return self.redirect("/course");
        }else{
          Service.getCourseById({id : course_id}).then(function(data){
            var course = data[0];
            var partner_id = course.partner;
            var partner = Service.getPartnerById({id : partner_id});
            var teachers = Service.getTeachersByCourseId({course : course_id});
            var resource = Service.getResourcesByCourseId({course : course_id, _limit : 1, _start : 0});
            self.assign({
              title: "课程",
              course : course,
              partner : partner,
              navLinks : navLinks,
              resource : resource,
              teachers : teachers,
              userInfo : self.userInfo,
              section : 'course'
            });
            self.display();
          })
        }
      }
    },

    videoAction : function(){
      var self = this;
      if(!self.userInfo){
        return self.redirect("/");
      }
      if(self.isGet()){
        var course_id = self.get('id');
        if(!course_id){
          return self.redirect("/course");
        }
        var course = Service.getCourseById({id : course_id});
        var resources = Service.getResourcesByCourseId({course : course_id});
        self.assign({
          title : "课程视频",
          course : course,
          navLinks : navLinks,
          userInfo : self.userInfo,
          resources : resources,
          section : 'course'
        })
        self.display();
      }
    },

    materialAction : function(){
      var self = this;
      if(!self.userInfo){
        return self.redirect("/")
      }
      if(self.isGet()){
        var course_id = self.get('id');
        if(!course_id){
          return self.redirect("/course");
        }
        Service.getCourseById({id : course_id}).then(function(data){
          if(data && data[0]){
            return self.redirect(data[0].materialAction)
          }
        })
      }
    }
  };
})
<commit_msg>Update CourseController.js<commit_after>/**
 * controller
 * @return
 */
module.exports = Controller("Home/BaseController", function(){
  "use strict";
  var Service = require("../../Service/Service");
  return {
    indexAction: function(){
      var self = this;
      Service.getCourseOrderByWeight().then(function(data){
        self.assign({
          courses : data,
          section : 'course',
          userInfo : self.userInfo,
          navLinks : navLinks,
          title : "课程"
        });
        self.display();
      })
    },

    tagAction : function(){
      var self = this;
      Service.getCoursesByTag({
        tag : self.post("tag")
      }).then(function(data){
        self.success(data)
      })
    },

    searchAction : function(){
      var self = this;
      Service.searchCourses({
        wd : self.post('wd')
      }).then(function(data){
        self.success(data)
      })
    },

    viewAction: function(){
      var self = this;
      if(self.isGet()){
        var course_id = self.get('id');
        if(!course_id){
          return self.redirect("/course");
        }else{
          Service.getCourseById({id : course_id}).then(function(data){
            var course = data[0];
            var partner_id = course.partner;
            var partner = Service.getPartnerById({id : partner_id});
            var teachers = Service.getTeachersByCourseId({course : course_id});
            var resource = Service.getResourcesByCourseId({course : course_id, _limit : 1, _start : 0});
            self.assign({
              title: "课程",
              course : course,
              partner : partner,
              navLinks : navLinks,
              resource : resource,
              teachers : teachers,
              userInfo : self.userInfo,
              section : 'course'
            });
            self.display();
          })
        }
      }
    },

    videoAction : function(){
      var self = this;
      if(!self.userInfo){
        return self.redirect("/");
      }
      if(self.isGet()){
        var course_id = self.get('id');
        if(!course_id){
          return self.redirect("/course");
        }
        var course = Service.getCourseById({id : course_id});
        var resources = Service.getResourcesByCourseId({course : course_id});
        self.assign({
          title : "课程视频",
          course : course,
          navLinks : navLinks,
          userInfo : self.userInfo,
          resources : resources,
          section : 'course'
        })
        self.display();
      }
    },

    materialAction : function(){
      var self = this;
      if(!self.userInfo){
        return self.redirect("/")
      }
      if(self.isGet()){
        var course_id = self.get('id');
        if(!course_id){
          return self.redirect("/course");
        }
        Service.getCourseById({id : course_id}).then(function(data){
          if(data && data[0]){
            return self.redirect(data[0].materialAction)
          }
        })
      }
    }
  };
})
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Laurent Bovet <laurent.bovet@windmaster.ch>
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var docson = docson || {};

docson.templateBaseUrl="templates";

define(["lib/jquery", "lib/handlebars", "lib/highlight", "lib/jsonpointer", "lib/marked", "lib/traverse"], function(jquery, handlebars, highlight, jsonpointer, marked) {

    var ready = $.Deferred();
    var boxTemplate;
    var signatureTemplate;
    var source;
    var stack = [];
    var boxes=[];

    Handlebars.registerHelper('scope', function(schema, options) {
        var result;
        boxes.push([]);
        if(schema && (schema.id || schema.root)) {
            stack.push( schema );
            result = options.fn(this);
            stack.pop();
        } else {
            result = options.fn(this);
        }
        boxes.pop();
        return result;
    });

    Handlebars.registerHelper('source', function(schema) {
        delete schema.root;
        delete schema.__boxId;
        delete schema.__name;
        delete schema.__ref;
        return JSON.stringify(schema, null, 2);
    });

    Handlebars.registerHelper('desc', function(schema) {
        var description = schema.description;

        if( !description ) return "";
        var text = description;
        if(marked) {
            marked.setOptions({gfm: true, breaks: true})
            return new Handlebars.SafeString(marked(text));
        } else {
            return text;
        }
    });

    Handlebars.registerHelper('equals', function(lvalue, rvalue, options) {
        if (arguments.length < 3)
            throw new Error("Handlebars Helper equals needs 2 parameters");
        if( lvalue!=rvalue ) {
            return options.inverse(this);
        } else {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('contains', function(arr, item, options) {;
        if(arr && arr.indexOf(item) != -1) {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('primitive', function(schema, options) {
        if(schema.type && schema.type != "object" && schema.type != "array" || schema.enum) {
            return withType(this, options, true)
        }
    });

    Handlebars.registerHelper('exists', function(value, options) {
        if(value !== undefined) {
            value = value === null ? "null": value;
            value = value === true ? "true": value;
            value = value === false ? "false": value;
            value = typeof value === "object" ? JSON.stringify(value): value;
            this.__default = value;
            var result = options.fn(this);
            delete this.__default;
            return result;
        }
    });

    Handlebars.registerHelper('range', function(from, to, replFrom, replTo, exclFrom, exclTo, sep) {
        var result = "";
        if(from !== undefined || to !== undefined) {
            result += exclFrom ? "]" : "[";
            result += from !== undefined ? from : replFrom;
            if( (from || replFrom) !== (to || replTo)) {
                result += (from !== undefined || replFrom !== null) && (to !== undefined || replTo !== null) ? sep : "";
                result += to !== undefined ? to : replTo;
            }
            result += exclTo ? "[" : "]";
            return result;
        }
    });

    var sub = function(schema) {
        return schema.type == "array" || schema.allOf || schema.anyOf || schema.oneOf || schema.not || schema.additionalProperties;
    }

    Handlebars.registerHelper('sub', function(schema, options) {
        if(sub(schema) || (schema.type && schema.type != "object" && schema.type != "array") || schema.enum) {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('main', function(schema, options) {
        if(!sub(schema)) {
            return options.fn(this);
        }
    });

    var simpleSchema = function(schema) {
        var result = schema.description===undefined && schema.title===undefined && schema.id===undefined;
        result &= schema.properties===undefined;
        return result;
    };

    Handlebars.registerHelper('simple', function(schema, options) {
        if(simpleSchema(schema) && !schema.$ref) {
            return withType(schema, options, true);
        }
    });

    var withType = function(schema, options, hideAny) {
        schema.__type = schema.type;
        if(!schema.type && !hideAny) {
            schema.__type="any";
        }
        if(schema.format) {
            schema.__type=schema.format;
        }
        if( (schema.__type == "any" || schema.__type == "object") && schema.title) {
            schema.__type = schema.title;
        }
        var result = options.fn(schema);
        delete schema.__type;
        return result;
    }

    Handlebars.registerHelper('complex', function(schema, options) {
        if(!simpleSchema(schema) && !schema.$ref || schema.properties) {
            return withType(schema, options);
        }
    });

    Handlebars.registerHelper('enum', function(schema) {
        if(schema.enum) {
            return (schema.enum.length > 1) ? "enum": "constant";
        }
    });

    Handlebars.registerHelper('obj', function(schema, options) {
        if(schema.properties || schema.type == "object") {
            return withType(schema, options);
        }
    });

    var pushBox = function(schema) {
        boxes[boxes.length-1].push(schema);
    }

    Handlebars.registerHelper('box', function(schema, options) {
        if(schema) {
            pushBox(schema);
            return options.fn(schema);
        }
    });

    Handlebars.registerHelper('boxId', function() {
        return boxes[boxes.length-1].length
    });

    Handlebars.registerHelper('boxes', function(options) {
        var result="";
        $.each(boxes[boxes.length-1], function(k, box) {
            box.__boxId = k+1;
            result=result+options.fn(box);
        });
        boxes[boxes.length-1] = []
        return result;
    });

    var resolveIdRef = function(ref) {
        if(stack) {
            var i;
            for(i=stack.length-1; i>=0; i--) {
                if(stack[i][ref]) {
                    return stack[i][ref];
                }
            }
        }
        return null;
    }

    var resolvePointerRef = function(ref) {
        var root = stack[1];
        if(ref=="#") {
            return root;
        }
        try {
            return jsonpointer.get(stack[1], ref);
        } catch(e) {
            console.log(e);
            return null;
        }
    }

    var resolveRef = function(ref) {
        if(ref.indexOf("#") == 0) {
            return resolvePointerRef(ref);
        } else {
            return resolveIdRef(ref);
        }
    }

    var getName = function(schema) {
        if(!schema) {
            return "<error>";
        }
        var name = schema.title;
        name = !name && schema.id ? schema.id: name;
        name = !name ? schema.__name: name;
        return name;
    }

    Handlebars.registerHelper('name', function(schema, options) {
        schema.__name = getName(schema);
        if(schema.__name) {
            return options.fn(schema);
        }
    });

    var refName = function(ref) {
        var name = getName(resolveRef(ref));
        if(!name) {
            if(ref == "#") {
                name = "<root>";
            } else {
                name = ref.replace("#", "/")
            }
        }
        var segments = name.split("/");
        name = segments[segments.length-1];
        return name;
    }

    function renderSchema(schema) {
        if(stack.indexOf(schema) == -1) { // avoid recursion
            return new Handlebars.SafeString(boxTemplate(schema));
        } else {
            return new Handlebars.SafeString(boxTemplate({"description": "_circular reference_"}));
        }
    }

    Handlebars.registerHelper('ref', function(schema, options) {
        if(schema.$ref) {
            var target = resolveRef(schema.$ref);
            if(target) {
                target.__name = refName(schema.$ref);
                target.__ref = schema.$ref.replace("#", "");
            }
            var result;
            if(target) {
                result = options.fn(target);
            } else {
                result = new Handlebars.SafeString(""+schema.$ref+"");
            }
            if(target) {
                delete target.__ref;
            }
            return result;
        }
    });

    Handlebars.registerHelper('schema', function(schema) {
        return renderSchema(schema);
    });

    Handlebars.registerHelper('signature', function(schema, keyword, schemas) {
        if(!schemas) {
            schemas = []
        }
        schemas = schemas instanceof Array ? schemas : [schemas];
        return new Handlebars.SafeString(signatureTemplate({ schema: schema, keyword: keyword, schemas: schemas}));
    });

    Handlebars.registerHelper('l', function(context) {
        console.log(context);
    });

    function init() {
        $.when( $.get(docson.templateBaseUrl+"/box.html").done(function(content) {
            source = content
            boxTemplate = Handlebars.compile(source);
        }), $.get(docson.templateBaseUrl+"/signature.html").done(function(content) {
            source = content
            signatureTemplate = Handlebars.compile(source);
        })).always(function() {
            ready.resolve();
        });
    };

    docson.doc = function(element, schema, ref, baseUrl) {
        var d = $.Deferred();
        init();
        ready.done(function() {
            if(typeof element == "string") {
                element = $("#"+element);
            }
            if(typeof schema == "string") {
                schema = JSON.parse(schema);
            }

            var refsPromise = $.Deferred().resolve().promise();
            var refs = {};

            traverse(schema).forEach(function(item) {
                // Fix Swagger weird generation for array.
                if(item && item.$ref == "array") {
                    delete item.$ref;
                    item.type ="array";
                }

                // Fetch external schema
                if(this.key === "$ref") {
                    var external = false;
                    if((/^https?:\/\//).test(item)) {
                        external = true;
                    } else if(item.indexOf('#') > 0){
                        //Turning relative refs to absolute ones
                        external = true;
                        item = baseUrl + item;
                        this.update(item);
                    }
                    if(external){
                        var segments = item.split("#");
                        var p = $.get(segments[0]).then(function(content) {
                            if(typeof content != "object") {
                                try {
                                    content = JSON.parse(content);
                                } catch(e) {
                                    console.error("Unable to parse "+segments[0], e);
                                }
                            }
                            if(content) {
                                refs[item] = content;
                            }
                        });
                        refsPromise = p.then(refsPromise)
                    }
                }
            });

            refsPromise.done(function() {
                stack.push(refs);
                var target = schema;
                if(ref) {
                    ref = ref[0] !== '/' ? '/'+ref : ref;
                    target = jsonpointer.get(schema, ref);
                    stack.push( schema );
                }
                target.root = true;
                target.__ref = "<root>";
                var html = boxTemplate(target);

                if(ref) {
                    stack.pop();
                }
                stack.pop();

                element.addClass("docson").html(html);

                var resizeHandler = element.get(0).onresize;
                function resized() {
                    if(resizeHandler) {
                        var box = element.find(".box").first();
                        element.get(0).onresize(box.outerWidth(), box.outerHeight());
                    }
                }
                element.get(0).resized = resized;
                resized();

                if(highlight) {
                    element.find(".json-schema").each(function(k, schemaElement) {
                        highlight.highlightSchema(schemaElement);
                    });
                }
                element.find(".box-title").each(function() {
                   var ref = $(this).attr("ref");
                   if(ref) {
                       if(window.location.href.indexOf("docson/index.html") > -1) {
                           $(this).find(".box-name").css("cursor", "pointer").attr("title", "Open in new window")
                           .hover(
                               function(){ $(this).addClass('link') },
                               function(){ $(this).removeClass('link') })
                           .click(function() {
                                var url = window.location.href+"$$expand";
                                if(ref !=="<root>") {
                                   url = url.replace(/(docson\/index.html#[^\$]*).*/, "$1$"+ref+"$$expand");
                                }
                                var w;
                                function receiveMessage(event) {
                                   if (event.data.id && event.data.id == "docson" && event.data.action == "ready") {
                                       w.postMessage({ id: "docson", action: "load", definitions: schema, type: event.data.url.split("$")[1], expand: true}, "*");
                                   }
                                }
                                window.addEventListener("message", receiveMessage, false);
                                w = window.open(url, "_blank");
                           });
                       }
                   }
                });
                element.find(".box").mouseenter(function() {
                    $(this).children(".source-button").fadeIn(300);
                    $(this).children(".box-body").children(".expand-button").fadeIn(300);
                });
                element.find(".box").mouseleave(function() {
                    $(this).children(".source-button").fadeOut(300);
                    $(this).children(".box-body").children(".expand-button").fadeOut(300);
                });
                element.find(".signature-type-expandable").click(function() {
                    var boxId = $(this).attr("boxid");
                    $(this).toggleClass("signature-type-expanded");
                    $(this).parent().parent().parent().children(".signature-box-container").
                        children("[boxid='"+boxId+"']").toggle(resizeHandler ? 0 : 300);
                    resized();
                });
                element.find(".expand-button").click(function() {
                    if($(this).attr("expanded")) {
                        $(this).parent().parent().find(".expand-button").html(" + ").attr("title", "Expand all");
                        $(this).parent().parent().find(".signature-type-expandable").removeClass("signature-type-expanded");
                        $(this).parent().parent().find(".box-container").hide( resizeHandler ? 0 : 300);
                        $(this).parent().parent().find(".expand-button").removeAttr("expanded");
                        resized();
                    } else {
                        $(this).parent().parent().find(".expand-button").html(" - ").attr("title", "Collapse all");
                        $(this).parent().parent().find(".signature-type-expandable").addClass("signature-type-expanded");
                        $(this).parent().parent().find(".box-container").show(resizeHandler ? 0 : 300);
                        $(this).parent().parent().find(".expand-button").attr("expanded", true);
                        resized();
                    }
                });
                element.find(".source-button").click(function() {
                    $(this).parent().children(".box-body").toggle();
                    $(this).parent().children(".source").toggle();
                    resized();
                });
            });
            d.resolve();
        })
        return d.promise();
    }

    return docson;
});
<commit_msg>Allowing nested $refs<commit_after>/*
 * Copyright 2013 Laurent Bovet <laurent.bovet@windmaster.ch>
 *
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var docson = docson || {};

docson.templateBaseUrl="templates";

define(["lib/jquery", "lib/handlebars", "lib/highlight", "lib/jsonpointer", "lib/marked", "lib/traverse"], function(jquery, handlebars, highlight, jsonpointer, marked) {

    var ready = $.Deferred();
    var boxTemplate;
    var signatureTemplate;
    var source;
    var stack = [];
    var boxes=[];

    Handlebars.registerHelper('scope', function(schema, options) {
        var result;
        boxes.push([]);
        if(schema && (schema.id || schema.root)) {
            stack.push( schema );
            result = options.fn(this);
            stack.pop();
        } else {
            result = options.fn(this);
        }
        boxes.pop();
        return result;
    });

    Handlebars.registerHelper('source', function(schema) {
        delete schema.root;
        delete schema.__boxId;
        delete schema.__name;
        delete schema.__ref;
        return JSON.stringify(schema, null, 2);
    });

    Handlebars.registerHelper('desc', function(schema) {
        var description = schema.description;

        if( !description ) return "";
        var text = description;
        if(marked) {
            marked.setOptions({gfm: true, breaks: true})
            return new Handlebars.SafeString(marked(text));
        } else {
            return text;
        }
    });

    Handlebars.registerHelper('equals', function(lvalue, rvalue, options) {
        if (arguments.length < 3)
            throw new Error("Handlebars Helper equals needs 2 parameters");
        if( lvalue!=rvalue ) {
            return options.inverse(this);
        } else {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('contains', function(arr, item, options) {;
        if(arr && arr.indexOf(item) != -1) {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('primitive', function(schema, options) {
        if(schema.type && schema.type != "object" && schema.type != "array" || schema.enum) {
            return withType(this, options, true)
        }
    });

    Handlebars.registerHelper('exists', function(value, options) {
        if(value !== undefined) {
            value = value === null ? "null": value;
            value = value === true ? "true": value;
            value = value === false ? "false": value;
            value = typeof value === "object" ? JSON.stringify(value): value;
            this.__default = value;
            var result = options.fn(this);
            delete this.__default;
            return result;
        }
    });

    Handlebars.registerHelper('range', function(from, to, replFrom, replTo, exclFrom, exclTo, sep) {
        var result = "";
        if(from !== undefined || to !== undefined) {
            result += exclFrom ? "]" : "[";
            result += from !== undefined ? from : replFrom;
            if( (from || replFrom) !== (to || replTo)) {
                result += (from !== undefined || replFrom !== null) && (to !== undefined || replTo !== null) ? sep : "";
                result += to !== undefined ? to : replTo;
            }
            result += exclTo ? "[" : "]";
            return result;
        }
    });

    var sub = function(schema) {
        return schema.type == "array" || schema.allOf || schema.anyOf || schema.oneOf || schema.not || schema.additionalProperties;
    }

    Handlebars.registerHelper('sub', function(schema, options) {
        if(sub(schema) || (schema.type && schema.type != "object" && schema.type != "array") || schema.enum) {
            return options.fn(this);
        }
    });

    Handlebars.registerHelper('main', function(schema, options) {
        if(!sub(schema)) {
            return options.fn(this);
        }
    });

    var simpleSchema = function(schema) {
        var result = schema.description===undefined && schema.title===undefined && schema.id===undefined;
        result &= schema.properties===undefined;
        return result;
    };

    Handlebars.registerHelper('simple', function(schema, options) {
        if(simpleSchema(schema) && !schema.$ref) {
            return withType(schema, options, true);
        }
    });

    var withType = function(schema, options, hideAny) {
        schema.__type = schema.type;
        if(!schema.type && !hideAny) {
            schema.__type="any";
        }
        if(schema.format) {
            schema.__type=schema.format;
        }
        if( (schema.__type == "any" || schema.__type == "object") && schema.title) {
            schema.__type = schema.title;
        }
        var result = options.fn(schema);
        delete schema.__type;
        return result;
    }

    Handlebars.registerHelper('complex', function(schema, options) {
        if(!simpleSchema(schema) && !schema.$ref || schema.properties) {
            return withType(schema, options);
        }
    });

    Handlebars.registerHelper('enum', function(schema) {
        if(schema.enum) {
            return (schema.enum.length > 1) ? "enum": "constant";
        }
    });

    Handlebars.registerHelper('obj', function(schema, options) {
        if(schema.properties || schema.type == "object") {
            return withType(schema, options);
        }
    });

    var pushBox = function(schema) {
        boxes[boxes.length-1].push(schema);
    }

    Handlebars.registerHelper('box', function(schema, options) {
        if(schema) {
            pushBox(schema);
            return options.fn(schema);
        }
    });

    Handlebars.registerHelper('boxId', function() {
        return boxes[boxes.length-1].length
    });

    Handlebars.registerHelper('boxes', function(options) {
        var result="";
        $.each(boxes[boxes.length-1], function(k, box) {
            box.__boxId = k+1;
            result=result+options.fn(box);
        });
        boxes[boxes.length-1] = []
        return result;
    });

    var resolveIdRef = function(ref) {
        if(stack) {
            var i;
            for(i=stack.length-1; i>=0; i--) {
                if(stack[i][ref]) {
                    return stack[i][ref];
                }
            }
        }
        return null;
    }

    var resolvePointerRef = function(ref) {
        var root = stack[1];
        if(ref=="#") {
            return root;
        }
        try {
            return jsonpointer.get(stack[1], ref);
        } catch(e) {
            console.log(e);
            return null;
        }
    }

    var resolveRef = function(ref) {
        if(ref.indexOf("#") == 0) {
            return resolvePointerRef(ref);
        } else {
            return resolveIdRef(ref);
        }
    }

    var getName = function(schema) {
        if(!schema) {
            return "<error>";
        }
        var name = schema.title;
        name = !name && schema.id ? schema.id: name;
        name = !name ? schema.__name: name;
        return name;
    }

    Handlebars.registerHelper('name', function(schema, options) {
        schema.__name = getName(schema);
        if(schema.__name) {
            return options.fn(schema);
        }
    });

    var refName = function(ref) {
        var name = getName(resolveRef(ref));
        if(!name) {
            if(ref == "#") {
                name = "<root>";
            } else {
                name = ref.replace("#", "/")
            }
        }
        var segments = name.split("/");
        name = segments[segments.length-1];
        return name;
    }

    function renderSchema(schema) {
        if(stack.indexOf(schema) == -1) { // avoid recursion
            return new Handlebars.SafeString(boxTemplate(schema));
        } else {
            return new Handlebars.SafeString(boxTemplate({"description": "_circular reference_"}));
        }
    }

    Handlebars.registerHelper('ref', function(schema, options) {
        if(schema.$ref) {
            var target = resolveRef(schema.$ref);
            if(target) {
                target.__name = refName(schema.$ref);
                target.__ref = schema.$ref.replace("#", "");
            }
            var result;
            if(target) {
                result = options.fn(target);
            } else {
                result = new Handlebars.SafeString(""+schema.$ref+"");
            }
            if(target) {
                delete target.__ref;
            }
            return result;
        }
    });

    Handlebars.registerHelper('schema', function(schema) {
        return renderSchema(schema);
    });

    Handlebars.registerHelper('signature', function(schema, keyword, schemas) {
        if(!schemas) {
            schemas = []
        }
        schemas = schemas instanceof Array ? schemas : [schemas];
        return new Handlebars.SafeString(signatureTemplate({ schema: schema, keyword: keyword, schemas: schemas}));
    });

    Handlebars.registerHelper('l', function(context) {
        console.log(context);
    });

    function init() {
        $.when( $.get(docson.templateBaseUrl+"/box.html").done(function(content) {
            source = content
            boxTemplate = Handlebars.compile(source);
        }), $.get(docson.templateBaseUrl+"/signature.html").done(function(content) {
            source = content
            signatureTemplate = Handlebars.compile(source);
        })).always(function() {
            ready.resolve();
        });
    };

    docson.doc = function(element, schema, ref, baseUrl) {
        var d = $.Deferred();
        if(baseUrl === undefined) baseUrl='';
        init();
        ready.done(function() {
            if(typeof element == "string") {
                element = $("#"+element);
            }
            if(typeof schema == "string") {
                schema = JSON.parse(schema);
            }

            var refsPromise = $.Deferred().resolve().promise();
            var refs = {};

            var renderBox = function() {
                stack.push(refs);
                var target = schema;
                if(ref) {
                    ref = ref[0] !== '/' ? '/'+ref : ref;
                    target = jsonpointer.get(schema, ref);
                    stack.push( schema );
                }
                target.root = true;
                target.__ref = "<root>";
                var html = boxTemplate(target);

                if(ref) {
                    stack.pop();
                }
                stack.pop();

                element.addClass("docson").html(html);

                var resizeHandler = element.get(0).onresize;
                function resized() {
                    if(resizeHandler) {
                        var box = element.find(".box").first();
                        element.get(0).onresize(box.outerWidth(), box.outerHeight());
                    }
                }
                element.get(0).resized = resized;
                resized();

                if(highlight) {
                    element.find(".json-schema").each(function(k, schemaElement) {
                        highlight.highlightSchema(schemaElement);
                    });
                }
                element.find(".box-title").each(function() {
                   var ref = $(this).attr("ref");
                   if(ref) {
                       if(window.location.href.indexOf("docson/index.html") > -1) {
                           $(this).find(".box-name").css("cursor", "pointer").attr("title", "Open in new window")
                           .hover(
                               function(){ $(this).addClass('link') },
                               function(){ $(this).removeClass('link') })
                           .click(function() {
                                var url = window.location.href+"$$expand";
                                if(ref !=="<root>") {
                                   url = url.replace(/(docson\/index.html#[^\$]*).*/, "$1$"+ref+"$$expand");
                                }
                                var w;
                                function receiveMessage(event) {
                                   if (event.data.id && event.data.id == "docson" && event.data.action == "ready") {
                                       w.postMessage({ id: "docson", action: "load", definitions: schema, type: event.data.url.split("$")[1], expand: true}, "*");
                                   }
                                }
                                window.addEventListener("message", receiveMessage, false);
                                w = window.open(url, "_blank");
                           });
                       }
                   }
                });
                element.find(".box").mouseenter(function() {
                    $(this).children(".source-button").fadeIn(300);
                    $(this).children(".box-body").children(".expand-button").fadeIn(300);
                });
                element.find(".box").mouseleave(function() {
                    $(this).children(".source-button").fadeOut(300);
                    $(this).children(".box-body").children(".expand-button").fadeOut(300);
                });
                element.find(".signature-type-expandable").click(function() {
                    var boxId = $(this).attr("boxid");
                    $(this).toggleClass("signature-type-expanded");
                    $(this).parent().parent().parent().children(".signature-box-container").
                        children("[boxid='"+boxId+"']").toggle(resizeHandler ? 0 : 300);
                    resized();
                });
                element.find(".expand-button").click(function() {
                    if($(this).attr("expanded")) {
                        $(this).parent().parent().find(".expand-button").html(" + ").attr("title", "Expand all");
                        $(this).parent().parent().find(".signature-type-expandable").removeClass("signature-type-expanded");
                        $(this).parent().parent().find(".box-container").hide( resizeHandler ? 0 : 300);
                        $(this).parent().parent().find(".expand-button").removeAttr("expanded");
                        resized();
                    } else {
                        $(this).parent().parent().find(".expand-button").html(" - ").attr("title", "Collapse all");
                        $(this).parent().parent().find(".signature-type-expandable").addClass("signature-type-expanded");
                        $(this).parent().parent().find(".box-container").show(resizeHandler ? 0 : 300);
                        $(this).parent().parent().find(".expand-button").attr("expanded", true);
                        resized();
                    }
                });
                element.find(".source-button").click(function() {
                    $(this).parent().children(".box-body").toggle();
                    $(this).parent().children(".source").toggle();
                    resized();
                });
            };

            var resolveRefsReentrant = function(schema){
                traverse(schema).forEach(function(item) {
                    // Fix Swagger weird generation for array.
                    if(item && item.$ref == "array") {
                        delete item.$ref;
                        item.type ="array";
                    }

                    // Fetch external schema
                    if(this.key === "$ref") {
                        var external = false;
                        if((/^https?:\/\//).test(item)) {
                            external = true;
                        } else if(item.indexOf('#') > 0){
                            //Turning relative refs to absolute ones
                            external = true;
                            item = baseUrl + item;
                            this.update(item);
                        }
                        if(external){
                            var segments = item.split("#");
                            refs[item] = null;
                            var p = $.get(segments[0]).then(function(content) {
                                if(typeof content != "object") {
                                    try {
                                        content = JSON.parse(content);
                                    } catch(e) {
                                        console.error("Unable to parse "+segments[0], e);
                                    }
                                }
                                if(content) {
                                    refs[item] = content;
                                    renderBox();
                                    resolveRefsReentrant(content);
                                }
                            });
                        }
                    }
                });
            };

            resolveRefsReentrant(schema);
            renderBox();

            d.resolve();
        })
        return d.promise();
    }

    return docson;
});
<|endoftext|>


<commit_before>$(document).ready(function(){
	$db="relax-o-notes";

	$("#upload_file_btn").live("click", function(){
		var doc={
			"uploaded_by": $("#uploaded_by").val(),
			"gravatar_url": "http://gravatar.com/avatar/"+md5($("#uploaded_by").val())
		};
		$.couch.db($db).saveDoc(doc,{
			success: function(data){
				var id=data.id;
				var stat=data.ok;
				if(stat){
					$("#uploadModal").modal('hide');

				}
				console.log(data);
			},
			error: function(data){
				console.log(data);
			}
		});
		return false;
	});

});
<commit_msg>call to notes/ map function<commit_after>$(document).ready(function(){
	$db="relax-o-notes";

	$("#upload_file_btn").live("click", function(){
		var doc={
			"uploaded_by": $("#uploaded_by").val(),
			"gravatar_url": "http://gravatar.com/avatar/"+md5($("#uploaded_by").val())
		};
		$.couch.db($db).saveDoc(doc,{
			success: function(data){
				var id=data.id;
				var stat=data.ok;
				if(stat){
					$("#uploadModal").modal('hide');

				}
				console.log(data);
			},
			error: function(data){
				console.log(data);
			}
		});
		return false;
	});

	$.couch.db($db).view("app/notes/",{
		success: function(data){
			console.log(data);
		},
		error: function(data){
			console.log(data);
		}
	});

});
<|endoftext|>