Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' into addItems-nullTag

  • Loading branch information...
commit 24789638ab705631801eca10aeab2a388e030f81 2 parents 2a41ac5 + 53d4988
Ben Combee authored
Showing with 617 additions and 320 deletions.
  1. +3 −3 samples/AjaxSample.html
  2. +3 −3 samples/GestureSample.html
  3. +3 −3 samples/JsonpSample.html
  4. +2 −2 samples/PlatformSample.html
  5. +1 −1  samples/PlatformSample.js
  6. +3 −3 samples/Playground.html
  7. +3 −3 samples/RepeaterSample.html
  8. +3 −3 samples/ScrollerSample.html
  9. +3 −3 samples/WebServiceSample.html
  10. +44 −44 source/ajax/Ajax.js
  11. +9 −3 source/ajax/AjaxProperties.js
  12. +22 −15 source/ajax/WebService.js
  13. +1 −1  source/ajax/cookie.js
  14. +12 −4 source/ajax/formdata.js
  15. +16 −3 source/ajax/xhr.js
  16. +8 −4 source/dom/Control.js
  17. +24 −1 source/dom/dispatcher.js
  18. +4 −0 source/dom/dom.css
  19. +70 −0 source/dom/dom.js
  20. +5 −5 source/dom/drag.js
  21. +25 −23 source/kernel/Component.js
  22. +1 −1  source/kernel/Oop.js
  23. +1 −1  source/kernel/UiComponent.js
  24. +1 −1  source/touch/ScrollMath.js
  25. +11 −3 source/touch/TouchScrollStrategy.js
  26. +202 −154 source/touch/TransitionScrollStrategy.js
  27. +3 −3 source/touch/touch.js
  28. +7 −1 source/ui/Input.js
  29. +5 −5 source/ui/Popup.js
  30. +4 −0 tools/minifier/minify.js
  31. +33 −20 tools/test/ajax/tests/AjaxTest.js
  32. +2 −2 tools/test/ajax/tests/JsonpTest.js
  33. +1 −1  tools/test/ajax/tests/WebServiceTest.js
  34. +80 −0 tools/test/core/tests/ViewportPositioningTest.js
  35. +2 −1  tools/test/core/tests/package.js
