Connecting to third-party language reference sites

Introduction to embedding data from third-party sites

There are several ways to obtain data from a server run by a third-party, such as Google, the Wikimedia Foundation: iframe, AJAX request and helper tabs. Each has its own strengths and limitations.

iframe

You can use an <iframe> tag to display certain third-party web pages inside your own web page.

Strengths

  • The entire interactive web page from the third-party site is embedded in your page.

Limitations

  • Certain pages, like Google Translate are designed for display only in their own tab; attempting to embed such a page in an iframe will fail.
  • It's not possible to modify the CSS of a page displayed in an iframe. In particular, this means your page needs to adapt itself to the space requirements of the embedded page.
  • You need to be aware of the potential security concerns of allowing third-party pages to enter your own pages.
  • You must be sure not to infringe on intellectual property or trademark issues.

AJAX request

If the third-party server allows it, you may be able to make an AJAX call to retrieve raw HTML from the server, which you can then insert into the native HTML of your page.

Strengths

  • You can manipulate the HTML as you see fit, cherry-picking the parts you want and inserting them where you want in your page.
  • You can apply your own custom CSS to all the inserted HTML.

Limitations

  • When the user clicks on a link in the inserted HTML, your page may be replaced by a new page from the third-party server. You will need to intercept the clicks and convert them into custom AJAX calls.
  • Certain AJAX APIs, such as the Google Translate API are provided as pay-per-use services. If your web site is still at the development stage, you may prefer a cost-free solution.

Helper tab

You can open the source web page in its own tab, and then use the content script of your Chrome extension to query the page for the information you need, and transfer it to your own web page.

Strengths

  • You can retrieve just the information you want to show in your page.
  • You can format it in any way you want.
  • The user can consult the helper tab at any time, to see all the information provided by the source server.

Limitations

  • The structure of the third-party page may change without notice, so the query selectors that you use to retrieve the desired information may break at any time.

The simplest technique is to embed a third-party web page inside your own, using an <iframe> tag. In the next section, you'll see how to do this with pages from Wiktionary.org.

Using an iframe to embed a third-party page

This tutorial follows on from a tutorial on creating the prototype Annotations extension for Chrome. If you haven't just completed that tutorial, the best way to get started here will be to download the source files for the final section of that tutorial and work from there.

In this section, you will learn how to :
  • Modify the Meteor web pages used for the NoteBook window, so you don't can deliver it from an Apache server.
  • Create an <iframe> in your NoteBook page
  • Set the src attribute of the <iframe> element when you select a word on a page in your browser.
Download the source files

Un-Meteorizing the NoteBook

Because this tutorial does not rely on any of the features of Meteor, you can simplify the files in your Meteor client folder as shown below:

Meteor client/main.html

<!DOCTYPE html>
<html lang=en>
<head>
  <meta charset="utf-8">
  <title>NoteBook</title>
  <link rel="stylesheet" type="text/css" href="main.css">
</head>

<body>
  <p id="selection"></p>
  <iframe src="" id="wiktionary"></iframe>
  <script src="main.js"></script>
</body>
</html>

<!-- <head>
  <title>NoteBook</title>
</head> -->

<!-- <body>
  <p id="selection"></p>
  
  <table border="1">
    <tr>
      <th>Word</th>
      <th>Index</th>
      <th>Count/Billion</th>
    </tr>
      {{> rows}}
  </table>
</body> -->

<!-- TEMPLATES -->

