Loading web content

You can use WebView to load web content from the Internet in your app. Here's an overview of the classes that you need.


Diagram showing the WebView classes and their relationship.

To use the WebView APIs in your apps, you must add the access_internet permission to your bar-descriptor.xml file. To learn more about the bar-descriptor.xml file, see The bar-descriptor.xml file.

Loading a webpage

You can use WebView to load a webpage from the Internet. For example, you can build a simple search function that navigates to a search engine in a webpage. Here's how to load a webpage from the Internet in QML by adding a WebView to a container in your app. If you want to try this, create a new Cascades project using the Standard empty project template and replace the container in main.qml with the following code sample:

Container {
   WebView {
       id: webView
       url: "<search_engine_URL>"
   }
}

You can do the same thing in C++:

QWebView *view = new QWebView(parent);
view->load(url("<search_engine_URL>"));
view->show();

In the code sample above, the WebView isn't in a scrollable container, so the webpage displayed in your app is restricted by the size of your container. WebView itself doesn't have a size. If a WebView is added to a Container, it adapts to the size of the web content loaded. The exact layout of the WebView can be customized using properties of the container. For more information, see Layouts. To make the WebView more useful, you can use ScrollView to let the user scroll forward and backward on a webpage.

Here's a code sample that adds a WebView to a ScrollView within a container.

import bb.cascades 1.0

Page {
    ScrollView {
        Container {
            background: Color.create ("#f8f8f8")
            layout: StackLayout {
                orientation: LayoutOrientation.TopToBottom
            }
            WebView {
                url: "<search_engine_URL>"
            }
        }
    }
}

If you create this UI in a simple NavigationPane with a TextField for input and a Button, you can build a simple search function into your app. You can build this with two basic files: the main.qml file, which contains the UI for a search button in your container, and the search.qml file, which creates the searching function using a WebView and a search engine. This example uses Google but you can use any search engine. Here's how you can create the UI for the search button in main.qml:

import bb.cascades 1.0

NavigationPane {
    id: myNavPane
    Page {
        Container {
            layout: StackLayout {
                orientation: LayoutOrientation.LeftToRight
            }
            TextField {
                id: mySearchTerm
            }
            Button {
                id: myButton
                text: "Search"

                onClicked: {
                    var page = pageDefinition.createObject();
                    myNavPane.push(page);
                }

                attachedObjects: ComponentDefinition {
                    id: pageDefinition
                    source: "mysearch.qml"
                } // end attachedObjects
            } // end Button
        } // end Container
    } // end Page
} // end NavigationPane

In the mysearch.qml file, you can use WebView to display a web search with the text that the user enters in the TextField that was part of the UI created in main.qml. Here's a code sample that demonstrates how you can do this:

import bb.cascades 1.0

Page {
    ScrollView {
        Container {
            background: Color.create ("#f8f8f8")
            layout: StackLayout {
               orientation: LayoutOrientation.TopToBottom
            }

            WebView {
                 url: "http://www.google.com/search?q=" + mySearchTerm.text
            } // end WebView

        } // end container
    } // end Scrollview
} // end page

Scaling a webpage

Each WebView object has an associated WebSettings object that you can use to improve the readability of your WebView. You can set font sizes, adjust zoom settings, or scale content using a ratio between device pixels (or physical pixels) and device-independent pixels (or CSS pixels). CSS pixels are not the same as device pixels. CSS pixels expand and contract with zooming, and the ratio of device pixels to CSS pixels depends on the scale factor used to display the web content on the device's screen. CSS pixels equal device pixels when content is scaled to 100%.

Some best practices for displaying web content in a WebView are described below.

Consider font sizes

You can set font sizes using the defaultFontSize, minimumFontSize, and defaultFontSizeFollowsSystemFontSize properties. The default font size that a WebView uses is 16 CSS pixels and the default minimum font size is 8 CSS pixels.

If you set the defaultFontSizeFollowsSystemFontSize property to true, the defaultFontSize is ignored and the default system font size is used. You can set the defaultFontSizeFollowsSystemFontSize to true, combined with relative font sizes in your content, to make an accessible WebView whose text scales with the system font size when it changes.

For more information about setting and querying font properties in WebView, see the API Reference.

Use default settings

If you don't set any properties to adjust the scaling of your WebView, your web content fills the device screen so that you can see all of the content on one page. By default, the zoomToFitEnabled property ensures that your content fills the WebView on the screen when it is loaded.

Here's a simple code sample that contains a WebView. The image to the right illustrates how the corresponding content appears on the device.

WebView {
    id: webView
    url: "http://developer.blackberry.com"
}
Screen showing a WebView with no scaling properties set.

In the example above, no viewport is specified and the defaultFontSizeFollowsSystemFontSize property defaults to false. This means that the webpage starts out with an appropriate scale for the BlackBerry 10 device screen. These defaults also indicate that the default font size does not change when the user changes their font size settings.

