pandora/static/js/textPanel.js

579 lines
20 KiB
JavaScript
Raw Normal View History

2013-02-21 10:49:37 +00:00
'use strict';
pandora.ui.textPanel = function() {
2013-02-21 16:07:20 +00:00
var that = Ox.SplitPanel({
2013-02-21 12:28:10 +00:00
elements: [
{element: Ox.Element(), size: 24},
{element: Ox.Element()},
{element: Ox.Element(), size: 16}
],
orientation: 'vertical'
2013-02-21 16:07:20 +00:00
}),
embedURLs,
selected = -1,
selectedURL;
2013-02-21 10:49:37 +00:00
pandora.api.getText({id: pandora.user.ui.text}, function(result) {
2013-02-21 16:07:20 +00:00
var text = result.data;
embedURLs = text.type == 'html'
? getEmbedURLs(text.text)
: [];
2013-02-21 10:49:37 +00:00
2013-02-21 16:07:20 +00:00
var $toolbar = Ox.Bar({size: 24}),
2013-02-21 10:49:37 +00:00
$editMenu, $uploadButton,
$find = Ox.Input({
clear: true,
2013-05-09 10:13:58 +00:00
placeholder: Ox._('Find in Texts'),
2013-02-21 10:49:37 +00:00
value: pandora.user.ui.textFind,
width: 188
})
.css({
float: 'right',
margin: '4px 4px 4px 2px'
})
.bindEvent({
submit: function(data) {
Ox.print('SUBMIT', data);
}
})
.appendTo($toolbar),
$nextButton = Ox.Button({
2013-02-21 11:25:24 +00:00
disabled: embedURLs.length < 2,
2013-02-21 10:49:37 +00:00
title: 'arrowRight',
2014-01-22 17:16:51 +00:00
tooltip: Ox._('Next Reference'),
2013-02-21 10:49:37 +00:00
type: 'image'
})
.css({
float: 'right',
margin: '4px 2px 4px 2px'
})
2013-02-21 16:07:20 +00:00
.bindEvent({
click: function() {
2013-02-22 03:10:14 +00:00
that.selectEmbed(
selected < embedURLs.length - 1 ? selected + 1 : 0,
true
2013-02-21 16:07:20 +00:00
);
}
})
2013-02-21 10:49:37 +00:00
.appendTo($toolbar),
$currentButton = Ox.Button({
2013-02-21 11:25:24 +00:00
disabled: embedURLs.length < 1,
2013-02-21 10:49:37 +00:00
title: 'center',
2013-05-09 10:13:58 +00:00
tooltip: Ox._('Current Reference'),
2013-02-21 10:49:37 +00:00
type: 'image'
})
.css({
float: 'right',
margin: '4px 2px 4px 2px'
})
2013-10-28 11:10:26 +00:00
.bindEvent({
click: scrollToSelectedEmbed
})
2013-02-21 10:49:37 +00:00
.appendTo($toolbar),
$previousButton = Ox.Button({
2013-02-21 11:25:24 +00:00
disabled: embedURLs.length < 2,
2013-02-21 10:49:37 +00:00
title: 'arrowLeft',
2014-01-22 17:16:51 +00:00
tooltip: Ox._('Previous Reference'),
2013-02-21 10:49:37 +00:00
type: 'image'
})
.css({
float: 'right',
margin: '4px 2px 4px 2px'
})
2013-02-21 16:07:20 +00:00
.bindEvent({
click: function() {
2013-02-22 03:10:14 +00:00
that.selectEmbed(
selected ? selected - 1 : embedURLs.length - 1,
true
2013-02-21 16:07:20 +00:00
);
}
})
2013-02-21 10:49:37 +00:00
.appendTo($toolbar),
$statusbar = Ox.Bar({size: 16}),
$panel = Ox.SplitPanel({
elements: [
{
element: pandora.$ui.text = text.type == 'html'
2013-02-21 16:07:20 +00:00
? pandora.ui.textHTML(text)
2013-02-21 10:49:37 +00:00
: pandora.ui.textPDF(text)
},
{
element: pandora.$ui.textEmbed = pandora.ui.textEmbed(),
2014-02-14 07:36:37 +00:00
// fixme: at some point pdf will also have a sidebar
size: text.type == 'html' ? pandora.user.ui.embedSize : 0,
resizable: text.type == 'html',
2013-02-21 10:49:37 +00:00
resize: [192, 256, 320, 384, 448, 512]
}
],
orientation: 'horizontal'
});
2013-02-21 11:56:56 +00:00
if (text.editable) {
if (text.type == 'html') {
$editMenu = Ox.MenuButton({
items: [
2013-05-09 10:13:58 +00:00
{id: 'insertHTML', title: Ox._('Insert HTML...')},
{id: 'insertEmbed', title: Ox._('Insert Embed...')}
2013-02-21 11:56:56 +00:00
],
title: 'edit',
2013-05-09 10:13:58 +00:00
tooltip: Ox._('Editing Options'),
2013-02-21 11:56:56 +00:00
type: 'image'
})
.css({
float: 'left',
margin: '4px 2px 4px 4px'
})
2013-02-23 11:12:24 +00:00
.bindEvent({
click: function(data) {
if (data.id == 'insertEmbed') {
pandora.$ui.insertEmbedDialog = pandora.ui.insertEmbedDialog(function() {
// ...
}).open();
}
}
})
2013-02-21 11:56:56 +00:00
.appendTo($toolbar);
} else {
2013-02-21 14:09:23 +00:00
$uploadButton = Ox.FileButton({
image: 'upload',
2013-05-09 10:13:58 +00:00
tooltip: Ox._('Upload PDF'),
2013-02-21 11:56:56 +00:00
type: 'image'
})
.css({
float: 'left',
margin: '4px 2px 4px 4px'
})
2013-02-21 14:09:23 +00:00
.bindEvent({
click: function(data) {
2013-07-14 18:56:47 +00:00
if (data.files.length) {
2013-02-21 14:09:23 +00:00
pandora.$ui.uploadPDFDialog = pandora.ui.uploadPDFDialog({
file: data.files[0],
id: pandora.user.ui.text
}).open();
}
}
})
2013-02-21 11:56:56 +00:00
.appendTo($toolbar);
}
2013-02-21 10:49:37 +00:00
}
2013-02-21 12:28:10 +00:00
that.replaceElement(0, $toolbar);
that.replaceElement(1, $panel);
that.replaceElement(2, $statusbar);
2013-02-21 10:49:37 +00:00
embedURLs.length && that.selectEmbed(0);
2013-02-21 10:49:37 +00:00
});
2013-02-21 11:25:24 +00:00
function getEmbedURLs(text) {
2013-02-21 16:07:20 +00:00
var matches = text.match(/<a [^<>]*?href="(.+?)".*?>/gi),
2013-02-21 11:25:24 +00:00
urls = [];
if (matches) {
matches.forEach(function(match) {
2013-02-21 16:07:20 +00:00
var url = match.match(/"(.+?)"/)[1];
if (pandora.isEmbedURL(url)) {
urls.push(url);
}
2013-02-21 11:25:24 +00:00
});
}
return urls;
2013-02-21 10:49:37 +00:00
}
2013-10-28 11:10:26 +00:00
function scrollToSelectedEmbed() {
2013-11-08 18:57:24 +00:00
var scrollTop = Math.max(pandora.$ui.text[0].scrollTop + $('#embed' + selected).offset().top - 48, 0),
position = 100 * scrollTop / Math.max(1,
2014-01-22 12:48:32 +00:00
pandora.$ui.text[0].scrollHeight);
2013-10-28 11:10:26 +00:00
pandora.$ui.text.scrollTo(position);
}
2013-11-04 14:10:13 +00:00
that.selectEmbed = function(index, scroll) {
2013-02-22 03:10:14 +00:00
if (index != selected) {
selected = index;
selectedURL = embedURLs[selected]
2013-02-22 03:10:14 +00:00
$('.OxSpecialLink').removeClass('OxActive');
selected > -1 && $('#embed' + selected).addClass('OxActive');
pandora.$ui.textEmbed.update(selectedURL);
2013-11-04 14:10:13 +00:00
scroll && scrollToSelectedEmbed();
2013-02-22 03:10:14 +00:00
}
};
2013-02-21 16:07:20 +00:00
that.update = function(text) {
var index;
embedURLs = getEmbedURLs(text);
index = embedURLs.indexOf(selectedURL);
if (embedURLs.length && (index == -1 || index >= embedURLs.length)) {
index = 0;
}
selected = -1;
that.selectEmbed(index);
};
2013-02-21 10:49:37 +00:00
return that;
};
2013-02-21 16:07:20 +00:00
pandora.ui.textHTML = function(text) {
2013-02-21 10:49:37 +00:00
var height = getHeight(),
width = getWidth(),
that = Ox.Element()
2013-02-24 09:28:25 +00:00
.css({
'overflow-y': 'auto'
})
.bind({
scroll: function(event) {
var position = Math.round(100 * that[0]. scrollTop / Math.max(1,
that[0].scrollHeight - that.height())),
settings = pandora.user.ui.texts[pandora.user.ui.text];
position = position - position % 10;
if (!scrolling && settings && (settings.name || (position != settings.position))) {
pandora.UI.set('texts.' + pandora.UI.encode(pandora.user.ui.text), {
position: position ? position : 0
});
}
scrolling = false;
},
})
.bindEvent({
pandora_showsidebar: function(data) {
that.update();
},
})
.bindEvent('pandora_texts.' + text.id.toLowerCase(), function(data) {
data.value && data.value.name && scrollToPosition();
2013-02-24 09:28:25 +00:00
}),
scrolling = false,
2014-01-19 12:59:21 +00:00
$content = Ox.Element()
.css({margin: '16px'})
.appendTo(that),
2013-02-21 10:49:37 +00:00
2013-09-26 21:37:44 +00:00
$title = Ox.EditableContent({
editable: text.name ? text.editable : false,
2013-05-09 10:13:58 +00:00
placeholder: text.editable ? Ox._('Doubleclick to edit title') : Ox._('Untitled'),
tooltip: text.editable ? pandora.getEditTooltip('title') : '',
2013-05-09 10:13:58 +00:00
value: text.name || Ox._('{0} Texts', [pandora.site.site.name]),
2013-02-21 10:49:37 +00:00
width: width
})
.css({
//position: 'absolute',
//width: width + 'px',
height: '32px',
fontSize: '18px',
})
.bindEvent({
submit: function(data) {
Ox.Request.clearCache('getText');
pandora.api.editText({
2013-02-21 11:56:56 +00:00
id: pandora.user.ui.text,
2013-02-21 10:49:37 +00:00
name: data.value
}, function(result) {
2013-08-17 14:32:33 +00:00
if (result.data.id != pandora.user.ui.text) {
Ox.Request.clearCache();
pandora.renameList(pandora.user.ui.text, result.data.id, result.data.name);
pandora.$ui.info.updateListInfo();
}
2013-02-21 10:49:37 +00:00
});
}
})
2013-02-24 09:28:25 +00:00
.appendTo($content),
2013-02-21 10:49:37 +00:00
$spaceTop = Ox.Element()
.css({height: '16px'})
2013-02-24 09:28:25 +00:00
.appendTo($content),
2013-02-21 10:49:37 +00:00
2013-09-26 21:37:44 +00:00
$text = Ox.EditableContent({
2013-02-21 10:49:37 +00:00
clickLink: pandora.clickLink,
2013-09-26 21:37:44 +00:00
collapseToEnd: false,
2013-02-21 10:49:37 +00:00
editable: text.editable,
2013-02-21 14:51:28 +00:00
format: function(text) {
/*
var $text = $('<div>').html(text),
$chapterElement = $text.find('[data-type="chapters"]')[0],
$footnoteElement = $text.find('[data-type="footnotes"]')[0],
$keywordElement = $text.find('[data-type="keywords"]')[0],
$chapters = [],
$footnotes = [],
$keywords = [],
footnote = 0,
keywords = [];
// chapters
$text.find('[data-type="chapter"]').each(function(index, element) {
var $element = $(element),
name = $element.attr('data-name') || $element.html(),
level;
Ox.loop(1, 7, function(i) {
if ($element.is('h' + i)) {
level = i;
return false; // break
}
});
if (!level) {
level = name.split(' ')[0].split('.').length || 1;
}
});
// footnotes
$text.find('[data-type="footnote"]').each(function(index, element) {
var $element = $(element),
value = $element.attr('data-value');
footnote = value ? parseInt(value) : footnote + 1;
});
2014-02-14 07:36:37 +00:00
// FIXME: remove footnotes, don't link to keywords inside footnotes
// keywords
2014-02-14 07:36:37 +00:00
$text.find('[data-type="keyword"]').each(function(index, element) {
var $element = $(element),
value = $element.attr('data-value') || element.html();
keywords.append(value);
});
$keywords = Ox.map(Ox.sort(Ox.unique(keywords)), function(keyword) {
return $('<a>').attr({href: '#'}).html(keyword);
});
text = $text.html();
*/
// embeds
2013-02-22 03:10:14 +00:00
var index = 0;
2013-02-21 14:51:28 +00:00
return text.replace(
/<a [^<>]*?href="(.+?)".*?>/gi,
function() {
2013-02-22 03:10:14 +00:00
var link = arguments[0], ret, url = arguments[1];
if (pandora.isEmbedURL(url)) {
ret = '<a id="embed' + index
+ '" class="OxSpecialLink" href="' + url
+ '">'
index++;
} else {
ret = link;
}
return ret;
2013-02-21 14:51:28 +00:00
}
);
},
globalAttributes: ['data-name', 'data-type', 'data-value', 'lang'],
2013-05-09 10:13:58 +00:00
placeholder: text.editable ? Ox._('Doubleclick to edit text') : '',
tooltip: text.editable ? pandora.getEditTooltip('text') : '',
2013-02-21 10:49:37 +00:00
type: 'textarea',
2013-02-21 13:14:33 +00:00
width: width,
value: text.text
2013-02-21 10:49:37 +00:00
})
.css({
//position: 'absolute',
2013-02-24 09:28:25 +00:00
//height: height + 'px',
2013-02-21 10:49:37 +00:00
width: width + 'px',
//marginTop: '48px',
2014-01-19 12:59:21 +00:00
fontSize: '12px',
2014-01-19 12:59:41 +00:00
lineHeight: '18px'
2013-02-21 10:49:37 +00:00
})
.bindEvent({
submit: function(data) {
Ox.Request.clearCache('getText');
pandora.api.editText({
2013-02-21 12:00:45 +00:00
id: pandora.user.ui.text,
2013-02-21 10:49:37 +00:00
text: data.value
});
pandora.$ui.textPanel.update(data.value);
2013-02-21 10:49:37 +00:00
}
})
2013-02-24 09:28:25 +00:00
.appendTo($content);
2013-02-21 10:49:37 +00:00
setTimeout(scrollToPosition);
2013-02-21 10:49:37 +00:00
function getHeight() {
// 24 menu + 24 toolbar + 16 statusbar + 32 title + 32 margins
// + 1px to get rid of scrollbar
return window.innerHeight - 128 - 1;
2013-02-21 10:49:37 +00:00
}
function getWidth() {
2013-02-21 12:00:45 +00:00
return window.innerWidth
- pandora.user.ui.showSidebar * pandora.user.ui.sidebarSize - 1
- pandora.user.ui.embedSize - 1
2014-09-26 12:12:25 +00:00
- 32 - Ox.UI.SCROLLBAR_SIZE;
2013-02-21 10:49:37 +00:00
}
function scrollTo(position) {
scrolling = true;
that[0].scrollTop = that[0].scrollHeight / 100 * position;
}
function scrollToPosition() {
var settings = pandora.user.ui.texts[pandora.user.ui.text] || {},
position = settings.position || 0,
element,
scrollTop;
if (settings.name) {
element = that.find('*[data-name="' + settings.name + '"]');
if (element.length) {
scrollTop = Math.max(that[0].scrollTop + element.offset().top - 48, 0);
position = 100 * scrollTop / that[0].scrollHeight;
}
}
scrollTo(position);
}
2013-10-28 11:10:26 +00:00
that.scrollTo = scrollTo;
2013-02-21 10:49:37 +00:00
that.update = function() {
$text.options({
width: getWidth()
2013-08-17 14:32:33 +00:00
}).css({
width: getWidth() + 'px'
2013-02-21 10:49:37 +00:00
});
scrollToPosition();
2013-02-21 10:49:37 +00:00
return that;
};
2014-11-01 16:09:54 +00:00
that.bindEvent({
mousedown: function() {
setTimeout(function() {
!Ox.Focus.focusedElementIsInput() && that.gainFocus();
});
}
});
2013-02-21 11:56:56 +00:00
return that;
2013-02-21 10:49:37 +00:00
};
pandora.ui.textPDF = function(text) {
2013-02-24 07:48:25 +00:00
var that = Ox.Element(),
$iframe,
page = pandora.user.ui.texts[pandora.user.ui.text].position || 1,
url = '/texts/' + pandora.user.ui.text + '/text.pdf.html#page=' + page;
2013-02-21 14:09:23 +00:00
if (text.uploaded) {
2013-02-24 07:48:25 +00:00
$iframe = Ox.Element('<iframe>')
2013-02-21 14:09:23 +00:00
.attr({
frameborder: 0,
2013-02-24 07:48:25 +00:00
height: '100%',
src: url,
2013-02-21 14:09:23 +00:00
width: '100%'
})
.bindMessage({
edit: function(data) {
pandora.ui.insertEmbedDialog(data.src, function(url) {
data.src = url;
var embed = text.embeds.filter(function(embed) {
return embed.id == data.id
&& embed.type == data.type
&& embed.page == data.page;
})[0];
2013-07-14 18:56:47 +00:00
if (embed) {
embed.src = url;
} else {
text.embeds.push(data);
//fixme sort embeds by page/id
}
pandora.api.editText({
id: text.id,
embeds: text.embeds
}, function(result) {
$iframe.postMessage('update', data);
});
}).open();
},
page: function(data) {
pandora.UI.set('texts.' + pandora.UI.encode(pandora.user.ui.text), {
'position': data.page
});
2013-02-24 07:48:25 +00:00
}
})
.appendTo(that);
that.setPage = function(page) {
$iframe && $iframe.postMessage('page', {page: page});
}
2013-02-21 14:09:23 +00:00
} else {
2013-09-08 17:03:22 +00:00
that.html('Please upload PDF');
2013-02-21 14:09:23 +00:00
}
2013-02-21 10:49:37 +00:00
return that;
};
pandora.ui.textEmbed = function() {
2013-02-21 10:49:37 +00:00
var that = Ox.Element()
.bindEvent({
resizestart: function() {
2013-02-22 04:43:26 +00:00
$iframe.attr('src') && $overlay.show();
2013-02-21 10:49:37 +00:00
},
resize: function(data) {
pandora.user.ui.embedSize = data.size;
2013-02-21 11:56:56 +00:00
pandora.$ui.text.update();
2013-02-21 10:49:37 +00:00
},
resizeend: function(data) {
2013-02-22 04:43:26 +00:00
$iframe.attr('src') && $overlay.hide();
// set to 0 so that UI.set registers a change of the value
pandora.user.ui.embedSize = 0;
pandora.UI.set({embedSize: data.size});
2013-02-21 10:49:37 +00:00
}
}),
2013-02-21 11:56:56 +00:00
$message = $('<div>')
.css({marginTop: '16px', textAlign: 'center'})
2013-05-10 14:54:30 +00:00
.html(Ox._('No Embeds'))
2013-02-21 11:56:56 +00:00
.hide()
.appendTo(that),
2013-02-24 07:48:25 +00:00
$iframe = Ox.Element('<iframe>')
2013-02-21 10:49:37 +00:00
.attr({
height: '100%',
id: 'embed',
2013-02-21 10:49:37 +00:00
frameborder: 0,
2013-02-21 11:25:24 +00:00
src: '',
2013-02-21 13:14:33 +00:00
width: '100%',
2013-09-03 13:51:07 +00:00
allowfullscreen: true,
2013-02-21 13:14:33 +00:00
mozallowfullscreen: true,
webkitAllowFullScreen: true
2013-02-21 10:49:37 +00:00
})
2013-02-21 11:25:24 +00:00
.hide()
2013-02-21 11:56:56 +00:00
.appendTo(that),
2013-02-21 10:49:37 +00:00
$overlay = $('<div>')
.css({
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0
})
.hide()
2013-02-21 11:56:56 +00:00
.appendTo(that);
2013-02-21 10:49:37 +00:00
that.update = function(url) {
var parsed, src;
2013-02-21 11:25:24 +00:00
if (url) {
url = url.replace(/&amp;/g, '&')
+ (url.indexOf('#embed') < url.indexOf('?') ? '&' : '?')
+ 'matchRatio=true';
src = $iframe.attr('src');
parsed = {src: Ox.parseURL(src), url: Ox.parseURL(url)};
if (
src
&& parsed.url.protocol == parsed.src.protocol
&& parsed.url.hostname == parsed.src.hostname
) {
2013-02-24 07:48:25 +00:00
$iframe.postMessage('seturl', {
url: parsed.url.pathname + parsed.url.search + parsed.url.hash
2013-02-24 07:48:25 +00:00
});
} else {
$iframe.attr({src: url});
}
2013-02-21 11:56:56 +00:00
$message.hide();
2013-02-21 16:07:20 +00:00
$iframe.show();
2013-02-21 11:25:24 +00:00
} else {
$iframe.hide();
2013-02-21 11:56:56 +00:00
$message.show();
2013-02-21 11:25:24 +00:00
}
2013-02-21 10:49:37 +00:00
return that;
};
return that;
2013-02-21 14:09:23 +00:00
};