Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'master' into eventHandlerImmutable

  • Loading branch information...
commit 160bf0da4488d21eae67a51cec2cd9520c75447b 2 parents c2dbfcd + a8b720f
Mark Bessey authored
Showing with 2,299 additions and 28,491 deletions.
  1. +10 −0 CONTRIBUTING md
  2. +14 −11 README.md
  3. +5 −2 loader.js
  4. +1 −1  package.json
  5. +10 −1 samples/AjaxSample.js
  6. +14 −4 samples/ScrollerSample.js
  7. +13 −10 source/ajax/Ajax.js
  8. +11 −1 source/ajax/AjaxProperties.js
  9. +12 −8 source/ajax/Async.js
  10. +9 −8 source/ajax/Jsonp.js
  11. +21 −2 source/ajax/WebService.js
  12. +28 −5 source/ajax/xhr.js
  13. +64 −3 source/boot/boot.js
  14. +108 −52 source/dom/Control.js
  15. +37 −3 source/dom/dispatcher.js
  16. +56 −0 source/dom/dom.js
  17. +16 −10 source/dom/gesture.js
  18. +8 −1 source/dom/platform.js
  19. +61 −29 source/kernel/Component.js
  20. +1 −1  source/kernel/Layout.js
  21. +4 −1 source/kernel/Object.js
  22. +35 −3 source/kernel/Oop.js
  23. +2 −1  source/kernel/Signals.js
  24. +21 −7 source/kernel/UiComponent.js
  25. +18 −13 source/touch/ScrollMath.js
  26. +7 −4 source/touch/ScrollStrategy.js
  27. +53 −18 source/touch/Scroller.js
  28. +11 −6 source/touch/TouchScrollStrategy.js
  29. +18 −11 source/touch/TranslateScrollStrategy.js
  30. +8 −1 source/touch/touch.js
  31. +6 −2 source/ui/Animator.js
  32. +2 −0  source/ui/BaseLayout.js
  33. +8 −2 source/ui/Button.js
  34. +3 −2 source/ui/Checkbox.js
  35. +15 −1 source/ui/DragAvatar.js
  36. +4 −2 source/ui/Group.js
  37. +1 −0  source/ui/GroupItem.js
  38. +8 −6 source/ui/Image.js
  39. +17 −13 source/ui/Input.js
  40. +27 −13 source/ui/Popup.js
  41. +10 −4 source/ui/Repeater.js
  42. +19 −11 source/ui/RichText.js
  43. +6 −5 source/ui/Select.js
  44. +27 −13 source/ui/Selection.js
  45. +6 −2 source/ui/TextArea.js
  46. +3 −1 source/ui/ToolDecorator.js
  47. +54 −61 tools/minifier/minify.js
  48. +1 −0  tools/minifier/node_modules/.bin/nopt
  49. 0  tools/minifier/node_modules/nopt/.npmignore
  50. +23 −0 tools/minifier/node_modules/nopt/LICENSE
  51. +210 −0 tools/minifier/node_modules/nopt/README.md
  52. +44 −0 tools/minifier/node_modules/nopt/bin/nopt.js
  53. +30 −0 tools/minifier/node_modules/nopt/examples/my-program.js
  54. +555 −0 tools/minifier/node_modules/nopt/lib/nopt.js
  55. +23 −0 tools/minifier/node_modules/nopt/node_modules/abbrev/README.md
  56. +106 −0 tools/minifier/node_modules/nopt/node_modules/abbrev/lib/abbrev.js
  57. +20 −0 tools/minifier/node_modules/nopt/node_modules/abbrev/package.json
  58. +31 −0 tools/minifier/node_modules/nopt/package.json
  59. +3 −1 tools/minifier/node_modules/uglify-js/.npmignore
  60. +9 −6 tools/minifier/node_modules/uglify-js/bin/uglifyjs
  61. +1 −1,380 tools/minifier/node_modules/uglify-js/lib/consolidator.js
  62. +0 −75 tools/minifier/node_modules/uglify-js/lib/object-ast.js
  63. +37 −19 tools/minifier/node_modules/uglify-js/lib/parse-js.js
  64. +96 −16 tools/minifier/node_modules/uglify-js/lib/process.js
  65. +1 −0  tools/minifier/node_modules/uglify-js/lib/squeeze-more.js
  66. +9 −16 tools/minifier/node_modules/uglify-js/package.json
  67. +7 −1 tools/minifier/node_modules/uglify-js/test/testparser.js
  68. +1 −1  tools/minifier/node_modules/uglify-js/test/unit/compress/expected/issue14.js
  69. +3 −1 tools/minifier/node_modules/uglify-js/test/unit/scripts.js
  70. +0 −13 tools/minifier/node_modules/uglify-js/tmp/269.js
  71. +0 −22,315 tools/minifier/node_modules/uglify-js/tmp/app.js
  72. +0 −15 tools/minifier/node_modules/uglify-js/tmp/embed-tokens.js
  73. +0 −26 tools/minifier/node_modules/uglify-js/tmp/goto.js
  74. +0 −8 tools/minifier/node_modules/uglify-js/tmp/goto2.js
  75. +0 −138 tools/minifier/node_modules/uglify-js/tmp/instrument2.js
  76. +0 −8 tools/minifier/node_modules/uglify-js/tmp/liftvars.js
  77. +0 −3,930 tools/minifier/node_modules/uglify-js/tmp/uglify-hangs.js
  78. +0 −166 tools/minifier/node_modules/uglify-js/tmp/uglify-hangs2.js
  79. +135 −0 tools/minifier/path-relative-shim.js
  80. +28 −0 tools/test/core/tests/ComponentTest.js
  81. +33 −1 tools/test/core/tests/KindTest.js
  82. +1 −0  tools/test/core/tests/package.js