<!-- <template name="rows">
  {{#each rows}}
    <tr>
      <td>{{word}}</td>
      <td>{{index}}</td>
      <td>{{count}}</td>
    </tr>
  {{/each}}
</template> -->

Meteor client/main.js

// import { Template } from 'meteor/templating'
// Template.rows.helpers({
//   rows: function rows() {
//     return Session.get("rows")
//   }
// })

// import { Session } from 'meteor/session'

// Session.set("rows", [])

// Meteor.startup(function() {
  
;(function startUpWithoutMeteor(){
  var  extensionId = "bjgdcgpomeengebjdjliaedpiboaildf"
  // Use your own extension id ^

  var connections = {
    port: null
  , p: document.getElementById("selection")
  , wiktionary: document.getElementById("wiktionary")
  , wikiURL: [
      "https://en.wiktionary.org/w/index.php?title="
    , "&printable=no"
    ]

  , initialize: function initialize() {
      this.port = chrome.runtime.connect(extensionId)
      this.port.onMessage.addListener(treatMessage)

      return this
    }

  , changeSelection: function changeSelection(request) {
      var selection = request.data
      this.p.innerHTML = selection
      // Meteor.call("analyzeText", {data: selection}, updateTable)

      // function updateTable(error, data) {
      //   if (error) {

      //   } else {
      //     Session.set("rows", data)
      //   }
      // }
      
      this.showInWikiTab(selection)
    }

  , showInWikiTab: function showInWikiTab(word) {
      var word = word.substr(0, word.indexOf(" ")) || word

      if (!word) {
        return
      }
      
      var url = this.wikiURL[0] + word + this.wikiURL[1]
      wiktionary.src = url
    }

  , getFrequencyData: function getFrequencyData(request) {
      // { method: "getFrequencyData"
      // , data: textContent
      // , id: <tab id where call originated> }
      // Meteor.call("getFrequencyData",request,treatFrequencyData)

      function treatFrequencyData(error, data) {
        if (error) {
          console.log("treatFrequencyData", error)

        } else {
          connections.port.postMessage({ 
            method: "treatFrequencyData"
          , data: data
          , id: request.id
          })
        }
      }
    }

  , disableExtension: function disableExtension() {
      if (this.port) {
        this.port.postMessage({ method: "disableExtension" })
        this.port = null
      }
    }
  }.initialize()

  // LISTENERS //LISTENERS //LISTENERS //LISTENERS //LISTENERS //

  function treatMessage(request) {
    var method = connections[request.method]
    if (typeof method === "function") {
      method.call(connections, request)
    }
  }

  function disableExtension() {
    treatMessage({ method: "disableExtension" })
  }

  window.onbeforeunload = disableExtension
})()// remove iife () when Meteor.startup() is restored

You'll also have to make a small change the background.js script of your extension, to make the new version of the client/main.html file open without using Meteor as the server.

background.js

"use strict"

;(function background(){

  var extension = {
    port: null
//, meteorURL: "http://localhost:3000/"
  , meteorURL: "http://localhost/NoteBook/main.html"
  // use your own local URL ^
  , injectedHTML: chrome.extension.getURL("html/inject.html")
  , injectedCSSFile: "css/inject.css"
  , tabMap: {}

  // code omitted for clarity
})()
This assumes that you know how to set up an Apache server on your development machine, and that you know how to edit the hosts and httpd.conf files to point the Apache server at the Meteor client folder. If that's not the case, then just don't comment out the lines of code in red above, and keep your Meteor server running.

The advantage of using Apache instead of Meteor is that you can more easily host your files online, and get your friends and colleagues to test your extension without running their own Meteor servers.

Adding CSS for the iframe

By default, the dimensions of the iframe will be set to something like 300 x 150 pixels, which is not nearly big enough to show the contents of the Wiktionary page. You can fix this by adding the following rule to your main.css file:

Meteor mais.css

p#selection {
  min-height: 2em;
  width: 100%;
  background-color: #ddd;
  border: 1px solid #ccc;
  border-bottom-color: #eee;
  border-right-color: #eee;
}

table {
  border: 1px solid #000;
  border-collapse: collapse;
  min-width: 200px;
  width: 100%;
}
th {
  background-color: #ccc;
  padding: 0.1em 0.25em;
}
td {
  padding: 0 0.25em;
}
td {
  text-align: right;
}
td:first-child {
  text-align: left;
}

iframe#wiktionary {
  width: 888px;
  height: 555px;
}

Setting the src for the iframe

The edited main.html file now includes an <iframe> tag with an id of #wiktionary. The changeSelection method in the main.js script now calls a showInWikiTab method, which creates a URL of the form ...

"https://en.wiktionary.org/w/index.php?title=" +
WORD_TO_LOOK_UP
+ "&printable=no"

... which it uses to set the src of the iframe.

Now, when you make a selection in the main content window, the Wiktionary page for the first word in the selection (or for the lowercase version of that word) will be shown in the NoteBook window. You may have to resize the window to see enough of the page.

The Wiktionary page appears in the iframe
Figure 1. The Wiktionary page appears in the iframe

A settings pane to choose native and target languages

In this section, you will see how to :
Download the source files
In this section, you'll learn how to:
  • X
  • Y

Using a helper tab to display a translation from Google

In this section, you will see how to :
Download the source files
In this section, you'll learn how to:
  • X
  • Y

NEXT

In this section, you will see how to :
Download the source files
In this section, you'll learn how to:
  • X
  • Y

Conclusion

Here's what you've learnt:
  • 98% of good stuff
  • 2% salt

Well done!

Overview

Lexogram is an online language-learning environment consisting of a Chrome extension and a reactive web site built with Meteor. Lexogram helps you make notes about web pages that you visit in the language that you are learning.

This tutorial shows you how to create a web page that can display information from third-party language reference sites, such as Google Translate and Wiktionary. It follows on from an earlier tutorial which shows you how to create a Chrome extension and communicate with a Meteor site running on your local server. For simplicity, the Meteor-specific elements have been commented out for this tutorial. This means that the web page you create can be hosted on any HTML server.

In particular, you will be learning to:
  • Query Wiktionary for information on a word in any language
  • Query Google Translate for a machine translation of a multi-word phrase