'use strict'; pandora.ui.infoView = function(data, isMixed) { isMixed = isMixed || {}; // fixme: given that currently, the info view doesn't scroll into view nicely // when collapsing the movies browser, the info view should become a split panel var ui = pandora.user.ui, isMultiple = arguments.length == 2, canEdit = pandora.hasCapability('canEditMetadata') || isMultiple || data.editable, canRemove = pandora.hasCapability('canRemoveItems'), canSeeAllMetadata = pandora.user.level != 'guest' && !isMultiple, css = { marginTop: '4px', textAlign: 'justify' }, iconRatio = ui.icons == 'posters' ? ( ui.showSitePosters ? pandora.site.posters.ratio : data.posterRatio ) : 1, iconSize = isMultiple ? 0 : ui.infoIconSize, iconWidth = isMultiple ? 0 : iconRatio > 1 ? iconSize : Math.round(iconSize * iconRatio), iconHeight = iconRatio < 1 ? iconSize : Math.round(iconSize / iconRatio), iconLeft = iconSize == 256 ? Math.floor((iconSize - iconWidth) / 2) : 0, borderRadius = ui.icons == 'posters' ? 0 : iconSize / 8, isEditable = canEdit && (isMultiple ? !ui.listSelection.some(function(id) { return id.slice(0, 2) != '0x' }) : data.id.slice(0, 2) == '0x' ), listWidth = 144 + Ox.UI.SCROLLBAR_SIZE, margin = 16, statisticsWidth = 128, $bar = Ox.Bar({size: 16}) .bindEvent({ doubleclick: function(e) { if ($(e.target).is('.OxBar')) { $data.animate({scrollTop: 0}, 250); } } }), $options = Ox.MenuButton({ items: [ { id: 'update', title: Ox._('Update Metadata'), disabled: !canEdit || isEditable }, {}, { id: 'delete', title: Ox._('Delete {0}...', [pandora.site.itemName.singular]), disabled: !canRemove } ], style: 'square', title: 'set', tooltip: Ox._('Options'), type: 'image', }) .css({ float: 'left', borderColor: 'rgba(0, 0, 0, 0)', background: 'rgba(0, 0, 0, 0)' }) .bindEvent({ click: function(data_) { if (data_.id == 'update') { updateMetadata(); } else if (data_.id == 'delete') { pandora.$ui.deleteItemsDialog = pandora.ui.deleteItemsDialog({ items: [data] }).open(); } } }) .appendTo($bar), $edit = Ox.MenuButton({ items: [ { id: 'insert', title: Ox._('Insert HTML...'), disabled: true } ], style: 'square', title: 'edit', tooltip: Ox._('Edit'), type: 'image', }) .css({ float: 'right', borderColor: 'rgba(0, 0, 0, 0)', background: 'rgba(0, 0, 0, 0)' }) .bindEvent({ click: function(data) { // ... } }) .appendTo($bar), $main = Ox.Element(), that = Ox.SplitPanel({ elements: [ {element: $bar, size: isMultiple ? 0 : 16}, {element: $main} ], orientation: 'vertical' }), $list, $info = $('
') .css({ position: 'absolute', left: canEdit && !ui.showIconBrowser ? -listWidth + 'px' : 0, top: 0, right: 0 }) .appendTo($main), $data = Ox.Container() .css({ position: 'absolute', left: (canEdit ? listWidth : 0) + 'px', top: 0, right: 0, height: getHeight() + 'px' }) .appendTo($info); if (!isMultiple) { var $icon = Ox.Element({ element: '', tooltip: canEdit ? ( !ui.showIconBrowser ? Ox._('Doubleclick to edit icon') : Ox._('Doubleclick to hide icons') ) : '' }) .attr({ src: pandora.getMediaURL('/' + data.id + '/' + ( ui.icons == 'posters' ? (ui.showSitePosters ? 'siteposter' : 'poster') : 'icon' ) + '512.jpg?' + data.modified) }) .css({ position: 'absolute', left: margin + iconLeft + 'px', top: margin + 'px', width: iconWidth + 'px', height: iconHeight + 'px', borderRadius: borderRadius + 'px', cursor: 'pointer' }) .bindEvent({ singleclick: toggleIconSize }) .appendTo($data.$element), $reflection = $('
') .addClass('OxReflection') .css({ position: 'absolute', left: margin + 'px', top: margin + iconHeight + 'px', width: iconSize + 'px', height: Math.round(iconSize / 2) + 'px', overflow: 'hidden' }) .appendTo($data.$element), $reflectionIcon = $('') .attr({ src: pandora.getMediaURL('/' + data.id + '/' + ( ui.icons == 'posters' ? (ui.showSitePosters ? 'siteposter' : 'poster') : 'icon' ) + '512.jpg?' + data.modified) }) .css({ position: 'absolute', left: iconLeft + 'px', width: iconWidth + 'px', height: iconHeight + 'px', borderRadius: borderRadius + 'px' }) .appendTo($reflection), $reflectionGradient = $('
') .css({ position: 'absolute', width: iconSize + 'px', height: Math.round(iconSize / 2) + 'px' }) .appendTo($reflection); } var $text = Ox.Element() .addClass('OxTextPage') .css({ position: 'absolute', left: margin + (iconSize == 256 ? 256 : iconWidth) + margin + 'px', top: margin + 'px', right: margin + statisticsWidth + margin + 'px' }) .appendTo($data.$element), $statistics = $('
') .css({ position: 'absolute', width: statisticsWidth + 'px', top: margin + 'px', right: margin + 'px' }) .appendTo($data.$element), $reloadButton, $capabilities, $browserImages = []; [$options, $edit].forEach(function($element) { $element.find('input').css({ borderWidth: 0, borderRadius: 0, padding: '3px' }); }); pandora.createLinks($text); // Title ------------------------------------------------------------------- if (!isMultiple) { $('
') .css({ marginTop: '-2px' }) .append( Ox.EditableContent({ clickLink: pandora.clickLink, editable: isEditable, format: function(value) { return formatTitle(value); }, tooltip: isEditable ? pandora.getEditTooltip() : '', value: data.title }) .css({ marginBottom: '-3px', fontWeight: 'bold', fontSize: '13px' }) .bindEvent({ submit: function(event) { editMetadata('title', event.value); } }) ) .appendTo($text); } // Director ---------------------------------------------------------------- if (data.director || isEditable) { $('
') .css({ marginTop: '2px' }) .append( Ox.EditableContent({ clickLink: pandora.clickLink, editable: isEditable, format: function(value) { return formatValue(value.split(', '), 'name'); }, placeholder: formatLight(Ox._(isMixed.director ? 'Mixed Director' : 'Unknown Director')), tooltip: isEditable ? pandora.getEditTooltip() : '', value: data.director ? data.director.join(', ') : '' }) .css({ marginBottom: '-3px', fontWeight: 'bold', fontSize: '13px' }) .bindEvent({ submit: function(event) { editMetadata('director', event.value); } }) ) .appendTo($text); } // Country, Year, Language, Runtime, Color, Sound -------------------------- if (isEditable) { var $div = $('
') .addClass('OxSelectable') .css(css) .appendTo($text); ['country', 'year'].forEach(function(key, i) { i && $('
').css({float: 'left'}).html('; ').appendTo($div); $('
') .css({float: 'left'}) .html(formatKey(key).replace('', ' ')) .appendTo($div); Ox.EditableContent({ clickLink: pandora.clickLink, format: function(value) { return formatValue(value.split(', '), key) }, placeholder: formatLight(isMixed[key] ? 'mixed' : 'unknown'), tooltip: pandora.getEditTooltip(), value: key == 'country' ? (data[key] ? data[key].join(', ') : ['']) : data[key] || '' }) .css({float: 'left'}) .bindEvent({ submit: function(event) { editMetadata(key, event.value); } }) .appendTo($div); }); } else if (!isMultiple && (data.country || data.year || data.language || data.runtime || data.color || data.sound)) { var html = []; ['country', 'year', 'language', 'runtime', 'color', 'sound'].forEach(function(key) { if (data[key]) { html.push( formatKey(key) + ( key != 'runtime' ? formatValue(data[key], key) : data[key] < 60 ? Math.round(data[key]) + ' sec' : Math.round(data[key] / 60) + ' min' ) ) } }); $('
') .addClass('OxSelectable') .css(css) .html(html.join('; ')) .appendTo($text); } // Alternative Titles ------------------------------------------------------ // FIXME: This should be an array of objects {title: '', info: ''} data.alternativeTitles && $('
') .addClass('OxSelectable') .css(css) .html( formatKey('Alternative Title' + (data.alternativeTitles.length == 1 ? '' : 's')) + data.alternativeTitles.map(function(value) { return value[0] + ( canSeeAllMetadata && Ox.isArray(value[1]) && value[1].length ? ' ' + formatLight('(' + value[1].join(', ') + ')') : '' ); }).join(', ') ) .appendTo($text); // FIXME: we will want to check for data.seriesId here if (isEditable && data.seriesTitle) { var $div = $('
') .addClass('OxSelectable') // FIXME: Don't extend! .css(Ox.extend(css, {marginTop: '20px'})) // FIXME: just a guess .appendTo($text); ['episodeDirector', 'seriesYear'].forEach(function(key, i) { i && $('
').css({float: 'left'}).html('; ').appendTo($div); $('
') .css({float: 'left'}) .html(formatKey(Ox.toUnderscores(key).replace(/_/g, ' ')).replace('', ' ')) .appendTo($div); Ox.Editable({ clickLink: pandora.clickLink, format: function(value) { return formatValue( value.split(', '), key == 'episodeDirector' ? 'name' : 'year' ); }, placeholder: formatLight(Ox._(isMixed[key] ? 'mixed' : 'unknown')), tooltip: pandora.getEditTooltip(), value: key == 'episodeDirector' ? (data[key] ? data[key].join(', ') : ['']) : data[key] || '' }) .css({float: 'left'}) .bindEvent({ submit: function(event) { editMetadata(key, event.value); } }) .appendTo($div); }); } else if (!isMultiple && (data.episodeDirector || data.writer || data.producer || data.cinematographer || data.editor)) { $div = $('
') .addClass('OxSelectable') .css(css) .appendTo($text); html = []; ['episodeDirector', 'writer', 'producer', 'cinematographer', 'editor'].forEach(function(key) { data[key] && html.push( formatKey(key == 'episodeDirector' ? 'director' : key) + formatValue(data[key], 'name') ); }); $div.html(html.join('; ')); } data.cast && $('
') .addClass('OxSelectable') .css(css) .html( formatKey('cast') + data.cast.map(function(value) { // FIXME: 'uncredited' should be removed on the backend value.character = value.character.replace('(uncredited)', '').trim(); return formatValue(value.actor, 'name') + ( canSeeAllMetadata && value.character ? ' ' + formatLight('(' + value.character + ')') : '' ); }).join(', ') ) .appendTo($text); if (data.productionCompany && canSeeAllMetadata) { $('
') .addClass('OxSelectable') .css(css) .html( formatKey('studio') + formatValue(data.productionCompany, 'productionCompany') ) .appendTo($text); } if (!isMultiple && (data.genre || (data.keyword && canSeeAllMetadata))) { $div = $('
') .addClass('OxSelectable') .css(css) .appendTo($text); html = []; (canSeeAllMetadata ? ['genre', 'keyword'] : ['genre']).forEach(function(key) { data[key] && html.push( formatKey(key == 'keyword' ? 'keywords' : key) + formatValue(data[key], key) ); }); $div.html(html.join('; ')); } data.summary && $('
') .addClass('OxSelectable') .css(css) .html(formatKey('summary') + data.summary) .appendTo($text); if (!isMultiple && canSeeAllMetadata) { data.trivia && data.trivia.forEach(function(value) { $('
') .css({ display: 'table-row' }) .append( $('
') .css({ display: 'table-cell', width: '12px', paddingTop: '4px' }) .html('') ) .append( $('
') .addClass('OxSelectable') .css({ display: 'table-cell', paddingTop: '4px', textAlign: 'justify' }) .html(value) ) .append( $('
').css({clear: 'both'}) ) .appendTo($text); }); data.filmingLocations && $('
') .addClass('OxSelectable') .css(css) .html( formatKey(Ox._('Filming Locations')) + data.filmingLocations.map(function(location) { return '' + location + '' }).join('; ') ) .appendTo($text); data.releasedate && $('
') .addClass('OxSelectable') .css(css) .html( formatKey(Ox._('Release Date')) + Ox.formatDate(data.releasedate, '%A, %B %e, %Y') ) .appendTo($text); if (data.budget || data.gross || data.profit) { $div = $('
') .addClass('OxSelectable') .css(css) .appendTo($text); html = []; ['budget', 'gross', 'profit'].forEach(function(key) { data[key] && html.push( formatKey(key == 'profit' && data[key] < 0 ? 'loss' : key) + Ox.formatCurrency(Math.abs(data[key]), '$') ); }); $div.html(html.join('; ')); } if (data.connections) { $div = $('
') .addClass('OxSelectable') .css(css) .appendTo($text); html = []; [ 'Edited from', 'Edited into', 'Features', 'Featured in', 'Follows', 'Followed by', 'References', 'Referenced in', 'Remake of', 'Remade as', 'Spin off from', 'Spin off', 'Spoofs', 'Spoofed in' ].forEach(function(key) { data.connections[key] && html.push( formatKey(key) + data.connections[key].map(function(connection) { return ( connection.item ? '' + connection.title + '' : connection.title ) + ( connection.description ? ' ' + formatLight('(' + connection.description + ')') : '' ); }).join(', ') ); }); $div.html(html.join('; ')); } } ['reviews', 'links'].forEach(function(key) { data[key] && $('
') .addClass('OxSelectable') .css(css) .html( formatKey(key) + data[key].map(function(value) { return '' + value.source + '' }).join(', ') ) .appendTo($text); }); $('
').css({height: '16px'}).appendTo($text); // Mainstream Score, Arthouse Score ---------------------------------------- if (!isMultiple) { ['votes', 'likes'].forEach(function(key) { var value = data[key] || 0; $('
') .css({marginBottom: '4px'}) .append( formatKey( key == 'votes' ? 'Mainstream Score' : 'Arthouse Score', 'statistics' ) ) .append( Ox.Theme.formatColorPercent(value, 1, true) .css({textAlign: 'right', cursor: 'pointer'}) .bind({ click: function() { pandora.UI.set({listSort: [{ key: key, operator: pandora.getSortOperator(key) }]}); } }) ) .appendTo($statistics); }); // Duration, Aspect Ratio -------------------------------------------------- ['duration', 'aspectratio'].forEach(function(key) { var itemKey = Ox.getObjectById(pandora.site.itemKeys, key), value = data[key] || 0; $('
') .css({marginBottom: '4px'}) .append(formatKey(itemKey.title, 'statistics')) .append( Ox.Theme.formatColor(null, 'gradient') .css({textAlign: 'right', cursor: 'pointer'}) .html( Ox['format' + Ox.toTitleCase(itemKey.format.type)] .apply(null, [value].concat(itemKey.format.args)) ) .bind({ click: function() { pandora.UI.set({listSort: [{ key: key, operator: pandora.getSortOperator(key) }]}); } }) ) .appendTo($statistics); }); // Hue, Saturation, Lightness, Volume -------------------------------------- ['hue', 'saturation', 'lightness', 'volume'].forEach(function(key) { var value = data[key] || 0; $('
') .css({marginBottom: '4px'}) .append(formatKey(key, 'statistics')) .append( Ox.Theme.formatColor(value, key == 'volume' ? 'lightness' : key) .css({textAlign: 'right', cursor: 'pointer'}) .bind({ click: function() { pandora.UI.set({listSort: [{ key: key, operator: pandora.getSortOperator(key) }]}); } }) ) .appendTo($statistics); }); // Cuts per Minute, Words per Minute --------------------------------------- ['cutsperminute', 'wordsperminute'].forEach(function(key) { var value = data[key] || 0; $('
') .css({marginBottom: '4px'}) .append( formatKey(key.slice(0, -9) + ' per minute', 'statistics') ) .append( Ox.Theme.formatColor(null, 'gradient') .css({textAlign: 'right', cursor: 'pointer'}) .html(Ox.formatNumber(value, 3)) .bind({ click: function() { pandora.UI.set({listSort: [{ key: key, operator: pandora.getSortOperator(key) }]}); } }) ) .appendTo($statistics); }); } // Rights Level ------------------------------------------------------------ var $rightsLevel = $('
'); $('
') .css({marginBottom: '4px'}) .append(formatKey('Rights Level', 'statistics')) .append($rightsLevel) .appendTo($statistics); renderRightsLevel(); // Notes ------------------------------------------------------------------- if (canEdit) { $('
') .css({marginBottom: '4px'}) .append(formatKey('Notes', 'statistics')) .append( Ox.EditableContent({ clickLink: pandora.clickLink, placeholder: formatLight(Ox._(isMixed.notes ? 'Mixed notes' : 'No notes')), tooltip: pandora.getEditTooltip(), type: 'textarea', value: data.notes || '', width: 128 }) .bindEvent({ submit: function(event) { editMetadata('notes', event.value); } }) ) .appendTo($statistics); } $('
').css({height: '16px'}).appendTo($statistics); if (canEdit && !isMultiple) { $icon.bindEvent({ doubleclick: function() { pandora.UI.set({showIconBrowser: !ui.showIconBrowser}); $info.animate({ left: ui.showIconBrowser ? 0 : -listWidth + 'px' }, 250); $icon.options({ tooltip: !ui.showIconBrowser ? 'Doubleclick to edit icon' : 'Doubleclick to hide icons' }); } }); renderList(); } function editMetadata(key, value) { if (value != data[key]) { var edit = {id: isMultiple ? ui.listSelection : data.id}; if (key == 'title') { Ox.extend(edit, parseTitle(value)); } else if (['director', 'country'].indexOf(key) > -1) { edit[key] = value ? value.split(', ') : []; } else { edit[key] = value; } pandora.api.edit(edit, function(result) { if (!isMultiple) { if (result.data.id != data.id) { Ox.Request.clearCache(); // fixme: too much pandora.UI.set({item: result.data.id}); pandora.$ui.browser.value(data.id, 'id', result.data.id); // FIXME: does this update selected? } pandora.updateItemContext(); pandora.$ui.browser.value(result.data.id, key, result.data[key]); } that.triggerEvent('change', Ox.extend({}, key, value)); }); } } function formatKey(key, mode) { var item = Ox.getObjectById(pandora.site.itemKeys, key); key = Ox._(item ? item.title : key); mode = mode || 'text'; return mode == 'text' ? '' + Ox._(Ox.toTitleCase(key)) + ': ' : $('
').css({marginBottom: '4px', fontWeight: 'bold'}) .html(Ox._(Ox.toTitleCase(key).replace(' Per ', ' per '))) } function formatLight(str) { return '' + str + ''; } function formatTitle(title) { var match = /(.+) (\(S\d{2}(E\d{2})?\))/.exec(title); if (match) { title = formatValue(match[1], 'title') + ' ' + formatLight(match[2]) + title.substr(match[0].length); } return title + ( data.originalTitle && data.originalTitle != title ? ' ' + formatLight('(' + data.originalTitle + ')') : '' ); } function formatValue(value, key) { return (Ox.isArray(value) ? value : [value]).map(function(value) { return key ? '' + value + '' : value; }).join(', '); } function getHeight() { return pandora.$ui.contentPanel.size(1) - 16; } function getRightsLevelElement(rightsLevel) { return Ox.Theme.formatColorLevel( rightsLevel, pandora.site.rightsLevels.map(function(rightsLevel) { return rightsLevel.name; }) ); } function parseTitle(title) { var data = {title: title}, match = /(\(S(\d{2})E(\d{2})\))/.exec(title), episodeMatch = /(.+) \(S01\) (.+)/.exec(title), split; if (match) { data.season = parseInt(match[2], 10); data.episode = parseInt(match[3], 10); split = title.split(match[1]); data.seriesTitle = split[0].trim(); data.episodeTitle = split[1].trim(); } else if (episodeMatch) { data.seriesTitle = episodeMatch[1].trim(); data.episodeTitle = episodeMatch[2].trim(); data.season = 1; } return data; } function renderCapabilities(rightsLevel) { var capabilities = [].concat( canEdit ? [{name: 'canSeeItem', symbol: 'Find'}] : [], [ {name: 'canPlayClips', symbol: 'PlayInToOut'}, {name: 'canPlayVideo', symbol: 'Play'}, {name: 'canDownloadVideo', symbol: 'Download'} ] ), userLevels = canEdit ? pandora.site.userLevels : [pandora.user.level]; $capabilities.empty(); userLevels.forEach(function(userLevel, i) { var $element, $line = $('
') .css({ height: '16px', marginBottom: '4px' }) .appendTo($capabilities); if (canEdit) { $element = Ox.Theme.formatColorLevel(i, userLevels.map(function(userLevel) { return Ox.toTitleCase(userLevel); }), [0, 240]); Ox.Label({ textAlign: 'center', title: Ox.toTitleCase(userLevel), width: 60 }) .addClass('OxColor OxColorGradient') .css({ float: 'left', height: '12px', paddingTop: '2px', background: $element.css('background'), fontSize: '8px', color: $element.css('color') }) .data({OxColor: $element.data('OxColor')}) .appendTo($line); } capabilities.forEach(function(capability) { var hasCapability = pandora.hasCapability(capability.name, userLevel) >= rightsLevel, $element = Ox.Theme.formatColorLevel(hasCapability, ['', '']); Ox.Button({ tooltip: (canEdit ? Ox.toTitleCase(userLevel) : 'You') + ' ' + (hasCapability ? 'can' : 'can\'t') + ' ' + Ox.toSlashes(capability.name) .split('/').slice(1).join(' ') .toLowerCase() .replace('see item', 'see the item') .replace('play video', 'play the full video') .replace('download video', 'download the video'), title: capability.symbol, type: 'image' }) .addClass('OxColor OxColorGradient') .css({ background: $element.css('background'), cursor: hasCapability ? 'pointer' : 'default' }) .css('margin' + (canEdit ? 'Left' : 'Right'), '4px') .data({OxColor: $element.data('OxColor')}) .bindEvent({ click: function() { if (hasCapability) { if (capability.name == 'canSeeItem') { $data.animate({scrollTop: 0}, 250); } else if (capability.name == 'canPlayClips') { pandora.UI.set({itemView: 'clips'}); } else if (capability.name == 'canPlayVideo') { pandora.UI.set({itemView: ui.videoView}); } else if (capability.name == 'canDownloadVideo') { pandora.ui.downloadVideoDialog({ item: ui.item, rightsLevel: data.rightsLevel, title: data.title, video: data.video }).open(); } } } }) .appendTo($line); }); if (!canEdit) { Ox.Button({ title: 'Help', tooltip: Ox._('About Rights'), type: 'image' }) .css({marginLeft: '52px'}) .bindEvent({ click: function() { pandora.UI.set({page: 'rights'}); } }) .appendTo($line); } }); } function renderFrames() { pandora.api.get({ id: data.id, keys: ['frames'] }, 0, function(result) { var images = result.data.frames.map(function(image) { return Ox.extend(image, {index: image.index.toString()}); }), selectedImage = images.filter(function(image) { return image.selected; })[0], modified = data.modified; $list = Ox.IconList({ defaultRatio: !data.stream ? pandora.site.posters.ratio : data.stream.aspectratio, fixedRatio: !data.stream ? false : data.stream.aspectratio, item: function(data, sort, size) { var ratio = data.width / data.height; size = size || 128; return { height: ratio <= 1 ? size : size / ratio, id: data.id, info: data.width + ' × ' + data.height + ' px', title: Ox.formatDuration(data.position), url: data.url, width: ratio >= 1 ? size : size * ratio } }, items: images, keys: ['index', 'position', 'width', 'height', 'url'], max: 1, min: 1, orientation: 'both', // fixme: should never be undefined selected: selectedImage ? [selectedImage['index']] : [], size: 128, sort: [{key: 'index', operator: '+'}], unique: 'index' }) .addClass('OxMedia') .css({ display: 'block', position: 'absolute', left: 0, top: 0, width: listWidth + 'px', height: getHeight() + 'px' }) .bindEvent({ select: function(event) { var index = event.ids[0]; selectedImage = images.filter(function(image) { return image.index == index; })[0]; var imageRatio = selectedImage.width / selectedImage.height, src = selectedImage.url if ($browserImages.length == 0) { $browserImages = pandora.$ui.browser.find('img[src*="/' + data.id + '/"]'); } pandora.api.setPosterFrame({ id: data.id, // fixme: api slightly inconsistent, this shouldn't be "position" position: selectedImage.index }, function() { var src; Ox.Request.clearCache(); if (ui.icons == 'frames') { src = pandora.getMediaURL('/' + data.id + '/icon512.jpg?' + Ox.uid()); $icon.attr({src: src}); $reflectionIcon.attr({src: src}); if (pandora.$ui.videoPreview) { pandora.$ui.videoPreview.options({ position: $list.value(selectedImage.index, 'position') }); } } else if (ui.icons == 'posters' && ui.showSitePosters) { src = pandora.getMediaURL('/' + data.id + '/siteposter512.jpg?' + Ox.uid()); $icon.attr({src: src}); $reflectionIcon.attr({src: src}); } $browserImages.each(function() { $(this).attr({src: pandora.getMediaURL('/' + data.id + '/' + ( ui.icons == 'posters' ? ui.showSitePosters ? 'siteposter' : 'poster' : 'icon' ) + '128.jpg?' + Ox.uid())}); }); if (ui.listSort[0].key == 'modified') { pandora.$ui.browser.reloadList(); } }); } }) .appendTo($info); $list.size(); }); } function renderList() { if (ui.icons == 'posters' && !ui.showSitePosters) { renderPosters() } else { renderFrames() } } function renderPosters() { pandora.api.get({ id: data.id, keys: ['posters'] }, 0, function(result) { var images = result.data.posters.map(function(image) { return Ox.extend(image, {index: image.index.toString()}); }), selectedImage = images.filter(function(image) { return image.selected; })[0], modified = data.modified; if (images.length == 1) { renderFrames() return } $list = Ox.IconList({ defaultRatio: pandora.site.posters.ratio, fixedRatio: false, item: function(data, sort, size) { var ratio = data.width / data.height; size = size || 128; return { height: ratio <= 1 ? size : size / ratio, id: data.id, info: data.width + ' × ' + data.height + ' px', title: data.source, url: data.url.replace('http://', '//') + ( data.source == pandora.site.site.url ? '?' + modified : '' ), width: ratio >= 1 ? size : size * ratio } }, items: images, keys: ['index', 'source', 'width', 'height', 'url'], max: 1, min: 1, orientation: 'both', // fixme: should never be undefined selected: selectedImage ? [selectedImage['index']] : [], size: 128, sort: [{key: 'index', operator: '+'}], unique: 'index' }) .addClass('OxMedia') .css({ display: 'block', position: 'absolute', left: 0, top: 0, width: listWidth + 'px', height: getHeight() + 'px' }) .bindEvent({ select: function(event) { var index = event.ids[0]; selectedImage = images.filter(function(image) { return image.index == index; })[0]; var imageRatio = selectedImage.width / selectedImage.height, src = selectedImage.url.replace('http://', '//'); if ($browserImages.length == 0) { $browserImages = pandora.$ui.browser.find('img[src*="/' + data.id + '/"]'); } if (!ui.showSitePosters) { $browserImages.each(function() { var $this = $(this), size = Math.max($this.width(), $this.height()); $this.attr({src: src}); $this.css(imageRatio < 1 ? { width: Math.round(size * imageRatio) + 'px', height: size + 'px' } : { width: size + 'px', height: Math.round(size / imageRatio) + 'px' }); }); $icon.attr({src: src}); $reflectionIcon.attr({src: src}); iconRatio = imageRatio; iconSize = iconSize == 256 ? 512 : 256; toggleIconSize(); } pandora.api.setPoster({ id: data.id, source: selectedImage.source }, function() { var src; Ox.Request.clearCache(); if (!ui.showSitePosters) { $browserImages.each(function() { $(this).attr({ src: pandora.getMediaURL('/' + data.id + '/poster128.jpg?' + Ox.uid()) }); }); } if (ui.listSort[0].key == 'modified') { pandora.$ui.browser.reloadList(); } }); } }) .appendTo($info); $list.size(); }); } function renderRightsLevel() { var $rightsLevelElement = getRightsLevelElement(data.rightslevel), $rightsLevelSelect; $rightsLevel.empty(); if (canEdit) { $rightsLevelSelect = Ox.Select({ items: pandora.site.rightsLevels.map(function(rightsLevel, i) { return {id: i, title: rightsLevel.name}; }), width: 128, value: data.rightslevel }) .addClass('OxColor OxColorGradient') .css({ marginBottom: '4px', background: $rightsLevelElement.css('background') }) .data({OxColor: $rightsLevelElement.data('OxColor')}) .bindEvent({ change: function(event) { var rightsLevel = event.value; $rightsLevelElement = getRightsLevelElement(rightsLevel); $rightsLevelSelect .css({background: $rightsLevelElement.css('background')}) .data({OxColor: $rightsLevelElement.data('OxColor')}) renderCapabilities(rightsLevel); var edit = { id: isMultiple ? ui.listSelection : data.id, rightslevel: rightsLevel }; pandora.api.edit(edit, function(result) { that.triggerEvent('change', Ox.extend({}, 'rightslevel', rightsLevel)); }); } }) .appendTo($rightsLevel); } else { $rightsLevelElement .css({ marginBottom: '4px', cursor: 'pointer' }) .bind({ click: function() { pandora.UI.set({listSort: [{ key: 'rightslevel', operator: pandora.getSortOperator('rightslevel') }]}); } }) .appendTo($rightsLevel); } $capabilities = $('
').appendTo($rightsLevel); renderCapabilities(data.rightslevel); } function toggleIconSize() { iconSize = iconSize == 256 ? 512 : 256; iconWidth = iconRatio > 1 ? iconSize : Math.round(iconSize * iconRatio); iconHeight = iconRatio < 1 ? iconSize : Math.round(iconSize / iconRatio); iconLeft = iconSize == 256 ? Math.floor((iconSize - iconWidth) / 2) : 0, borderRadius = ui.icons == 'posters' ? 0 : iconSize / 8; $icon.animate({ left: margin + iconLeft + 'px', width: iconWidth + 'px', height: iconHeight + 'px', borderRadius: borderRadius + 'px' }, 250); $reflection.animate({ top: margin + iconHeight + 'px', width: iconSize + 'px', height: iconSize / 2 + 'px' }, 250); $reflectionIcon.animate({ left: iconLeft + 'px', width: iconWidth + 'px', height: iconHeight + 'px', borderRadius: borderRadius + 'px' }, 250); $reflectionGradient.animate({ width: iconSize + 'px', height: iconSize / 2 + 'px' }, 250); $text.animate({ left: margin + (iconSize == 256 ? 256 : iconWidth) + margin + 'px' }, 250); pandora.UI.set({infoIconSize: iconSize}); } function updateMetadata() { var item = ui.item; $options.disableItem('update'); // fixme: maybe there's a better method name for this? pandora.api.updateExternalData({ id: ui.item }, function(result) { (result.data.taskId ? pandora.wait : Ox.noop)(result.data.taskId, function(result) { pandora.updateItemContext(); Ox.Request.clearCache(); if (ui.item == item && ui.itemView == 'info') { pandora.$ui.contentPanel.replaceElement( 1, pandora.$ui.item = pandora.ui.item() ); } $options.enableItem('update'); }); }); } that.reload = function() { var src = pandora.getMediaURL('/' + data.id + '/' + ( ui.icons == 'posters' ? (ui.showSitePosters ? 'siteposter' : 'poster') : 'icon' ) + '512.jpg?' + Ox.uid()) $icon.attr({src: src}); $reflectionIcon.attr({src: src}); iconSize = iconSize == 256 ? 512 : 256; iconRatio = ui.icons == 'posters' ? (ui.showSitePosters ? pandora.site.posters.ratio : data.posterRatio) : 1; toggleIconSize(); pandora.user.level == 'admin' && $list.replaceWith($list = renderList()); }; that.resizeElement = function() { var height = getHeight() + 'px'; $data.css({height: height}); $list && $list.css({height: height}); }; that.bindEvent({ mousedown: function() { setTimeout(function() { !Ox.Focus.focusedElementIsInput() && that.gainFocus(); }); }, pandora_icons: that.reload, pandora_showsiteposters: function() { ui.icons == 'posters' && that.reload(); } }); return that; };