1/** 2 * Plugin for URL management in BookReader 3 * Note read more about the url "fragment" here: 4 * https://openlibrary.org/dev/docs/bookurls 5 */ 6 7jQuery.extend(BookReader.defaultOptions, { 8 enableUrlPlugin: true, 9 bookId: "", 10 // Defaults can be a urlFragment string 11 defaults: null, 12 updateWindowTitle: false, 13 14 // 'history' | 'hash', 15 urlMode: 'hash', 16 17 // When using 'history' mode, this part of the URL is kept constant 18 // Example: /details/plato/ 19 urlHistoryBasePath: '/', 20 21 // Only these params will be reflected onto the URL 22 urlTrackedParams: ['page', 'search', 'mode', 'region', 'highlight'], 23 24 // If true, don't update the URL when page == n0 (eg "/page/n0") 25 urlTrackIndex0: false, 26}); 27 28BookReader.prototype.setup = (function(super_) { 29 return function(options) { 30 super_.call(this, options); 31 32 this.bookId = options.bookId; 33 this.defaults = options.defaults; 34 35 this.locationPollId = null; 36 this.oldLocationHash = null; 37 this.oldUserHash = null; 38 }; 39})(BookReader.prototype.setup); 40 41BookReader.prototype.init = (function(super_) { 42 return function() { 43 44 if (this.options.enableUrlPlugin) { 45 this.bind(BookReader.eventNames.PostInit, function(e, br) { 46 if (br.options.updateWindowTitle) { 47 document.title = br.shortTitle(50); 48 } 49 if (br.options.urlMode === 'hash') { 50 br.urlStartLocationPolling(); 51 } 52 }); 53 54 this.bind(BookReader.eventNames.fragmentChange, 55 this.urlUpdateFragment.bind(this) 56 ); 57 } 58 super_.call(this); 59 }; 60})(BookReader.prototype.init); 61 62/** 63 * Returns a shortened version of the title with the maximum number of characters 64 * @param {string} maximumCharacters 65 */ 66BookReader.prototype.shortTitle = function(maximumCharacters) { 67 if (this.bookTitle.length < maximumCharacters) { 68 return this.bookTitle; 69 } 70 71 var title = this.bookTitle.substr(0, maximumCharacters - 3); 72 title += "..."; 73 return title; 74}; 75 76/** 77 * Starts polling of window.location to see hash fragment changes 78 */ 79BookReader.prototype.urlStartLocationPolling = function() { 80 var self = this; 81 this.oldLocationHash = this.urlReadFragment(); 82 83 if (this.locationPollId) { 84 clearInterval(this.locationPollID); 85 this.locationPollId = null; 86 } 87 88 this.locationPollId = setInterval(function() { 89 var newFragment = self.urlReadFragment(); 90 if (newFragment != self.oldLocationHash && newFragment != self.oldUserHash) { 91 self.trigger(BookReader.eventNames.stop); 92 93 // Queue change if animating 94 if (self.animating) { 95 if (self.autoStop) self.autoStop(); 96 self.animationFinishedCallback = function() { 97 self.updateFromParams(self.paramsFromFragment(newFragment)); 98 }; 99 } else { 100 // update immediately 101 self.updateFromParams(self.paramsFromFragment(newFragment)); 102 } 103 self.oldUserHash = newFragment; 104 } 105 }, 500); 106}; 107 108/** 109 * Update URL from the current parameters. 110 * Call this instead of manually using window.location.replace 111 */ 112BookReader.prototype.urlUpdateFragment = function() { 113 var allParams = this.paramsFromCurrent(); 114 var params = {}; 115 116 if (!this.options.urlTrackIndex0 117 && 'undefined' !== typeof(allParams.index) 118 && allParams.index === 0) { 119 delete allParams.index; 120 delete allParams.page; 121 } 122 123 for (var i = 0; i < this.options.urlTrackedParams.length; i++) { 124 param = this.options.urlTrackedParams[i]; 125 if (param in allParams) {
126 params[param] = allParams[param]; 127 } 128 } 129 130 var newFragment = this.fragmentFromParams(params); 131 var currFragment = this.urlReadFragment(); 132 133 if (currFragment === newFragment) { 134 return; 135 } 136 137 if (this.options.urlMode === 'history') { 138 if (window.history && window.history.replaceState) { 139 var baseWithoutSlash = this.options.urlHistoryBasePath.replace(/\/+$/, ''); 140 var newFragmentWithSlash = newFragment === '' ? '' : '/' + newFragment; 141 142 window.history.replaceState( 143 {}, 144 null, 145 baseWithoutSlash 146 + newFragmentWithSlash 147 + window.location.search 148 ); 149 } 150 } else { 151 window.location.replace('#' + newFragment); 152 } 153 154 this.oldLocationHash = newFragment; 155}; 156 157/** 158 * Will read either the hash or URL and return the bookreader fragment 159 * @return {string} 160 */ 161BookReader.prototype.urlReadFragment = function() { 162 if (this.options.urlMode === 'history') { 163 return window.location.pathname.substr(this.options.urlHistoryBasePath.length); 164 } else { 165 return window.location.hash.substr(1); 166 } 167}; 168
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.