1/** 2 * @file js/classes/ObjectProxy.js 3 * 4 * Copyright (c) 2013-2019 Simon Fraser University 5 * Copyright (c) 2000-2019 John Willinsky 6 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING. 7 * 8 * @class ObjectProxy 9 * @ingroup js_classes 10 * 11 * @brief Proxy that will be added to every object before 12 * instantiation. 13 * 14 * This proxy allows us to use a generic object factory. It'll 15 * also be a good place to intercept objects and implement 16 * cross-cutting concerns if required. 17 */ 18(function($) { 19 20 21 /** 22 * @constructor 23 * The constructor must remain empty because it will 24 * be replaced on instantiation of the proxy. 25 */ 26 $.pkp.classes.ObjectProxy = function() { 27 return this; 28 }; 29 30 31 // 32 // Private instance variables 33 // 34 /** 35 * @private 36 * @type {string} The object name of this object. 37 */ 38 $.pkp.classes.ObjectProxy.prototype.objectName_ = ''; 39 40 41 // 42 // Protected methods 43 // 44 /** 45 * Find a static property in the constructor hierarchy. 46 * Extra arguments will be passed to the static method (if any). 47 * 48 * NB: If the property is a function then it will be executed 49 * in the current context with the additional arguments given. 50 * If it is any other type then the property will be returned. 51 * 52 * @param {string} propertyName The name of the static 53 * property to be found. 54 * @return {*} The property or undefined if the property 55 * was not found. 56 */ 57 $.pkp.classes.ObjectProxy.prototype.self = 58 function(propertyName) { 59 var ctor, foundProperty, args; 60 61 // Loop through the inheritance hierarchy to find the property. 62 for (ctor = this.constructor; ctor; 63 ctor = ctor.parent_ && ctor.parent_.constructor) { 64 65 // Try to find the property in the current constructor. 66 if (ctor.hasOwnProperty(propertyName)) { 67 foundProperty = ctor[propertyName]; 68 if ($.isFunction(foundProperty)) { 69 // If the property is a function then call it. 70 args = Array.prototype.slice.call(arguments, 1); 71 return foundProperty.apply(this, args); 72 } 73 // Return the property itself. 74 return foundProperty; 75 } 76 } 77 78 // The property was not found on any of the functions 79 // in the constructor hierarchy. 80 throw new Error(['Static property "', propertyName, '" not found!'].join('')); 81 }; 82 83 84 /** 85 * Find the parent constructor or method in the prototype hierarchy. 86 * Extra arguments will be passed to the parent method. 87 * 88 * NB: If the method is found then it will be executed in the context 89 * of the me parameter with the given arguments. 90 * 91 * @param {*=} opt_methodName The name of the method to be found. Do 92 * not set when calling this method from a constructor! 93 * @param {...*} var_args Additional parameters to be passed. 94 * @return {*} The return value of the parent method. 95 */ 96 $.pkp.classes.ObjectProxy.prototype.parent = 97 function(opt_methodName, var_args) { 98 var caller, args, foundCaller, ctor; 99 100 // Retrieve a reference to the function that called us. 101 caller = $.pkp.classes.ObjectProxy.prototype.parent.caller; 102 103 // 1) Check whether the caller is a constructor. 104 if (caller.parent_) { 105 // We were called from within a constructor and 106 // therefore the methodName parameter is not set. 107 args = Array.prototype.slice.call(arguments); 108 109 // Call the constructor. 110 return caller.parent_.constructor.apply(this, args); 111 } 112 113 // Assume that we were called from within a method and that 114 // therefore the methodName parameter is set. 115 args = Array.prototype.slice.call(arguments, 1); 116 117 // 2) Look for the caller in the top-level instance methods. 118 if (this.hasOwnProperty(opt_methodName) && this[opt_methodName] === caller) { 119 return this.constructor.parent_[opt_methodName].apply(this, args); 120 } 121 122 // 3) Look for the caller in the prototype chain. 123 foundCaller = false; 124 for (ctor = this.constructor; ctor; 125 ctor = ctor.parent_ && ctor.parent_.constructor) { 126 if (ctor.prototype.hasOwnProperty(opt_methodName) && 127 ctor.prototype[opt_methodName] === caller) { 128 foundCaller = true; 129 } else if (foundCaller) { 130 return ctor.prototype[opt_methodName].apply(this, args); 131 } 132 } 133 134 // 4) This method was not called by the right caller. 135 throw new Error(['Trying to call parent from a method of one name ', 136 'to a method of a different name'].join('')); 137 }; 138 139 140 // 141 // Public methods 142 // 143 /** 144 * Return the object name of this object 145 * @return {string} The object name of this object. 146 */ 147 $.pkp.classes.ObjectProxy.prototype.getObjectName = function() { 148 return this.objectName_; 149 }; 150 151 152/** @param {jQuery} $ jQuery closure. */ 153}(jQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.