There are two approaches to scaling your web content if the default settings don't display your web content appropriately.

  • You can use a devicePixelRatio of 1.0 and tailor your web content to fit the standard screen width of BlackBerry 10 devices. Typically, this setting is used when the web content is created specifically for BlackBerry 10 devices.

  • You can use the default devicePixelRatio and use a viewport value of "initial-scale: 1.0" for web content that it is designed to be compatible with a wide range of mobile devices. Typically, this setting is used when the web content is an existing mobile webpage.

As a best practice, you should determine the display dimensions of the device that you are running your app on. Then, you can create a UI layout that adapts to different screen sizes and resolutions. For more information about designing your app for different screen resolutions, see Resolution independence.

Use a device pixel ratio of 1.0

You can use the devicePixelRatio to adjust the web content in your WebView. Increasing devicePixelRatio zooms in the content and decreasing it zooms out the content.

Here's a simple code sample that demonstrates a device pixel ratio of 1.0. in a WebView. The image to the right illustrates how the corresponding content appears on the device

WebView {
    id: webView
    url: "http://developer.blackberry.com"
    settings.devicePixelRatio: 1.0
}
Screen showing a WebView with a pixel ratio of 1.0.

If you set the device pixel ratio to 1.0, your web content should be designed to fit the width of a BlackBerry 10 device in portrait orientation (720 CSS pixels), but it should make use of extra space if it is available.

In the example above, the devicePixelRatio setting indicates that one CSS pixel is equal to one device pixel. This setting is useful for web content tailored to BlackBerry 10 devices, since having one CSS pixel equal one device pixel can simplify the design process.

Here's a code sample that demonstrates setting the pixel ratio to reduce the size of the web content in a WebView.

WebView {
    id: webView
    url: "http://developer.blackberry.com"
    settings.devicePixelRatio: 0.5
}

You'll notice that the WebView still fills the device screen, but the web content has been scaled to half of its original size. This example, and the effect it has on the output, is shown here for demonstration only. In this example, the web content is not readable. You would not display this type of web content using this pixel ratio.

Screen showing a WebView with device pixel ratio 0.5.

Use the default device pixel ratio and the viewport property

You can use the viewport property to scale the content of your WebView so that it fills the width of the device and is zoomed in for readability.

Here's a code sample that contains a WebView that sets the viewport property. The image to the right illustrates how the corresponding content appears on the device.

WebView {
    id: webView
    url: "http://developer.blackberry.com"
    settings.viewport: {
        "initial-scale": 1.0
    }
}

The code sample above uses the default devicePixelRatio. This default value depends on which BlackBerry 10 device you are running your app on. Your web content should set the viewport property to "initial-scale=1.0".

Screen showing a WebView with viewport scaling properties set.

Since this strategy is used when the web content is designed to be compatible with a wide range of mobile devices, it should be designed to fit in a width of 320 CSS pixels, but make use of extra space if it is available.

With the default device pixel ratio setting, one CSS pixel typically equals two or more device pixels and the exact value can be a fraction. For example, on BlackBerry 10 devices with a 768 x 1280 pixel screen, the default devicePixelRatio is 2.243750.

The key-value pair, "initial-scale: 1.0", scales the content in for readability. The initial-scale value controls the zoom level when the page is first loaded. You can also use maximum-scaleminimum-scale, and user-scalable values to control how users are allowed to zoom on the page. For more details about how to allow users to zoom on a webpage, see Adding gesture handling to your WebView.

Monitoring webpage progress

WebView signals are emitted when anything related to your webpage changes. When you display a webpage in your app, you can use signals to monitor the progress of your webpage loading or determine when the user navigates away from the initial webpage using a link. For more information about handling signals, see Signals and slots.

You can use the loadingChanged() signal and the WebLoadRequest to determine the status of a webpage load request. Here's a code sample that demonstrates how to do this:

Label {
  id: statusLabel
  leftMargin: 10
  text: "No webpage yet."
} 
WebView {
  id: myWebView
  url: "http://developer.blackberry.com"

  onLoadingChanged: {
    if (loadRequest.status ==  WebLoadStatus.Started ) {
       statusLabel.setText("Load started.")
    }
    else if (loadRequest.status ==  WebLoadStatus.Succeeded ) {
       statusLabel.setText("Load finished.")
    }
       else if (loadRequest.status ==  WebLoadStatus.Failed ) {
          statusLabel.setText("Load failed.")
       }
    }
}

Handling navigation on a webpage

You can use the navigationRequested() signal and the WebNavigationRequest properties to handle user interaction and navigation on a webpage that you displayed using WebView. The navigationRequested() signal is emitted when the user tries to navigate to a new URL from the WebView that's displayed in your app. Here's a code sample that shows you how to do that:

