<chapter id="importer">
  <title>The Importer</title>
  <para>To access code of other JavaScript files, cjs has the <code>imports</code> object.</para>

  <para>
    In cjs in combination with Cinnamon you can use following statements to import statements:

    <informalexample>
      <programlisting>
        imports.*
        imports.gi.*
        imports.ui.*
        imports.misc.*
      </programlisting>
    </informalexample>
  </para>

  <sect2>
    <title><code>imports.*</code></title>

    <para>This is the normal form of importing modules.</para>

    <para>
      You can think of this object like nested objects which properties are the JavaScript files or directories.
      All functions, variables (var, let, const) in a JavaScript file can be accessed like this file is an object.
    </para>

    <para>
      To clarify, an example:
      <informalexample>
        <programlisting>
          //Direct access to file a.js
          const A = imports.a;
          //Directories must be also typed in, in order to get file c.js in directory b
          const C = imports.b.c;

          log(A.foo); //"Property foo"
          log(A.bar()); //"Method bar"
          log(C.baz); //"Property baz"

        </programlisting>
      </informalexample>
      <code>a.js</code>
      <informalexample>
        <programlisting>
          let foo = "Property foo";

          function bar(){
            return "Method bar";
          }
      </programlisting>
      </informalexample>
      <code>c.js</code> in a directory named b
      <informalexample>
        <programlisting>
          let baz = "Property baz";
        </programlisting>
      </informalexample>
    </para>

    <para>
      In every case, you can include cjs core modules.
      Those provide you useful functions or (less often) bindings to C libraries.
    </para>

    <para>
      Examples are:
      <informalexample>
        <programlisting>
          const Cairo = imports.cairo; //Cairo graphics
          const Lang = imports.lang; //useful JavaScript functions for extensing the language
          const Gettext = imports.gettext; //Gettext translation
          const TweenEquations = imports.tweener.equations; //Tween equations for animations
        </programlisting>
      </informalexample>
    </para>

    <para>As you can see, it is common to assign the import to a constant in UpperCamelCase which looks like the imported module.</para>

    <para>To view the source of those cjs modules, you should visit <ulink role="online-location" url="https://github.com/linuxmint/cjs/tree/master/modules">the GitHub page</ulink>.</para>
  </sect2>

  <sect2>
    <title><code>imports.gi.*</code></title>

    <para>As Cinnamon uses C libraries like Clutter, Muffin and more, there is a little problem: How can those libraries be used in cjs?</para>

    <para>
      For this, there is <ulink role="online-location" url="https://wiki.gnome.org/Projects/GObjectIntrospection">GObject Introspection</ulink>.
      In short, it allows you to use C libraries in cjs, Python and other languages.
    </para>

    <para>
      C libraries are included like this:
      <informalexample>
        <programlisting>
          const St = imports.gi.St; //Shell Toolkit, the normal way to display widgets on the Cinnamon screen
          const Cinnamon = imports.gi.Cinnamon; //Cinnamon C libraries, e.g. AppSystem
        </programlisting>
      </informalexample>
    </para>

    <para>Note: Not like normal <code>imports.*</code>, <code>imports.gi.*</code> imports needs to have the first letter after <code>gi.</code> be in upper case.</para>
  </sect2>

  <sect2>
    <title><code>imports.ui.*</code></title>

    <para>Those imports under <code>imports.ui.*</code> are core Cinnamon modules.</para>

    <para>
      Some important modules:
      <informalexample>
        <programlisting>
          const PopupMenu = imports.ui.popupMenu; //High-level classes for building menus for applets or context menus
          const Applet = imports.ui.applet; //Base applet classes
        </programlisting>
      </informalexample>
    </para>

    <para>The source is in <code>/usr/share/cinnamon/js/ui/</code></para>
  </sect2>

  <sect2>
    <title><code>imports.misc.*</code></title>

    <para>Those imports under <code>imports.misc.*</code> belong to Cinnamon, but aren't tied to it as much as <code>imports.ui.*</code>.</para>

    <para>
      <informalexample>
        <programlisting>
          const Util = imports.misc.util; //useful functions
          const Interfaces = imports.misc.interfaces; //DBus stuff
        </programlisting>
      </informalexample>
    </para>

    <para>The source is in <code>/usr/share/cinnamon/js/misc/</code></para>
  </sect2>

  <sect2>
    <title>Importing xlet modules</title>

    <para>
      When you want to split a big xlet file into smaller files, you'll need to import them.
      The best way is using <code>imports.ui.manager.xlet[UUID]</code>.
      <code>manager</code> is one of <code>appletManager</code>, <code>deskletManager</code>, or <code>extensionSystem</code>.
      <code>xlet</code> is the xlet type pluralized and is one of <code>applets</code>, <code>desklets</code>, or <code>extensions</code>.
      <code>UUID</code> is the string of your xlet's UUID.

      <para>
        Importing for applets:
        <informalexample>
          <programlisting>
            const Module = imports.ui.appletManager['foo@bar'].module; // get module.js in your applet directory
          </programlisting>
        </informalexample>
      </para>

      <para>
        Importing for desklets:
        <informalexample>
          <programlisting>
            const Module = imports.ui.deskletManager['foo@bar'].module; // get module.js in your desklet directory
          </programlisting>
        </informalexample>
      </para>

      <para>
        Importing for extensions:
        <informalexample>
          <programlisting>
            const Module = imports.ui.extensionSystem['foo@bar'].module; // get module.js in your extension directory
          </programlisting>
        </informalexample>
      </para>
    </para>
    <para>
      In Cinnamon 3.6+, there is now a simpler way to import files using <code>require</code>. This method is not compatible with previous versions of Cinnamon.

      <para>
        Importing GI modules:
        <informalexample>
          <programlisting>
            const Cinnamon = require('gi.Cinnamon');
          </programlisting>
        </informalexample>
      </para>

      <para>
        Importing Cinnamon modules:
        <informalexample>
          <programlisting>
            const DND = require('ui.dnd');
          </programlisting>
        </informalexample>
      </para>

      <para>
        Importing other JS files (".js" extension is optional):
        <informalexample>
          <programlisting>
            const MenuItem = require('./menuItem.js').MenuItem;
          </programlisting>
        </informalexample>
      </para>

      <para>
        You can also manually export your modules by adding them to <code>module.exports</code> at the end of the file.
        Inside your module file:
        <informalexample>
          <programlisting>
            function MenuItem() {...}
            ...
            module.exports = MenuItem;
          </programlisting>
        </informalexample>
        Then from the file you want import MenuItem from:
        <informalexample>
          <programlisting>
            const MenuItem = require('./menuItem');
          </programlisting>
        </informalexample>
      </para>
    </para>
  </sect2>
</chapter>