View
10 CONTRIBUTING md
@@ -0,0 +1,10 @@
+# Contributions
+
+Contributions are welcome for Enyo and its associated libraries including onyx and layout.
+
+Please see [Contributing to Enyo](http://enyojs.com/community/contribute/) for details
+on our contribution policy and guidelines for use of the Enyo-DCO-1.0-Signed-off-by
+line in your commits and pull requests.
+
+If you're interested in introducing new kinds, you might also consider hosting your own repo
+and contributing to the [Enyo community gallery](http://enyojs.com/gallery).
View
25 README.md
@@ -25,13 +25,13 @@ Enyo up to 1.x was the underlying framework used to develop applications for HP'
Enyo was designed from the beginning to be highly extensible. This repository reflects a small working set of code, that can be expanded with any number of libraries or plugins.
-Enyo 2 is lightweight (at the time of this writing, roughly 13k gzipped), easy to digest, and powerful.
+Enyo 2 is lightweight, easy to digest, and powerful.
# What Do I Get
-The core code includes the Enyo kernel, the DOM extensions, and some Ajax (XHR) tools. These things are actually separable (it's easy to make micro-builds of Enyo), but we believe this is a useful working set.
+The core code includes the Enyo kernel, the DOM extensions, some Ajax (XHR) tools, and basic wrapper kinds for a lot of DOM form elements. These things are actually separable (it's easy to make micro-builds of Enyo), but we believe this is a useful working set.
-The Enyo 2 kernel provides a modularity concept (Component) and a view concept (UiComponent). The DOM aspect includes a widget concept (Control) and an extensible event system (Dispatcher). The Ajax package includes basic xhr functionality and an implementation of xhr as a Component (Ajax).
+The Enyo 2 kernel provides a modularity concept (Component) and a view concept (UiComponent). The DOM aspect includes a widget concept (Control) and an extensible event system (Dispatcher). The Ajax package includes basic xhr functionality and an implementation of xhr as a Component (Ajax). The touch package provides platform-optimized scrollers, while the UI package provides base kinds for common controls like buttons and popups.
Just these pieces are sufficient to create large applications using the Enyo encapsulation model. Developers that want only this low-level code are encouraged to roll-their-own. For those that want a richer set of tools, there are some pre-built libraries already available, and much more on the way.
@@ -66,10 +66,11 @@ Here is an Enyo Hello World:
<head>
<title>Enyo</title>
<script src="enyojs/2.0/enyo.js" type="text/javascript"></script>
+ <link href="enyojs/2.0/enyo.css" rel="stylesheet" type="text/css" />
</head>
<body>
<script type="text/javascript">
- new enyo.Control({content: "Hello From Enyo"}).write();
+ new enyo.Control({content: "Hello From Enyo"}).renderInto(document.body);
</script>
</body>
</html>
@@ -78,7 +79,8 @@ This example loads an enyo.js build from _enyojs/2.0/_. If you downloaded the SD
The base enyo.Control works much like an HTML tag. You can assign _classes_ and _attributes_ and give it a _style_. E.g.
- new enyo.Control({content: "Hello From Enyo", classes: "foo", style: "color: red", attributes: {tabIndex: 0}}).write();
+ new enyo.Control({content: "Hello From Enyo", classes: "foo", style: "color: red",
+ attributes: {tabIndex: 0}}).renderInto(document.body);
produces
@@ -91,7 +93,7 @@ Now, the good parts start when you combine more than one Control, e.g.
{content: "Hello From Enyo"},
{tag: "hr"}
]
- }).write();
+ }).renderInto(document.body);
This Control now encapsulates two Controls into one scope (we can encapsulate any type of Component, that's why the property is called _components_. Controls are one kind of Component.) The outer Control is responsible for the encapsulated components: it manages their lifecycle, listens to their messages, and maintains references to them. For example:
@@ -103,9 +105,9 @@ This Control now encapsulates two Controls into one scope (we can encapsulate an
helloTap: function() {
this.$.hello.addStyles("color: red");
}
- }).write();
+ }).renderInto(document.body);
-Here we've given one of the components a name ('hello') and told it to send a 'helloTap' message when it's tapped (tap is basically the same as the DOM click event, but it works in both mouse and touch environments). The _$_ property is a hash that references all the sub-components (we don't store these references directly on _this_ to avoid name conflicts). Btw, notice there is no add/remove machinery to listen to this event, that's all taken care of.
+Here we've given one of the components a name ('hello') and told it to send a 'helloTap' message when it's tapped (tap is basically the same as the DOM click event, but it works in both mouse and touch environments). The '$' property is a hash that references all the sub-components (we don't store these references directly on _this_ to avoid name conflicts). Notice there is no add/remove machinery to listen to this event, that's all taken care of.
The main point is that 'hello' and the 'hr', their references and behavior, are completely contained inside the outer control. Now, to re-use this, we need to make it a prototype.
@@ -123,9 +125,10 @@ Enyo contains a constructor/prototype-generator that we call enyo.kind. Construc
}
});
// make two, they're small
- new Hello().write();
- new Hello().write();
+ new enyo.Control({
+ component: [ {kind: "Hello"}, {kind: "Hello"} ]
+ }).renderInto(document.body);
The code above creates a new kind called "Hello" derived from enyo.Control. It contains some components and some behavior. I can create as many "Hello" objects as I want, each instance is independent, and the user of a "Hello" doesn't need to know anything about its internals.
-This ability to define encapsulated objects and behavior (Components) and to re-use those encapsulations as prototypes (kinds) is money.
+This ability to define encapsulated objects and behavior (Components) and to re-use those encapsulations as prototypes (kinds) is money.
View
7 loader.js
@@ -102,6 +102,9 @@
finish: function() {
this.packageFolder = "";
this.verbose && console.log("-------------- fini");
+ if (this.finishCallback) {
+ this.finishCallback();
+ }
},
continueBlock: function(inBlock) {
while (inBlock.index < inBlock.depends.length) {
@@ -129,10 +132,10 @@
// assemble path
path = prefix + path;
// process path
- if (path.slice(-3) == "css") {
+ if (path.slice(-4) == ".css") {
this.verbose && console.log("+ stylesheet: [" + prefix + "][" + inPath + "]");
this.requireStylesheet(path);
- } else if (path.slice(-2) == "js" && path.slice(-10) != "package.js") {
+ } else if (path.slice(-3) == ".js" && path.slice(-10) != "package.js") {
this.verbose && console.log("+ module: [" + prefix + "][" + inPath + "]");
this.requireScript(inPath, path);
} else {
View
2  package.json
@@ -12,7 +12,7 @@
"licenses": [{
"type": "Apache-2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0"
}],
- "bugs": "https://github.com/enyojs/enyo/issues/",
+ "bugs": "https://enyojs.atlassian.net/",
"repositories": [{
"type": "git", "url": "http://github.com/enyojs/enyo"
}]
View
11 samples/AjaxSample.js
@@ -8,11 +8,15 @@ enyo.kind({
{kind: "onyx.Input", name:"query", fit:true, value:'select * from upcoming.events where woeid in (select woeid from geo.places where text="Sunnyvale, CA")'},
{kind: "onyx.Button", content:"Fetch", ontap:"fetch"}
]},
+ {kind: "FittableColumns", classes:"onyx-toolbar-inline", components: [
+ {content: "URL: "},
+ {kind: "onyx.Input", name:"baseUrl", fit:true, value:'http://query.yahooapis.com/v1/public/yql?format=json'}
+ ]},
{kind: "onyx.TextArea", fit:true, classes:"ajax-sample-source"}
],
fetch: function() {
var ajax = new enyo.Ajax({
- url: "http://query.yahooapis.com/v1/public/yql?format=json"
+ url: this.$.baseUrl.getValue()
});
// send parameters the remote service using the 'go()' method
ajax.go({
@@ -20,9 +24,14 @@ enyo.kind({
});
// attach responders to the transaction object
ajax.response(this, "processResponse");
+ // handle error
+ ajax.error(this, "processError");
},
processResponse: function(inSender, inResponse) {
// do something with it
this.$.textArea.setValue(JSON.stringify(inResponse, null, 2));
+ },
+ processError: function(inSender, inResponse) {
+ alert("Error!");
}
});
View
18 samples/ScrollerSample.js
@@ -1,7 +1,7 @@
enyo.kind({
name: "enyo.sample.ScrollerSample",
kind: "FittableRows",
- classes: "enyo-fit",
+ classes: "enyo-fit enyo-unselectable",
components: [
{kind: "onyx.Toolbar", components: [
{kind: "onyx.PickerDecorator", components: [
@@ -14,7 +14,7 @@ enyo.kind({
]}
]}
]},
- {kind: "Panels", fit:true, classes: "scroller-sample-panels", components: [
+ {kind: "Panels", fit: true, draggable: false, classes: "scroller-sample-panels", components: [
// Default scroller (chooses best scrolling method for platform)
{kind: "Scroller", classes: "scroller-sample-scroller enyo-fit"},
// Forces touch scrolling, even on desktop
@@ -22,7 +22,7 @@ enyo.kind({
// Horizontal-only scrolling
{kind: "Scroller", vertical:"hidden", classes: "scroller-sample-scroller enyo-fit"},
// Vertical-only scrolling
- {kind: "Scroller", horizontal:"hidden", classes: "scroller-sample-scroller enyo-fit"}
+ {kind: "Scroller", horizontal:"hidden", classes: "scroller-sample-scroller enyo-fit", onmousedown: "mouseDown", ondragstart: "dragStart"}
]}
],
create: function() {
@@ -39,5 +39,15 @@ enyo.kind({
sampleChanged: function(inSender, inEvent) {
this.$.panels.setIndex(inEvent.selected.indexInContainer()-1);
},
- text: "Foo<br>Bar<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. <br>Foo<br>Bar<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. <br>Foo<br>Bar<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. <br>Foo<br>Bar<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. <br>"
+ text: "Foo<br>Bar<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. <br>Foo<br>Bar<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. <br>Foo<br>Bar<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. <br>Foo<br>Bar<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow<br>Foo<br>Bar<br>Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. Boom boom pow. <br>",
+ // The following are used when this sample is called from the Sampler app
+ mouseDown: function(inSender, inEvent) {
+ inEvent.preventDefault();
+ },
+ dragStart: function(inSender, inEvent) {
+ if (inEvent.horizontal) {
+ // Prevent drag propagation on horizontal drag events
+ return true;
+ }
+ }
});
View
23 source/ajax/Ajax.js
@@ -1,12 +1,12 @@
/**
_enyo.Ajax_ is a wrapper for _XmlHttpRequest_ that uses
the <a href="#enyo.Async">enyo.Async</a> API.
-
+
IMPORTANT: _enyo.Ajax_ publishes all the properties of the
<a href="#enyo.AjaxProperties">enyo.AjaxProperties</a>
object.
- Like _enyo.Async_, _enyo.Ajax_ is an **Object**, not a **Component**.
+ Like _enyo.Async_, _enyo.Ajax_ is an **Object**, not a **Component**.
Do not try to make _enyo.Ajax_ objects inside a _components_ block.
If you want to use _enyo.Ajax_ as a component, you should probably
@@ -16,7 +16,7 @@
getWoeid: function(inPlace) {
// setup <a href="#enyo.AjaxProperties">enyo.AjaxProperties</a> by sending them to the _enyo.Ajax_ constructor
- var x = enyo.Ajax({url: "http://query.yahooapis.com/v1/public/yql?format=json"});
+ var x = new enyo.Ajax({url: "http://query.yahooapis.com/v1/public/yql?format=json"});
// send parameters the remote service using the 'go()' method
x.go({
q: 'select woeid from geo.placefinder where text="' + inPlace + '"'
@@ -54,7 +54,7 @@ enyo.kind({
request: function(inParams) {
var parts = this.url.split("?");
var uri = parts.shift() || "";
- var args = parts.join("?").split("&");
+ var args = parts.length ? (parts.join("?").split("&")) : [];
//
var body = enyo.isString(inParams) ? inParams : enyo.Ajax.objectToQuery(inParams);
if (this.method == "GET") {
@@ -62,16 +62,18 @@ enyo.kind({
args.push(body);
body = null;
}
- if (this.cacheBust) {
+ // 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 url = [uri, args.join("&")].join("?");
+ var url = args.length ? [uri, args.join("&")].join("?") : uri;
//
- var xhr_headers = {
- "Content-Type": this.contentType
- };
+ var xhr_headers = {};
+ if (this.method != "GET") {
+ xhr_headers["Content-Type"] = this.contentType;
+ }
enyo.mixin(xhr_headers, this.headers);
//
this.xhr = enyo.xhr.request({
@@ -83,7 +85,8 @@ enyo.kind({
sync: window.PalmSystem ? false : this.sync,
username: this.username,
password: this.password,
- xhrFields: this.xhrFields
+ xhrFields: this.xhrFields,
+ mimeType: this.mimeType
});
},
receive: function(inText, inXhr) {
View
12 source/ajax/AjaxProperties.js
@@ -1,3 +1,8 @@
+/**
+ Common set of published properties used in both
+ <a href="#enyo.Ajax">enyo.Ajax</a> and
+ <a href="#enyo.WebService">enyo.WebService</a>.
+*/
enyo.AjaxProperties = {
/**
When true, appends a random number as a parameter for GET requests
@@ -46,6 +51,11 @@ enyo.AjaxProperties = {
password: "",
/**
Optional object with fields to pass directly to the underlying XHR object.
+ One example is the _withCredentials_ flag used for cross-origin requests.
*/
- xhrFields: null
+ xhrFields: null,
+ /**
+ Optional string to override the MIME-Type.
+ */
+ mimeType: null
};
View
20 source/ajax/Async.js
@@ -13,13 +13,17 @@
More information on _Async_ and its usage is available in the
<a href="https://github.com/enyojs/enyo/wiki/Async">Async documentation</a>
in the Enyo Developer Guide.
-
-
-
*/
enyo.kind({
name: "enyo.Async",
kind: enyo.Object,
+ published: {
+ /**
+ If set to a non-zero value, the number of milliseconds to
+ wait after the _go_ call before failing with the "timeout" error
+ */
+ timeout: 0
+ },
//* @protected
failed: false,
context: null,
@@ -34,7 +38,7 @@ enyo.kind({
//* @public
/**
Registers a response function.
- First parameter is an optional this context for the response method.
+ First parameter is an optional _this_ context for the response method.
Second (or only) parameter is the function object.
*/
response: function(/* [inContext], inResponder */) {
@@ -43,7 +47,7 @@ enyo.kind({
},
/**
Registers an error handler.
- First parameter is an optional this context for the response method.
+ First parameter is an optional _this_ context for the response method.
Second (or only) parameter is the function object.
*/
error: function(/* [inContext], inResponder */) {
@@ -96,7 +100,7 @@ enyo.kind({
this.fail("timeout");
},
//* @protected
- //* Called as part of the async implementation, triggers the handler chain.
+ //* Called as part of the async implementation; triggers the handler chain.
respond: function(inValue) {
this.failed = false;
this.endTimer();
@@ -109,8 +113,8 @@ enyo.kind({
this.endTimer();
this.handle(inError, this.errorHandlers);
},
- //* Called from an error handler, this method clears the error
- // condition and resumes calling handler methods.
+ //* Called from an error handler; clears the error condition and resumes
+ //* calling handler methods.
recover: function() {
this.failed = false;
},
View
17 source/ajax/Jsonp.js
@@ -1,15 +1,16 @@
/**
- A specialized form of <a href="#enyo.Async">enyo.Async</a> used for making
- JSONP requests to a remote server. This differs from the normal
- XmlHTTPRequest call in that the external resource is loaded using a
- &lt;script&gt; tag. This allows us to bypass the same-domain rules that
- normally apply to XHR, since the browser will load scripts from any address.
+ _enyo.JsonpRequest_ is a specialized form of
+ <a href="#enyo.Async">enyo.Async</a> used for making JSONP requests to a
+ remote server. This differs from the normal XmlHTTPRequest call in that the
+ external resource is loaded using a &lt;script&gt; tag. This allows us to
+ bypass the same-domain rules that normally apply to XHR, since the browser
+ will load scripts from any address.
*/
enyo.kind({
name: "enyo.JsonpRequest",
kind: enyo.Async,
published: {
- //* The URL for the service.
+ //* The URL for the service
url: "",
//* Optional character set to use to interpret the return data
charset: null,
@@ -22,7 +23,8 @@ enyo.kind({
callbackName: "callback",
/**
When true, appends a random number as a parameter for GET requests
- to try to force a new fetch of the resource instead of reusing a local cache.
+ to try to force a new fetch of the resource instead of reusing a
+ local cache
*/
cacheBust: true
},
@@ -42,7 +44,6 @@ enyo.kind({
script.onerror = enyo.bind(this, function() {
// we don't get an error code, so we'll just use the generic 400 error status
this.fail(400);
- this.removeScriptElement();
});
// add script before existing script to make sure it's in a valid part of document
// http://www.jspatterns.com/the-ridiculous-case-of-adding-a-script-element/
View
23 source/ajax/WebService.js
@@ -21,7 +21,7 @@ enyo.kind({
name: "enyo.WebService",
kind: enyo._AjaxComponent,
published: {
- //* Set to true to use JSONP protocol.
+ //* Set to true to use JSONP protocol
jsonp: false,
/**
When using JSONP, the name of the callback parameter.
@@ -30,11 +30,28 @@ enyo.kind({
internal callback function as necessary.
*/
callbackName: "callback",
- //* When using JSONP, optional character set to use to interpret the return data
+ /**
+ When using JSONP, optional character set to use to interpret the
+ return data
+ */
charset: null
},
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: ""
},
//* @protected
@@ -42,6 +59,8 @@ 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);
},
View
33 source/ajax/xhr.js
@@ -11,9 +11,10 @@ enyo.xhr = {
- _username_: The optional user name to use for authentication purposes.
- _password_: The optional password to use for authentication purposes.
- _xhrFields_: Optional object containing name/value pairs to mix directly into the generated xhr object.
+ - _mimeType_: Optional string to override the MIME-Type.
*/
request: function(inParams) {
- var xhr = this.getXMLHttpRequest();
+ var xhr = this.getXMLHttpRequest(inParams.url);
//
var method = inParams.method || "GET";
var async = ("sync" in inParams) ? !inParams.sync : true;
@@ -33,6 +34,10 @@ enyo.xhr = {
}
}
//
+ if(typeof(xhr.overrideMimeType) == "function" && inParams.mimeType) {
+ xhr.overrideMimeType(inParams.mimeType);
+ }
+ //
xhr.send(inParams.body || null);
if (!async) {
xhr.onreadystatechange(xhr);
@@ -41,22 +46,40 @@ enyo.xhr = {
},
//* @protected
makeReadyStateHandler: function(inXhr, inCallback) {
+ if (window.XDomainRequest && inXhr instanceof XDomainRequest) {
+ inXhr.onload = function() {
+ inCallback && inCallback.apply(null, [inXhr.responseText, inXhr]);
+ };
+ }
inXhr.onreadystatechange = function() {
if (inXhr.readyState == 4) {
inCallback && inCallback.apply(null, [inXhr.responseText, inXhr]);
}
};
},
- getXMLHttpRequest: function() {
+ inOrigin: function(inUrl) {
+ var a = document.createElement("a"), result = false;
+ a.href = inUrl;
+ if (a.protocol === ":" || (a.protocol === window.location.protocol && a.hostname === window.location.hostname && a.port === window.location.port)) {
+ result = true;
+ }
+ return result;
+ },
+ getXMLHttpRequest: function(inUrl) {
+ try {
+ if (window.XDomainRequest && !this.inOrigin(inUrl) && !/^file:\/\//.test(window.location.href)) {
+ return new XDomainRequest();
+ }
+ } catch(e) {}
try {
return new XMLHttpRequest();
- } catch (e) {}
+ } catch(e) {}
try {
return new ActiveXObject('Msxml2.XMLHTTP');
- } catch (e) {}
+ } catch(e) {}
try {
return new ActiveXObject('Microsoft.XMLHTTP');
- } catch (e) {}
+ } catch(e) {}
return null;
}
};
View
67 source/boot/boot.js
@@ -1,10 +1,27 @@
// machine for a loader instance
enyo.machine = {
sheet: function(s) {
- document.write('<link href="' + s + '" media="screen" rel="stylesheet" type="text/css" />');
+ if (!enyo.runtimeLoading) {
+ document.write('<link href="' + s + '" media="screen" rel="stylesheet" type="text/css" />');
+ } else {
+ var link = document.createElement('link');
+ link.href = s;
+ link.media = "screen";
+ link.rel = "stylesheet";
+ link.type = "text/css";
+ document.getElementsByTagName('head')[0].appendChild(link);
+ }
},
script: function(inSrc, onLoad, onError) {
- document.write('<scri' + 'pt src="' + inSrc + '"' + (onLoad ? ' onload="' + onLoad + '"' : '') + (onError ? ' onerror="' + onError + '"' : '') + '></scri' + 'pt>');
+ if (!enyo.runtimeLoading) {
+ document.write('<scri' + 'pt src="' + inSrc + '"' + (onLoad ? ' onload="' + onLoad + '"' : '') + (onError ? ' onerror="' + onError + '"' : '') + '></scri' + 'pt>');
+ } else {
+ var script = document.createElement('script');
+ script.src = inSrc;
+ script.onLoad = onLoad;
+ script.onError = onError;
+ document.getElementsByTagName('head')[0].appendChild(script);
+ }
},
inject: function(inCode) {
document.write('<script type="text/javascript">' + inCode + "</script>");
@@ -28,8 +45,52 @@ enyo.depends = function() {
ldr.load.apply(ldr, arguments);
};
+// Runtime loader
+// Usage: enyo.load(depends, [onLoadCallback])
+// where - depends is string or array of string paths to package.js, script, or css to load
+// - doneCallback is fired after file or package loading has completed
+// Only one file/package is loaded at a time; additional calls are queued and loading deferred
+(function() {
+ var enyo = window.enyo;
+ var runtimeLoadQueue = [];
+ enyo.load = function(depends, onLoadCallback) {
+ runtimeLoadQueue.push(arguments);
+ if (!enyo.runtimeLoading) {
+ enyo.runtimeLoading = true;
+ runtimeLoad();
+ }
+ }
+ function runtimeLoad(onLoad) {
+ if (onLoad) {
+ onLoad(); // Run user callback function
+ }
+ if (runtimeLoadQueue.length) {
+ var args = runtimeLoadQueue.shift();
+ var depends = args[0];
+ var dependsArg = enyo.isArray(depends) ? depends : [depends];
+ var onLoadCallback = args[1];
+ enyo.loader.finishCallback = function() {
+ // Once loader is done loading a package, we chain a call to runtimeLoad(),
+ // which will call the onLoadCallback from the original load call, passing
+ // a reference to the depends argument from the original call for tracking,
+ // followed by kicking off any additionally queued load() calls
+ runtimeLoad(function() {
+ onLoadCallback && onLoadCallback(depends);
+ });
+ }
+ enyo.loader.packageFolder = "./";
+ // Kick off next queued call to loader
+ enyo.depends.apply(this, dependsArg);
+ } else {
+ enyo.runtimeLoading = false;
+ enyo.loader.finishCallback = null;
+ enyo.loader.packageFolder = "";
+ }
+ }
+})();
+
// predefined path aliases
enyo.path.addPaths({
enyo: enyo.args.root,
lib: "$enyo/../lib"
-});
+});
View
160 source/dom/Control.js
@@ -1,20 +1,37 @@
+/**
+ _enyo.Control_ is a component that controls a DOM node (i.e., an element in
+ the user interface). Controls are generally visible and the user often
+ interacts with them directly. While things like buttons and input boxes are
+ obviously controls, in Enyo, a control may become as complex as an entire
+ application.
+
+ For more information, see the documentation on
+ <a href="https://github.com/enyojs/enyo/wiki/Creating-Controls">Controls</a>
+ in the Enyo Developer Guide.
+*/
enyo.kind({
name: "enyo.Control",
kind: enyo.UiComponent,
published: {
- //* HTML tag name to use for control. If it's null, no tag is generated, only the contents are used.
+ /**
+ HTML tag name to use for the control. If null, no tag is generated;
+ only the contents are used.
+ */
tag: "div",
- //* Hash of DOM attributes to apply to the generated HTML tag.
+ //* Hash of DOM attributes to apply to the generated HTML tag
attributes: null,
- //* Space-delimited set of CSS classes to apply to the generated HTML tag.
+ //* Space-delimited set of CSS classes to apply to the generated HTML tag
classes: "",
- //* Style attribute to apply to the generated HTML tag.
+ //* Style attribute to apply to the generated HTML tag
style: "",
- //* Content that will be generated inside the HTML tag; defaults to plain text unless _allowHtml_ is true.
+ /**
+ Content that will be generated inside the HTML tag; defaults to
+ plain text unless _allowHtml_ is true
+ */
content: "",
- //* Boolean indicating whether the tag will be visible or hidden in the document.
+ //* Boolean indicating whether the tag will be visible in the document
showing: true,
- //* If false, HTML codes in _content_ are escaped before rendering.
+ //* If false, HTML codes in _content_ are escaped before rendering
allowHtml: false,
//
// convenience properties for common attributes
@@ -25,25 +42,27 @@ enyo.kind({
// esoteric
//
/**
- Set to false if the control should not generate any HTML. Used to inhibit generation
- of popups until they're shown at runtime.
+ Set to false if the control should not generate any HTML. Used to
+ inhibit generation of popups until they're shown at runtime.
*/
canGenerate: true,
//
// ad hoc properties:
//
- //* Flag used by control layouts to pick which control will expand to fill area.
+ //* Flag used by control layouts to determine which control will expand
+ //* to fill the available space
fit: false,
- //* Used by Ares design editor for design objects.
+ //* Used by Ares design editor for design objects
isContainer: false
},
handlers: {
//* Controls will call a user-provided _tap_ method when tapped upon.
ontap: "tap"
},
- //* The default kind for controls created inside this control that don't specify their own kind.
+ //* The default kind for controls created inside this control that don't
+ //* specify their own kind
defaultKind: "Control",
- //* A set of CSS classes that are applied to controls created inside this control.
+ //* A set of CSS classes that are applied to controls created inside this control
controlClasses: "",
//* @protected
node: null,
@@ -69,6 +88,7 @@ enyo.kind({
},
destroy: function() {
this.removeNodeFromDom();
+ enyo.Control.unregisterDomEvents(this.id);
this.inherited(arguments);
},
importProps: function(inProps) {
@@ -78,7 +98,7 @@ enyo.kind({
},
initProps: function(inPropNames) {
// for each named property, trigger the *Changed handler if the property value is truthy
- for (var i=0, n, cf; n=inPropNames[i]; i++) {
+ for (var i=0, n, cf; (n=inPropNames[i]); i++) {
if (this[n]) {
// FIXME: awkward
cf = n + "Changed";
@@ -125,7 +145,7 @@ enyo.kind({
//
//* @public
/**
- Returns the DOM node representing the Control.
+ Returns the DOM node representing the control.
If the control is not currently rendered, returns null.
If hasNode() returns a value, the _node_ property will be valid and
@@ -145,7 +165,8 @@ enyo.kind({
return this.generated && (this.node || this.findNodeById());
},
/**
- Appends the String value of _inAddendum_ to the _content_ of this Control.
+ Appends the string value of _inAddendum_ to the _content_ of this
+ control.
*/
addContent: function(inAddendum) {
this.setContent(this.content + inAddendum);
@@ -153,11 +174,13 @@ enyo.kind({
/**
Gets the value of an attribute on this object.
- If this Control has a node, the attribute value is retrieved from the node;
- otherwise, it's read from the _attributes_ property of the control itself.
+ If this control has a node, the attribute value is retrieved from the
+ node; otherwise, it's read from the _attributes_ property of the control
+ itself.
- Caveat: If the control is rendered, the _attributes_ property is used to construct
- the rendering, and values that have changed on the node itself are lost.
+ Caveat: If the control is rendered, the _attributes_ property is used to
+ construct the rendering, and values that have changed on the node itself
+ are lost.
// Get the value attribute for this DomNode
var value = this.getAttribute("tabIndex");
@@ -166,7 +189,8 @@ enyo.kind({
return this.hasNode() ? this.node.getAttribute(inName) : this.attributes[inName];
},
/**
- Sets the value of an attribute on this object. Pass null _inValue_ to remove an attribute.
+ Sets the value of an attribute on this object. Pass null _inValue_ to
+ remove an attribute.
// set the tabIndex attribute for this DomNode
this.setAttribute("tabIndex", 3);
@@ -181,6 +205,11 @@ enyo.kind({
}
this.invalidateTags();
},
+ /**
+ Gets the value of a property named _inName_ directly from the DOM node.
+ A caller-specified default value, _inDefault_, is returned when the DOM
+ node has not yet been created.
+ */
getNodeProperty: function(inName, inDefault) {
if (this.hasNode()) {
return this.node[inName];
@@ -188,6 +217,12 @@ enyo.kind({
return inDefault;
}
},
+ /**
+ Sets the value of the _inName_ property on the control's DOM node to
+ _inValue_, if and only if the DOM node has been rendered. This method
+ does not alter any values cached in local properties of the
+ _enyo.Control_ instance.
+ */
setNodeProperty: function(inName, inValue) {
if (this.hasNode()) {
this.node[inName] = inValue;
@@ -214,11 +249,12 @@ enyo.kind({
return this.attributes["class"] || "";
},
/**
- Returns true if the _class_ attribute contains a substring matching _inClass_.
+ Returns true if the _class_ attribute contains a substring matching
+ _inClass_.
The _class_ attribute is a string that can contain multiple CSS classes.
This method tests whether a particular class is part of the set of
- classes on this Control.
+ classes on this control.
// returns true if _class_ is "bar foo baz", but false for "barfoobaz"
var hasFooClass = this.$.control.hasClass("foo");
@@ -243,8 +279,9 @@ enyo.kind({
_inClass_ must have no leading or trailing spaces.
- Using a compound class name is supported, but the name is treated atomically.
- For example, given "a b c", removeClass("a b") will produce "c", but removeClass("a c") will produce "a b c".
+ Using a compound class name is supported, but the name is treated
+ atomically. For example, given _"a b c"_, _removeClass("a b")_ will
+ produce _"c"_, but _removeClass("a c")_ will produce _"a b c"_.
// remove the highlight class from this object
this.removeClass("highlight");
@@ -257,10 +294,11 @@ enyo.kind({
}
},
/**
- Adds or removes substring _inClass_ from the _class_ attribute of this object based
- on the value of _inTrueToAdd_.
+ Adds or removes substring _inClass_ from the _class_ attribute of this
+ object based on the value of _inTrueToAdd_.
- If _inTrueToAdd_ is truthy, then _inClass_ is added; otherwise, _inClass_ is removed.
+ If _inTrueToAdd_ is truthy, then _inClass_ is added; otherwise,
+ _inClass_ is removed.
// add or remove the highlight class, depending on the "highlighted" property
this.addRemoveClass("highlight", this.highlighted);
@@ -271,6 +309,7 @@ enyo.kind({
//
// styles
//
+ //* @protected
initStyles: function() {
this.domStyles = this.domStyles || {};
enyo.Control.cssTextToDomStyles(this.kindStyle, this.domStyles);
@@ -292,12 +331,13 @@ enyo.kind({
this.invalidateTags();
this.renderStyles();
},
+ //* @public
/**
Applies a single style value to this object.
this.$.box.applyStyle("z-index", 4);
- You can remove a style by setting its value to null.
+ You may remove a style by setting its value to null.
this.$.box.applyStyle("z-index", null);
*/
@@ -316,6 +356,13 @@ enyo.kind({
enyo.Control.cssTextToDomStyles(inCssText, this.domStyles);
this.domStylesChanged();
},
+ /**
+ Returns the computed value of a CSS style named from _inStyle_
+ for the DOM node of the control. If the node hasn't been generated,
+ returns _inDefault_ as a default value. This uses JavaScript-style
+ property names, not CSS-style names, so use "fontFamily" instead of
+ "font-family".
+ */
getComputedStyleValue: function(inStyle, inDefault) {
if (this.hasNode()) {
return enyo.dom.getComputedStyleValue(this.node, inStyle);
@@ -331,6 +378,10 @@ enyo.kind({
stylesToNode: function() {
this.node.style.cssText = this.style + (this.style[this.style.length-1] == ';' ? ' ' : '; ') + this.domCssText;
},
+ setupBodyFitting: function() {
+ enyo.dom.applyBodyFit();
+ this.addClass("enyo-fit enyo-clip");
+ },
//
//
//* @public
@@ -381,8 +432,13 @@ enyo.kind({
},
/**
Uses _document.write_ to output the control into the document.
- If control has _fit: true_ defined, appropriate styles will be set
+ If the control has _fit: true_ defined, appropriate styles will be set
to have it expand to fill its container.
+
+ Note that this has all the limitations that _document.write_ has.
+ It only works while the page is loading, so you can't call this from an
+ event handler. Also, it will not work in certain environments, such as
+ Chrome Packaged Apps or Windows 8.
*/
write: function() {
if (this.fit) {
@@ -394,10 +450,6 @@ enyo.kind({
// support method chaining
return this;
},
- setupBodyFitting: function() {
- enyo.dom.applyBodyFit();
- this.addClass("enyo-fit enyo-clip");
- },
/**
Override this method to perform tasks that require access to the DOM node.
@@ -410,7 +462,7 @@ enyo.kind({
// CAVEAT: Currently we use one entry point ('reflow') for
// post-render layout work *and* post-resize layout work.
this.reflow();
- for (var i=0, c; c=this.children[i]; i++) {
+ for (var i=0, c; (c=this.children[i]); i++) {
c.rendered();
}
},
@@ -441,9 +493,11 @@ enyo.kind({
return {left: n.offsetLeft, top: n.offsetTop, width: n.offsetWidth, height: n.offsetHeight};
},
/**
- Sets any or all of geometry style properties _width_, _height_, _left_, _top_, _right_ and _bottom_.
+ Sets any or all of the geometry style properties _width_, _height_,
+ _left_, _top_, _right_ and _bottom_.
- Values may be specified as strings (with units specified), or as numbers when a unit is provided in _inUnit_.
+ Values may be specified as strings (with units included), or as numbers
+ when a unit is provided in _inUnit_.
this.setBounds({width: 100, height: 100}, "px"); // adds style properties like "width: 100px; height: 100px;"
//
@@ -452,7 +506,7 @@ enyo.kind({
setBounds: function(inBounds, inUnit) {
var s = this.domStyles, unit = inUnit || "px";
var extents = ["width", "height", "left", "top", "right", "bottom"];
- for (var i=0, b, e; e=extents[i]; i++) {
+ for (var i=0, b, e; (e=extents[i]); i++) {
b = inBounds[e];
if (b || b === 0) {
s[e] = b + (!enyo.isString(b) ? unit : '');
@@ -523,7 +577,7 @@ enyo.kind({
},
generateChildHtml: function() {
var results = '';
- for (var i=0, c; c=this.children[i]; i++) {
+ for (var i=0, c; (c=this.children[i]); i++) {
var h = c.generateHtml();
if (c.prepend) {
// FIXME: does webkit's fast string-consing work in reverse?
@@ -548,11 +602,10 @@ enyo.kind({
},
prepareTags: function() {
var htmlStyle = this.domCssText + this.style;
- this._openTag = '<'
- + this.tag
- + (htmlStyle ? ' style="' + htmlStyle + '"' : "")
- + enyo.Control.attributesToHtml(this.attributes)
- ;
+ this._openTag = '<' +
+ this.tag +
+ (htmlStyle ? ' style="' + htmlStyle + '"' : "") +
+ enyo.Control.attributesToHtml(this.attributes);
if (enyo.Control.selfClosing[this.tag]) {
this._openTag += '/>';
this._closeTag = '';
@@ -576,7 +629,7 @@ enyo.kind({
}
},
getParentNode: function() {
- return this.parentNode || (this.parent && this.parent.hasNode());
+ return this.parentNode || (this.parent && (this.parent.hasNode() || this.parent.getParentNode()));
},
addNodeToParent: function() {
if (this.node) {
@@ -605,7 +658,7 @@ enyo.kind({
this.generated = false;
},
teardownChildren: function() {
- for (var i=0, c; c=this.children[i]; i++) {
+ for (var i=0, c; (c=this.children[i]); i++) {
c.teardownRender();
}
},
@@ -678,8 +731,10 @@ enyo.kind({
//
statics: {
/**
- Returns passed-in string with ampersand, less-than, and greater-than characters replaced by HTML entities,
- e.g. '&lt;code&gt;"This &amp; That"&lt;/code&gt;' becomes '&amp;lt;code&amp;gt;"This &amp;amp; That"&amp;lt;/code&amp;gt;'
+ Returns passed-in string with ampersand, less-than, and greater-than
+ characters replaced by HTML entities, e.g.,
+ '&lt;code&gt;"This &amp; That"&lt;/code&gt;' becomes
+ '&amp;lt;code&amp;gt;"This &amp;amp; That"&amp;lt;/code&amp;gt;'
*/
escapeHtml: function(inText) {
return inText != null ? String(inText).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') : '';
@@ -698,7 +753,7 @@ enyo.kind({
// remove spaces between rules, then split rules on delimiter (;)
var rules = inText.replace(/; /g, ";").split(";");
// parse string styles into name/value pairs
- for (var i=0, s, n, v, rule; rule=rules[i]; i++) {
+ for (var i=0, s, n, v, rule; (rule=rules[i]); i++) {
// "background-image: url(http://foo.com/foo.png)" => ["background-image", "url(http", "//foo.com/foo.png)"]
s = rule.split(":");
// n = "background-image", s = ["url(http", "//foo.com/foo.png)"]
@@ -725,8 +780,9 @@ enyo.kind({
return (cssText ? ' style="' + cssText + '"' : "");
},
/**
- Returns passed-in string with ampersand and double quote characters replaced by HTML entities,
- e.g. 'hello from "Me & She"' becomes 'hello from &amp;quot;Me &amp;amp; She&amp;quot;'
+ Returns passed-in string with ampersand and double quote characters
+ replaced by HTML entities, e.g., 'hello from "Me & She"' becomes
+ 'hello from &amp;quot;Me &amp;amp; She&amp;quot;'
*/
escapeAttribute: function(inText) {
return !enyo.isString(inText) ? inText : String(inText).replace(/&/g,'&amp;').replace(/\"/g,'&quot;');
@@ -782,4 +838,4 @@ enyo.Control.subclass = function(ctor, props) {
proto.kindAttributes = enyo.mixin(enyo.clone(ka), proto.attributes);
proto.attributes = null;
}
-};
+};
View
40 source/dom/dispatcher.js
@@ -14,6 +14,13 @@ enyo.dispatcher = {
d.listen(document, n);
}
for (i=0, n; n=d.windowEvents[i]; i++) {
+ // Chrome Packaged Apps don't like "unload"
+ if(n === "unload"
+ && typeof(window.chrome) === "object"
+ && window.chrome.app) {
+ continue;
+ }
+
d.listen(window, n);
}
},
@@ -56,8 +63,8 @@ enyo.dispatcher = {
//* Takes an Event.target and finds the corresponding Enyo control.
findDispatchTarget: function(inNode) {
var t, n = inNode;
- // FIXME: Mozilla: try/catch is here to squelch "Permission denied to access property xxx from a non-chrome context"
- // which appears to happen for scrollbar nodes in particular. It's unclear why those nodes are valid targets if
+ // FIXME: Mozilla: try/catch is here to squelch "Permission denied to access property xxx from a non-chrome context"
+ // which appears to happen for scrollbar nodes in particular. It's unclear why those nodes are valid targets if
// it is illegal to interrogate them. Would like to trap the bad nodes explicitly rather than using an exception block.
try {
while (n) {
@@ -108,7 +115,34 @@ enyo.bubble = function(inEvent) {
// This string is set on event handlers attributes for DOM elements that
// don't normally bubble (like onscroll) so that they can participate in the
// Enyo event system.
-enyo.bubbler = 'enyo.bubble(arguments[0])';
+enyo.bubbler = "enyo.bubble(arguments[0])";
+
+// The code below helps make Enyo compatible with Google Packages Apps
+// Content Security Policy(http://developer.chrome.com/extensions/contentSecurityPolicy.html)
+// which, among other things forbids use of inline scripts.
+// We replace online scripting with equivalent means, leaving enyo.bubbler
+// for backward compatibility.
+(function() {
+ var bubbleUp = function() {
+ enyo.bubble(arguments[0]);
+ };
+
+ /**
+ * Makes given events bubble on specified enyo contol
+ */
+ enyo.makeBubble = function() {
+ var args = Array.prototype.slice.call(arguments, 0),
+ control = args.shift();
+
+ if(typeof(control) === "object" && typeof(control.hasNode) === "function") {
+ enyo.forEach(args, function(event) {
+ if(this.hasNode()) {
+ this.node.addEventListener(event, bubbleUp);
+ }
+ }, control);
+ }
+ };
+})();
// FIXME: we need to create and initialize dispatcher someplace else to allow overrides
enyo.requiresWindow(enyo.dispatcher.connect);
View
56 source/dom/dom.js
@@ -67,5 +67,61 @@ enyo.dom = {
return document.documentElement.offsetWidth;
}
return 320;
+ },
+ // moved from FittableLayout.js into common protected code
+ _ieCssToPixelValue: function(inNode, inValue) {
+ var v = inValue;
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+ var s = inNode.style;
+ // store style and runtime style values
+ var l = s.left;
+ var rl = inNode.runtimeStyle && inNode.runtimeStyle.left;
+ // then put current style in runtime style.
+ if (rl) {
+ inNode.runtimeStyle.left = inNode.currentStyle.left;
+ }
+ // apply given value and measure its pixel value
+ s.left = v;
+ v = s.pixelLeft;
+ // finally restore previous state
+ s.left = l;
+ if (rl) {
+ s.runtimeStyle.left = rl;
+ }
+ return v;
+ },
+ _pxMatch: /px/i,
+ getComputedBoxValue: function(inNode, inProp, inBoundary, inComputedStyle) {
+ var s = inComputedStyle || this.getComputedStyle(inNode);
+ if (s) {
+ return parseInt(s.getPropertyValue(inProp + "-" + inBoundary), 0);
+ } else if (inNode && inNode.currentStyle) {
+ var v = inNode.currentStyle[inProp + enyo.cap(inBoundary)];
+ if (!v.match(this._pxMatch)) {
+ v = this._ieCssToPixelValue(inNode, v);
+ }
+ return parseInt(v, 0);
+ }
+ return 0;
+ },
+ //* @public
+ //* Gets the boundaries of a node's margin or padding box.
+ calcBoxExtents: function(inNode, inBox) {
+ var s = this.getComputedStyle(inNode);
+ return {
+ top: this.getComputedBoxValue(inNode, inBox, "top", s),
+ right: this.getComputedBoxValue(inNode, inBox, "right", s),
+ bottom: this.getComputedBoxValue(inNode, inBox, "bottom", s),
+ left: this.getComputedBoxValue(inNode, inBox, "left", s)
+ };
+ },
+ //* Gets the calculated padding of a node.
+ calcPaddingExtents: function(inNode) {
+ return this.calcBoxExtents(inNode, "padding");
+ },
+ //* Gets the calculated margin of a node.
+ calcMarginExtents: function(inNode) {
+ return this.calcBoxExtents(inNode, "margin");
}
};
View
26 source/dom/gesture.js
@@ -1,14 +1,15 @@
//* @public
/**
- Enyo supports a set of cross-platform gesture events that work similarly on
- all supported platforms. These events are provided so that users can write a
- single set of event handlers for applications that run on both mobile and
+ Enyo supports a set of normalized events that work similarly across all
+ supported platforms. These events are provided so that users can write a
+ single set of event handlers for applications that run on both mobile and
desktop platforms. They are needed because desktop and mobile platforms
- handle basic gestures differently.
-
- For more information on gesture events and their associated properties, see
- the documentation on [Gestures](https://github.com/enyojs/enyo/wiki/Gestures)
- in the Enyo Developer Guide.
+ handle basic input differently.
+
+ For more information on normalized input events and their associated
+ properties, see the documentation on
+ [User Input](https://github.com/enyojs/enyo/wiki/User-Input) in the Enyo
+ Developer Guide.
*/
enyo.gesture = {
//* @protected
@@ -23,10 +24,15 @@ enyo.gesture = {
e.preventDefault = this.preventDefault;
e.disablePrevention = this.disablePrevention;
//
- // normalize event.which
- // Note that while "which" works in IE9, it is broken for mousemove. Therefore,
+ // normalize event.which and event.pageX/event.pageY
+ // Note that while "which" works in IE9, it is broken for mousemove. Therefore,
// in IE, use window.event.button
if (enyo.platform.ie) {
+ //Fix for IE8, which doesn't include pageX and pageY properties
+ if(enyo.platform.ie==8 && e.target) {
+ e.pageX = e.clientX + e.target.scrollLeft;
+ e.pageY = e.clientY + e.target.scrollTop;
+ }
var b = window.event && window.event.button;
// multi-button not supported, priority: left, right, middle
// (note: IE bitmask is 1=left, 2=right, 4=center);
View
9 source/dom/platform.js
@@ -3,9 +3,12 @@
Can have one of the following properties:
* android
+ * androidChrome (Chrome on Android, standard starting in 4.1)
* ie
* ios
* webos
+ * safari (desktop version)
+ * chrome (desktop version)
If the property is defined, its value will be the major version number
of the platform.
@@ -32,6 +35,8 @@ enyo.platform = {
var ua = navigator.userAgent;
var ep = enyo.platform;
var platforms = [
+ // Android 4+ using Chrome
+ {platform: "androidChrome", regex: /Android .* Chrome\/(\d+)[.\d]+/},
// Android 2 - 4
{platform: "android", regex: /Android (\d+)/},
// Kindle Fire
@@ -45,7 +50,9 @@ enyo.platform = {
// webOS 1 - 3
{platform: "webos", regex: /(?:web|hpw)OS\/(\d+)/},
// desktop safari
- {platform: "safari", regex: /Version\/(\d+)[.\d]+\s+Safari/}
+ {platform: "safari", regex: /Version\/(\d+)[.\d]+\s+Safari/},
+ // desktop Chrome
+ {platform: "chrome", regex: /Chrome\/(\d+)[.\d]+/}
];
for (var i = 0, p, m, v; p = platforms[i]; i++) {
m = p.regex.exec(ua);
View
90 source/kernel/Component.js
@@ -41,8 +41,26 @@ enyo.kind({
name: "enyo.Component",
kind: enyo.Object,
published: {
+ /**
+ A unique name for the component within its owner. This is used to
+ set the access name in the owner's _$_ hash. If not specified, a
+ default name will be provided based on the name of the object's
+ kind, optionally with a number suffix if more than one instance
+ exists in the owner.
+ */
name: "",
+ /**
+ A unique id for the component, usually automatically generated based
+ on its position within the component hierarchy, although it may also
+ be directly specified. _enyo.Control_ uses this id value for the DOM
+ id attribute.
+ */
id: "",
+ /**
+ The component that owns this component. It is usually implicitly
+ defined during creation based on the _createComponent_ call or
+ _components_ hash.
+ */
owner: null
},
//* @protected
@@ -103,9 +121,9 @@ enyo.kind({
},
//* @public
/**
- 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
+ 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
being destroyed, unless user code keeps a reference to it.
*/
destroy: function() {
@@ -130,6 +148,7 @@ enyo.kind({
}
});
},
+ //* @protected
makeId: function() {
var delim = "_", pre = this.owner && this.owner.getId();
return this.name ? (pre ? pre + delim : "") + this.name : "";
@@ -159,6 +178,11 @@ 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.$_).
+ */
addComponent: function(inComponent) {
var n = inComponent.getName();
if (!n) {
@@ -180,12 +204,14 @@ enyo.kind({
}
this.$[n] = inComponent;
},
+ //* Removes _inComponent_ from the list of components owned by the current
+ //* component (i.e., _this.$_).
removeComponent: function(inComponent) {
delete this.$[inComponent.getName()];
},
//* @public
/**
- Returns an Array of owned components. In other words, converts the _$_
+ Returns an array of owned components; in other words, converts the _$_
hash into an array and returns the array.
*/
getComponents: function() {
@@ -204,6 +230,9 @@ enyo.kind({
inProps.owner = inProps.owner || this;
},
_createComponent: function(inInfo, inMoreInfo) {
+ if (!inInfo.kind && ("kind" in inInfo)) {
+ throw "enyo.create: Attempt to create a null kind. Check dependencies for [" + inInfo.name + "].";
+ }
// CAVEAT: inInfo and inMoreInfo are copied before mutation, but it's only a shallow copy
var props = enyo.mixin(enyo.clone(inMoreInfo), inInfo);
this.adjustComponentProps(props);
@@ -211,13 +240,14 @@ enyo.kind({
},
//* @public
/**
- Creates and returns a Component as defined by the combination of
- _inInfo_ and _inMoreInfo_.
- The created Component passes through initialization machinery provided
+ 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 _this_.
- Properties in _inInfo_ override properties in _inMoreInfo_.
+ 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_
// (will be available as this.$.dynamic).
@@ -233,8 +263,8 @@ enyo.kind({
return this._createComponent(inInfo, inMoreInfo);
},
/**
- Creates Components as defined by the array of configurations _inInfo_.
- Each configuration in _inInfo_ is combined with _inCommonInfo_ as
+ Creates Components as defined by the array of configurations _inInfos_.
+ Each configuration in _inInfos_ is combined with _inCommonInfo_ as
described in _createComponent_.
_createComponents_ returns an array of references to the created components.
@@ -287,14 +317,6 @@ enyo.kind({
}
return this.dispatchBubble(inEventName, e, inSender);
},
- dispatchBubble: function(inEventName, inEvent, inSender) {
- // Try to dispatch from here, stop bubbling on truthy return value
- if (this.dispatchEvent(inEventName, inEvent, inSender)) {
- return true;
- }
- // Bubble to next target
- return this.bubbleUp(inEventName, inEvent, inSender);
- },
/**
Bubbles an event up an object chain, starting <b>above</b> _this_.
@@ -322,16 +344,17 @@ enyo.kind({
},
//* @protected
/**
- Dispatch refers to sending an event to a named delegate.
+ Dispatching refers to sending an event to a named delegate.
This object may dispatch an event to itself via a handler,
- or to it's owner ia an event property.
- e.g.
+ or to its owner via an event property, e.g.:
+
handlers {
// 'tap' events dispatched to this.tapHandler
ontap: "tapHandler"
}
- // 'tap' dispatched to 'tapHandler' delegate in this.owner
- ontap: "tapHandler",
+
+ // 'tap' events dispatched to 'tapHandler' delegate in this.owner
+ ontap: "tapHandler"
*/
dispatchEvent: function(inEventName, inEvent, inSender) {
// bottleneck event decoration
@@ -353,6 +376,15 @@ enyo.kind({
return this.bubbleDelegation(this.owner, this[inEventName], inEventName, inEvent, this);
}
},
+ // internal - try dispatching event to self, if that fails bubble it up the tree
+ dispatchBubble: function(inEventName, inEvent, inSender) {
+ // Try to dispatch from here, stop bubbling on truthy return value
+ if (this.dispatchEvent(inEventName, inEvent, inSender)) {
+ return true;
+ }
+ // Bubble to next target
+ return this.bubbleUp(inEventName, inEvent, inSender);
+ },
decorateEvent: function(inEventName, inEvent, inSender) {
// an event may float by us as part of a dispatchEvent chain or delegateEvent
// both call this method so intermediaries can decorate inEvent
@@ -375,11 +407,11 @@ enyo.kind({
return this.bubbleDelegation(inDelegate, inName, inEventName, inEvent, inSender);
},
/**
- Dispatch the event to named delegate inMethodName, if it exists.
- Sub-kinds may re-route dispatches.
+ 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
- need to also override dispatchEvent.
+ need to also override _dispatchEvent_.
*/
dispatch: function(inMethodName, inEvent, inSender) {
var fn = inMethodName && this[inMethodName];
@@ -413,7 +445,7 @@ enyo.defaultCtor = enyo.Component;
enyo.create = enyo.Component.create = function(inConfig) {
if (!inConfig.kind && ("kind" in inConfig)) {
- throw "enyo.create: Attempt to create a null kind. Check dependencies.";
+ throw "enyo.create: Attempt to create a null kind. Check dependencies for [" + (inConfig.name || "") + "].";
}
var kind = inConfig.kind || inConfig.isa || enyo.defaultCtor;
var ctor = enyo.constructorForKind(kind);
View
2  source/kernel/Layout.js
@@ -1,5 +1,5 @@
/**
- The base kind for layout kinds. These are used by
+ _enyo.Layout_ is the base kind for layout kinds. These are used by
<a href="#enyo.UiComponent">enyo.UiComponent</a>-based controls to allow for
arranging of the children by setting the _layoutKind_ property.
View
5 source/kernel/Object.js
@@ -22,7 +22,7 @@ enyo.kind({
},
/**
Sets property named 'n' with value 'v' and then invokes callback
- function 'cf' (if specified) with the original value of property 'n'.
+ function 'cf' (if specified), passing in the original value of 'n'.
All property setting should bottleneck here so that objects can
observe changes wlog.
*/
@@ -39,12 +39,14 @@ enyo.kind({
this.setPropertyValue(n, v, (this.getProperty(n) !== v) && cf);
},
//* @public
+ //* Destroys object with passed-in name.
destroyObject: function(inName) {
if (this[inName] && this[inName].destroy) {
this[inName].destroy();
}
this[inName] = null;
},
+ //* Gets value of property with passed-in name.
getProperty: function(n) {
var getter = "get" + enyo.cap(n);
if (this[getter]) {
@@ -52,6 +54,7 @@ enyo.kind({
}
return this[n];
},
+ //* Sets value of property named 'n' to 'v'.
setProperty: function(n, v) {
var setter = "set" + enyo.cap(n);
if (this[setter]) {
View
38 source/kernel/Oop.js
@@ -27,9 +27,10 @@ enyo.kind = function(inProps) {
// establish base class reference
var base = enyo.constructorForKind(kind);
var isa = base && base.prototype || null;
- // if we have an explicit kind property with value undefined, we probably tried to reference a kind that is not yet in scope
- if (hasKind && (kind !== null) && (base == null)) {
- throw "enyo.kind: Attempt to subclass an undefined kind. Check dependencies for [" + name + "].";
+ // if we have an explicit kind property with value undefined, we probably
+ // tried to reference a kind that is not yet in scope
+ if (hasKind && kind === undefined || base === undefined) {
+ throw "enyo.kind: Attempt to subclass an undefined kind. Check dependencies for [" + (name || "<unnamed>") + "].";
}
// make a boilerplate constructor
var ctor = enyo.kind.makeCtor();
@@ -56,9 +57,40 @@ enyo.kind = function(inProps) {
return ctor;
};
+/**
+ Creates a Singleton
+
+ enyo.singleton({
+ kind: Control,
+ name: "app.MySingleton",
+ published: {
+ value: "foo"
+ },
+ makeSomething: function() {
+ //...
+ }
+ });
+
+ app.MySingleton.makeSomething();
+ app.MySingleton.setValue("bar");
+*/
+enyo.singleton = function(conf, context) {
+ // extract 'name' property (the name of our singleton)
+ var name = conf.name;
+ delete(conf.name);
+ // create an unnamed kind and save its constructor's function
+ var kind = enyo.kind(conf);
+ // create the singleton with the previous name and constructor
+ enyo.setObject(name, new kind(), context);
+};
+
//* @protected
enyo.kind.makeCtor = function() {
return function() {
+ if (!(this instanceof arguments.callee)) {
+ throw "enyo.kind: constructor called directly, not using 'new'";
+ }
+
// two-pass instantiation
var result;
if (this._constructor) {
View
3  source/kernel/Signals.js
@@ -1,5 +1,5 @@
/**
- _Signals_ components are used to listen to global messages.
+ _enyo.Signals_ components are used to listen to global messages.
An object with a Signals component can listen to messages sent from anywhere
by declaring handlers for them.
@@ -15,6 +15,7 @@
enyo.kind({
name: "enyo.Signals",
kind: enyo.Component,
+ //* @protected
create: function() {
this.inherited(arguments);
enyo.Signals.addListener(this);
View
28 source/kernel/UiComponent.js
@@ -23,6 +23,7 @@ enyo.kind({
handlers: {
onresize: "resizeHandler"
},
+ //* @protected
statics: {
_resizeFlags: {showingOnly: true} // don't waterfall these events into hidden controls
},
@@ -120,7 +121,7 @@ enyo.kind({
*/
getClientControls: function() {
var results = [];
- for (var i=0, cs=this.controls, c; c=cs[i]; i++) {
+ for (var i=0, cs=this.controls, c; (c=cs[i]); i++) {
if (!c.isChrome) {
results.push(c);
}
@@ -133,18 +134,18 @@ enyo.kind({
*/
destroyClientControls: function() {
var c$ = this.getClientControls();
- for (var i=0, c; c=c$[i]; i++) {
+ for (var i=0, c; (c=c$[i]); i++) {
c.destroy();
}
},
//* @protected
- addControl: function(inControl) {
+ addControl: function(inControl, inBefore) {
// Called to add an already created control to the object's control list. It is
// not used to create controls and should likely not be called directly.
// It can be overridden to detect when controls are added.
this.controls.push(inControl);
// When we add a Control, we also establish a parent.
- this.addChild(inControl);
+ this.addChild(inControl, inBefore);
},
removeControl: function(inControl) {
// Called to remove a control from the object's control list. As with addControl it
@@ -169,10 +170,15 @@ enyo.kind({
return this.controls[inIndex];
},
// children
- addChild: function(inChild) {
+ addChild: function(inChild, inBefore) {
+ // if inBefore is undefined, use the old behavior of adding to front
+ // or end of children based in this.prepend property. if it's null,
+ // add to end, otherwise add before the specified control.
+ //
// allow delegating the child to a different container
if (this.controlParent /*&& !inChild.isChrome*/) {
// this.controlParent might have a controlParent, and so on; seek the ultimate parent
+ // inBefore is not passed because that control won't be in the controlParent's scope
this.controlParent.addChild(inChild);
} else {
// NOTE: addChild drives setParent.
@@ -186,7 +192,15 @@ enyo.kind({
// Set the child's parent property to this
inChild.setParent(this);
// track in children array
- this.children[this.prepend ? "unshift" : "push"](inChild);
+ if (inBefore === undefined) {
+ this.children[this.prepend ? "unshift" : "push"](inChild);
+ } else if (inBefore === null) {
+ // this case is needed to allow adding to end when this.prepend is true
+ this.children.push(inChild);
+ } else {
+ var idx = this.indexOfChild(inBefore);
+ this.children.splice(idx, 0, inChild);
+ }
/*
// FIXME: hacky, allows us to reparent a rendered control; we need better API for dynamic reparenting
if (inChild.hasNode()) {
@@ -257,7 +271,7 @@ enyo.kind({
}
}
// waterfall to my children
- for (var i=0, cs=this.children, c; c=cs[i]; i++) {
+ for (var i=0, cs=this.children, c; (c=cs[i]); i++) {
// Do not send {showingOnly: true} events to hidden controls. This flag is set for resize events
// which are broadcast from within the framework. This saves a *lot* of unnecessary layout.
// TODO: Maybe remember that we did this, and re-send those messages on setShowing(true)?
View
31 source/touch/ScrollMath.js
@@ -9,25 +9,30 @@ enyo.kind({
name: "enyo.ScrollMath",
kind: enyo.Component,
published: {
+ //* True if vertical scrolling is enabled
vertical: true,
+ //* True if horizontal scrolling is enabled
horizontal: true
},
events: {
+ //* Fires when scroll action starts.
onScrollStart: "",
+ //* Fires while scroll action is in progress.
onScroll: "",
+ //* Fires when scroll action stops.
onScrollStop: ""
},
- //* 'spring' damping returns the scroll position to a value inside the
- //* boundaries. Lower values provide FASTER snapback.
+ //* 'Spring' damping returns the scroll position to a value inside the
+ //* boundaries. Lower values provide _faster_ snapback.
kSpringDamping: 0.93,
- //* 'drag' damping resists dragging the scroll position beyond the
- //* boundaries. Lower values provide MORE resistance.
+ //* 'Drag' damping resists dragging the scroll position beyond the
+ //* boundaries. Lower values provide _more_ resistance.
kDragDamping: 0.5,
- //* 'friction' damping reduces momentum over time. Lower values provide
- //* MORE friction.
+ //* 'Friction' damping reduces momentum over time. Lower values provide
+ //* _more_ friction.
kFrictionDamping: 0.97,
//* Additional 'friction' damping applied when momentum carries the viewport
- //* into overscroll. Lower values provide MORE friction.
+ //* into overscroll. Lower values provide _more_ friction.
kSnapFriction: 0.9,
//* Scalar applied to 'flick' event velocity
kFlickScalar: 15,
@@ -35,19 +40,19 @@ enyo.kind({
//* prevent compositing artifacts.
kMaxFlick: enyo.platform.android > 2 ? 2 : 1e9,
//* The value used in friction() to determine if the delta (e.g., y - y0) is
- //* close enough to zero to consider as zero.
+ //* close enough to zero to consider as zero
kFrictionEpsilon: 1e-2,
- //* Top snap boundary, generally 0.
+ //* Top snap boundary, generally 0
topBoundary: 0,
- //* Right snap boundary, generally (viewport width - content width).
+ //* Right snap boundary, generally (viewport width - content width)
rightBoundary: 0,
- //* Bottom snap boundary, generally (viewport height - content height).
+ //* Bottom snap boundary, generally (viewport height - content height)
bottomBoundary: 0,
- //* Left snap boundary, generally 0.
+ //* Left snap boundary, generally 0
leftBoundary: 0,
//* Animation time step
interval: 20,
- //* Flag to enable frame-based animation; if false, time-based animation is used.
+ //* Flag to enable frame-based animation; if false, time-based animation is used
fixedTime: true,
//* @protected
// simulation state
View
11 source/touch/ScrollStrategy.js
@@ -1,7 +1,7 @@
/**
_enyo.ScrollStrategy_ is a helper kind that implements a default scrolling
strategy for an <a href="#enyo.Scroller">enyo.Scroller</a>.
-
+
_enyo.ScrollStrategy_ is not typically created in application code.
*/
enyo.kind({
@@ -10,7 +10,7 @@ enyo.kind({
published: {
/**
Specifies how to vertically scroll. Acceptable values are:
-
+
* "scroll": Always shows a scrollbar; sets _overflow: scroll_.
* "auto": Scrolls only if needed; sets _overflow: auto_.
* "hidden": Never scrolls; sets _overflow: hidden_.
@@ -26,8 +26,11 @@ enyo.kind({
* "default": Same as "auto".
*/
horizontal: "default",
+ //* Scroll position along horizontal axis
scrollLeft: 0,
+ //* Scroll position along vertical axis
scrollTop: 0,
+ //* Maximum height of scroll content
maxHeight: null
},
//* @protected
@@ -42,10 +45,10 @@ enyo.kind({
this.horizontalChanged();
this.verticalChanged();
this.maxHeightChanged();
- this.container.setAttribute("onscroll", enyo.bubbler);
},
rendered: function() {
this.inherited(arguments);
+ enyo.makeBubble(this.container, "scroll");
this.scrollNode = this.calcScrollNode();
},
teardownRender: function() {
@@ -170,7 +173,7 @@ enyo.kind({
down: function(inSender, inEvent) {
this.calcStartInfo();
},
- // NOTE: mobile native scrollers need touchmove. Indicate this by
+ // NOTE: mobile native scrollers need touchmove. Indicate this by
// setting the requireTouchmove property to true.
move: function(inSender, inEvent) {
if (inEvent.which && (this.canVertical && inEvent.vertical || this.canHorizontal && inEvent.horizontal)) {
View
71 source/touch/Scroller.js
@@ -24,27 +24,28 @@ enyo.kind({
*/
vertical: "default",
/**
- Sets the vertical scroll position.
+ The vertical scroll position
*/
scrollTop: 0,
/**
- Sets the horizontal scroll position.
+ The horizontal scroll position
*/
scrollLeft: 0,
/**
- Sets the maximum height of the scroll content.
+ Maximum height of the scroll content
*/
maxHeight: null,
/**
Set to true to make this scroller select a platform-appropriate
- touch-based scrolling strategy. Please note that specifycing a
- scrollStrategy will take precedence over this setting.
+ touch-based scrolling strategy. Note that if you specify a value for
+ _strategyKind_, that will take precedence over this setting.
*/
touch: false,
/**
- Specifies a type of scrolling. The Enyo Scroller will attempt to
+ Specifies a type of scrolling. The scroller will attempt to
automatically select a strategy compatible with the runtime
- environment. A specific strategy may also be chosen:
+ environment. Alternatively, you may choose to use a specific
+ strategy:
* <a href="#enyo.ScrollStrategy">ScrollStrategy</a> is the default
and implements no scrolling, relying instead on the environment
@@ -58,12 +59,15 @@ enyo.kind({
currently recommended only for Android 3 and 4.
*/
strategyKind: "ScrollStrategy",
- //* Set to true to display a scroll thumb in Touch scrollers.
+ //* Set to true to display a scroll thumb in touch scrollers
thumb: true
},
events: {
+ //* Fires when a scrolling action starts.
onScrollStart: "",
+ //* Fires while a scrolling action is in progress.
onScroll: "",
+ //* Fires when a scrolling action stops.
onScrollStop: ""
},
handlers: {
@@ -74,16 +78,17 @@ enyo.kind({
},
classes: "enyo-scroller",
/**
- If true and a touch scroller, the scroller will overscroll and bounce back at the edges (Defaults to true.)
+ If true (the default) and a touch scroller, the scroller will overscroll
+ and bounce back at the edges
*/
touchOverscroll: true,
/**
- If true, the scroller will not propagate _dragstart_ events that cause
- it to start scrolling. (Defaults to true.)
+ If true (the default), the scroller will not propagate _dragstart_
+ events that cause it to start scrolling
*/
preventDragPropagation: true,
/**
- If true, the scroller will not propagate scroll events.
+ If true, the scroller will not propagate scroll events
*/
preventScrollPropagation: true,
//* @protected
@@ -101,7 +106,10 @@ enyo.kind({
}
}
},
- //* Returns true if the platform has native div scrollers (desktop browsers always have them).
+ /**
+ Returns true if the platform has native div scrollers (desktop
+ browsers always have them).
+ */
hasNativeScrolling: function() {
for (var i=0, t, m; t=this.osInfo[i]; i++) {
if (enyo.platform[t.os] < t.version) {
@@ -192,26 +200,36 @@ enyo.kind({
},
// FIXME: these properties are virtual; property changed methods are fired only if
// property value changes, not if getter changes.
+ //* Sets scroll position along horizontal axis.
setScrollLeft: function(inLeft) {
this.scrollLeft = inLeft;
this.$.strategy.setScrollLeft(this.scrollLeft);
},
+ //* Sets scroll position along vertical axis.
setScrollTop: function(inTop) {
this.scrollTop = inTop;
this.$.strategy.setScrollTop(inTop);
},
+ //* Gets scroll position along horizontal axis.
getScrollLeft: function() {
return this.$.strategy.getScrollLeft();
},
+ //* Gets scroll position along vertical axis.
getScrollTop: function() {
return this.$.strategy.getScrollTop();
},
//* @public
- //* Returns an object describing the scroll boundaries with height and width properties.
+ /**
+ Returns an object describing the scroll boundaries with _height_ and
+ _width_ properties.
+ */
getScrollBounds: function() {
return this.$.strategy.getScrollBounds();
},
- //* Scrolls the given control (_inControl_) into view. If _inAlignWithTop_ is true, _inControl_ is aligned with the top of the scroller.
+ /**
+ Scrolls the given control (_inControl_) into view. If _inAlignWithTop_
+ is true, _inControl_ is aligned with the top of the scroller.
+ */
scrollIntoView: function(inControl, inAlignWithTop) {
this.$.strategy.scrollIntoView(inControl, inAlignWithTop);
},
@@ -219,15 +237,19 @@ enyo.kind({
scrollTo: function(inX, inY) {
this.$.strategy.scrollTo(inX, inY);
},
- //* Ensures that the given control is visible in the scroller's viewport. Unlike _scrollIntoView_, which uses DOM's _scrollIntoView_, this only affects the current scroller.
+ /**
+ Ensures that the given control is visible in the scroller's viewport.
+ Unlike _scrollIntoView_, which uses DOM's _scrollIntoView_, this only
+ affects the current scroller.
+ */
scrollToControl: function(inControl, inAlignWithTop) {
this.scrollToNode(inControl.hasNode(), inAlignWithTop);
},
- // Ensures that the given node is visible in the scroller's viewport.
+ //* Ensures that the given node is visible in the scroller's viewport.
scrollToNode: function(inNode, inAlignWithTop) {
this.$.strategy.scrollToNode(inNode, inAlignWithTop);
},
- // Normalizes scroll event to onScroll.
+ //* Normalizes scroll event to _onScroll_.
domScroll: function(inSender, e) {
// if a scroll event originated here, pass it to our strategy to handle
if (this.$.strategy.domScroll && e.originator == this) {
@@ -236,12 +258,21 @@ enyo.kind({
this.doScroll(e);
return true;
},
+ /**
+ Returns true if the current scroll event should be stopped; false if it
+ should be allowed to propagate.
+ */
shouldStopScrollEvent: function(inEvent) {
return (this.preventScrollPropagation && inEvent.originator.owner != this.$.strategy);
},
+ /**
+ Calls _shouldStopScrollEvent_ to determine whether current scroll event
+ should be stopped.
+ */
scrollStart: function(inSender, inEvent) {
return this.shouldStopScrollEvent(inEvent);
},
+ //* Either propagates or stops the current scroll event.
scroll: function(inSender, inEvent) {
// note: scroll event can be native dom or generated.
if (inEvent.dispatchTarget) {