// vim: et:ts=4:sw=4:sts=4:ft=javascript 'use strict'; pandora.documentColumns = [ { id: 'title', operator: '+', title: Ox._('Title'), find: true, visible: true, width: 256 }, { id: 'id', operator: '+', title: Ox._('ID'), visible: true, width: 64 }, { format: function(value) { return value.toUpperCase(); }, id: 'extension', operator: '+', title: Ox._('Extension'), find: true, visible: true, width: 64 }, { align: 'right', format: function(value, data) { return Ox.isArray(value) ? Ox.formatDimensions(value, 'px') : Ox.formatCount(value, (data && data.extension == 'html') ? 'word' : 'page'); }, id: 'dimensions', operator: '-', title: Ox._('Dimensions'), visible: true, width: 128 }, { align: 'right', format: function(value) { return Ox.formatValue(value, 'B'); }, id: 'size', operator: '-', title: Ox._('Size'), visible: true, width: 64 }, { id: 'description', operator: '+', title: Ox._('Description'), find: true, visible: true, width: 256 }, { align: 'right', id: 'matches', operator: '-', title: Ox._('Matches'), visible: true, width: 64 }, { id: 'user', operator: '+', title: Ox._('User'), find: true, visible: true, width: 128 }, { align: 'right', format: function(value) { return Ox.formatDate(value, '%F %T'); }, id: 'created', operator: '-', title: Ox._('Created'), visible: true, width: 144 }, { align: 'right', format: function(value) { return Ox.formatDate(value, '%F %T'); }, id: 'modified', operator: '-', title: Ox._('Modified'), visible: true, width: 144 } ]; pandora.ui.documentSortSelect = function() { var ui = pandora.user.ui, $orderButton = Ox.Button({ overlap: 'left', title: getOrderButtonTitle(), tooltip: getOrderButtonTooltip(), type: 'image' }) .bindEvent({ click: function() { pandora.UI.set({documentsSort: [{ key: ui.documentsSort[0].key, operator: ui.documentsSort[0].operator == '+' ? '-' : '+' }]}); } }), $sortSelect = Ox.Select({ items: pandora.documentColumns.map(function(column) { return { id: column.id, title: Ox._('Sort by {0}', [column.title]) }; }), value: ui.documentsSort[0].key, width: 128 }) .bindEvent({ change: function(data) { var key = data.value; pandora.UI.set({documentsSort: [{ key: key, operator: Ox.getObjectById(pandora.documentColumns, key).operator }]}); } }), that = Ox.FormElementGroup({ elements: [$sortSelect, $orderButton], float: 'right' }) .css({float: 'left', margin: '4px 2px'}); function getOrderButtonTitle() { return ui.documentsSort[0].operator == '+' ? 'up' : 'down'; } function getOrderButtonTooltip() { return Ox._(ui.documentsSort[0].operator == '+' ? 'Ascending' : 'Descending'); } that.sortValue = function(value) { $sortSelect.value(value); $orderButton.options({ title: getOrderButtonTitle(), tooltip: getOrderButtonTooltip() }); }; return that; }; pandora.ui.documentViewSelect = function() { var ui = pandora.user.ui, that = Ox.Select({ items: [ {id: 'list', title: Ox._('View as List')}, {id: 'grid', title: Ox._('View as Grid')} ], value: ui.documentsView, width: 128 }) .css({float: 'left', margin: '4px 2px 4px 4px'}) .bindEvent({ change: function(data) { pandora.UI.set({documentsView: data.value}); } }); return that; }; pandora.ui.documentsPanel = function(options) { var ui = pandora.user.ui, hasItemView = ui.section == 'items' && ui.item, hasListSelection = ui.section == 'items' && !ui.item && ui.listSelection.length, isItemView = options.isItemView, listLoaded = false, allFindKeys = ['user', 'title', 'entity', 'extension', 'description'].filter(function(key) { return key != 'entity' || pandora.site.entities.length; }), $listBar = Ox.Bar({size: 24}), $viewSelect = pandora.ui.documentViewSelect().appendTo($listBar), $sortElement = pandora.ui.documentSortSelect().appendTo($listBar), $findElement = findElement(updateList, isItemView).appendTo($listBar), $list = renderList(), $listStatusbar = Ox.Bar({size: 16}).css({textAlign: 'center'}), $listStatus = Ox.Element() .css({ margin: '2px 4px', fontSize: '9px', overflow: 'hidden', textOverflow: 'ellipsis' }) .html(Ox._('Loading...')) .appendTo($listStatusbar), $listPanel = Ox.SplitPanel({ elements: [ {element: $listBar, size: 24}, {element: $list}, {element: $listStatusbar, size: 16} ], orientation: 'vertical' }) .bindEvent({ resize: function() { $list.size(); }, }), $itemBar = Ox.Bar({size: 24}), $itemMenu = Ox.MenuButton({ items: isItemView ? [ {id: 'open', title: '', keyboard: 'return'}, {id: 'edit', title: ''}, {id: 'embed', title: Ox._('Embed Document...')}, {}, {id: 'remove', title: '', keyboard: 'delete'} ] : [ {id: 'upload', title: Ox._('Upload {0}...', [Ox._('Documents')]), file: {width: 192}}, {}, {id: 'open', title: '', keyboard: 'return'}, {id: 'add', title: ''}, {id: 'embed', title: Ox._('Embed Document...')}, {}, {id: 'replace', title: Ox._('Replace {0}...', [Ox._('Document')]), file: {width: 192}}, {id: 'delete', title: '', keyboard: 'delete'} ], title: 'set', tooltip: Ox._('Options'), type: 'image' }) .css({float: 'left', margin: '4px'}) .bindEvent({ click: function(data) { if (data.id == 'add') { isItemView ? openDocumentsDialog() : addDocuments(); } else if (data.id == 'delete') { deleteDocuments(); } else if (data.id == 'edit') { pandora.UI.set({ section: 'documents', document: ui.documentsSelection[ui.item][0], documentView: 'info' }); } else if (data.id == 'embed') { openEmbedDialog(); } else if (data.id == 'open') { openDocuments(); } else if (data.id == 'remove') { removeDocuments(); } else if (data.id == 'replace') { replaceDocument(data); } else if (data.id == 'upload') { uploadDocuments(data); } } }) .appendTo($itemBar), $deselectButton = Ox.Button({ title: 'close', tooltip: Ox._('Done'), type: 'image' }) .css({float: 'right', margin: '4px 4px 4px 2px'}) .bindEvent({ click: function() { pandora.UI.set( 'documentsSelection.' + (isItemView ? ui.item : ''), [] ); } }) .hide() .appendTo($itemBar), $selectButton = Ox.ButtonGroup({ buttons: [ {id: 'previous', title: 'left', tooltip: Ox._('Previous')}, {id: 'next', title: 'right', tooltip: Ox._('Next')} ], type: 'image' }) .css({float: 'right', margin: '4px 2px'}) .bindEvent({ click: function(data) { $list.selectSelected(data.id == 'previous' ? -1 : 1); } }) .hide() .appendTo($itemBar), $item = Ox.Element().css({overflowY: 'scroll'}), $preview, $data, $itemStatusbar = Ox.Bar({size: 16}) .css({textAlign: 'center'}), $itemStatus = Ox.Element() .css({ margin: '2px 4px', fontSize: '9px', overflow: 'hidden', textOverflow: 'ellipsis' }) .appendTo($itemStatusbar), $itemPanel = Ox.SplitPanel({ elements: [ {element: $itemBar, size: 24}, {element: $item}, {element: $itemStatusbar, size: 16} ], orientation: 'vertical' }) .bindEvent({ resize: function(data) { ui.documentSize = data.size; resizeItem(); }, resizeend: function(data) { // set to 0 so that UI.set registers a change of the value ui.documentSize = 0; pandora.UI.set({documentSize: data.size}); }, toggle: function(data) { pandora.UI.set({showDocument: !data.collapsed}); } }), that = Ox.SplitPanel({ elements: [ { element: $listPanel }, { collapsible: isItemView, collapsed: isItemView && !ui.showDocument, element: $itemPanel, size: ui.documentSize, resizable: true, resize: [192, 256, 320, 384], tooltip: 'document ' + Ox.SYMBOLS.shift + 'D' } ], orientation: 'horizontal' }) .bindEvent({ pandora_documentsize: function(data) { that.size(1, data.value); }, pandora_documentssort: function(data) { $sortElement.sortValue(ui.documentsSort[0].key); $list.options({sort: data.value}); }, pandora_documentsview: function(data) { $listPanel.replaceElement(1, $list = renderList()); }, pandora_showdocument: function(data) { isItemView && that.toggleElement(1); } }) .bindEvent( 'pandora_documentsselection.' + ( isItemView ? ui.item.toLowerCase() : '' ), selectDocuments ); if (isItemView) { pandora.$ui.documentsList = $list; } function addDocuments() { var ids = ui.documentsSelection['']; pandora.api.addDocument({ item: hasItemView ? ui.item : ui.listSelection, ids: ids }, function() { Ox.Request.clearCache(); if (ui.item && ui.itemView == 'documents') { // FIXME: $list.reloadList() would be much better pandora.$ui.contentPanel.replaceElement(1, pandora.$ui.item = pandora.ui.item() ); // FIXME: there has to be a way to do this without timeout setTimeout(function() { pandora.UI.set('documentsSelection.' + ui.item, ids); }, 1000); } }); } function closeDocuments() { if (pandora.$ui.documentDialog) { pandora.$ui.documentDialog.close(); } } function deleteDocuments() { pandora.ui.deleteDocumentDialog( $list.options('selected').map(function(id) { return $list.value(id); }), function() { Ox.Request.clearCache(); // ... $list.reloadList(); } ).open(); } function editDocuments() { pandora.UI.set('documentsSelection.', $list.options('selected')); openDocumentsDialog(); } function findElement(callback, isItemView) { var $findSelect = Ox.Select({ items: [ {id: 'all', title: Ox._('Find: All')}, {id: 'title', title: Ox._('Find: Title')}, {id: 'user', title: Ox._('Find: User')}, {id: 'entity', title: Ox._('Find: Entity')} ].filter(function(item) { if (item.id == 'user') { return !isItemView; } else if (item.id == 'entity') { return pandora.site.entities.length; } return true; }), overlap: 'right', type: 'image' }) .bindEvent({ change: function(data) { $findInput.options({placeholder: data.title}).focusInput(); } }), $findInput = Ox.Input({ changeOnKeypress: true, clear: true, placeholder: Ox._('Find: All'), width: 192 }) .bindEvent({ change: function(data) { data.key = $findSelect.value(); data.value = $findInput.value() callback(data); } }), that = Ox.FormElementGroup({ elements: [ $findSelect, $findInput ] }) .css({float: 'right', margin: '4px 4px 4px 2px'}); // to determine the width of the find input inside // the documents dialog, that dialog has to be present setTimeout(function() { $findInput.options({width: getFindInputWidth()}); }); return that; } function getFindInputWidth() { // 2 * 128px selects + 2 * 16px buttons + 4 * 4px margins = 304px return Math.min(192, ( isItemView ? window.innerWidth - (ui.showSidebar * ui.sidebarSize) - 1 - (ui.showDocument * ui.documentSize) : pandora.$ui.documentsDialog.options('width') - ui.documentSize - 1 ) - 304); } function getPreviewSize() { var ratio = $list.value($list.options('selected')[0], 'ratio'), size = ui.documentSize - 16 - Ox.UI.SCROLLBAR_SIZE, height = ratio > 1 ? size / ratio : size, width = ratio > 1 ? size : size * ratio, left = Math.floor((size - width) / 2); return { height: height, // fixme: CSS gets applied twice, to image and enclosing element margin: [8, 8, 8, 8 + left].map(function(px) { return Math.round(px / 2) + 'px'; }).join(' '), width: width }; } function openDocuments() { pandora.openDocumentDialog({ documents: $list.options('selected').map(function(id) { return $list.value(id); }) }).bindEvent({ close: function() { $list.closePreview(); } }); } function openDocumentsDialog() { pandora.$ui.documentsDialog = pandora.ui.documentsDialog().open(); } function openEmbedDialog() { pandora.$ui.embedDocumentDialog = pandora.ui.embedDocumentDialog( ui.documentsSelection[isItemView ? ui.item : ''][0] ).open(); } function replaceDocument(data) { var id = $list.options('selected')[0]; pandora.ui.uploadDocumentDialog({ files: data.files, id: id }, function(files) { if (files) { Ox.Request.clearCache(); $list.bindEventOnce({ load: function() { $list.options({selected: files.ids}); selectDocuments(); } }) .reloadList(); } }).open(); } function removeDocuments() { pandora.api.removeDocument({ item: ui.item, ids: $list.options('selected') }, function() { Ox.Request.clearCache(); // ... $list.reloadList(); }); } function renderData() { var $name, $description, $input, item = $list.value($list.options('selected')[0]), editable = item.user == pandora.user.username || pandora.hasCapability('canEditDocuments') || options.editable, labelWidth = 80, width = ui.documentSize - 16 - Ox.UI.SCROLLBAR_SIZE; return isItemView ? Ox.Element() .css({textAlign: 'center'}) .append( Ox.$('