ginebra2/chrome/bedrockchrome/suggests.snippet/suggests.js
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 23 Jun 2010 17:59:43 +0300
changeset 5 0f2326c2a325
parent 0 1450b09d0cfd
child 6 1c3b8676e58c
permissions -rw-r--r--
Revision: 201024 Kit: 2010125

/*!
  \file suggests.js This module contains the Suggests class.
*/

/*!
  Class to handle displaying URL suggestions from history and bookmarks.
*/
function Suggests()
{
    // "Private" member variables
    var suggestsXOffset = 20;
    var inputTimeoutId = null;
    var inputTimeoutDelay = _getTimeoutDelaySetting();
    var maxHeight = 0; // maximum height of suggest list
    var urlSearchHeight = 0;

    // "Private" methods

    //! 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);

        // 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
    }

    //! 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_url_bar_drop_down_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/, "<b>" + input + "</b>");

        suggestLI.innerHTML = '<a href="#" onclick="searchSuggests.searchUrlValue(\''+input+'\');'+
            'return false;">'+
            '<div class="SuggestElement">'+'<span class="aTitle">'+recenttitle+'</span>'+'</div></a>';
        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, "<b>$&</b>");
            recenturl = recenturl.replace(pattern, "<b>$&</b>");

            suggestLI.innerHTML = '<a href="#" onclick="searchSuggests.gotoUrl(\''+suggests[i].url+'\');' +
                ' return false;">'+
                '<div class="SuggestElement">'+
                '<span class="aTitle">'+recenttitle+'</span><br/>'+
                '<span class="aUrl">'+recenturl+'</span></div></a>';
            suggestUL.appendChild(suggestLI);
        }

        snippetId.appendChild(suggestUL);
    }

    //! 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));
    }

    //! 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);
    }

    //! 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 == "QGraphicsSceneMousePressEvent") {
            _hideSuggests();
        }
    }

    //! 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
        }
    }

    //! Sets the user input URL suggest delay.
    /*!
      \param to the new delay time.
    */
    this.setSuggestTimeout = function(to)
    {
        inputTimeoutDelay = to;
    }
}

// we don't have access to WRT::LoadController::GotoModeEditing
Suggests.GotoModeEditing = 1;