Skip to content

Commit

Permalink
Merge pull request #3623 from bryan-m-hughes/timob-10464
Browse files Browse the repository at this point in the history
[TIMOB-10464] Event bubbling architecture changes
  • Loading branch information
cb1kenobi committed Jan 10, 2013
2 parents 7cc547a + 435f29c commit 003d852
Show file tree
Hide file tree
Showing 28 changed files with 1,018 additions and 1,086 deletions.
224 changes: 167 additions & 57 deletions mobileweb/titanium/Ti/UI.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
/*global Ti define window document navigator instrumentation*/
define(
["Ti/_", "Ti/_/Evented", "Ti/_/has", "Ti/_/lang", "Ti/_/ready", "Ti/_/style", "Ti/_/dom"],
function(_, Evented, has, lang, ready, style, dom) {
['Ti/_', 'Ti/_/Evented', 'Ti/_/has', 'Ti/_/lang', 'Ti/_/ready', 'Ti/_/style', 'Ti/_/dom', 'Ti/_/event',
'Ti/_/Gestures/DoubleTap', 'Ti/_/Gestures/Dragging', 'Ti/_/Gestures/LongPress', 'Ti/_/Gestures/Pinch', 'Ti/_/Gestures/SingleTap',
'Ti/_/Gestures/Swipe', 'Ti/_/Gestures/TouchCancel', 'Ti/_/Gestures/TouchEnd', 'Ti/_/Gestures/TouchMove',
'Ti/_/Gestures/TouchStart', 'Ti/_/Gestures/TwoFingerTap'],
function(_, Evented, has, lang, ready, style, dom, event,
DoubleTap, Dragging, LongPress, Pinch, SingleTap, Swipe, TouchCancel, TouchEnd, TouchMove, TouchStart, TwoFingerTap) {

var global = window,
doc = document,
body = doc.body,
on = require.on,
modules = "2DMatrix,ActivityIndicator,AlertDialog,Animation,Button,EmailDialog,ImageView,Label,OptionDialog,Picker,PickerColumn,PickerRow,ProgressBar,ScrollableView,ScrollView,Slider,Switch,Tab,TabGroup,TableView,TableViewRow,TableViewSection,TextArea,TextField,View,WebView,Window",
is = require.is,
modules = '2DMatrix,ActivityIndicator,AlertDialog,Animation,Button,EmailDialog,ImageView,Label,OptionDialog,Picker,PickerColumn,PickerRow,ProgressBar,ScrollableView,ScrollView,Slider,Switch,Tab,TabGroup,TableView,TableViewRow,TableViewSection,TextArea,TextField,View,WebView,Window',
creators = {},
setStyle = style.set,
handheld = navigator.userAgent.toLowerCase().match(/(iphone|android)/),
iphone = handheld && handheld[0] === "iphone",
iphone = handheld && handheld[0] === 'iphone',
targetHeight = {},
hidingAddressBar,
finishAddressBar = function() {
Expand All @@ -20,23 +26,36 @@ define(
hideAddressBar = finishAddressBar,
splashScreen,
unitize = dom.unitize,
Gesture;

on(body, "touchmove", function(e) {
Gesture,
recognizers = [
TouchStart,
TouchEnd,
TouchMove,
TouchCancel,
Dragging,
SingleTap,
DoubleTap,
LongPress,
Pinch,
Swipe,
TwoFingerTap
];

on(body, 'touchmove', function(e) {
e.preventDefault();
});

modules.split(',').forEach(function(name) {
creators['create' + name] = function(args) {
return new (require("Ti/UI/" + name))(args);
return new (require('Ti/UI/' + name))(args);
};
});

if (!navigator.standalone && handheld) {
hideAddressBar = function() {
if (!hidingAddressBar) {
hidingAddressBar = 1;
var isPortrait = require("Ti/Gesture").isPortrait | 0,
var isPortrait = require('Ti/Gesture').isPortrait | 0,
h = targetHeight[isPortrait],
timer;

Expand All @@ -52,7 +71,7 @@ define(
targetHeight[isPortrait] = h;
}

setStyle(body, "height", h + "px");
setStyle(body, 'height', h + 'px');

if (iphone) {
global.scrollTo(0, 0);
Expand All @@ -67,33 +86,35 @@ define(
}, 50);
}
}
}
};
ready(hideAddressBar);
on(global, "orientationchange", hideAddressBar);
on(global, "touchstart", hideAddressBar);
on(global, 'orientationchange', hideAddressBar);
on(global, 'touchstart', hideAddressBar);
}

ready(10, function() {
setTimeout(function() {
var container = (Ti.UI._container = Ti.UI.createView({
var container = Ti.UI._container = Ti.UI.createView({
left: 0,
top: 0
})),
}),
node = container.domNode,
coefficients = container._layoutCoefficients;
coefficients = container._layoutCoefficients,
useTouch = 'ontouchstart' in global,
touching = 0;

coefficients.width.x1 = 1;
coefficients.height.x1 = 1;
container._measuredTop = 0;
container._measuredLeft = 0;
node.id = "TiUIContainer";
setStyle(node, "overflow", "hidden");
node.id = 'TiUIContainer';
setStyle(node, 'overflow', 'hidden');
body.appendChild(node);

(splashScreen = doc.getElementById("splash")) && container.addEventListener("postlayout", function(){
(splashScreen = doc.getElementById('splash')) && container.addEventListener('postlayout', function(){
setTimeout(function(){
setStyle(splashScreen,{
position: "absolute",
position: 'absolute',
width: unitize(container._measuredWidth),
height: unitize(container._measuredHeight),
left: 0,
Expand All @@ -104,14 +125,66 @@ define(
}, 10);
});
hideAddressBar();

function processTouchEvent(eventType, evt) {
var i = 0, len = recognizers.length,
j,
events = [],
results,
recognizer,
elements = evt._elements;

if (elements && elements.length) {
// Convert mouse* events to touch* events
useTouch || require.mix(evt, {
touches: evt.type === 'mouseup' ? [] : [evt],
targetTouches: [],
changedTouches: [evt]
});

// Calculate the set of gesture events
for (; i < len; i++) {
recognizer = recognizers[i]['process' + eventType];
if (recognizer) {
results = recognizer(evt, elements);
for(j in results) {
events[j] || (events[j] = []);
events[j] = events[j].concat(results[j]);
}
}
}

// Fire the events
Ti.UI._fireGestureEvents(events, elements);
}
}

on(node, useTouch ? 'touchstart' : 'mousedown', function(evt){
var handles = [
on(global, useTouch ? 'touchmove' : 'mousemove', function(evt){
(useTouch || touching) && processTouchEvent('TouchMoveEvent', evt);
}),
on(global, useTouch ? 'touchend' : 'mouseup', function(evt){
touching = 0;
processTouchEvent('TouchEndEvent', evt);
event.off(handles);
}),
useTouch && on(global, 'touchcancel', function(evt){
processTouchEvent('TouchCancelEvent', evt);
event.off(handles);
})
];
touching = 1;
processTouchEvent('TouchStartEvent', evt);
});
}, 1);
});

on(global, "resize", function() {
on(global, 'resize', function() {
Ti.UI._recalculateLayout();
});

return lang.setObject("Ti.UI", Evented, creators, {
return lang.setObject('Ti.UI', Evented, creators, {

_addWindow: function(win, set) {
this._container.add(win.modal ? win._modalParentContainer : win);
Expand All @@ -132,6 +205,44 @@ define(
return win;
},

_fireGestureEvents: function(events, elements) {
var i = 0, len = recognizers.length,
j,
x, y, pt,
sourceIndex = 0,
e;

// Fire the events
while(elements[sourceIndex] && !elements[sourceIndex]._isPublished) {
sourceIndex++;
}
elements[sourceIndex] || (sourceIndex = 0);
for (i in events) {
for (j = 0, len = events[i].length; j < len; j++) {

// Create the event object with proper relative locations, etc
e = events[i][j];
if (is(e.x, 'Number') && is(e.y, 'Number')) {
pt = this._container.convertPointToView({
x: e.x,
y: e.y
}, elements[sourceIndex]);
x = pt ? pt.x : e.x;
y = pt ? pt.y : e.y;
} else {
x = y = void 0;
}
e.x = x;
e.y = y;
e.bubbles = true;
e.cancelBubble = false; // We use true and false here instead of 0 and 1 because they are user facing

// Fire the event
elements[0].fireEvent(i, e);
}
}
},

_layoutSemaphore: 0,

_nodesToLayout: [],
Expand Down Expand Up @@ -175,7 +286,7 @@ define(
j,
len = nodes.length;

has("ti-instrumentation") && (self._layoutInstrumentationTest = instrumentation.startTest("Layout"));
has('ti-instrumentation') && (self._layoutInstrumentationTest = instrumentation.startTest('Layout'));

// Determine which nodes need to be re-layed out
for (i = 0; i < len; i++) {
Expand All @@ -189,7 +300,7 @@ define(
children = node._children;
for (j in children) {
child = children[j];
if (node.layout !== "composite" || child._needsMeasuring || node._layout._isDependentOnParent(child)) {
if (node.layout !== 'composite' || child._needsMeasuring || node._layout._isDependentOnParent(child)) {
recursionStack.push(child);
}
}
Expand Down Expand Up @@ -222,7 +333,7 @@ define(
children = node._children;
for (j in children) {
child = children[j];
if (child !== previousParent && (node.layout !== "composite" || child._needsMeasuring || node._layout._isDependentOnParent(child))) {
if (child !== previousParent && (node.layout !== 'composite' || child._needsMeasuring || node._layout._isDependentOnParent(child))) {
child._markedForLayout = true;
recursionStack.push(child);
}
Expand All @@ -239,20 +350,19 @@ define(

// Layout all nodes that need it
if (layoutRootNode) {
var container = self._container,
props = container.properties.__values__,
var props = container.properties.__values__,
width = container._measuredWidth = props.width = global.innerWidth,
height = container._measuredHeight = props.height = global.innerHeight;
container._measuredSandboxWidth = width;
container._measuredSandboxHeight = height;
container.fireEvent("postlayout");
container.fireEvent('postlayout');
setStyle(container.domNode, {
width: width + "px",
height: height + "px"
width: width + 'px',
height: height + 'px'
});
container._layout._doLayout(container, width, height, false, false);
}
for (var i in rootNodesToLayout) {
for (i = 0; i < rootNodesToLayout.length; i++) {
node = rootNodesToLayout[i];
node._layout._doLayout(node,
node._measuredWidth - node._borderLeftWidth - node._borderRightWidth,
Expand All @@ -261,14 +371,14 @@ define(
node._parent._layout._getHeight(node, node.height) === Ti.UI.SIZE);
}

has("ti-instrumentation") && instrumentation.stopTest(self._layoutInstrumentationTest,
self._elementLayoutCount + " out of approximately " + document.getElementById("TiUIContainer").getElementsByTagName("*").length + " elements laid out.");
has('ti-instrumentation') && instrumentation.stopTest(self._layoutInstrumentationTest,
self._elementLayoutCount + ' out of approximately ' + document.getElementById('TiUIContainer').getElementsByTagName('*').length + ' elements laid out.');

self._layoutInProgress = false;
self._layoutTimer = null;
self._nodesToLayout = [];
self.fireEvent("postlayout");

self.fireEvent('postlayout');
}

if (force) {
Expand All @@ -282,7 +392,7 @@ define(
},

_recalculateLayout: function() {
Gesture || (Gesture = require("Ti/Gesture"));
Gesture || (Gesture = require('Ti/Gesture'));
Gesture._updateOrientation();
var container = this._container;
if (container) {
Expand All @@ -299,7 +409,7 @@ define(
},
backgroundImage: {
set: function(value) {
return setStyle(body, "backgroundImage", value ? style.url(value) : "");
return setStyle(body, 'backgroundImage', value ? style.url(value) : '');
}
},
currentTab: void 0
Expand Down Expand Up @@ -357,35 +467,35 @@ define(
RETURNKEY_SEARCH: 8, // Search
RETURNKEY_SEND: 9, // Send
RETURNKEY_YAHOO: 10, // Search
TEXT_ALIGNMENT_CENTER: "center",
TEXT_ALIGNMENT_RIGHT: "right",
TEXT_ALIGNMENT_LEFT: "left",
TEXT_ALIGNMENT_CENTER: 'center',
TEXT_ALIGNMENT_RIGHT: 'right',
TEXT_ALIGNMENT_LEFT: 'left',
TEXT_AUTOCAPITALIZATION_ALL: 3,
TEXT_AUTOCAPITALIZATION_NONE: 0,
TEXT_AUTOCAPITALIZATION_SENTENCES: 2,
TEXT_AUTOCAPITALIZATION_WORDS: 1,
TEXT_VERTICAL_ALIGNMENT_BOTTOM: "bottom",
TEXT_VERTICAL_ALIGNMENT_CENTER: "center",
TEXT_VERTICAL_ALIGNMENT_TOP: "top",
TEXT_VERTICAL_ALIGNMENT_BOTTOM: 'bottom',
TEXT_VERTICAL_ALIGNMENT_CENTER: 'center',
TEXT_VERTICAL_ALIGNMENT_TOP: 'top',
ANIMATION_CURVE_EASE_IN: 1,
ANIMATION_CURVE_EASE_IN_OUT: 0,
ANIMATION_CURVE_EASE_OUT: 2,
ANIMATION_CURVE_LINEAR: 3,
SIZE: "auto",
FILL: "fill",
INHERIT: "inherit",
UNIT_PX: "px",
UNIT_MM: "mm",
UNIT_CM: "cm",
UNIT_IN: "in",
UNIT_DIP: "dp", // We don't have DIPs, so we treat them as pixels
SIZE: 'auto',
FILL: 'fill',
INHERIT: 'inherit',
UNIT_PX: 'px',
UNIT_MM: 'mm',
UNIT_CM: 'cm',
UNIT_IN: 'in',
UNIT_DIP: 'dp', // We don't have DIPs, so we treat them as pixels

// Hidden constants
_LAYOUT_COMPOSITE: "composite",
_LAYOUT_VERTICAL: "vertical",
_LAYOUT_HORIZONTAL: "horizontal",
_LAYOUT_CONSTRAINING_VERTICAL: "constrainingVertical",
_LAYOUT_CONSTRAINING_HORIZONTAL: "constrainingHorizontal"
_LAYOUT_COMPOSITE: 'composite',
_LAYOUT_VERTICAL: 'vertical',
_LAYOUT_HORIZONTAL: 'horizontal',
_LAYOUT_CONSTRAINING_VERTICAL: 'constrainingVertical',
_LAYOUT_CONSTRAINING_HORIZONTAL: 'constrainingHorizontal'
}

});
Expand Down
2 changes: 1 addition & 1 deletion mobileweb/titanium/Ti/UI/Label.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ define(["Ti/_/declare", "Ti/_/UI/FontWidget", "Ti/_/dom", "Ti/_/css", "Ti/_/styl

_setText: function() {
this._textContainerDomNode.innerHTML = this._getText();
this._hasSizeDimensions() && this._triggerLayout();
this._triggerLayout();
},

_setTextShadow: function() {
Expand Down

0 comments on commit 003d852

Please sign in to comment.