From da57e0f89e1dad89e2221f2f232528ef5cbd7ba2 Mon Sep 17 00:00:00 2001 From: Julian Viereck <julian.viereck@gmail.com> Date: Tue, 11 Sep 2012 09:30:44 -0700 Subject: [PATCH 01/17] Julian's html-search-bar work --- web/viewer.css | 52 ++++- web/viewer.html | 13 +- web/viewer.js | 563 ++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 611 insertions(+), 17 deletions(-) diff --git a/web/viewer.css b/web/viewer.css index 0f615094a..caf3a09f1 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -245,7 +245,7 @@ html[dir='rtl'] #sidebarContent { 0 1px 1px hsla(0,0%,0%,.1); } -#toolbarViewer { +#toolbarViewer, .findbar { position: relative; height: 32px; background-image: url(images/texture.png), @@ -265,6 +265,32 @@ html[dir='rtl'] #sidebarContent { 0 1px 0 hsla(0,0%,0%,.15), 0 1px 1px hsla(0,0%,0%,.1); } + +.findbar { + top: 40px; + left: 40px; + position: absolute; + z-index: 100; + height: 20px; + + min-width: 16px; + padding: 3px 6px 3px 6px; + margin: 4px 2px 4px 0; + border: 1px solid transparent; + border-radius: 2px; + color: hsl(0,0%,85%); + font-size: 12px; + line-height: 14px; + text-align: left; + -webkit-user-select:none; + -moz-user-select:none; + cursor: default; +} + +.notFound { + background-color: rgb(255, 137, 153); +} + html[dir='ltr'] #toolbarViewerLeft { margin-left: -1px; } @@ -1069,6 +1095,30 @@ canvas { white-space:pre; } +.textLayer .highlight { + margin: -1px; + padding: 1px; + + background-color: rgba(0, 137, 26, 0.2); + border-radius: 4px; +} + +.textLayer .highlight.begin { + border-radius: 4px 0px 0px 4px; +} + +.textLayer .highlight.end { + border-radius: 0px 4px 4px 0px; +} + +.textLayer .highlight.middle { + border-radius: 0px; +} + +.textLayer .highlight.selected { + background-color: rgba(255, 0, 0, 0.2); +} + /* TODO: file FF bug to support ::-moz-selection:window-inactive so we can override the opaque grey background when the window is inactive; see https://bugzilla.mozilla.org/show_bug.cgi?id=706209 */ diff --git a/web/viewer.html b/web/viewer.html index 70cd8cdb0..0ee6313a6 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -108,9 +108,20 @@ limitations under the License. </div> <!-- sidebarContainer --> <div id="mainContainer"> + <div class="findbar hidden" id="findbar"> + <label for="findInput">Find: </label> + <input id="findInput" type="search"> + <button id="findPrevious"><</button> + <button id="findNext">></button> + <input type="checkbox" id="findHighlightAll"> + <label for="findHighlightAll">Highlight all</label> + <input type="checkbox" id="findMatchCase"> + <label for="findMatchCase">Match case</label> + <span id="findMsgWrap" class="hidden">Reached end of page, continued from top</span> + <span id="findMsgNotFound" class="hidden">Phrase not found</span> + </div> <div class="toolbar"> <div id="toolbarContainer"> - <div id="toolbarViewer"> <div id="toolbarViewerLeft"> <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="4" data-l10n-id="toggle_slider"> diff --git a/web/viewer.js b/web/viewer.js index 2662adff7..65c87740f 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -208,6 +208,345 @@ var Settings = (function SettingsClosure() { var cache = new Cache(kCacheSize); var currentPageNumber = 1; +var PDFFindController = { + startedTextExtraction: false, + + // If active, search resulsts will be highlighted. + active: false, + + // Stores the text for each page. + pageContents: [], + + pageMatches: [], + + selected: { + pageIdx: 0, + matchIdx: 0 + }, + + dirtyMatch: false, + + findTimeout: null, + + initialize: function() { + var events = [ + 'find', + 'findagain', + 'findhighlightallchange', + 'findcasesensitivitychange' + ]; + + this.handelEvent = this.handelEvent.bind(this); + + for (var i = 0; i < events.length; i++) { + window.addEventListener(events[i], this.handelEvent); + } + }, + + calcFindMatch: function(pageContent) { + // TODO: Handle the other search options here as well. + + var query = this.state.query; + var queryLen = query.length; + + if (queryLen === 0) + return []; + + var matches = []; + + var matchIdx = -queryLen; + while (true) { + matchIdx = pageContent.indexOf(query, matchIdx + queryLen); + if (matchIdx === -1) { + break; + } + + matches.push(matchIdx); + } + return matches; + }, + + extractText: function() { + if (this.startedTextExtraction) + return; + this.startedTextExtraction = true; + var self = this; + function extractPageText(pageIndex) { + PDFView.pages[pageIndex].getTextContent().then( + function textContentResolved(data) { + // Bulid the search string. + var bidiTexts = data.bidiTexts; + var str = ''; + + for (var i = 0; i < bidiTexts.length; i++) { + str += bidiTexts[i].str; + } + + // Store the pageContent as a string. + self.pageContents.push(str); + // Ensure there is a empty array of matches. + self.pageMatches.push([]); + + if ((pageIndex + 1) < PDFView.pages.length) + extractPageText(pageIndex + 1); + } + ); + } + extractPageText(0); + }, + + handelEvent: function(e) { + this.state = e.detail; + if (e.detail.findPrevious === undefined) { + this.dirtyMatch = true; + } + + clearTimeout(this.findTimeout); + if (e.type === 'find') { + // Only trigger the find action after 250ms of silence. + this.findTimeout = setTimeout(this.performFind.bind(this), 250); + } else { + this.performFind(); + } + }, + + updatePage: function(idx) { + var page = PDFView.pages[idx]; + + if (page.textLayer) { + page.textLayer.updateMatches(); + } else if (this.selected.pageIdx === idx) { + // If the page is selected, scroll the page into view, which triggers + // rendering the page, which adds the textLayer. Once the textLayer is + // build, it will scroll onto the selected match. + page.scrollIntoView(); + } + }, + + performFind: function() { + // Recalculate all the matches. + // TODO: Make one match show up as the current match + + var pages = PDFView.pages; + var pageContents = this.pageContents; + var pageMatches = this.pageMatches; + + this.active = true; + + if (this.dirtyMatch) { + // Need to recalculate the matches. + this.dirtyMatch = false; + + this.selected = { + pageIdx: -1, + matchIdx: -1 + }; + + // TODO: Make this way more lasily (aka. efficient) - e.g. calculate only + // the matches for the current visible pages. + var firstMatch = true; + for (var i = 0; i < pageContents.length; i++) { + var matches = pageMatches[i] = this.calcFindMatch(pageContents[i]); + if (firstMatch && matches.length !== 0) { + firstMatch = false; + this.selected = { + pageIdx: i, + matchIdx: 0 + }; + } + this.updatePage(i, true); + } + } else { + // If there is NO selection, then there is no match at all -> no sense to + // handel previous/next action. + if (this.selected.pageIdx === -1) + return; + + // Handle findAgain case. + var previous = this.state.findPrevious; + var sPageIdx = this.selected.pageIdx; + var sMatchIdx = this.selected.matchIdx; + + if (previous) { + // Select previous match. + + if (sMatchIdx !== 0) { + this.selected.matchIdx -= 1; + } else { + var len = pageMatches.length; + for (var i = sPageIdx - 1; i != sPageIdx; i--) { + if (i < 0) + i += len; + + if (pageMatches[i].length !== 0) { + this.selected = { + pageIdx: i, + matchIdx: pageMatches[i].length - 1 + }; + break; + } + } + // If pageIdx stayed the same, select last match on the page. + if (this.selected.pageIdx === sPageIdx) { + this.selected.matchIdx = pageMatches[sPageIdx].length - 1; + } + } + } else { + // Select next match. + + if (pageMatches[sPageIdx].length !== sMatchIdx + 1) { + this.selected.matchIdx += 1; + } else { + var len = pageMatches.length; + for (var i = sPageIdx + 1; i < len + sPageIdx; i++) { + if (pageMatches[i % len].length !== 0) { + this.selected = { + pageIdx: i % len, + matchIdx: 0 + }; + break; + } + } + // If pageIdx stayed the same, select last match on the page. + if (this.selected.pageIdx === sPageIdx) { + this.selected.matchIdx = 0; + } + } + } + + this.updatePage(sPageIdx, sPageIdx === this.selected.pageIdx); + if (sPageIdx !== this.selected.pageIdx) { + this.updatePage(this.selected.pageIdx, true); + } + } + } +}; + +var PDFFindBar = { + // TODO: Enable the FindBar *AFTER* the pagesPromise in the load function + // got resolved + + opened: false, + + FIND_FOUND: 0, // Successful find + FIND_NOTFOUND: 1, // Unsuccessful find + FIND_WRAPPED: 2, // Successful find, but wrapped around + + initialize: function() { + this.bar = document.getElementById('findbar'); + this.toggleButton = document.getElementById('viewSearch'); + this.findField = document.getElementById('findInput'); + this.highlightAll = document.getElementById('findHighlightAll'); + this.caseSensitive = document.getElementById('findMatchCase'); + this.findMsgWrap = document.getElementById('findMsgWrap'); + this.findMsgNotFound = document.getElementById('findMsgNotFound'); + + var self = this; + this.toggleButton.addEventListener('click', + function() { + self.toggle(); + }); + + this.findField.addEventListener('input', function() { + self.dispatchEvent(''); + }); + + // TODO: Add keybindings like enter, shift-enter, CMD-G etc. to go to prev/ + // next match when the findField is selected. + + document.getElementById('findPrevious').addEventListener('click', + function() { + self.dispatchEvent('again', true); + }); + + document.getElementById('findNext').addEventListener('click', + function() { + self.dispatchEvent('again', false); + }); + + this.highlightAll.addEventListener('click', + function() { + self.dispatchEvent('highlightallchange'); + }); + + this.caseSensitive.addEventListener('click', + function() { + self.dispatchEvent('casesensitivitychange'); + }); + }, + + dispatchEvent: function(aType, aFindPrevious) { + var event = document.createEvent('CustomEvent'); + event.initCustomEvent('find' + aType, true, true, { + query: this.findField.value, + caseSensitive: this.caseSensitive.checked, + highlightAll: this.highlightAll.checked, + findPrevious: aFindPrevious + }); + return window.dispatchEvent(event); + }, + + updateUIState: function(aState) { + var notFound = false; + var wrapped = false; + + switch (aState) { + case this.FIND_FOUND: + break; + + case this.FIND_NOTFOUND: + notFound = true; + break; + + case this.FIND_WRAPPED: + wrapped = true; + break; + } + + if (notFound) { + this.findField.classList.add('notFound'); + this.findMsgNotFound.classList.remove('hidden'); + } else { + this.findField.classList.remove('notFound'); + this.findMsgNotFound.classList.add('hidden'); + } + + if (wrapped) { + this.findMsgWrap.classList.remove('hidden'); + } else { + this.findMsgWrap.classList.add('hidden'); + } + }, + + open: function() { + if (this.opened) return; + + this.opened = true; + this.toggleButton.classList.add('toggled'); + this.bar.classList.remove('hidden'); + this.findField.select(); + this.findField.focus(); + }, + + close: function() { + if (!this.opened) return; + + this.opened = false; + this.toggleButton.classList.remove('toggled'); + this.bar.classList.add('hidden'); + + PDFFindController.active = false; + }, + + toggle: function() { + if (this.opened) { + this.close(); + } else { + this.open(); + } + } +}; + var PDFView = { pages: [], thumbnails: [], @@ -242,6 +581,9 @@ var PDFView = { this.watchScroll(thumbnailContainer, this.thumbnailViewScroll, this.renderHighestPriority.bind(this)); + PDFFindBar.initialize(); + PDFFindController.initialize(); + this.initialized = true; container.addEventListener('scroll', function() { self.lastScroll = Date.now(); @@ -736,6 +1078,9 @@ var PDFView = { thumbnails.push(thumbnailView); var pageRef = page.ref; pagesRefMap[pageRef.num + ' ' + pageRef.gen + ' R'] = i; + + // Trigger text extraction. TODO: Make this happen lasyliy if needed. + PDFFindController.extractText(); } self.pagesRefMap = pagesRefMap; @@ -1229,6 +1574,7 @@ var PageView = function pageView(container, pdfPage, id, scale, this.resume = null; this.textContent = null; + this.textLayer = null; var anchor = document.createElement('a'); anchor.name = '' + this.id; @@ -1475,7 +1821,8 @@ var PageView = function pageView(container, pdfPage, id, scale, textLayerDiv.className = 'textLayer'; div.appendChild(textLayerDiv); } - var textLayer = textLayerDiv ? new TextLayerBuilder(textLayerDiv) : null; + var textLayer = this.textLayer = + textLayerDiv ? new TextLayerBuilder(textLayerDiv, this.id - 1) : null; var scale = this.scale, viewport = this.viewport; canvas.width = viewport.width; @@ -1834,21 +2181,25 @@ var CustomStyle = (function CustomStyleClosure() { return CustomStyle; })(); -var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { +var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { var textLayerFrag = document.createDocumentFragment(); + this.textLayerDiv = textLayerDiv; this.layoutDone = false; this.divContentDone = false; + this.pageIdx = pageIdx; + this.matches = []; this.beginLayout = function textLayerBuilderBeginLayout() { this.textDivs = []; this.textLayerQueue = []; + this.renderingDone = false; }; this.endLayout = function textLayerBuilderEndLayout() { this.layoutDone = true; this.insertDivContent(); - }, + }; this.renderLayer = function textLayerBuilderRenderLayer() { var self = this; @@ -1862,8 +2213,11 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { if (textDivs.length > 100000) return; - while (textDivs.length > 0) { - var textDiv = textDivs.shift(); + var i = textDivs.length; + + while (i !== 0) { + i--; + var textDiv = textDivs[i]; textLayerFrag.appendChild(textDiv); ctx.font = textDiv.style.fontSize + ' ' + textDiv.style.fontFamily; @@ -1875,9 +2229,14 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { CustomStyle.setProp('transform' , textDiv, 'scale(' + textScale + ', 1)'); CustomStyle.setProp('transformOrigin' , textDiv, '0% 0%'); + + textLayerDiv.appendChild(textDiv); } } + this.renderingDone = true; + this.updateMatches(); + textLayerDiv.appendChild(textLayerFrag); }; @@ -1944,6 +2303,184 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { this.textContent = textContent; this.insertDivContent(); }; + + this.convertMatches = function textLayerBuilderConvertMatches(matches) { + var i = 0; + var iIndex = 0; + var bidiTexts = this.textContent.bidiTexts; + var end = bidiTexts.length - 1; + var queryLen = PDFFindController.state.query.length; + + var lastDivIdx = -1; + var pos; + + var ret = []; + + // Loop over all the matches. + for (var m = 0; m < matches.length; m++) { + var matchIdx = matches[m]; + // # Calculate the begin position. + + // Loop over the divIdxs. + while (i !== end && matchIdx >= (iIndex + bidiTexts[i].str.length)) { + iIndex += bidiTexts[i].str.length; + i++; + } + + // TODO: Do proper handling here if something goes wrong. + if (i == bidiTexts.length) { + console.error('Could not find matching mapping'); + } + + var match = { + begin: { + divIdx: i, + offset: matchIdx - iIndex + } + }; + + // # Calculate the end position. + matchIdx += queryLen; + + // Somewhat same array as above, but use a > instead of >= to get the end + // position right. + while (i !== end && matchIdx > (iIndex + bidiTexts[i].str.length)) { + iIndex += bidiTexts[i].str.length; + i++; + } + + match.end = { + divIdx: i, + offset: matchIdx - iIndex + }; + ret.push(match); + } + + return ret; + }; + + this.renderMatches = function textLayerBuilder_renderMatches(matches) { + var bidiTexts = this.textContent.bidiTexts; + var textDivs = this.textDivs; + var prevEnd = null; + var isSelectedPage = this.pageIdx === PDFFindController.selected.pageIdx; + var selectedMatchIdx = PDFFindController.selected.matchIdx; + + var infty = { + divIdx: -1, + offset: undefined + }; + + function beginText(begin, className) { + var divIdx = begin.divIdx; + var div = textDivs[divIdx]; + div.innerHTML = ''; + + var content = bidiTexts[divIdx].str.substring(0, begin.offset); + var node = document.createTextNode(content); + if (className) { + var isSelected = isSelectedPage && + divIdx === selectedMatchIdx; + var span = document.createElement('span'); + span.className = className + (isSelected ? ' selected' : ''); + span.appendChild(node); + div.appendChild(span); + return; + } + div.appendChild(node); + } + + function appendText(from, to, className) { + var divIdx = from.divIdx; + var div = textDivs[divIdx]; + + var content = bidiTexts[divIdx].str.substring(from.offset, to.offset); + var node = document.createTextNode(content); + if (className) { + var span = document.createElement('span'); + span.className = className; + span.appendChild(node); + div.appendChild(span); + return; + } + div.appendChild(node); + } + + function highlightDiv(divIdx, className) { + textDivs[divIdx].className = className; + } + + for (var i = 0; i < matches.length; i++) { + var match = matches[i]; + var begin = match.begin; + var end = match.end; + + var isSelected = isSelectedPage && i === selectedMatchIdx; + var highlightSuffix = (isSelected ? ' selected' : ''); + if (isSelected) + scrollIntoView(textDivs[begin.divIdx], {top: -50}); + + // Match inside new div. + if (!prevEnd || begin.divIdx !== prevEnd.divIdx) { + // If there was a previous div, then add the text at the end + if (prevEnd !== null) { + appendText(prevEnd, infty); + } + // clears the divs and set the content until the begin point. + beginText(begin); + } else { + appendText(prevEnd, begin); + } + + if (begin.divIdx === end.divIdx) { + appendText(begin, end, 'highlight' + highlightSuffix); + } else { + appendText(begin, infty, 'highlight begin' + highlightSuffix); + for (var n = begin.divIdx + 1; n < end.divIdx; n++) { + highlightDiv(n, 'highlight middle' + highlightSuffix); + } + beginText(end, 'highlight end' + highlightSuffix); + } + prevEnd = end; + } + + if (prevEnd) { + appendText(prevEnd, infty); + } + }; + + this.updateMatches = function textLayerUpdateMatches() { + // Only show matches, once all rendering is done. + if (!this.renderingDone) + return; + + // Clear out all matches. + var matches = this.matches; + var textDivs = this.textDivs; + var bidiTexts = this.textContent.bidiTexts; + var clearedUntilDivIdx = -1; + + for (var i = 0; i < matches.length; i++) { + var match = matches[i]; + var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx); + for (var n = begin; n <= match.end.divIdx; n++) { + var div = bidiTexts[n].str; + div.textContent = div.textContent; + div.className = ''; + } + clearedUntilDivIdx = match.end.divIdx + 1; + } + + if (!PDFFindController.active) + return; + + // Convert the matches on the page controller into the match format used + // for the textLayer. + this.matches = matches = + this.convertMatches(PDFFindController.pageMatches[this.pageIdx] || []); + + this.renderMatches(this.matches); + }; }; document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) { @@ -2059,16 +2596,6 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) { PDFView.switchSidebarView('outline'); }); - document.getElementById('viewSearch').addEventListener('click', - function() { - PDFView.switchSidebarView('search'); - }); - - document.getElementById('searchButton').addEventListener('click', - function() { - PDFView.search(); - }); - document.getElementById('previous').addEventListener('click', function() { PDFView.page--; @@ -2331,6 +2858,12 @@ window.addEventListener('keydown', function keydown(evt) { // control is selected or not. if (cmd == 1 || cmd == 8) { // either CTRL or META key. switch (evt.keyCode) { +//#if !(FIREFOX || MOZCENTRAL) + case 70: + PDFFindBar.toggle(); + handled = true; + break; +//#endif case 61: // FF/Mac '=' case 107: // FF '+' and '=' case 187: // Chrome '+' From d94bbad575bbeea6d5e875d5031784e02bf26a9f Mon Sep 17 00:00:00 2001 From: Artur Adib <arturadib@gmail.com> Date: Tue, 25 Sep 2012 14:54:29 -0400 Subject: [PATCH 02/17] typo fix --- web/viewer.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index 65c87740f..aa91f5da0 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -236,10 +236,10 @@ var PDFFindController = { 'findcasesensitivitychange' ]; - this.handelEvent = this.handelEvent.bind(this); + this.handleEvent = this.handleEvent.bind(this); for (var i = 0; i < events.length; i++) { - window.addEventListener(events[i], this.handelEvent); + window.addEventListener(events[i], this.handleEvent); } }, @@ -295,7 +295,7 @@ var PDFFindController = { extractPageText(0); }, - handelEvent: function(e) { + handleEvent: function(e) { this.state = e.detail; if (e.detail.findPrevious === undefined) { this.dirtyMatch = true; @@ -358,7 +358,7 @@ var PDFFindController = { } } else { // If there is NO selection, then there is no match at all -> no sense to - // handel previous/next action. + // handle previous/next action. if (this.selected.pageIdx === -1) return; From 6864a072215619c6c650a4600ea21a98c1288903 Mon Sep 17 00:00:00 2001 From: Artur Adib <arturadib@gmail.com> Date: Tue, 25 Sep 2012 16:17:27 -0400 Subject: [PATCH 03/17] Use "find" instead of both find & search --- .../firefox/components/PdfStreamConverter.js | 4 +- l10n/ar/viewer.properties | 10 +-- l10n/da/viewer.properties | 8 +- l10n/en-US/viewer.properties | 10 +-- l10n/es/viewer.properties | 10 +-- l10n/fi/viewer.properties | 10 +-- l10n/ja/viewer.properties | 10 +-- l10n/nl/viewer.properties | 10 +-- l10n/sv/viewer.properties | 10 +-- l10n/zh-TW/viewer.properties | 8 +- web/viewer.css | 16 ++-- web/viewer.html | 14 ++-- web/viewer.js | 82 +++++++++---------- 13 files changed, 101 insertions(+), 101 deletions(-) diff --git a/extensions/firefox/components/PdfStreamConverter.js b/extensions/firefox/components/PdfStreamConverter.js index 76b7788a8..58d142204 100644 --- a/extensions/firefox/components/PdfStreamConverter.js +++ b/extensions/firefox/components/PdfStreamConverter.js @@ -317,8 +317,8 @@ ChromeActions.prototype = { pdfBugEnabled: function() { return getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false); }, - searchEnabled: function() { - return getBoolPref(PREF_PREFIX + '.searchEnabled', false); + findEnabled: function() { + return getBoolPref(PREF_PREFIX + '.findEnabled', false); }, fallback: function(url, sendResponse) { var self = this; diff --git a/l10n/ar/viewer.properties b/l10n/ar/viewer.properties index 3ef9c1cd0..d1ceae44e 100644 --- a/l10n/ar/viewer.properties +++ b/l10n/ar/viewer.properties @@ -36,8 +36,8 @@ outline.title=إظهار ملخص المستند outline_label=ملخص المستند thumbs.title=إظهار الصور المصغرة thumbs_label=الصور المصغرة -search_panel.title=البحث في المستند -search_panel_label=بحث +find_panel.title=البحث في المستند +find_panel_label=بحث # Document outline messages no_outline=لا يوجد ملخص @@ -54,9 +54,9 @@ thumb_page_canvas=صورة مصغرة من الصفحة {{page}} page_rotate_cw.label=تدوير مع عقارب الساعة page_rotate_ccw.label=تدوير عكس عقارب الساعة -# Search panel button title and messages -search=بحث -search_terms_not_found=(لا يوجد) +# Find panel button title and messages +find=بحث +find_terms_not_found=(لا يوجد) # Error panel labels error_more_info=مزيد من المعلومات diff --git a/l10n/da/viewer.properties b/l10n/da/viewer.properties index 72e04bb62..90231c7ca 100644 --- a/l10n/da/viewer.properties +++ b/l10n/da/viewer.properties @@ -36,8 +36,8 @@ outline.title=Vis dokumentoversigt outline_label=Dokumentoversigt thumbs.title=Vis thumbnails thumbs_label=Thumbnails -search_panel.title=Søg i dokumentet -search_panel_label=Søg +find_panel.title=Søg i dokumentet +find_panel_label=Søg # Dokumentoversigtsbeskeder no_outline=Ingen dokumentoversigt tilgængelig @@ -51,8 +51,8 @@ thumb_page_title=Side {{page}} thumb_page_canvas=Thumbnail af side {{page}} # Søgepanelet -search=Søg -search_terms_not_found=(Ikke fundet) +find=Søg +find_terms_not_found=(Ikke fundet) # Fejlpanel error_more_info=Mere information diff --git a/l10n/en-US/viewer.properties b/l10n/en-US/viewer.properties index 6afb232e7..678e23c8e 100644 --- a/l10n/en-US/viewer.properties +++ b/l10n/en-US/viewer.properties @@ -36,8 +36,8 @@ outline.title=Show Document Outline outline_label=Document Outline thumbs.title=Show Thumbnails thumbs_label=Thumbnails -search_panel.title=Search Document -search_panel_label=Search +find_panel.title=Find in Document +find_panel_label=Find # Document outline messages no_outline=No Outline Available @@ -54,9 +54,9 @@ thumb_page_canvas=Thumbnail of Page {{page}} page_rotate_cw.label=Rotate Clockwise page_rotate_ccw.label=Rotate Counter-Clockwise -# Search panel button title and messages -search=Find -search_terms_not_found=(Not found) +# Find panel button title and messages +find=Find +find_terms_not_found=(Not found) # Error panel labels error_more_info=More Information diff --git a/l10n/es/viewer.properties b/l10n/es/viewer.properties index 8485cbf17..bac4cee67 100644 --- a/l10n/es/viewer.properties +++ b/l10n/es/viewer.properties @@ -36,8 +36,8 @@ outline.title=Mostrar esquema del documento outline_label=Esquema del documento thumbs.title=Mostrar miniaturas thumbs_label=Miniaturas -search_panel.title=Buscar en el documento -search_panel_label=Buscar +find_panel.title=Buscar en el documento +find_panel_label=Buscar # Document outline messages no_outline=No hay un esquema disponible @@ -50,9 +50,9 @@ thumb_page_title=Página {{page}} # number. thumb_page_canvas=Miniatura de la página {{page}} -# Search panel button title and messages -search=Buscar -search_terms_not_found=(No encontrado) +# Find panel button title and messages +find=Buscar +find_terms_not_found=(No encontrado) # Error panel labels error_more_info=Más información diff --git a/l10n/fi/viewer.properties b/l10n/fi/viewer.properties index 4cc0ba70e..5fcde5eaf 100644 --- a/l10n/fi/viewer.properties +++ b/l10n/fi/viewer.properties @@ -36,8 +36,8 @@ outline.title=Näytä asiakirjan jäsennys outline_label=Asiakirjan jäsennys thumbs.title=Näytä esikatselukuvat thumbs_label=Esikatselukuvat -search_panel.title=Etsi asiakirjasta -search_panel_label=Etsi +find_panel.title=Etsi asiakirjasta +find_panel_label=Etsi # Document outline messages no_outline=Jäsennystä ei ole tarjolla @@ -50,9 +50,9 @@ thumb_page_title=Sivu {{page}} # number. thumb_page_canvas=Sivun {{page}} esikatselukuva -# Search panel button title and messages -search=Etsi -search_terms_not_found=(Ei löytynyt) +# Find panel button title and messages +find=Etsi +find_terms_not_found=(Ei löytynyt) # Error panel labels error_more_info=Enemmän tietoa diff --git a/l10n/ja/viewer.properties b/l10n/ja/viewer.properties index 33f00ac4c..a79d65940 100644 --- a/l10n/ja/viewer.properties +++ b/l10n/ja/viewer.properties @@ -36,8 +36,8 @@ outline.title=文書の目次 outline_label=文書の目次 thumbs.title=縮小版 thumbs_label=縮小版 -search_panel.title=検索 -search_panel_label=検索 +find_panel.title=検索 +find_panel_label=検索 # Document outline messages no_outline=利用可能な目次はありません @@ -54,9 +54,9 @@ thumb_page_canvas=ページの縮小版 {{page}} page_rotate_cw.label=右回転 page_rotate_ccw.label=左回転 -# Search panel button title and messages -search=検索 -search_terms_not_found=(見つかりませんでした) +# Find panel button title and messages +find=検索 +find_terms_not_found=(見つかりませんでした) # Error panel labels error_more_info=詳細情報 diff --git a/l10n/nl/viewer.properties b/l10n/nl/viewer.properties index 5164862ea..45bbec253 100644 --- a/l10n/nl/viewer.properties +++ b/l10n/nl/viewer.properties @@ -34,8 +34,8 @@ outline.title=Toon document structuur outline_label=Document structuur thumbs.title=Toon miniaturen thumbs_label=Miniaturen -search_panel.title=Doorzoek document -search_panel_label=Zoek +find_panel.title=Doorzoek document +find_panel_label=Zoek # Document outline messages no_outline=Geen structuur beschikbaar @@ -48,9 +48,9 @@ thumb_page_title=Pagina {{page}} # number. thumb_page_canvas=Miniatuur van pagina {{page}} -# Search panel button title and messages -search=Zoek -search_terms_not_found=(Niet gevonden) +# Find panel button title and messages +find=Zoek +find_terms_not_found=(Niet gevonden) # Error panel labels error_more_info=Meer informatie diff --git a/l10n/sv/viewer.properties b/l10n/sv/viewer.properties index 81d4a3958..e09418442 100644 --- a/l10n/sv/viewer.properties +++ b/l10n/sv/viewer.properties @@ -34,8 +34,8 @@ outline.title=Visa dokumentdisposition outline_label=Dokumentdisposition thumbs.title=Visa miniatyrer thumbs_label=Miniatyrer -search_panel.title=Sök i dokumentet -search_panel_label=Sök +find_panel.title=Sök i dokumentet +find_panel_label=Sök # Document outline messages no_outline=Ingen dokumentdisposition tillgänglig @@ -48,9 +48,9 @@ thumb_page_title=Sida {{page}} # number. thumb_page_canvas=Miniatyr av sida {{page}} -# Search panel button title and messages -search=Hitta -search_terms_not_found=(hittades inte) +# Find panel button title and messages +find=Hitta +find_terms_not_found=(hittades inte) # Error panel labels error_more_info=Mer information diff --git a/l10n/zh-TW/viewer.properties b/l10n/zh-TW/viewer.properties index b7ff63235..99d85811b 100644 --- a/l10n/zh-TW/viewer.properties +++ b/l10n/zh-TW/viewer.properties @@ -34,8 +34,8 @@ outline.title=顯示文件綱要 outline_label=文件綱要 thumbs.title=顯示縮圖 thumbs_label=縮圖 -search_panel.title=搜索文件 -search_panel_label=搜索 +find_panel.title=搜索文件 +find_panel_label=搜索 # 文件綱要相關訊息 no_outline=無可用的綱要 @@ -51,8 +51,8 @@ page_rotate_cw.label=順時針旋轉 page_rotate_ccw.label=逆時針旋轉 # 搜尋面板按鍵文字及訊息 -search=搜索 -search_terms_not_found=(沒有找到) +find=搜索 +find_terms_not_found=(沒有找到) # 錯誤面板標籤 error_more_info=更多資訊 diff --git a/web/viewer.css b/web/viewer.css index caf3a09f1..bf172fe5b 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -728,7 +728,7 @@ html[dir='rtl'] .toolbarButton.pageDown::before { content: url(images/toolbarButton-viewOutline.png); } -#viewSearch.toolbarButton::before { +#viewFind.toolbarButton::before { display: inline-block; content: url(images/toolbarButton-search.png); } @@ -871,7 +871,7 @@ a:focus > .thumbnail > .thumbnailSelectionRing, } .outlineItem > a, -#searchResults > a { +#findResults > a { text-decoration: none; display: inline-block; min-width: 95%; @@ -888,7 +888,7 @@ a:focus > .thumbnail > .thumbnailSelectionRing, } .outlineItem > a:hover, -#searchResults > a:hover { +#findResults > a:hover { background-color: hsla(0,0%,100%,.02); background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-clip: padding-box; @@ -915,7 +915,7 @@ a:focus > .thumbnail > .thumbnailSelectionRing, font-style: italic; } -#searchScrollView { +#findScrollView { position: absolute; top: 10px; bottom: 10px; @@ -923,26 +923,26 @@ a:focus > .thumbnail > .thumbnailSelectionRing, width: 280px; } -#searchToolbar { +#findToolbar { padding-left: 0px; right: 0px; padding-top: 0px; padding-bottom: 5px; } -#searchToolbar > input { +#findToolbar > input { margin-left: 4px; width: 124px; } -#searchToolbar button { +#findToolbar button { width: auto; margin: 0; padding: 0 6px; height: 22px; } -#searchResults { +#findResults { overflow: auto; position: absolute; top: 30px; diff --git a/web/viewer.html b/web/viewer.html index 0ee6313a6..836cc554a 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -88,8 +88,8 @@ limitations under the License. <button id="viewOutline" class="toolbarButton group" title="Show Document Outline" tabindex="2" data-l10n-id="outline"> <span data-l10n-id="outline_label">Document Outline</span> </button> - <button id="viewSearch" class="toolbarButton group hidden" title="Search Document" tabindex="3" data-l10n-id="search_panel"> - <span data-l10n-id="search_panel_label">Search Document</span> + <button id="viewFind" class="toolbarButton group" title="Find in Document" tabindex="3" data-l10n-id="find_panel"> + <span data-l10n-id="find_panel_label">Find in Document</span> </button> </div> <div id="sidebarContent"> @@ -97,12 +97,12 @@ limitations under the License. </div> <div id="outlineView" class="hidden"> </div> - <div id="searchView" class="hidden"> - <div id="searchToolbar"> - <input id="searchTermsInput" class="toolbarField"> - <button id="searchButton" class="textButton toolbarButton" data-l10n-id="search">Find</button> + <div id="findView" class="hidden"> + <div id="findToolbar"> + <input id="findTermsInput" class="toolbarField"> + <button id="findButton" class="textButton toolbarButton" data-l10n-id="find">Find</button> </div> - <div id="searchResults"></div> + <div id="findResults"></div> </div> </div> </div> <!-- sidebarContainer --> diff --git a/web/viewer.js b/web/viewer.js index aa91f5da0..f7ed8a7aa 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -211,7 +211,7 @@ var currentPageNumber = 1; var PDFFindController = { startedTextExtraction: false, - // If active, search resulsts will be highlighted. + // If active, find results will be highlighted. active: false, // Stores the text for each page. @@ -244,7 +244,7 @@ var PDFFindController = { }, calcFindMatch: function(pageContent) { - // TODO: Handle the other search options here as well. + // TODO: Handle the other find options here as well. var query = this.state.query; var queryLen = query.length; @@ -274,7 +274,7 @@ var PDFFindController = { function extractPageText(pageIndex) { PDFView.pages[pageIndex].getTextContent().then( function textContentResolved(data) { - // Bulid the search string. + // Build the find string. var bidiTexts = data.bidiTexts; var str = ''; @@ -434,7 +434,7 @@ var PDFFindBar = { initialize: function() { this.bar = document.getElementById('findbar'); - this.toggleButton = document.getElementById('viewSearch'); + this.toggleButton = document.getElementById('viewFind'); this.findField = document.getElementById('findInput'); this.highlightAll = document.getElementById('findHighlightAll'); this.caseSensitive = document.getElementById('findMatchCase'); @@ -1224,39 +1224,39 @@ var PDFView = { return true; }, - search: function pdfViewStartSearch() { - // Limit this function to run every <SEARCH_TIMEOUT>ms. - var SEARCH_TIMEOUT = 250; - var lastSearch = this.lastSearch; + find: function pdfViewStartFind() { + // Limit this function to run every <FIND_TIMEOUT>ms. + var FIND_TIMEOUT = 250; + var lastFind = this.lastFind; var now = Date.now(); - if (lastSearch && (now - lastSearch) < SEARCH_TIMEOUT) { - if (!this.searchTimer) { - this.searchTimer = setTimeout(function resumeSearch() { - PDFView.search(); + if (lastFind && (now - lastFind) < FIND_TIMEOUT) { + if (!this.findTimer) { + this.findTimer = setTimeout(function resumeFind() { + PDFView.find(); }, - SEARCH_TIMEOUT - (now - lastSearch) + FIND_TIMEOUT - (now - lastFind) ); } return; } - this.searchTimer = null; - this.lastSearch = now; + this.FindTimer = null; + this.lastFind = now; function bindLink(link, pageNumber) { link.href = '#' + pageNumber; - link.onclick = function searchBindLink() { + link.onclick = function findBindLink() { PDFView.page = pageNumber; return false; }; } - var searchResults = document.getElementById('searchResults'); + var findResults = document.getElementById('findResults'); - var searchTermsInput = document.getElementById('searchTermsInput'); - searchResults.removeAttribute('hidden'); - searchResults.textContent = ''; + var findTermsInput = document.getElementById('findTermsInput'); + findResults.removeAttribute('hidden'); + findResults.textContent = ''; - var terms = searchTermsInput.value; + var terms = findTermsInput.value; if (!terms) return; @@ -1276,17 +1276,17 @@ var PDFView = { var link = document.createElement('a'); bindLink(link, pageNumber); link.textContent = 'Page ' + pageNumber + ': ' + textSample; - searchResults.appendChild(link); + findResults.appendChild(link); pageFound = true; } if (!pageFound) { - searchResults.textContent = ''; + findResults.textContent = ''; var noResults = document.createElement('div'); noResults.classList.add('noResults'); - noResults.textContent = mozL10n.get('search_terms_not_found', null, + noResults.textContent = mozL10n.get('find_terms_not_found', null, '(Not found)'); - searchResults.appendChild(noResults); + findResults.appendChild(noResults); } }, @@ -1331,20 +1331,20 @@ var PDFView = { switchSidebarView: function pdfViewSwitchSidebarView(view) { var thumbsView = document.getElementById('thumbnailView'); var outlineView = document.getElementById('outlineView'); - var searchView = document.getElementById('searchView'); + var findView = document.getElementById('findView'); var thumbsButton = document.getElementById('viewThumbnail'); var outlineButton = document.getElementById('viewOutline'); - var searchButton = document.getElementById('viewSearch'); + var findButton = document.getElementById('viewFind'); switch (view) { case 'thumbs': thumbsButton.classList.add('toggled'); outlineButton.classList.remove('toggled'); - searchButton.classList.remove('toggled'); + findButton.classList.remove('toggled'); thumbsView.classList.remove('hidden'); outlineView.classList.add('hidden'); - searchView.classList.add('hidden'); + findView.classList.add('hidden'); PDFView.renderHighestPriority(); break; @@ -1352,25 +1352,25 @@ var PDFView = { case 'outline': thumbsButton.classList.remove('toggled'); outlineButton.classList.add('toggled'); - searchButton.classList.remove('toggled'); + findButton.classList.remove('toggled'); thumbsView.classList.add('hidden'); outlineView.classList.remove('hidden'); - searchView.classList.add('hidden'); + findView.classList.add('hidden'); if (outlineButton.getAttribute('disabled')) return; break; - case 'search': + case 'find': thumbsButton.classList.remove('toggled'); outlineButton.classList.remove('toggled'); - searchButton.classList.add('toggled'); + findButton.classList.add('toggled'); thumbsView.classList.add('hidden'); outlineView.classList.add('hidden'); - searchView.classList.remove('hidden'); + findView.classList.remove('hidden'); - var searchTermsInput = document.getElementById('searchTermsInput'); - searchTermsInput.focus(); + var findTermsInput = document.getElementById('findTermsInput'); + findTermsInput.focus(); // Start text extraction as soon as the search gets displayed. this.extractText(); break; @@ -1386,7 +1386,7 @@ var PDFView = { self.pages[pageIndex].pdfPage.getTextContent().then( function textContentResolved(textContent) { self.pageText[pageIndex] = textContent.join(''); - self.search(); + self.find(); if ((pageIndex + 1) < self.pages.length) extractPageText(pageIndex + 1); } @@ -2545,8 +2545,8 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) { //#if !(FIREFOX || MOZCENTRAL) //#else -//if (FirefoxCom.requestSync('searchEnabled')) { -// document.querySelector('#viewSearch').classList.remove('hidden'); +//if (FirefoxCom.requestSync('findEnabled')) { +// document.querySelector('#viewFind').classList.remove('hidden'); //} //#endif @@ -2636,10 +2636,10 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) { PDFView.download(); }); - document.getElementById('searchTermsInput').addEventListener('keydown', + document.getElementById('findTermsInput').addEventListener('keydown', function(event) { if (event.keyCode == 13) { - PDFView.search(); + PDFView.find(); } }); From 6022476f036b4829a9b91c02ee988f2bf2f94bd2 Mon Sep 17 00:00:00 2001 From: Artur Adib <arturadib@gmail.com> Date: Wed, 26 Sep 2012 12:14:57 -0400 Subject: [PATCH 04/17] add support for case sensitive --- web/viewer.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/web/viewer.js b/web/viewer.js index f7ed8a7aa..80c25aafb 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -247,11 +247,17 @@ var PDFFindController = { // TODO: Handle the other find options here as well. var query = this.state.query; + var caseSensitive = this.state.caseSensitive; var queryLen = query.length; if (queryLen === 0) return []; + if (!caseSensitive) { + pageContent = pageContent.toLowerCase(); + query = query.toLowerCase(); + } + var matches = []; var matchIdx = -queryLen; From 73b96e0e580a6921868b07abeaed476c0d94a392 Mon Sep 17 00:00:00 2001 From: Artur Adib <arturadib@gmail.com> Date: Wed, 26 Sep 2012 14:09:55 -0400 Subject: [PATCH 05/17] bug fix: clear previous highlights --- web/viewer.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/web/viewer.js b/web/viewer.js index 80c25aafb..214b272fd 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -2365,6 +2365,18 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { return ret; }; + this.clearMatches = function textLayerBuilder_clearMatches() { + var textDivs = this.textDivs; + + // Clear all previous highlights + textDivs.forEach(function(div) { + var spans = div.querySelectorAll('span'); + for (var i = 0, ii = spans.length; i < ii; i++) { + spans[i].className = ''; + } + }); + } + this.renderMatches = function textLayerBuilder_renderMatches(matches) { var bidiTexts = this.textContent.bidiTexts; var textDivs = this.textDivs; @@ -2372,6 +2384,8 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { var isSelectedPage = this.pageIdx === PDFFindController.selected.pageIdx; var selectedMatchIdx = PDFFindController.selected.matchIdx; + this.clearMatches(); + var infty = { divIdx: -1, offset: undefined From 1ec2e2a1a2ac2260bbde0a5cee32209458dd2f9b Mon Sep 17 00:00:00 2001 From: Artur Adib <arturadib@gmail.com> Date: Wed, 26 Sep 2012 16:38:02 -0400 Subject: [PATCH 06/17] remove old unused code --- web/viewer.css | 36 +-------------- web/viewer.html | 7 --- web/viewer.js | 113 ------------------------------------------------ 3 files changed, 2 insertions(+), 154 deletions(-) diff --git a/web/viewer.css b/web/viewer.css index bf172fe5b..92e7d37f1 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -870,8 +870,7 @@ a:focus > .thumbnail > .thumbnailSelectionRing, margin-left: 20px; } -.outlineItem > a, -#findResults > a { +.outlineItem > a { text-decoration: none; display: inline-block; min-width: 95%; @@ -887,8 +886,7 @@ a:focus > .thumbnail > .thumbnailSelectionRing, white-space: nowrap; } -.outlineItem > a:hover, -#findResults > a:hover { +.outlineItem > a:hover { background-color: hsla(0,0%,100%,.02); background-image: -moz-linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0)); background-clip: padding-box; @@ -923,36 +921,6 @@ a:focus > .thumbnail > .thumbnailSelectionRing, width: 280px; } -#findToolbar { - padding-left: 0px; - right: 0px; - padding-top: 0px; - padding-bottom: 5px; -} - -#findToolbar > input { - margin-left: 4px; - width: 124px; -} - -#findToolbar button { - width: auto; - margin: 0; - padding: 0 6px; - height: 22px; -} - -#findResults { - overflow: auto; - position: absolute; - top: 30px; - bottom: 0px; - left: 0px; - right: 0; - padding: 4px 4px 0; - font-size: smaller; -} - #sidebarControls { position:absolute; width: 180px; diff --git a/web/viewer.html b/web/viewer.html index 836cc554a..a7e9091cc 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -97,13 +97,6 @@ limitations under the License. </div> <div id="outlineView" class="hidden"> </div> - <div id="findView" class="hidden"> - <div id="findToolbar"> - <input id="findTermsInput" class="toolbarField"> - <button id="findButton" class="textButton toolbarButton" data-l10n-id="find">Find</button> - </div> - <div id="findResults"></div> - </div> </div> </div> <!-- sidebarContainer --> diff --git a/web/viewer.js b/web/viewer.js index 214b272fd..bfd7cc972 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -244,8 +244,6 @@ var PDFFindController = { }, calcFindMatch: function(pageContent) { - // TODO: Handle the other find options here as well. - var query = this.state.query; var caseSensitive = this.state.caseSensitive; var queryLen = query.length; @@ -1230,72 +1228,6 @@ var PDFView = { return true; }, - find: function pdfViewStartFind() { - // Limit this function to run every <FIND_TIMEOUT>ms. - var FIND_TIMEOUT = 250; - var lastFind = this.lastFind; - var now = Date.now(); - if (lastFind && (now - lastFind) < FIND_TIMEOUT) { - if (!this.findTimer) { - this.findTimer = setTimeout(function resumeFind() { - PDFView.find(); - }, - FIND_TIMEOUT - (now - lastFind) - ); - } - return; - } - this.FindTimer = null; - this.lastFind = now; - - function bindLink(link, pageNumber) { - link.href = '#' + pageNumber; - link.onclick = function findBindLink() { - PDFView.page = pageNumber; - return false; - }; - } - - var findResults = document.getElementById('findResults'); - - var findTermsInput = document.getElementById('findTermsInput'); - findResults.removeAttribute('hidden'); - findResults.textContent = ''; - - var terms = findTermsInput.value; - - if (!terms) - return; - - // simple search: removing spaces and hyphens, then scanning every - terms = terms.replace(/\s-/g, '').toLowerCase(); - var index = PDFView.pageText; - var pageFound = false; - for (var i = 0, ii = index.length; i < ii; i++) { - var pageText = index[i].replace(/\s-/g, '').toLowerCase(); - var j = pageText.indexOf(terms); - if (j < 0) - continue; - - var pageNumber = i + 1; - var textSample = index[i].substr(j, 50); - var link = document.createElement('a'); - bindLink(link, pageNumber); - link.textContent = 'Page ' + pageNumber + ': ' + textSample; - findResults.appendChild(link); - - pageFound = true; - } - if (!pageFound) { - findResults.textContent = ''; - var noResults = document.createElement('div'); - noResults.classList.add('noResults'); - noResults.textContent = mozL10n.get('find_terms_not_found', null, - '(Not found)'); - findResults.appendChild(noResults); - } - }, - setHash: function pdfViewSetHash(hash) { if (!hash) return; @@ -1337,20 +1269,16 @@ var PDFView = { switchSidebarView: function pdfViewSwitchSidebarView(view) { var thumbsView = document.getElementById('thumbnailView'); var outlineView = document.getElementById('outlineView'); - var findView = document.getElementById('findView'); var thumbsButton = document.getElementById('viewThumbnail'); var outlineButton = document.getElementById('viewOutline'); - var findButton = document.getElementById('viewFind'); switch (view) { case 'thumbs': thumbsButton.classList.add('toggled'); outlineButton.classList.remove('toggled'); - findButton.classList.remove('toggled'); thumbsView.classList.remove('hidden'); outlineView.classList.add('hidden'); - findView.classList.add('hidden'); PDFView.renderHighestPriority(); break; @@ -1358,49 +1286,15 @@ var PDFView = { case 'outline': thumbsButton.classList.remove('toggled'); outlineButton.classList.add('toggled'); - findButton.classList.remove('toggled'); thumbsView.classList.add('hidden'); outlineView.classList.remove('hidden'); - findView.classList.add('hidden'); if (outlineButton.getAttribute('disabled')) return; break; - - case 'find': - thumbsButton.classList.remove('toggled'); - outlineButton.classList.remove('toggled'); - findButton.classList.add('toggled'); - thumbsView.classList.add('hidden'); - outlineView.classList.add('hidden'); - findView.classList.remove('hidden'); - - var findTermsInput = document.getElementById('findTermsInput'); - findTermsInput.focus(); - // Start text extraction as soon as the search gets displayed. - this.extractText(); - break; } }, - extractText: function() { - if (this.startedTextExtraction) - return; - this.startedTextExtraction = true; - var self = this; - function extractPageText(pageIndex) { - self.pages[pageIndex].pdfPage.getTextContent().then( - function textContentResolved(textContent) { - self.pageText[pageIndex] = textContent.join(''); - self.find(); - if ((pageIndex + 1) < self.pages.length) - extractPageText(pageIndex + 1); - } - ); - } - extractPageText(0); - }, - getVisiblePages: function pdfViewGetVisiblePages() { return this.getVisibleElements(this.container, this.pages, true); @@ -2656,13 +2550,6 @@ document.addEventListener('DOMContentLoaded', function webViewerLoad(evt) { PDFView.download(); }); - document.getElementById('findTermsInput').addEventListener('keydown', - function(event) { - if (event.keyCode == 13) { - PDFView.find(); - } - }); - document.getElementById('pageNumber').addEventListener('change', function() { PDFView.page = this.value; From e2a2085f6258e2e11b20b93b50ec131b91f4bb06 Mon Sep 17 00:00:00 2001 From: Artur Adib <arturadib@gmail.com> Date: Wed, 26 Sep 2012 16:47:26 -0400 Subject: [PATCH 07/17] remove find button in MOZCENTRAL --- web/viewer.html | 2 ++ web/viewer.js | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/web/viewer.html b/web/viewer.html index a7e9091cc..90124508b 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -88,9 +88,11 @@ limitations under the License. <button id="viewOutline" class="toolbarButton group" title="Show Document Outline" tabindex="2" data-l10n-id="outline"> <span data-l10n-id="outline_label">Document Outline</span> </button> +<!--#if !MOZCENTRAL--> <button id="viewFind" class="toolbarButton group" title="Find in Document" tabindex="3" data-l10n-id="find_panel"> <span data-l10n-id="find_panel_label">Find in Document</span> </button> +<!--#endif--> </div> <div id="sidebarContent"> <div id="thumbnailView"> diff --git a/web/viewer.js b/web/viewer.js index bfd7cc972..18954bca7 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -446,8 +446,7 @@ var PDFFindBar = { this.findMsgNotFound = document.getElementById('findMsgNotFound'); var self = this; - this.toggleButton.addEventListener('click', - function() { + this.toggleButton.addEventListener('click', function() { self.toggle(); }); From 6090b3edf9e3a3c66db09a9279290e7f4adaa72b Mon Sep 17 00:00:00 2001 From: Artur Adib <arturadib@gmail.com> Date: Thu, 27 Sep 2012 12:21:04 -0400 Subject: [PATCH 08/17] colors closer to FF's, add highlightAll support --- web/viewer.css | 4 ++-- web/viewer.js | 24 ++++++++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/web/viewer.css b/web/viewer.css index 92e7d37f1..77d4807dc 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -1067,7 +1067,7 @@ canvas { margin: -1px; padding: 1px; - background-color: rgba(0, 137, 26, 0.2); + background-color: rgba(180, 0, 170, 0.2); border-radius: 4px; } @@ -1084,7 +1084,7 @@ canvas { } .textLayer .highlight.selected { - background-color: rgba(255, 0, 0, 0.2); + background-color: rgba(0, 100, 0, 0.2); } /* TODO: file FF bug to support ::-moz-selection:window-inactive diff --git a/web/viewer.js b/web/viewer.js index 18954bca7..f55074263 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -458,22 +458,18 @@ var PDFFindBar = { // next match when the findField is selected. document.getElementById('findPrevious').addEventListener('click', - function() { - self.dispatchEvent('again', true); - }); + function() { self.dispatchEvent('again', true); } + ); - document.getElementById('findNext').addEventListener('click', - function() { + document.getElementById('findNext').addEventListener('click', function() { self.dispatchEvent('again', false); }); - this.highlightAll.addEventListener('click', - function() { + this.highlightAll.addEventListener('click', function() { self.dispatchEvent('highlightallchange'); }); - this.caseSensitive.addEventListener('click', - function() { + this.caseSensitive.addEventListener('click', function() { self.dispatchEvent('casesensitivitychange'); }); }, @@ -2276,6 +2272,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { var prevEnd = null; var isSelectedPage = this.pageIdx === PDFFindController.selected.pageIdx; var selectedMatchIdx = PDFFindController.selected.matchIdx; + var highlightAll = PDFFindController.state.highlightAll; this.clearMatches(); @@ -2323,7 +2320,14 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { textDivs[divIdx].className = className; } - for (var i = 0; i < matches.length; i++) { + var i0 = selectedMatchIdx, i1 = i0 + 1, i; + + if (highlightAll) { + i0 = 0; + i1 = matches.length; + } + + for (i = i0; i < i1; i++) { var match = matches[i]; var begin = match.begin; var end = match.end; From ecf3dae7764990a0f0e7218541a7609fc61338bc Mon Sep 17 00:00:00 2001 From: Julian Viereck <julian.viereck@gmail.com> Date: Fri, 28 Sep 2012 15:16:10 +0200 Subject: [PATCH 09/17] Fix clear matches functionality --- web/viewer.js | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index f55074263..1883333a5 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -2254,19 +2254,12 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { return ret; }; - this.clearMatches = function textLayerBuilder_clearMatches() { - var textDivs = this.textDivs; - - // Clear all previous highlights - textDivs.forEach(function(div) { - var spans = div.querySelectorAll('span'); - for (var i = 0, ii = spans.length; i < ii; i++) { - spans[i].className = ''; - } - }); - } - this.renderMatches = function textLayerBuilder_renderMatches(matches) { + // Early exit if there is nothing to render. + if (matches.length === 0) { + return; + } + var bidiTexts = this.textContent.bidiTexts; var textDivs = this.textDivs; var prevEnd = null; @@ -2274,8 +2267,6 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { var selectedMatchIdx = PDFFindController.selected.matchIdx; var highlightAll = PDFFindController.state.highlightAll; - this.clearMatches(); - var infty = { divIdx: -1, offset: undefined @@ -2377,12 +2368,13 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { var bidiTexts = this.textContent.bidiTexts; var clearedUntilDivIdx = -1; + // Clear out all current matches. for (var i = 0; i < matches.length; i++) { var match = matches[i]; var begin = Math.max(clearedUntilDivIdx, match.begin.divIdx); for (var n = begin; n <= match.end.divIdx; n++) { - var div = bidiTexts[n].str; - div.textContent = div.textContent; + var div = textDivs[n]; + div.textContent = bidiTexts[n].str; div.className = ''; } clearedUntilDivIdx = match.end.divIdx + 1; From 2a1264a74646eecb1ce5d4b59c5dbaa169a32ede Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Fri, 28 Sep 2012 09:03:35 -0700 Subject: [PATCH 10/17] Don't try to highlight anything if the page isn't selected and we aren't highlighting all. --- web/viewer.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/web/viewer.js b/web/viewer.js index 1883333a5..1d743d668 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -2316,6 +2316,9 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { if (highlightAll) { i0 = 0; i1 = matches.length; + } else if(!isSelectedPage) { + // Not highlighting all and this isn't the selected page, so do nothing. + return; } for (i = i0; i < i1; i++) { From 38193b1887cbe7f920cc99e728e5281cd76f262c Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Fri, 28 Sep 2012 11:18:45 -0700 Subject: [PATCH 11/17] Update the find bar ui status. --- web/viewer.css | 10 ++++++- web/viewer.html | 3 +- web/viewer.js | 76 ++++++++++++++++++++++++++++++++++--------------- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/web/viewer.css b/web/viewer.css index 77d4807dc..95b4dc5ab 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -282,9 +282,17 @@ html[dir='rtl'] #sidebarContent { font-size: 12px; line-height: 14px; text-align: left; + cursor: default; +} + +.findbar label { -webkit-user-select:none; -moz-user-select:none; - cursor: default; +} + +#findMsg { + font-style: italic; + color: #A6B7D0; } .notFound { diff --git a/web/viewer.html b/web/viewer.html index 90124508b..73c4cb87a 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -112,8 +112,7 @@ limitations under the License. <label for="findHighlightAll">Highlight all</label> <input type="checkbox" id="findMatchCase"> <label for="findMatchCase">Match case</label> - <span id="findMsgWrap" class="hidden">Reached end of page, continued from top</span> - <span id="findMsgNotFound" class="hidden">Phrase not found</span> + <span id="findMsg"></span> </div> <div class="toolbar"> <div id="toolbarContainer"> diff --git a/web/viewer.js b/web/viewer.js index 1d743d668..759133127 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -34,6 +34,12 @@ var RenderingStates = { PAUSED: 2, FINISHED: 3 }; +var FindStates = { + FIND_FOUND: 0, + FIND_NOTFOUND: 1, + FIND_WRAPPED: 2, + FIND_PENDING: 3 +}; //#if (GENERIC || CHROME) //PDFJS.workerSrc = '../build/pdf.js'; @@ -337,6 +343,12 @@ var PDFFindController = { this.active = true; + if (!this.state.query) { + this.updateUIState(FindStates.FIND_FOUND); + return; + } + this.updateUIState(FindStates.FIND_PENDING); + if (this.dirtyMatch) { // Need to recalculate the matches. this.dirtyMatch = false; @@ -360,16 +372,24 @@ var PDFFindController = { } this.updatePage(i, true); } + if (!firstMatch) { + this.updateUIState(FindStates.FIND_FOUND); + } else { + this.updateUIState(FindStates.FIND_NOTFOUND); + } } else { // If there is NO selection, then there is no match at all -> no sense to // handle previous/next action. - if (this.selected.pageIdx === -1) + if (this.selected.pageIdx === -1) { + this.updateUIState(FindStates.FIND_NOTFOUND); return; + } // Handle findAgain case. var previous = this.state.findPrevious; var sPageIdx = this.selected.pageIdx; var sMatchIdx = this.selected.matchIdx; + var findState = FindStates.FIND_FOUND; if (previous) { // Select previous match. @@ -393,6 +413,9 @@ var PDFFindController = { // If pageIdx stayed the same, select last match on the page. if (this.selected.pageIdx === sPageIdx) { this.selected.matchIdx = pageMatches[sPageIdx].length - 1; + findState = FindStates.FIND_WRAPPED; + } else if (this.selected.pageIdx > sPageIdx) { + findState = FindStates.FIND_WRAPPED; } } } else { @@ -411,18 +434,28 @@ var PDFFindController = { break; } } - // If pageIdx stayed the same, select last match on the page. + + // If pageIdx stayed the same, select first match on the page. if (this.selected.pageIdx === sPageIdx) { this.selected.matchIdx = 0; + findState = FindStates.FIND_WRAPPED; + } else if (this.selected.pageIdx < sPageIdx) { + findState = FindStates.FIND_WRAPPED; } } } + this.updateUIState(findState, previous); this.updatePage(sPageIdx, sPageIdx === this.selected.pageIdx); if (sPageIdx !== this.selected.pageIdx) { this.updatePage(this.selected.pageIdx, true); } } + }, + + updateUIState: function(state, previous) { + // TODO: Update the firefox find bar or update the html findbar. + PDFFindBar.updateUIState(state, previous); } }; @@ -432,18 +465,13 @@ var PDFFindBar = { opened: false, - FIND_FOUND: 0, // Successful find - FIND_NOTFOUND: 1, // Unsuccessful find - FIND_WRAPPED: 2, // Successful find, but wrapped around - initialize: function() { this.bar = document.getElementById('findbar'); this.toggleButton = document.getElementById('viewFind'); this.findField = document.getElementById('findInput'); this.highlightAll = document.getElementById('findHighlightAll'); this.caseSensitive = document.getElementById('findMatchCase'); - this.findMsgWrap = document.getElementById('findMsgWrap'); - this.findMsgNotFound = document.getElementById('findMsgNotFound'); + this.findMsg = document.getElementById('findMsg'); var self = this; this.toggleButton.addEventListener('click', function() { @@ -485,36 +513,38 @@ var PDFFindBar = { return window.dispatchEvent(event); }, - updateUIState: function(aState) { + updateUIState: function(state, previous) { var notFound = false; - var wrapped = false; + var findMsg = ''; + var status = 'pending'; - switch (aState) { - case this.FIND_FOUND: + switch (state) { + case FindStates.FIND_FOUND: break; - case this.FIND_NOTFOUND: + case FindStates.FIND_NOTFOUND: + findMsg = mozL10n.get('find_not_found', null, 'Phrase not found'); notFound = true; break; - case this.FIND_WRAPPED: - wrapped = true; + case FindStates.FIND_WRAPPED: + if (previous) { + findMsg = mozL10n.get('find_wrapped_to_bottom', null, + 'Reached end of page, continued from bottom'); + } else { + findMsg = mozL10n.get('find_wrapped_to_top', null, + 'Reached end of page, continued from top'); + } break; } if (notFound) { this.findField.classList.add('notFound'); - this.findMsgNotFound.classList.remove('hidden'); } else { this.findField.classList.remove('notFound'); - this.findMsgNotFound.classList.add('hidden'); } - if (wrapped) { - this.findMsgWrap.classList.remove('hidden'); - } else { - this.findMsgWrap.classList.add('hidden'); - } + this.findMsg.textContent = findMsg; }, open: function() { @@ -2316,7 +2346,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv, pageIdx) { if (highlightAll) { i0 = 0; i1 = matches.length; - } else if(!isSelectedPage) { + } else if (!isSelectedPage) { // Not highlighting all and this isn't the selected page, so do nothing. return; } From 53672af0f79c64a88eb4280063e9df7e55f7144a Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Fri, 28 Sep 2012 11:43:22 -0700 Subject: [PATCH 12/17] Fix un-highlight when there is no query. --- web/viewer.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index 759133127..4381e6c2f 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -343,10 +343,6 @@ var PDFFindController = { this.active = true; - if (!this.state.query) { - this.updateUIState(FindStates.FIND_FOUND); - return; - } this.updateUIState(FindStates.FIND_PENDING); if (this.dirtyMatch) { @@ -372,7 +368,7 @@ var PDFFindController = { } this.updatePage(i, true); } - if (!firstMatch) { + if (!firstMatch || !this.state.query) { this.updateUIState(FindStates.FIND_FOUND); } else { this.updateUIState(FindStates.FIND_NOTFOUND); From dd0cb37f38d4ebb22f16198f4051fc29cea33452 Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Fri, 28 Sep 2012 12:30:07 -0700 Subject: [PATCH 13/17] Add some door hanger styling for the find bar --- web/viewer.css | 37 +++++++++++++++++++++++++++++++------ web/viewer.html | 14 +++++++------- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/web/viewer.css b/web/viewer.css index 95b4dc5ab..30877a6d6 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -267,17 +267,15 @@ html[dir='rtl'] #sidebarContent { } .findbar { - top: 40px; - left: 40px; + top: 32px; + left: 68px; position: absolute; - z-index: 100; + z-index: 10000; height: 20px; min-width: 16px; padding: 3px 6px 3px 6px; margin: 4px 2px 4px 0; - border: 1px solid transparent; - border-radius: 2px; color: hsl(0,0%,85%); font-size: 12px; line-height: 14px; @@ -290,6 +288,33 @@ html[dir='rtl'] #sidebarContent { -moz-user-select:none; } +.doorHanger { + border: 1px solid hsla(0,0%,0%,.5); + border-radius: 2px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); +} +.doorHanger:after, .doorHanger:before { + bottom: 100%; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} +.doorHanger:after { + border-bottom-color: hsla(0,0%,32%,.99); + border-width: 8px; + left: 16px; + margin-left: -8px; +} +.doorHanger:before { + border-bottom-color: hsla(0,0%,0%,.5); + border-width: 9px; + left: 16px; + margin-left: -9px; +} + #findMsg { font-style: italic; color: #A6B7D0; @@ -1317,7 +1342,7 @@ canvas { } @media all and (max-width: 600px) { - #toolbarViewerRight { + #toolbarViewerRight, #findbar, #viewFind { display: none; } } diff --git a/web/viewer.html b/web/viewer.html index 73c4cb87a..e59120471 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -88,11 +88,6 @@ limitations under the License. <button id="viewOutline" class="toolbarButton group" title="Show Document Outline" tabindex="2" data-l10n-id="outline"> <span data-l10n-id="outline_label">Document Outline</span> </button> -<!--#if !MOZCENTRAL--> - <button id="viewFind" class="toolbarButton group" title="Find in Document" tabindex="3" data-l10n-id="find_panel"> - <span data-l10n-id="find_panel_label">Find in Document</span> - </button> -<!--#endif--> </div> <div id="sidebarContent"> <div id="thumbnailView"> @@ -103,7 +98,7 @@ limitations under the License. </div> <!-- sidebarContainer --> <div id="mainContainer"> - <div class="findbar hidden" id="findbar"> + <div class="findbar hidden doorHanger" id="findbar"> <label for="findInput">Find: </label> <input id="findInput" type="search"> <button id="findPrevious"><</button> @@ -118,10 +113,15 @@ limitations under the License. <div id="toolbarContainer"> <div id="toolbarViewer"> <div id="toolbarViewerLeft"> - <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="4" data-l10n-id="toggle_slider"> + <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="3" data-l10n-id="toggle_slider"> <span data-l10n-id="toggle_slider_label">Toggle Sidebar</span> </button> <div class="toolbarButtonSpacer"></div> +<!--#if !MOZCENTRAL--> + <button id="viewFind" class="toolbarButton group" title="Find in Document" tabindex="4" data-l10n-id="find_panel"> + <span data-l10n-id="find_panel_label">Find in Document</span> + </button> +<!--#endif--> <div class="splitToolbarButton"> <button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="5" data-l10n-id="previous"> <span data-l10n-id="previous_label">Previous</span> From 3bd20a7415d7ae99c969bb66eae0a2090ead6ee1 Mon Sep 17 00:00:00 2001 From: Artur Adib <arturadib@gmail.com> Date: Tue, 2 Oct 2012 16:19:51 -0400 Subject: [PATCH 14/17] bug fix: textLayer ready still needs scroll --- web/viewer.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index 4381e6c2f..467f9515d 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -323,14 +323,16 @@ var PDFFindController = { updatePage: function(idx) { var page = PDFView.pages[idx]; - if (page.textLayer) { - page.textLayer.updateMatches(); - } else if (this.selected.pageIdx === idx) { + if (this.selected.pageIdx === idx) { // If the page is selected, scroll the page into view, which triggers // rendering the page, which adds the textLayer. Once the textLayer is // build, it will scroll onto the selected match. page.scrollIntoView(); } + + if (page.textLayer) { + page.textLayer.updateMatches(); + } }, performFind: function() { From 45fe76e752dc6042f0f6e3df346ccb8deaf3c36b Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Tue, 2 Oct 2012 15:59:57 -0700 Subject: [PATCH 15/17] Add support for enter/shift for find. --- web/viewer.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/web/viewer.js b/web/viewer.js index 467f9515d..7933e5393 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -480,9 +480,17 @@ var PDFFindBar = { self.dispatchEvent(''); }); - // TODO: Add keybindings like enter, shift-enter, CMD-G etc. to go to prev/ + // TODO: Add keybindings CMD-G etc. to go to prev/ // next match when the findField is selected. + this.findField.addEventListener('keydown', function(evt) { + switch (evt.keyCode) { + case 13: // Enter + self.dispatchEvent('again', evt.shiftKey); + break; + } + }); + document.getElementById('findPrevious').addEventListener('click', function() { self.dispatchEvent('again', true); } ); From 1f85b8b4ed79bedd6d5aeb641889772107878e89 Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Tue, 2 Oct 2012 17:08:47 -0700 Subject: [PATCH 16/17] Update the l10n for the html find bar. --- l10n/en-US/viewer.properties | 12 ++++++++---- web/viewer.html | 14 +++++++------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/l10n/en-US/viewer.properties b/l10n/en-US/viewer.properties index 678e23c8e..8e0ca9879 100644 --- a/l10n/en-US/viewer.properties +++ b/l10n/en-US/viewer.properties @@ -36,8 +36,6 @@ outline.title=Show Document Outline outline_label=Document Outline thumbs.title=Show Thumbnails thumbs_label=Thumbnails -find_panel.title=Find in Document -find_panel_label=Find # Document outline messages no_outline=No Outline Available @@ -55,8 +53,14 @@ page_rotate_cw.label=Rotate Clockwise page_rotate_ccw.label=Rotate Counter-Clockwise # Find panel button title and messages -find=Find -find_terms_not_found=(Not found) +find.title=Find in Document +find_label=Find +find_previous.title=Find the previous occurrence of the phrase +find_next.title=Find the next occurrence of the phrase +find_highlight=Highlight all +find_match_case_label=Match case +find_wrapped_to_bottom=Reached end of page, continued from bottom +find_wrapped_to_top=Reached end of page, continued from top # Error panel labels error_more_info=More Information diff --git a/web/viewer.html b/web/viewer.html index e59120471..7af1d919b 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -99,14 +99,14 @@ limitations under the License. <div id="mainContainer"> <div class="findbar hidden doorHanger" id="findbar"> - <label for="findInput">Find: </label> + <label for="findInput" data-l10n-id="find_label">Find</label>: <input id="findInput" type="search"> - <button id="findPrevious"><</button> - <button id="findNext">></button> + <button id="findPrevious" data-l10n-id="find_previous" title=""><</button> + <button id="findNext" data-l10n-id="find_next">></button> <input type="checkbox" id="findHighlightAll"> - <label for="findHighlightAll">Highlight all</label> + <label for="findHighlightAll" data-l10n-id="find_highlight">Highlight all</label> <input type="checkbox" id="findMatchCase"> - <label for="findMatchCase">Match case</label> + <label for="findMatchCase" data-l10n-id="find_match_case_label">Match case</label> <span id="findMsg"></span> </div> <div class="toolbar"> @@ -118,8 +118,8 @@ limitations under the License. </button> <div class="toolbarButtonSpacer"></div> <!--#if !MOZCENTRAL--> - <button id="viewFind" class="toolbarButton group" title="Find in Document" tabindex="4" data-l10n-id="find_panel"> - <span data-l10n-id="find_panel_label">Find in Document</span> + <button id="viewFind" class="toolbarButton group" title="Find in Document" tabindex="4" data-l10n-id="find"> + <span data-l10n-id="find_label">Find</span> </button> <!--#endif--> <div class="splitToolbarButton"> From 5d848ca31a726bc5cf5fd6a09039001ab070f660 Mon Sep 17 00:00:00 2001 From: Brendan Dahl <brendan.dahl@gmail.com> Date: Thu, 4 Oct 2012 13:44:17 -0700 Subject: [PATCH 17/17] Ignore find key shortcut only for mozcentral for now. --- web/viewer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/viewer.js b/web/viewer.js index 7933e5393..2fb9c90a6 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -2799,7 +2799,7 @@ window.addEventListener('keydown', function keydown(evt) { // control is selected or not. if (cmd == 1 || cmd == 8) { // either CTRL or META key. switch (evt.keyCode) { -//#if !(FIREFOX || MOZCENTRAL) +//#if !MOZCENTRAL case 70: PDFFindBar.toggle(); handled = true;