/*! * Aloha Editor * Author & Copyright (c) 2012 Gentics Software GmbH * aloha-sales@gentics.com * Licensed under the terms of http://www.aloha-editor.com/license.html */ define('RepositoryBrowser', [ 'jquery', 'Class', 'PubSub', 'repository-browser-i18n-' + ( (window && window.__DEPS__ && window.__DEPS__.lang) || 'en' ), 'jstree', 'jqgrid', 'jquery-layout' ], function ( $, Class, PubSub, i18n ) { 'use strict'; var jQuery = $; var browserInstances = []; var numOpenedBrowsers = 0; var uid = (new Date()).getTime(); var DEFAULTS = { repositoryManager: null, repositoryFilter: [], objectTypeFilter: [], renditionFilter: ['cmis:none'], // ['*'] filter: ['url'], element: null, isFloating: false, verticalPadding: 100, horizontalPadding: 50, maxHeight: 1000, minHeight: 400, minWidth: 400, maxWidth: 1200, treeWidth: 300, listWidth: 'auto', pageSize: 8, adaptPageSize: false, rowHeight: 32, rootPath: '', rootFolderId: 'aloha', columns: { icon: {title: '', width: 30, sortable: false, resizable: false}, name: {title: 'Name', width: 200, sorttype: 'text'}, url: {title: 'URL', width: 220, sorttype: 'text'}, preview: {title: 'Preview', width: 150, sorttype: 'text'} }, i18n: { 'Browsing': 'Browsing', 'Close': 'Close', 'in': 'in', 'Input search text...': 'Input search text...', 'numerous': 'numerous', 'of': 'of', 'Repository Browser': 'Repository Browser', 'Search': 'Search', 'Searching for': 'Searching for', 'Viewing': 'Viewing' } }; /** * Prevents native browser selection on the given element. * * @param {jQuery.} element An element on which to prevent * selection. */ function disableSelection($element) { $element.each(function () { jQuery(this) .attr('unselectable', 'on') .css({ '-moz-user-select': 'none', '-webkit-user-select': 'none', 'user-select': 'none' }) .each(function () { this.onselectstart = function () { return false; }; }); }); } /** * Get icon name from given resource type. * * @param {string} type Resource type. * @return {string} Icon name. */ function getIcon(type) { switch (type) { case 'folder': return 'folder'; case 'document': return 'document'; default: return ''; } } /** * Return unique id. * * @return {number} */ function uniqueId() { return ++uid; } /** * FIXME: free cache * * @param {RepositoryBrowser} browser * @param {object} obj */ function cacheWrite(browser, obj) { browser._cachedRepositoryObjects[obj.uid] = obj; } /** * @param {RepositoryBrowser} browser * @param {object} obj * @return {object} */ function cacheRead(browser, uid) { return browser._cachedRepositoryObjects[uid]; } /** * @param {jQuery.} $node * @return {string} Id of repository object tethered to the given DOM * element. */ function getIdFromTreeNode($node) { return $node.find('a:first').attr('data-repo-obj'); } /** * Composite for jqGrid and jsTree * * Convert a repository object into an object that can be used with our tree * component. Also add a reference to this object in the cache. According * to the Repository specification, each object will at least have the * following properties: id, name, url, and type. Any and all other * attributes are optional. */ function createComposite(props, browser) { var uid = uniqueId(); var state = (false === props.hasMoreItems || 'folder' !== props.baseType) ? null : 'closed'; // Initialize as array instead? will jstree accept empty list? var children = null; if (props.children) { state = 'open'; children = []; var i; var child; for (i = 0; i < props.children.length; i++) { child = createComposite(props.children[i], browser); children.push(child); cacheWrite(browser, child.resource); } } var treeResource = $.extend(props, { uid: uid, loaded: false }); return { state: state, resource: treeResource, children: children, // jsTreee
  • attributes attr: { rel: props.type, 'data-repo-obj': uid }, data: { title: props.name, icon: getIcon(props.baseType), attr: { 'data-repo-obj': uid } } }; } var RepositoryBrowser = Class.extend({ /** * @private * @type The repository objects queried through this browser. */ _cachedRepositoryObjects: {}, /** * @private * @type The last search query. */ _searchQuery: null, /** * @private * @type */ _orderBy: null, /** * @private * @type prefilled value of the search field */ _prefilledValue: null, /** * @type {jsGrid} */ $_grid: null, /** * @type {jsTree} */ $_tree: null, /** * @type {jQuery.} The layout of the browser panels. */ $_list: null, /** * @type {boolean} Whether or not the browser is visibly opened. This * flag is set to true when the show() function is * called. */ _isOpened: true, /** * @constructor */ _constructor: function () { this.init.apply(this, arguments); }, /** * Process the given browser configurations, and renders a hidden * instance of this browser. * * @param {object} options User defined custom browser configurations. */ init: function (options) { options = jQuery.extend({}, DEFAULTS, options, {i18n: i18n}); // If no element was specified on which to render the browser, then // we will create an overlay and render the browser on it. if (!options.element || 0 === options.element.length) { options.isFloating = true; options.element = this._createOverlay(); } if (options.maxWidth < options.minWidth) { options.maxWidth = options.minWidth; } jQuery.extend(this, options); this._prefilledValue = this._i18n('Input search text...'); this._cachedRepositoryObjects = {}; this._searchQuery = null; this._orderBy = null; this._pagingCount = null; this._pagingOffset = 0; this._pagingBtns = { first: null, end: null, next: null, prev: null }; this._initializeUI(); browserInstances.push(this); PubSub.pub('repository-browser.initialized', {data: this}); }, /** * Retrieves the corresponding internationalization string for the * given keyword. * * @param {string} key The key for which a full i18n string is * retrieved. * @return {string} The return value is either the i18n value matched * by the given key, or else the key. */ _i18n: function (key) { return this.i18n[key] || key; }, /** * Prepares the browser UI. */ _initializeUI: function () { this.element.attr('data-repository-browser', ++uid); //.html(''); this.element.width(this.maxWidth); this.$_grid = this._createGrid(this.element).resize(); this._setInitialHeight(); this.$_tree = this._createTree(this.$_grid.find('.ui-layout-west')); this.$_list = this._createList(this.$_grid.find('.ui-layout-center')); var that = this; var give = this.treeWidth / 5; this.$_grid.layout({ // Disable cursor hot keys since they interfere with text // editing. For example, CTRL+left (wordwise left) and // CTRL+SHIFT+left (select wordwise left) would stop working. enableCursorHotkey: false, west__size: this.treeWidth - 1, west__minSize: this.treeWidth - give, west__maxSize: this.treeWidth + give, center__size: 'auto', paneClass: 'ui-layout-pane', resizerClass: 'ui-layout-resizer', togglerClass: 'ui-layout-toggler', onresize: function (name, $element) { if ('center' === name) { that.$_list.setGridWidth($element.width()); } } // , applyDefaultStyles: true }).sizePane('west', this.treeWidth); // Fix for a ui-layout bug in // chrome. disableSelection(this.$_grid); this._preloadImages(); jQuery(function () { jQuery(window).resize(function () { that._onWindowResized(); }); }); this.element.mousedown(function () { jQuery.each(browserInstances, function (index) { this.element.css('z-index', 99999 + index); }); jQuery(this).css('z-index', 99999 + browserInstances.length + 1); }); // IE7 Work-around: Otherwise tree will not be displayed correctly. jQuery('.repository-browser-grid').css('width', this.maxWidth); this.close(); // adapt the page size this._adaptPageSize(); }, /** * Sets the initial height of the repository browser using the minHeight maxHeight setting. */ _setInitialHeight: function () { var overflow = this.maxHeight - jQuery(window).height() + this.verticalPadding; var targetHeight = overflow > 0 ? Math.max(this.minHeight, this.maxHeight - overflow) : this.maxHeight; this.$_grid.height(targetHeight); }, /** * Automatically resize the browser modal, constraining its dimensions * between minWidth and maxWidth. */ _onWindowResized: function () { var overflow = this.maxWidth - jQuery(window).width() + this.horizontalPadding, $header, $container; var target = overflow > 0 ? Math.max(this.minWidth, this.maxWidth - overflow) : this.maxWidth; this.element.width(target); this.$_grid.width(target); this._setInitialHeight(); // adapt tree $header = this.$_grid.find('.repository-browser-tree-header'); this.$_tree.height(this.$_grid.height() - $header.outerHeight(true)); // adapt list $container = this.$_grid.find('.ui-layout-center'); $container.find('.ui-jqgrid-bdiv').height(this.$_grid.height() - ( $container.find('.ui-jqgrid-titlebar').height() + $container.find('.ui-jqgrid-hdiv').height() + $container.find('.ui-jqgrid-pager').height() )); // adapt paging if (this._adaptPageSize()) { // if the pagesize changed, we need to refresh the list if (this._currentFolder) { this._fetchItems(this._currentFolder); } } }, /** * Preload images used by the browser UI. */ _preloadImages: function () { var path = this.rootPath + 'img/'; var imgs = [ 'arrow-000-medium.png', 'arrow-180.png', 'arrow-315-medium.png', 'arrow-stop-180.png', 'arrow-stop.png', 'arrow.png', 'control-stop-square-small.png', 'folder-horizontal-open.png', 'folder-open.png', 'magnifier-left.png', 'page.png', 'picture.png', 'sort-alphabet-descending.png', 'sort-alphabet.png' ]; var j = imgs.length; while (j) { var img = document.createElement('img'); img.src = path + imgs[--j]; } }, /** * Process the received repository items. * * @param {Array.} items List objects retrieved by repository * manager. * @param {TODO} metainfo * @param {function} callback Function to receive the processed items. */ _processRepoResponse: function (items, metainfo, callback) { // If the second parameter is a function, it is the callback; if (typeof metainfo === 'function') { callback = metainfo; metainfo = undefined; } var repobrowser = this; var collection = []; var currentFolder = repobrowser._currentFolder && repobrowser._currentFolder.id; var open = null; var composite; var i; for (i = 0; i < items.length; i++) { composite = createComposite(items[i], repobrowser); collection.push(composite); cacheWrite(repobrowser, composite.resource); if (currentFolder === composite.resource.id) { open = composite.resource; } } callback(collection, metainfo); if (open) { window.setTimeout(function () { repobrowser.$_tree.jstree( 'select_node', 'li[data-repo-obj="' + open.uid + '"]' ); }, 0); // Is this timeout still necessary } }, /** * Retrieve the root node, and its children. * * @param {function(object)} callback A function to receive the * retrieved folder structure. */ _fetchRepoRoot: function (callback) { if (!this._currentFolder) { // get the selected folder this._currentFolder = this.getSelectedFolder(); } if (this.repositoryManager) { this.getRepoChildren({ inFolderId: this.rootFolderId, repositoryFilter: this.repositoryFilter }, callback); } }, /** * Retrieves a cached repository object that is associated with the * given node element. * * @param {jQuery. $node The element whose corresponding * repository object is to be * retreived. * @return {!Object} The cached repository object or null if none is * found in the cache. */ _getObjectFromCache: function ($node) { if ($node && $node.length) { var id = $node.find('a:first').attr('data-repo-obj'); return this._cachedRepositoryObjects[id]; } return null; }, /** * Queries the repository manager for items contained in folder that * was clicked. * * @param {jQuery.} $event jQuery event object. Unused. * @param {object} data An object containing information about the * jstree node that was clicked. */ _onTreeNodeSelected: function ($event, data) { // Suppress a bug in jsTree. if (data.args[0].context) { return; } var repobrowser = this; var folder = cacheRead(repobrowser, getIdFromTreeNode(data.rslt.obj)); if (folder) { // Reset paging and search repobrowser._pagingOffset = 0; repobrowser._currentFolder = folder; repobrowser._clearSearch(); repobrowser._fetchItems(folder); repobrowser.folderSelected(folder); } }, /** * Render and initialize a jstree instance for the given container * element. * * @param {jQuery.} $container The element in which the * jstree instance will be * rendered. * @return {jQuery.} $tree Element which has been * initialized for jstree. */ _createTree: function ($container) { var $tree = jQuery('
    '); var $header = jQuery('
    ' + this._i18n('Repository Browser') + '
    '); $container.append($header, $tree); $tree.height(this.$_grid.height() - $header.outerHeight(true)); $tree.bind('loaded.jstree', function ($event, data) { $(this).find('>ul>li:first').css('padding-top', 5); // Because jstree `open_node' will add substree items to every // item matched by the selector, we need to ensure that // `open_node' is invoked for one item at a time. $(this).find('li[rel="repository"]:first').each( function (i, li) { $tree.jstree('open_node', li); }); }); var that = this; // Bind the jsree select node event $tree.bind('select_node.jstree', function ($event, data) { that._onTreeNodeSelected($event, data); }); // Bind the jsree open node event $tree.bind('open_node.jstree', function ($event, data) { that.folderOpened(data.rslt.obj); }); // Bind the jsree close node event $tree.bind('close_node.jstree', function ($event, data) { that.folderClosed(data.rslt.obj); }); $tree.jstree({ types: this.types, rootFolderId: this.rootFolderId, plugins: ['themes', 'json_data', 'ui', 'types'], core: {animation: 250}, themes: { url: this.rootPath + 'css/jstree.css', dots: true, icons: true, theme: 'browser' }, json_data: { data: function (nodes, callback) { if (that.repositoryManager) { that.jstree_callback = callback; that._fetchSubnodes(nodes, callback); } else { callback(); } }, correct_state: true }, ui: {select_limit: 1} }); return $tree; }, /** * Creates a grid inside the given element. The grid provides panels * in which we render the folder list tree, and a the folder items * list. * * @param {jQuery.} $container A DOM element in which to * render the grid. * @return {jQuery.\
    \
    \
    ' ); $container.append($grid); return $grid; }, /** * Creates a table inwhich to render repository items. * * @param {jQuery.} $container A DOM element in which to * render the list. * @return {jQuery.'); // This is a hidden utility column to help us with auto sorting. var model = [{ name: 'id', sorttype: 'int', firstsortorder: 'asc', hidden: true }]; var names = ['']; jQuery.each(this.columns, function (key, value) { names.push(value.title || ' '); model.push({ name: key, width: value.width, sortable: value.sortable, sorttype: value.sorttype, resizable: value.resizable, fixed: value.fixed }); }); /* * jqGrid requires that we use an id, despite what the * documentation says * (http://www.trirand.com/jqgridwiki/doku.php?id=wiki:pager&s[]=pager). * We need a unique id, however, in order to distinguish pager * elements for each browser instance. */ var pagerUID = 'repository-browser-list-page-' + (++uid); $container.append($list, jQuery('
    ')); $list.jqGrid({ datatype: 'local', width: $container.width(), shrinkToFit: true, colNames: names, colModel: model, caption: ' ', altRows: true, altclass: 'repository-browser-list-altrow', resizeclass: 'repository-browser-list-resizable', // http://www.trirand.com/jqgridwiki/doku.php?id=wiki:pager&s[]=pager pager: '#' + pagerUID, // # of records to view in the grid. Passed as parameter to url // when retrieving data from server. //rowNum: this.pageSize, viewrecords: true, // Event handlers: // http://www.trirand.com/jqgridwiki/doku.php?id=wiki:events // Fires after click on [page button] and before populating the // data. onPaging: function (button) {}, // Called if the request fails. loadError: function (xhr, status, error) {}, // Raised immediately after row was double clicked. ondblClickRow: function (rowid, iRow, iCol, e) {}, // Fires after all the data is loaded into the grid and all // other processes are complete. gridComplete: function () {}, // Executed immediately after every server request. loadComplete: function (data) {} }); $container.find('.ui-jqgrid-bdiv').height(this.$_grid.height() - ( $container.find('.ui-jqgrid-titlebar').height() + $container.find('.ui-jqgrid-hdiv').height() + $container.find('.ui-jqgrid-pager').height() )); var that = this; $list.click(function () { that.rowClicked.apply(that, arguments); }); // Override jqGrid paging. $container .find('.ui-pg-button').unbind() .find('>span.ui-icon').each(function () { var dir = this.className.match(/ui\-icon\-seek\-([a-z]+)/)[1]; that._pagingBtns[dir] = jQuery(this) .parent() .addClass('ui-state-disabled') .click(function () { if (!jQuery(this).hasClass('ui-state-disabled')) { that._doPaging(dir); } }); }); // TODO: Implement this once repositories can handle it; hiding it // for now. $container.find('.ui-pg-input').parent().hide(); $container.find('.ui-separator').parent().css('opacity', 0).first().hide(); //$container.find('#repository-browser-list-pager-left').hide(); this._createTitlebar($container); //this.$_grid.find('.loading').html('Loading...'); // Override jqGrid sorting. var listProps = $list[0].p; $container.find('.ui-jqgrid-view tr:first th div').each(function (i) { if (false !== listProps.colModel[i].sortable) { jQuery(this).css('cursor', 'pointer'); jQuery(this).unbind().click(function (event) { event.stopPropagation(); that._sortList(listProps.colModel[i], this); }); } }); return $list; }, /** * Clear the search */ _clearSearch: function () { var $searchField = this.$_grid.find('.repository-browser-search-field'); $searchField.val(this._prefilledValue).addClass('repository-browser-search-field-empty'); this._searchQuery = null; }, _createTitlebar: function ($container) { var $bar = $container.find('.ui-jqgrid-titlebar'); var $btns = jQuery( '
    \ \ \ \ \ ' + this._i18n('Close') + '\
    \
    ' ); var that = this; $bar.addClass('repository-browser-grab-handle').append($btns); $bar.find('.repository-browser-search-btn') .html(this._i18n('Search')) .click(function () { that._triggerSearch(); }); var $searchField = $bar.find('.repository-browser-search-field'); this._clearSearch(); $searchField.keypress(function (event) { // On ENTER. if (13 === event.keyCode) { that._triggerSearch(); } }); $searchField.focus(function () { if (jQuery(this).val() === that._prefilledValue) { jQuery(this) .val('') .removeClass('repository-browser-search-field-empty'); } }); $searchField.blur(function () { if (jQuery(this).val() === '') { that._clearSearch(); } }); $bar.find('.repository-browser-close-btn') .click(function () { that.close(); }); $bar.find('.repository-browser-btn') .mousedown(function () { jQuery(this).addClass('repository-browser-pressed'); }) .mouseup(function () { jQuery(this).removeClass('repository-browser-pressed'); }); }, _triggerSearch: function () { var $searchField = this.$_grid.find('input.repository-browser-search-field'); var searchValue = $searchField.val(); if (jQuery($searchField).hasClass('aloha-browser-search-field-empty') || '' === searchValue) { searchValue = null; } this._pagingOffset = 0; this._searchQuery = searchValue; this._fetchItems(this._currentFolder); }, /** * TODO: Fix this so that sorting does toggle between desc and asc when * you click on a column on which we were not sorting. */ _sortList: function (columnModel, element){ // Reset sort properties in all column headers. this.$_grid.find('span.ui-grid-ico-sort').addClass('ui-state-disabled'); columnModel.sortorder = ('asc' === columnModel.sortorder) ? 'desc' : 'asc'; jQuery(element) .find('span.s-ico').show() .find('.ui-icon-' + columnModel.sortorder) .removeClass('ui-state-disabled'); this._setSortOrder(columnModel.name, columnModel.sortorder); this._fetchItems(this._currentFolder); }, _doPaging: function (dir) { switch (dir) { case 'first': this._pagingOffset = 0; break; case 'end': if ((this._pagingCount % this.pageSize) === 0) { // item count is exactly divisible by page size this._pagingOffset = this._pagingCount - this.pageSize; } else { this._pagingOffset = this._pagingCount - (this._pagingCount % this.pageSize); } break; case 'next': this._pagingOffset += this.pageSize; break; case 'prev': this._pagingOffset -= this.pageSize; // avoid "ot of bounds" situation if (this._pagingOffset < 0) { this._pagingOffset = 0; } break; } this._fetchItems(this._currentFolder); }, /** * Adds new sort fields into the _orderBy array. If a field already * exists, it will be spliced from where it is and unshifted to the end * of the array. */ _setSortOrder: function (by, order) { var sortItem = {}; var isFound = false; var orderBy = this._orderBy || []; var orderItem; var field; var i; sortItem[by] = order || 'asc'; for (i = 0; i < orderBy.length; ++i) { orderItem = orderBy[i]; for (field in orderItem) { if (orderItem.hasOwnProperty(field)) { if (field === by) { orderBy.splice(i, 1); orderBy.unshift(sortItem); isFound = true; break; } } } if (isFound) { break; } } if (isFound) { orderBy.unshift(sortItem); } this._orderBy = orderBy; }, _listItems: function (items) { var $list = this.$_list.clearGridData(); var i; var obj; for (i = 0; i < items.length; i++) { obj = items[i].resource; $list.addRowData( obj.uid, jQuery.extend({id: obj.id}, this.renderRowCols(obj)) ); } }, /** * Handle repository timeouts */ handleTimeout: function () { }, _processItems: function (data, metainfo) { // If the total number of items is known, we can calculate the // number of pages. this._pagingCount = (metainfo && jQuery.isNumeric(metainfo.numItems)) ? metainfo.numItems : null; // TODO: should we use undefined? this.$_grid.find('.loading').hide(); this.$_list.show(); this._listItems(data); var CSS_DISABLED = 'ui-state-disabled'; var $btns = this._pagingBtns; if (this._pagingOffset <= 0) { $btns.first.add($btns.prev).addClass(CSS_DISABLED); } else { $btns.first.add($btns.prev).removeClass(CSS_DISABLED); } if (!jQuery.isNumeric(this._pagingCount)) { $btns.end.addClass(CSS_DISABLED); if (data.length <= this.pageSize) { $btns.next.addClass(CSS_DISABLED); } else { $btns.next.removeClass(CSS_DISABLED); } } else if (this._pagingOffset + this.pageSize >= this._pagingCount) { $btns.end.add($btns.next).addClass(CSS_DISABLED); } else { $btns.end.add($btns.next).removeClass(CSS_DISABLED); } var from; var to; if (0 === data.length && 0 === this._pagingOffset) { from = 0; to = 0; } else { from = this._pagingOffset + 1; to = from + data.length - 1; } this.$_grid.find('.ui-paging-info').html( this._i18n('Viewing') + ' ' + (from) + ' - ' + (to) + ' ' + this._i18n('of') + ' ' + (jQuery.isNumeric(this._pagingCount) ? this._pagingCount : this._i18n('numerous')) ); // when the repository manager reports a timeout, we handle it if (metainfo && metainfo.timeout) { this.handleTimeout(); } }, _createOverlay: function () { // We only want one overlay element. if (0 === jQuery('.repository-browser-modal-overlay').length) { jQuery('body').append( '
    '); } var that = this; // Register a close procedure for each browser instance. jQuery('.repository-browser-modal-overlay').click(function () { that.close(); }); var $container = jQuery( '
    '); jQuery('body').append($container); return $container; }, _fetchSubnodes: function (nodes, callback) { if (-1 === nodes) { this._fetchRepoRoot(callback); } else { var i; for (i = 0; i < nodes.length; i++) { var obj = this._getObjectFromCache(nodes.eq(i)); if (obj) { this.fetchChildren(obj, callback); } } } }, // ==================================================================== // API Methods // ==================================================================== /** * Get child folders of a specified repository node. * * @param {object} params An object containing parameters with which to * fetch the objects. * @param {function} callback Function to receive fetched items. */ getRepoChildren: function (params, callback) { if (this.repositoryManager) { var that = this; this.repositoryManager.getChildren(params, function (items) { that._processRepoResponse(items, callback); }); } }, /** * Query repositories for items matching the given parameters. * * @param {object} params An object containing parameters with which to * fetch the objects. * @param {function} callback Function to receive fetched items. */ queryRepository: function (params, callback) { if (this.repositoryManager) { var that = this; this.repositoryManager.query(params, function (response) { that._processRepoResponse( (response.results > 0) ? response.items : [], { numItems: response.numItems, hasMoreItems: response.hasMoreItems, timeout: response.timeout }, callback ); }); } }, /** * Builds a row that an be rendered in the grid layout from the given * repository item. * * @param {object} item The repository resource to render. * @returns {object} An object representing the rendered row such that * it can be used to populate the grid layout. */ renderRowCols: function (item) { var row = {}; jQuery.each(this.columns, function (name, value) { switch (name) { case 'icon': row.icon = '
    '; break; default: row[name] = item[name] || '--'; } }); return row; }, /** * User should implement this according to their needs. * * @param {object} item Repository resource for a row. */ onSelect: function (item) {}, /** * Fetch an object's children if we haven't already done so. * * @param {object} obj * @param {function} callback A function to receive the fetched * children object. */ fetchChildren: function (obj, callback) { if (true === obj.hasMoreItems || 'folder' === obj.baseType) { if (false === obj.loaded) { var that = this; this.getRepoChildren({ inFolderId: obj.id, repositoryId: obj.repositoryId }, function (data) { that._cachedRepositoryObjects[obj.uid].loaded = true; if (typeof callback === 'function') { callback(data); } }); } } }, /** * Handles click events on rows. * * @param {jQuery.} jQuery event object. * @return {jQuery.} The clicked row of null. */ rowClicked: function ($event) { var row = jQuery($event.target).parent('tr'); if (row.length) { var uid = row.attr('id'); var item = this._cachedRepositoryObjects[uid]; this.onSelect(item); return item; } return null; }, getFieldOfHeader: function ($th) { return $th.find('div.ui-jqgrid-sortable').attr('id').replace('jqgh_', ''); }, _fetchItems: function (folder) { if (!folder) { return; } // When searching, we do this recursively. var recursive = (typeof this._searchQuery === 'string'); this.$_list.setCaption((typeof this._searchQuery === 'string') ? this._i18n('Searching for') + ' "' + this._searchQuery + '" ' + this._i18n('in') + ' ' + folder.name : this._i18n('Browsing') + ': ' + folder.name); this.$_list.hide(); this.$_grid.find('.loading').show(); var that = this; this.queryRepository({ repositoryId: folder.repositoryId, inFolderId: folder.id, queryString: this._searchQuery, orderBy: this._orderBy, skipCount: this._pagingOffset, maxItems: this.pageSize, objectTypeFilter: this.objectTypeFilter, renditionFilter: this.renditionFilter, filter: this.filter, recursive: recursive }, function (data, metainfo) { that._processItems(data, metainfo); }); }, setObjectTypeFilter: function (otf) { this.objectTypeFilter = (typeof otf === 'string') ? [otf] : otf; }, getObjectTypeFilter: function () { return this.objectTypeFilter; }, show: function () { this.open(); }, open: function () { if (this._isOpened) { return; } this._isOpened = true; var $element = this.element; if (this.isFloating) { //$element.find('.repository-browser-close-btn').show(); jQuery('.repository-browser-modal-overlay') .stop() .css({top: 0, left: 0}) .show(); $element.stop().show(); // recalculate sizes this._onWindowResized(); this.$_grid.resize(); var win = jQuery(window); $element.css({ left: this.horizontalPadding / 2, top: this.verticalPadding / 2 }).draggable({ handle: $element.find('.repository-browser-grab-handle') }); // Wake-up animation. this.$_grid.css({ marginTop: 0, opacity: 0 }).animate({ marginTop: 0, opacity: 1 }, 1500, 'easeOutExpo', function () { // Disable filter to prevent IE<=8 filter bug. if (jQuery.browser.msie) { jQuery(this).add($element).css( 'filter', 'progid:DXImageTransform.Microsoft.gradient(enabled=false)' ); } }); } else { $element.stop().show().css({ opacity: 1, filter: 'progid:DXImageTransform.Microsoft.gradient(enabled=false)' }); this._onWindowResized(); this.$_grid.resize(); } ++numOpenedBrowsers; }, close: function () { if (!this._isOpened) { return; } this._isOpened = false; this.element.fadeOut(250, function () { jQuery(this).css('top', 0).hide(); if (0 === numOpenedBrowsers || 0 === --numOpenedBrowsers) { jQuery('.repository-browser-modal-overlay').hide(); } }); }, /** * Refreshes the browser. * TODO: Should we also refresh the tree? */ refresh: function () { // Refresh the list, if we have a current folder. if (this._currentFolder) { this._fetchItems(this._currentFolder); } }, /** * Gets called when a folder in the tree is opened. * * @param {jQuery.} $node Tree node. */ folderOpened: function($node) { var repobrowser = this; var folder = cacheRead(repobrowser, getIdFromTreeNode($node)); if (folder) { repobrowser.repositoryManager.folderOpened(folder); } }, /** * This function gets called when a folder in the tree is closed * * @param {object} obj folder data object */ folderClosed: function(obj) { var folder = this._getObjectFromCache(obj); if (folder) { if (this.repositoryManager) { this.repositoryManager.folderClosed(folder); } } }, /** * This function gets called when a folder in the tree is selected * * @param {object} obj folder data object */ folderSelected: function(obj) { if (this.repositoryManager) { this.repositoryManager.folderSelected(obj); } }, /** * Get the selected folder * @return {object} selected folder or undefined */ getSelectedFolder: function () { if (this.repositoryManager) { if (typeof this.repositoryManager.getSelectedFolder === 'function') { return this.repositoryManager.getSelectedFolder(); } } }, /** * Adapt the page size. * @return true if the page size was actually changed, false if not */ _adaptPageSize: function () { var listHeight, newPageSize, container; // if this is off, don't do anything if (!this.adaptPageSize || !this.$_list || !this.rowHeight) { return false; } // get the current height of the container container = this.$_grid.find('.ui-jqgrid-bdiv'); // reduce by 20 px to leave place for a scrollbar listHeight = container.innerHeight() - 20; // do the math if (listHeight) { newPageSize = Math.floor(listHeight / this.rowHeight); if (newPageSize <= 0) { newPageSize = 1; } if (newPageSize !== this.pageSize) { this.pageSize = newPageSize; return true; } else { return false; } } else { return false; } } }); return RepositoryBrowser; }); define('repository-browser-i18n-de', [], function () { 'use strict'; return { 'Browsing': 'Durchsuchen', 'Close': 'Schließen', 'in': 'in', 'Input search text...': 'Suchtext einfügen...', 'numerous': 'zahlreiche', 'of': 'von', 'Repository Browser': 'Repository Browser', 'Search': 'Suchen', 'Searching for': 'Suche nach', 'Viewing': 'Anzeige', 'button.switch-metaview.tooltip': 'Zwischen Metaansicht und normaler Ansicht umschalten' }; }); define('repository-browser-i18n-en', [], function () { 'use strict'; return { 'Browsing': 'Browsing', 'Close': 'Close', 'in': 'in', 'Input search text...': 'Input search text...', 'numerous': 'numerous', 'of': 'of', 'Repository Browser': 'Repository Browser', 'Search': 'Search', 'Searching for': 'Searching for', 'Viewing': 'Viewing', 'button.switch-metaview.tooltip': 'Switch between meta and normal view' }; });