WebView {
  id: myWebView
  url: "http://developer.blackberry.com"

  onNavigationRequested: {
     console.log ("\t - onNavigationRequested " + request.url + 
                   " navigationType=" + request.navigationType);
  } 
}

You can restrict whether the user has permission to change the URL of the content in a WebView. When the URL of the webpage is changed, the navigationRequested signal is emitted. You can use the WebNavigationRequest to determine what type of navigation was requested by the user and the URL that the user wants to navigate to. You can reject the navigation by changing the action property of the  WebNavigationRequest or by calling WebNavigationRequest::ignore().  Here's a code sample that shows you how to do this:

WebView {
  id: myWebView
  url: "http://developer.blackberry.com"

  onNavigationRequested: {
     console.log("NavigationRequested: " + request.url + 
               " navigationType=" + request.navigationType)

     if (!shouldAcceptNavigationToUrl(request.url)) {
         request.action = WebNavigationRequestAction.Ignore 
     }
  }
}

Navigation requests are accepted by default, and the new URL will be loaded in the WebView in your app. If you want navigation requests to open in a new tab or window, your app must reject the navigation request and open the requested URL in a new WebView. Navigation requests are delegated to your app so that your app can accept or ignore the navigation. If a user navigates to a webpage that involves HTTP redirects, several navigation requests will be made for each URL involved. Your app can obtain the target of a redirect, and accept or ignore each navigation request that the user makes.

WebView is not intended to be a full browser for viewing web content. WebView has a simple webpage history mechanism. You can track the user's navigation history internally. You can use the canGoBack() property and the goBack() function, which you can call to navigate through the user's previous requests. Here's a code sample that shows you how to do this:

import bb.cascades 1.0

Page {
    content: Container {
        background: Color.create(0.25, 0.25, 0.25)
        
        // Set up a container with three basic buttons
        // for tabbing through webpage history.
        Container {
            layout: StackLayout {
                orientation: LayoutOrientation.LeftToRight
            }
            Button {
                id: backButton
                text: "Back"
                onClicked: {
                    myWebView.goBack();
                }
            }
            Button {
                id: forwardButton
                text: "Forward"
                onClicked: {
                    myWebView.goForward();
                }
            }
            Button {
                id: refreshButton
                text: "Refresh"
                onClicked: {
                    myWebView.reload();
                }
            }
        }

        // Now set up a container and a ScrollView to
        // display a webpage in a WebView. 
        Container {
            ScrollView {
                scrollViewProperties.pinchToZoomEnabled: true
                scrollViewProperties.scrollMode: ScrollMode.Both
                WebView {
                    id: myWebView
                    url: "http://<mySiteURL>/"
                }
            }
        }
    }
}

If you need to view web content in a full browser, you can use the invocation framework to invoke the BlackBerry Browser. For more information about invoking BlackBerry Browser, see App integration.

Searching for text on a webpage

To help the user find text on a webpage, you can use the findText() function. By default, each occurrence of the text that the user wants to find is highlighted from the top of the page to the bottom. When the search reaches the bottom of the webpage, it wraps and continues at the top of the webpage. By default, searches are not case-sensitive.

You can use the WebFindFlag class to specify whether a webpage is searched from top to bottom (by default) or from bottom to top, whether the search is case-sensitive, whether it wraps around, or whether all occurrences of the search term is highlighted on the webpage or whether each term found on the page is highlighted sequentially.

Here's a code sample that adds a TextField and a Button to a Container. The Container also includes a scrolling WebView that contains content from the Internet.

Screen showing a simple function to find text on a WebView.
import bb.cascades 1.0

Page {
    Container {
        id: container 
        background: Color.LightGray
        layout: StackLayout { orientation: LayoutOrientation.TopToBottom }

        Container {
          layout: StackLayout {orientation: LayoutOrientation.LeftToRight }
          TextField {
            id: jsField
            layoutProperties: StackLayoutProperties { spaceQuota: 1.0 }
            objectName: "jsField"
            hinttext: "Search for ..."
            } // text field

          Button {
            id: findButton
            preferredWidth: 100
            text: "Find on page"
            onClicked: {
                webView.findText(jsField.text)
                } 
            } // button
        } // top container
    
        ScrollView {
            scrollViewProperties {
                scrollMode: ScrollMode.Both
            }
            layoutProperties: StackLayoutProperties { spaceQuota: 1.0 }

            Container {
               background: Color.LightGray
               layout: StackLayout { orientation: LayoutOrientation.TopToBottom }

               WebView {
                 id: webView
                 url: "http://developer.blackberry.com/"
                 } // webview
             } // container        
         } // scrollview
     } // container
} // page

Last modified: 2014-01-23

comments powered by Disqus