lots of stuff (part2)

This commit is contained in:
j 2014-05-21 02:02:39 +02:00
parent feddea0ccd
commit 0d77cfd158
14 changed files with 767 additions and 578 deletions

View file

@ -1,5 +1,5 @@
{
"coverRatio": 0.75,
"iconRatio": 0.75,
"itemKeys": [
{
"id": "*",
@ -110,6 +110,7 @@
"title": "Extension",
"type": "string",
"columnWidth": 80,
"format": {"type": "upper", "args": []},
"sort": true
},
{
@ -194,51 +195,44 @@
"sort": true
},
{
"id": "isbn10",
"title": "ISBN-10",
"type": "string",
"columnWidth": 96,
"sort": true
},
{
"id": "isbn13",
"title": "ISBN-13",
"type": "string",
"id": "isbn",
"title": "ISBN",
"type": ["string"],
"columnWidth": 96,
"sort": true
},
{
"id": "asin",
"title": "ASIN",
"type": "string",
"type": ["string"],
"columnWidth": 96,
"sort": true
},
{
"id": "lccn",
"title": "LCCN",
"type": "string",
"type": ["string"],
"columnWidth": 96,
"sort": true
},
{
"id": "olid",
"title": "OLID",
"type": "string",
"type": ["string"],
"columnWidth": 96,
"sort": true
},
{
"id": "oclc",
"title": "OCLC",
"type": "string",
"type": ["string"],
"columnWidth": 96,
"sort": true
},
{
"id": "mainid",
"title": "Main ID",
"type": "string"
"id": "primaryid",
"title": "Primary ID",
"type": ["string"]
},
{
"id": "random",
@ -319,7 +313,6 @@
"username": ""
},
"ui": {
"coverSize": 256,
"fileInfo": "extension",
"filters": [
{"id": "author", "sort": [{"key": "items", "operator": "-"}]},
@ -331,6 +324,8 @@
"filtersSize": 176,
"find": {"conditions": [], "operator": "&"},
"icons": "cover",
"iconInfo": "extension",
"iconSize": 256,
"item": "",
"itemView": "info",
"listColumns": ["title", "author", "publisher", "date"],
@ -354,9 +349,9 @@
"section": "books",
"showBrowser": true,
"showDebugMenu": false,
"showFileInfo": true,
"showFolder": {},
"showFilters": true,
"showIconInfo": true,
"showInfo": true,
"showSection": {
"notifications": {

View file

@ -0,0 +1,38 @@
"""empty message
Revision ID: 1fe914156ac0
Revises: 4480ecc50e04
Create Date: 2014-05-20 18:29:36.352416
"""
# revision identifiers, used by Alembic.
revision = '1fe914156ac0'
down_revision = '4480ecc50e04'
from alembic import op
import sqlalchemy as sa
def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('item', sa.Column('sort_isbn', sa.String(length=1000), nullable=True))
op.create_index(op.f('ix_item_sort_isbn'), 'item', ['sort_isbn'], unique=False)
#op.drop_column('item', 'sort_isbn13')
#op.drop_column('item', 'sort_isbn10')
#op.drop_index('ix_item_sort_isbn10', table_name='item')
#op.drop_index('ix_item_sort_isbn13', table_name='item')
### end Alembic commands ###
pass
def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.create_index('ix_item_sort_isbn13', 'item', ['sort_isbn13'], unique=False)
op.create_index('ix_item_sort_isbn10', 'item', ['sort_isbn10'], unique=False)
op.drop_index(op.f('ix_item_sort_isbn'), table_name='item')
op.add_column('item', sa.Column('sort_isbn10', sa.VARCHAR(length=1000), nullable=True))
op.add_column('item', sa.Column('sort_isbn13', sa.VARCHAR(length=1000), nullable=True))
op.drop_column('item', 'sort_isbn')
### end Alembic commands ###

View file

@ -0,0 +1,44 @@
"""empty message
Revision ID: 3822b1700859
Revises: 1fe914156ac0
Create Date: 2014-05-20 23:25:34.942115
"""
# revision identifiers, used by Alembic.
revision = '3822b1700859'
down_revision = '1fe914156ac0'
from alembic import op
import sqlalchemy as sa
def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.create_table('metadata',
sa.Column('created', sa.DateTime(), nullable=True),
sa.Column('modified', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('key', sa.String(length=256), nullable=True),
sa.Column('value', sa.String(length=256), nullable=True),
sa.Column('data', sa.PickleType(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
#op.drop_column(u'item', 'sort_isbn13')
#op.drop_column(u'item', 'sort_isbn10')
#op.create_index(op.f('ix_item_sort_isbn'), 'item', ['sort_isbn'], unique=False)
#op.drop_index('ix_item_sort_isbn10', table_name='item')
#op.drop_index('ix_item_sort_isbn13', table_name='item')
### end Alembic commands ###
def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.create_index('ix_item_sort_isbn13', 'item', ['sort_isbn13'], unique=False)
op.create_index('ix_item_sort_isbn10', 'item', ['sort_isbn10'], unique=False)
op.drop_index(op.f('ix_item_sort_isbn'), table_name='item')
op.add_column(u'item', sa.Column('sort_isbn10', sa.VARCHAR(length=1000), nullable=True))
op.add_column(u'item', sa.Column('sort_isbn13', sa.VARCHAR(length=1000), nullable=True))
op.drop_table('metadata')
### end Alembic commands ###

View file

@ -0,0 +1,35 @@
"""empty message
Revision ID: 3ea9f03f386f
Revises: 3822b1700859
Create Date: 2014-05-20 23:37:03.959948
"""
# revision identifiers, used by Alembic.
revision = '3ea9f03f386f'
down_revision = '3822b1700859'
from alembic import op
import sqlalchemy as sa
def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.drop_table('metadata')
op.create_table('metadata',
sa.Column('created', sa.DateTime(), nullable=True),
sa.Column('modified', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('key', sa.String(length=256), nullable=True),
sa.Column('value', sa.String(length=256), nullable=True),
sa.Column('data', sa.PickleType(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
### end Alembic commands ###
def downgrade():
pass
### commands auto generated by Alembic - please adjust! ###
### end Alembic commands ###

View file

@ -6,13 +6,14 @@ oml.ui.browser = function() {
that = Ox.IconList({
centered: true,
defaultRatio: oml.config.coverRatio,
defaultRatio: oml.config.iconRatio,
draggable: true,
item: function(data, sort, size) {
var color = oml.getFileInfoColor(ui.fileInfo, data).map(function(rgb) {
var color = oml.getIconInfoColor(ui.iconInfo, data).map(function(rgb) {
return rgb.concat(0.8);
}),
ratio = data.coverRatio || oml.config.coverRatio,
ratio = (ui.icons == 'cover' ? data.coverRatio : data.previewRatio)
|| oml.config.iconRatio,
width = Math.round(ratio >= 1 ? size : size * ratio),
height = Math.round(ratio <= 1 ? size : size / ratio),
sortKey = sort[0].key,
@ -22,7 +23,7 @@ oml.ui.browser = function() {
);
size = size || 64;
return {
extra: ui.showFileInfo ? $('<div>')
extra: ui.showIconInfo ? $('<div>')
.css({
width: width + 'px',
height: Math.round(size / 12.8) + 'px',
@ -39,7 +40,7 @@ oml.ui.browser = function() {
WebkitTransform: 'rotate(45deg)'
})
.html(
ui.fileInfo == 'extension'
ui.iconInfo == 'extension'
? data.extension.toUpperCase()
: Ox.formatValue(data.size, 'B')
) : null,
@ -47,7 +48,7 @@ oml.ui.browser = function() {
id: data.id,
info: info,
title: data.title,
url: '/' + data.id + '/cover128.jpg',
url: '/' + data.id + '/' + ui.icons + '128.jpg',
width: width
};
},
@ -57,8 +58,8 @@ oml.ui.browser = function() {
}), callback);
},
keys: [
'author', 'coverRatio', 'extension', 'id',
'mediastate', 'size', 'textsize', 'title'
'author', 'coverRatio', 'extension', 'id', 'mediastate',
'previewRatio', 'size', 'textsize', 'title'
],
max: 1,
min: 1,
@ -87,6 +88,15 @@ oml.ui.browser = function() {
oml_find: function() {
that.reloadList();
},
oml_iconinfo: function() {
that.reloadList(true);
},
oml_icons: function() {
that.reloadList(true);
},
oml_showiconinfo: function() {
that.reloadList(true);
},
oml_item: function(data) {
if (data.value && !data.previousValue) {
that.gainFocus();

View file

@ -130,7 +130,7 @@ oml.ui.folders = function() {
Ox.Button({
style: 'symbol',
title: 'info',
tooltip: Ox._(!index ? 'Preferences' : 'Profile'),
tooltip: Ox._(!index ? 'Preferences...' : 'Profile...'),
type: 'image'
})
.bindEvent({

View file

@ -5,13 +5,14 @@ oml.ui.gridView = function() {
var ui = oml.user.ui,
that = Ox.IconList({
defaultRatio: oml.config.coverRatio,
defaultRatio: oml.config.iconRatio,
draggable: true,
item: function(data, sort, size) {
var color = oml.getFileInfoColor(ui.fileInfo, data).map(function(rgb) {
var color = oml.getIconInfoColor(ui.iconInfo, data).map(function(rgb) {
return rgb.concat(0.8);
}),
ratio = data.coverRatio || oml.config.coverRatio,
ratio = (ui.icons == 'cover' ? data.coverRatio : data.previewRatio)
|| oml.config.iconRatio,
width = Math.round(ratio >= 1 ? size : size * ratio),
height = Math.round(ratio <= 1 ? size : size / ratio),
sortKey = sort[0].key,
@ -21,7 +22,7 @@ oml.ui.gridView = function() {
);
size = size || 128;
return {
extra: ui.showFileInfo ? $('<div>')
extra: ui.showIconInfo ? $('<div>')
.css({
width: width + 'px',
height: Math.round(size / 12.8) + 'px',
@ -38,7 +39,7 @@ oml.ui.gridView = function() {
WebkitTransform: 'rotate(45deg)'
})
.html(
ui.fileInfo == 'extension'
ui.iconInfo == 'extension'
? data.extension.toUpperCase()
: Ox.formatValue(data.size, 'B')
) : null,
@ -46,7 +47,7 @@ oml.ui.gridView = function() {
id: data.id,
info: info,
title: data.title,
url: '/' + data.id + '/cover128.jpg',
url: '/' + data.id + '/' + ui.icons + '128.jpg',
width: width
};
},
@ -56,13 +57,24 @@ oml.ui.gridView = function() {
}), callback);
},
keys: [
'author', 'coverRatio', 'extension', 'id',
'mediastate', 'size', 'textsize', 'title'
'author', 'coverRatio', 'extension', 'id', 'mediastate',
'previewRatio', 'size', 'textsize', 'title'
],
selected: ui.listSelection,
size: 128,
sort: ui.listSort,
unique: 'id'
})
.bindEvent({
oml_iconinfo: function() {
that.reloadList(true);
},
oml_icons: function() {
that.reloadList(true);
},
oml_showiconinfo: function() {
that.reloadList(true);
}
});
return that;

View file

@ -4,8 +4,8 @@ oml.ui.identifyDialog = function(data) {
var ui = oml.user.ui,
ids = [
'isbn10', 'isbn13', 'asin', 'lccn', 'oclc', 'olid'
lookupItems = [
'isbn', 'asin', 'lccn', 'oclc', 'olid'
].map(function(id) {
return {
id: id,
@ -13,48 +13,113 @@ oml.ui.identifyDialog = function(data) {
};
}),
keys = [
'title', 'author', 'publisher', 'date', 'edition', 'language'
].map(function(id) {
var key = Ox.getObjectById(oml.config.itemKeys, id);
return {
format: key.format,
id: id,
title: key.title,
visible: true
};
}),
selected = data.primaryid ? 'lookup' : 'find',
originalData = Ox.clone(data, true),
$lookupForm = Ox.Element(),
selected = data.mainid ? 'id' : 'title',
$lookupSelect = Ox.Select({
items: lookupItems,
overlap: 'right',
max: 1,
min: 1,
value: data.primaryid ? data.primaryid[0] : 'isbn',
width: 128
})
.bindEvent({
change: function(data) {
$lookupInput.focusInput(true);
}
}),
idValue, titleValue,
$lookupInput = Ox.Input({
value: data.primaryid ? data.primaryid[1] : '',
width: 480
})
.bindEvent({
change: function(data) {
// ...
},
submit: lookupMetadata
}),
$idInputs, $idButtons = {},
$lookupButton = Ox.Button({
overlap: 'left',
title: Ox._('Look Up'),
width: 128
})
.bindEvent({
click: lookupMetadata
}),
$idForm = renderIdForm(data),
$lookupElement = Ox.FormElementGroup({
elements: [
Ox.FormElementGroup({
elements: [
$lookupSelect,
$lookupInput
],
float: 'left'
}),
$lookupButton
],
float: 'right'
})
.css({
margin: '16px'
})
.appendTo($lookupForm),
$idPreview = data.mainid
$lookupPreview = data.primaryid
? oml.ui.infoView(data)
: Ox.Element(),
$idPanel = Ox.SplitPanel({
$lookupPanel = Ox.SplitPanel({
elements: [
{element: Ox.Element().append($idForm), size: 96},
{element: $idPreview}
{element: $lookupForm, size: 48},
{element: $lookupPreview}
],
orientation: 'vertical'
}),
$titleInputs, $titleButtons = {},
$findForm = Ox.Element(),
$titleForm = renderTitleForm(),
$findInput = Ox.Input({
label: Ox._('Title, Author etc.'),
labelWidth: 128,
width: 608,
value: [data.title].concat(data.author || []).join(' ')
})
.bindEvent({
submit: findMetadata
}),
$titlePanel = Ox.SplitPanel({
$findButton = Ox.Button({
overlap: 'left',
title: Ox._('Find'),
width: 128
})
.bindEvent({
click: findMetadata
}),
$findElement = Ox.FormElementGroup({
elements: [
$findInput,
$findButton
],
float: 'right'
})
.css({
margin: '16px'
})
.appendTo($findForm),
$findList,
$findPanel = Ox.SplitPanel({
elements: [
{element: $titleForm, size: 96},
{element: renderResults()}
{element: $findForm, size: 48},
{element: renderResults([])}
],
orientation: 'vertical'
}),
@ -63,8 +128,8 @@ oml.ui.identifyDialog = function(data) {
$buttons = Ox.ButtonGroup({
buttons: [
{id: 'id', title: Ox._('Look Up by ID')},
{id: 'title', title: Ox._('Find by Title')}
{id: 'lookup', title: Ox._('Look Up by ID')},
{id: 'find', title: Ox._('Find by Title')}
],
selectable: true,
value: selected
@ -78,14 +143,17 @@ oml.ui.identifyDialog = function(data) {
change: function(data) {
selected = data.value;
$innerPanel.options({selected: selected});
$updateButton.options({
disabled: selected == 'find' && !$findList
});
}
})
.appendTo($bar),
$innerPanel = Ox.SlidePanel({
elements: [
{id: 'id', element: $idPanel},
{id: 'title', element: $titlePanel}
{id: 'lookup', element: $lookupPanel},
{id: 'find', element: $findPanel}
],
orientation: 'horizontal',
selected: selected,
@ -100,43 +168,89 @@ oml.ui.identifyDialog = function(data) {
orientation: 'vertical'
}),
that = Ox.Dialog({
buttons: [
Ox.Button({
id: 'dontupdate',
title: Ox._('No, Don\'t Update')
})
.bindEvent({
click: function() {
that.close();
$metadataSelect = Ox.Select({
items: [
{id: 'original', title: Ox._('Show Original Metadata')},
{id: 'edited', title: Ox._('Show Edited Metadata')}
],
max: 1,
min: 1,
value: 'edited',
width: 192
})
.css({
margin: '4px'
})
.bindEvent({
change: function(data) {
if (selected == 'lookup') {
if (!$lookupButton.options('disabled')) {
$lookupButton.triggerEvent('click');
}
} else {
if ($findList) {
$findList.triggerEvent('select', {
ids: $findList.options('selected')
});
}
}
}),
Ox.Button({
disabled: true,
id: 'update',
title: Ox._('Yes, Update')
})
.bindEvent({
click: function() {
Ox.print('$$$', idValue);
var edit = Ox.extend(
{id: data.id},
$innerPanel.options('selected') == 'id'
? idValue || {mainid: ''}
: titleValue
}
}),
$dontUpdateButton = Ox.Button({
id: 'dontupdate',
title: Ox._('No, Don\'t Update')
})
.bindEvent({
click: function() {
that.close();
}
}),
$updateButton = Ox.Button({
disabled: true,
id: 'update',
title: Ox._('Yes, Update')
})
.bindEvent({
click: function() {
// FIXME: Wrong if user messes with lookup elements before clicking update button
var primaryId;
if (selected == 'lookup') {
primaryId = [
$lookupSelect.value(),
$lookupInput.value()
];
} else {
primaryId = $findList.value(
$findList.options('selected')[0],
'primaryid'
);
that.options({content: Ox.LoadingScreen().start()});
that.disableButtons();
Ox.print('VALUE SENT:', edit)
oml.api.edit(edit, function(result) {
}
that.options({content: Ox.LoadingScreen().start()});
that.disableButtons();
oml.api.edit({
id: data.id,
primaryid: primaryId
}, function(result) {
(
$metadataSelect.value() == 'original'
? oml.api.resetMetadata : Ox.noop
)({id: ui.item}, function(result) {
that.close();
Ox.Request.clearCache('find');
oml.$ui.browser.reloadList(true);
Ox.Request.clearCache(data.id);
oml.$ui.infoView.updateElement(data.id);
});
}
})
});
}
}),
that = Ox.Dialog({
buttons: [
$dontUpdateButton,
$updateButton
],
closeButton: true,
content: $outerPanel,
@ -147,379 +261,126 @@ oml.ui.identifyDialog = function(data) {
width: 768
});
$($metadataSelect.find('.OxButton')[0]).css({margin: 0});
$metadataSelect.appendTo($(that.find('.OxBar')[2]));
function disableButtons() {
Ox.forEach(selected == 'id' ? $idButtons : $titleButtons, function($button) {
$button.options({disabled: true});
$lookupSelect.options('items').forEach(function(item) {
$lookupSelect.disableItem(item.id);
});
$lookupInput.options({disabled: true});
$lookupButton.options({disabled: true});
$findInput.options({disabled: true});
$findButton.options({disabled: true});
$metadataSelect.options('items').forEach(function(item) {
$metadataSelect.disableItem(item.id);
});
$updateButton.options({disabled: true});
}
function findMetadata(data) {
function enableButtons() {
$lookupSelect.options('items').forEach(function(item) {
$lookupSelect.enableItem(item.id);
});
$lookupInput.options({disabled: false});
$lookupButton.options({disabled: false});
$findInput.options({disabled: false});
$findButton.options({disabled: false});
$metadataSelect.options('items').forEach(function(item) {
$metadataSelect.enableItem(item.id);
});
$updateButton.options({disabled: false});
}
function findMetadata() {
disableButtons();
$titlePanel.replaceElement(1, Ox.LoadingScreen().start());
oml.api.findMetadata(data, function(result) {
$findPanel.replaceElement(1, Ox.LoadingScreen().start());
oml.api.findMetadata({
query: $findInput.value()
}, function(result) {
var items = result.data.items.map(function(item, index) {
return Ox.extend({index: (index + 1).toString()}, item);
});
updateTitleButtons();
$titlePanel.replaceElement(1, renderResults(items));
return Ox.extend({index: index.toString()}, item);
});
enableButtons();
$updateButton.options({disabled: !items.length});
$findPanel.replaceElement(1, renderResults(items));
});
}
function getMetadata(key, value) {
function lookupMetadata() {
disableButtons();
$idPanel.replaceElement(1, Ox.LoadingScreen().start());
oml.api.getMetadata(Ox.extend({}, key, value), function(result) {
$idForm = renderIdForm(result.data);
$idPreview = Ox.isEmpty(data) ? Ox.Element() : oml.ui.infoView(result.data);
$idPanel
.replaceElement(0, $idForm)
.replaceElement(1, $idPreview);
$lookupPanel.replaceElement(1, Ox.LoadingScreen().start());
oml.api.getMetadata(Ox.extend(
{includeEdits: $metadataSelect.value() == 'edited'},
$lookupSelect.value(),
$lookupInput.value()
), function(result) {
enableButtons();
$updateButton.options({disabled: Ox.isEmpty(data)});
$lookupPreview = Ox.isEmpty(data)
? Ox.Element()
: oml.ui.infoView(result.data);
$lookupPanel.replaceElement(1, $lookupPreview);
});
}
function idInputValues(key, values) {
var $input = $idInputs[ids.map(function(id) {
return id.id;
}).indexOf(key)];
if (Ox.isUndefined(values)) {
values = $input.options('elements').map(function($element) {
return $element.value();
});
} else {
$input.options('elements').forEach(function($element, index) {
$element.value(values[index]);
});
}
return values;
}
function isEmpty(data) {
return Ox.every(data, Ox.isEmpty);
}
function isOriginal(data) {
return Ox.every(Object.keys(data), function(key) {
return data[key] == originalData[key];
});
}
function renderIdForm(data) {
var $element = Ox.Element();
$idInputs = ids.map(function(id, index) {
return Ox.FormElementGroup({
elements: [
Ox.Checkbox({
overlap: 'right',
title: Ox._(id.title),
value: id.id == data.mainid,
width: 80
})
.bindEvent({
change: function(data) {
var value = $idInputs[index].options('elements')[1].value();
if (data.value) {
if (value) {
idValue = Ox.extend({}, id.id, value);
$idInputs.forEach(function($input, i) {
if (i != index) {
$input.options('elements')[0].value(false);
}
});
getMetadata(id.id, value, function() {
// ...
});
} else {
this.value(false);
}
} else {
this.value(true);
}
}
}),
Ox.Input({
value: data[id.id] || '',
width: 160
})
.bindEvent({
submit: function(data) {
if (data.value) {
idValue = Ox.extend({}, id.id, data.value);
$idInputs.forEach(function($input, i) {
$input.options('elements')[0].options({
disabled: true,
value: i == index
});
$input.options('elements')[1].options({
disabled: true
});
});
getMetadata(id.id, data.value, function() {
Ox.print('GOT METADATA');
updateIdButtons();
});
}
}
})
],
float: 'left'
})
.css({
position: 'absolute',
left: 16 + Math.floor(index / 2) * 248 + 'px',
top: 16 + (index % 2) * 24 + 'px'
})
.appendTo($element);
});
$idButtons.clear = Ox.Button({
title: Ox._('Clear'),
width: 64
})
.css({
position: 'absolute',
right: '160px',
top: '64px'
})
.bindEvent({
click: function() {
ids.forEach(function(id) {
idInputValues(id.id, [false, '']);
});
updateIdButtons();
}
})
.appendTo($element);
$idButtons.reset = Ox.Button({
disabled: true,
title: Ox._('Reset'),
width: 64
})
.css({
position: 'absolute',
right: '88px',
top: '64px'
})
.bindEvent({
click: function() {
ids.forEach(function(id) {
idInputValues(id.id, [
id.id == originalData.mainid,
originalData[id.id]
]);
});
updateIdButtons();
}
})
.appendTo($element);
$idButtons.find = Ox.Button({
title: Ox._('Look Up'),
width: 64
})
.css({
position: 'absolute',
right: '16px',
top: '64px'
})
.bindEvent({
click: function() {
var key, value;
Ox.forEach(ids, function(id) {
var values = idInputValues(id.id);
if (values[0]) {
key = id.id;
value = values[1];
return false;
}
});
getMetadata(key, value, function() {
// ...
})
Ox.print('NOT IMPLEMENTED')
}
})
.appendTo($element);
updateIdButtons();
return $element;
}
function renderResults(items) {
var $list = Ox.TableList({
columns: [
{
var $resultsPanel;
if (items.length) {
$findList = Ox.TableList({
columns: [{
format: function(value, data) {
return value
? '<b>' + Ox.getObjectById(ids, value).title
+ ':</b> ' + data[data.mainid]
: '<b>No ID</b>'
return '<b>' + Ox.getObjectById(
lookupItems, data.primaryid[0]
).title + ':</b> ' + data.primaryid[1]
},
id: 'mainid',
id: 'index',
visible: true,
width: 192 - Ox.UI.SCROLLBAR_SIZE
}
],
items: [{
'index': '0',
'mainid': ''
}].concat(items || []),
keys: ['mainid', 'isbn10', 'isbn13'],
min: 1,
max: 1,
scrollbarVisible: true,
sort: [{key: 'index', operator: '+'}],
unique: 'index'
})
.bindEvent({
select: function(data) {
var index = data.ids[0],
mainid = $list.value(index, 'mainid');
if (!mainid) {
titleValue = {};
keys.forEach(function(key) {
titleValue[key.id] = titleInputValue(key.id);
}],
items: items,
keys: ['primaryid'].concat(lookupItems.map(function(item) {
return item.id;
})),
min: 1,
max: 1,
scrollbarVisible: true,
selected: ['0'],
sort: [{key: 'index', operator: '+'}],
unique: 'index'
})
.bindEvent({
select: function(data) {
var index = data.ids[0],
primaryId = $findList.value(index, 'primaryid');
Ox.print('EEEE', index, primaryId);
disableButtons();
$resultsPanel.replaceElement(1, Ox.LoadingScreen().start());
oml.api.getMetadata(Ox.extend(
{includeEdits: $metadataSelect.value() == 'edited'},
primaryId[0],
primaryId[1]
), function(result) {
enableButtons();
$resultsPanel.replaceElement(1, oml.ui.infoView(result.data));
});
$results.replaceElement(1, oml.ui.infoView(titleValue));
} else {
titleValue = Ox.extend({}, mainid, $list.value(index, mainid));
$results.replaceElement(1, Ox.LoadingScreen().start());
oml.api.getMetadata(titleValue, function(result) {
if (index == $list.options('selected')[0]) {
$results.replaceElement(1, oml.ui.infoView(result.data));
that.options('buttons')[1].options({disabled: false});
}
});
}
}
}),
$results = Ox.SplitPanel({
}),
$resultsPanel = Ox.SplitPanel({
elements: [
{element: $list, size: 192},
{element: $findList || Ox.Element(), size: 192},
{element: Ox.Element()}
],
orientation: 'horizontal'
});
return $results;
}
function renderTitleForm() {
var $element = Ox.Element();
$titleInputs = keys.map(function(key, index) {
return Ox.Input({
label: Ox._(key.title),
labelWidth: 80,
value: data[key.id],
width: 240
})
.css({
position: 'absolute',
left: 16 + Math.floor(index / 2) * 248 + 'px',
top: 16 + (index % 2) * 24 + 'px'
})
.bindEvent({
submit: function(data) {
$titleButtons.find.triggerEvent('click');
}
})
.appendTo($element);
});
$titleButtons.clear = Ox.Button({
title: Ox._('Clear'),
width: 64
})
.css({
position: 'absolute',
right: '160px',
top: '64px'
})
.bindEvent({
click: function() {
keys.forEach(function(key) {
titleInputValue(key.id, '');
});
updateTitleButtons();
}
})
.appendTo($element);
$titleButtons.reset = Ox.Button({
disabled: true,
title: Ox._('Reset'),
width: 64
})
.css({
position: 'absolute',
right: '88px',
top: '64px'
})
.bindEvent({
click: function() {
keys.forEach(function(key) {
titleInputValue(key.id, originalData[key.id]);
});
updateTitleButtons();
}
})
.appendTo($element);
$titleButtons.find = Ox.Button({
title: Ox._('Find'),
width: 64
})
.css({
position: 'absolute',
right: '16px',
top: '64px'
})
.bindEvent({
click: function() {
var data = {};
keys.forEach(function(key) {
data[key.id] = titleInputValue(key.id);
});
findMetadata(data);
}
})
.appendTo($element);
return $element;
}
function titleInputValue(key, value) {
var $input = $titleInputs[keys.map(function(key) {
return key.id;
}).indexOf(key)];
if (Ox.isUndefined(value)) {
value = $input.value();
if (key == 'author') {
value = value ? value.split(', ') : [];
}
setTimeout(function() {
$findList.triggerEvent('select', {ids: ['0']});
});
} else {
$input.value(
key == 'author' ? (value || []).join(', ') : value
);
$findList = void 0;
$resultsPanel = Ox.Element();
}
return value;
}
function updateIdButtons() {
var data = {}, empty, original;
ids.forEach(function(id) {
data[id.id] = idInputValues(id.id)[1];
});
empty = isEmpty(data);
original = isOriginal(data);
$idButtons.clear.options({disabled: empty});
$idButtons.reset.options({disabled: original});
$idButtons.find.options({disabled: empty});
that && that[original ? 'disableButton' : 'enableButton']('update');
}
function updateTitleButtons() {
var data = {}, empty, original;
keys.forEach(function(key) {
data[key.id] = titleInputValue(key.id);
});
empty = isEmpty(data);
original = isOriginal(data);
$titleButtons.clear.options({disabled: empty});
$titleButtons.reset.options({disabled: original});
$titleButtons.find.options({disabled: empty});
that[original ? 'disableButton' : 'enableButton']('update');
return $resultsPanel;
}
return that;

View file

@ -260,8 +260,8 @@ oml.ui.importExportDialog = function(selected) {
Ox.Select({
id: 'mode',
items: [
{id: 'add', title: Ox._('Add (keep files in destination path)')},
{id: 'replace', title: Ox._('Replace (delete files from destination path)')}
{id: 'add', title: Ox._('Add (keep all exisiting files in destination path)')},
{id: 'replace', title: Ox._('Replace (delete all existing files from destination path)')}
],
label: Ox._('Export Mode'),
labelWidth: 128,

View file

@ -4,14 +4,17 @@ oml.ui.infoView = function(identifyData) {
var ui = oml.user.ui,
coverSize = identifyData ? 256 : ui.coverSize,
iconSize = identifyData ? 256 : ui.iconSize,
css = getCSS(coverSize, oml.config.coverRatio),
css = getCSS(iconSize, oml.config.iconRatio),
that = Ox.Element()
.addClass('OxTextPage')
.css({overflowY: 'auto'})
.bindEvent({
oml_icons: function() {
that.updateElement(ui.item, [$icon])
},
oml_item: function() {
if (ui.item) {
that.updateElement(ui.item);
@ -24,12 +27,12 @@ oml.ui.infoView = function(identifyData) {
}
}),
$cover = Ox.Element()
$icon = Ox.Element()
.css({
position: 'absolute',
left: '16px',
top: '16px',
width: css.cover.width
width: css.icon.width
})
.appendTo(that),
@ -41,7 +44,7 @@ oml.ui.infoView = function(identifyData) {
right: !identifyData ? '176px' : 16 + Ox.UI.SCROLLBAR_SIZE + 'px',
top: '16px'
})
[coverSize == 512 ? 'hide' : 'show']()
[iconSize == 512 ? 'hide' : 'show']()
.appendTo(that),
$data,
@ -65,7 +68,7 @@ oml.ui.infoView = function(identifyData) {
height = Math.round(ratio <= 1 ? size : size / ratio),
left = size == 256 ? Math.floor((size - width) / 2) : 0;
return {
cover: {
icon: {
width: size + 'px'
},
info: {
@ -82,34 +85,99 @@ oml.ui.infoView = function(identifyData) {
};
}
function getImageSize(size, ratio) {
var width = Math.round(ratio >= 1 ? size : size * ratio),
height = Math.round(ratio <= 1 ? size : size / ratio),
left = Math.floor((size - width) / 2);
return {width: width, height: height, left: left};
function getIconTooltip() {
return !identifyData
? 'Click to see ' + (ui.iconSize == 256 ? 'large' : 'small')
+ ' ' + ui.icons + ', doubleclick to see '
+ (ui.icons == 'cover' ? 'preview' : 'cover')
: '';
}
function formatLight(str) {
return '<span class="OxLight">' + str + '</span>';
function formatLight(string) {
return '<span class="OxLight">' + string + '</span>';
}
function formatKey(key) {
var item = Ox.getObjectById(oml.config.itemKeys, key);
return '<span style="font-weight: bold">'
+ Ox._(Ox.toTitleCase(key)) + ':&nbsp;</span> ';
+ Ox._(Ox.toTitleCase(key)) + ':</span>&nbsp;';
}
function formatValue(value, key, join) {
value = Ox.encodeHTMLEntities(value);
function formatValue(value, key) {
return value ? (Ox.isArray(value) ? value : [value]).map(function(value) {
return key && !identifyData ?
'<a href="/' + key + '==' + value + '">' + value + '</a>'
'<a href="/' + key + '==' + (
key == 'date' ? value.slice(0, 4) : value
) + '">' + value + '</a>'
: value;
}).join(join || ', ') : '';
}).join('; ') : '';
}
function identify(data) {
oml.ui.identifyDialog(data).open();
oml.$ui.identifyDialog = oml.ui.identifyDialog(data).open();
}
function renderIdentifyButton(data) {
return Ox.FormElementGroup({
elements: [
Ox.Button({
disabled: data.mediastate != 'available',
title: Ox._('Identify Book...'),
width: 112
})
.bindEvent({
click: function() {
identify(data);
}
}),
data.mediastate == 'available' && data.primaryid
? Ox.Select({
items: Ox.flatten([
'isbn', 'asin', 'lccn', 'oclc', 'olid'
].map(function(key) {
return (data[key] || []).map(function(value) {
return {
id: key + ':' + value,
title: '<b>' + Ox.getObjectById(
oml.config.itemKeys, key
).title + ':</b> ' + value
};
});
})).concat([
{id: '', title: '<b>No ID</b>'}
]),
max: 1,
min: 1,
overlap: 'left',
title: 'select',
tooltip: Ox._('Set Primary ID'),
type: 'image',
value: data.primaryid.join(':')
})
.bindEvent({
click: function(data) {
Ox.print('####', data);
},
change: function(data) {
Ox.print('$$$', data);
oml.api.edit({
id: ui.item,
primaryid: data.value ? data.value.split(':') : ''
}, function(result) {
that.updateElement(result.data, [$data]);
});
}
})
: Ox.Button({
disabled: true,
overlap: 'left',
title: 'select',
type: 'image'
})
],
float: 'right'
})
.css({marginTop: '16px'});
}
function renderMediaButton(data) {
@ -166,7 +234,7 @@ oml.ui.infoView = function(identifyData) {
disabled: !ui._lists,
items: getListItems(),
overlap: 'left',
title: 'list',
title: 'select',
tooltip: Ox._('Download Book to a List'),
type: 'image'
})
@ -230,18 +298,19 @@ oml.ui.infoView = function(identifyData) {
function toggleCoverSize(ratio) {
var css;
coverSize = coverSize == 256 ? 512 : 256,
css = getCSS(coverSize, ratio);
//$cover.animate(css.cover, 250);
iconSize = iconSize == 256 ? 512 : 256,
css = getCSS(iconSize, ratio);
//$icon.animate(css.icon, 250);
Ox.print('ANIMATE,', css)
$info.animate(css.info, 250);
$image.animate(css.image, 250);
$reflectionImage.animate(css.image, 250);
$reflection.animate(css.reflection, 250);
oml.UI.set({coverSize: coverSize});
oml.UI.set({iconSize: iconSize});
}
function updateCover(ratio) {
var css = getCSS(coverSize, ratio);
var css = getCSS(iconSize, ratio);
$image.css(css.image).show();
$reflectionImage.css(css.image);
$reflection.css(css.reflection).show();
@ -254,7 +323,7 @@ oml.ui.infoView = function(identifyData) {
$elements = $elements
? Ox.makeArray($elements)
: [$cover, $info, $data];
: [$icon, $info, $data];
(data ? Ox.noop : oml.api.get)({
id: id,
@ -271,24 +340,27 @@ oml.ui.infoView = function(identifyData) {
Ox.print('BOOK DATA', data)
var $mediaButton,
isEditable = !data.mainid && data.mediastate == 'available',
var $div,
isEditable = data.mediastate == 'available' && !identifyData,
src = !identifyData
? '/' + data.id + '/cover512.jpg?' + data.modified
? '/' + data.id + '/' + ui.icons + '512.jpg?' + data.modified
: data.cover,
ratio = data.coverRatio || oml.config.coverRatio,
size = coverSize,
ratio = (
ui.icons == 'cover' || identifyData
? data.coverRatio : data.previewRatio
) || oml.config.iconRatio,
size = iconSize,
reflectionSize = Math.round(size / 2);
$elements.forEach(function($element) {
$element.empty();
if ($element == $cover) {
if ($element == $icon) {
$image = Ox.Element({
element: '<img>',
tooltip: '' // TODO
tooltip: getIconTooltip()
})
.on({
error: function() {
@ -312,13 +384,21 @@ oml.ui.infoView = function(identifyData) {
})
.hide()
.bindEvent({
doubleclick: function() {
if (!identifyData) {
oml.UI.set({
icons: ui.icons == 'cover'
? 'preview' : 'cover'
});
}
},
singleclick: function() {
if (!identifyData) {
toggleCoverSize(ratio);
}
}
})
.appendTo($cover);
.appendTo($icon);
$reflection = $('<div>')
.addClass('OxReflection')
@ -329,7 +409,7 @@ oml.ui.infoView = function(identifyData) {
overflow: 'hidden'
})
.hide()
.appendTo($cover);
.appendTo($icon);
$reflectionImage = $('<img>')
.attr({src: src})
@ -348,58 +428,130 @@ oml.ui.infoView = function(identifyData) {
} else if ($element == $info) {
// -------- Title
$('<div>')
.css({
marginTop: '-2px',
fontSize: '13px',
fontWeight: 'bold'
marginTop: '-2px'
})
.html(
data.title ? Ox.encodeHTMLEntities(data.title)
: '<span class="OxLight">'
+ Ox._('No Title')
+ '</span>'
.append(
Ox.EditableContent({
clickLink: oml.clickLink,
editable: isEditable,
tooltip: isEditable ? oml.getEditTooltip() : '',
value: data.title || 'No Title'
})
.css({
fontWeight: 'bold',
fontSize: '13px'
})
.bindEvent({
submit: function(event) {
editMetadata('title', event.value);
}
})
)
.appendTo($info);
if (data.author) {
$('<div>')
.css({
marginTop: '4px',
fontSize: '13px',
fontWeight: 'bold'
})
.html(formatValue(data.author, 'author'))
.appendTo($info);
}
// -------- Author
if (data.place || data.publisher || data.date) {
$('<div>')
.css({
marginTop: '8px'
})
.html(
(formatValue(data.place, 'place', ' ; '))
+ (data.place && (data.publisher || data.date) ? ' : ' : '')
+ (formatValue(data.publisher, 'publisher'))
+ (data.publisher && data.date ? ', ' : '')
+ (data.date || '')
)
.appendTo($info);
}
$('<div>')
.css({
marginTop: '2px'
})
.append(
Ox.EditableContent({
clickLink: oml.clickLink,
editable: isEditable,
format: function(value) {
return formatValue(value.split('; '), 'author');
},
placeholder: formatLight(Ox._('Unknown Author')),
tooltip: isEditable ? oml.getEditTooltip() : '',
value: data.author ? data.author.join('; ') : ''
})
.css({
marginBottom: '-3px',
fontWeight: 'bold',
fontSize: '13px'
})
.bindEvent({
submit: function(event) {
editMetadata('author', event.value);
}
})
)
.appendTo($info);
if (data.edition || data.language) {
$('<div>')
.css({
marginTop: '8px'
// -------- Place, Publisher, Date
$div = $('<div>')
.css({
marginTop: '4px',
})
.appendTo($info);
['place', 'publisher', 'date'].forEach(function(key, index) {
if (index) {
$('<span>').html(', ').appendTo($div);
}
$('<span>')
.html(formatKey(key))
.appendTo($div);
Ox.EditableContent({
clickLink: oml.clickLink,
editable: isEditable,
format: function(value) {
return formatValue(value.split('; '), key)
},
placeholder: formatLight('unknown'),
tooltip: isEditable ? oml.getEditTooltip() : '',
value: key == 'place'
? (data[key] ? data[key].join('; ') : [''])
: data[key] || ''
})
.html(
(Ox.encodeHTMLEntities(data.edition || ''))
+ (data.edition && data.language ? '; ' : '')
+ (formatValue(data.language, 'language'))
)
.appendTo($info);
}
.bindEvent({
submit: function(event) {
editMetadata(key, event.value);
}
})
.appendTo($div);
});
// -------- Edition, Language, Pages
$div = $('<div>')
.css({
marginTop: '4px',
})
.appendTo($info);
['edition', 'language', 'pages'].forEach(function(key, index) {
if (index) {
$('<span>').html(', ').appendTo($div);
}
$('<span>')
.html(formatKey(key))
.appendTo($div);
Ox.EditableContent({
clickLink: oml.clickLink,
editable: isEditable,
format: function(value) {
return key == 'language'
? formatValue(value, key)
: value;
},
placeholder: formatLight('unknown'),
tooltip: isEditable ? oml.getEditTooltip() : '',
value: data[key] || ''
})
.bindEvent({
submit: function(event) {
editMetadata(key, event.value);
}
})
.appendTo($div);
});
// -------- Classification
if (data.classification) {
$('<div>')
@ -413,6 +565,8 @@ oml.ui.infoView = function(identifyData) {
.appendTo($info);
}
// -------- Description
if (data.description) {
$('<div>')
.css({
@ -427,10 +581,11 @@ oml.ui.infoView = function(identifyData) {
$('<div>').css({height: '16px'}).appendTo($info);
oml.createLinks($info);
} else if ($element == $data) {
$mediaButton = renderMediaButton(data)
.appendTo($data);
renderMediaButton(data).appendTo($data);
$('<div>')
.addClass('OxSelectable')
@ -439,7 +594,7 @@ oml.ui.infoView = function(identifyData) {
})
.text(
[
(data.extension || '???').toUpperCase(), // FIXME
data.extension.toUpperCase(),
Ox.formatValue(data.size, 'B')
].join(', ')
)
@ -462,24 +617,13 @@ oml.ui.infoView = function(identifyData) {
}
});
Ox.Button({
disabled: data.mediastate != 'available',
title: Ox._('Identify Book...'),
width: 128
})
.css({marginTop: '16px'})
.bindEvent({
click: function() {
identify(data);
}
})
.appendTo($data);
renderIdentifyButton(data).appendTo($data);
[
'isbn10', 'isbn13', 'asin', 'lccn', 'oclc', 'olid'
'isbn', 'asin', 'lccn', 'oclc', 'olid'
].forEach(function(id, index) {
var title;
if (data[id]) {
if (data[id] && !Ox.isEmpty(data[id])) {
title = Ox.getObjectById(oml.config.itemKeys, id).title;
$('<div>')
.css({
@ -488,11 +632,19 @@ oml.ui.infoView = function(identifyData) {
})
.text(title)
.appendTo($data);
Ox.EditableContent({
editable: false,
value: data[id]
})
.appendTo($data);
Ox.makeArray(data[id]/*FIXME!*/).forEach(function(value) {
var isPrimary = data.primaryid[0] == id
&& data.primaryid[1] == value;
Ox.Element({
tooltip: isPrimary ? 'Primary ID' : ''
})
.html(
Ox.encodeHTMLEntities(value) + (
isPrimary ? ' (*)' : ''
)
)
.appendTo($data);
});
}
});
@ -502,16 +654,19 @@ oml.ui.infoView = function(identifyData) {
});
// FIXME: identify dialog should call this too
function editMetadata(key, value) {
var edit;
Ox.print('EM', key, value, data[key])
if (value != data[key]) {
edit = Ox.extend({id: ui.item}, key, value);
var edit = {id: data.id};
if (Ox.contains(['author', 'place'], key)) {
edit[key] = value ? value.split('; ') : [];
} else {
edit[key] = value;
}
Ox.print('EDIT METADATA', key, value, edit);
oml.api.edit(edit, function(result) {
Ox.Request.clearCache('find');
oml.$ui.browser.reloadList();
//that.updateElement(result.data, $info);
oml.$ui.browser.value(
result.data.id, key, result.data[key]
);
});
}
}
@ -523,7 +678,7 @@ oml.ui.infoView = function(identifyData) {
if (!identifyData) {
ui.item && that.updateElement(ui.item);
} else {
that.updateElement(identifyData, [$cover, $info]);
that.updateElement(identifyData, [$icon, $info]);
}
oml.bindEvent({

View file

@ -83,7 +83,7 @@ oml.ui.mainMenu = function() {
},
{},
{
id: 'iconSubmenu',
id: 'iconsSubmenu',
title: 'Icons',
items: [
{
@ -105,26 +105,27 @@ oml.ui.mainMenu = function() {
},
{},
{
id: 'showfileinfo',
title: 'Show File Info',
checked: ui.showFileInfo
id: 'showiconinfo',
title: 'Show Icon Info',
checked: ui.showIconInfo
},
{},
{
group: 'fileinfo',
group: 'iconinfo',
min: 1,
max: 1,
disabled: !ui.showFileInfo,
items: [
{
id: 'extension',
title: Ox._('Show Extension'),
checked: ui.fileInfo == 'extension'
checked: ui.iconInfo == 'extension',
disabled: !ui.showIconInfo
},
{
id: 'size',
title: Ox._('Show Size'),
checked: ui.fileInfo == 'size'
checked: ui.iconInfo == 'size',
disabled: !ui.showIconInfo
}
]
}
@ -283,10 +284,12 @@ oml.ui.mainMenu = function() {
? data.checked : data.checked[0].id;
if (id == 'icons') {
oml.UI.set({icons: value});
} else if (id == 'showfileinfo') {
oml.UI.set({showFileInfo: value});
} else if (id == 'fileinfo') {
oml.UI.set({fileInfo: value});
} else if (id == 'icons') {
oml.UI.set({icons: value});
} else if (id == 'showiconinfo') {
oml.UI.set({showIconInfo: value});
} else if (id == 'iconinfo') {
oml.UI.set({iconInfo: value});
} else if (id == 'sort') {
oml.UI.set({
listSort: [{
@ -512,6 +515,12 @@ oml.ui.mainMenu = function() {
that[action]('deletelist');
*/
},
oml_iconinfo: function(data) {
// ...
},
oml_icons: function(data) {
that.checkItem('viewMenu_iconsSubmenu_' + data.value);
},
oml_item: function(data) {
if (!!data.value != !!data.previousValue) {
that[data.value ? 'disableItem' : 'enableItem']('showfilters');
@ -533,6 +542,11 @@ oml.ui.mainMenu = function() {
oml_showfilters: function(data) {
that.setItemTitle('showfilters', Ox._((data.value ? 'Hide' : 'Show') + ' Filters'));
},
oml_showiconinfo: function(data) {
var action = data.value ? 'enableItem' : 'disableItem';
that[action]('viewMenu_iconsSubmenu_extension');
that[action]('viewMenu_iconsSubmenu_size');
},
oml_showinfo: function(data) {
that.setItemTitle('showinfo', Ox._((data.value ? 'Hide' : 'Show') + ' Info'));
},

View file

@ -184,7 +184,12 @@
|| document.documentElement,
script = document.createElement('script');
script.onload = function() {
Ox.load({UI: {theme: theme}}, callback);
Ox.load({UI: {theme: theme}}, function() {
Ox.formatUpper = function(string) {
return string.toUpperCase();
};
callback();
});
};
script.src = oxjsPath + '/Ox.js?' + omlVersion;
script.type = 'text/javascript';

View file

@ -7,7 +7,7 @@ oml.ui.previewDialog = function() {
$image,
$list = oml.$ui.list,
item = Ox.last($list.options('selected')),
coverRatio = $list.value(item, 'coverRatio') || oml.config.coverRatio,
coverRatio = $list.value(item, 'coverRatio') || oml.config.iconRatio,
size = getSize(coverRatio),
that = Ox.Dialog({

View file

@ -133,6 +133,27 @@ oml.clickLink = function(e) {
}
};
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;
}
});
};
(function() {
oml.doHistory = function(action, items, targets, callback) {
@ -713,7 +734,15 @@ oml.getEditTooltip = function(title) {
}());
oml.getFileInfoColor = function(type, data) {
oml.getFilterSizes = function() {
var ui = oml.user.ui;
return Ox.splitInt(
window.innerWidth - ui.showSidebar * ui.sidebarSize - 1,
5
);
};
oml.getIconInfoColor = function(type, data) {
return type == 'extension' ? (
data.extension == 'epub' ? [[32, 160, 32], [0, 128, 0], [128, 255, 128]]
: data.extension == 'pdf' ? (
@ -728,14 +757,6 @@ oml.getFileInfoColor = function(type, data) {
: [[224, 32, 32], [192, 0, 0], [255, 192, 192]];
};
oml.getFilterSizes = function() {
var ui = oml.user.ui;
return Ox.splitInt(
window.innerWidth - ui.showSidebar * ui.sidebarSize - 1,
5
);
};
oml.getInfoHeight = function() {
return Math.min(
oml.user.ui.sidebarSize,
@ -909,8 +930,7 @@ oml.openLink = function(url) {
if (Ox.startsWith(url, 'mailto:')) {
window.open(url);
} else {
//window.open('/url=' + encodeURIComponent(url), '_blank');
window.open(url, '_blank');
window.open('/url=' + encodeURIComponent(url), '_blank');
}
};