/** * 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(400); } 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, onerror: "this.src='" + folderUrl + "';", width: '100%'}, imgLink); var albumRight = dojo.create('td', {className: 'albumListRight'}, albumRow); var albumTitleRow = dojo.create('tr', null, albumRight); 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', style: 'text-align: right'}, albumTitleRow); 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, albumRight); 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 imageTd = dojo.create('tr', null, td).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, onerror: "this.src='" + docUrl + "';", style:'height:100px;'})); } else { dojo.create('img', {src: mediaItems[i].thumbnailUrl, onerror: "this.src='" + docUrl + "';", style:'height:100px;'}, imageTd); } var titleTd = dojo.create('tr', null, td).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 actionsTd = dojo.create('tr', null, td).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) { console.log('created album response: ' + JSON.stringify(response)); renderAlbumsByUser(viewer.id); }); } else { social.updateAlbum(viewer.id, album.id, newAlbum, function(response) { console.log('updated album response: ' + JSON.stringify(response)); renderAlbumsByUser(viewer.id); }); } destroyDialog(); } // Handles destroying the dialog popup function destroyDialog() { console.log('destroyDialog'); 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) { 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) { 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.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) { 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) { console.log('delete mediaItem response: ' + JSON.stringify(response)); social.getMediaItemsByAlbum(viewer.id, albumId, function(response) { renderMediaItems(album, response.list); }); }); } } }