diff -r b0dd75e285d2 -r 0954f5dd2cd0 ginebra2/chrome/bedrockchrome/suggests.snippet/suggests.js --- a/ginebra2/chrome/bedrockchrome/suggests.snippet/suggests.js Fri May 14 15:40:36 2010 +0300 +++ b/ginebra2/chrome/bedrockchrome/suggests.snippet/suggests.js Tue Jun 29 00:46:29 2010 -0400 @@ -1,69 +1,263 @@ +/*! + \file suggests.js This module contains the Suggests class. +*/ + +/*! + Class to handle displaying URL suggestions from history and bookmarks. +*/ function Suggests() { - // attach internal funcs - this.write = writeSuggests; + // "Private" member variables + var suggestsXOffset = 20; + var inputTimeoutId = null; + var inputTimeoutDelay = _getTimeoutDelaySetting(); + var maxHeight = 0; // maximum height of suggest list + var urlSearchHeight = 0; - // do setup - this.write(); + // "Private" methods - this.showSuggests = function() { - window.chrome.alert("showSuggests"); - //window.snippets.updateGeometry(); - window.snippets.SuggestsId.repaint(); + //! Calculates the maximum height for the suggest list. + //! If not all suggest items can fit in list, only half an item should be + //! visible the end when scrolled to the top. This is to indicate more items. + function _setMaxHeight() + { + // Calculate height of available space for suggest list. + var statusbarSz = snippets.StatusBarChromeId.getGeometry(); + var urlSearchSz = snippets.UrlSearchChromeId.getGeometry(); + var toolbarSz = snippets.WebViewToolbarId.getGeometry(); + // leave some space between suggest and toolbar (~10% of display height) + var bufferHeight = Math.ceil(chrome.displaySize.height / 10); + var availableHeight = chrome.displaySize.height - + (statusbarSz.height + urlSearchSz.height + toolbarSz.height + bufferHeight); + // Calculate number of elements that can fit in available space. + var elementHeight = 70; // set in suggests.css + var numElements = Math.floor(availableHeight / elementHeight); - var curPos = window.snippets.SuggestsId.getPosition(); - window.chrome.alert(curPos.x); - if (curPos.y == 0) - window.snippets.SuggestsId.setPosition(5,68); - window.snippets.SuggestsId.show(); - window.snippets.SuggestsId.zValue = 10; + // in order to make room for 1/2 entry at end of list we may + // need to sacrifice 1 full element. + if ((availableHeight % elementHeight) < (elementHeight / 2)) { + numElements -= 1; + } + numElements += 0.5; // half of final visible entry + // max suggest list height in pixels + maxHeight = Math.floor(numElements * elementHeight); + } + + //! Temporary substitute for settings function to get the delay for + //! displaying the URL suggests list. + function _getTimeoutDelaySetting() + { + // no setting stored for this currently + return (1000); // 1 second } - this.hideSuggests = function() { - window.snippets.SuggestsId.hide(); + //! Displays and updates suggest list. + function _showSuggests() + { + // make sure the input is the latest + var input = window.snippets.UrlSearchChromeId.url; + + // only display suggestions if there is input + if (input.length != 0) { + _updateSuggestList(input); + this.updateSuggestsSize(); + + if (!snippets.SuggestsChromeId.visible + && (pageController.loadState == Suggests.GotoModeEditing)) { + window.scrollTo(0, 0); + // Disable the content view, leave the URL serach bar and status bar enabled. + views.WebView.enabled = false; + views.WebView.freeze(); + snippets.SuggestsChromeId.show(false); + } + } else { + // no user input so hide suggestions + _hideSuggests(); + } + } + + //! Updates the suggestion list based on the specified input. + /*! + \param input the current URL box text + */ + function _updateSuggestList(input) + { + var recenturl; + var recenttitle = window.localeDelegate.translateText( + "txt_browser_chrome_suggests_search_for"); + var snippetId = document.getElementById('SuggestsId'); + var suggests = window.pageController.fetchSuggestions(input); + var suggestUL = document.createElement('ul'); + var suggestLI = document.createElement('li'); + var pattern = new RegExp(input, "ig"); + + snippetId.innerHTML = ""; // clear previous results + suggestUL.id = 'suggestUlId'; + suggestLI.id = "searchLiId"; + + // always provide an option to search for user entry + recenttitle = recenttitle.replace(/%1/, "" + input + ""); + + suggestLI.innerHTML = ''+ + '
'+''+recenttitle+''+'
'; + suggestUL.appendChild(suggestLI); + + // add each search suggestion to unordered list + for (i=0; i < suggests.length; i++) { + recenturl = suggests[i].url; + recenttitle = suggests[i].title; + suggestLI = document.createElement('li'); + suggestLI.id = "suggestsLiId"; + + // bold search text + recenttitle = recenttitle.replace(pattern, "$&"); + recenturl = recenturl.replace(pattern, "$&"); + + suggestLI.innerHTML = ''+ + '
'+ + ''+recenttitle+'
'+ + ''+recenturl+'
'; + suggestUL.appendChild(suggestLI); + } + + snippetId.appendChild(suggestUL); } - this.setWidth = function(width) { - document.getElementById("SuggestsId").style.width = width; - //window.chrome.alert("set width:" + document.getElementById("SuggestsId").offsetWidth); + //! Hides suggests list and support items. + function _hideSuggests() + { + clearTimeout(inputTimeoutId); + window.snippets.SuggestsChromeId.hide(false); + views.WebView.enabled = true; + views.WebView.unfreeze(); + } + + // Public Functions + + //! Handler for onload javascript event. + this.loadComplete = function() + { + var urlSearchSz = snippets.UrlSearchChromeId.getGeometry(); + + urlSearchHeight = urlSearchSz.height; + snippets.SuggestsChromeId.anchorTo("UrlSearchChromeId", suggestsXOffset, urlSearchHeight); + snippets.SuggestsChromeId.zValue = 10; + + _setMaxHeight(); // calculate max suggest list height + + // hide suggests on external mouse events + snippets.SuggestsChromeId.externalMouseEvent.connect(this.handleExternalMouseEvent); + // need to resize suggest page snippet on geometry change + chrome.prepareForGeometryChange.connect(createDelegate(this, this.handleGeometryChange)); } - this.setHeight = function(height) { - document.getElementById("SuggestsId").style.height = height; - //window.chrome.alert("set height:" + document.getElementById("SuggestsId").offsetHeight); + //! Updates the size of the suggests window depending on the size of the + //! main DIV -- which changes as the number of items changes. + this.updateSuggestsSize = function() + { + if (snippets.SuggestsChromeId != undefined) { + var totalW = chrome.displaySize.width; + var divHeight = document.getElementById("SuggestsId").clientHeight + 2; + var displayHeight = Math.min(maxHeight, divHeight); + var displayWidth = totalW - (2 * suggestsXOffset); + + // reset snippet height + snippets.SuggestsChromeId.setSize(displayWidth, displayHeight); + } + } + + //! Handles the geometry change signal. Need to re-calculate max height + //! and then update suggest page height. + this.handleGeometryChange = function() + { + _setMaxHeight(); // max height is based on display height + this.updateSuggestsSize(); + } + + //! Loads google search page for search string. + /*! + \param input value to search for + */ + this.searchUrlValue = function(input) + { + var searchurl = window.pageController.searchUrl(input); + + _hideSuggests(); + + window.pageController.currentLoad(searchurl); + window.pageController.urlTextChanged(searchurl); } - this.removeAllItems = function() { - var parentList = document.getElementById("SuggestsUListId"); - while (parentList.childNodes[0]) { - parentList.removeChild(parentList.childNodes[0]); + //! Hides suggests list and loads specified page. + /*! + \param url address of page to load + */ + this.gotoUrl = function(url) + { + _hideSuggests(); + url = window.pageController.guessUrlFromString(url); + window.pageController.currentLoad(url); + window.pageController.urlTextChanged(url); + } + + //! Handles external mouse events - dismisses suggests list. + /*! + \param type the type of event + \param name the name of event + \param description event description + */ + this.handleExternalMouseEvent = function(type, name, description) + { + if (name == "MouseClick") { + _hideSuggests(); } - this.setHeight(0); } - this.addItem = function(str) { - this.setHeight(document.getElementById("SuggestsId").offsetHeight + 26); // FIXME 26 is the row height - var parentList = document.getElementById("SuggestsUListId"); - var item = document.createElement("li"); - item.innerHTML = str; - item.onclick=function() { window.chrome.alert(item.innerHTML + " is selected."); window.snippets.SuggestsId.hide();} - item.onmouseover=function() { item.style.backgroundColor = 'Aquamarine'; } - item.onmouseout=function() { item.style.backgroundColor = ''; } - parentList.appendChild(item); + //! Updates the user input for suggestion list. + /*! + \param input the current user input + */ + this.updateUserInput = function() + { + // user still editing URL - don't show/update suggests yet + clearTimeout(inputTimeoutId); + inputTimeoutId = setTimeout(_showSuggests.bind(this), inputTimeoutDelay); + } + + //! Called when load state changes. Suggests should only be called when + //! the load state is editing. + this.updateLoadState = function() + { + if (pageController.loadState != Suggests.GotoModeEditing) { + // loading or reloadable - suggests not ok + _hideSuggests(); // ensure suggests are hidden + } + } + + //! Called when URL search bar looses focus. The external mouse event + //! handler deals with most cases where the suggestion list should be + //! dismissed but we don't get those events when the list isn't visible + //! so this handler is needed to cancel the timer in those cases. + this.urlSearchLostFocus = function() + { + // if visible user may be scrolling suggestion page so ignore focus change + if (!snippets.SuggestsChromeId.visible) { + // prevent suggestion list from being displayed until URL edited again + clearTimeout(inputTimeoutId); + } + } + + //! Sets the user input URL suggest delay. + /*! + \param to the new delay time. + */ + this.setSuggestTimeout = function(to) + { + inputTimeoutDelay = to; } } -// "Private" methods -function writeSuggests() { - var html = - '
' + - '
' + - '
' + - '
    ' + - '
' + - '
' + - '
' + - '
'; - document.write(html); -} - +// we don't have access to WRT::LoadController::GotoModeEditing +Suggests.GotoModeEditing = 1;