autofit: 'auto'
};
+ // This object/dictionary controls which optional features are enabled
+ // XXXmang in progress
+ this.features = {
+ // search
+ // read aloud
+ // open library entry
+ // table of contents
+ // embed/share ui
+ // info ui
+ };
+
return this;
};
// Enact other parts of initial params
this.updateFromParams(params);
+ // Start AJAX request for OL data
+ this.getOpenLibraryJSON(this.gotOpenLibraryRecord);
+
+}
+
+// XXXmang
+BookReader.prototype.gotOpenLibraryRecord = function(olObject) {
+ // console.log(olObject);
+ if (olObject) {
+ if (olObject['table_of_contents']) {
+ console.log('xxx updating table of contents');
+ br.updateTOC(olObject['table_of_contents']); // XXX
+ }
+ }
+}
+
+BookReader.prototype.updateTOC = function(tocEntries) {
+ this.removeChapters();
+ for (var i = 0; i < tocEntries.length; i++) {
+ this.addChapterFromEntry(tocEntries[i]);
+ }
+}
+
+/*
+ * Example table of contents entry - this format is defined by Open Library
+ * {
+ * "pagenum": "17",
+ * "level": 1,
+ * "label": "CHAPTER I",
+ * "type": {"key": "/type/toc_item"},
+ * "title": "THE COUNTRY AND THE MISSION"
+ * }
+ */
+BookReader.prototype.addChapterFromEntry = function(tocEntryObject) {
+ console.log(tocEntryObject);
+ var pageIndex = this.getPageIndex(tocEntryObject['pagenum']);
+ // Only add if we know where it is
+ if (pageIndex) {
+ this.addChapter(tocEntryObject['title'], tocEntryObject['pagenum'], pageIndex);
+ }
}
BookReader.prototype.setupKeyListeners = function() {
BookReader.prototype.initNavbar = function() {
// Setup nav / chapter / search results bar
+ // $$$ should make this work inside the BookReader div (self-contained), rather than after
$('#BookReader').after(
'<div id="BRnav"><div id="BRnavpos"><div id="pager"></div><div id="BRnavline"></div></div></div>'
);
-
- // $$$mang demo
- /*
- $('#BRnavpos').append(
- '<div class="search" style="left:80%;" title="Search result">'
- + ' <div class="query">The Kingdom of the Future, for instance, though interesting in a Caley Robinson way, with its cold, mystical colour relieved by touches of warm reddish browns, and its big draped figures, was a composition in the past, and did not stimulate the <strong><a href="">emotional</a></strong> powers of the observer with a suggestion of coming ages or a prophecy of progress. <span>Page 26</span></div>'
- + '</div>'
- );
- */
/*
<!-- LOAD SEARCH RESULTS FIRST SO CHAPTER INDICATORS CAN APPEAR IN FRONT -->
</div>
*/
-
- $('.chapter').bt({
- contentSelector: '$(this).find(".title")',
- trigger: 'hover',
+ /* $$$mang search results and chapters should automatically coalesce
+ $('.searchChap').bt({
+ contentSelector: '$(this).find(".query")',
+ trigger: 'click',
closeWhenOthersOpen: true,
cssStyles: {
- backgroundColor: '#000',
- border: '2px solid #e2dcc5',
+ width: '250px',
+ padding: '10px 10px 15px',
+ backgroundColor: '#fff',
+ border: '3px solid #e2dcc5',
borderBottom: 'none',
- padding: '5px 10px',
- fontFamily: '"Arial", sans-serif',
- fontSize: '11px',
- fontWeight: '700',
- color: '#fff',
- whiteSpace: 'nowrap'
+ fontFamily: '"Lucida Grande","Arial",sans-serif',
+ fontSize: '12px',
+ lineHeight: '18px',
+ color: '#615132'
},
- shrinkToFit: true,
- width: '200px',
+ shrinkToFit: false,
+ width: '230px',
padding: 0,
spikeGirth: 0,
spikeLength: 0,
- overlap: '16px',
+ overlap: '10px',
overlay: false,
killTitle: true,
textzIndex: 9999,
wrapperzIndex: 9997,
offsetParent: null,
positions: ['top'],
- fill: 'black',
+ fill: 'white',
windowMargin: 10,
- strokeWidth: 0,
+ strokeWidth: 3,
+ strokeStyle: '#e2dcc5',
cornerRadius: 0,
centerPointX: 0,
centerPointY: 0,
shadow: false
});
- $('.search').bt({
+ $('.searchChap').each(function(){
+ $(this).hover(function(){
+ $(this).addClass('front');
+ },function(){
+ $(this).removeClass('front');
+ });
+ });
+ */
+
+ // XXXmang testing
+ this.addSearchResult('hi there', '25', 22);
+ $("#pager").draggable({axis:'x',containment:'parent'});
+}
+
+BookReader.prototype.addSearchResult = function(queryString, pageNumber, pageIndex) {
+ var uiStringSearch = "Search result"; // i18n
+ var uiStringPage = "Page"; // i18n
+
+ var percentThrough = BookReader.util.cssPercentage(pageIndex, this.numLeafs);
+
+ // $$$mang add click-through to page
+ $('<div class="search" style="left:' + percentThrough + ';" title="' + uiStringSearch + '"><div class="query">'
+ + queryString + '<span>' + uiStringPage + ' ' + pageNumber + '</span></div>')
+ .appendTo('#BRnavpos').bt({
contentSelector: '$(this).find(".query")',
trigger: 'click',
closeWhenOthersOpen: true,
centerPointX: 0,
centerPointY: 0,
shadow: false
- });
- $('.searchChap').bt({
- contentSelector: '$(this).find(".query")',
- trigger: 'click',
+ })
+ .hover(function(){
+ $(this).addClass('front');
+ },function(){
+ $(this).removeClass('front');
+ }
+ );
+}
+
+BookReader.prototype.removeSearchResults = function() {
+ $('#BRnavpos .search').remove();
+}
+
+BookReader.prototype.addChapter = function(chapterTitle, pageNumber, pageIndex) {
+ var uiStringPage = 'Page'; // i18n
+
+ var percentThrough = BookReader.util.cssPercentage(pageIndex, this.numLeafs);
+
+ $('<div class="chapter" style="left:' + percentThrough + ';"><div class="title">'
+ + chapterTitle + '<span>|</span> ' + uiStringPage + ' ' + pageNumber + '</div></div>')
+ .appendTo('#BRnavpos')
+ .data({'self': this, 'pageIndex': pageIndex })
+ .bt({
+ contentSelector: '$(this).find(".title")',
+ trigger: 'hover',
closeWhenOthersOpen: true,
cssStyles: {
- width: '250px',
- padding: '10px 10px 15px',
- backgroundColor: '#fff',
- border: '3px solid #e2dcc5',
+ backgroundColor: '#000',
+ border: '2px solid #e2dcc5',
borderBottom: 'none',
- fontFamily: '"Lucida Grande","Arial",sans-serif',
- fontSize: '12px',
- lineHeight: '18px',
- color: '#615132'
+ padding: '5px 10px',
+ fontFamily: '"Arial", sans-serif',
+ fontSize: '11px',
+ fontWeight: '700',
+ color: '#fff',
+ whiteSpace: 'nowrap'
},
- shrinkToFit: false,
- width: '230px',
+ shrinkToFit: true,
+ width: '200px',
padding: 0,
spikeGirth: 0,
spikeLength: 0,
- overlap: '10px',
+ overlap: '16px',
overlay: false,
killTitle: true,
textzIndex: 9999,
wrapperzIndex: 9997,
offsetParent: null,
positions: ['top'],
- fill: 'white',
+ fill: 'black',
windowMargin: 10,
- strokeWidth: 3,
- strokeStyle: '#e2dcc5',
+ strokeWidth: 0,
cornerRadius: 0,
centerPointX: 0,
centerPointY: 0,
shadow: false
+ })
+ .hover( function() {
+ $(this).addClass('front');
+ }, function() {
+ $(this).removeClass('front');
+ }
+ )
+ .bind('click', function() {
+ $(this).data('self').jumpToIndex($(this).data('pageIndex'));
});
-
- // XXXmang needs to be done for each element when added
- $('.chapter').each(function(){
- $(this).hover(function(){
- $(this).addClass('front');
- },function(){
- $(this).removeClass('front');
- });
- });
- $('.search').each(function(){
- $(this).hover(function(){
- $(this).addClass('front');
- },function(){
- $(this).removeClass('front');
- });
- });
- $('.searchChap').each(function(){
- $(this).hover(function(){
- $(this).addClass('front');
- },function(){
- $(this).removeClass('front');
- });
- });
- $("#pager").draggable({axis:'x',containment:'parent'});
+}
+
+BookReader.prototype.removeChapters = function() {
+ $('#BRnavpos .chapter').remove();
}
BookReader.prototype.initToolbar = function(mode, ui) {
return this.getPageURI(index, reduce, rotate);
}
+
+/////// Functions that can/should be overriden by third-parties
+
+// If your book has a record on Open Library you get some nice things for free
+BookReader.prototype.getOpenLibraryJSON = function(callback) {
+ return null;
+}
+
+
// Library functions
BookReader.util = {
disableSelect: function(jObject) {
return Math.min(Math.max(value, min), max);
},
+ // Given value and maximum, calculate a percentage suitable for CSS
+ cssPercentage: function(value, max) {
+ return parseInt(((value + 0.0) / max) * 100) + '%';
+ },
+
notInArray: function(value, array) {
// inArray returns -1 or undefined if value not in array
return ! (jQuery.inArray(value, array) >= 0);