1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

use shared image loader

This commit is contained in:
Luke Pulverenti 2016-01-16 13:29:08 -05:00
parent 08d07100ef
commit 000727d782
17 changed files with 570 additions and 347 deletions

View file

@ -16,12 +16,12 @@
},
"devDependencies": {},
"ignore": [],
"version": "1.0.25",
"_release": "1.0.25",
"version": "1.0.26",
"_release": "1.0.26",
"_resolution": {
"type": "version",
"tag": "1.0.25",
"commit": "f2e83b0e30527b5182ceb043d170ad7188368245"
"tag": "1.0.26",
"commit": "6fe8727397b13e87e3afaeee600f600269e0ee18"
},
"_source": "git://github.com/MediaBrowser/Emby.ApiClient.Javascript.git",
"_target": "~1.0.3",

View file

@ -748,16 +748,13 @@
console.log('Begin getConnectServers');
return new Promise(function (resolve, reject) {
if (!credentials.ConnectAccessToken || !credentials.ConnectUserId) {
resolve([]);
return;
return Promise.resolve([]);
}
var url = "https://connect.emby.media/service/servers?userId=" + credentials.ConnectUserId;
ajax({
return ajax({
type: "GET",
url: url,
dataType: "json",
@ -768,7 +765,7 @@
}).then(function (servers) {
servers = servers.map(function (i) {
return servers.map(function (i) {
return {
ExchangeToken: i.AccessKey,
ConnectServerId: i.Id,
@ -780,13 +777,10 @@
};
});
resolve(servers);
}, function () {
resolve([]);
return [];
});
});
}
self.getSavedServers = function () {
@ -858,9 +852,8 @@
var info = {
Id: foundServer.Id,
LocalAddress: foundServer.Address,
LocalAddress: convertEndpointAddressToManualAddress(foundServer) || foundServer.Address,
Name: foundServer.Name,
ManualAddress: convertEndpointAddressToManualAddress(foundServer),
DateLastLocalConnection: new Date().getTime()
};
@ -1467,14 +1460,11 @@
self.getRegistrationInfo = function (feature, apiClient) {
if (isConnectUserSupporter()) {
return new Promise(function (resolve, reject) {
resolve({
return Promise.resolve({
Name: feature,
IsRegistered: true,
IsTrial: false
});
});
}
return self.getAvailableServers().then(function (servers) {

View file

@ -15,12 +15,12 @@
},
"devDependencies": {},
"ignore": [],
"version": "1.0.18",
"_release": "1.0.18",
"version": "1.0.20",
"_release": "1.0.20",
"_resolution": {
"type": "version",
"tag": "1.0.18",
"commit": "a251227c4635bcac732075e494b2d8a4e7956d26"
"tag": "1.0.20",
"commit": "b88c3533403d7fc921adb381c81917c80d9c4e77"
},
"_source": "git://github.com/MediaBrowser/emby-webcomponents.git",
"_target": "~1.0.0",

View file

@ -0,0 +1,25 @@
define([], function () {
function loadImage(elem, url) {
if (elem.tagName !== "IMG") {
var tmp = new Image();
tmp.onload = function () {
elem.style.backgroundImage = "url('" + url + "')";
};
tmp.src = url;
} else {
elem.setAttribute("src", url);
}
return Promise.resolve(elem);
}
return {
loadImage: loadImage
};
});

View file

@ -0,0 +1,175 @@
define(['visibleinviewport', 'imageloader'], function (visibleinviewport, imageLoader) {
var thresholdX = screen.availWidth;
var thresholdY = screen.availHeight;
var wheelEvent = (document.implementation.hasFeature('Event.wheel', '3.0') ? 'wheel' : 'mousewheel');
function isVisible(elem) {
return visibleinviewport(elem, true, thresholdX, thresholdY);
}
function fillImage(elem) {
var source = elem.getAttribute('data-src');
if (source) {
imageLoader.loadImage(elem, source);
elem.setAttribute("data-src", '');
}
}
function cancelAll(tokens) {
for (var i = 0, length = tokens.length; i < length; i++) {
tokens[i] = true;
}
}
function unveilElements(images) {
if (!images.length) {
return;
}
var cancellationTokens = [];
function unveilInternal(tokenIndex) {
var remaining = [];
var anyFound = false;
var out = false;
// TODO: This out construct assumes left to right, top to bottom
for (var i = 0, length = images.length; i < length; i++) {
if (cancellationTokens[tokenIndex]) {
return;
}
var img = images[i];
if (!out && isVisible(img)) {
anyFound = true;
fillImage(img);
} else {
if (anyFound) {
out = true;
}
remaining.push(img);
}
}
images = remaining;
if (!images.length) {
document.removeEventListener('focus', unveil, true);
document.removeEventListener('scroll', unveil, true);
document.removeEventListener(wheelEvent, unveil, true);
window.removeEventListener('resize', unveil, true);
}
}
function unveil() {
cancelAll(cancellationTokens);
var index = cancellationTokens.length;
cancellationTokens.length++;
setTimeout(function () {
unveilInternal(index);
}, 1);
}
document.addEventListener('scroll', unveil, true);
document.addEventListener('focus', unveil, true);
document.addEventListener(wheelEvent, unveil, true);
window.addEventListener('resize', unveil, true);
unveil();
}
function fillImages(elems) {
for (var i = 0, length = elems.length; i < length; i++) {
var elem = elems[0];
var source = elem.getAttribute('data-src');
if (source) {
ImageStore.setImageInto(elem, source);
elem.setAttribute("data-src", '');
}
}
}
function lazyChildren(elem) {
unveilElements(elem.getElementsByClassName('lazy'));
}
function lazyImage(elem, url) {
elem.setAttribute('data-src', url);
fillImages([elem]);
}
function getPrimaryImageAspectRatio(items) {
var values = [];
for (var i = 0, length = items.length; i < length; i++) {
var ratio = items[i].PrimaryImageAspectRatio || 0;
if (!ratio) {
continue;
}
values[values.length] = ratio;
}
if (!values.length) {
return null;
}
// Use the median
values.sort(function (a, b) { return a - b; });
var half = Math.floor(values.length / 2);
var result;
if (values.length % 2)
result = values[half];
else
result = (values[half - 1] + values[half]) / 2.0;
// If really close to 2:3 (poster image), just return 2:3
var aspect2x3 = 2 / 3;
if (Math.abs(aspect2x3 - result) <= .15) {
return aspect2x3;
}
// If really close to 16:9 (episode image), just return 16:9
var aspect16x9 = 16 / 9;
if (Math.abs(aspect16x9 - result) <= .2) {
return aspect16x9;
}
// If really close to 1 (square image), just return 1
if (Math.abs(1 - result) <= .15) {
return 1;
}
// If really close to 4:3 (poster image), just return 2:3
var aspect4x3 = 4 / 3;
if (Math.abs(aspect4x3 - result) <= .15) {
return aspect4x3;
}
return result;
}
return {
lazyChildren: lazyChildren,
getPrimaryImageAspectRatio: getPrimaryImageAspectRatio
};
});

View file

@ -0,0 +1,164 @@
define(['cryptojs-md5'], function () {
function setImageIntoElement(elem, url) {
if (elem.tagName !== "IMG") {
elem.style.backgroundImage = "url('" + url + "')";
} else {
elem.setAttribute("src", url);
}
}
// Request Quota (only for File System API)
var requestedBytes = 1024 * 1024 * 1500;
var imageCacheDirectoryEntry;
var imageCacheFolder = 'images';
function createDir(rootDirEntry, folders, callback, errorCallback) {
// Throw out './' or '/' and move on to prevent something like '/foo/.//bar'.
if (folders[0] == '.' || folders[0] == '') {
folders = folders.slice(1);
}
rootDirEntry.getDirectory(folders[0], { create: true }, function (dirEntry) {
// Recursively add the new subfolder (if we still have another to create).
if (folders.length > 1) {
createDir(dirEntry, folders.slice(1), callback, errorCallback);
} else {
callback(dirEntry);
}
}, errorCallback);
}
navigator.webkitPersistentStorage.requestQuota(
requestedBytes, function (grantedBytes) {
var requestMethod = window.webkitRequestFileSystem || window.requestFileSystem;
requestMethod(PERSISTENT, grantedBytes, function (fs) {
fileSystem = fs;
createDir(fileSystem.root, imageCacheFolder.split('/'), function (dirEntry) {
imageCacheDirectoryEntry = dirEntry;
});
});
});
function getCacheKey(url) {
// Try to strip off the domain to share the cache between local and remote connections
var index = url.indexOf('://');
if (index != -1) {
url = url.substring(index + 3);
index = url.indexOf('/');
if (index != -1) {
url = url.substring(index + 1);
}
}
return CryptoJS.MD5(url).toString();
}
function downloadToFile(url, dir, filename, callback, errorCallback) {
console.log('Downloading ' + url);
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "arraybuffer";
xhr.onload = function (e) {
if (this.status == 200) {
writeData(dir, filename, this.getResponseHeader('Content-Type'), this.response, callback, errorCallback);
} else {
errorCallback();
}
}
xhr.send();
}
function writeData(dir, filename, fileType, data, callback, errorCallback) {
dir.getFile(filename, { create: true }, function (fileEntry) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function (e) {
callback(fileEntry);
};
fileWriter.onerror = errorCallback;
// Create a new Blob and write it to log.txt.
var blob = new Blob([data], { type: fileType });
fileWriter.write(blob);
}, errorCallback);
}, errorCallback);
}
function getImageUrl(originalUrl) {
return new Promise(function (resolve, reject) {
if (originalUrl.indexOf('tag=') != -1) {
originalUrl += "&accept=webp";
}
var key = getCacheKey(originalUrl);
var fileEntryCallback = function (fileEntry) {
resolve(fileEntry.toURL());
};
var errorCallback = function (e) {
console.log('Imagestore error: ' + e.name);
reject();
};
if (!fileSystem || !imageCacheDirectoryEntry) {
errorCallback('');
return;
}
var path = '/' + imageCacheFolder + "/" + key;
fileSystem.root.getFile(path, { create: false }, fileEntryCallback, function () {
downloadToFile(originalUrl, imageCacheDirectoryEntry, key, fileEntryCallback, errorCallback);
});
});
}
var fileSystem;
return {
loadImage: function (elem, url) {
return getImageUrl(url).then(function (localUrl) {
setImageIntoElement(elem, localUrl);
return elem;
}, function () {
setImageIntoElement(elem, url);
return elem;
});
}
};
});

View file

@ -29,14 +29,14 @@
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
},
"ignore": [],
"homepage": "https://github.com/polymerelements/iron-behaviors",
"homepage": "https://github.com/PolymerElements/iron-behaviors",
"_release": "1.0.12",
"_resolution": {
"type": "version",
"tag": "v1.0.12",
"commit": "657f526a2382a659cdf4e13be87ecc89261588a3"
},
"_source": "git://github.com/polymerelements/iron-behaviors.git",
"_source": "git://github.com/PolymerElements/iron-behaviors.git",
"_target": "^1.0.0",
"_originalSource": "polymerelements/iron-behaviors"
"_originalSource": "PolymerElements/iron-behaviors"
}

View file

@ -1,6 +1,6 @@
{
"name": "paper-input",
"version": "1.1.4",
"version": "1.1.5",
"description": "Material design text fields",
"authors": [
"The Polymer Authors"
@ -44,14 +44,14 @@
"iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0",
"paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0",
"test-fixture": "PolymerElements/test-fixture#^1.0.0",
"web-component-tester": "Polymer/web-component-tester#^3.4.0",
"web-component-tester": "^4.0.0",
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
},
"_release": "1.1.4",
"_release": "1.1.5",
"_resolution": {
"type": "version",
"tag": "v1.1.4",
"commit": "8ca01ac3cafc61abd980d262875ffca0c79640fa"
"tag": "v1.1.5",
"commit": "0aa8318b5e026688f94c78c7673acabf5bad0f17"
},
"_source": "git://github.com/polymerelements/paper-input.git",
"_target": "^1.0.9",

View file

@ -1,6 +1,6 @@
{
"name": "paper-input",
"version": "1.1.4",
"version": "1.1.5",
"description": "Material design text fields",
"authors": [
"The Polymer Authors"
@ -44,7 +44,7 @@
"iron-validator-behavior": "PolymerElements/iron-validator-behavior#^1.0.0",
"paper-icon-button": "PolymerElements/paper-icon-button#^1.0.0",
"test-fixture": "PolymerElements/test-fixture#^1.0.0",
"web-component-tester": "Polymer/web-component-tester#^3.4.0",
"web-component-tester": "^4.0.0",
"webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.0"
}
}

View file

@ -32,7 +32,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*/
/**
* The label for this input. Bind this to `<label>`'s content and `hidden` property, e.g.
* The label for this input. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to
* `<label>`'s content and `hidden` property, e.g.
* `<label hidden$="[[!label]]">[[label]]</label>` in your `template`
*/
label: {
@ -40,7 +42,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* The value for this input. Bind this to the `<input is="iron-input">`'s `bindValue`
* The value for this input. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to
* the `<input is="iron-input">`'s `bindValue`
* property, or the value property of your input that is `notify:true`.
*/
value: {
@ -49,8 +53,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Set to true to disable this input. Bind this to both the `<paper-input-container>`'s
* and the input's `disabled` property.
* Set to true to disable this input. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to
* both the `<paper-input-container>`'s and the input's `disabled` property.
*/
disabled: {
type: Boolean,
@ -58,8 +63,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Returns true if the value is invalid. Bind this to both the `<paper-input-container>`'s
* and the input's `invalid` property.
* Returns true if the value is invalid. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to both the
* `<paper-input-container>`'s and the input's `invalid` property.
*
* If `autoValidate` is true, the `invalid` attribute is managed automatically,
* which can clobber attempts to manage it manually.
@ -71,48 +77,55 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Set to true to prevent the user from entering invalid input. Bind this to the
* `<input is="iron-input">`'s `preventInvalidInput` property.
* Set to true to prevent the user from entering invalid input. If you're
* using PaperInputBehavior to implement your own paper-input-like element,
* bind this to `<input is="iron-input">`'s `preventInvalidInput` property.
*/
preventInvalidInput: {
type: Boolean
},
/**
* Set this to specify the pattern allowed by `preventInvalidInput`. Bind this to the
* `<input is="iron-input">`'s `allowedPattern` property.
* Set this to specify the pattern allowed by `preventInvalidInput`. If
* you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `allowedPattern`
* property.
*/
allowedPattern: {
type: String
},
/**
* The type of the input. The supported types are `text`, `number` and `password`. Bind this
* to the `<input is="iron-input">`'s `type` property.
* The type of the input. The supported types are `text`, `number` and `password`.
* If you're using PaperInputBehavior to implement your own paper-input-like element,
* bind this to the `<input is="iron-input">`'s `type` property.
*/
type: {
type: String
},
/**
* The datalist of the input (if any). This should match the id of an existing `<datalist>`. Bind this
* to the `<input is="iron-input">`'s `list` property.
* The datalist of the input (if any). This should match the id of an existing `<datalist>`.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `list` property.
*/
list: {
type: String
},
/**
* A pattern to validate the `input` with. Bind this to the `<input is="iron-input">`'s
* `pattern` property.
* A pattern to validate the `input` with. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to
* the `<input is="iron-input">`'s `pattern` property.
*/
pattern: {
type: String
},
/**
* Set to true to mark the input as required. Bind this to the `<input is="iron-input">`'s
* `required` property.
* Set to true to mark the input as required. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to
* the `<input is="iron-input">`'s `required` property.
*/
required: {
type: Boolean,
@ -120,8 +133,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* The error message to display when the input is invalid. Bind this to the
* `<paper-input-error>`'s content, if using.
* The error message to display when the input is invalid. If you're using
* PaperInputBehavior to implement your own paper-input-like element,
* bind this to the `<paper-input-error>`'s content, if using.
*/
errorMessage: {
type: String
@ -136,8 +150,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Set to true to disable the floating label. Bind this to the `<paper-input-container>`'s
* `noLabelFloat` property.
* Set to true to disable the floating label. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to
* the `<paper-input-container>`'s `noLabelFloat` property.
*/
noLabelFloat: {
type: Boolean,
@ -145,8 +160,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Set to true to always float the label. Bind this to the `<paper-input-container>`'s
* `alwaysFloatLabel` property.
* Set to true to always float the label. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to
* the `<paper-input-container>`'s `alwaysFloatLabel` property.
*/
alwaysFloatLabel: {
type: Boolean,
@ -154,8 +170,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Set to true to auto-validate the input value. Bind this to the `<paper-input-container>`'s
* `autoValidate` property.
* Set to true to auto-validate the input value. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to
* the `<paper-input-container>`'s `autoValidate` property.
*/
autoValidate: {
type: Boolean,
@ -163,8 +180,9 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Name of the validator to use. Bind this to the `<input is="iron-input">`'s `validator`
* property.
* Name of the validator to use. If you're using PaperInputBehavior to
* implement your own paper-input-like element, bind this to
* the `<input is="iron-input">`'s `validator` property.
*/
validator: {
type: String
@ -173,7 +191,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// HTMLInputElement attributes for binding if needed
/**
* Bind this to the `<input is="iron-input">`'s `autocomplete` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `autocomplete` property.
*/
autocomplete: {
type: String,
@ -181,29 +200,34 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Bind this to the `<input is="iron-input">`'s `autofocus` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `autofocus` property.
*/
autofocus: {
type: Boolean
},
/**
* Bind this to the `<input is="iron-input">`'s `inputmode` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `inputmode` property.
*/
inputmode: {
type: String
},
/**
* Bind this to the `<input is="iron-input">`'s `minlength` property.
* The minimum length of the input value.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `minlength` property.
*/
minlength: {
type: Number
},
/**
* The maximum length of the input value. Bind this to the `<input is="iron-input">`'s
* `maxlength` property.
* The maximum length of the input value.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `maxlength` property.
*/
maxlength: {
type: Number
@ -211,7 +235,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/**
* The minimum (numeric or date-time) input value.
* Bind this to the `<input is="iron-input">`'s `min` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `min` property.
*/
min: {
type: String
@ -220,7 +245,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/**
* The maximum (numeric or date-time) input value.
* Can be a String (e.g. `"2000-1-1"`) or a Number (e.g. `2`).
* Bind this to the `<input is="iron-input">`'s `max` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `max` property.
*/
max: {
type: String
@ -228,14 +254,16 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
/**
* Limits the numeric or date-time increments.
* Bind this to the `<input is="iron-input">`'s `step` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `step` property.
*/
step: {
type: String
},
/**
* Bind this to the `<input is="iron-input">`'s `name` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `name` property.
*/
name: {
type: String
@ -251,7 +279,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Bind this to the `<input is="iron-input">`'s `readonly` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `readonly` property.
*/
readonly: {
type: Boolean,
@ -259,7 +288,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Bind this to the `<input is="iron-input">`'s `size` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `size` property.
*/
size: {
type: Number
@ -268,7 +298,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// Nonstandard attributes for binding if needed
/**
* Bind this to the `<input is="iron-input">`'s `autocapitalize` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `autocapitalize` property.
*/
autocapitalize: {
type: String,
@ -276,7 +307,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Bind this to the `<input is="iron-input">`'s `autocorrect` property.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `autocorrect` property.
*/
autocorrect: {
type: String,
@ -284,28 +316,36 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
/**
* Bind this to the `<input is="iron-input">`'s `autosave` property, used with type=search.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `autosave` property,
* used with type=search.
*/
autosave: {
type: String
},
/**
* Bind this to the `<input is="iron-input">`'s `results` property, used with type=search.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `results` property,
* used with type=search.
*/
results: {
type: Number
},
/**
* Bind this to the `<input is="iron-input">`'s `accept` property, used with type=file.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the `<input is="iron-input">`'s `accept` property,
* used with type=file.
*/
accept: {
type: String
},
/**
* Bind this to the `<input is="iron-input">`'s `multiple` property, used with type=file.
* If you're using PaperInputBehavior to implement your own paper-input-like
* element, bind this to the`<input is="iron-input">`'s `multiple` property,
* used with type=file.
*/
multiple: {
type: Boolean
@ -354,8 +394,20 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return this.inputElement;
},
registered: function() {
// These types have some default placeholder text; overlapping
// the label on top of it looks terrible. Auto-float the label in this case.
this._typesThatHaveText = ["date", "datetime", "datetime-local", "month",
"time", "week", "file"];
},
attached: function() {
this._updateAriaLabelledBy();
if (this.inputElement &&
this._typesThatHaveText.indexOf(this.inputElement.type) !== -1) {
this.alwaysFloatLabel = true;
}
},
_appendStringWithSpace: function(str, more) {

View file

@ -39,9 +39,10 @@ for `suffix`).
</paper-input>
A `paper-input` can use the native `type=search` or `type=file` features.
However, since we can't control the native styling of the input, in these cases
it's recommended to use a placeholder text, or `always-float-label`,
as to not overlap the native UI (search icon, file button, etc.).
However, since we can't control the native styling of the input (search icon,
file button, date placeholder, etc.), in these cases the label will be
automatically floated. The `placeholder` attribute can still be used for
additional informational text.
<paper-input label="search!" type="search"
placeholder="search for cats" autosave="test" results="5">
@ -100,6 +101,7 @@ style this element.
aria-labelledby$="[[_ariaLabelledBy]]"
aria-describedby$="[[_ariaDescribedBy]]"
disabled$="[[disabled]]"
title$="[[title]]"
bind-value="{{value}}"
invalid="{{invalid}}"
prevent-invalid-input="[[preventInvalidInput]]"

View file

@ -70,7 +70,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</template>
</test-fixture>
<test-fixture id="required-char-counter">
<template>
<paper-input auto-validate char-counter required error-message="error"></paper-input>
@ -95,6 +94,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
</template>
</test-fixture>
<test-fixture id="date">
<template>
<paper-input label="foo" type="date"></paper-input>
</template>
</test-fixture>
<letters-only></letters-only>
<test-fixture id="validator">
@ -121,6 +126,18 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
assert.ok(floatingLabel);
});
test('special types autofloat the label', function() {
var input = fixture('date');
// Browsers that don't support special <input> types like `date` fallback
// to `text`, so make sure to only test if type is still preserved after
// the element is attached.
if (input.inputElement.type === "date") {
assert.equal(input.alwaysFloatLabel, true);
var floatingLabel = Polymer.dom(Polymer.dom(input.root).querySelector('paper-input-container').root).querySelector('.label-is-floating');
assert.ok(floatingLabel);
}
});
test('always-float-label attribute works without placeholder', function() {
var input = fixture('always-float-label');
var container = Polymer.dom(input.root).querySelector('paper-input-container');

View file

@ -32,14 +32,14 @@
"iron-test-helpers": "PolymerElements/iron-test-helpers#^1.0.0"
},
"ignore": [],
"homepage": "https://github.com/polymerelements/paper-ripple",
"homepage": "https://github.com/PolymerElements/paper-ripple",
"_release": "1.0.5",
"_resolution": {
"type": "version",
"tag": "v1.0.5",
"commit": "d72e7a9a8ab518b901ed18dde492df3b87a93be5"
},
"_source": "git://github.com/polymerelements/paper-ripple.git",
"_source": "git://github.com/PolymerElements/paper-ripple.git",
"_target": "^1.0.0",
"_originalSource": "polymerelements/paper-ripple"
"_originalSource": "PolymerElements/paper-ripple"
}

View file

@ -24,14 +24,14 @@
"web-component-tester": "*"
},
"private": true,
"homepage": "https://github.com/polymer/polymer",
"homepage": "https://github.com/Polymer/polymer",
"_release": "1.2.3",
"_resolution": {
"type": "version",
"tag": "v1.2.3",
"commit": "aa535d1675342007cbf64dc9c66497cf74cbc616"
},
"_source": "git://github.com/polymer/polymer.git",
"_source": "git://github.com/Polymer/polymer.git",
"_target": "^1.0.0",
"_originalSource": "polymer/polymer"
"_originalSource": "Polymer/polymer"
}

View file

@ -1,185 +0,0 @@
(function () {
function setImageIntoElement(elem, url) {
if (elem.tagName !== "IMG") {
elem.style.backgroundImage = "url('" + url + "')";
} else {
elem.setAttribute("src", url);
}
if (browserInfo.chrome && !browserInfo.mobile) {
if (!elem.classList.contains('noFade')) {
fadeIn(elem, 1);
}
}
}
function fadeIn(elem, iterations) {
var keyframes = [
{ opacity: '0', offset: 0 },
{ opacity: '1', offset: 1 }];
var timing = { duration: 200, iterations: iterations };
return elem.animate(keyframes, timing);
}
// Request Quota (only for File System API)
var requestedBytes = 1024 * 1024 * 600; // MB
var imageCacheDirectoryEntry;
var imageCacheFolder = 'images';
function createDir(rootDirEntry, folders, callback, errorCallback) {
// Throw out './' or '/' and move on to prevent something like '/foo/.//bar'.
if (folders[0] == '.' || folders[0] == '') {
folders = folders.slice(1);
}
rootDirEntry.getDirectory(folders[0], { create: true }, function (dirEntry) {
// Recursively add the new subfolder (if we still have another to create).
if (folders.length > 1) {
createDir(dirEntry, folders.slice(1), callback, errorCallback);
} else {
callback(dirEntry);
}
}, errorCallback);
}
navigator.webkitPersistentStorage.requestQuota(requestedBytes, function (grantedBytes) {
var requestMethod = window.webkitRequestFileSystem || window.requestFileSystem;
requestMethod(PERSISTENT, grantedBytes, function (fs) {
fileSystem = fs;
createDir(fileSystem.root, imageCacheFolder.split('/'), function (dirEntry) {
imageCacheDirectoryEntry = dirEntry;
});
});
});
var fileSystem;
function imageFileStore() {
var self = this;
function getCacheKey(url) {
// Try to strip off the domain to share the cache between local and remote connections
var index = url.indexOf('://');
if (index != -1) {
url = url.substring(index + 3);
index = url.indexOf('/');
if (index != -1) {
url = url.substring(index + 1);
}
}
return CryptoJS.MD5(url).toString();
}
function downloadToFile(url, dir, filename, callback, errorCallback) {
console.log('Downloading ' + url);
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = "arraybuffer";
xhr.onload = function (e) {
if (this.status == 200) {
writeData(dir, filename, this.getResponseHeader('Content-Type'), this.response, callback, errorCallback);
} else {
errorCallback('');
}
}
xhr.send();
}
function writeData(dir, filename, fileType, data, callback, errorCallback) {
dir.getFile(filename, { create: true }, function (fileEntry) {
// Create a FileWriter object for our FileEntry (log.txt).
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function (e) {
callback(fileEntry);
};
fileWriter.onerror = errorCallback;
// Create a new Blob and write it to log.txt.
var blob = new Blob([data], { type: fileType });
fileWriter.write(blob);
}, errorCallback);
}, errorCallback);
}
self.getImageUrl = function (originalUrl) {
return new Promise(function (resolve, reject) {
if (originalUrl.indexOf('tag=') != -1) {
originalUrl += "&accept=webp";
}
var key = getCacheKey(originalUrl);
var fileEntryCallback = function (fileEntry) {
resolve(fileEntry.toURL());
};
var errorCallback = function (e) {
console.log('Imagestore error: ' + e.name);
reject();
};
if (!fileSystem || !imageCacheDirectoryEntry) {
errorCallback('');
return;
}
var path = '/' + imageCacheFolder + "/" + key;
fileSystem.root.getFile(path, { create: false }, fileEntryCallback, function () {
downloadToFile(originalUrl, imageCacheDirectoryEntry, key, fileEntryCallback, errorCallback);
});
});
};
self.setImageInto = function (elem, url) {
self.getImageUrl(url).then(function (localUrl) {
setImageIntoElement(elem, localUrl);
}, function () {
setImageIntoElement(elem, url);
});
};
window.ImageStore = self;
}
require(['cryptojs-md5'], function () {
new imageFileStore();
});
})();

View file

@ -1849,6 +1849,14 @@ var AppInfo = {};
connectservice: apiClientBowerPath + '/connectservice'
};
if (navigator.webkitPersistentStorage) {
paths.imageloader = embyWebComponentsBowerPath + "/images/persistentimageloader";
} else if (Dashboard.isRunningInCordova()) {
paths.imageloader = 'cordova/imagestore';
} else {
paths.imageloader = embyWebComponentsBowerPath + "/images/basicimageloader";
}
paths.hlsjs = bowerPath + "/hls.js/dist/hls.min";
if (Dashboard.isRunningInCordova()) {
@ -2262,13 +2270,6 @@ var AppInfo = {};
var postInitDependencies = [];
if (navigator.webkitPersistentStorage) {
postInitDependencies.push('components/imagestore');
}
else if (Dashboard.isRunningInCordova()) {
postInitDependencies.push('cordova/imagestore');
}
postInitDependencies.push('scripts/thememediaplayer');
postInitDependencies.push('scripts/remotecontrol');
postInitDependencies.push('css!css/notifications.css');
@ -2396,7 +2397,7 @@ var AppInfo = {};
var keys = [];
keys.push(navigator.userAgent);
keys.push((navigator.cpuClass || ""));
keys.push(new Date().getTime());
var randomId = CryptoJS.SHA1(keys.join('|')).toString();
appStorage.setItem('_deviceId', randomId);
onDeviceAdAcquired(randomId);

View file

@ -1,4 +1,4 @@
define(['visibleinviewport'], function (visibleInViewport) {
define(['visibleinviewport', 'imageloader'], function (visibleInViewport, imageLoader) {
var wheelEvent = (document.implementation.hasFeature('Event.wheel', '3.0') ? 'wheel' : 'mousewheel');
var thresholdX = screen.availWidth;
@ -11,11 +11,27 @@
function fillImage(elem) {
var source = elem.getAttribute('data-src');
if (source) {
ImageStore.setImageInto(elem, source);
imageLoader.loadImage(elem, source).then(fadeIn);
elem.setAttribute("data-src", '');
}
}
function fadeIn(elem) {
if (!browserInfo.animate || browserInfo.mobile) {
return;
}
if (elem.classList.contains('noFade')) {
return;
}
var keyframes = [
{ opacity: '0', offset: 0 },
{ opacity: '1', offset: 1 }];
var timing = { duration: 300, iterations: 1 };
elem.animate(keyframes, timing);
}
function cancelAll(tokens) {
for (var i = 0, length = tokens.length; i < length; i++) {
@ -90,11 +106,7 @@
for (var i = 0, length = elems.length; i < length; i++) {
var elem = elems[0];
var source = elem.getAttribute('data-src');
if (source) {
ImageStore.setImageInto(elem, source);
elem.setAttribute("data-src", '');
}
fillImage(elem);
}
}
@ -109,36 +121,6 @@
fillImages([elem]);
}
function setImageIntoElement(elem, url) {
if (elem.tagName !== "IMG") {
elem.style.backgroundImage = "url('" + url + "')";
} else {
elem.setAttribute("src", url);
}
if (browserInfo.animate && !browserInfo.mobile) {
if (!elem.classList.contains('noFade')) {
fadeIn(elem, 1);
}
}
}
function fadeIn(elem, iterations) {
var keyframes = [
{ opacity: '0', offset: 0 },
{ opacity: '1', offset: 1 }];
var timing = { duration: 200, iterations: iterations };
return elem.animate(keyframes, timing);
}
window.ImageStore = {
setImageInto: setImageIntoElement
};
window.ImageLoader = {
fillImages: fillImages,
lazyImage: lazyImage,