blob: 87ed9a3ff70e3919b9e59c12fa42b6dffd730c34 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
/*
* The User Interface for the Albums & MediaItems gadget.
*
* SHINDIG TODOS
* set ownerId automatically?
* delete children mediaitems when album deleted?
* update only updates given fields?
* update album mediaitem count when inserting/removing mediaitem?
*
* GADGET TODOS
* album info such as how many albums are contained
* fix auto height for edit album popup
* thumnail pictures
*/
function MediaUI(social) {
var viewer = null;
var divManager = null;
var folderUrl = 'http://www.clker.com/cliparts/2/b/b/3/1194983972976950993blue_folder_seth_yastrov_01.svg.med.png';
var docUrl = 'http://www.plastyc.com/images/document-icon.png';
/*
* Initializes the gadget.
*/
this.init = function() {
console.log('initializing AlbumsUI');
// Manages high-level divs
divManager = new DivManager();
divManager.init();
// Load data and render
loadData(function() {
social.getAlbumsByUser(viewer.id, function(response) {
renderAlbums(response.list);
divManager.showAlbums();
});
});
}
/*
* Pre-load data for gadget.
*/
function loadData(callback) {
social.getViewer(function(data) {
viewer = data;
callback();
});
}
/*
* Manages the gadgets main DIV elements.
*
* TODO: use dojo.query() & classes rather than divs[]
* TODO: showOnly() function to avoid flashing/pauses
*/
function DivManager() {
var divs = [];
this.init = function() {
console.log('DivManager.init');
addDiv('albumsDiv');
addDiv('mediaItemsDiv');
addDiv('mediaItemDiv');
hideAll();
}
this.showAlbums = function() {
console.log('DivManager.showAlbums');
hideAll();
divs['albumsDiv'].style.display = 'block';
this.refreshWindow();
}
this.showMediaItems = function() {
console.log('DivManager.showMediaItems');
hideAll();
divs['mediaItemsDiv'].style.display = 'block';
this.refreshWindow();
}
this.showMediaItem = function() {
console.log('DivManager.showMediaItem');
hideAll();
divs['mediaItemDiv'].style.display = 'block';
this.refreshWindow();
}
this.refreshWindow = function() {
gadgets.window.adjustHeight(500);
}
function hideAll() {
for (key in divs) { divs[key].style.display = 'none'; }
}
function addDiv(id) { divs[id] = dojo.create('div', {id: id}, dojo.body()); }
}
/*
* Renders a list of the given albums.
*/
function renderAlbums(albums) {
console.log('renderAlbums');
dojo.empty('albumsDiv');
var albumsDiv = dojo.byId('albumsDiv');
var albumsBanner = dojo.create('div', null, albumsDiv);
var table = dojo.create('table', null, albumsBanner);
var tbody = dojo.create('tbody', null, table);
var tr = dojo.create('tr', null, tbody);
dojo.create('td', {innerHTML: viewer.name.formatted + "'s Albums", className: 'albumsTitle'}, tr);
dojo.create('td', null, tr).appendChild(new dijit.form.Button({label: '+ New Album', onClick: dojo.hitch(this, editAlbumPopup, null)}).domNode);
var albumsList = dojo.create('div', null, albumsDiv);
if (albums.length > 0) {
var table = dojo.create('table', {className: 'albumsTable'}, albumsList);
var tbody = dojo.create('tbody', null, table);
for (i = 0; i < albums.length; i++) {
var albumRow = dojo.create('tr', null, tbody);
var albumLeft = dojo.create('td', {className: 'albumListThumbnail'}, albumRow);
var imgLink = dojo.create('a', {href: 'javascript:;', onclick: dojo.hitch(this, onClickAlbum, viewer.id, albums[i])}, albumLeft);
dojo.create('img', {src: albums[i].thumbnailUrl || folderUrl, onerror: "this.src='" + folderUrl + "';", width: '100', height:'100'}, imgLink);
var albumRight = dojo.create('td', {className: 'albumListRight'}, albumRow);
var albumTitleTbody = dojo.create('table', null, albumRight).appendChild(dojo.create('tbody', null));
var albumTitleRow = dojo.create('tr', null, albumTitleTbody);
var titleTd = dojo.create('td', {className: 'albumListTitle'}, albumTitleRow);
dojo.create('a', {innerHTML: albums[i].title, href: 'javascript:;', onclick: dojo.hitch(this, onClickAlbum, viewer.id, albums[i])}, titleTd);
var editTd = dojo.create('td', {className: 'actionLinks'}, albumTitleRow);
editTd.style.textAlign="right";
dojo.create('a', {innerHTML: 'edit', href: 'javascript:;', onclick: dojo.hitch(this, editAlbumPopup, albums[i])}, editTd);
editTd.appendChild(dojo.doc.createTextNode(' | '));
dojo.create('a', {innerHTML: 'delete', href: 'javascript:;', onclick: dojo.hitch(this, deleteAlbumPopup, albums[i])}, editTd);
if (albums[i].description) {
var albumDescription = dojo.create('tr', null, albumTitleTbody);
dojo.create('td', {innerHTML: albums[i].description, className: 'albumListDescription', colSpan: '2'}, albumDescription);
}
//var albumInfo = dojo.create('tr', null, albumRight);
//var infoStr = "ID: " + albums[i].id + " | Owner ID: " + albums[i].ownerId;
//dojo.create('td', {innerHTML: infoStr, className: 'albumListInfo', colspan: '2'}, albumInfo);
}
} else {
albumsDiv.appendChild(dojo.doc.createTextNode('No albums found.'));
}
divManager.refreshWindow();
// Handles when user clicks an album
function onClickAlbum(userId, album) {
social.getMediaItemsByAlbum(userId, album.id, function(response) {
renderMediaItems(album, response.list);
divManager.showMediaItems();
});
}
}
/*
* Convenience function to retrieve albums and render.
*/
function renderAlbumsByUser(userId, callback) {
social.getAlbumsByUser(userId, function(response) {
renderAlbums(response.list);
divManager.showAlbums();
if (callback != null) callback();
});
}
/*
* Renders a grid of the given MediaItems.
*
* TODO: simplify this by simply taking in 'album', retrieving MediaItems here
*/
function renderMediaItems(album, mediaItems) {
console.log('renderMediaItems');
dojo.empty('mediaItemsDiv');
var mediaItemsDiv = dojo.byId('mediaItemsDiv');
var numCols = 5;
// Div to display navation bar and Create button
var topDiv = dojo.create('div', null, mediaItemsDiv);
var table = dojo.create('table', null, topDiv);
var tbody = dojo.create('tbody', null, table);
var tr = dojo.create('tr', null, tbody);
var td = dojo.create('td', {style: 'width:100%'}, tr);
dojo.create('a', {innerHTML: 'Albums', href: 'javascript:;', onclick: dojo.hitch(this, renderAlbumsByUser, viewer.id, null)}, td);
td.appendChild(dojo.doc.createTextNode(' > ' + album.title));
td = dojo.create('td', {style: 'width:100%'}, tr);
var createButton = new dijit.form.Button({label: '+ New MediaItem', onClick: dojo.hitch(this, editMediaItemPopup, album, null)});
td.appendChild(createButton.domNode);
// Div to display MediaItems in a grid
var gridDiv = dojo.create('div', null, mediaItemsDiv);
if (mediaItems.length > 0) {
var table = dojo.create('table', null, gridDiv);
var tbody = dojo.create('tbody', null, table);
var tr = null;
for (i = 0; i < mediaItems.length; i++) {
if (i % numCols == 0) {
tr = dojo.create('tr', null, tbody);
}
var td = dojo.create('td', {className: 'mediaItemBox'}, tr);
var imageTbody = dojo.create('table', null, td).appendChild(dojo.create('tbody', null));
var imageTd = dojo.create('tr', null, imageTbody).appendChild(dojo.create('td', {className: 'mediaItemThumbnail'}));
if (mediaItems[i].url) {
var imageLink = dojo.create('a', {href: 'javascript:;', onclick: dojo.hitch(this, renderMediaItem, album, mediaItems[i])}, imageTd);
imageLink.appendChild(dojo.create('img', {src: mediaItems[i].thumbnailUrl, height: '100', width:'100'}));
} else {
dojo.create('img', {src: mediaItems[i].thumbnailUrl, onerror: "this.src='" + docUrl + "';", height:'100', width:'100'}, imageTd);
}
var titleTbody = dojo.create('table', null, td).appendChild(dojo.create('tbody', null));
var titleTd = dojo.create('tr', null, titleTbody).appendChild(dojo.create('td', {style: "text-align:center; font-family:'comic sans ms';white-space:nowrap;"}));
titleTd.appendChild(dojo.doc.createTextNode(mediaItems[i].title));
var actionsTbody = dojo.create('table', null, td).appendChild(dojo.create('tbody', null));
var actionsTd = dojo.create('tr', null, actionsTbody).appendChild(dojo.create('td', {className: 'actionLinks', style: 'text-align: center;'}));
dojo.create('a', {innerHTML: 'edit', href: 'javascript:;', onclick: dojo.hitch(this, editMediaItemPopup, album, mediaItems[i])}, actionsTd);
actionsTd.appendChild(dojo.doc.createTextNode(' | '));
dojo.create('a', {innerHTML: 'delete', href: 'javascript:;', onclick: dojo.hitch(this, deleteMediaItemPopup, album, mediaItems[i])}, actionsTd);
}
} else {
gridDiv.appendChild(dojo.doc.createTextNode('Album is empty'));
}
divManager.refreshWindow();
}
/*
* Convenience function to retriev & render MediaItems by Album.
*/
function retrieveAndRenderMediaItems(album) {
social.getMediaItemsByAlbum(viewer.id, album.id, function(response) {
divManager.showMediaItems();
renderMediaItems(album, response.list);
});
}
/*
* Renders the view for a single MediaItem.
*/
function renderMediaItem(album, mediaItem) {
console.log('renderMediaItem');
dojo.empty('mediaItemDiv');
var mediaItemDiv = dojo.byId('mediaItemDiv');
// Div to display navation bar and Create button
var topDiv = dojo.create('div', null, mediaItemDiv);
var table = dojo.create('table', null, topDiv);
var tbody = dojo.create('tbody', null, table);
var tr = dojo.create('tr', null, tbody);
var td = dojo.create('td', {style: 'width:100%'}, tr);
dojo.create('a', {innerHTML: 'Albums', href: 'javascript:;', onclick: dojo.hitch(this, renderAlbumsByUser, viewer.id, null)}, td);
td.appendChild(dojo.doc.createTextNode(' > '));
dojo.create('a', {innerHTML: album.title, href: 'javascript:;', onclick: dojo.hitch(this, retrieveAndRenderMediaItems, album)}, td);
td.appendChild(dojo.doc.createTextNode(' > ' + mediaItem.title));
// Div to show MediaItem
var itemDiv = dojo.create('div', null, mediaItemDiv);
var table = dojo.create('table', null, itemDiv);
var tbody = dojo.create('tbody', null, table);
var tr = dojo.create('tr', null, tbody);
var td = dojo.create('td', null, tr);
dojo.create('img', {src: mediaItem.url}, td);
if (mediaItem.description) {
tr = dojo.create('tr', null, tbody);
td = dojo.create('td', null, tr);
td.appendChild(dojo.doc.createTextNode(mediaItem.description));
}
divManager.showMediaItem();
}
/*
* Popup to edit album.
*/
function editAlbumPopup(album) {
console.log('editAlbumPopup: ' + JSON.stringify(album));
var title = (album == null ? 'Create' : 'Edit') + ' Album';
var dialog = new dijit.Dialog({id: 'editAlbumPopup', title: title, onCancel: destroyDialog});
dojo.body().appendChild(dialog.domNode);
var formDiv = dojo.create('div', {id: 'editAlbumFormDiv'});
var form = new dijit.form.Form({id: 'editAlbumForm'});
formDiv.appendChild(form.domNode);
var table = dojo.create('table', null, form.domNode);
var tbody = dojo.create('tbody', null, table);
var tr = dojo.create('tr', null, tbody);
dojo.create('td', null, tr).appendChild(dojo.create('label', {'innerHTML': 'Title', 'for': 'title'}));
dojo.create('td', null, tr).appendChild(
new dijit.form.ValidationTextBox({
name: 'title',
value: album == null ? '' : album.title
}).domNode
);
tr = dojo.create('tr', null, tbody);
dojo.create('td', null, tr).appendChild(dojo.create('label', {'innerHTML': 'Thumnail URL', 'for': 'thumbnail'}));
dojo.create('td', null, tr).appendChild(
new dijit.form.ValidationTextBox({
name: 'thumbnail',
value: album == null ? '' : album.thumbnailUrl
}).domNode
);
tr = dojo.create('tr', null, tbody);
dojo.create('td', null, tr).appendChild(dojo.create('label', {'innerHTML': 'Description', 'for': 'description'}));
dojo.create('td', null, tr).appendChild(
new dijit.form.Textarea({
name: 'description',
value: album == null ? '' : album.description
}).domNode
);
tr = dojo.create('tr', null, tbody);
var buttonTd = dojo.create('td', {colspan: '2', align: 'center'}, tr);
buttonTd.appendChild(new dijit.form.Button({
label: 'Save',
onClick: saveForm
}).domNode
);
buttonTd.appendChild(new dijit.form.Button({
label: 'Cancel',
onClick: destroyDialog
}).domNode
);
dialog.set('content', formDiv);
dialog.show();
function saveForm() {
console.log('saveForm');
var values = form.get('value');
var newAlbum = {
title: values.title,
thumbnailUrl: values.thumbnail,
description: values.description,
ownerId: viewer.id // TODO: bug? Albums service should set this
};
if (album == null) {
social.createAlbum(viewer.id, newAlbum, function(response) {
publish('org.apache.shindig.album.created', newAlbum);
console.log('created album response: ' + JSON.stringify(response));
renderAlbumsByUser(viewer.id);
});
} else {
social.updateAlbum(viewer.id, album.id, newAlbum, function(response) {
publish('org.apache.shindig.album.updated', newAlbum);
console.log('updated album response: ' + JSON.stringify(response));
renderAlbumsByUser(viewer.id);
});
}
destroyDialog();
}
// Handles destroying the dialog popup
function destroyDialog() {
console.log('destroyDialog');
dialog.hide();
dialog.destroyRecursive(false);
dialog.destroyRendering(false);
dialog.destroy(false);
}
}
/*
* Popup to edit MediaItem.
*/
function editMediaItemPopup(album, mediaItem) {
console.log('editMediaItemPopup: ' + JSON.stringify(mediaItem));
var albumId = mediaItem == null ? album.id : mediaItem.albumId;
var title = (mediaItem == null ? 'Create' : 'Edit') + ' MediaItem';
var dialog = new dijit.Dialog({id: 'editMediaItemPopup', title: title, onCancel: destroyDialog});
dojo.body().appendChild(dialog.domNode);
// Form div
var formDiv = dojo.create('div', {id: 'editMediaItemFormDiv'});
var form = new dijit.form.Form({id: 'editMediaItemForm'});
formDiv.appendChild(form.domNode);
var table = dojo.create('table', null, form.domNode);
var tbody = dojo.create('tbody', null, table);
var tr = dojo.create('tr', null, tbody);
dojo.create('td', null, tr).appendChild(dojo.create('label', {'innerHTML': 'Title', 'for': 'title'}));
dojo.create('td', null, tr).appendChild(
new dijit.form.ValidationTextBox({
name: 'title',
value: mediaItem == null ? '' : mediaItem.title
}).domNode
);
tr = dojo.create('tr', null, tbody);
dojo.create('td', null, tr).appendChild(dojo.create('label', {'innerHTML': 'Description', 'for': 'description'}));
dojo.create('td', null, tr).appendChild(
new dijit.form.Textarea({
name: 'description',
value: mediaItem == null ? '' : mediaItem.description
}).domNode
);
tr = dojo.create('tr', null, tbody);
dojo.create('td', null, tr).appendChild(dojo.create('label', {'innerHTML': 'Type', 'for': 'type'}));
dojo.create('td', null, tr).appendChild(
new dijit.form.ValidationTextBox({
name: 'type',
value: mediaItem == null ? '' : mediaItem.type
}).domNode
);
tr = dojo.create('tr', null, tbody);
dojo.create('td', null, tr).appendChild(dojo.create('label', {'innerHTML': 'Thumnail URL', 'for': 'thumbnailUrl'}));
dojo.create('td', null, tr).appendChild(
new dijit.form.ValidationTextBox({
name: 'thumbnailUrl',
value: mediaItem == null ? '' : mediaItem.thumbnailUrl
}).domNode
);
tr = dojo.create('tr', null, tbody);
dojo.create('td', null, tr).appendChild(dojo.create('label', {'innerHTML': 'URL', 'for': 'url'}));
dojo.create('td', null, tr).appendChild(
new dijit.form.ValidationTextBox({
name: 'url',
value: mediaItem == null ? '' : mediaItem.url
}).domNode
);
tr = dojo.create('tr', null, tbody);
var buttonTd = dojo.create('td', {colspan: '2', align: 'center'}, tr);
buttonTd.appendChild(new dijit.form.Button({
label: 'Save',
onClick: saveForm
}).domNode
);
buttonTd.appendChild(new dijit.form.Button({
label: 'Cancel',
onClick: destroyDialog
}).domNode
);
// Textarea div for JSON
var textAreaDiv = dojo.create('div', {style: 'width:100%; height:100%;', id: 'textAreaDiv'});
var textArea = new dijit.form.Textarea({value: JSON.stringify(mediaItem), rows: '20'});
textAreaDiv.appendChild(textArea.domNode);
// Put divs together
var tabContainer = new dijit.layout.TabContainer({style: 'width:400px; height:300px;'});
var formContentPane = new dijit.layout.ContentPane({title: 'Form', content: formDiv});
tabContainer.addChild(formContentPane);
var textAreaContentPane = new dijit.layout.ContentPane({title: 'JSON', content: textAreaDiv});
tabContainer.addChild(textAreaContentPane);
tabContainer.startup();
var dialogDiv = dojo.create('div', null);
dialogDiv.appendChild(tabContainer.domNode);
dialog.set('content', dialogDiv);
dialog.show();
function saveForm() {
console.log('saveForm mediaItem');
var values = form.get('value');
var newMediaItem = {
title: values.title,
description: values.description,
type: values.type,
thumbnailUrl: values.thumbnailUrl,
url: values.url
};
if (newMediaItem.type == null || newMediaItem.type == '') newMediaItem.type = 'image';
if (mediaItem == null) {
social.createMediaItem(viewer.id, albumId, newMediaItem, function(response) {
publish('org.apache.shindig.mediaItem.created', newMediaItem);
console.log('created MediaItem response: ' + JSON.stringify(response));
social.getMediaItemsByAlbum(viewer.id, album.id, function(response) {
renderMediaItems(album, response.list);
});
});
} else {
social.updateMediaItem(viewer.id, albumId, mediaItem.id, newMediaItem, function(response) {
publish('org.apache.shindig.mediaItem.updated', newMediaItem);
console.log('updated MediaItem response: ' + JSON.stringify(response));
social.getMediaItemsByAlbum(viewer.id, album.id, function(response) {
renderMediaItems(album, response.list);
});
});
}
destroyDialog();
}
// Handles destroying the dialog popup
function destroyDialog() {
console.log('destroyDialog');
dialog.hide();
dialog.destroyRecursive(false);
dialog.destroyRendering(false);
dialog.destroy(false);
}
}
/*
* Popup to confirm that the user wants to delete album.
*/
function deleteAlbumPopup(album) {
console.log('deleteAlbumPopup');
if (confirm("Delete '" + album.title + "'?")) {
social.deleteAlbum(viewer.id, album.id, function(response) {
publish('org.apache.shindig.album.deleted', album);
console.log('delete album response: ' + JSON.stringify(response));
renderAlbumsByUser(viewer.id);
});
}
}
/*
* Popup to confirm user wants to delete MediaItem.
*/
function deleteMediaItemPopup(album, mediaItem) {
console.log('deleteMediaItemPopup');
var albumId = mediaItem.albumId;
if (confirm("Delete '" + mediaItem.title + "'?")) {
social.deleteMediaItem(viewer.id, albumId, mediaItem.id, function(response) {
publish('org.apache.shindig.mediaItem.deleted', mediaItem);
console.log('delete mediaItem response: ' + JSON.stringify(response));
social.getMediaItemsByAlbum(viewer.id, albumId, function(response) {
renderMediaItems(album, response.list);
});
});
}
}
/*
* Publishers.
*/
function publish(topic, payload) {
gadgets.Hub.publish(topic, payload);
}
}