mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Merge pull request #777 from timhobbs/master
Cast updates and lazy loading
This commit is contained in:
commit
b7c828e294
19 changed files with 607 additions and 127 deletions
|
@ -139,7 +139,7 @@
|
|||
text-align: left;
|
||||
margin-left: 0;
|
||||
right: 0;
|
||||
bottom: 83px;
|
||||
bottom: 85px;
|
||||
}
|
||||
|
||||
/* Media queries
|
||||
|
@ -259,7 +259,7 @@
|
|||
}
|
||||
|
||||
#mediaPlayer #videoControls .mediaPlayerFlyout {
|
||||
bottom: 148px;
|
||||
bottom: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,17 @@
|
|||
|
||||
this.hasReceivers = false;
|
||||
|
||||
this.currentMediaOffset = 0;
|
||||
|
||||
// Progress bar element id
|
||||
this.progressBar = "positionSlider";
|
||||
|
||||
// Timec display element id
|
||||
this.duration = "currentTime";
|
||||
|
||||
// Playback display element id
|
||||
this.playback = "playTime";
|
||||
|
||||
this.initializeCastPlayer();
|
||||
};
|
||||
|
||||
|
@ -89,7 +100,7 @@
|
|||
|
||||
// v1 Id AE4DA10A
|
||||
// v2 Id 472F0435
|
||||
var applicationID = 'AE4DA10A';
|
||||
var applicationID = '472F0435';
|
||||
|
||||
// request session
|
||||
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
|
||||
|
@ -445,6 +456,8 @@
|
|||
|
||||
function getMetadata(item) {
|
||||
|
||||
console.log("md item", item);
|
||||
|
||||
var metadata = {};
|
||||
|
||||
if (item.Type == 'Episode') {
|
||||
|
@ -512,7 +525,7 @@
|
|||
|
||||
else if (item.MediaType == 'Movie') {
|
||||
metadata = new chrome.cast.media.MovieMediaMetadata();
|
||||
metadata.type = chrome.cast.media.MetadataType.MUSIC_TRACK;
|
||||
metadata.type = chrome.cast.media.MetadataType.MOVIE;
|
||||
|
||||
if (item.ProductionYear) {
|
||||
metadata.releaseYear = item.ProductionYear;
|
||||
|
@ -617,6 +630,8 @@
|
|||
return;
|
||||
}
|
||||
|
||||
this.currentMediaOffset = startTimeTicks || 0;
|
||||
|
||||
var maxBitrate = 12000000;
|
||||
var mediaInfo = getMediaSourceInfo(user, item, maxBitrate, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
|
||||
|
||||
|
@ -653,40 +668,62 @@
|
|||
|
||||
console.log("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')');
|
||||
this.currentMediaSession = mediaSession;
|
||||
this.currentMediaTime = this.session.media[0].currentTime;
|
||||
|
||||
if (how == 'loadMedia') {
|
||||
this.castPlayerState = PLAYER_STATE.PLAYING;
|
||||
clearInterval(this.timer);
|
||||
this.startProgressTimer(this.incrementMediaTime);
|
||||
}
|
||||
|
||||
if (how == 'activeSession') {
|
||||
this.castPlayerState = this.session.media[0].playerState;
|
||||
this.currentMediaTime = this.session.media[0].currentTime;
|
||||
}
|
||||
|
||||
if (this.castPlayerState == PLAYER_STATE.PLAYING) {
|
||||
// start progress timer
|
||||
//this.startProgressTimer(this.incrementMediaTime);
|
||||
this.startProgressTimer(this.incrementMediaTime);
|
||||
}
|
||||
|
||||
this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this));
|
||||
this.currentMediaDuration = this.currentMediaSession.media.duration;
|
||||
|
||||
//this.currentMediaDuration = this.currentMediaSession.media.duration;
|
||||
//var duration = this.currentMediaDuration;
|
||||
//var hr = parseInt(duration / 3600);
|
||||
//duration -= hr * 3600;
|
||||
//var min = parseInt(duration / 60);
|
||||
//var sec = parseInt(duration % 60);
|
||||
//if (hr > 0) {
|
||||
// duration = hr + ":" + min + ":" + sec;
|
||||
//}
|
||||
//else {
|
||||
// if (min > 0) {
|
||||
// duration = min + ":" + sec;
|
||||
// }
|
||||
// else {
|
||||
// duration = sec;
|
||||
// }
|
||||
//}
|
||||
//document.getElementById("duration").innerHTML = duration;
|
||||
var playTime = document.getElementById(this.playback);
|
||||
if (!playTime) {
|
||||
// Set duration time
|
||||
var totalTime = document.getElementById(this.duration);
|
||||
totalTime.innerHTML = " / " + formatTime(this.currentMediaDuration);
|
||||
|
||||
// Set play time
|
||||
playTime = document.createElement("div");
|
||||
playTime.id = this.playback;
|
||||
playTime.className = "currentTime";
|
||||
playTime.style.marginRight = "5px";
|
||||
totalTime.parentNode.insertBefore(playTime, totalTime);
|
||||
playTime.innerHTML = formatTime(this.currentMediaTime);
|
||||
}
|
||||
};
|
||||
|
||||
function formatTime(duration) {
|
||||
var hr = parseInt(duration / 3600);
|
||||
duration -= hr * 3600;
|
||||
var min = parseInt(duration / 60);
|
||||
var sec = parseInt(duration % 60);
|
||||
|
||||
hr = "" + hr;
|
||||
min = "" + min;
|
||||
sec = "" + sec;
|
||||
var hh = pad(hr);
|
||||
var mm = pad(min);
|
||||
var ss = pad(sec);
|
||||
|
||||
duration = hh + ":" + mm + ":" + ss;
|
||||
|
||||
return duration;
|
||||
};
|
||||
|
||||
function pad(s) {
|
||||
return "00".substring(0, 2 - s.length) + s;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -707,7 +744,7 @@
|
|||
this.castPlayerState = PLAYER_STATE.IDLE;
|
||||
}
|
||||
console.log("chromecast updating media");
|
||||
//this.updateProgressBar(e);
|
||||
this.updateProgressBarByTimer();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -745,6 +782,7 @@
|
|||
this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this));
|
||||
this.castPlayerState = PLAYER_STATE.PLAYING;
|
||||
// start progress timer
|
||||
clearInterval(this.timer);
|
||||
this.startProgressTimer(this.incrementMediaTime);
|
||||
break;
|
||||
case PLAYER_STATE.IDLE:
|
||||
|
@ -791,6 +829,10 @@
|
|||
this.onError.bind(this));
|
||||
this.castPlayerState = PLAYER_STATE.STOPPED;
|
||||
clearInterval(this.timer);
|
||||
var playTime = document.getElementById(this.playback);
|
||||
if (playTime) {
|
||||
playTime.parentNode.removeChild(playTime);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -849,19 +891,10 @@
|
|||
* @param {Event} e An event object from seek
|
||||
*/
|
||||
CastPlayer.prototype.seekMedia = function (event) {
|
||||
var pos = parseInt(event.offsetX);
|
||||
var pi = document.getElementById("progress_indicator");
|
||||
var p = document.getElementById("progress");
|
||||
if (event.currentTarget.id == 'progress_indicator') {
|
||||
var curr = parseInt(this.currentMediaTime + this.currentMediaDuration * pos / PROGRESS_BAR_WIDTH);
|
||||
var pp = parseInt(pi.style.marginLeft) + pos;
|
||||
var pw = parseInt(p.style.width) + pos;
|
||||
}
|
||||
else {
|
||||
var curr = parseInt(pos * this.currentMediaDuration / PROGRESS_BAR_WIDTH);
|
||||
var pp = pos - 21 - PROGRESS_BAR_WIDTH;
|
||||
var pw = pos;
|
||||
}
|
||||
var pos = parseInt(event);
|
||||
var p = document.getElementById(this.progressBar);
|
||||
var curr = parseInt(this.currentMediaTime + this.currentMediaDuration * pos);
|
||||
var pw = parseInt(p.value) + pos;
|
||||
|
||||
if (this.castPlayerState != PLAYER_STATE.PLAYING && this.castPlayerState != PLAYER_STATE.PAUSED) {
|
||||
return;
|
||||
|
@ -899,20 +932,20 @@
|
|||
* @param {Object} e An media status update object
|
||||
*/
|
||||
CastPlayer.prototype.updateProgressBar = function (e) {
|
||||
var p = document.getElementById("progress");
|
||||
var pi = document.getElementById("progress_indicator");
|
||||
var p = document.getElementById(this.progressBar);
|
||||
if (e.idleReason == 'FINISHED' && e.playerState == 'IDLE') {
|
||||
p.style.width = '0px';
|
||||
pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + 'px';
|
||||
p.value = 0;
|
||||
clearInterval(this.timer);
|
||||
this.castPlayerState = PLAYER_STATE.STOPPED;
|
||||
if (e.idleReason == 'FINISHED') {
|
||||
$.publish("/playback/complete", e);
|
||||
console.log("playback complete", e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.style.width = Math.ceil(PROGRESS_BAR_WIDTH * e.currentTime / this.currentMediaSession.media.duration + 1) + 'px';
|
||||
p.value = Number(e.currentTime / this.currentMediaSession.media.duration + 1).toFixed(3);
|
||||
this.progressFlag = false;
|
||||
setTimeout(this.setProgressFlag.bind(this), 1000); // don't update progress in 1 second
|
||||
var pp = Math.ceil(PROGRESS_BAR_WIDTH * e.currentTime / this.currentMediaSession.media.duration);
|
||||
pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + pp + 'px';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -928,47 +961,159 @@
|
|||
* Update progress bar based on timer
|
||||
*/
|
||||
CastPlayer.prototype.updateProgressBarByTimer = function () {
|
||||
var p = document.getElementById("progress");
|
||||
if (isNaN(parseInt(p.style.width))) {
|
||||
p.style.width = 0;
|
||||
var p = document.getElementById(this.progressBar);
|
||||
if (isNaN(parseInt(p.value))) {
|
||||
p.value = 0;
|
||||
}
|
||||
|
||||
if (this.currentMediaDuration > 0) {
|
||||
var pp = Math.floor(PROGRESS_BAR_WIDTH * this.currentMediaTime / this.currentMediaDuration);
|
||||
var pp = Number(this.currentMediaTime / this.currentMediaDuration).toFixed(3);
|
||||
|
||||
var startTime = this.currentMediaOffset / 10000000;
|
||||
var playTime = document.getElementById(this.playback);
|
||||
if (playTime) {
|
||||
playTime.innerHTML = formatTime(startTime + this.currentMediaTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.progressFlag) {
|
||||
// don't update progress if it's been updated on media status update event
|
||||
p.style.width = pp + 'px';
|
||||
var pi = document.getElementById("progress_indicator");
|
||||
pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + pp + 'px';
|
||||
p.value = pp;
|
||||
}
|
||||
|
||||
if (pp > PROGRESS_BAR_WIDTH) {
|
||||
if (pp > 100 || this.castPlayerState == PLAYER_STATE.IDLE) {
|
||||
clearInterval(this.timer);
|
||||
this.deviceState = DEVICE_STATE.IDLE;
|
||||
this.castPlayerState = PLAYER_STATE.IDLE;
|
||||
$.publish("/playback/complete", true);
|
||||
console.log("playback complete");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {function} A callback function for the fucntion to start timer
|
||||
*/
|
||||
CastPlayer.prototype.startProgressTimer = function(callback) {
|
||||
if(this.timer) {
|
||||
clearInterval(this.timer);
|
||||
this.timer = null;
|
||||
}
|
||||
|
||||
// start progress timer
|
||||
this.timer = setInterval(callback.bind(this), this.timerStep);
|
||||
};
|
||||
|
||||
var castPlayer = new CastPlayer();
|
||||
|
||||
function chromecastPlayer() {
|
||||
function chromecastPlayer(castPlayer) {
|
||||
|
||||
var self = this;
|
||||
|
||||
var isPositionSliderActive = false;
|
||||
|
||||
self.name = PlayerName;
|
||||
|
||||
self.play = function (options) {
|
||||
self.isPaused = false;
|
||||
|
||||
if (options.items) {
|
||||
self.playlist = [];
|
||||
|
||||
Dashboard.getCurrentUser().done(function (user) {
|
||||
self.playlistIndex = 0;
|
||||
|
||||
castPlayer.loadMedia(user, options.items[0], options.startTimeTicks);
|
||||
$.subscribe("/playback/complete", function (e) {
|
||||
if (self.playlistIndex < (self.playlist.items || []).length) {
|
||||
self.play(self.playlist);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
////$(".positionSlider", "#footer").off("slidestart slidestop")
|
||||
//// .on('slidestart', function (e) {
|
||||
//// isPositionSliderActive = true;
|
||||
////}).on('slidestop', positionSliderChange);
|
||||
|
||||
////function positionSliderChange() {
|
||||
//// isPositionSliderActive = false;
|
||||
//// var newPercent = parseInt(this.value);
|
||||
//// self.changeStream(newPercent);
|
||||
////}
|
||||
|
||||
function getItemsForPlayback(query) {
|
||||
var userId = Dashboard.getCurrentUserId();
|
||||
|
||||
query.Limit = query.Limit || 100;
|
||||
query.Fields = getItemFields;
|
||||
query.ExcludeLocationTypes = "Virtual";
|
||||
|
||||
return ApiClient.getItems(userId, query);
|
||||
};
|
||||
|
||||
function queueItems (items) {
|
||||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
self.playlist.push(items[i]);
|
||||
}
|
||||
};
|
||||
|
||||
function queueItemsNext(items) {
|
||||
var insertIndex = 1;
|
||||
for (var i = 0, length = items.length; i < length; i++) {
|
||||
self.playlist.splice(insertIndex, 0, items[i]);
|
||||
insertIndex++;
|
||||
}
|
||||
};
|
||||
|
||||
function translateItemsForPlayback(items) {
|
||||
var deferred = $.Deferred();
|
||||
var firstItem = items[0];
|
||||
var promise;
|
||||
if (firstItem.IsFolder) {
|
||||
promise = self.getItemsForPlayback({
|
||||
ParentId: firstItem.Id,
|
||||
Filters: "IsNotFolder",
|
||||
Recursive: true,
|
||||
SortBy: "SortName",
|
||||
MediaTypes: "Audio,Video"
|
||||
});
|
||||
}
|
||||
else if (firstItem.Type == "MusicArtist") {
|
||||
promise = self.getItemsForPlayback({
|
||||
Artists: firstItem.Name,
|
||||
Filters: "IsNotFolder",
|
||||
Recursive: true,
|
||||
SortBy: "SortName",
|
||||
MediaTypes: "Audio"
|
||||
});
|
||||
}
|
||||
else if (firstItem.Type == "MusicGenre") {
|
||||
promise = self.getItemsForPlayback({
|
||||
Genres: firstItem.Name,
|
||||
Filters: "IsNotFolder",
|
||||
Recursive: true,
|
||||
SortBy: "SortName",
|
||||
MediaTypes: "Audio"
|
||||
});
|
||||
}
|
||||
|
||||
if (promise) {
|
||||
promise.done(function (result) {
|
||||
deferred.resolveWith(null, [result.Items]);
|
||||
});
|
||||
} else {
|
||||
deferred.resolveWith(null, [items]);
|
||||
}
|
||||
|
||||
return deferred.promise();
|
||||
};
|
||||
|
||||
self.play = function (options) {
|
||||
console.log("play", options);
|
||||
$("#nowPlayingBar", "#footer").show();
|
||||
if (self.isPaused) {
|
||||
self.isPaused = !self.isPaused;
|
||||
castPlayer.playMedia();
|
||||
} else if (options.items) {
|
||||
Dashboard.getCurrentUser().done(function (user) {
|
||||
castPlayer.loadMedia(user, options.items[self.playlistIndex++], options.startPositionTicks);
|
||||
});
|
||||
} else {
|
||||
var userId = Dashboard.getCurrentUserId();
|
||||
|
||||
var query = {};
|
||||
|
@ -978,46 +1123,154 @@
|
|||
query.Ids = options.ids.join(',');
|
||||
|
||||
ApiClient.getItems(userId, query).done(function (result) {
|
||||
|
||||
options.items = result.Items;
|
||||
|
||||
self.play(options);
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
self.unpause = function () {
|
||||
console.log("unpause");
|
||||
self.isPaused = !self.isPaused;
|
||||
castPlayer.playMedia();
|
||||
};
|
||||
|
||||
self.pause = function () {
|
||||
console.log("pause");
|
||||
self.isPaused = true;
|
||||
castPlayer.pauseMedia();
|
||||
};
|
||||
|
||||
self.shuffle = function (id) {
|
||||
self.play({ ids: [id] });
|
||||
var userId = Dashboard.getCurrentUserId();
|
||||
ApiClient.getItem(userId, id).done(function (item) {
|
||||
var query = {
|
||||
UserId: userId,
|
||||
Fields: getItemFields,
|
||||
Limit: 50,
|
||||
Filters: "IsNotFolder",
|
||||
Recursive: true,
|
||||
SortBy: "Random"
|
||||
};
|
||||
|
||||
if (item.IsFolder) {
|
||||
query.ParentId = id;
|
||||
}
|
||||
else if (item.Type == "MusicArtist") {
|
||||
query.MediaTypes = "Audio";
|
||||
query.Artists = item.Name;
|
||||
}
|
||||
else if (item.Type == "MusicGenre") {
|
||||
query.MediaTypes = "Audio";
|
||||
query.Genres = item.Name;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
self.getItemsForPlayback(query).done(function (result) {
|
||||
self.playlist = { items: result.Items };
|
||||
console.log("shuffle items", result.Items);
|
||||
self.play(self.playlist);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
self.instantMix = function (id) {
|
||||
self.play({ ids: [id] });
|
||||
};
|
||||
var userId = Dashboard.getCurrentUserId();
|
||||
ApiClient.getItem(userId, id).done(function (item) {
|
||||
var promise;
|
||||
var getItemFields = "MediaSources,Chapters";
|
||||
var mixLimit = 3;
|
||||
|
||||
self.queue = function (options) {
|
||||
if (item.Type == "MusicArtist") {
|
||||
promise = ApiClient.getInstantMixFromArtist(name, {
|
||||
UserId: userId,
|
||||
Fields: getItemFields,
|
||||
Limit: mixLimit
|
||||
});
|
||||
}
|
||||
else if (item.Type == "MusicGenre") {
|
||||
promise = ApiClient.getInstantMixFromMusicGenre(name, {
|
||||
UserId: userId,
|
||||
Fields: getItemFields,
|
||||
Limit: mixLimit
|
||||
});
|
||||
}
|
||||
else if (item.Type == "MusicAlbum") {
|
||||
promise = ApiClient.getInstantMixFromAlbum(id, {
|
||||
UserId: userId,
|
||||
Fields: getItemFields,
|
||||
Limit: mixLimit
|
||||
});
|
||||
}
|
||||
else if (item.Type == "Audio") {
|
||||
promise = ApiClient.getInstantMixFromSong(id, {
|
||||
UserId: userId,
|
||||
Fields: getItemFields,
|
||||
Limit: mixLimit
|
||||
});
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
self.queueNext = function (options) {
|
||||
|
||||
};
|
||||
|
||||
self.stop = function () {
|
||||
castPlayer.stop();
|
||||
promise.done(function (result) {
|
||||
self.playlist = { items: result.Items };
|
||||
console.log("instant mix items", result.Items);
|
||||
self.play(self.playlist);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
self.canQueueMediaType = function (mediaType) {
|
||||
return mediaType == "Audio";
|
||||
};
|
||||
|
||||
return false;
|
||||
self.queue = function (options) {
|
||||
Dashboard.getCurrentUser().done(function (user) {
|
||||
if (options.items) {
|
||||
translateItemsForPlayback(options.items).done(function (items) {
|
||||
queueItems(items);
|
||||
});
|
||||
} else {
|
||||
getItemsForPlayback({
|
||||
Ids: options.ids.join(',')
|
||||
}).done(function (result) {
|
||||
translateItemsForPlayback(result.Items).done(function (items) {
|
||||
queueItems(items);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
self.queueNext = function (options) {
|
||||
Dashboard.getCurrentUser().done(function (user) {
|
||||
if (options.items) {
|
||||
queueItemsNext(options.items);
|
||||
} else {
|
||||
self.getItemsForPlayback({
|
||||
Ids: options.ids.join(',')
|
||||
}).done(function (result) {
|
||||
options.items = result.Items;
|
||||
queueItemsNext(options.items);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
self.stop = function () {
|
||||
$("#nowPlayingBar", "#footer").hide();
|
||||
self.playlist = [];
|
||||
self.playlistIndex = 0;
|
||||
castPlayer.stopMedia();
|
||||
};
|
||||
|
||||
self.mute = function () {
|
||||
castPlayer.mute();
|
||||
};
|
||||
|
||||
self.unMute = function () {
|
||||
self.unmute = function () {
|
||||
castPlayer.unMute();
|
||||
};
|
||||
|
||||
|
@ -1026,18 +1279,13 @@
|
|||
};
|
||||
|
||||
self.getTargets = function () {
|
||||
|
||||
var targets = [];
|
||||
|
||||
targets.push(self.getCurrentTargetInfo());
|
||||
|
||||
return targets;
|
||||
};
|
||||
|
||||
self.getCurrentTargetInfo = function () {
|
||||
|
||||
var appName = null;
|
||||
|
||||
if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.friendlyName) {
|
||||
appName = castPlayer.session.friendlyName;
|
||||
}
|
||||
|
@ -1051,9 +1299,80 @@
|
|||
appName: appName
|
||||
};
|
||||
};
|
||||
|
||||
self.setCurrentTime = function (ticks, item, updateSlider) {
|
||||
// Convert to ticks
|
||||
ticks = Math.floor(ticks);
|
||||
var timeText = Dashboard.getDisplayTime(ticks);
|
||||
if (self.currentDurationTicks) {
|
||||
timeText += " / " + Dashboard.getDisplayTime(self.currentDurationTicks);
|
||||
if (updateSlider) {
|
||||
var percent = ticks / self.currentDurationTicks;
|
||||
percent *= 100;
|
||||
self.positionSlider.val(percent).slider('enable').slider('refresh');
|
||||
}
|
||||
} else {
|
||||
self.positionSlider.slider('disable').slider('refresh');
|
||||
}
|
||||
|
||||
MediaController.registerPlayer(new chromecastPlayer());
|
||||
self.currentTimeElement.html(timeText);
|
||||
};
|
||||
|
||||
self.changeStream = function (position) {
|
||||
console.log("seek", position);
|
||||
////castPlayer.seekMedia(position);
|
||||
};
|
||||
|
||||
self.removeFromPlaylist = function (i) {
|
||||
self.playlist.remove(i);
|
||||
};
|
||||
|
||||
self.currentPlaylistIndex = function (i) {
|
||||
if (i == null) {
|
||||
return currentPlaylistIndex;
|
||||
}
|
||||
|
||||
var newItem = self.playlist[i];
|
||||
|
||||
Dashboard.getCurrentUser().done(function (user) {
|
||||
self.playInternal(newItem, 0, user);
|
||||
currentPlaylistIndex = i;
|
||||
});
|
||||
};
|
||||
|
||||
self.nextTrack = function () {
|
||||
var newIndex = currentPlaylistIndex + 1;
|
||||
var newItem = self.playlist[newIndex];
|
||||
|
||||
if (newItem) {
|
||||
Dashboard.getCurrentUser().done(function (user) {
|
||||
self.playInternal(newItem, 0, user);
|
||||
currentPlaylistIndex = newIndex;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
self.previousTrack = function () {
|
||||
var newIndex = currentPlaylistIndex - 1;
|
||||
if (newIndex >= 0) {
|
||||
var newItem = self.playlist[newIndex];
|
||||
if (newItem) {
|
||||
Dashboard.getCurrentUser().done(function (user) {
|
||||
self.playInternal(newItem, 0, user);
|
||||
currentPlaylistIndex = newIndex;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.volumeDown = function () {
|
||||
};
|
||||
|
||||
self.volumeUp = function () {
|
||||
};
|
||||
}
|
||||
|
||||
MediaController.registerPlayer(new chromecastPlayer(castPlayer));
|
||||
|
||||
$(MediaController).on('playerchange', function () {
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
showTitle: true,
|
||||
showParentTitle: true,
|
||||
overlayText: true,
|
||||
selectionPanel: true
|
||||
selectionPanel: true,
|
||||
lazy: true
|
||||
});
|
||||
|
||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||
|
|
|
@ -432,6 +432,8 @@
|
|||
|
||||
options.shape = options.shape || "portrait";
|
||||
|
||||
options.lazy = options.lazy || false;
|
||||
|
||||
var html = "";
|
||||
|
||||
var primaryImageAspectRatio = options.shape == 'auto' ? LibraryBrowser.getAveragePrimaryImageAspectRatio(items) : null;
|
||||
|
@ -667,7 +669,7 @@
|
|||
|
||||
var style = "";
|
||||
|
||||
if (imgUrl) {
|
||||
if (imgUrl && !options.lazy) {
|
||||
style += 'background-image:url(\'' + imgUrl + '\');';
|
||||
}
|
||||
|
||||
|
@ -680,9 +682,16 @@
|
|||
imageCssClass += " coveredPosterItemImage";
|
||||
}
|
||||
|
||||
var dataSrc = "";
|
||||
|
||||
if (options.lazy) {
|
||||
imageCssClass += " lazy";
|
||||
dataSrc = ' data-src="' + imgUrl + '"';
|
||||
}
|
||||
|
||||
var progressHtml = options.showProgress === false ? '' : LibraryBrowser.getItemProgressBarHtml(item);
|
||||
|
||||
html += '<div class="' + imageCssClass + '" style="' + style + '">';
|
||||
html += '<div class="' + imageCssClass + '" style="' + style + '"' + dataSrc + '>';
|
||||
|
||||
html += '<div class="posterItemOverlayTarget"></div>';
|
||||
|
||||
|
@ -755,6 +764,10 @@
|
|||
|
||||
var itemCountHtml = LibraryBrowser.getItemCountsHtml(options, item);
|
||||
|
||||
if (item.Type == "Person" && !itemCountHtml) {
|
||||
itemCountHtml = " ";
|
||||
}
|
||||
|
||||
if (itemCountHtml) {
|
||||
html += "<div class='" + cssClass + "'>";
|
||||
html += itemCountHtml;
|
||||
|
|
|
@ -174,6 +174,62 @@
|
|||
return p.isDefaultPlayer;
|
||||
})[0];
|
||||
};
|
||||
|
||||
self.pause = function () {
|
||||
currentPlayer.pause();
|
||||
};
|
||||
|
||||
self.stop = function () {
|
||||
currentPlayer.stop();
|
||||
};
|
||||
|
||||
self.unpause = function () {
|
||||
currentPlayer.unpause();
|
||||
};
|
||||
|
||||
self.seek = function (position) {
|
||||
currentPlayer.changeStream(position);
|
||||
};
|
||||
|
||||
self.currentPlaylistIndex = function (i) {
|
||||
currentPlayer.currentPlaylistIndex(i);
|
||||
};
|
||||
|
||||
self.removeFromPlaylist = function (i) {
|
||||
currentPlayer.removeFromPlaylist(i);
|
||||
};
|
||||
|
||||
self.nextTrack = function () {
|
||||
currentPlayer.nextTrack();
|
||||
};
|
||||
|
||||
self.previousTrack = function () {
|
||||
currentPlayer.previousTrack();
|
||||
};
|
||||
|
||||
self.mute = function () {
|
||||
currentPlayer.mute();
|
||||
};
|
||||
|
||||
self.unmute = function () {
|
||||
currentPlayer.unmute();
|
||||
};
|
||||
|
||||
self.toggleMute = function () {
|
||||
currentPlayer.toggleMute();
|
||||
};
|
||||
|
||||
self.volumeDown = function () {
|
||||
currentPlayer.volumeDown();
|
||||
};
|
||||
|
||||
self.volumeUp = function () {
|
||||
currentPlayer.volumeUp();
|
||||
};
|
||||
|
||||
self.shuffle = function (id) {
|
||||
currentPlayer.shuffle(id);
|
||||
};
|
||||
}
|
||||
|
||||
window.MediaController = new mediaController();
|
||||
|
|
|
@ -872,18 +872,18 @@
|
|||
$('#video-fullscreenButton', videoControls).show();
|
||||
}
|
||||
|
||||
var videoElement = $("video", videoElement);
|
||||
var video = $("video", videoElement);
|
||||
|
||||
initialVolume = localStorage.getItem("volume") || 0.5;
|
||||
|
||||
videoElement.each(function () {
|
||||
video.each(function () {
|
||||
this.volume = initialVolume;
|
||||
});
|
||||
|
||||
self.volumeSlider.val(initialVolume).slider('refresh');
|
||||
self.updateVolumeButtons(initialVolume);
|
||||
|
||||
videoElement.on("volumechange", function (e) {
|
||||
video.on("volumechange", function (e) {
|
||||
|
||||
var muted = this.muted;
|
||||
|
||||
|
@ -899,13 +899,13 @@
|
|||
|
||||
}).on("play.once", function () {
|
||||
|
||||
videoElement.off("play.once");
|
||||
video.off("play.once");
|
||||
|
||||
}).on("playing.once", function () {
|
||||
|
||||
self.updateCanClientSeek(this);
|
||||
|
||||
videoElement.off("playing.once");
|
||||
video.off("playing.once");
|
||||
|
||||
ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType);
|
||||
|
||||
|
@ -1037,7 +1037,7 @@
|
|||
currentItem = item;
|
||||
currentMediaSource = mediaSource;
|
||||
|
||||
return videoElement[0];
|
||||
return video[0];
|
||||
}
|
||||
};
|
||||
})();
|
|
@ -33,7 +33,8 @@
|
|||
shape: "portrait",
|
||||
context: 'movies',
|
||||
showTitle: true,
|
||||
centerText: true
|
||||
centerText: true,
|
||||
lazy: true
|
||||
});
|
||||
|
||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
context: 'movies',
|
||||
showTitle: true,
|
||||
showItemCounts: true,
|
||||
coverImage: true
|
||||
coverImage: true,
|
||||
lazy: true
|
||||
});
|
||||
|
||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false);
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
shape: "backdrop",
|
||||
preferThumb: true,
|
||||
context: 'movies',
|
||||
selectionPanel: true
|
||||
selectionPanel: true,
|
||||
lazy: true
|
||||
});
|
||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||
}
|
||||
|
@ -45,7 +46,8 @@
|
|||
items: result.Items,
|
||||
shape: "banner",
|
||||
preferBanner: true,
|
||||
context: 'movies'
|
||||
context: 'movies',
|
||||
lazy: true
|
||||
});
|
||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||
}
|
||||
|
@ -56,7 +58,8 @@
|
|||
context: 'movies',
|
||||
showTitle: true,
|
||||
centerText: true,
|
||||
selectionPanel: true
|
||||
selectionPanel: true,
|
||||
lazy: true
|
||||
});
|
||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||
}
|
||||
|
@ -68,7 +71,8 @@
|
|||
showTitle: true,
|
||||
timeline: true,
|
||||
centerText: true,
|
||||
selectionPanel: true
|
||||
selectionPanel: true,
|
||||
lazy: true
|
||||
});
|
||||
$('.itemsContainer', page).addClass('timelineItemsContainer');
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
context: 'music',
|
||||
showTitle: true,
|
||||
coverImage: true,
|
||||
centerText: true
|
||||
centerText: true,
|
||||
lazy: true
|
||||
});
|
||||
|
||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
shape: "square",
|
||||
context: 'music',
|
||||
showTitle: true,
|
||||
showParentTitle: true
|
||||
showParentTitle: true,
|
||||
lazy: true
|
||||
});
|
||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||
}
|
||||
|
@ -45,7 +46,8 @@
|
|||
context: 'music',
|
||||
showTitle: true,
|
||||
showParentTitle: true,
|
||||
timeline: true
|
||||
timeline: true,
|
||||
lazy: true
|
||||
});
|
||||
$('.itemsContainer', page).addClass('timelineItemsContainer');
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
context: 'music',
|
||||
showTitle: true,
|
||||
coverImage: true,
|
||||
centerText: true
|
||||
centerText: true,
|
||||
lazy: true
|
||||
});
|
||||
|
||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
||||
|
@ -119,4 +120,10 @@
|
|||
updateFilterControls(this);
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$("body").on("create", function () {
|
||||
$(".lazy").unveil(200);
|
||||
});
|
||||
});
|
||||
|
||||
})(jQuery, document);
|
|
@ -32,7 +32,8 @@
|
|||
preferThumb: true,
|
||||
context: 'music',
|
||||
showItemCounts: true,
|
||||
centerText: true
|
||||
centerText: true,
|
||||
lazy: true
|
||||
});
|
||||
|
||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
html += '<tbody>';
|
||||
|
||||
$.each(MediaPlayer.playlist, function (i, item) {
|
||||
$.each(MediaController.playlist, function (i, item) {
|
||||
|
||||
var name = LibraryBrowser.getPosterViewDisplayName(item);
|
||||
|
||||
|
@ -65,14 +65,14 @@
|
|||
|
||||
var index = parseInt(this.getAttribute('data-index'));
|
||||
|
||||
MediaPlayer.currentPlaylistIndex(index);
|
||||
MediaController.currentPlaylistIndex(index);
|
||||
reloadPlaylist(page);
|
||||
|
||||
}).on('click', '.lnkRemove', function () {
|
||||
|
||||
var index = parseInt(this.getAttribute('data-index'));
|
||||
|
||||
MediaPlayer.removeFromPlaylist(index);
|
||||
MediaController.removeFromPlaylist(index);
|
||||
reloadPlaylist(page);
|
||||
});
|
||||
|
||||
|
|
|
@ -1330,42 +1330,42 @@ $(function () {
|
|||
footerHtml += '<div class="barBackground ui-bar-b"></div>';
|
||||
footerHtml += '<div style="display:inline-block;width:12px;"></div>';
|
||||
footerHtml += '<a id="playlistButton" class="mediaButton playlistButton" href="playlist.html" data-role="button" data-icon="bullets" data-iconpos="notext" data-inline="true" title="Playlist">Playlist</a>';
|
||||
footerHtml += '<button id="previousTrackButton" class="mediaButton previousTrackButton" title="Previous Track" type="button" onclick="MediaPlayer.previousTrack();" data-icon="previous-track" data-iconpos="notext" data-inline="true">Previous Track</button>';
|
||||
footerHtml += '<button id="playButton" class="mediaButton" title="Play" type="button" onclick="MediaPlayer.unpause();" data-icon="play" data-iconpos="notext" data-inline="true">Play</button>';
|
||||
footerHtml += '<button id="pauseButton" class="mediaButton" title="Pause" type="button" onclick="MediaPlayer.pause();" data-icon="pause" data-iconpos="notext" data-inline="true">Pause</button>';
|
||||
footerHtml += '<button id="previousTrackButton" class="mediaButton previousTrackButton" title="Previous Track" type="button" onclick="MediaController.previousTrack();" data-icon="previous-track" data-iconpos="notext" data-inline="true">Previous Track</button>';
|
||||
footerHtml += '<button id="playButton" class="mediaButton" title="Play" type="button" onclick="MediaController.unpause();" data-icon="play" data-iconpos="notext" data-inline="true">Play</button>';
|
||||
footerHtml += '<button id="pauseButton" class="mediaButton" title="Pause" type="button" onclick="MediaController.pause();" data-icon="pause" data-iconpos="notext" data-inline="true">Pause</button>';
|
||||
|
||||
footerHtml += '<div id="mediaElement"></div>';
|
||||
|
||||
footerHtml += '<button id="stopButton" class="mediaButton" title="Stop" type="button" onclick="MediaPlayer.stop();" data-icon="stop" data-iconpos="notext" data-inline="true">Stop</button>';
|
||||
footerHtml += '<button id="nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" onclick="MediaPlayer.nextTrack();" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
||||
footerHtml += '<button id="stopButton" class="mediaButton" title="Stop" type="button" onclick="MediaController.stop();" data-icon="stop" data-iconpos="notext" data-inline="true">Stop</button>';
|
||||
footerHtml += '<button id="nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" onclick="MediaController.nextTrack();" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
||||
|
||||
footerHtml += '<div class="positionSliderContainer sliderContainer">';
|
||||
footerHtml += '<input type="range" class="mediaSlider positionSlider slider" step=".001" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
||||
footerHtml += '<input id="positionSlider" type="range" class="mediaSlider positionSlider slider" step=".001" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
||||
footerHtml += '</div>';
|
||||
|
||||
footerHtml += '<div class="currentTime"></div>';
|
||||
footerHtml += '<div class="currentTime" id="currentTime"></div>';
|
||||
footerHtml += '<div class="nowPlayingMediaInfo"></div>';
|
||||
|
||||
footerHtml += '<button id="muteButton" class="mediaButton muteButton" title="Mute" type="button" onclick="MediaPlayer.mute();" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
||||
footerHtml += '<button id="unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" onclick="MediaPlayer.unMute();" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
||||
footerHtml += '<button id="muteButton" class="mediaButton muteButton" title="Mute" type="button" onclick="MediaController.mute();" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
||||
footerHtml += '<button id="unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" onclick="MediaController.unMute();" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
||||
|
||||
footerHtml += '<div class="volumeSliderContainer sliderContainer">';
|
||||
footerHtml += '<input type="range" class="mediaSlider volumeSlider slider" step=".05" min="0" max="1" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
||||
footerHtml += '</div>';
|
||||
|
||||
footerHtml += '<button onclick="MediaPlayer.showQualityFlyout();" id="qualityButton" class="mediaButton qualityButton" title="Quality" type="button" data-icon="gear" data-iconpos="notext" data-inline="true">Quality</button>';
|
||||
footerHtml += '<button onclick="MediaController.showQualityFlyout();" id="qualityButton" class="mediaButton qualityButton" title="Quality" type="button" data-icon="gear" data-iconpos="notext" data-inline="true">Quality</button>';
|
||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="qualityFlyout" style="display:none;" class="mediaPlayerFlyout"></div></div>';
|
||||
|
||||
footerHtml += '<button onclick="MediaPlayer.showAudioTracksFlyout();" id="audioTracksButton" class="imageButton mediaButton audioTracksButton" title="Audio tracks" type="button" data-icon="audiocd" data-iconpos="notext" data-inline="true">Audio Tracks</button>';
|
||||
footerHtml += '<button onclick="MediaController.showAudioTracksFlyout();" id="audioTracksButton" class="imageButton mediaButton audioTracksButton" title="Audio tracks" type="button" data-icon="audiocd" data-iconpos="notext" data-inline="true">Audio Tracks</button>';
|
||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="audioTracksFlyout" style="display:none;" class="mediaPlayerFlyout audioTracksFlyout"></div></div>';
|
||||
|
||||
footerHtml += '<button onclick="MediaPlayer.showSubtitleMenu();" id="subtitleButton" class="imageButton mediaButton subtitleButton" title="Subtitles" type="button" data-icon="subtitles" data-iconpos="notext" data-inline="true">Subtitles</button>';
|
||||
footerHtml += '<button onclick="MediaController.showSubtitleMenu();" id="subtitleButton" class="imageButton mediaButton subtitleButton" title="Subtitles" type="button" data-icon="subtitles" data-iconpos="notext" data-inline="true">Subtitles</button>';
|
||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="subtitleFlyout" style="display:none;" class="mediaPlayerFlyout subtitleFlyout"></div></div>';
|
||||
|
||||
footerHtml += '<button onclick="MediaPlayer.showChaptersFlyout();" id="chaptersButton" class="mediaButton chaptersButton" title="Scenes" type="button" data-icon="video" data-iconpos="notext" data-inline="true">Scenes</button>';
|
||||
footerHtml += '<button onclick="MediaController.showChaptersFlyout();" id="chaptersButton" class="mediaButton chaptersButton" title="Scenes" type="button" data-icon="video" data-iconpos="notext" data-inline="true">Scenes</button>';
|
||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="chaptersFlyout" style="display:none;" class="mediaPlayerFlyout chaptersFlyout"></div></div>';
|
||||
|
||||
footerHtml += '<button onclick="MediaPlayer.toggleFullscreen();" id="fullscreenButton" class="mediaButton fullscreenButton" title="Fullscreen" type="button" data-icon="action" data-iconpos="notext" data-inline="true">Fullscreen</button>';
|
||||
footerHtml += '<button onclick="MediaController.toggleFullscreen();" id="fullscreenButton" class="mediaButton fullscreenButton" title="Fullscreen" type="button" data-icon="action" data-iconpos="notext" data-inline="true">Fullscreen</button>';
|
||||
|
||||
footerHtml += '</div>';
|
||||
|
||||
|
@ -1386,6 +1386,10 @@ $(function () {
|
|||
ApiClient.closeWebSocket();
|
||||
}
|
||||
});
|
||||
|
||||
$("body").on("create", function () {
|
||||
$(".lazy").unveil(200);
|
||||
});
|
||||
});
|
||||
|
||||
Dashboard.jQueryMobileInit();
|
||||
|
@ -1428,4 +1432,3 @@ $(document).on('pagebeforeshow', ".page", function () {
|
|||
Dashboard.refreshSystemInfoFromServer();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
context: 'tv',
|
||||
showTitle: true,
|
||||
showItemCounts: true,
|
||||
coverImage: true
|
||||
coverImage: true,
|
||||
lazy: true
|
||||
});
|
||||
|
||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false);
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
items: result.Items,
|
||||
shape: "backdrop",
|
||||
preferThumb: true,
|
||||
context: 'tv'
|
||||
context: 'tv',
|
||||
lazy: true
|
||||
});
|
||||
|
||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||
|
@ -45,7 +46,8 @@
|
|||
items: result.Items,
|
||||
shape: "banner",
|
||||
preferBanner: true,
|
||||
context: 'tv'
|
||||
context: 'tv',
|
||||
lazy: true
|
||||
});
|
||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||
}
|
||||
|
@ -56,7 +58,8 @@
|
|||
shape: "portrait",
|
||||
context: 'tv',
|
||||
showTitle: true,
|
||||
centerText: true
|
||||
centerText: true,
|
||||
lazy: true
|
||||
});
|
||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||
}
|
||||
|
@ -67,7 +70,8 @@
|
|||
shape: "portrait",
|
||||
context: 'tv',
|
||||
timeline: true,
|
||||
showTitle: true
|
||||
showTitle: true,
|
||||
lazy: true
|
||||
});
|
||||
|
||||
$('.itemsContainer', page).addClass('timelineItemsContainer');
|
||||
|
|
4
dashboard-ui/thirdparty/jquery.ba-tinypubsub.min.js
vendored
Normal file
4
dashboard-ui/thirdparty/jquery.ba-tinypubsub.min.js
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
|
||||
* http://benalman.com/
|
||||
* Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */
|
||||
(function (a) { var b = a({}); a.subscribe = function () { b.on.apply(b, arguments) }, a.unsubscribe = function () { b.off.apply(b, arguments) }, a.publish = function () { b.trigger.apply(b, arguments) } })(jQuery)
|
62
dashboard-ui/thirdparty/jquery.unveil-custom.js
vendored
Normal file
62
dashboard-ui/thirdparty/jquery.unveil-custom.js
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* jQuery Unveil
|
||||
* A very lightweight jQuery plugin to lazy load images
|
||||
* http://luis-almeida.github.com/unveil
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
* Copyright 2013 Luís Almeida
|
||||
* https://github.com/luis-almeida
|
||||
*/
|
||||
|
||||
; (function ($) {
|
||||
|
||||
$.fn.unveil = function (threshold, callback) {
|
||||
|
||||
var $w = $(window),
|
||||
th = threshold || 0,
|
||||
retina = window.devicePixelRatio > 1,
|
||||
attrib = retina ? "data-src-retina" : "data-src",
|
||||
images = this,
|
||||
loaded;
|
||||
|
||||
this.one("unveil", function () {
|
||||
var elemType = $(this).get(0).tagName;
|
||||
var source = this.getAttribute(attrib);
|
||||
source = source || this.getAttribute("data-src");
|
||||
if (source) {
|
||||
if (elemType === "DIV") {
|
||||
this.style.backgroundImage = "url('" + source + "')";
|
||||
} else {
|
||||
this.setAttribute("src", source);
|
||||
}
|
||||
if (typeof callback === "function") callback.call(this);
|
||||
}
|
||||
});
|
||||
|
||||
function unveil() {
|
||||
var inview = images.filter(function () {
|
||||
var $e = $(this);
|
||||
if ($e.is(":hidden")) return;
|
||||
|
||||
var wt = $w.scrollTop(),
|
||||
wb = wt + $w.height(),
|
||||
et = $e.offset().top,
|
||||
eb = et + $e.height();
|
||||
|
||||
return eb >= wt - th && et <= wb + th;
|
||||
});
|
||||
|
||||
loaded = inview.trigger("unveil");
|
||||
images = images.not(loaded);
|
||||
}
|
||||
|
||||
$w.scroll(unveil);
|
||||
$w.resize(unveil);
|
||||
|
||||
unveil();
|
||||
|
||||
return this;
|
||||
|
||||
};
|
||||
|
||||
})(window.jQuery || window.Zepto);
|
Loading…
Add table
Add a link
Reference in a new issue