nextcloud/apps/files/js/navigation.js

427 lines
11 KiB
JavaScript

/*
* @Copyright 2014 Vincent Petry <pvince81@owncloud.com>
*
* @author Vincent Petry
* @author Felix Nüsse <felix.nuesse@t-online.de>
*
*
* This file is licensed under the Affero General Public License version 3
* or later.
*
* See the COPYING-README file.
*
*/
(function () {
/**
* @class OCA.Files.Navigation
* @classdesc Navigation control for the files app sidebar.
*
* @param $el element containing the navigation
*/
var Navigation = function ($el) {
this.initialize($el);
};
/**
* @memberof OCA.Files
*/
Navigation.prototype = {
/**
* Currently selected item in the list
*/
_activeItem: null,
/**
* Currently selected container
*/
$currentContent: null,
/**
* Strategy by which the quickaccesslist is sorted
*
* Possible Strategies:
* customorder
* datemodified
* date
* alphabet
*
*/
$sortingStrategy: 'alphabet',
/**
* Key for the quick-acces-list
*/
$quickAccessListKey: 'sublist-favorites',
/**
* Initializes the navigation from the given container
*
* @private
* @param $el element containing the navigation
*/
initialize: function ($el) {
this.$el = $el;
this._activeItem = null;
this.$currentContent = null;
this._setupEvents();
var scope=this;
$.get(OC.generateUrl("/apps/files/api/v1/quickaccess/get/SortingStrategy"), function (data, status) {
scope.$sortingStrategy=data;
scope.setInitialQuickaccessSettings();
});
},
/**
* Setup UI events
*/
_setupEvents: function () {
this.$el.on('click', 'li a', _.bind(this._onClickItem, this))
this.$el.on('click', 'li button', _.bind(this._onClickMenuButton, this));
this._setOnDrag();
},
/**
* Returns the container of the currently active app.
*
* @return app container
*/
getActiveContainer: function () {
return this.$currentContent;
},
/**
* Returns the currently active item
*
* @return item ID
*/
getActiveItem: function () {
return this._activeItem;
},
/**
* Switch the currently selected item, mark it as selected and
* make the content container visible, if any.
*
* @param string itemId id of the navigation item to select
* @param array options "silent" to not trigger event
*/
setActiveItem: function (itemId, options) {
var currentItem = this.$el.find('li[data-id=' + itemId + ']');
var itemDir = currentItem.data('dir');
var itemView = currentItem.data('view');
var oldItemId = this._activeItem;
if (itemId === this._activeItem) {
if (!options || !options.silent) {
this.$el.trigger(
new $.Event('itemChanged', {
itemId: itemId,
previousItemId: oldItemId,
dir: itemDir,
view: itemView
})
);
}
return;
}
this.$el.find('li a').removeClass('active');
if (this.$currentContent) {
this.$currentContent.addClass('hidden');
this.$currentContent.trigger(jQuery.Event('hide'));
}
this._activeItem = itemId;
currentItem.children('a').addClass('active');
this.$currentContent = $('#app-content-' + (itemView !== '' ? itemView : itemId));
this.$currentContent.removeClass('hidden');
if (!options || !options.silent) {
this.$currentContent.trigger(jQuery.Event('show'));
this.$el.trigger(
new $.Event('itemChanged', {
itemId: itemId,
previousItemId: oldItemId,
dir: itemDir,
view: itemView
})
);
}
},
/**
* Returns whether a given item exists
*/
itemExists: function (itemId) {
return this.$el.find('li[data-id=' + itemId + ']').length;
},
/**
* Event handler for when clicking on an item.
*/
_onClickItem: function (ev) {
var $target = $(ev.target);
var itemId = $target.closest('li').attr('data-id');
if (!_.isUndefined(itemId)) {
this.setActiveItem(itemId);
}
ev.preventDefault();
},
/**
* Event handler for when dragging an item
*/
_setOnDrag: function () {
var scope = this;
var element = $("#sublist-favorites");
$(function () {
if (document.getElementById(scope.$quickAccessListKey.toString()).hasAttribute("draggable")) {
element.sortable({
axis: "y",
containment: "parent",
scroll: false,
zIndex: 0,
opacity: 0.5,
tolerance: "pointer",
//revert: 0.05,
//delay: 150,
start: function (event, ui) {
//Fix for offset
ui.helper[0].style.left = '0px';
//Change Icon while dragging
var list = document.getElementById(scope.$quickAccessListKey).getElementsByTagName('li');
for (var j = 0; j < list.length; j++) {
if (!(typeof list[j].getElementsByTagName('a')[0] === 'undefined')) {
list[j].getElementsByTagName('a')[0].classList.remove("nav-icon-files");
list[j].getElementsByTagName('a')[0].classList.add('icon-menu');
}
}
},
stop: function (event, ui) {
//Clean up offset
ui.item.removeAttr("style");
//Change Icon back after dragging
var list = document.getElementById(scope.$quickAccessListKey.toString()).getElementsByTagName('li');
for (var j = 0; j < list.length; j++) {
if (!(typeof list[j].getElementsByTagName('a')[0] === 'undefined')) {
list[j].getElementsByTagName('a')[0].classList.add("nav-icon-files");
list[j].getElementsByTagName('a')[0].classList.remove('icon-menu');
}
}
},
update: function (event, ui) {
var list = document.getElementById(scope.$quickAccessListKey.toString()).getElementsByTagName('li');
var string = [];
for (var j = 0; j < list.length; j++) {
var Object = {
id: j,
name: scope.getCompareValue(list, j, 'alphabet')
};
string.push(Object);
}
var resultorder = JSON.stringify(string);
$.get(OC.generateUrl("/apps/files/api/v1/quickaccess/set/CustomSortingOrder"), {
order: resultorder
}, function (data, status) {
});
}
});
} else {
if (scope.$sortingStrategy === 'customorder') {
scope.$sortingStrategy = 'datemodified';
}
}
});
},
/**
* Event handler for clicking a button
*/
_onClickMenuButton: function (ev) {
var $target = $(ev.target);
var itemId = $target.closest('button').attr('id');
var collapsibleToggles = [];
var dotmenuToggles = [];
// The collapsibleToggles-Array consists of a list of Arrays. Every subarray must contain the Button to listen to at the 0th index,
// and the parent, which should be toggled at the first arrayindex.
collapsibleToggles.push(["#button-collapse-favorites", "#button-collapse-parent-favorites"]);
// The dotmenuToggles-Array consists of a list of Arrays. Every subarray must contain the Button to listen to at the 0th index,
// and the parent, which should be toggled at the first arrayindex.
dotmenuToggles.push(["#dotmenu-button-favorites", "dotmenu-content-favorites"]);
collapsibleToggles.forEach(function foundToggle (item) {
if (item[0] === ("#" + itemId)) {
$(item[1]).toggleClass('open');
var show = 1;
if (!$(item[1]).hasClass('open')) {
show = 0;
}
$.get(OC.generateUrl("/apps/files/api/v1/quickaccess/set/showList"), {show: show}, function (data, status) {
});
}
});
dotmenuToggles.forEach(function foundToggle (item) {
if (item[0] === ("#" + itemId)) {
document.getElementById(item[1]).classList.toggle('open');
}
});
ev.preventDefault();
},
/**
* Sort initially as setup of sidebar for QuickAccess
*/
setInitialQuickaccessSettings: function () {
var quickAccesKey = this.$quickAccessListKey;
var list = document.getElementById(quickAccesKey).getElementsByTagName('li');
var sort = true;
var reverse = false;
if (this.$sortingStrategy === 'datemodified') {
sort = false;
reverse = false;
var scope = this;
$.get(OC.generateUrl("/apps/files/api/v1/quickaccess/get/FavoriteFolders/"), function (data, status) {
for (var i = 0; i < data.favoriteFolders.length; i++) {
for (var j = 0; j < list.length; j++) {
if (scope.getCompareValue(list, j, 'alphabet').toLowerCase() === data.favoriteFolders[i].name.toLowerCase()) {
list[j].setAttribute("mtime", data.favoriteFolders[i].mtime);
}
}
}
scope.QuickSort(list, 0, list.length - 1);
scope.reverse(list);
});
} else if (this.$sortingStrategy === 'alphabet') {
sort = true;
} else if (this.$sortingStrategy === 'date') {
sort = true;
} else if (this.$sortingStrategy === 'customorder') {
var scope = this;
$.get(OC.generateUrl("/apps/files/api/v1/quickaccess/get/CustomSortingOrder"), function (data, status) {
var ordering = JSON.parse(data);
for (var i = 0; i < ordering.length; i++) {
for (var j = 0; j < list.length; j++) {
if (scope.getCompareValue(list, j, 'alphabet').toLowerCase() === ordering[i].name.toLowerCase()) {
list[j].setAttribute("folderPosition", ordering[i].id);
}
}
}
scope.QuickSort(list, 0, list.length - 1);
});
sort = false;
}
if (sort) {
this.QuickSort(list, 0, list.length - 1);
}
if (reverse) {
this.reverse(list);
}
},
/**
* Sorting-Algorithm for QuickAccess
*/
QuickSort: function (list, start, end) {
var lastMatch;
if (list.length > 1) {
lastMatch = this.quicksort_helper(list, start, end);
if (start < lastMatch - 1) {
this.QuickSort(list, start, lastMatch - 1);
}
if (lastMatch < end) {
this.QuickSort(list, lastMatch, end);
}
}
},
/**
* Sorting-Algorithm-Helper for QuickAccess
*/
quicksort_helper: function (list, start, end) {
var pivot = Math.floor((end + start) / 2);
var pivotElement = this.getCompareValue(list, pivot);
var i = start;
var j = end;
while (i <= j) {
while (this.getCompareValue(list, i) < pivotElement) {
i++;
}
while (this.getCompareValue(list, j) > pivotElement) {
j--;
}
if (i <= j) {
this.swap(list, i, j);
i++;
j--;
}
}
return i;
},
/**
* Sorting-Algorithm-Helper for QuickAccess
* This method allows easy access to the element which is sorted by.
*/
getCompareValue: function (nodes, int, strategy) {
if ((typeof strategy === 'undefined')) {
strategy = this.$sortingStrategy;
}
if (strategy === 'alphabet') {
return nodes[int].getElementsByTagName('a')[0].innerHTML.toLowerCase();
} else if (strategy === 'date') {
return nodes[int].getAttribute('folderPosition').toLowerCase();
} else if (strategy === 'datemodified') {
return nodes[int].getAttribute('mtime');
} else if (strategy === 'customorder') {
return nodes[int].getAttribute('folderPosition');
}
return nodes[int].getElementsByTagName('a')[0].innerHTML.toLowerCase();
},
/**
* Sorting-Algorithm-Helper for QuickAccess
* This method allows easy swapping of elements.
*/
swap: function (list, j, i) {
list[i].before(list[j]);
list[j].before(list[i]);
},
/**
* Reverse QuickAccess-List
*/
reverse: function (list) {
var len = list.length - 1;
for (var i = 0; i < len / 2; i++) {
this.swap(list, i, len - i);
}
}
};
OCA.Files.Navigation = Navigation;
})();