2014-05-12 12:57:47 +00:00
|
|
|
|
oml.addList = function() {
|
2014-05-18 23:24:04 +00:00
|
|
|
|
// addList(isSmart, isFrom[, name[, callback]])
|
|
|
|
|
// or addList(list) [=duplicate]
|
2014-05-12 12:57:47 +00:00
|
|
|
|
var args = arguments,
|
|
|
|
|
isDuplicate = args.length == 1,
|
2014-05-18 23:24:04 +00:00
|
|
|
|
isSmart, isFrom, name, callback,
|
|
|
|
|
list, listData, data,
|
2014-05-22 14:20:40 +00:00
|
|
|
|
ui = oml.user.ui,
|
2014-05-12 23:43:27 +00:00
|
|
|
|
username = oml.user.preferences.username;
|
2014-05-17 14:42:46 +00:00
|
|
|
|
Ox.Request.clearCache('getLists');
|
2014-05-12 12:57:47 +00:00
|
|
|
|
oml.api.getLists(function(result) {
|
|
|
|
|
var lists = result.data.lists,
|
2014-05-12 23:43:27 +00:00
|
|
|
|
listNames = lists.filter(function(list) {
|
|
|
|
|
return list.user = username;
|
|
|
|
|
}).map(function(list) {
|
2014-05-12 12:57:47 +00:00
|
|
|
|
return list.name;
|
|
|
|
|
}),
|
|
|
|
|
query;
|
|
|
|
|
if (!isDuplicate) {
|
|
|
|
|
isSmart = args[0];
|
|
|
|
|
isFrom = args[1];
|
2014-05-18 23:24:04 +00:00
|
|
|
|
name = args[2] || Ox._('Untitled');
|
|
|
|
|
callback = args[3];
|
2014-05-12 12:57:47 +00:00
|
|
|
|
data = {
|
2014-05-18 23:24:04 +00:00
|
|
|
|
name: oml.getValidName(name, listNames),
|
2014-05-12 12:57:47 +00:00
|
|
|
|
type: !isSmart ? 'static' : 'smart'
|
|
|
|
|
};
|
2014-05-14 09:57:11 +00:00
|
|
|
|
if (!isSmart) {
|
|
|
|
|
if (isFrom) {
|
2014-05-12 12:57:47 +00:00
|
|
|
|
data.items = ui.listSelection;
|
2014-05-14 09:57:11 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (!isFrom) {
|
|
|
|
|
data.query = oml.config.user.ui.find;
|
2014-05-12 12:57:47 +00:00
|
|
|
|
} else {
|
|
|
|
|
data.query = ui.find;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
addList();
|
|
|
|
|
} else {
|
|
|
|
|
list = args[0];
|
|
|
|
|
listData = Ox.getObjectById(Ox.flatten(Ox.values(lists)), list);
|
|
|
|
|
data = Ox.extend({
|
2014-05-18 23:24:04 +00:00
|
|
|
|
name: oml.getValidName(listData.name, listNames),
|
2014-05-12 12:57:47 +00:00
|
|
|
|
type: listData.type
|
|
|
|
|
}, listData.query ? {
|
|
|
|
|
query: listData.query
|
|
|
|
|
} : {});
|
|
|
|
|
if (!data.query) {
|
|
|
|
|
var query = {
|
|
|
|
|
conditions: [{key: 'list', operator: '==', value: list}],
|
|
|
|
|
operator: '&'
|
|
|
|
|
};
|
|
|
|
|
oml.api.find({query: query}, function(result) {
|
|
|
|
|
if (result.data.items) {
|
|
|
|
|
oml.api.find({
|
|
|
|
|
query: query,
|
|
|
|
|
keys: ['id'],
|
|
|
|
|
sort: [{key: 'id', operator: '+'}],
|
|
|
|
|
range: [0, result.data.items]
|
|
|
|
|
}, function(result) {
|
|
|
|
|
data.items = result.data.items.map(function(item) {
|
|
|
|
|
return item.id;
|
|
|
|
|
});
|
|
|
|
|
addList();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
addList();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
addList();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
function addList() {
|
|
|
|
|
oml.api.addList(data, function(result) {
|
|
|
|
|
var list = result.data.id,
|
|
|
|
|
$folderList = oml.$ui.folderList[0];
|
|
|
|
|
oml.$ui.folder[0].options({collapsed: false}); // FIXME: SET UI!
|
|
|
|
|
// FIXME: DOESN'T WORK
|
2014-05-18 23:24:04 +00:00
|
|
|
|
if (
|
|
|
|
|
!oml.$ui.importExportDialog
|
|
|
|
|
|| !oml.$ui.importExportDialog.is(':visible')
|
|
|
|
|
) {
|
|
|
|
|
$folderList
|
|
|
|
|
.bindEventOnce({
|
|
|
|
|
load: function() {
|
|
|
|
|
$folderList
|
|
|
|
|
.gainFocus()
|
|
|
|
|
.options({selected: [list]});
|
|
|
|
|
oml.UI.set({
|
|
|
|
|
find: {
|
|
|
|
|
conditions: [{
|
|
|
|
|
key: 'list',
|
|
|
|
|
operator: '==',
|
|
|
|
|
value: list
|
|
|
|
|
}],
|
|
|
|
|
operator: '&'
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
oml.$ui.listDialog = oml.ui.listDialog().open();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2014-05-17 14:42:46 +00:00
|
|
|
|
oml.$ui.folders.updateOwnLists();
|
2014-05-18 23:24:04 +00:00
|
|
|
|
callback && callback();
|
2014-05-12 12:57:47 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.clearFilters = function() {
|
|
|
|
|
var ui = oml.user.ui,
|
|
|
|
|
find = Ox.clone(ui.find, true),
|
|
|
|
|
indices = ui._filterState.map(function(filterState) {
|
|
|
|
|
return filterState.index;
|
|
|
|
|
}).filter(function(index) {
|
|
|
|
|
return index > -1;
|
|
|
|
|
});
|
|
|
|
|
find.conditions = find.conditions.filter(function(condition, index) {
|
|
|
|
|
return !Ox.contains(indices, index);
|
|
|
|
|
});
|
|
|
|
|
oml.UI.set({find: find});
|
|
|
|
|
};
|
|
|
|
|
|
2016-01-16 08:40:20 +00:00
|
|
|
|
oml.autovalidateEmail = function(value, blur, callback) {
|
|
|
|
|
value = value.toLowerCase().split('').map(function(v, i) {
|
|
|
|
|
return /[0-9a-z\.\+\-_@]/.test(v) ? v : null;
|
|
|
|
|
}).join('').slice(0, 255);
|
|
|
|
|
callback({valid: Ox.isValidEmail(value), value: value});
|
|
|
|
|
};
|
|
|
|
|
|
2014-05-19 18:12:02 +00:00
|
|
|
|
oml.clickLink = function(e) {
|
|
|
|
|
if (
|
|
|
|
|
e.target.hostname == document.location.hostname
|
|
|
|
|
&& !Ox.startsWith(e.target.pathname, '/static')
|
|
|
|
|
) {
|
|
|
|
|
oml.URL.push(e.target.pathname, true);
|
|
|
|
|
} else {
|
|
|
|
|
oml.openLink(e.target.href);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-05-21 00:02:39 +00:00
|
|
|
|
oml.createLinks = function($element) {
|
|
|
|
|
function isExternalLink(target) {
|
|
|
|
|
return target.hostname != document.location.hostname
|
|
|
|
|
|| Ox.startsWith(target.pathname, '/static');
|
|
|
|
|
}
|
|
|
|
|
$element.on({
|
|
|
|
|
click: function(e) {
|
|
|
|
|
var $target = $(e.target);
|
|
|
|
|
if ($target.is('a')) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
if (isExternalLink(e.target)) {
|
|
|
|
|
oml.openLink(e.target.href);
|
|
|
|
|
} else {
|
|
|
|
|
oml.clickLink(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2014-05-12 12:57:47 +00:00
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
|
|
oml.doHistory = function(action, items, targets, callback) {
|
|
|
|
|
items = Ox.makeArray(items);
|
|
|
|
|
targets = Ox.makeArray(targets);
|
|
|
|
|
if (action == 'copy' || action == 'paste') {
|
|
|
|
|
addItems(items, targets[0], addToHistory);
|
|
|
|
|
} else if (action == 'cut' || action == 'delete') {
|
|
|
|
|
removeItems(items, targets[0], addToHistory);
|
|
|
|
|
} else if (action == 'move') {
|
|
|
|
|
removeItems(items, targets[0], function() {
|
|
|
|
|
addItems(items, targets[1], addToHistory);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
function addToHistory(result, addedItems) {
|
|
|
|
|
var actions = {
|
|
|
|
|
copy: 'Copying',
|
|
|
|
|
cut: 'Cutting',
|
|
|
|
|
'delete': 'Deleting',
|
|
|
|
|
move: 'Moving',
|
|
|
|
|
paste: 'Pasting'
|
|
|
|
|
},
|
|
|
|
|
length = items.length,
|
|
|
|
|
text = Ox._(actions[action]) + ' ' + (
|
|
|
|
|
length == 1 ? 'Book' : 'Books'
|
|
|
|
|
);
|
|
|
|
|
oml.history.add({
|
|
|
|
|
action: action,
|
|
|
|
|
items: action == 'cut' || action == 'delete' ? [items]
|
|
|
|
|
: action == 'copy' || action == 'paste' ? [addedItems]
|
|
|
|
|
: [items, addedItems], // move
|
|
|
|
|
positions: [],
|
|
|
|
|
targets: targets,
|
|
|
|
|
text: text
|
|
|
|
|
});
|
|
|
|
|
callback(result);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.redoHistory = function(callback) {
|
|
|
|
|
var object = oml.history.redo();
|
|
|
|
|
if (object) {
|
|
|
|
|
if (object.action == 'copy' || object.action == 'paste') {
|
|
|
|
|
addItems(object.items[0], object.targets[0], done);
|
|
|
|
|
} else if (object.action == 'cut' || object.action == 'delete') {
|
|
|
|
|
removeItems(object.items[0], object.targets[0], done);
|
|
|
|
|
} else if (object.action == 'move') {
|
|
|
|
|
removeItems(object.items[0], object.targets[0], function() {
|
|
|
|
|
addItems(object.items[1], object.targets[1], done);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function done() {
|
|
|
|
|
doneHistory(object, callback);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.undoHistory = function(callback) {
|
|
|
|
|
var object = oml.history.undo();
|
|
|
|
|
if (object) {
|
|
|
|
|
if (object.action == 'copy' || object.action == 'paste') {
|
|
|
|
|
removeItems(object.items[0], object.targets[0], done);
|
|
|
|
|
} else if (object.action == 'cut' || object.action == 'delete') {
|
|
|
|
|
addItems(object.items[0], object.targets[0], done);
|
|
|
|
|
} else if (object.action == 'move') {
|
|
|
|
|
removeItems(object.items[1], object.targets[1], function() {
|
|
|
|
|
addItems(object.items[0], object.targets[0], done);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function done() {
|
|
|
|
|
doneHistory(object, callback);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function addItems(items, target, callback) {
|
|
|
|
|
oml.api.find({
|
|
|
|
|
query: {
|
|
|
|
|
conditions: [{
|
|
|
|
|
key: 'list',
|
|
|
|
|
operator: '==',
|
|
|
|
|
value: target
|
|
|
|
|
}],
|
|
|
|
|
operator: '&'
|
|
|
|
|
},
|
|
|
|
|
positions: items
|
|
|
|
|
}, function(result) {
|
|
|
|
|
var existingItems = Object.keys(result.data.positions),
|
|
|
|
|
addedItems = items.filter(function(item) {
|
|
|
|
|
return !Ox.contains(existingItems, item);
|
|
|
|
|
});
|
|
|
|
|
if (addedItems.length) {
|
|
|
|
|
oml.api.addListItems({
|
|
|
|
|
items: addedItems,
|
|
|
|
|
list: target
|
|
|
|
|
}, function(result) {
|
2014-05-17 23:14:29 +00:00
|
|
|
|
Ox.Request.clearCache();
|
2014-05-12 12:57:47 +00:00
|
|
|
|
callback(result, addedItems);
|
2016-01-16 06:35:23 +00:00
|
|
|
|
});
|
2014-05-12 12:57:47 +00:00
|
|
|
|
} else {
|
|
|
|
|
callback(null, []);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function doneHistory(object, callback) {
|
|
|
|
|
var list, listData, ui = oml.user.ui;
|
|
|
|
|
Ox.Request.clearCache('find');
|
|
|
|
|
object.targets.filter(function(list) {
|
|
|
|
|
return list != ui._list;
|
|
|
|
|
}).forEach(function(list) {
|
|
|
|
|
listData = oml.getListData(list);
|
|
|
|
|
oml.api.find({
|
|
|
|
|
query: {
|
|
|
|
|
conditions: [{
|
|
|
|
|
key: 'list',
|
|
|
|
|
operator: '==',
|
|
|
|
|
value: list
|
|
|
|
|
}],
|
|
|
|
|
operator: '&'
|
|
|
|
|
}
|
|
|
|
|
}, function(result) {
|
|
|
|
|
oml.$ui.folderList[listData.folder].value(
|
|
|
|
|
list, 'items', result.data.items
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
if (Ox.contains(object.targets, ui._list)) {
|
|
|
|
|
// FIXME: Why is this timeout needed?
|
2016-01-12 08:52:20 +00:00
|
|
|
|
setTimeout(oml.reloadLists, 250);
|
2014-05-12 12:57:47 +00:00
|
|
|
|
}
|
|
|
|
|
callback && callback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function removeItems(items, target, callback) {
|
|
|
|
|
oml.api.removeListItems({
|
|
|
|
|
items: items,
|
|
|
|
|
list: target
|
|
|
|
|
}, callback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}());
|
|
|
|
|
|
|
|
|
|
oml.enableDragAndDrop = function($list, canMove) {
|
|
|
|
|
|
|
|
|
|
var $tooltip = Ox.Tooltip({
|
|
|
|
|
animate: false
|
|
|
|
|
}),
|
|
|
|
|
drag = {},
|
|
|
|
|
scrollInterval,
|
2014-05-25 14:05:26 +00:00
|
|
|
|
ui = oml.user.ui;
|
2014-05-12 12:57:47 +00:00
|
|
|
|
|
|
|
|
|
$list.bindEvent({
|
|
|
|
|
draganddropstart: function(data) {
|
|
|
|
|
var $lists = oml.$ui.libraryList.concat(oml.$ui.folderList);
|
|
|
|
|
drag.action = 'copy';
|
|
|
|
|
drag.ids = $list.options('selected');
|
|
|
|
|
drag.item = drag.ids.length == 1
|
2016-01-05 05:14:50 +00:00
|
|
|
|
? Ox.decodeHTMLEntities($list.value(drag.ids[0], 'title'))
|
2014-05-12 12:57:47 +00:00
|
|
|
|
: drag.ids.length;
|
|
|
|
|
drag.source = oml.getListData();
|
|
|
|
|
drag.targets = {};
|
|
|
|
|
$lists.forEach(function($list) {
|
|
|
|
|
$list.addClass('OxDroppable').find('.OxItem').each(function() {
|
|
|
|
|
var $item = $(this),
|
|
|
|
|
id = $item.data('id'),
|
|
|
|
|
data = oml.getListData(id);
|
|
|
|
|
drag.targets[id] = Ox.extend(data, {
|
|
|
|
|
editable: data.editable || (
|
|
|
|
|
data.type == 'library'
|
2014-05-25 14:05:26 +00:00
|
|
|
|
&& drag.source.user != ''
|
|
|
|
|
&& data.user == ''
|
2014-05-12 12:57:47 +00:00
|
|
|
|
),
|
|
|
|
|
selected: data.id == ui._list
|
|
|
|
|
}, data);
|
|
|
|
|
if (!drag.targets[id].selected && drag.targets[id].editable) {
|
|
|
|
|
$item.addClass('OxDroppable');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
$tooltip.options({title: getTitle()}).show(data.event);
|
2014-09-29 13:17:59 +00:00
|
|
|
|
Ox.$window.on({
|
2014-05-12 12:57:47 +00:00
|
|
|
|
keydown: keydown,
|
|
|
|
|
keyup: keyup
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
draganddrop: function(data) {
|
|
|
|
|
var event = data.event;
|
|
|
|
|
$tooltip.options({
|
|
|
|
|
title: getTitle(event)
|
|
|
|
|
}).show(event);
|
|
|
|
|
if (scrollInterval && !isAtListsTop(event) && !isAtListsBottom(event)) {
|
|
|
|
|
clearInterval(scrollInterval);
|
|
|
|
|
scrollInterval = 0;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
draganddroppause: function(data) {
|
|
|
|
|
var event = data.event, scroll, title,
|
|
|
|
|
ui = oml.user.ui,
|
|
|
|
|
$parent, $grandparent, $panel;
|
|
|
|
|
if (!ui.showSidebar) {
|
|
|
|
|
if (event.clientX < 16 && event.clientY >= 44
|
|
|
|
|
&& event.clientY < window.innerHeight - 16
|
|
|
|
|
) {
|
2014-09-25 11:39:05 +00:00
|
|
|
|
oml.$ui.mainPanel.toggleElement(0);
|
2014-05-12 12:57:47 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$parent = $(event.target).parent();
|
|
|
|
|
$grandparent = $parent.parent();
|
|
|
|
|
$panel = $parent.is('.OxCollapsePanel') ? $parent
|
|
|
|
|
: $grandparent.is('.OxCollapsePanel') ? $grandparent
|
|
|
|
|
: null;
|
|
|
|
|
if ($panel) {
|
|
|
|
|
title = $panel.children('.OxBar').children('.OxTitle')
|
|
|
|
|
.html().split(' ')[0].toLowerCase();
|
|
|
|
|
if (!ui.showFolder[title]) {
|
2014-09-29 13:17:59 +00:00
|
|
|
|
Ox.$elements[$panel.data('oxid')].options({
|
2014-05-12 12:57:47 +00:00
|
|
|
|
collapsed: false
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!scrollInterval) {
|
|
|
|
|
scroll = isAtListsTop(event) ? -16
|
|
|
|
|
: isAtListsBottom(event) ? 16
|
|
|
|
|
: 0
|
|
|
|
|
if (scroll) {
|
|
|
|
|
scrollInterval = setInterval(function() {
|
|
|
|
|
oml.$ui.folders.scrollTop(
|
|
|
|
|
oml.$ui.folders.scrollTop() + scroll
|
|
|
|
|
);
|
|
|
|
|
}, 100);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
draganddropenter: function(data) {
|
|
|
|
|
var $parent = $(data.event.target).parent(),
|
|
|
|
|
$item = $parent.is('.OxItem') ? $parent : $parent.parent(),
|
|
|
|
|
$list = $item.parent().parent().parent().parent();
|
|
|
|
|
if ($list.is('.OxDroppable')) {
|
|
|
|
|
$item.addClass('OxDrop');
|
|
|
|
|
drag.target = drag.targets[$item.data('id')];
|
|
|
|
|
} else {
|
|
|
|
|
drag.target = null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
draganddropleave: function(data) {
|
|
|
|
|
var $parent = $(data.event.target).parent(),
|
|
|
|
|
$item = $parent.is('.OxItem') ? $parent : $parent.parent();
|
|
|
|
|
if ($item.is('.OxDroppable')) {
|
|
|
|
|
$item.removeClass('OxDrop');
|
|
|
|
|
drag.target = null;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
draganddropend: function(data) {
|
|
|
|
|
var targets;
|
2014-09-29 13:17:59 +00:00
|
|
|
|
Ox.$window.off({
|
2014-05-12 12:57:47 +00:00
|
|
|
|
keydown: keydown,
|
|
|
|
|
keyup: keyup
|
|
|
|
|
});
|
|
|
|
|
if (
|
|
|
|
|
drag.target && drag.target.editable && !drag.target.selected
|
|
|
|
|
&& (drag.action == 'copy' || drag.source.editable)
|
|
|
|
|
) {
|
|
|
|
|
var targets = drag.action == 'copy' ? drag.target.id
|
|
|
|
|
: [oml.user.ui._list, drag.target.id];
|
|
|
|
|
oml.doHistory(drag.action, data.ids, targets, function() {
|
|
|
|
|
Ox.Request.clearCache('find');
|
|
|
|
|
oml.api.find({
|
|
|
|
|
query: {
|
|
|
|
|
conditions: [{
|
|
|
|
|
key: 'list',
|
|
|
|
|
operator: '==',
|
|
|
|
|
value: drag.target.id
|
|
|
|
|
}],
|
|
|
|
|
operator: '&'
|
|
|
|
|
}
|
|
|
|
|
}, function(result) {
|
2014-05-12 23:43:27 +00:00
|
|
|
|
/* FIXME
|
2014-05-12 12:57:47 +00:00
|
|
|
|
oml.$ui.folderList[drag.target.folder].value(
|
|
|
|
|
drag.target.id, 'items', result.data.items
|
|
|
|
|
);
|
2014-05-12 23:43:27 +00:00
|
|
|
|
*/
|
2014-05-12 12:57:47 +00:00
|
|
|
|
cleanup(250);
|
|
|
|
|
});
|
2014-05-17 14:42:46 +00:00
|
|
|
|
oml.$ui.folders.updateItems();
|
|
|
|
|
if (drag.action == 'move') {
|
|
|
|
|
oml.$ui.list.updateElement();
|
|
|
|
|
}
|
2014-05-12 12:57:47 +00:00
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
cleanup()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function cleanup(ms) {
|
|
|
|
|
ms = ms || 0;
|
|
|
|
|
drag = {};
|
|
|
|
|
clearInterval(scrollInterval);
|
|
|
|
|
scrollInterval = 0;
|
|
|
|
|
setTimeout(function() {
|
|
|
|
|
$('.OxDroppable').removeClass('OxDroppable');
|
|
|
|
|
$('.OxDrop').removeClass('OxDrop');
|
|
|
|
|
$tooltip.hide();
|
|
|
|
|
}, ms);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTitle() {
|
|
|
|
|
var image, text,
|
|
|
|
|
actionText = drag.action == 'copy' ? (
|
2014-05-25 14:05:26 +00:00
|
|
|
|
drag.source.user == '' ? 'copy' : 'download'
|
2014-05-12 12:57:47 +00:00
|
|
|
|
) : 'move',
|
|
|
|
|
itemText = Ox.isString(drag.item)
|
|
|
|
|
? '"' + Ox.encodeHTMLEntities(Ox.truncate(drag.item, 32)) + '"'
|
|
|
|
|
: Ox._('{0} books', [drag.item]),
|
|
|
|
|
targetText;
|
|
|
|
|
if (drag.action == 'move') {
|
2014-05-25 14:05:26 +00:00
|
|
|
|
if (drag.source.user != '') {
|
2014-05-12 12:57:47 +00:00
|
|
|
|
text = Ox._('You can only remove books<br>from your own lists.');
|
|
|
|
|
} else if (drag.source.type == 'library') {
|
|
|
|
|
text = Ox._('You cannot move books<br>out of your library.');
|
|
|
|
|
} else if (drag.source.type == 'smart') {
|
|
|
|
|
text = Ox._('You cannot move books<br>out of a smart list.');
|
|
|
|
|
}
|
|
|
|
|
} else if (drag.target) {
|
|
|
|
|
targetText = drag.target.type == 'libraries' ? Ox._('a library')
|
|
|
|
|
: drag.target.type == 'library' ? Ox._('your library')
|
|
|
|
|
: Ox._('the list "{0}"', [Ox.encodeHTMLEntities(Ox.truncate(drag.target.name, 32))]);
|
|
|
|
|
if (
|
|
|
|
|
(
|
|
|
|
|
drag.target.type == 'library'
|
2014-05-25 14:05:26 +00:00
|
|
|
|
&& drag.source.user == ''
|
|
|
|
|
&& drag.target.user == ''
|
2014-05-12 12:57:47 +00:00
|
|
|
|
)
|
|
|
|
|
|| drag.target.selected
|
|
|
|
|
) {
|
|
|
|
|
text = Ox._('{0}<br>is already in {1}.', [
|
|
|
|
|
Ox._(itemText[0] == '"' ? '' : 'These ') + itemText,
|
|
|
|
|
targetText
|
|
|
|
|
]);
|
2014-05-25 14:05:26 +00:00
|
|
|
|
} else if (drag.target.user != '') {
|
2014-05-12 12:57:47 +00:00
|
|
|
|
text = Ox._(
|
|
|
|
|
'You can only {0} books<br>to your own {1}.',
|
|
|
|
|
[actionText, drag.target.type == 'library' ? 'library' : 'lists']
|
|
|
|
|
);
|
|
|
|
|
} else if (drag.target.type == 'smart') {
|
|
|
|
|
text = Ox._('You cannot {0} books<br>to a smart list.', [actionText]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (text) {
|
|
|
|
|
image = 'symbolClose'
|
|
|
|
|
} else {
|
|
|
|
|
image = drag.action == 'copy' ? (
|
2014-05-25 14:05:26 +00:00
|
|
|
|
drag.source.user == '' ? 'symbolAdd' : 'symbolDownload'
|
2014-05-12 12:57:47 +00:00
|
|
|
|
) : 'symbolRemove',
|
|
|
|
|
text = Ox._(Ox.toTitleCase(actionText)) + ' ' + (
|
|
|
|
|
Ox.isString(drag.item)
|
|
|
|
|
? '"' + Ox.encodeHTMLEntities(Ox.truncate(drag.item, 32)) + '"'
|
|
|
|
|
: drag.item + ' ' + 'books'
|
|
|
|
|
) + '<br>' + (
|
|
|
|
|
drag.target && drag.target.editable && !drag.target.selected
|
|
|
|
|
? Ox._('to {0}.', [targetText])
|
2014-05-25 14:05:26 +00:00
|
|
|
|
: drag.source.user == ''
|
2014-05-12 12:57:47 +00:00
|
|
|
|
? Ox._('to {0} list.', [ui._list == ':' ? 'a' : 'another'])
|
|
|
|
|
: Ox._('to your library or to one of your lists.')
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return $('<div>')
|
|
|
|
|
.append(
|
|
|
|
|
$('<div>')
|
|
|
|
|
.css({
|
|
|
|
|
float: 'left',
|
|
|
|
|
width: '16px',
|
|
|
|
|
height: '16px',
|
|
|
|
|
padding: '1px',
|
|
|
|
|
border: '3px solid rgb(' + Ox.Theme.getThemeData().symbolDefaultColor.join(', ') + ')',
|
|
|
|
|
borderRadius: '12px',
|
|
|
|
|
margin: '3px 2px 2px 2px'
|
|
|
|
|
})
|
|
|
|
|
.append(
|
|
|
|
|
$('<img>')
|
|
|
|
|
.attr({src: Ox.UI.getImageURL(image)})
|
|
|
|
|
.css({width: '16px', height: '16px'})
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
.append(
|
|
|
|
|
$('<div>')
|
|
|
|
|
.css({
|
|
|
|
|
float: 'left',
|
|
|
|
|
margin: '1px 2px 2px 2px',
|
|
|
|
|
fontSize: '11px',
|
|
|
|
|
whiteSpace: 'nowrap'
|
|
|
|
|
})
|
|
|
|
|
.html(text)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isAtListsTop(e) {
|
|
|
|
|
return ui.showSidebar
|
|
|
|
|
&& e.clientX < ui.sidebarSize
|
|
|
|
|
&& e.clientY >= 44 && e.clientY < 60;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isAtListsBottom(e) {
|
|
|
|
|
var listsBottom = window.innerHeight - oml.getInfoHeight();
|
|
|
|
|
return ui.showSidebar
|
|
|
|
|
&& e.clientX < ui.sidebarSize
|
|
|
|
|
&& e.clientY >= listsBottom - 16 && e.clientY < listsBottom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function keydown(e) {
|
|
|
|
|
if (e.metaKey) {
|
|
|
|
|
drag.action = 'move';
|
|
|
|
|
$tooltip.options({title: getTitle()}).show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function keyup(e) {
|
|
|
|
|
if (drag.action == 'move') {
|
|
|
|
|
drag.action = 'copy';
|
|
|
|
|
$tooltip.options({title: getTitle()}).show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
2016-01-14 09:25:14 +00:00
|
|
|
|
oml.formatAuthor = function(author) {
|
|
|
|
|
var isEditor = false;
|
|
|
|
|
return (author || []).map(function(value) {
|
|
|
|
|
if (Ox.endsWith(value, ' (Ed.)')) {
|
|
|
|
|
isEditor = true;
|
|
|
|
|
value = value.slice(0, -6);
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
}).join(', ') + (isEditor ? ' (Ed.)' : '');
|
|
|
|
|
};
|
|
|
|
|
|
2014-05-14 09:57:11 +00:00
|
|
|
|
oml.getEditTooltip = function(title) {
|
|
|
|
|
return function(e) {
|
|
|
|
|
var $target = $(e.target);
|
|
|
|
|
return (
|
|
|
|
|
$target.is('a') || $target.parents('a').length
|
|
|
|
|
? Ox._('Shift+doubleclick to edit') : Ox._('Doubleclick to edit')
|
|
|
|
|
) + (title ? ' ' + Ox._(title) : '');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2014-05-04 17:26:43 +00:00
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
|
|
// Note: getFindState has to run after getListState and getFilterState
|
|
|
|
|
|
|
|
|
|
function everyCondition(conditions, key, operator) {
|
|
|
|
|
// If every condition has the given key and operator
|
|
|
|
|
// (excluding conditions where all subconditions match)
|
|
|
|
|
// returns true, otherwise false
|
|
|
|
|
return Ox.every(conditions, function(condition) {
|
|
|
|
|
return condition.key == key && condition.operator == operator;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function oneCondition(conditions, key, operator, includeSubconditions) {
|
|
|
|
|
// If exactly one condition has the given key and operator
|
|
|
|
|
// (including or excluding conditions where all subconditions match)
|
|
|
|
|
// returns the corresponding index, otherwise returns -1
|
|
|
|
|
var indices = Ox.indicesOf(conditions, function(condition) {
|
|
|
|
|
return (
|
|
|
|
|
condition.conditions
|
|
|
|
|
? includeSubconditions && everyCondition(condition.conditions, key, operator)
|
|
|
|
|
: condition.key == key && condition.operator == operator
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
return indices.length == 1 ? indices[0] : -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
oml.getFindState = function(find) {
|
|
|
|
|
// The find element is populated if exactly one condition in an & query
|
|
|
|
|
// has a findKey as key and "=" as operator (and all other conditions
|
|
|
|
|
// are either list or filters), or if all conditions in an | query have
|
|
|
|
|
// the same filter id as key and "==" as operator
|
|
|
|
|
Ox.Log('Find', 'getFindState', find)
|
|
|
|
|
// FIXME: this is still incorrect when you select a lot of filter items
|
|
|
|
|
// and reload the page (will be advanced)
|
|
|
|
|
var conditions,
|
2016-02-07 13:53:10 +00:00
|
|
|
|
indices,
|
|
|
|
|
state = {index: -1, key: '*', value: ''},
|
|
|
|
|
ui = oml.user.ui;
|
2014-05-04 17:26:43 +00:00
|
|
|
|
if (find.operator == '&') {
|
|
|
|
|
// number of conditions that are not list or filters
|
|
|
|
|
conditions = find.conditions.length
|
|
|
|
|
- !!ui._list
|
|
|
|
|
- ui._filterState.filter(function(filter) {
|
|
|
|
|
return filter.index > -1;
|
|
|
|
|
}).length;
|
|
|
|
|
// indices of non-advanced find queries
|
|
|
|
|
indices = oml.config.findKeys.map(function(findKey) {
|
|
|
|
|
return oneCondition(find.conditions, findKey.id, '=');
|
|
|
|
|
}).filter(function(index) {
|
|
|
|
|
return index > -1;
|
|
|
|
|
});
|
|
|
|
|
state = conditions == 1 && indices.length == 1 ? {
|
|
|
|
|
index: indices[0],
|
|
|
|
|
key: find.conditions[indices[0]].key,
|
|
|
|
|
value: Ox.decodeURIComponent(find.conditions[indices[0]].value)
|
|
|
|
|
} : {
|
|
|
|
|
index: -1,
|
|
|
|
|
key: conditions == 0 && indices.length == 0 ? '*' : 'advanced',
|
|
|
|
|
value: ''
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
state = {
|
|
|
|
|
index: -1,
|
|
|
|
|
key: 'advanced',
|
|
|
|
|
value: ''
|
|
|
|
|
};
|
|
|
|
|
Ox.forEach(ui.filters, function(key) {
|
|
|
|
|
if (everyCondition(find.conditions, key, '==')) {
|
|
|
|
|
state.key = '*';
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return state;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oml.getFilterState = function(find) {
|
|
|
|
|
// A filter is selected if exactly one condition in an & query or every
|
|
|
|
|
// condition in an | query has the filter id as key and "==" as operator
|
2016-02-07 13:53:10 +00:00
|
|
|
|
var ui = oml.user.ui;
|
2014-05-04 17:26:43 +00:00
|
|
|
|
return ui.filters.map(function(filter) {
|
|
|
|
|
// FIXME: cant index be an empty array, instead of -1?
|
|
|
|
|
var key = filter.id,
|
|
|
|
|
state = {index: -1, find: Ox.clone(find, true), selected: []};
|
|
|
|
|
if (find.operator == '&') {
|
|
|
|
|
// include conditions where all subconditions match
|
|
|
|
|
state.index = oneCondition(find.conditions, key, '==', true);
|
|
|
|
|
if (state.index > -1) {
|
|
|
|
|
state.selected = find.conditions[state.index].conditions
|
|
|
|
|
? find.conditions[state.index].conditions.map(function(condition) {
|
|
|
|
|
return condition.value;
|
|
|
|
|
})
|
|
|
|
|
: [find.conditions[state.index].value];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (everyCondition(find.conditions, key, '==')) {
|
|
|
|
|
state.index = Ox.range(find.conditions.length);
|
|
|
|
|
state.selected = find.conditions.map(function(condition) {
|
|
|
|
|
return condition.value;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (state.selected.length) {
|
|
|
|
|
if (Ox.isArray(state.index)) {
|
|
|
|
|
// every condition in an | query matches this filter
|
|
|
|
|
state.find = {conditions: [], operator: ''};
|
|
|
|
|
} else {
|
|
|
|
|
// one condition in an & query matches this filter
|
|
|
|
|
state.find.conditions.splice(state.index, 1);
|
|
|
|
|
if (
|
|
|
|
|
state.find.conditions.length == 1
|
|
|
|
|
&& state.find.conditions[0].conditions
|
|
|
|
|
) {
|
|
|
|
|
// unwrap single remaining bracketed query
|
|
|
|
|
state.find = {
|
|
|
|
|
conditions: state.find.conditions[0].conditions,
|
|
|
|
|
operator: state.find.conditions[0].operator
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return state;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oml.getListState = function(find) {
|
|
|
|
|
// A list is selected if exactly one condition in an & query has "list"
|
|
|
|
|
// as key and "==" as operator
|
|
|
|
|
var index, state = '';
|
|
|
|
|
if (find.operator == '&') {
|
|
|
|
|
index = oneCondition(find.conditions, 'list', '==');
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
state = find.conditions[index].value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return state;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}());
|
|
|
|
|
|
2014-05-21 00:02:39 +00:00
|
|
|
|
oml.getFilterSizes = function() {
|
|
|
|
|
var ui = oml.user.ui;
|
|
|
|
|
return Ox.splitInt(
|
|
|
|
|
window.innerWidth - ui.showSidebar * ui.sidebarSize - 1,
|
|
|
|
|
5
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.getIconInfoColor = function(type, data) {
|
2014-05-12 12:57:47 +00:00
|
|
|
|
return type == 'extension' ? (
|
2016-01-16 08:53:44 +00:00
|
|
|
|
data.extension == 'cbr' ? [[224, 224, 32], [192, 192, 0], [255, 255, 192]]
|
|
|
|
|
: data.extension == 'epub' ? [[32, 160, 32], [0, 128, 0], [128, 255, 128]]
|
2014-05-04 17:26:43 +00:00
|
|
|
|
: data.extension == 'pdf' ? (
|
2014-05-12 12:57:47 +00:00
|
|
|
|
data.textsize
|
|
|
|
|
? [[224, 32, 32], [192, 0, 0], [255, 192, 192]]
|
|
|
|
|
: [[224, 128, 32], [192, 96, 0], [255, 192, 128]]
|
2014-05-04 17:26:43 +00:00
|
|
|
|
)
|
2014-05-12 12:57:47 +00:00
|
|
|
|
: data.extension == 'txt' ? [[255, 255, 255], [224, 224, 224], [0, 0, 0]]
|
|
|
|
|
: [[96, 96, 96], [64, 64, 64], [192, 192, 192]]
|
|
|
|
|
) : data.mediastate == 'available' ? [[32, 160, 32], [0, 128, 0], [128, 255, 128]]
|
|
|
|
|
: data.mediastate == 'transferring' ? [[160, 160, 32], [128, 128, 0], [255, 255, 128]]
|
|
|
|
|
: [[224, 32, 32], [192, 0, 0], [255, 192, 192]];
|
2014-05-04 17:26:43 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-05-12 12:57:47 +00:00
|
|
|
|
oml.getInfoHeight = function() {
|
|
|
|
|
return Math.min(
|
|
|
|
|
oml.user.ui.sidebarSize,
|
|
|
|
|
window.innerHeight - 20 - 24 - 16 - 1
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.getListData = function(list) {
|
2014-05-14 09:57:11 +00:00
|
|
|
|
var ui = oml.user.ui;
|
|
|
|
|
list = Ox.isUndefined(list) ? ui._list : list;
|
|
|
|
|
return ui._lists ? Ox.getObjectById(ui._lists, list) : {};
|
2014-05-12 12:57:47 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-05-04 17:26:43 +00:00
|
|
|
|
oml.getListFoldersHeight = function() {
|
|
|
|
|
var ui = oml.user.ui;
|
2014-05-19 15:00:33 +00:00
|
|
|
|
return oml.$ui.folder.reduce(function(value, $folder, index) {
|
2014-05-04 17:26:43 +00:00
|
|
|
|
var items = oml.$ui.folderList[index].options('items').length;
|
2014-05-19 15:00:33 +00:00
|
|
|
|
return value + 16 + !$folder.options('collapsed') * (1 + items) * 16;
|
2014-05-04 17:26:43 +00:00
|
|
|
|
}, 16);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.getListFoldersWidth = function() {
|
|
|
|
|
var ui = oml.user.ui;
|
|
|
|
|
return ui.sidebarSize - (
|
|
|
|
|
oml.$ui.appPanel
|
|
|
|
|
&& oml.getListFoldersHeight()
|
2014-05-12 12:57:47 +00:00
|
|
|
|
> window.innerHeight - 20 - 24 - 1 - ui.showInfo * oml.getInfoHeight()
|
2014-05-04 17:26:43 +00:00
|
|
|
|
? Ox.UI.SCROLLBAR_SIZE : 0
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2014-05-18 23:24:04 +00:00
|
|
|
|
oml.getLists = function(callback) {
|
|
|
|
|
var ui = oml.user.ui;
|
|
|
|
|
Ox.Request.clearCache('getLists');
|
|
|
|
|
oml.api.getLists(function(result) {
|
|
|
|
|
ui._lists = result.data.lists.map(function(list) {
|
|
|
|
|
// FIXME: 'editable' is notoriously vague
|
|
|
|
|
list.name = list.type == 'libraries' ? Ox._('Libraries')
|
|
|
|
|
: list.type == 'library' ? Ox._('Library') : list.name;
|
|
|
|
|
return Ox.extend(list, {
|
2014-05-25 14:05:26 +00:00
|
|
|
|
editable: list.user == '' && list.type == 'static',
|
2014-05-25 12:16:04 +00:00
|
|
|
|
own: list.user == '',
|
2016-01-11 17:59:42 +00:00
|
|
|
|
title: Ox.encodeHTMLEntities((list.user ? list.user + ': ' : '') + list.name)
|
2014-05-18 23:24:04 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
callback(ui._lists);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.getOwnListNames = function() {
|
2014-10-31 11:46:32 +00:00
|
|
|
|
var ui = oml.user.ui;
|
2014-05-18 23:24:04 +00:00
|
|
|
|
return ui._lists.filter(function(list) {
|
2014-10-31 11:46:32 +00:00
|
|
|
|
return list.user == '' && list.type != 'library';
|
|
|
|
|
}).map(function(list) {
|
2014-05-18 23:24:04 +00:00
|
|
|
|
return list.name;
|
|
|
|
|
});
|
2014-10-31 11:46:32 +00:00
|
|
|
|
};
|
2014-05-18 23:24:04 +00:00
|
|
|
|
|
2014-05-12 12:57:47 +00:00
|
|
|
|
oml.getPageTitle = function(stateOrURL) {
|
2016-02-07 13:53:10 +00:00
|
|
|
|
var page = Ox.getObjectById(
|
2014-05-12 12:57:47 +00:00
|
|
|
|
oml.config.pages,
|
|
|
|
|
Ox.isObject(stateOrURL) ? stateOrURL.page : stateOrURL.slice(1)
|
|
|
|
|
);
|
2016-02-07 13:53:10 +00:00
|
|
|
|
return (page ? page.title + ' – ' : '') + 'Open Media Library';
|
2014-05-12 12:57:47 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.getSortOperator = function(key) {
|
|
|
|
|
var itemKey = Ox.getObjectById(oml.config.itemKeys, key);
|
|
|
|
|
return itemKey.sortOperator
|
|
|
|
|
|| Ox.contains(
|
|
|
|
|
['string', 'text'],
|
|
|
|
|
Ox.isArray(itemKey.type) ? itemKey.type[0] : itemKey.type
|
|
|
|
|
) ? '+' : '-';
|
|
|
|
|
};
|
|
|
|
|
|
2014-05-18 23:24:04 +00:00
|
|
|
|
oml.getUsers = function(callback) {
|
2014-05-25 18:06:12 +00:00
|
|
|
|
var ui = oml.user.ui;
|
|
|
|
|
Ox.Request.clearCache('getUsers');
|
|
|
|
|
oml.api.getUsers(function(result) {
|
2014-05-27 15:29:10 +00:00
|
|
|
|
var users = [{
|
2014-05-12 12:57:47 +00:00
|
|
|
|
id: oml.user.id,
|
2014-05-25 12:16:04 +00:00
|
|
|
|
name: '',
|
2014-05-12 12:57:47 +00:00
|
|
|
|
online: oml.user.online
|
2014-05-25 18:06:12 +00:00
|
|
|
|
}].concat(
|
|
|
|
|
Ox.sortBy(result.data.users.filter(function(user) {
|
2014-05-12 12:57:47 +00:00
|
|
|
|
return user.peered;
|
2014-05-25 18:06:12 +00:00
|
|
|
|
}), 'index')
|
2014-05-12 12:57:47 +00:00
|
|
|
|
);
|
2014-05-25 12:16:04 +00:00
|
|
|
|
ui._users = users;
|
|
|
|
|
callback(users);
|
|
|
|
|
});
|
2014-05-12 12:57:47 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-05-18 23:24:04 +00:00
|
|
|
|
oml.getValidName = function(value, names, chars) {
|
|
|
|
|
var index = 1, length = 256, suffix;
|
|
|
|
|
if (chars) {
|
|
|
|
|
value = value.replace(
|
|
|
|
|
new RegExp('[' + Ox.escapeRegExp(chars) + ']', 'g'),
|
|
|
|
|
''
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
value = Ox.clean(Ox.clean(value).slice(0, length));
|
|
|
|
|
names = names || [];
|
|
|
|
|
while (Ox.contains(names, value)) {
|
|
|
|
|
suffix = ' [' + (++index) + ']';
|
|
|
|
|
value = value.replace(/ \[\d+\]$/, '')
|
|
|
|
|
.slice(0, length - suffix.length) + suffix;
|
|
|
|
|
};
|
|
|
|
|
return value;
|
|
|
|
|
};
|
|
|
|
|
|
2014-05-04 17:26:43 +00:00
|
|
|
|
oml.hasDialogOrScreen = function() {
|
|
|
|
|
return !!$('.OxDialog:visible').length
|
|
|
|
|
|| !!$('.OxFullscreen').length
|
|
|
|
|
|| !!$('.OxScreen').length;
|
|
|
|
|
};
|
|
|
|
|
|
2014-05-19 18:12:02 +00:00
|
|
|
|
oml.openLink = function(url) {
|
2016-01-16 12:05:35 +00:00
|
|
|
|
window.open(url);
|
2014-05-19 18:12:02 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-01-12 08:52:20 +00:00
|
|
|
|
oml.reloadLists = function() {
|
|
|
|
|
Ox.Request.clearCache('find');
|
2016-01-16 08:57:38 +00:00
|
|
|
|
if (oml.user.ui.showFilters) {
|
|
|
|
|
oml.$ui.filters.forEach(function($filter) {
|
|
|
|
|
$filter.reloadList(true);
|
|
|
|
|
});
|
|
|
|
|
}
|
2016-01-12 08:52:20 +00:00
|
|
|
|
oml.$ui.list.reloadList(true);
|
2016-01-16 08:57:38 +00:00
|
|
|
|
oml.$ui.browser.reloadList(true);
|
2014-05-12 12:57:47 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-05-25 14:05:26 +00:00
|
|
|
|
oml.renameUser = function(data) {
|
2014-05-25 18:06:12 +00:00
|
|
|
|
|
2014-05-25 14:05:26 +00:00
|
|
|
|
var ui = oml.user.ui,
|
|
|
|
|
index = Ox.getIndexById(ui._users, data.id),
|
2015-12-02 21:05:23 +00:00
|
|
|
|
name,
|
2014-05-25 18:06:12 +00:00
|
|
|
|
set = {},
|
2015-12-02 21:05:23 +00:00
|
|
|
|
oldFind,
|
|
|
|
|
newFind;
|
|
|
|
|
if (index == -1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-05-25 18:06:12 +00:00
|
|
|
|
|
2015-12-02 21:05:23 +00:00
|
|
|
|
name = ui._users[index].name;
|
|
|
|
|
oldFind = Ox.clone(ui.find, true);
|
|
|
|
|
newFind = Ox.clone(ui.find, true);
|
2014-05-25 14:05:26 +00:00
|
|
|
|
ui._users[index].name = data.name;
|
|
|
|
|
ui._users[index].nickname = data.nickname;
|
2016-01-05 15:13:42 +00:00
|
|
|
|
set['showFolder.' + oml.UI.encode(name)] = null;
|
|
|
|
|
set['showFolder.' + oml.UI.encode(data.name)] = ui.showFolder[name];
|
2014-05-25 14:05:26 +00:00
|
|
|
|
Ox.forEach(ui.lists, function(value, key) {
|
|
|
|
|
var split = key.split(':'),
|
|
|
|
|
username = split[0],
|
|
|
|
|
listname = split.slice(1).join(':');
|
|
|
|
|
if (username == name) {
|
2016-01-05 15:13:42 +00:00
|
|
|
|
set['lists.' + oml.UI.encode(key)] = null;
|
|
|
|
|
set['lists.' + oml.UI.encode(data.name + ':' + listname)] = value;
|
2014-05-25 14:05:26 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
2014-05-25 18:06:12 +00:00
|
|
|
|
|
|
|
|
|
ui._lists.filter(function(list) {
|
|
|
|
|
return list.user === '' && list.type == 'smart';
|
|
|
|
|
}).forEach(function(list) {
|
|
|
|
|
updateConditions(list.query);
|
|
|
|
|
});
|
2014-05-25 14:05:26 +00:00
|
|
|
|
oml.UI.set(set, false);
|
2014-05-25 18:06:12 +00:00
|
|
|
|
|
|
|
|
|
updateConditions(newFind);
|
|
|
|
|
if (!Ox.isEqual(oldFind, newFind)) {
|
|
|
|
|
oml.replaceURL = true;
|
|
|
|
|
oml.UI.set({find: newFind}, false);
|
|
|
|
|
}
|
|
|
|
|
oml.$ui.folders.updateUser(index);
|
|
|
|
|
|
|
|
|
|
function updateCondition(condition) {
|
|
|
|
|
if (condition.key == 'list') {
|
|
|
|
|
condition.value = condition.value.replace(
|
|
|
|
|
new RegExp('^' + Ox.escapeRegExp(name) + ':'),
|
|
|
|
|
data.name + ':'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateConditions(query) {
|
|
|
|
|
query.conditions.forEach(function(condition) {
|
|
|
|
|
if (!condition.conditions) {
|
|
|
|
|
updateCondition(condition);
|
|
|
|
|
} else {
|
|
|
|
|
condition.conditions.forEach(updateCondition);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
2016-01-08 05:31:48 +00:00
|
|
|
|
|
2014-05-25 14:05:26 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-05-04 17:26:43 +00:00
|
|
|
|
oml.resizeFilters = function() {
|
|
|
|
|
// ...
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.resizeListFolders = function() {
|
|
|
|
|
// FIXME: does this have to be here?
|
|
|
|
|
var width = oml.getListFoldersWidth(),
|
2015-04-20 07:50:42 +00:00
|
|
|
|
columnWidth = width - 16 - 48;
|
2014-05-04 17:26:43 +00:00
|
|
|
|
oml.$ui.librariesList
|
2014-05-17 11:45:57 +00:00
|
|
|
|
.css({width: width + 'px'})
|
|
|
|
|
.resizeColumn('name', columnWidth);
|
2014-05-04 17:26:43 +00:00
|
|
|
|
Ox.forEach(oml.$ui.folder, function($folder, index) {
|
|
|
|
|
$folder.css({width: width + 'px'});
|
|
|
|
|
oml.$ui.libraryList[index]
|
2014-05-17 11:45:57 +00:00
|
|
|
|
.css({width: width + 'px'})
|
|
|
|
|
.resizeColumn('name', columnWidth);
|
2014-05-04 17:26:43 +00:00
|
|
|
|
oml.$ui.folderList[index]
|
2014-05-17 11:45:57 +00:00
|
|
|
|
.css({width: width + 'px'})
|
|
|
|
|
.resizeColumn('name', columnWidth);
|
2014-05-04 17:26:43 +00:00
|
|
|
|
});
|
2014-05-19 15:00:33 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.resizeWindow = function() {
|
|
|
|
|
oml.$ui.leftPanel && oml.$ui.leftPanel.size(2, oml.getInfoHeight());
|
|
|
|
|
oml.resizeListFolders();
|
2016-01-12 13:41:52 +00:00
|
|
|
|
oml.$ui.viewPanel && oml.$ui.viewPanel.updateElement();
|
2014-05-19 18:12:02 +00:00
|
|
|
|
oml.$ui.list && oml.$ui.list.size();
|
2014-05-04 17:26:43 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.updateFilterMenus = function() {
|
|
|
|
|
// FIXME: does this have to be a utils function?
|
|
|
|
|
var selected = oml.$ui.filters.map(function($filter) {
|
|
|
|
|
return !Ox.isEmpty($filter.options('selected'));
|
|
|
|
|
}),
|
|
|
|
|
filtersHaveSelection = !!Ox.sum(selected);
|
|
|
|
|
oml.$ui.filters.forEach(function($filter, index) {
|
|
|
|
|
$filter[
|
|
|
|
|
selected[index] ? 'enableMenuItem' : 'disableMenuItem'
|
|
|
|
|
]('clearFilter');
|
|
|
|
|
$filter[
|
|
|
|
|
filtersHaveSelection ? 'enableMenuItem' : 'disableMenuItem'
|
|
|
|
|
]('clearFilters');
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
oml.validatePublicKey = function(value) {
|
2015-11-26 00:26:10 +00:00
|
|
|
|
return /^[a-z0-9+\/]{16}$/.test(value);
|
2014-05-04 17:26:43 +00:00
|
|
|
|
};
|
|
|
|
|
|
2015-05-14 11:40:29 +00:00
|
|
|
|
oml.updateDebugMenu = function() {
|
|
|
|
|
var menu = $('.OxTitle').filter(function(i, e) {
|
|
|
|
|
return e.innerHTML == 'Debug'
|
|
|
|
|
});
|
|
|
|
|
oml.user.ui.showDebugMenu ? menu.show() : menu.hide();
|
|
|
|
|
};
|
2015-06-06 17:54:44 +00:00
|
|
|
|
|
2019-01-13 13:04:38 +00:00
|
|
|
|
oml.supportedExtensions = ['pdf', 'epub', 'kepub', 'cbr', 'cbz', 'txt'];
|
2016-01-13 16:17:51 +00:00
|
|
|
|
|
|
|
|
|
oml.upload = function(fileslist, callback) {
|
|
|
|
|
var files = [], ids = [];
|
|
|
|
|
for (var i = 0; i < fileslist.length; i++) {
|
2016-03-18 18:31:42 +00:00
|
|
|
|
var extension = Ox.last(fileslist[i].name.split('.')).toLowerCase();
|
2015-06-06 17:54:44 +00:00
|
|
|
|
if (Ox.contains(oml.supportedExtensions, extension)) {
|
2016-01-13 16:17:51 +00:00
|
|
|
|
files.push(fileslist[i]);
|
2015-06-06 17:54:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-01-13 16:17:51 +00:00
|
|
|
|
Ox.serialForEach(files, function(file, index, array, next) {
|
|
|
|
|
var request = new XMLHttpRequest(),
|
|
|
|
|
url = '/api/upload/';
|
|
|
|
|
request.onreadystatechange = function() {
|
|
|
|
|
if (request.readyState == 4) {
|
|
|
|
|
if (request.status == 200) {
|
|
|
|
|
var response = JSON.parse(request.responseText);
|
2016-01-20 07:44:38 +00:00
|
|
|
|
ids = ids.concat(response.data.ids);
|
|
|
|
|
next();
|
2016-01-13 16:17:51 +00:00
|
|
|
|
} else {
|
|
|
|
|
callback(null, {
|
|
|
|
|
code: request.status,
|
|
|
|
|
text: request.statusText
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
var formData = new FormData();
|
|
|
|
|
formData.append('files', file);
|
|
|
|
|
if (oml.user.ui._list[0] == ':' && oml.user.ui._list.length > 1) {
|
|
|
|
|
formData.append('list', oml.user.ui._list.slice(1));
|
|
|
|
|
}
|
|
|
|
|
request.open('post', url, true);
|
|
|
|
|
request.send(formData);
|
|
|
|
|
}, function() {
|
|
|
|
|
callback({
|
|
|
|
|
'status': {'code': 200},
|
|
|
|
|
'data': {'ids': ids}
|
|
|
|
|
});
|
|
|
|
|
});
|
2015-06-06 17:54:44 +00:00
|
|
|
|
};
|