View
6 samples/AjaxSample.html
@@ -5,7 +5,7 @@
<!-- -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- -->
- <script src="../enyo.js" type="text/javascript"></script>
+ <script src="../../enyo/enyo.js" type="text/javascript"></script>
<script src="../../lib/layout/package.js" type="text/javascript"></script>
<script src="../../lib/onyx/package.js" type="text/javascript"></script>
<!-- -->
@@ -13,9 +13,9 @@
<script src="AjaxSample.js" type="text/javascript"></script>
<!-- -->
</head>
-<body>
+<body class="onyx">
<script type="text/javascript">
- new enyo.sample.AjaxSample().write();
+ new enyo.sample.AjaxSample().renderInto(document.body);
</script>
</body>
</html>
View
6 samples/GestureSample.html
@@ -5,7 +5,7 @@
<!-- -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- -->
- <script src="../enyo.js" type="text/javascript"></script>
+ <script src="../../enyo/enyo.js" type="text/javascript"></script>
<script src="../../lib/layout/package.js" type="text/javascript"></script>
<script src="../../lib/onyx/package.js" type="text/javascript"></script>
<!-- -->
@@ -13,9 +13,9 @@
<script src="GestureSample.js" type="text/javascript"></script>
<!-- -->
</head>
-<body>
+<body class="onyx">
<script type="text/javascript">
- new enyo.sample.GestureSample().write();
+ new enyo.sample.GestureSample().renderInto(document.body);
</script>
</body>
</html>
View
6 samples/JsonpSample.html
@@ -5,7 +5,7 @@
<!-- -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- -->
- <script src="../enyo.js" type="text/javascript"></script>
+ <script src="../../enyo/enyo.js" type="text/javascript"></script>
<script src="../../lib/layout/package.js" type="text/javascript"></script>
<script src="../../lib/onyx/package.js" type="text/javascript"></script>
<!-- -->
@@ -13,9 +13,9 @@
<script src="JsonpSample.js" type="text/javascript"></script>
<!-- -->
</head>
-<body>
+<body class="onyx">
<script type="text/javascript">
- new enyo.sample.JsonpSample().write();
+ new enyo.sample.JsonpSample().renderInto(document.body);
</script>
</body>
</html>
View
4 samples/PlatformSample.html
@@ -5,7 +5,7 @@
<!-- -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- -->
- <script src="../enyo.js" type="text/javascript"></script>
+ <script src="../../enyo/enyo.js" type="text/javascript"></script>
<script src="../../lib/layout/package.js" type="text/javascript"></script>
<script src="../../lib/onyx/package.js" type="text/javascript"></script>
<!-- -->
@@ -13,7 +13,7 @@
<script src="PlatformSample.js" type="text/javascript"></script>
<!-- -->
</head>
-<body>
+<body class="onyx">
<script type="text/javascript">
new enyo.sample.PlatformSample().renderInto(document.body);
</script>
View
2  samples/PlatformSample.js
@@ -26,7 +26,7 @@ enyo.kind({
create: function() {
this.inherited(arguments);
this.$.uaString.setContent(navigator.userAgent);
- this.$.enyoPlatformJSON.setContent(JSON.stringify(enyo.platform));
+ this.$.enyoPlatformJSON.setContent(JSON.stringify(enyo.platform, null, 1));
this.updateWindowSize();
},
resizeHandler: function() {
View
6 samples/Playground.html
@@ -5,7 +5,7 @@
<!-- -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- -->
- <script src="../enyo.js" type="text/javascript"></script>
+ <script src="../../enyo/enyo.js" type="text/javascript"></script>
<script src="../../lib/canvas/package.js" type="text/javascript"></script>
<script src="../../lib/layout/package.js" type="text/javascript"></script>
<script src="../../lib/onyx/package.js" type="text/javascript"></script>
@@ -15,9 +15,9 @@
<script src="Playground.js" type="text/javascript"></script>
<!-- -->
</head>
-<body>
+<body class="onyx">
<script type="text/javascript">
- new enyo.sample.Playground().write();
+ new enyo.sample.Playground().renderInto(document.body);
</script>
</body>
</html>
View
6 samples/RepeaterSample.html
@@ -5,7 +5,7 @@
<!-- -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- -->
- <script src="../enyo.js" type="text/javascript"></script>
+ <script src="../../enyo/enyo.js" type="text/javascript"></script>
<script src="../../lib/layout/package.js" type="text/javascript"></script>
<script src="../../lib/onyx/package.js" type="text/javascript"></script>
<!-- -->
@@ -13,9 +13,9 @@
<script src="RepeaterSample.js" type="text/javascript"></script>
<!-- -->
</head>
-<body>
+<body class="onyx">
<script type="text/javascript">
- new enyo.sample.RepeaterSample().write();
+ new enyo.sample.RepeaterSample().renderInto(document.body);
</script>
</body>
</html>
View
6 samples/ScrollerSample.html
@@ -5,7 +5,7 @@
<!-- -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- -->
- <script src="../enyo.js" type="text/javascript"></script>
+ <script src="../../enyo/enyo.js" type="text/javascript"></script>
<script src="../../lib/layout/package.js" type="text/javascript"></script>
<script src="../../lib/onyx/package.js" type="text/javascript"></script>
<!-- -->
@@ -13,9 +13,9 @@
<script src="ScrollerSample.js" type="text/javascript"></script>
<!-- -->
</head>
-<body>
+<body class="onyx">
<script type="text/javascript">
- new enyo.sample.ScrollerSample().write();
+ new enyo.sample.ScrollerSample().renderInto(document.body);
</script>
</body>
</html>
View
6 samples/WebServiceSample.html
@@ -5,7 +5,7 @@
<!-- -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- -->
- <script src="../enyo.js" type="text/javascript"></script>
+ <script src="../../enyo/enyo.js" type="text/javascript"></script>
<script src="../../lib/layout/package.js" type="text/javascript"></script>
<script src="../../lib/onyx/package.js" type="text/javascript"></script>
<!-- -->
@@ -13,9 +13,9 @@
<script src="WebServiceSample.js" type="text/javascript"></script>
<!-- -->
</head>
-<body>
+<body class="onyx">
<script type="text/javascript">
- new enyo.sample.WebServiceSample().write();
+ new enyo.sample.WebServiceSample().renderInto(document.body);
</script>
</body>
</html>
View
88 source/ajax/Ajax.js
@@ -31,32 +31,24 @@ enyo.kind({
},
//* @public
/**
- Sends the Ajax request with parameters _inParams_. _inParams_ values may be
- either Strings or Objects.
+ Sends the Ajax request with parameters _inParams_. _inParams_ values may be
+ either Strings or Objects.
- _inParams_ as an Object is converted into the url query string. For
- instance, passing <code>{q: "searchTerm"}</code> will result in the addition
- of the string `q="searchTerm"` to the current url query string.
+ _inParams_ as an Object is converted into the url query string. For
+ instance, passing <code>{q: "searchTerm"}</code> will result in the addition
+ of the string `q="searchTerm"` to the current url query string.
- _inParams_ as a String is used as the request body, and triggers various
- behaviors depending on the query method.
+ _inParams_ as a String is used as the query part of the URL directly.
- * The GET method, since it has no body, translates the string into a
- parameter. Thus `'q="searchTerm"'` translates into `q=searchTerm` in the
- url query string.
+ _inParams_ will not be converted into a POST body, it will always be used as
+ part of the URL query string if provided. Use the `postBody` property for
+ specifying a body.
- * The POST method uses the provided string as its body. However, this will
- be overridden by the value of _postBody_, if set.
-
- The use of _inParams_ as a String is discouraged. Instead, set the request
- body content via _postBody_ and use _inParams_ as an Object to set the query
- string.
-
- When the request is completed, the code will set a `xhrResponse` property
- in the `enyo.Ajax` object with the subproperties `status`, `headers`, and
- `body`. These cache the results from the XHR for later use. The keys for
- the `headers` object have been converted to all lower case as HTTP headers
- are case-insensitive.
+ When the request is completed, the code will set a `xhrResponse` property
+ in the `enyo.Ajax` object with the subproperties `status`, `headers`, and
+ `body`. These cache the results from the XHR for later use. The keys for
+ the `headers` object have been converted to all lower case as HTTP headers
+ are case-insensitive.
*/
go: function(inParams) {
this.startTimer();
@@ -69,35 +61,33 @@ enyo.kind({
var uri = parts.shift() || "";
var args = parts.length ? (parts.join("?").split("&")) : [];
//
- var body = null;
- //
- if(enyo.isString(inParams)){
- //If inParams parameter is a string, use it as request body
- body = inParams;
- }
- else{
- //If inParams parameter is not a string, build a query from it
- if(inParams){
- body = enyo.Ajax.objectToQuery(inParams);
- }
- }
- //
- if (this.method == "GET") {
- if (body) {
- args.push(body);
- body = null;
- }
- // don't use cacheBust on file URLs, can cause problems in Android 4
- if (this.cacheBust && !/^file:/i.test(uri)) {
- args.push(Math.random());
+ var query = null;
+ //
+ if(enyo.isString(inParams)){
+ //If inParams parameter is a string, use it as request body
+ query = inParams;
+ }
+ else{
+ //If inParams parameter is not a string, build a query from it
+ if(inParams){
+ query = enyo.Ajax.objectToQuery(inParams);
}
}
//
+ if (query) {
+ args.push(query);
+ query = null;
+ }
+ if (this.cacheBust) {
+ args.push(Math.random());
+ }
+ //
var url = args.length ? [uri, args.join("&")].join("?") : uri;
//
var xhr_headers = {};
- body = this.postBody || body;
+ var body;
if (this.method != "GET") {
+ body = this.postBody;
if (this.method === "POST" && body instanceof enyo.FormData) {
if (body.fake) {
xhr_headers["Content-Type"] = body.getContentType();
@@ -110,6 +100,16 @@ enyo.kind({
}
} else {
xhr_headers["Content-Type"] = this.contentType;
+ if (body instanceof Object) {
+ if (this.contentType === "application/json") {
+ body = JSON.stringify(body);
+ } else if (this.contentType === "application/x-www-form-urlencoded") {
+ body = enyo.Ajax.objectToQuery(body);
+ }
+ else {
+ body = body.toString();
+ }
+ }
}
}
enyo.mixin(xhr_headers, this.headers);
View
12 source/ajax/AjaxProperties.js
@@ -38,8 +38,14 @@ enyo.AjaxProperties = {
*/
headers: null,
/**
- The content for the request body for POST method. If this is not set, params will be used instead.
- When both params and postBody are set, postBody override any data provided as params thus destroying them.
+ The content for the request body for POST/PUT methods.
+
+ When postBody is a Buffer or a String, it is passed verbatim in the request body.
+ When postBody is an Object, the way it is encoded depends on the contentType:
+
+ * application/json => JSON.stringify
+ * application/x-www-urlencoed => url-encoded parameters
+ * multipart/form-data => passed as fields in enyo.FormData (XHR2 emulation)
*/
postBody: "",
/**
@@ -56,7 +62,7 @@ enyo.AjaxProperties = {
*/
xhrFields: null,
/**
- Optional string to override the MIME-Type.
+ Optional string to override the MIME-Type header.
*/
mimeType: null
};
View
37 source/ajax/WebService.js
@@ -17,15 +17,15 @@ enyo.kind({
_enyo.WebService_ uses _enyo.Ajax_ by default and, like _enyo.Ajax_, it
publishes all the properties of the
<a href="#enyo.AjaxProperties">enyo.AjaxProperties</a> object.
-
- To use `enyo.JsonpRequest` instead of `enyo.Ajax`, set `json` to `true`.
+
+ To use `enyo.JsonpRequest` instead of `enyo.Ajax`, set `json` to `true`.
If you make changes to _enyo.WebService_, be sure to add or update the
appropriate [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/ajax/tests).
-
+
For more information, see the documentation on
[Consuming Web Services](https://github.com/enyojs/enyo/wiki/Consuming-Web-Services)
- in the Enyo Developer Guide.
+ in the Enyo Developer Guide.
*/
enyo.kind({
name: "enyo.WebService",
@@ -54,17 +54,17 @@ enyo.kind({
events: {
/**
Fires when a response is received.
-
+
_inEvent.ajax_ contains the Async instance associated with the request.
-
+
_inEvent.data_ contains the response data.
*/
onResponse: "",
/**
Fires when an error is received.
-
+
_inEvent.ajax_ contains the Async instance associated with the request.
-
+
_inEvent.data_ contains the error data.
*/
onError: ""
@@ -74,25 +74,32 @@ enyo.kind({
this.inherited(arguments);
},
//* @public
- //* Sends a Web request with the passed-in parameters, returning the
- //* associated Async instance.
- send: function(inParams) {
- return this.jsonp ? this.sendJsonp(inParams) : this.sendAjax(inParams);
+ /**
+ Sends a Web request with the passed-in parameters, returning the
+ associated Async instance.
+
+ _inProps_ is an optional object parameterthat can be used to override some
+ of the AJAX properties for this request, such as setting a _postBody_.
+ */
+ send: function(inParams, inProps) {
+ return this.jsonp ? this.sendJsonp(inParams, inProps) : this.sendAjax(inParams, inProps);
},
//* @protected
- sendJsonp: function(inParams) {
+ sendJsonp: function(inParams, inProps) {
var jsonp = new enyo.JsonpRequest();
for (var n in {'url':1, 'callbackName':1, 'charset':1, 'timeout':1}) {
jsonp[n] = this[n];
}
+ enyo.mixin(jsonp, inProps);
return this.sendAsync(jsonp, inParams);
},
- sendAjax: function(inParams) {
- var ajax = new enyo.Ajax();
+ sendAjax: function(inParams, inProps) {
+ var ajax = new enyo.Ajax(inProps);
for (var n in enyo.AjaxProperties) {
ajax[n] = this[n];
}
ajax.timeout = this.timeout;
+ enyo.mixin(ajax, inProps);
return this.sendAsync(ajax, inParams);
},
sendAsync: function(inAjax, inParams) {
View
2  source/ajax/cookie.js
@@ -45,6 +45,6 @@ enyo.setCookie = function(inName, inValue, inProps) {
}
}
//
- //console.log(cookie);
+ //enyo.log(cookie);
document.cookie = cookie;
};
View
16 source/ajax/formdata.js
@@ -19,9 +19,17 @@ _enyo.FormData_ is inspired by
*/
(function(w) {
if (w.FormData) {
- enyo.FormData = w.FormData;
- enyo.Blob = w.Blob;
- return;
+ try {
+ var t1 = new w.FormData();
+ var t2 = new w.Blob();
+ // Android Chrome 18 will throw an error trying to create these
+ enyo.FormData = w.FormData;
+ enyo.Blob = w.Blob;
+ return;
+ }
+ catch (e) {
+ // ignore error and fall through to fake FormData code
+ }
}
function FormData() {
this.fake = true;
@@ -43,7 +51,7 @@ _enyo.FormData_ is inspired by
FormData.prototype.toString = function() {
var boundary = this.boundary;
var body = "";
- this._fields.forEach(function(field) {
+ enyo.forEach(this._fields, function(field) {
body += "--" + boundary + "\r\n";
if (field[2] || field[1].name) {
// file upload
View
19 source/ajax/xhr.js
@@ -19,14 +19,15 @@ enyo.xhr = {
*/
request: function(inParams) {
var xhr = this.getXMLHttpRequest(inParams);
+ var url = enyo.path.rewrite(this.simplifyFileURL(inParams.url));
//
var method = inParams.method || "GET";
var async = !inParams.sync;
//
if (inParams.username) {
- xhr.open(method, enyo.path.rewrite(inParams.url), async, inParams.username, inParams.password);
+ xhr.open(method, url, async, inParams.username, inParams.password);
} else {
- xhr.open(method, enyo.path.rewrite(inParams.url), async);
+ xhr.open(method, url, async);
}
//
enyo.mixin(xhr, inParams.xhrFields);
@@ -104,12 +105,24 @@ enyo.xhr = {
if (a.protocol === ":" ||
(a.protocol === window.location.protocol &&
a.hostname === window.location.hostname &&
- a.port === (window.location.port ||
+ a.port === (window.location.port ||
(window.location.protocol === "https:" ? "443" : "80")))) {
result = true;
}
return result;
},
+ simplifyFileURL: function(inUrl) {
+ var a = document.createElement("a"), result = false;
+ a.href = inUrl;
+ // protocol is ":" for relative URLs
+ if (a.protocol === "file:" ||
+ a.protocol === ":" && window.location.protocol === "file:") {
+ // leave off search and hash parts of the URL
+ return a.protocol + '//' + a.host + a.pathname;
+ } else {
+ return inUrl;
+ }
+ },
getXMLHttpRequest: function(inParams) {
try {
// only use XDomainRequest when it exists, no extra headers were set, and the
View
12 source/dom/Control.js
@@ -52,8 +52,12 @@ enyo.kind({
//
// ad hoc properties:
//
- //* Flag used by control layouts to determine which control will expand
- //* to fill the available space
+ /**
+ Flag used by control layouts to determine which control will expand
+ to fill the available space. This only has meaning when the control
+ is being used as a child of a control with a version of FittableLayout
+ as its layoutKind.
+ */
fit: false,
//* Used by Ares design editor for design objects
isContainer: false
@@ -160,7 +164,7 @@ enyo.kind({
A control will only return a node if it has been rendered.
if (this.hasNode()) {
- console.log(this.node.nodeType);
+ enyo.log(this.node.nodeType);
}
*/
hasNode: function() {
@@ -525,7 +529,7 @@ enyo.kind({
Values returned are only valid if _hasNode()_ is truthy.
var bounds = this.getBounds();
- console.log(bounds.width);
+ enyo.log(bounds.width);
*/
getBounds: function() {
var n = this.node || this.hasNode() || 0;
View
25 source/dom/dispatcher.js
@@ -7,6 +7,8 @@ enyo.dispatcher = {
"click", "dblclick", "change", "keydown", "keyup", "keypress", "input"],
// these events come from window
windowEvents: ["resize", "load", "unload", "message"],
+ // these events come from css
+ cssEvents: ["webkitTransitionEnd"],
// feature plugins (aka filters)
features: [],
connect: function() {
@@ -14,6 +16,9 @@ enyo.dispatcher = {
for (i=0; (n=d.events[i]); i++) {
d.listen(document, n);
}
+ for (i=0; (n=d.cssEvents[i]); i++) {
+ d.listen(document, n);
+ }
for (i=0; (n=d.windowEvents[i]); i++) {
// Chrome Packaged Apps don't like "unload"
if(n === "unload" &&
@@ -24,6 +29,9 @@ enyo.dispatcher = {
d.listen(window, n);
}
+ for (i=0; (n=d.cssEvents[i]); i++) {
+ d.listen(document, n);
+ }
},
listen: function(inListener, inEventName, inHandler) {
var d = enyo.dispatch;
@@ -32,7 +40,7 @@ enyo.dispatcher = {
inListener.addEventListener(inEventName, inHandler || d, false);
};
} else {
- //console.log("IE8 COMPAT: using 'attachEvent'");
+ //enyo.log("IE8 COMPAT: using 'attachEvent'");
this.listen = function(inListener, inEvent, inHandler) {
inListener.attachEvent("on" + inEvent, function(e) {
e.target = e.srcElement;
@@ -147,3 +155,18 @@ enyo.bubbler = "enyo.bubble(arguments[0])";
// FIXME: we need to create and initialize dispatcher someplace else to allow overrides
enyo.requiresWindow(enyo.dispatcher.connect);
+
+// generate a tapped event for a raw-click event
+enyo.dispatcher.features.push(
+ function (e) {
+ if ("click" === e.type) {
+ if (e.clientX === 0 && e.clientY === 0) {
+ // this allows the click to dispatch as well
+ // but note the tap event will fire first
+ var cp = enyo.clone(e);
+ cp.type = "tap";
+ enyo.dispatch(cp);
+ }
+ }
+ }
+);
View
4 source/dom/dom.css
@@ -37,6 +37,10 @@ button {
font-size: inherit;
font-family: inherit;
}
+button::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
/* user selection */
View
70 source/dom/dom.js
@@ -69,6 +69,20 @@ enyo.dom = {
}
return 320;
},
+ getWindowHeight: function() {
+ if (window.innerHeight) {
+ return window.innerHeight;
+ }
+ if (document.body && document.body.offsetHeight) {
+ return document.body.offsetHeight;
+ }
+ if (document.compatMode=='CSS1Compat' &&
+ document.documentElement &&
+ document.documentElement.offsetHeight ) {
+ return document.documentElement.offsetHeight;
+ }
+ return 480;
+ },
// moved from FittableLayout.js into common protected code
_ieCssToPixelValue: function(inNode, inValue) {
var v = inValue;
@@ -124,5 +138,61 @@ enyo.dom = {
//* Gets the calculated margin of a node.
calcMarginExtents: function(inNode) {
return this.calcBoxExtents(inNode, "margin");
+ },
+ //* Returns an object like `{top: 0, left: 0, bottom: 100, right: 100, height: 10, width: 10}` that represents the object's position within the viewport. Negative values mean part of the object is not visible.
+ calcViewportPositionForNode: function(inNode) {
+ // Parse upward and grab our positioning relative to the viewport
+ var top = 0,
+ left = 0,
+ node = inNode,
+ width = node.offsetWidth,
+ height = node.offsetHeight,
+ docHeight = (document.body.parentNode.offsetHeight > this.getWindowHeight() ? this.getWindowHeight() - document.body.parentNode.scrollTop : document.body.parentNode.offsetHeight),
+ docWidth = (document.body.parentNode.offsetWidth > this.getWindowWidth() ? this.getWindowWidth() - document.body.parentNode.scrollLeft : document.body.parentNode.offsetWidth),
+ transformProp = enyo.dom.getStyleTransformProp(),
+ xregex = /translateX\((-?\d+)px\)/i,
+ yregex = /translateY\((-?\d+)px\)/i,
+ borderLeft = 0, borderTop = 0;
+ if (node.offsetParent) {
+ do {
+ left += node.offsetLeft - (node.offsetParent ? node.offsetParent.scrollLeft : 0);
+ if (transformProp && xregex.test(node.style[transformProp])) {
+ left += parseInt(node.style[transformProp].replace(xregex, '$1'), 10);
+ }
+ top += node.offsetTop - (node.offsetParent ? node.offsetParent.scrollTop : 0);
+ if (transformProp && yregex.test(node.style[transformProp])) {
+ top += parseInt(node.style[transformProp].replace(yregex, '$1'), 10);
+ }
+ // Need to correct for borders if any exist on parent elements
+ if (node !== inNode) {
+ if (node.currentStyle) {
+ // Oh IE, we do so love working around your incompatibilities
+ borderLeft = parseInt(node.currentStyle.borderLeftWidth, 10);
+ borderTop = parseInt(node.currentStyle.borderTopWidth, 10);
+ } else if (window.getComputedStyle) {
+ borderLeft = parseInt(window.getComputedStyle(node, '').getPropertyValue('border-left-width'), 10);
+ borderTop = parseInt(window.getComputedStyle(node, '').getPropertyValue('border-top-width'), 10);
+ } else {
+ // No computed style options, so try the normal style object (much less robust)
+ borderLeft = parseInt(node.style.borderLeftWidth, 10);
+ borderTop = parseInt(node.style.borderTopWidth, 10);
+ }
+ if (borderLeft) {
+ left += borderLeft;
+ }
+ if (borderTop) {
+ top += borderTop;
+ }
+ }
+ } while ((node = node.offsetParent));
+ }
+ return {
+ 'top': top,
+ 'left': left,
+ 'bottom': docHeight - top - height,
+ 'right': docWidth - left - width,
+ 'height': height,
+ 'width': width
+ };
}
};
View
10 source/dom/drag.js
@@ -41,7 +41,7 @@ enyo.gesture.drag = {
minTrack: 8,
down: function(e) {
// tracking if the mouse is down
- //console.log("tracking ON");
+ //enyo.log("tracking ON");
// Note: 'tracking' flag indicates interest in mousemove, it's turned off
// on mouseup
// make sure to stop dragging in case the up event was not received.
@@ -60,7 +60,7 @@ enyo.gesture.drag = {
this.stopDragging(e);
this.cancelHold();
this.tracking = false;
- //console.log("enyo.gesture.drag: mouse must be down to drag.");
+ //enyo.log("enyo.gesture.drag: mouse must be down to drag.");
return;
}
if (this.dragEvent) {
@@ -127,12 +127,12 @@ enyo.gesture.drag = {
return e;
},
sendDragStart: function(e) {
- //console.log("dragstart");
+ //enyo.log("dragstart");
this.dragEvent = this.makeDragEvent("dragstart", this.target, e);
enyo.dispatch(this.dragEvent);
},
sendDrag: function(e) {
- //console.log("sendDrag to " + this.dragEvent.target.id + ", over to " + e.target.id);
+ //enyo.log("sendDrag to " + this.dragEvent.target.id + ", over to " + e.target.id);
// send dragOver event to the standard event target
var synth = this.makeDragEvent("dragover", e.target, e, this.dragEvent.dragInfo);
enyo.dispatch(synth);
@@ -142,7 +142,7 @@ enyo.gesture.drag = {
enyo.dispatch(synth);
},
sendDragFinish: function(e) {
- //console.log("dragfinish");
+ //enyo.log("dragfinish");
var synth = this.makeDragEvent("dragfinish", this.dragEvent.target, e, this.dragEvent.dragInfo);
synth.preventTap = function() {
e.preventTap && e.preventTap();
View
48 source/kernel/Component.js
@@ -22,7 +22,7 @@
{kind: "Component", name: "other"}
]
});
-
+
In this case, when _me_ is created, _other_ is also created, and we say that
_me owns other_. In other words, the _owner_ property of _other_ equals
_me_. Notice that you can specify the _kind_ of _other_ explicitly in its
@@ -33,6 +33,9 @@
default namespaces. In this case, _kind: "Component"_ resolves to
_enyo.Component_.
+ To move a component, use the _setOwner_ method to change the component's owner.
+ If you want to make a component unowned, use _setOwner(null)_.
+
If you make changes to _enyo.Component_, be sure to add or update the
appropriate [unit tests](https://github.com/enyojs/enyo/tree/master/tools/test/core/tests).
@@ -128,7 +131,7 @@ enyo.kind({
/**
Removes this component from its owner (sets _owner_ to null) and does
any cleanup. The component is flagged with a _destroyed: true_ property.
- Usually the component will be suitable for garbage collection after
+ Usually the component will be suitable for garbage collection after
being destroyed, unless user code keeps a reference to it.
*/
destroy: function() {
@@ -145,7 +148,7 @@ enyo.kind({
destroyComponents: function() {
enyo.forEach(this.getComponents(), function(c) {
// This local components list may be stale as components
- // we owned when the loop started could have been destroyed
+ // we owned when the loop started could have been destroyed
// by containers. Avoid redestroying components by testing
// destroyed flag.
if (!c.destroyed) {
@@ -184,7 +187,6 @@ enyo.kind({
// set and return
return inComponent.name = n;
},
- //* @public
/**
Adds _inComponent_ to the list of components owned by the current
component (i.e., _this.$_).
@@ -198,14 +200,14 @@ enyo.kind({
this.warn('Duplicate component name "' + n + '" in owner "' + this.id + '" violates unique-name-under-owner rule, replacing existing component in the hash and continuing, but this is an error condition and should be fixed.');
//if (this.shouldWarn()) {
/*
- try {
+ try {
throw new Error('Duplicate component name "' + n + '" violates unique-name-under-owner rule, replacing existing component in the hash and continuing, but this is an error condition and should be fixed.');
} catch(x) {
enyo.warn(x);
enyo.log(x.stack);
}
*/
- /*this.warn() &&*/ //console.warn('Duplicate component name "' + n + '" violates unique-name-under-owner rule, replacing existing component in the hash and continuing, but this is an error condition and should be fixed.');
+ /*this.warn() &&*/ //enyo.warn('Duplicate component name "' + n + '" violates unique-name-under-owner rule, replacing existing component in the hash and continuing, but this is an error condition and should be fixed.');
//}
}
this.$[n] = inComponent;
@@ -222,8 +224,8 @@ enyo.kind({
*/
getComponents: function() {
var results = [];
- for (var n in this.$) {
- results.push(this.$[n]);
+ for (var n in this.$) {
+ results.push(this.$[n]);
}
return results;
},
@@ -249,17 +251,17 @@ enyo.kind({
Creates and returns a component as defined by the combination of
_inInfo_ and _inMoreInfo_. Properties in _inInfo_ override properties in
_inMoreInfo_.
-
+
The created component passes through initialization machinery provided
by the creating component, which may supply special handling.
Unless the owner is explicitly specified, the new component will be
owned by the instance on which _createComponent_ is called.
- // Create a new component named _dynamic_ owned by _this_
+ // Create a new component named _dynamic_ owned by _this_
// (will be available as this.$.dynamic).
this.createComponent({name: "dynamic"});
- // Create a new component named _another_ owned by _other_
+ // Create a new component named _another_ owned by _other_
// (will be available as other.$.another).
this.createComponent({name: "another"}, {owner: other});
*/
@@ -275,7 +277,7 @@ enyo.kind({
_createComponents_ returns an array of references to the created components.
- // ask foo to create components _bar_ and _zot_, but set the owner of
+ // ask foo to create components _bar_ and _zot_, but set the owner of
// both components to _this_.
this.$.foo.createComponents([
{name: "bar"},
@@ -306,8 +308,8 @@ enyo.kind({
function(inSender, inEvent)
- where _inSender_ refers to the Component that most recently
- propagated the event and _inEvent_ is an object containing
+ where _inSender_ refers to the Component that most recently
+ propagated the event and _inEvent_ is an object containing
event information.
_inEvent_ will have at least one property, _originator_, which
@@ -333,8 +335,8 @@ enyo.kind({
function(inSender, inEvent)
- where _inSender_ refers to the Component that most recently
- propagated the event and _inEvent_ is an object containing
+ where _inSender_ refers to the Component that most recently
+ propagated the event and _inEvent_ is an object containing
event information.
_inEvent_ will have at least one property, _originator_, which
@@ -351,14 +353,14 @@ enyo.kind({
//* @protected
/**
Dispatching refers to sending an event to a named delegate.
- This object may dispatch an event to itself via a handler,
+ This object may dispatch an event to itself via a handler,
or to its owner via an event property, e.g.:
-
+
handlers {
// 'tap' events dispatched to this.tapHandler
ontap: "tapHandler"
}
-
+
// 'tap' events dispatched to 'tapHandler' delegate in this.owner
ontap: "tapHandler"
*/
@@ -417,7 +419,7 @@ enyo.kind({
Dispatches the event to named delegate _inMethodName_, if it exists.
Subkinds may re-route dispatches.
Note that both 'handlers' events and events delegated from owned controls
- arrive here. If you need to handle these differently, you may
+ arrive here. If you need to handle these differently, you may
need to also override _dispatchEvent_.
*/
dispatch: function(inMethodName, inEvent, inSender) {
@@ -465,7 +467,7 @@ enyo.create = enyo.Component.create = function(inConfig) {
var kind = inConfig.kind || inConfig.isa || enyo.defaultCtor;
var ctor = enyo.constructorForKind(kind);
if (!ctor) {
- console.error('no constructor found for kind "' + kind + '"');
+ enyo.error('no constructor found for kind "' + kind + '"');
ctor = enyo.Component;
}
return new ctor(inConfig);
@@ -489,7 +491,7 @@ enyo.Component.subclass = function(ctor, props) {
}
//
// handlers are merged with supertype handlers
- // and kind time.
+ // and kind time.
//
if (props.handlers) {
var kh = proto.kindHandlers;
@@ -531,7 +533,7 @@ enyo.Component.addEvent = function(inName, inValue, inProto) {
// bubble this event
return this.bubble(inName, inEvent);
};
- // NOTE: Mark this function as a generated event handler to allow us to
+ // NOTE: Mark this function as a generated event handler to allow us to
// do event chaining. Is this too complicated?
//inProto[fn]._dispatcher = true;
}
View
2  source/kernel/Oop.js
@@ -167,7 +167,7 @@ enyo.kind.features.push(function(ctor, props) {
enyo.kind.statics = {
subclass: function(ctor, props) {
- //console.log("subclassing [" + ctor.prototype.kind + "] from [", this.prototype.kind + "]");
+ //enyo.log("subclassing [" + ctor.prototype.kind + "] from [", this.prototype.kind + "]");
},
extend: function(props) {
enyo.mixin(this.prototype, props);
View
2  source/kernel/UiComponent.js
@@ -300,7 +300,7 @@ enyo.master = new enyo.Component({
},
isDescendantOf: enyo.nop,
bubble: function(inEventName, inEvent, inSender) {
- //console.log("master event: " + inEventName);
+ //enyo.log("master event: " + inEventName);
if (inEventName == "onresize") {
// Resize is special; waterfall this message.
// This works because master is a Component, so it waterfalls
View
2  source/touch/ScrollMath.js
@@ -275,7 +275,7 @@ enyo.kind({
/**
Animates a scroll to the specified position.
*/
- scrollTo: function(inY, inX) {
+ scrollTo: function(inX, inY) {
if (inY !== null) {
this.y = this.y0 - (inY + this.y0) * (1 - this.kFrictionDamping);
}
View
14 source/touch/TouchScrollStrategy.js
@@ -73,6 +73,8 @@ enyo.kind({
components: [
{name: "client", classes: "enyo-touch-scroller"}
],
+ // flag telling us whether the list is currently reordering
+ listReordering: false,
create: function() {
this.inherited(arguments);
this.transform = enyo.dom.canTransform();
@@ -179,7 +181,7 @@ enyo.kind({
//* Scrolls to specific x/y positions within the scroll area.
scrollTo: function(inX, inY) {
this.stop();
- this.$.scrollMath.scrollTo(inY || inY === 0 ? inY : null, inX);
+ this.$.scrollMath.scrollTo(inX, inY || inY === 0 ? inY : null);
},
scrollIntoView: function() {
this.stop();
@@ -275,6 +277,10 @@ enyo.kind({
}
},
drag: function(inSender, inEvent) {
+ // if the list is doing a reorder, don't scroll
+ if(this.listReordering) {
+ return false;
+ }
if (this.dragging) {
inEvent.preventDefault();
this.$.scrollMath.drag(inEvent);
@@ -401,8 +407,10 @@ enyo.kind({
//* Syncs and shows both the vertical and horizontal scroll indicators.
showThumbs: function() {
this.syncThumbs();
- this.$.vthumb.show();
- this.$.hthumb.show();
+ if (this.horizontal != "hidden")
+ this.$.hthumb.show();
+ if (this.vertical != "hidden")
+ this.$.vthumb.show();
},
//* Hides the vertical and horizontal scroll indicators.
hideThumbs: function() {
View
356 source/touch/TransitionScrollStrategy.js
@@ -22,7 +22,8 @@ enyo.kind({
},
handlers: {
ondown: "down",
- ondragfinish: "dragfinish"
+ ondragfinish: "dragfinish",
+ onwebkitTransitionEnd: "transitionComplete"
},
//* No scrollMath tool for this strategy
tools: [
@@ -39,18 +40,14 @@ enyo.kind({
bottomBoundary: 0,
//* Left snap boundary, generally 0
leftBoundary: 0,
- //* X value used in addition to scrollLeft to determine scrolling behavior
- x:0,
- //* Y value used in addition to scrollTop to determine scrolling behavior
- y:0,
//* Flag to specify whether scrolling is in progress
scrolling: false,
//* Event listener for webkit transition completion
listener: null,
//* X Distance to scroll into overscroll space before bouncing back
- deltaX:0,
+ boundaryX:0,
//* Y Distance to scroll into overscroll space before bouncing back
- deltaY:0,
+ boundaryY:0,
//* Timeout used to stop scrolling on mousedown
stopTimeout: null,
//* MS delay used to stop scrolling on mousedown
@@ -74,13 +71,22 @@ enyo.kind({
//* Sets the left scroll position within the scroller.
setScrollLeft: function(inLeft) {
this.stop();
- this.setScrollX(inLeft);
+ this.scrollLeft = inLeft;
+ this.effectScroll();
},
//* Sets the top scroll position within the scroller.
setScrollTop: function(inTop) {
this.stop();
- this.setScrollY(inTop);
+ this.scrollTop = inTop;
+ this.effectScroll();
},
+ setScrollX: function(inLeft) {
+ this.scrollLeft = -1*inLeft;
+ },
+ setScrollY: function(inTop) {
+ this.scrollTop = -1*inTop;
+ },
+
//* Gets the left scroll position within the scroller.
getScrollLeft: function() {
return this.scrollLeft;
@@ -97,23 +103,19 @@ enyo.kind({
this.inherited(arguments);
enyo.dom.transformValue(this.$.client, this.translation, "0,0,0");
},
- rendered: function() {
- this.inherited(arguments);
- this.setupListener();
- },
- // setup webkitTransitionEnd listener
- setupListener: function() {
- this.listener = this.$.client.node.addEventListener('webkitTransitionEnd', enyo.bind(this,"transitionComplete"), false);
- },
getScrollSize: function() {
var n = this.$.client.hasNode();
return {width: n ? n.scrollWidth : 0, height: n ? n.scrollHeight : 0};
},
horizontalChanged: function() {
- this.horizontal = (this.horizontal != "hidden");
+ if(this.horizontal == "hidden") {
+ this.horizontal = false;
+ }
},
verticalChanged: function() {
- this.vertical = (this.vertical != "hidden");
+ if(this.vertical == "hidden") {
+ this.vertical = false;
+ }
},
calcScrollNode: function() {
return this.$.clientContainer.hasNode();
@@ -125,28 +127,38 @@ enyo.kind({
this.$.clientContainer.addRemoveClass("enyo-scrollee-fit", !this.maxHeight);
},
calcAutoScrolling: function() {
- var v = (this.vertical != "hidden");
- var h = (this.horizontal != "hidden");
- if ((v || h) && this.scrollNode) {
+ if((this.vertical || this.horizontal) && this.scrollNode) {
var b = this.getScrollBounds();
- if (v) {
+ if(this.vertical) {
this.vertical = b.height > b.clientHeight;
}
- if (h) {
+ if(this.horizontal) {
this.horizontal = b.width > b.clientWidth;
}
}
},
- isInOverScroll: function(x,y) {
- return (this.isInOverScrollX() || this.isInOverScrollY());
+ isInOverScroll: function() {
+ return (this.isInTopOverScroll() || this.isInBottomOverScroll() || this.isInLeftOverScroll() || this.isInRightOverScroll());
+ },
+ isInLeftOverScroll: function() {
+ return (this.getScrollLeft() < this.leftBoundary);
+ },
+ isInRightOverScroll: function() {
+ if(this.getScrollLeft <= 0) {
+ return false;
+ } else {
+ return (this.getScrollLeft()*-1 < this.rightBoundary);
+ }
},
- isInOverScrollX: function(x) {
- x = x || this.x;
- return (x > this.leftBoundary || x < this.rightBoundary);
+ isInTopOverScroll: function() {
+ return (this.getScrollTop() < this.topBoundary);
},
- isInOverScrollY: function(y) {
- y = y || this.y;
- return (y > this.topBoundary || y < this.bottomBoundary);
+ isInBottomOverScroll: function() {
+ if(this.getScrollTop() <= 0) {
+ return false;
+ } else {
+ return (this.getScrollTop()*-1 < this.bottomBoundary);
+ }
},
calcStartInfo: function() {
var sb = this.getScrollBounds(), y = this.getScrollTop(), x = this.getScrollLeft();
@@ -162,12 +174,10 @@ enyo.kind({
this.calcBoundaries();
this.syncScrollMath();
var dy = this.vertical ? e.wheelDeltaY || e.wheelDelta : 0;
- var y = parseFloat(this.y) + parseFloat(dy);
- y = (y < this.bottomBoundary) ? this.bottomBoundary : (y > this.topBoundary) ? this.topBoundary : y;
- this.stop();
- this.effectScroll(this.x,y);
- this.setScrollX(this.x);
- this.setScrollY(y);
+ var y = parseFloat(this.getScrollTop()) + -1*parseFloat(dy);
+ y = (y*-1 < this.bottomBoundary) ? -1*this.bottomBoundary : (y < this.topBoundary) ? this.topBoundary : y;
+ this.setScrollTop(y);
+ this.doScroll();
e.preventDefault();
return true;
}
@@ -182,7 +192,7 @@ enyo.kind({
},
// Scroll to current x,y coordinates and bubble scrollstart event
start: function() {
- this.startScrolling(this.x,this.y);
+ this.startScrolling();
this.doScrollStart();
},
// If scrolling, stop. Hide thumbs and bubble scrollstop event.
@@ -200,30 +210,19 @@ enyo.kind({
updateX: function() {
var x = window.getComputedStyle(this.$.client.node,null).getPropertyValue("-webkit-transform").split('(')[1];
x = (x == undefined) ? 0 : x.split(')')[0].split(',')[4];
- this.setScrollX(parseFloat(x));
+ this.scrollLeft = -1*parseFloat(x);
},
// Set scroll y value to the current computed style
updateY: function() {
var y = window.getComputedStyle(this.$.client.node,null).getPropertyValue("-webkit-transform").split('(')[1];
y = (y == undefined) ? 0 : y.split(')')[0].split(',')[5];
- this.setScrollY(parseFloat(y));
- },
- // Set scroll x and scroll left values
- setScrollX: function(inX) {
- this.scrollLeft = -1*inX;
- this.x = inX;
- },
- // Set scroll y and scroll top values
- setScrollY: function(inY) {
- this.scrollTop = -1*inY;
- this.y = inY;
+ this.scrollTop = -1*parseFloat(y);
},
// Apply transform to scroll the scroller
- effectScroll: function(inX, inY) {
- var o = inX + "px, " + inY + "px" + (this.accel ? ",0" : "");
+ effectScroll: function() {
+ var o = (-1*this.scrollLeft) + "px, " + (-1*this.scrollTop) + "px" + (this.accel ? ",0" : "");
enyo.dom.transformValue(this.$.client, this.translation, o);
},
-
// On touch, stop transition by setting transform values to current computed style, and
// changing transition time to 0s. TODO
down: function(inSender, inEvent) {
@@ -255,8 +254,6 @@ enyo.kind({
inEvent.preventDefault();
this.prevY = inEvent.pageY;
this.prevX = inEvent.pageX;
- this.y = -1*(this.scrollTop);
- this.x = -1*(this.scrollLeft);
if (this.preventDragPropagation) {
return true;
}
@@ -318,38 +315,44 @@ enyo.kind({
},
// Move scroller based on user's dragging
drag: function(inSender, e) {
+ // if the list is doing a reorder, don't scroll
+ if(this.listReordering) {
+ return false;
+ }
// if shouldDrag() set this.dragging to true
if(this.dragging) {
e.preventDefault();
// calculate new scroll values
- this.x = this.horizontal ? this.dragHorizontal(e) : this.x;
- this.y = this.vertical ? this.dragVertical(e) : this.y;
+ this.scrollLeft = this.horizontal ? this.calculateDragDistance(parseInt(this.getScrollLeft()), (-1*(e.pageX-this.prevX)), this.leftBoundary, this.rightBoundary) : this.getScrollLeft();
+ this.scrollTop = this.vertical ? this.calculateDragDistance(this.getScrollTop(), (-1*(e.pageY-this.prevY)), this.topBoundary, this.bottomBoundary) : this.getScrollTop();
// apply new scroll values
- this.effectScroll(this.x,this.y);
+ this.effectScroll();
this.scroll();
// save values for next drag
this.prevY = e.pageY;
this.prevX = e.pageX;
- return true;
+ this.setBoundaryX();
+ this.setBoundaryY();
}
},
- dragVertical: function(e) {
- var dy = e.pageY - this.prevY;
- var y = this.y + dy;
- return this.overscrollDragDamping(y, dy, this.topBoundary, this.bottomBoundary);
+ //* Figure how far the drag should go based on pointer movement (delta)
+ calculateDragDistance: function(currentPosition, delta, aBoundary, bBoundary) {
+ var newPosition = currentPosition + delta;
+ return this.overscrollDragDamping(currentPosition, newPosition,delta,aBoundary,bBoundary);
},
- dragHorizontal: function(e) {
- var dx = e.pageX - this.prevX;
- var x = this.x + dx;
- return this.overscrollDragDamping(x, dx, this.leftBoundary, this.rightBoundary);
- },
- // Provides resistance against dragging into overscroll
- overscrollDragDamping: function(value, delta, aBoundary, bBoundary) {
- if(value > aBoundary || value < bBoundary) {
+ //* Provides resistance against dragging into overscroll
+ overscrollDragDamping: function(currentPosition, newPosition, delta, aBoundary, bBoundary) {
+ if(newPosition < aBoundary || newPosition*-1 < bBoundary) {
delta /= 2;
- value = this.y + delta;
+ newPosition = currentPosition + delta;
}
- return value;
+ return newPosition;
+ },
+ setBoundaryX: function() {
+ this.boundaryX = (this.isInLeftOverScroll()) ? this.leftBoundary : (this.isInRightOverScroll()) ? this.rightBoundary : null;
+ },
+ setBoundaryY: function() {
+ this.boundaryY = (this.isInTopOverScroll()) ? this.topBoundary : (this.isInBottomOverScroll()) ? this.bottomBoundary : null;
},
// When user releases the drag, set this.dragging to false, bounce overflow back, and hide scrim.
dragfinish: function(inSender, inEvent) {
@@ -364,62 +367,118 @@ enyo.kind({
}
}
},
- // When user flicks/throws scroller, figure the distance to be travelled and whether we will end up
- // in the overscroll region.
- flick: function(inSender, e) {
- n = enyo.now();
- var onAxis = Math.abs(e.xVelocity) > Math.abs(e.yVelocity) ? this.horizontal : this.vertical;
- if (this.dragging && onAxis) {
- this.y = this.vertical ? this.flickVertical(e) : this.y;
- this.x = this.horizontal ? this.flickHorizontal(e) : this.x;
- this.deltaX = null;
- this.deltaY = null;
- // if flick will put the x axis into overscroll, figure where we should bounce back (deltaX)
- if(this.isInOverScrollX()) {
- if(this.x < this.leftBoundary) {
- this.deltaX = this.figureDelta(this.leftBoundary - this.x);
+ // Bounce back from overscroll region
+ correctOverflow: function() {
+ if(this.isInOverScroll()) {
+ var x = (this.horizontal) ? this.correctOverflowX() : false;
+ var y = (this.vertical) ? this.correctOverflowY() : false;
+ if(x !== false && y !== false) {
+ this.scrollLeft = (x !== false) ? x : this.getScrollLeft();
+ this.scrollTop = (y !== false) ? y : this.getScrollTop();
+ this.startOverflowScrolling();
+ } else if(x !== false) {
+ this.scrollLeft = x;
+ this.scrollTop = this.targetScrollTop;
+ this.targetScrollLeft = this.getScrollLeft();
+ if(!this.vertical) {
+ this.startOverflowScrolling();
} else {
- this.deltaX = this.figureDelta(this.x);
+ this.startScrolling();
}
- }
- // if flick will put the y axis into overscroll, figure where we should bounce back (deltaY)
- if(this.isInOverScrollY()) {
- if(this.y < this.bottomBoundary) {
- this.deltaY = this.figureDelta(this.bottomBoundary - this.y);
+ } else if(y !== false) {
+ this.scrollTop = y;
+ this.scrollLeft = this.targetScrollLeft;
+ this.targetScrollTop = this.getScrollTop();
+ if(!this.horizontal) {
+ this.startOverflowScrolling();
} else {
- this.deltaY = this.figureDelta(this.y);
+ this.startScrolling();
}
}
+ }
+ },
+ // Determine if we're overscrolled on the x axis and if so return proper edge value
+ correctOverflowX: function() {
+ if(this.isInLeftOverScroll()) {
+ if(this.beyondBoundary(this.getScrollLeft(), this.leftBoundary, this.boundaryX)) {
+ return this.leftBoundary;
+ }
+ } else if(this.isInRightOverScroll()) {
+ if(this.beyondBoundary(this.getScrollLeft(), this.rightBoundary, this.boundaryX)) {
+ return -1*this.rightBoundary;
+ }
+ }
+ return false;
+ },
+ // Determine if we're overscrolled on the y axis and if so return proper edge value
+ correctOverflowY: function() {
+ if(this.isInTopOverScroll()) {
+ if(this.beyondBoundary(this.getScrollTop(), this.topBoundary, this.boundaryY)) {
+ return this.topBoundary;
+ }
+ } else if(this.isInBottomOverScroll()) {
+ if(this.beyondBoundary(this.getScrollTop(), this.bottomBoundary, this.boundaryY)) {
+ return -1*this.bottomBoundary;
+ }
+ }
+ return false;
+ },
+ // If we've crossed the determined delta, bounce back
+ beyondBoundary: function(current,boundary,max) {
+ return (Math.abs(Math.abs(boundary) - Math.abs(current)) > Math.abs(max));
+ },
+ // When user flicks/throws scroller, figure the distance to be travelled and whether we will end up
+ // in the overscroll region.
+ flick: function(inSender, e) {
+ if(this.dragging && this.flickOnEnabledAxis(e)) {
+ this.scrollLeft = this.horizontal ? this.calculateFlickDistance(this.scrollLeft, -1*e.xVelocity) : this.getScrollLeft();
+ this.scrollTop = this.vertical ? this.calculateFlickDistance(this.scrollTop, -1*e.yVelocity) : this.getScrollTop();
+ this.targetScrollLeft = this.scrollLeft;
+ this.targetScrollTop = this.scrollTop;
+ this.boundaryX = null;
+ this.boundaryY = null;
+ // if flick will put the x axis into overscroll, figure where we should bounce back (boundary)
+ if(this.isInLeftOverScroll()) {
+ this.boundaryX = this.figureBoundary(this.getScrollLeft());
+ } else if(this.isInRightOverScroll()) {
+ this.boundaryX = this.figureBoundary(-1*this.bottomBoundary - this.getScrollLeft());
+ }
+ // if flick will put the y axis into overscroll, figure where we should bounce back (boundary)
+ if(this.isInTopOverScroll()) {
+ this.boundaryY = this.figureBoundary(this.getScrollTop());
+ } else if(this.isInBottomOverScroll()) {
+ this.boundaryY = this.figureBoundary(-1*this.bottomBoundary - this.getScrollTop());
+ }
// kickoff scrolling animation
- this.startScrolling(this.x,this.y);
+ this.startScrolling();
return this.preventDragPropagation;
}
},
- flickVertical: function(e) {
- return (parseFloat(this.y) + e.yVelocity * this.kFlickScalar);
+ flickOnEnabledAxis: function(e) {
+ return Math.abs(e.xVelocity) > Math.abs(e.yVelocity) ? this.horizontal : this.vertical;
},
- flickHorizontal: function(e) {
- return (parseFloat(this.x) + e.xVelocity * this.kFlickScalar);
+ calculateFlickDistance: function(currentPosition, flickVelocity) {
+ return (currentPosition + (flickVelocity * this.kFlickScalar));
},
// Apply the 'scroll' transition, apply new transform based on x and y, and begin
// this.scrollInterval to update the scrollTop/Left values while scrolling
- startScrolling: function(x,y) {
+ startScrolling: function() {
this.applyTransition("scroll");
- this.effectScroll(x,y);
+ this.effectScroll();
this.setCSSTransitionInterval();
this.scrolling = true;
},
// Apply the 'bounce' transition, apply new transform based on x and y, and begin
// this.scrollInterval to update the scrollTop/Left values while scrolling
- startOverflowScrolling: function(x,y) {
+ startOverflowScrolling: function() {
this.applyTransition("bounce");
- this.effectScroll(x,y);
+ this.effectScroll();
this.setOverflowTransitionInterval();
this.scrolling = true;
},
// Apply the given transition to this.$.client
applyTransition: function(which) {
- this.$.client.applyStyle("-webkit-transition",this.transitions[which])
+ this.$.client.applyStyle("-webkit-transition",this.transitions[which]);
},
// Turn off CSS transition and clear this.scrollInterval
stopScrolling: function() {
@@ -454,6 +513,7 @@ enyo.kind({
clearCSSTransitionInterval: function() {
if(this.scrollInterval) {
clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
}
},
// Set scroller translation to current position and turn transition off. This effectively
@@ -461,62 +521,50 @@ enyo.kind({
resetCSSTranslationVals: function() {
var transformStyle = getComputedStyle(this.$.client.node,null).getPropertyValue("-webkit-transform").split('(')[1].split(')')[0].split(',');
this.applyTransition("none");
- this.effectScroll(transformStyle[4],transformStyle[5]);
- },
- // Bounce back from overscroll region
- correctOverflow: function(overflowY) {
- if(this.isInOverScroll()) {
- var x = (this.horizontal) ? this.correctOverflowX() : this.x;
- var y = (this.vertical) ? this.correctOverflowY() : this.y;
- if(x !== false && y !== false) {
- this.startOverflowScrolling(x,y);
- }
- }
- },
- // Determine if we're overscrolled on the x axis and if so return proper edge value
- correctOverflowX: function() {
- if(this.x > this.rightBoundary) {
- if(this.beyondBoundary(this.x, this.rightBoundary, this.deltaX)) {
- return this.rightBoundary;
- }
- } else if(this.x < this.leftBoundary) {
- if(this.beyondBoundary(this.x, this.leftBoundary, this.deltaX)) {
- return this.leftBoundary;
- }
- }
- return false;
- },
- // Determine if we're overscrolled on the y axis and if so return proper edge value
- correctOverflowY: function() {
- if(this.y > this.topBoundary) {
- if(this.beyondBoundary(this.y, this.topBoundary, this.deltaY)) {
- return this.topBoundary;
- }
- } else if(this.y < this.bottomBoundary) {
- if(this.beyondBoundary(this.y, this.bottomBoundary, this.deltaY)) {
- return this.bottomBoundary;
- }
- }
- return false;
+ this.scrollLeft = -1*transformStyle[4];
+ this.scrollTop = -1*transformStyle[5];
+ this.effectScroll();
},
// Figure how far into the overscroll region we should go before bouncing back
- figureDelta: function(target) {
- var kLimit = 200, kMultiplier = 5;
- return kLimit - target*kLimit*kMultiplier/Math.pow(target,1.3);
- },
- // If we've crossed the determined delta, bounce back
- beyondBoundary: function(current,boundary,max) {
- return (Math.abs(Math.abs(boundary) - Math.abs(current)) > Math.abs(max));
+ figureBoundary: function(target) {
+ var absTarget = Math.abs(target);
+ var retVal = absTarget - absTarget/Math.pow(absTarget,0.02);
+ retVal = target < 0 ? -1*retVal : retVal;
+ return retVal;
},
// When transition animation is complete, check if we need to bounce back from overscroll
// region. If not, stop.
- transitionComplete: function() {
- if(parseInt(this.scrollTop) < this.topBoundary) {
- this.startOverflowScrolling(this.leftBoundary,this.topBoundary);
- } else if (parseInt(this.scrollTop*-1) < this.bottomBoundary) {
- this.startOverflowScrolling(this.leftBoundary,this.bottomBoundary);
+ transitionComplete: function(inSender, inEvent) {
+ // Only process transition complete if sent from this container
+ if(inSender !== this.$.clientContainer) {
+ 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;
+ } else if (this.isInRightOverScroll()) {
+ posChanged = true;
+ this.scrollLeft = -1*this.rightBoundary;
+ }
+
+ if(posChanged) {
+ this.startOverflowScrolling();
} else {
this.stop();
}
+ },
+ //* Scroll to the specified x and y coordinates
+ scrollTo: function(inX, inY) {
+ this.setScrollTop(-1*inY);
+ this.setScrollLeft(-1*inX);
+ this.start();
}
});
View
6 source/touch/touch.js
@@ -77,7 +77,7 @@ enyo.requiresWindow(function() {
e.target = this.findTarget(e);
// normalize "mouse button" info
e.which = 1;
- //console.log("target for " + inEvent.type + " at " + e.pageX + ", " + e.pageY + " is " + (e.target ? e.target.id : "none"));
+ //enyo.log("target for " + inEvent.type + " at " + e.pageX + ", " + e.pageY + " is " + (e.target ? e.target.id : "none"));
return e;
},
calcNodeOffset: function(inNode) {
@@ -102,9 +102,9 @@ enyo.requiresWindow(function() {
if (o && n != this.excludedTarget) {
var x = inX - o.left;
var y = inY - o.top;
- //console.log("test: " + n.id + " (left: " + o.left + ", top: " + o.top + ", width: " + o.width + ", height: " + o.height + ")");
+ //enyo.log("test: " + n.id + " (left: " + o.left + ", top: " + o.top + ", width: " + o.width + ", height: " + o.height + ")");
if (x>0 && y>0 && x<=o.width && y<=o.height) {
- //console.log("IN: " + n.id + " -> [" + x + "," + y + " in " + o.width + "x" + o.height + "] (children: " + n.childNodes.length + ")");
+ //enyo.log("IN: " + n.id + " -> [" + x + "," + y + " in " + o.width + "x" + o.height + "] (children: " + n.childNodes.length + ")");
var target;
for (var n$=n.childNodes, i=n$.length-1, c; (c=n$[i]); i--) {
target = this.findTargetTraverse(c, inX, inY);
View
8 source/ui/Input.js
@@ -109,9 +109,15 @@ enyo.kind({
this.node.focus();
}
},
+ //* Returns true if the Input is focused.
+ hasFocus: function() {
+ if (this.hasNode()) {
+ return document.activeElement === this.node;
+ }
+ },
// note: we disallow dragging of an input to allow text selection on all platforms
dragstart: function() {
- return true;
+ return this.hasFocus();
},
focused: function() {
if (this.selectOnFocus) {
View
10 source/ui/Popup.js
@@ -121,8 +121,8 @@ enyo.kind({
p.right = null;
}
} else if (typeof p.right === 'number') {
- if (p.right - b.width < 0) {
- if (p.right + b.width <= d.width) {
+ if (p.right + b.width > d.width) {
+ if (p.right - b.width >= 0) {
p.left = d.width - p.right;
} else {
p.left = 0;
@@ -135,7 +135,7 @@ enyo.kind({
if (typeof p.top === 'number') {
if (p.top + b.height > d.height) {
- if (p.top - b.height > 0) {
+ if (p.top - b.height >= 0) {
p.bottom = d.height - p.top;
} else {
p.bottom = 0;
@@ -145,8 +145,8 @@ enyo.kind({
p.bottom = null;
}
} else if (typeof p.bottom === 'number') {
- if (p.bottom - b.height < 0) {
- if (p.bottom + b.height <= d.height) {
+ if (p.bottom + b.height > d.height) {
+ if (p.bottom - b.height >= 0) {
p.top = d.height - p.bottom;
} else {
p.top = 0;
View
4 tools/minifier/minify.js
@@ -58,6 +58,10 @@ concatCss = function(loader, doneCB) {
if (/^data:/.test(urlPath)) {
return "url(" + urlPath + ")";
}
+ // skip an external link
+ if (/^http(:?s)?:/.test(urlPath)) {
+ return "url(" + urlPath + ")";
+ }
// get absolute path to referenced asset
var normalizedUrlPath = path.join(sheet, "..", urlPath);
// Make relative asset path to built css
View
53 tools/test/ajax/tests/AjaxTest.js
@@ -5,7 +5,7 @@ enyo.kind({
_testAjax: function(inProps, inParams, inAssertFn, inAssertErrFn) {
return new enyo.Ajax(inProps)
.response(this, function(inSender, inValue) {
- this.finish(inAssertFn.call(null, inValue) ? "" : "bad response: " + inValue);
+ this.finish(inAssertFn.call(null, inValue) ? "" : "bad response: " + JSON.stringify(inValue));
})
.error(this, function(inSender, inError) {
if (!inAssertErrFn) {
@@ -42,21 +42,22 @@ enyo.kind({
return inValue == "hello";
});
},
- testPostRequestQuery: function() {
- this._testAjax({url: "php/test2.php", method: "POST"}, {query: "enyo"}, function(inValue) {
- return inValue.response == "query.enyo";
- });
- },
- testPostRequestQueryWithPayload: function() {
- this._testAjax({url: "php/test2.php", method: "POST", postBody:"data"}, {query: "enyo"}, function(inValue) {
- return inValue.response == "query.enyo";
- });
- },
- testPostRequestPayload: function() {
- this._testAjax({url: "php/test2.php", method: "POST", postBody:"query=enyo"}, null, function(inValue) {
- return inValue.response == "post.enyo";
- });
- },
+ // try a post with query object
+ testPostRequestQuery: function() {
+ this._testAjax({url: "php/test2.php", method: "POST"}, {query: "enyo"}, function(inValue) {
+ return inValue.response == "query.enyo";
+ });
+ },
+ testPostRequestQueryWithPayload: function() {
+ this._testAjax({url: "php/test2.php", method: "POST", postBody:"data"}, {query: "enyo"}, function(inValue) {
+ return inValue.response == "query.enyo";
+ });
+ },
+ testPostRequestPayload: function() {
+ this._testAjax({url: "php/test2.php", method: "POST", postBody:"query=enyo"}, null, function(inValue) {
+ return inValue.response == "post.enyo";
+ });
+ },
testPutRequest: function() {
this._testAjax({url: "php/test2.php", method: "PUT"}, null, function(inValue) {
return inValue.status == "put";
@@ -80,10 +81,16 @@ enyo.kind({
testContentType: function() {
var contentType = "text/plain";
this._testAjax({url: "php/test2.php", method: "PUT", contentType: contentType}, null, function(inValue) {
- return inValue.ctype == contentType;
+ return (inValue.ctype === contentType);
});
},
testCacheControlOn: function() {
+ // skip test on non-iOS platforms, since Firefox always sends cache-control header causing
+ // false positive
+ if (!enyo.platform.ios) {
+ this.finish();
+ return;
+ }
var contentType = "application/x-www-form-urlencoded";
this._testAjax({url: "php/test4.php", method: "POST", postBody: "data"}, null, function(inValue) {
if (enyo.platform.ios && enyo.platform.ios >= 6) {
@@ -98,6 +105,12 @@ enyo.kind({
});
},
testCacheControlOff: function() {
+ // skip test on non-iOS platforms, since Firefox always sends cache-control header causing
+ // false positive
+ if (!enyo.platform.ios) {
+ this.finish();
+ return;
+ }
var contentType = "application/x-www-form-urlencoded";
this._testAjax({url: "php/test4.php", method: "POST", postBody: "data", headers: {'cache-control': null} }, null, function(inValue) {
var status = (inValue.cacheCtrl === null);
@@ -123,7 +136,7 @@ enyo.kind({
var contentType = "multipart/form-data";
this._testAjax({url: "php/test4.php", method: "POST", postBody: formData}, null, function(inValue) {
var status = (inValue.ctype.indexOf(contentType) === 0) &&
- (inValue.ctype.indexOf("boundary=--") > 10);
+ (inValue.ctype.indexOf("boundary=--") > 10);
if (!status) {
enyo.log("Bad CT: " + inValue.ctype + " expected: " + contentType);
}
@@ -133,13 +146,13 @@ enyo.kind({
testContentTypeFormDataFile: function() {
var formData = new enyo.FormData();
var file = new enyo.Blob(["Some Random File Content!", "And some more..."], {
- name: "myFile"
+ name: "myFile"
});
formData.append('file', file);
var contentType = "multipart/form-data";
this._testAjax({url: "php/test4.php", method: "POST", postBody: formData}, null, function(inValue) {
var status = (inValue.ctype.indexOf(contentType) === 0) &&
- (inValue.ctype.indexOf("boundary=--") > 10);
+ (inValue.ctype.indexOf("boundary=--") > 10);
if (!status) {
enyo.log("Bad CT: " + inValue.ctype + " expected: " + contentType);
}
View
4 tools/test/ajax/tests/JsonpTest.js
@@ -4,7 +4,7 @@ enyo.kind({
_testJsonp: function(inProps, inParams, inAssertFn) {
return new enyo.JsonpRequest(inProps)
.response(this, function(inSender, inValue) {
- this.finish(inAssertFn.call(null, inValue) ? "" : "bad response: " + inValue);
+ this.finish(inAssertFn.call(null, inValue) ? "" : "bad response: " + JSON.stringify(inValue));
})
.error(this, function(inSender, inValue) {
this.finish("bad status: " + inValue);
@@ -13,7 +13,7 @@ enyo.kind({
.go(inParams);
},
_testResponse: function(inProps, inAssertFn) {
- this._testJsonp(enyo.mixin({url: "php/test1.php?format=jsonp", callbackName: "callback"}, inProps),
+ this._testJsonp(enyo.mixin({url: "php/test1.php?format=jsonp", callbackName: "callback"}, inProps),
null, inAssertFn);
},
testJsonResponse: function() {
View
2  tools/test/ajax/tests/WebServiceTest.js
@@ -7,7 +7,7 @@ enyo.kind({
return ws.send(inParams);
},
_response: function(inSender, inValue) {
- this.finish(inSender.assertFn(inValue.data) ? "" : "bad response: " + inValue.data);
+ this.finish(inSender.assertFn(inValue.data) ? "" : "bad response: " + JSON.stringify(inValue.data));
},
_error: function(inSender, inValue) {
this.finish("bad status: " + inValue.data);
View
80 tools/test/core/tests/ViewportPositioningTest.js
@@ -0,0 +1,80 @@
+enyo.kind({
+ name: "ViewportPositioningTest",
+ kind: enyo.TestSuite,
+
+ testMeasuringViewportCoordinates: function() {
+ var K = enyo.kind({
+ kind: enyo.Control,
+ style: "position: absolute; top: 10px; left: 10px; width: 10px; height: 10px;"
+ });
+
+ // Similar to ControlTest, create a testing div to test DOM information with (delete at end)
+ var div = document.createElement("div");
+ document.body.appendChild(div);
+ // Apply fixed positioning so that we know where things should be relative to the viewport
+ div.style.position = 'fixed';
+ div.style.top = '0px';
+ div.style.left = '0px';
+ div.style.width = '100%';
+ div.style.height = '100%';
+ div.style.boxSizing = 'border-box';
+
+ var k = new K();
+ k.renderInto(div);
+
+ var p = enyo.dom.calcViewportPositionForNode(k.hasNode()),
+ // Bottom and right require calculating viewport size
+ fromBottom = (document.body.parentNode.offsetHeight > enyo.dom.getWindowHeight() ? enyo.dom.getWindowHeight() - document.body.parentNode.scrollTop : document.body.parentNode.offsetHeight) - 20,
+ fromRight = (document.body.parentNode.offsetWidth > enyo.dom.getWindowWidth() ? enyo.dom.getWindowWidth() - document.body.parentNode.scrollLeft : document.body.parentNode.offsetWidth) - 20;
+ if (p.top !== 10) {
+ this.log('top failed with value: ' + p.top + ' (should be 10)');
+ }
+ if (p.left !== 10) {
+ this.log('left failed with value: ' + p.left + ' (should be 10)');
+ }
+ if (p.bottom !== fromBottom) {
+ this.log('bottom failed with value: ' + p.bottom + ' (should be ' + fromBottom + ')');
+ }
+ if (p.right !== fromRight) {
+ this.log('right failed with value: ' + p.right + ' (should be ' + fromRight + ')');
+ }
+ if (p.width !== 10) {
+ this.log('width failed with value: ' + p.width + ' (should be 10)');
+ }
+ if (p.height !== 10) {
+ this.log('height failed with value: ' + p.height + ' (should be 10)');
+ }
+
+ // Now test measuring the element when a parent has a border
+ div.style.border = "1px solid transparent";
+ k.hasNode().style.border = "1px solid transparent"
+ p = enyo.dom.calcViewportPositionForNode(k.hasNode()),
+ // We don't count the right border on the element itself because that is taken into account automatically by the element's width measurement
+ fromBottom -= 3,
+ fromRight -= 3;
+ if (p.top !== 11) {
+ this.log('top with border failed with value: ' + p.top + ' (should be 11)');
+ }
+ if (p.left !== 11) {
+ this.log('left with border failed with value: ' + p.left + ' (should be 11)');
+ }
+ if (p.bottom !== fromBottom) {
+ this.log('bottom with border failed with value: ' + p.bottom + ' (should be ' + fromBottom + ')');
+ }
+ if (p.right !== fromRight) {
+ this.log('right with border failed with value: ' + p.right + ' (should be ' + fromRight + ')');
+ }
+ if (p.width !== 12) {
+ this.log('width with border failed with value: ' + p.width + ' (should be 12)');
+ }
+ if (p.height !== 12) {
+ this.log('height with border failed with value: ' + p.height + ' (should be 12)');
+ }
+
+ // Clean up
+ k.destroy();
+ document.body.removeChild(div);
+
+ this.finish(this.logMessages && this.logMessages.length ? 'Following measurements failed:' : '');
+ }
+});
View
3  tools/test/core/tests/package.js
@@ -10,5 +10,6 @@ enyo.depends(
"ControlTest.js",
"ControlPropsTest.js",
"DecodePackagePathTest.js",
- "PathResolverTest.js"
+ "PathResolverTest.js",
+ "ViewportPositioningTest.js"
);
Please sign in to comment.
Something went wrong with that request. Please try again.