Thursday, August 11, 2011

TextView, Editor and RequireJS

Although Orion currently is using requireJS to load its javascript content, the text view and editor were made to work both with and without requireJS.
This decision created a special case when developing these components.
The textview and editor components are declared in the global namespace (so they work without requireJS) and they are also exported using the define mechanism of requireJS.
When, for example, an editor object needs to reference a textview object, it must do so using the global namespace so that it will still work when requireJS is not present.
In short, all the text view and editor components are implemented without any knowledge of requireJS. At the end of each file the define declaration for the
component implemented in the file is added. For example, in textview.js (where TextView is defined), these lines were added:

if (typeof window !== "undefined" && typeof window.define !== "undefined") {
  define(['orion/textview/textModel', 'orion/textview/keyBinding'], function() {
    return orion.textview;
  });
}

Similar lines were added to every file in text view and editor.

This is transparent to the user and the user can choose to use requireJS or not. Here is example using requireJS:

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/requirejs/require.js"></script>
<script type="text/javascript">
  require({
    baseUrl: '',
    paths: {orion: '/orion'}
  });
  require(["test"]);
</script>
</head>
<body>
<div id='textViewDiv' style='width:650px;height:650px;border: 1px solid teal;'></div>
</body>
</html>

In the same folder you need a "test.js" with the following content:

define(["orion/textview/textView"], function(mTextView) {
  var options = {
    parent: "textViewDiv",
    stylesheet: "/orion/textview/textview.css",
    fullSelection: true,
    tabSize: 4
  };
  var view = new mTextView.TextView(options);
  view.setText("Welcome to the TextView");
});

Here is the same example without requireJS:

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/orion/textview/keyBinding.js"></script>
<script type="text/javascript" src="/orion/textview/textModel.js"></script>
<script type="text/javascript" src="/orion/textview/textView.js"></script>
<script type="text/javascript">
function init() {
  var options = {
    parent: "textViewDiv",
    stylesheet: "/orion/textview/textview.css",
    fullSelection: true,
    tabSize: 4
  };
  var view = new orion.textview.TextView(options);
  view.setText("Welcome to the TextView");
}
</script>
</head>
<body onload="init()">
<div id='textViewDiv' style='width:650px;height:650px;border: 1px solid teal;'></div>
</body>
</html>


These examples do not really show the value of requireJS, but as the complexity of a web application grows having a system like requireJS to handle loading dependencies provides other benefits (simplicity, robust, performance, etc).

1 comment:

  1. The check for define can be shortened to:

    if (typeof define === 'function' && define.amd) {
    }

    define is a global in environments where requirejs runs, including in node and rhino, and define.amd signals it is an AMD define, and not some other kind of define function that may not understand AMD.

    ReplyDelete