📄 class.js
字号:
// callback specified as the name of a method on a known target if (target != null && isc.isA.Function(target[callback])) method = target[callback]; // callback is a String expression else method = this._makeCallbackFunction(callback, argNames); } else if (isc.isAn.Object(callback) && !isc.isA.Function(callback)) { // Object containing (possibly) target, and either methodName or action to fire if (callback.caller != null) target = callback.caller; else if (callback.target != null) target = callback.target; // Pick up arguments from the callback directly, if passed that way. if (callback.args) args = callback.args; if (callback.argNames) argNames = callback.argNames; if (callback.method) method = callback.method else if (callback.methodName && target != null) method = target[callback.methodName]; else if (callback.action) method = this._makeCallbackFunction(callback.action, argNames) } // At this point the target (if one was passed in) is available under 'target', and // we've converted the callback to a function, if possible. if (!isc.isA.Function(method)) { this.logWarn("fireCallback() unable to convert callback: " + this.echo(callback) + " to a function."); return; } // If no target was specified, fire it in the global scope if (target == null) target = window; // If the target has been destroyed, abort! else if (target.destroyed) { // NOTE: this isn't a warning scenario: destruction is normal, and callbacks are // commonly timers to do visual refreshes which don't matter if a component is // destroyed if (this.logIsInfoEnabled("callbacks")) { this.logInfo("aborting attempt to fire callback on destroyed target:"+ target + ". Callback:"+ isc.Log.echo(callback) + ",\n stack:" + this.getStackTrace()); } return; } // this causes anonymous callback functions to be labelled "callback" in stack traces. // Non-anonymous callbacks still show their usual name method._isCallback = true; if (args == null) args = []; var returnVal; if (!catchErrors || !isc.Browser.isMoz) { returnVal = method.apply(target, args); } else { try { returnVal = method.apply(target, args); } catch (e) { isc.Log._reportJSError(e); throw e;; } } return returnVal; }, //> @classMethod Class.delayCall() // This is a helper to delay a call to a method on some target by a specified // amount of time. Can be used to delay a call to a static method on this class by // ommiting the <code>target</code> parameter. // @param methodName (string) name of the method to call // @param [arrayArgs] (array) array of arguments to pass to the method in question // @param [time] (number) Number of ms to delay the call by - defaults to zero (so just pulls // execution of the method out of the current execution thread. // @param [target] (object) Target to fire the method on - if unspecified assume this is // a call to a classMethod on this Class. // @return (string) Timer ID for the delayed call - can be passed to // +link{Timer.clear()} to cancel the call before it executes // @visibility external //< delayCall : function (methodName, arrayArgs, time, target) { if (target == null) target = this; if (time == null) time = 0; return isc.Timer.setTimeout({target:target, methodName:methodName, args:arrayArgs}, time); }, _makeCallbackFunction : function (callback, argNames) { //return isc.Func.expressionToFunction(argNames, callback); if (argNames == null) { var undef; argNames = undef; } var func = isc._makeFunction(argNames, callback); func._showBodyInTrace = true; return func; }, //>@classMethod Class.fireOnPause() // Given some repeatedly performed event (EG keypress, scroll, etc), set up an action // to fire when the events have stopped occurring for some set period. // @param id (string) arbitrary identifier for the action // @param callback (callback) action to fire on quiescence // @param [delay] (number) delay in ms - defaults to 200ms // @param [target] (object) if passed, the callback will be fired in this target's scope //< // additional instanceID parameter passed from instance method to support instance-level IDs fireOnPauseDelay:200, _$_fireActionsOnPause:"_fireActionsOnPause", _actionsOnPause:{}, _actionOnPauseTimers:{}, fireOnPause : function (id, callback, delay, target, instanceID) { if (!id) return; if (!delay) delay = this.fireOnPauseDelay; // Note: If we have two separate instances calling the fireOnPause instance method with // the same ID, both actions need to fire -- the ID is essentially unique within the // instance only. // We use the instanceID parameter to create separate callbacks for the same ID used // on different instances. // If unset, default to this.getClassName() [not legal to have any instance with the // same ID as a SmartClient class]. if (instanceID == null) instanceID = this.getClassName(); if (!this._actionsOnPause[id]) { this._actionsOnPause[id] = {}; } if (!this._actionsOnPause[id][instanceID]) { this._actionsOnPause[id][instanceID] = {fireTime:delay, callback:callback, target:target}; } var stamp = isc.timeStamp(), elapsed = this._lastFireOnPause ? stamp - this.lastFireOnPause : null; this._lastFireOnPause = stamp; // If we're going to fire queue of actions before the delay passed in, we're done if (elapsed && delay >= (this._fireOnPauseDelay - elapsed)) return; if (this._fireOnPauseTimer) isc.Timer.clearTimeout(this._fireOnPauseTimer); this._fireOnPauseTimer = this.delayCall(this._$_fireActionsOnPause,null, delay); this._fireOnPauseDelay = delay; }, _fireActionsOnPause : function () { var fireAgainTime; // In theory this._fireOnPausedDelay ms have elapsed since the call to fireOnPause // (or the last call to this method). // In practice it's probably more accurate to check the elapsed time by comparing // timestamps var elapsed = isc.timeStamp() - this._lastFireOnPause, fireAgainTime; for (var id in this._actionsOnPause) { var actions = this._actionsOnPause[id]; for (var iid in actions) { var action = actions[iid]; if (action.fireTime <= elapsed) { this.fireCallback(action.callback, null, null, action.target); delete this._actionsOnPause[id][iid]; } else { action.fireTime -= elapsed; if (fireAgainTime == null) fireAgainTime = action.fireTime; else fireAgainTime = Math.min(fireAgainTime, action.fireTime); } } if (isc.isAn.emptyObject(this._actionsOnPause[id])) delete this._actionsOnPause[id]; } if (fireAgainTime != null) { this._fireOnPauseDelay = fireAgainTime; this._lastFireOnPause = isc.timeStamp(); this.delayCall(this._$_fireActionsOnPause, null, fireAgainTime); } }, //> @classMethod Class.evalWithVars() // // Evaluates the given string with an arbitrary number of arguments on the specified target. // evalVars and target are optional. // // @param evalString the string to evaluate // @param evalVars Map of key-value pairs. The keys are treated as argument names that are // then made available inside the eval body as variables. The values of // these variables are the values assigned to the keys in evalVars. // @param target the target on which to apply the eval - it will be available as the // 'this' variable inside the eval block. If not specified, the evalString // is evaluated in global context. // @return (any) returns the result of eval(evalString) //< evalWithVars : function (evalString, evalVars, target) { //!OBFUSCATEOK // if no target specified, eval in global scope if (!target) target = window; if (isc.Browser.isMoz && isc.Browser.geckoVersion >= 20061010 && window.opener != null) { var theFunc = function (scope) { //!OBFUSCATEOK with (scope) { return eval(evalString); } } return theFunc.apply(target, [evalVars || isc.emptyObject]); } // create two arrays of the keys and values of the evalVars map var argNames = ["evalString"]; var argValues = [evalString]; if (evalVars) { for (var argName in evalVars) { argNames.push(argName); argValues.push(evalVars[argName]); } } // make a function with argNames as arguments that evals evalString var theFunc = isc._makeFunction(argNames.join(","), "return eval(evalString)"); // call the function on the target return theFunc.apply(target, argValues); }, // calls evalWithVars(jsSrc, evalVars, target), and returns all globals created via // addGlobalID(). All other non-explicit globals are captured by the function body that's // created around the jsSrc. evalWithCapture : function (jsSrc, evalVars, target) { var globals = isc.globalsSnapshot = []; // // we need to create a function with the jsSrc as the body to avoid creating extraneous // globals - conveniently evalWithVars already does this for us. this.evalWithVars(jsSrc, evalVars, target); isc.globalsSnapshot = null; return globals; }, // takes a list of global IDs and destroys them destroyGlobals : function (globals) { if (!isc.isAn.Array(globals)) globals = [globals]; for (var i = 0; i < globals.length; i++) { var global = globals[i]; // call destroy() on the gloabl if it's defined if (window[global] && isc.isA.Function(window[global].destroy)) window[global].destroy(); else window[global] = null; // otherwise just null out the global ref } }, // Provides 'true' global eval - i.e. global vars actually stick to the window object when // eval'd in this manner vs a plain eval() which does not do that. // // Note: the eval logic here (separate approaches to actually perform the eval per browser) // duplicates FileLoader.delayedEval() - if you change this code, be sure to update that // method. // reportErrors optional param defaults to true globalEvalWithCapture : function (evalString, callback, evalVars, reportErrors) { if (reportErrors == null) reportErrors = true; //!OBFUSCATEOK // store these on these object - really for Safari's benefit, since it's the only one // requiring async execution. This makes the Safari case below easier. this._globalEvalVars = evalVars; this._globalEvalCallback = callback; if (isc.Browser.isSafari) { // This is the only mechanism that works for Safari. This presents an extra // challenge for supporting globals capture and evalVars. evalString = "isc.Class._globalEvalWithCaptureStart();\n" +evalString+"\nisc.Class._globalEvalWithCaptureEnd();"; window.setTimeout(evalString,0); return; } this._globalEvalWithCaptureStart(evalVars); // If an error occurs during eval, capture it and pass it to the completion block to be // provided to the user callback. var error; try { if (isc.Browser.isIE) { // Special IE only function that exports to global scope - can also be used to // execute VBScript code - no other mechanism is known to work window.execScript(evalString, "javascript"); } else { // FF/Moz: eval() doesn't work, but window.eval() does window.eval(evalString); } } catch (e) { // If we have been asked to report errors, do so - also hang onto the error so // the callback can make use of it if necessary if (reportErrors) isc.Log._reportJSError(e); error = e; } this._globalEvalWithCaptureEnd(error); }, _globalEvalWithCaptureStart : function () { // evalVars must go onto the window object - make sure we don't overwrite existing // values by holding on to any conflicting refs so we can restore later var undef, evalVars = this._globalEvalVars; this._restoreGlobals = {}; if (evalVars) { for (var evalVar in evalVars) { var globalValue = window[evalVar]; // need to be careful to preserve nulls, zeroes - so check that the value is // actually undefined. if (globalValue !== undef) this._restoreGlobals[evalVar] = globalValue; window[evalVar] = evalVars[evalVar]; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -