Skip to content

Commit

Permalink
Last go through the docs before releasing 0.3a; slightly improved Ass…
Browse files Browse the repository at this point in the history
…et#place in dom.indesign.jsx
  • Loading branch information
stdbrouw committed Nov 1, 2010
1 parent 7b670b6 commit 121f20c
Show file tree
Hide file tree
Showing 16 changed files with 138 additions and 41 deletions.
2 changes: 1 addition & 1 deletion core-packages/ui/doc/readme.rst
Expand Up @@ -188,7 +188,7 @@ The end result is the code we showed at the top of this page:
.. literalinclude:: ../../../examples/ui.jsx
:language: extendscript

You'll find this exact script in ``extendables/examples/ui.jsx``. You can copy-paste this file elsewhere and use it as a starting point to learn more about creating user interfaces with the Extendables UI library.
You'll find this exact script at ``extendables/examples/ui.jsx``. You can copy-paste this file elsewhere and use it as a starting point to learn more about creating user interfaces with the Extendables UI library.

What's wrong with a GUI designer?
=================================
Expand Down
12 changes: 6 additions & 6 deletions doc/core/contribute.rst
Expand Up @@ -107,10 +107,10 @@ If you're uncomfortable using Git, just use ``fab commit`` instead and it will g
Guidelines
----------

* versioning: `semver spec <http://semver.org/>`_. Since we're currently still in the experimental phase (version 0), semver places no restrictions on how we use version numbers, but this will become important once we graduate to version 1.
* Versioning: see the `semver spec <http://semver.org/>`_. Since we're currently still in the experimental phase (version 0), semver places no restrictions on how we use version numbers, but this will become important once we graduate to version 1.
* In time, if necessary, we may adopt the `nvie branching strategy <http://nvie.com/posts/a-successful-git-branching-model/>`_.
* what belongs in the framework and core-packages, what should be a site-package, what should be a script; experimentation
* we don't commit things that aren't documented or tested -- there's no point having functionality in the framework if nobody knows it's there or if it's not dependable; though we will look at unfinished
* version control messages: see Django style guide
* keep commits as atomic as possible: smaller is better
* style guide: none yet; tbd
* We don't commit things that aren't documented or tested -- there's no point having functionality in the framework if nobody knows it's there or if it's not dependable. We encourage people to show unfinished code, they just shouldn't expect it to get committed any time soon.
* Keep commits as atomic as possible: smaller is better.
* Version control messages: messages should be in the past tense, e.g. ``Improved XMLElement#repr``. If your commit closes a ticket in the issue tracker, start your commit message with ``Fixed #issue``, e.g. ``Fixed #33 -- improved XMLElement#repr``.
* In the documentation, instance methods are referred to as ``MyClass#mymethod``, class methods are referred to as ``MyClass.mymethod``.
* style guide: none yet; to be discussed. See the `Django style guide <http://docs.djangoproject.com/en/dev/internals/contributing/>`_ for a good example of issues that need to be addressed (code style, reporting bugs, how to do unit tests, naming conventions et cetera) and how we can communicate them.
42 changes: 36 additions & 6 deletions doc/core/design-patterns.rst
@@ -1,17 +1,47 @@
=====================================
Common design patterns in Extendables
=====================================
======================
Common design patterns
======================

For framework design issues currently under discussion, look at `issues in the GitHub issue tracker with a design label <http://github.com/stdbrouw/Extendables/issues/labels/design>`_.

getter/setters
==============

Sometimes, when coding an interface, it's useful to be able to pretend that an object has a certain attribute people can read from and write to, while in reality there's more going on behind the screen: a certain calculation, creating an object, doing a lookup in different places and so on — in essence, properties that work like functions, or functions that look like properties. This is a very useful abstraction that makes code more domain-specific.

Unfortunately, as opposed to Ruby and Python, Javascript has no support for making a function appear to be a property. Instead, you'll see the following idiom appear across different Javascript libraries:

.. literalinclude:: ../../../examples/getter-setters.jsx

Extendables makes considerable use of this idiom, which you're probably familiar with if you've ever used `jQuery <http://jquery.com/>`_ before.

domain-specific language constructs
===================================

