Skip to content

Commit

Permalink
Merge pull request #253 from enyojs/bindSafely
Browse files Browse the repository at this point in the history
add enyo.Object.bindSafely and core core to use it in preference to enyo.bind
  • Loading branch information
clinuz committed Mar 27, 2013
2 parents b2f05ea + 0dbe797 commit f7702eb
Show file tree
Hide file tree
Showing 17 changed files with 101 additions and 74 deletions.
29 changes: 14 additions & 15 deletions samples/GestureSample.js
Expand Up @@ -4,7 +4,7 @@ enyo.kind({
classes: "gesture-sample enyo-fit enyo-unselectable",
components: [
{
classes:"gesture-sample-pad",
classes:"gesture-sample-pad",
fit:true,
ondown: "handleEvent",
onup: "handleEvent",
Expand Down Expand Up @@ -54,9 +54,12 @@ enyo.kind({
this.inherited(arguments);
this.eventList = {};
this.eventCount = 0;
enyo.forEach(["All events","down","up","tap","move","enter","leave","dragstart","drag","dragover","hold","release","holdpulse","flick","gesturestart","gesturechange","gestureend"], enyo.bind(this, function(event) {
this.$.eventPicker.createComponent({content:event, style:"text-align:left"});
}));
enyo.forEach(
["All events","down","up","tap","move","enter","leave","dragstart","drag","dragover","hold","release",
"holdpulse","flick","gesturestart","gesturechange","gestureend"],
this.bindSafely(function(event) {
this.$.eventPicker.createComponent({content:event, style:"text-align:left"});
}));
},
handleEvent: function(inSender, inEvent) {
var event = enyo.clone(inEvent);
Expand All @@ -65,13 +68,13 @@ enyo.kind({
}
var eventItem = this.eventList[event.type];
if (eventItem) {
eventItem.setEvent(event);
eventItem.set("event", event, true);
} else {
this.eventCount++;
eventItem = this.$.eventList.createComponent({
kind: "enyo.sample.EventItem",
event:event,
truncate: this.$.truncateDetail.getValue(),
truncate: this.$.truncateDetail.get("value"),
persist: this.monitorEvent
});
this.eventList[event.type] = eventItem;
Expand All @@ -83,7 +86,7 @@ enyo.kind({
},
truncateChanged: function() {
for (var i in this.eventList) {
this.eventList[i].setTruncate(this.$.truncateDetail.getValue());
this.eventList[i].set("truncate", this.$.truncateDetail.get("value"));
}
this.reflow();
return false;
Expand All @@ -108,7 +111,7 @@ enyo.kind({
this.reflow();
},
toggleSettings: function() {
this.$.settings.setShowing(!this.$.settings.getShowing());
this.$.settings.set("showing", !this.$.settings.get("showing"));
this.reflow();
},
preventDefault: function() {
Expand Down Expand Up @@ -147,18 +150,14 @@ enyo.kind({
truncateChanged: function() {
this.$.eventProps.addRemoveClass("gesture-sample-truncate", this.truncate);
},
// since event is an object, force set
setEvent: function(inEvent) {
this.setPropertyValue("event", inEvent, "eventChanged");
},
eventChanged: function(inOld) {
if (this.event) {
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
this.$.animator.stop();
this.$.eventProps.setContent(this.getPropsString());
this.$.eventProps.set("content", this.getPropsString());
this.$.animator.play();
}
},
Expand All @@ -168,7 +167,7 @@ enyo.kind({
},
animationEnded: function() {
if (!this.persist) {
this.timeout = setTimeout(enyo.bind(this, function() {
this.timeout = setTimeout(this.bindSafely(function() {
this.doDone({type:this.event.type});
}), 2000);
}
Expand All @@ -185,7 +184,7 @@ enyo.kind({
for (var i in this.event) {
if ((this.event[i] !== undefined) &&
(this.event[i] !== null) &&
!(this.event[i] instanceof Object) &&
!(this.event[i] instanceof Object) &&
(i != "type")) {
props.push(i + ": " + this.event[i]);
}
Expand Down
2 changes: 1 addition & 1 deletion source/ajax/Ajax.js
Expand Up @@ -123,7 +123,7 @@ enyo.kind({
this.xhr = enyo.xhr.request({
url: url,
method: this.method,
callback: enyo.bind(this, "receive"),
callback: this.bindSafely("receive"),
body: body,
headers: xhr_headers,
sync: window.PalmSystem ? false : this.sync,
Expand Down
6 changes: 3 additions & 3 deletions source/ajax/Async.js
Expand Up @@ -56,11 +56,11 @@ enyo.kind({
},
//* @protected
route: function(inAsync, inValue) {
var r = enyo.bind(this, "respond");
var r = this.bindSafely("respond");
inAsync.response(function(inSender, inValue) {
r(inValue);
});
var f = enyo.bind(this, "fail");
var f = this.bindSafely("fail");
inAsync.error(function(inSender, inValue) {
f(inValue);
});
Expand All @@ -84,7 +84,7 @@ enyo.kind({
startTimer: function() {
this.startTime = enyo.now();
if (this.timeout) {
this.timeoutJob = setTimeout(enyo.bind(this, "timeoutComplete"), this.timeout);
this.timeoutJob = setTimeout(this.bindSafely("timeoutComplete"), this.timeout);
}
},
endTimer: function() {
Expand Down
6 changes: 3 additions & 3 deletions source/ajax/Jsonp.js
Expand Up @@ -48,7 +48,7 @@ enyo.kind({
script.charset = this.charset;
}
// most modern browsers also have an onerror handler
script.onerror = enyo.bind(this, function() {
script.onerror = this.bindSafely(function() {
// we don't get an error code, so we'll just use the generic 400 error status
this.fail(400);
});
Expand Down Expand Up @@ -84,10 +84,10 @@ enyo.kind({
this.src = this.buildUrl(inParams, callbackFunctionName);
this.addScriptElement();
//
window[callbackFunctionName] = enyo.bind(this, this.respond);
window[callbackFunctionName] = this.bindSafely(this.respond);
//
// setup cleanup handlers for JSONP completion and failure
var cleanup = enyo.bind(this, function() {
var cleanup = this.bindSafely(function() {
this.removeScriptElement();
window[callbackFunctionName] = null;
});
Expand Down
4 changes: 2 additions & 2 deletions source/kernel/Component.js
Expand Up @@ -473,7 +473,7 @@ enyo.kind({
this._silenced = true;
this._silence_count += 1;
},

//*@public
/**
If the internal silence counter is 0 this method will allow
Expand All @@ -500,7 +500,7 @@ enyo.kind({
}
// stop any existing jobs with same name
this.stopJob(inJobName);
this.__jobs[inJobName] = setTimeout(enyo.bind(this, function() {
this.__jobs[inJobName] = setTimeout(this.bindSafely(function() {
this.stopJob(inJobName);
// call "inJob" with this bound to the component.
inJob.call(this);
Expand Down
44 changes: 36 additions & 8 deletions source/kernel/Object.js
Expand Up @@ -36,7 +36,7 @@ enyo.kind({
enyo._objectCount++;
this.importProps(props);
},

importProps: function (props) {
if (props) {
for (var key in props) {
Expand Down Expand Up @@ -99,7 +99,7 @@ enyo.kind({
a string the object will attempt to be resolved. The goal is
to determine of the the property is a constructor, an instance or
nothing. See _lang.js#enyo.findAndInstance_ for more information.
If a method exists of the form `{property}FindAndInstance` it will
be used as the callback accepting two parameters, the constructor
if it was found and the instance if it was found or created,
Expand All @@ -113,15 +113,15 @@ enyo.kind({
// go ahead and call the enyo scoped version of this method
return enyo.findAndInstance.call(this, property, fn, this);
},

//*@public
/**
Call this method with the name (or path) to the desired property or
computed property. If it encounters a computed property it will return
the value of that property and not the function. If it cannot find
or resolve the requested path relative to the object it will return
undefined.
This method is backwards compatible and will automatically call any
existing _getter_ method that uses the getProperty convention although
this convention ought to be replaced using a computed property moving
Expand All @@ -137,7 +137,7 @@ enyo.kind({
been changed if the values are not the same. If the property it finds
is a computed property it will pass the intended value to the computed
property (but will not return the value).
This method is backwards compatible and will call any setter of the
setProperty convention although these methods should be replaced with
computed properties or observers where necessary.
Expand All @@ -146,14 +146,42 @@ enyo.kind({
return enyo.setPath.apply(this, arguments);
},

//*@public
/**
Bind a callback to this object. The bound method will be aborted cleanly with no
return value if the object has been destroyed. This usually should be used instead
of `enyo.bind` for running code in the context of a enyo.Object-derivative.
*/
bindSafely: function(method/*, bound arguments*/) {
var scope = this;
if (enyo.isString(method)) {
if (this[method]) {
method = this[method];
} else {
throw(['enyo.Object.bindSafely: this["', method, '"] is null (this="', this, '")'].join(''));
}
}
if (enyo.isFunction(method)) {
var args = enyo.cloneArray(arguments, 2);
return function() {
if (scope.destroyed) {
return;
}
var nargs = enyo.cloneArray(arguments);
return method.apply(scope, args.concat(nargs));
};
} else {
throw(['enyo.Object.bindSafely: this["', method, '"] is not a function (this="', this, '")'].join(''));
}
},
//*@protected
destroy: function () {
// JS objects are never truly destroyed (GC'd) until all references are gone,
// we might have some delayed action on this object that needs to have access
// to this flag.
this.destroyed = true;
},

_is_object: true
});

Expand Down Expand Up @@ -219,7 +247,7 @@ enyo.Object.addGetterSetter = function (property, value, proto) {
fn = proto[getter];
// if there isn't already a getter provided create one
if ("function" !== typeof fn) {
fn = proto[getter] = function () {return this.get(property)};
fn = proto[getter] = function () {return this.get(property);};
fn.overloaded = false;
} else if (false !== fn.overloaded) {
// otherwise we need to mark it as having been overloaded
Expand All @@ -229,7 +257,7 @@ enyo.Object.addGetterSetter = function (property, value, proto) {
// if there isn't already a setter provided create one
fn = proto[setter];
if ("function" !== typeof fn) {
fn = proto[setter] = function () {return this.set(property, arguments[0])};
fn = proto[setter] = function () {return this.set(property, arguments[0]);};
fn.overloaded = false;
} else if (false !== fn.overloaded) {
// otherwise we need to mark it as having been overloaded
Expand Down
8 changes: 4 additions & 4 deletions source/kernel/Oop.js
Expand Up @@ -79,12 +79,12 @@ enyo.kind = function(inProps) {
// create our prototype
//ctor.prototype = isa ? enyo.delegate(isa) : {};
enyo.setPrototype(ctor, isa ? enyo.delegate(isa) : {});

// there are special cases where a base class has a property
// that may need to be concatenated with a subclasses implementation
// as opposed to completely overwriting it...
enyo.handleConcatenatedProperties(ctor.prototype, inProps);

// put in our props
enyo.mixin(ctor.prototype, inProps);
// alias class name as 'kind' in the prototype
Expand Down Expand Up @@ -141,7 +141,7 @@ enyo.singleton = function(conf, context) {

//* @protected
enyo.kind.makeCtor = function() {
return function() {;
return function() {
if (!(this instanceof arguments.callee)) {
throw "enyo.kind: constructor called directly, not using 'new'";
}
Expand All @@ -158,7 +158,7 @@ enyo.kind.makeCtor = function() {
// post-constructor initialization
this.constructed.apply(this, arguments);
}

for (var idx = 0; idx < enyo.kind.postConstructors.length; ++idx) {
enyo.kind.postConstructors[idx].apply(this, cargs);
}
Expand Down
2 changes: 1 addition & 1 deletion source/kernel/job.js
Expand Up @@ -9,7 +9,7 @@
onscroll: function() {
// updateThumb will be called, but only when 1s has elapsed since the
// last onscroll
enyo.job("updateThumb", enyo.bind(this, "updateThumb"), 1000);
enyo.job("updateThumb", this.bindSafely("updateThumb"), 1000);
}
*/
enyo.job = function(inJobName, inJob, inWait) {
Expand Down
2 changes: 1 addition & 1 deletion source/touch/ScrollMath.js
Expand Up @@ -151,7 +151,7 @@ enyo.kind({
// delta tracking
var x0, y0;
// animation handler
var fn = enyo.bind(this, function() {
var fn = this.bindSafely(function() {
// wall-clock time
var t1 = enyo.now();
// schedule next frame
Expand Down
2 changes: 1 addition & 1 deletion source/touch/Thumb.js
Expand Up @@ -102,7 +102,7 @@ enyo.kind({
},
delayHide: function(inDelay) {
if (this.showing) {
enyo.job(this.id + "hide", enyo.bind(this, "hide"), inDelay || 0);
enyo.job(this.id + "hide", this.bindSafely("hide"), inDelay || 0);
}
},
cancelDelayHide: function() {
Expand Down
10 changes: 5 additions & 5 deletions source/touch/TransitionScrollStrategy.js
Expand Up @@ -522,7 +522,7 @@ enyo.kind({
// crossing into the overflow region, and bubble a scroll event
setCSSTransitionInterval: function() {
this.clearCSSTransitionInterval();
this.scrollInterval = setInterval(enyo.bind(this, function() {
this.scrollInterval = setInterval(this.bindSafely(function() {
this.updateScrollPosition();
this.correctOverflow();
}), this.scrollIntervalMS);
Expand All @@ -531,7 +531,7 @@ enyo.kind({
// a scroll event (don't check for crossing into overflow since we're there already)
setOverflowTransitionInterval: function() {
this.clearCSSTransitionInterval();
this.scrollInterval = setInterval(enyo.bind(this, function() {
this.scrollInterval = setInterval(this.bindSafely(function() {
this.updateScrollPosition();
}), this.scrollIntervalMS);
},
Expand Down Expand Up @@ -575,17 +575,17 @@ enyo.kind({
if(inEvent.originator !== this.$.client) {
return;
}

var posChanged = false;

if(this.isInTopOverScroll()) {
posChanged = true;
this.scrollTop = this.topBoundary;
} else if (this.isInBottomOverScroll()) {
posChanged = true;
this.scrollTop = -1*this.bottomBoundary;
}

if(this.isInLeftOverScroll()) {
posChanged = true;
this.scrollLeft = this.leftBoundary;
Expand Down
2 changes: 1 addition & 1 deletion source/ui/Animator.js
Expand Up @@ -44,7 +44,7 @@ enyo.kind({
//* @protected
constructed: function() {
this.inherited(arguments);
this._next = enyo.bind(this, "next");
this._next = this.bindSafely("next");
},
destroy: function() {
this.stop();
Expand Down

0 comments on commit f7702eb

Please sign in to comment.