Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Add progress and loading attributes; includes docs, demo, and test.
Browse files Browse the repository at this point in the history
  • Loading branch information
rictic committed Sep 18, 2014
1 parent 5e0d9f8 commit 76bde89
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 4 deletions.
57 changes: 53 additions & 4 deletions core-ajax.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
@homepage github.io
-->
<link rel="import" href="core-xhr.html">
<polymer-element name="core-ajax" hidden attributes="url handleAs auto params response error method headers body contentType withCredentials">
<polymer-element name="core-ajax" hidden attributes="url handleAs auto params response error method headers body contentType withCredentials progress loading">
<script>

Polymer('core-ajax', {
Expand Down Expand Up @@ -106,7 +106,7 @@
params: '',

/**
* The response for the most recently made request, or null if it hasn't
* The response for the current request, or null if it hasn't
* completed yet or the request resulted in error.
*
* @attribute response
Expand All @@ -116,7 +116,7 @@
response: null,

/**
* The error for the most recently made request, or null if it hasn't
* The error for the current request, or null if it hasn't
* completed yet or the request resulted in success.
*
* @attribute error
Expand All @@ -125,6 +125,24 @@
*/
error: null,

/**
* Whether the current request is currently loading.
*
* @attribute loading
* @type boolean
* @default false
*/
loading: false,

/**
* The progress of the current request.
*
* @attribute progress
* @type {loaded: number, total: number, lengthComputable: boolean}
* @default {}
*/
progress: {},

/**
* The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'.
* Default is 'GET'.
Expand Down Expand Up @@ -233,7 +251,22 @@
this.fire('core-error', {response: response, xhr: xhr});
},

processProgress: function(progress, xhr) {
if (xhr !== this.activeRequest) {
return;
}
var progressProxy = {
lengthComputable: progress.lengthComputable,
loaded: progress.loaded,
total: progress.total
}
this.progress = progressProxy;
},

complete: function(xhr) {
if (xhr === this.activeRequest) {
this.loading = false;
}
this.fire('core-complete', {response: xhr.status, xhr: xhr});
},

Expand Down Expand Up @@ -334,8 +367,24 @@
args.url = this.url;
args.method = this.method;

this.response = this.error = null;
this.response = this.error = this.progress = null;
this.activeRequest = args.url && this.xhr.request(args);
if (this.activeRequest) {
this.loading = true;
var activeRequest = this.activeRequest;
// IE < 10 doesn't support progress events.
if ('onprogress' in activeRequest) {
this.activeRequest.addEventListener(
'progress',
function(progress) {
this.processProgress(progress, activeRequest);
}.bind(this), false);
} else {
this.progress = {
lengthComputable: false,
}
}
}
return this.activeRequest;
}

Expand Down
63 changes: 63 additions & 0 deletions demo-progress.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html>
<head>
<script src="../platform/platform.js" debug></script>
<meta charset="utf-8">
<title>Race condition</title>
</head>
<body>
<link rel="import" href="core-ajax.html">
<link rel="import" href="../paper-progress/paper-progress.html">
<polymer-element name="progress-test">
<template>
<core-ajax
id='ajax' auto
url="http://httpbin.org/drip"
params="{{ {numbytes: numbytes, duration:5} }}"
response="{{response}}"
progress="{{progress}}"
loading="{{loading}}"
></core-ajax>

<!--
Ordinarily you'd gate on progress.lengthComputable, but we know the
length in this case (and httpbin sadly doesn't return a
Content-Length header for this requesthere).
-->
<div>
<button on-click='{{restart}}'>Restart</button>
<template if='{{loading}}'>
Loading...
</template>
<template if='{{!loading}}'>
Loaded!
</template>
</div>
<template if='{{loading && progress.loaded}}'>
<paper-progress
value="{{progress.loaded}}"
min="0"
max="{{numbytes}}">
</paper-progress><br>
</template>
</template>
<script>
Polymer('progress-test', {
loading: true,
i: 0,
numbytes: 1000,
pretty: function(i) {
return JSON.stringify(i, null, 2);
},
restart: function() {
this.$.ajax.abort();
this.$.ajax.go();
}
});
</script>

</polymer-element>

<progress-test></progress-test>
</body>
</html>
100 changes: 100 additions & 0 deletions tests/html/core-ajax-progress-and-loading.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<!doctype html>
<!--
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<title>core-ajax-response-and-error</title>

<script src="../../../platform/platform.js"></script>
<script src="../../../polymer-test-tools/chai/chai.js"></script>
<script src="../../../polymer-test-tools/htmltest.js"></script>

<link rel="import" href="../../core-ajax.html">

</head>
<body>

<polymer-element name="race-condition">
<template>
<!-- TODO: change this from /headers to /drip if we can get httpbin to
send a Content-Length with their /drip response. -->
<core-ajax
auto url="http://httpbin.org/headers"
params="{{ {numbytes: numbytes, duration:1} }}"
loading="{{loading}}" progress="{{progress}}"
on-core-response='{{responseReceived}}'></core-ajax>
</template>
<script>
Polymer({
numbytes: 1000,
loading: null,
loadingWasTrue: false,
loadingFinished: false,
previousLoaded: null,
domReady: function() {
// This will fail the test if it neither passes nor fails in time.
this.finalTimeout = setTimeout(function() {
chai.assert.fail('', '', 'Test timed out.');
}, 3000);
},
loadingChanged: function() {
this.assertConsistent();
},
progressChanged: function() {
this.assertConsistent();
},
responseReceived: function() {
// Shortly after the response is received we should settle into
// the final consistent state for the element.
setTimeout(function() {
chai.assert.equal(this.loading, false);
chai.assert.equal(this.loadingWasTrue, true);
if (this.progress && this.progress.lengthComputable) {
chai.assert.equal(this.progress.total, this.progress.loaded);
}
this.assertConsistent();
clearTimeout(this.finalTimeout);
done();
}.bind(this), 100);
},
assertConsistent: function() {
debugger;
if (this.progress && this.progress.lengthComputable) {
chai.assert.isNumber(this.progress.total);
chai.assert.isNumber(this.progress.loaded);
chai.assert(this.progress.loaded >= 0,
'Bytes loaded should not be negative.');
chai.assert(this.progress.loaded <= this.progress.total,
'Bytes loaded should be less than or equal the total.');
if (this.previousLoaded !== null) {
chai.assert(this.progress.loaded >= this.previousLoaded,
'Bytes loaded should increase monotonically.');
}
this.previousLoaded = this.progress.loaded;
console.log(this.progress.loaded + ' of ' + this.progress.total);
}
if (this.loading === true) {
this.loadingWasTrue = true;
}
if (this.loadingWasTrue && this.loading === false) {
this.loadingFinished = true;
}
if (this.loadingFinished) {
chai.assert.equal(
this.loading, false,
'Once loaded, the request should stay that way');
}
}
});
</script>
</polymer-element>

<race-condition></race-condition>
</body>
</html>
1 change: 1 addition & 0 deletions tests/js/htmltests.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
htmlSuite('core-ajax', function() {
htmlTest('html/core-ajax.html');
htmlTest('html/core-ajax-response-and-error.html');
htmlTest('html/core-ajax-progress-and-loading.html');
});

0 comments on commit 76bde89

Please sign in to comment.