* esp. in the UI interface
* make code read more like plain English, at the expense of having function names that are, perhaps, in themselves not always very descriptive (e.g. ``obj.is`` in itself might not make a lot of sense, even though it's pretty obvious what ``obj.is(Array)`` does.)
Some parts of Extendables try to make coding a bit more elegant and a bit more like plain English by introducing a `domain-specific language <http://en.wikipedia.org/wiki/Domain-specific_language>`_ within Javascript.

For example, in the UI module you would add styles to a dialog using ``var dialog = ui.Dialog("Hello there").with(styles);`` and not ``var dialog = ui.Dialog("Hello there"); dialog.add_styles(styles);``

In the Jasmine testing library, you define tests that look like

.. code-block:: javascript
it('needs proper unit tests', function () {
expect(false).toBeTruthy();
});
By themselves, the function names ``it`` and ``expect`` are vague and undescriptive. But in context, they lead to very elegant code that makes immediate sense. Extendables uses domain-specific constructs wherever a single isolated task needs to be accomplished (building a user interface, testing your code) but avoids them elsewhere, in favor of more generally descriptive function and class names.

In Extendables, modules that implement a domain-specific constructs are referred to as frameworks, because they frame your entire way of coding, whereas a library includes mostly helper classes and functions.

extending prototypes
====================

* people should make sure not to override these methods
Extendables does most of its work by extending the prototypes of built-in objects, like ``Number``, ``Array`` and ``String``. That way, we can keep our code entirely object-oriented instead of having
to define a plethora of helper functions.

If a developer wishes to extend object prototypes him- or herself, they need to be aware of which methods Extendables adds to the prototypes. Overriding prototype methods provided by Extendables could unpredictably alter how applications work, so some care needs to be taken.

..
- factories (Error handling)
- basic functional programming using select/reject/compact in Extendables' internal code
1 change: 1 addition & 0 deletions doc/core/index.rst
Expand Up @@ -9,5 +9,6 @@ Core

writing-a-module
contribute
design-patterns
roadmap
changes
6 changes: 3 additions & 3 deletions doc/core/writing-a-module.rst
@@ -1,8 +1,8 @@
.. _writing-a-module:

=======================================
Writing your own module for Extendables
=======================================
=======================
Writing your own module
=======================

Modules versus scripts
----------------------
Expand Down
16 changes: 9 additions & 7 deletions doc/patches/application-specific/indesign.rst
Expand Up @@ -5,21 +5,23 @@ InDesign enhancements
XML traversal
=============

Extendables includes a number of shortcuts methods on :func:`XMLElement` that make XML traversal less verbose.

.. note::

For handling straight-up XML (not InDesign-aware XMLElement objects),
use the built-in XML support in ExtendScript

Here's an example to get you started:

.. literalinclude:: ../../../examples/xml-traversal.jsx
:language: extendscript

Extendables provides some shortcut methods that make traversing XML in InDesign less verbose.

``XMLElement``
--------------

.. include:: ../../../patches/doc/jsdoc/XMLElement.rst
:start-after: class-methods

.. note::

For handling straight-up XML (not InDesign-aware XMLElement objects),
use the built-in XML support in ExtendScript

Handy helpers
=============
Expand Down
6 changes: 3 additions & 3 deletions doc/patches/application.rst
@@ -1,6 +1,6 @@
===================
Application methods
===================
=======================
``Application`` methods
=======================

Most of Extendables' functionality is either at the application-specific level or at the ExtendScript level. However, each ``app`` object, regardless of the host application, does get a ``is`` method added in that makes it easy to write code that targets a specific application or version.

Expand Down
2 changes: 2 additions & 0 deletions doc/patches/array.rst
Expand Up @@ -4,6 +4,8 @@

.. contents::

Extendables adds a considerable amount of methods to the ``Array`` object prototype. Most of these will be familiar from either Javascript 1.6+ (modern browsers implement Javascript 1.8 or higher) or from Jeremy Ashkenas' `underscore.js <http://documentcloud.github.com/underscore/>`_ library.

.. literalinclude:: ../../examples/arrays.jsx
:language: extendscript

Expand Down
6 changes: 3 additions & 3 deletions doc/patches/index.rst
@@ -1,6 +1,6 @@
================
DOM enhancements
================
============
Enhancements
============

While Extendables includes a number of enhancements to the DOM objects you'll find in Adobe software, it works most of its magic at the Javascript level: it adds all kinds of methods to ``Array``, ``String``, ``Object``, ``Function`` and other prototypes, allowing for more expressive code with less boilerplate.

Expand Down
7 changes: 4 additions & 3 deletions examples/basic.jsx
Expand Up @@ -27,8 +27,9 @@ var styling = {
}
var dialog = new ui.Dialog("I'm hungry").with(styling);
var suggestion = dialog.row('suggestion');
dialog.text('food', 'Want some food suggestions?').using('big').button('ok', 'Sure thing!');
dialog.button('no', 'No thanks');
dialog.text('food', 'Want some food suggestions?').using('big')
.button('ok', 'Sure thing!')
.button('no', 'No thanks');

// event handlers, the easy way
dialog.ok.on('click').do(function(){
Expand All @@ -40,5 +41,5 @@ dialog.no.on('click').do(function(){
this.window.close();
});

// let's show this dialog
// let's get started
dialog.window.show();
31 changes: 31 additions & 0 deletions examples/getter-setters.jsx
@@ -0,0 +1,31 @@
function Person () {
this.is_child = false;

// private attribute
this._age = null;

this.age = function (value) {
if (value) {
// setter
this._age = value;
if (this._age < 18) {
this.is_child = true;
}
} else {
// getter
if (this._age instanceof Number) {
return "{_age} years old".format(this);
} else {
return this._age;
}
}
}
}

var timmy = new Person();
// this sets the person's age
timmy.age(13);
// this returns the person's age
$.writeln(timmy.age());
// this allows our object to do more than just setting an attribute
$.writeln(timmy.is_child == true);
22 changes: 22 additions & 0 deletions examples/test/examples.specs
@@ -0,0 +1,22 @@
describe('Example code', function () {
var examples = new Folder("examples").at(Folder.extendables);

it('has a working basic code sample', function () {
$.evalFile(new File("basic.jsx").at(examples));
});
it('has a working code sample showcasing array functionality', function () {
$.evalFile(new File("arrays.jsx").at(examples));
});
it('has a working code sample showcasing methods on File and Folder', function () {
$.evalFile(new File("files-and-folders.jsx").at(examples));
});
it('has a working code sample showing the getter/setter design pattern', function () {
$.evalFile(new File("getter-setters.jsx").at(examples));
});
it('has a working code sample that constructs a user interface', function () {
$.evalFile(new File("ui.jsx").at(examples));
});
it('has a working code sample that does XML traversal', function () {
$.evalFile(new File("xml-traversal.jsx").at(examples));
});
});
7 changes: 4 additions & 3 deletions patches/dom.application.jsx
Expand Up @@ -7,9 +7,10 @@

/**
* @desc Check the host app.
* @param {String} application The application name. Case-insensitive. Prefixing
* @param {String|Number} [version] The application version number. Add two to your CS version number.
* or pass in the version number as a string prefixed with 'CS', like ``app.is('indesign', 'CS5')``.
* @param {String} application The application name. Case-insensitive.
* @param {String|Number} [version]
* The application version number. Add two to your CS version number.
* or pass in the version number as a string prefixed with 'CS', like ``app.is('indesign', 'CS5')``.
*
* @example
* alert(app.is('toolkit')); // any version
Expand Down
10 changes: 8 additions & 2 deletions patches/dom.indesign.jsx
Expand Up @@ -263,13 +263,19 @@ Asset.prototype.place = function (positioning) {
var x = positioning.x || margins.left;
var y = positioning.y || margins.top;
if (positioning.has('layer')) {
var destination_layer = current('document').layers.item(positioning.layer);
// positioning.layer can be both an actual layer or a layer name
if (positioning.layer instanceof Layer) {
var destination_layer = positioning.layer;
} else {
var destination_layer = current('document').layers.item(positioning.layer);
}
// can't place an asset on a layer that doesn't exist
if (destination_layer == null) {
teardown();
throw new RangeError("Layer {layer} does not exist".format(positioning));
}
} else {
var destination_layer = doc.activeLayer
var destination_layer = doc.activeLayer;
}
// put asset on the right page on a temporary layer
window.activePage = page;
Expand Down
6 changes: 3 additions & 3 deletions patches/object.jsx
Expand Up @@ -92,11 +92,11 @@ Object.prototype.is = function(type) {

Object.prototype.has = function (key) {
if (key in this) {
try {
return new Boolean(this[key]) != false;
} catch (error) {
if (this[key] == null) {
// invalid object
return false;
} else {
return new Boolean(this[key]) != false;
}
} else {
return false;
Expand Down
3 changes: 2 additions & 1 deletion test/runner.framework.jsx
@@ -1,7 +1,8 @@
#include "../extendables.jsx"
extract("testing");

var specs = new File($.fileName).parent.getFiles("*.specs");
var specs = new File($.fileName).parent.files("*.specs");
specs = specs.concat(new Folder("examples/test").at(Folder.extendables).files("*.specs"));

specs.forEach(function (specfile) {
try {
Expand Down

0 comments on commit 121f20c

Please sign in to comment.