<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Criteria Studio &#187; titanium</title>
	<atom:link href="https://www.criteriastudio.com/tag/titanium/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.criteriastudio.com</link>
	<description>Mobile apps developers</description>
	<lastBuildDate>Wed, 23 May 2018 10:18:22 +0000</lastBuildDate>
	<language>es-ES</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>Entrevista en Radio3 &#8220;La irrupción de nuevos oficios: desarrollo de apps&#8221;</title>
		<link>https://www.criteriastudio.com/entrevista-en-radio3-la-irrupcion-de-nuevos-oficios-desarrollo-de-apps/</link>
		<comments>https://www.criteriastudio.com/entrevista-en-radio3-la-irrupcion-de-nuevos-oficios-desarrollo-de-apps/#comments</comments>
		<pubDate>Thu, 01 May 2014 07:46:28 +0000</pubDate>
		<dc:creator><![CDATA[J. Rayon]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[radio]]></category>
		<category><![CDATA[titan]]></category>
		<category><![CDATA[titanium]]></category>
		<category><![CDATA[uned]]></category>

		<guid isPermaLink="false">http://www.criteriastudio.com/?p=641</guid>
		<description><![CDATA[Entrevista emitida en Radio 3 (Radio Nacional de España) en cl programa de la UNED con motivo de la participación de CriteriaStudio en el programa modular &#8220;Apps, web y marketing&#8221; Escuchar entrevista (rtve.es) Visitar la web del programa de la UNED &#8220;Apps, web y marketing&#8221;]]></description>
				<content:encoded><![CDATA[<p>Entrevista emitida en Radio 3 (Radio Nacional de España) en cl programa de la UNED con motivo de la participación de CriteriaStudio en el programa modular &#8220;Apps, web y marketing&#8221;</p>
<ul>
<li><a title="Entrevista desarrollo de apps móviles" href="http://www.rtve.es/alacarta/audios/uned/uned-programa-modular-uned-apps-web-marketing-irrupcion-nuevos-oficios-desarrollo-apps-aplicaciones-moviles-24-04-14/2529837/" target="_blank">Escuchar entrevista (rtve.es)</a></li>
<li><a title="Programa de la UNED: apps, web y marketing" href="http://uned.appswebymarketing.com/" target="_blank">Visitar la web del programa de la UNED &#8220;Apps, web y marketing&#8221;</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://www.criteriastudio.com/entrevista-en-radio3-la-irrupcion-de-nuevos-oficios-desarrollo-de-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Titanium: Tablas y callbacks</title>
		<link>https://www.criteriastudio.com/titanium-tablas-y-callbacks/</link>
		<comments>https://www.criteriastudio.com/titanium-tablas-y-callbacks/#comments</comments>
		<pubDate>Fri, 31 Aug 2012 17:01:23 +0000</pubDate>
		<dc:creator><![CDATA[J. Rayon]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[callback]]></category>
		<category><![CDATA[HTTPClient]]></category>
		<category><![CDATA[tableviews]]></category>
		<category><![CDATA[titanium]]></category>

		<guid isPermaLink="false">http://www.criteriastudio.com/?p=563</guid>
		<description><![CDATA[En el último evento de Titanium, desarrollé un pequeño ejemplo para iOS y Android que consistía en una tabla con imágenes de un feed de flickr. Al pulsar una fila de la tabla se abre una ventana con la foto ampliada. Es un ejemplo sencillo que me permite introducir un par de conceptos sobre Titanium y [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>En el <a href="http://www.criteriastudio.com/summer-workshop-de-titanium-14-agosto-en-becode/">último evento de Titanium</a>, desarrollé un pequeño ejemplo para iOS y Android que consistía en una tabla con imágenes de un <a href="http://www.flickr.com/services/feeds/">feed de flickr</a>. Al pulsar una fila de la tabla se abre una ventana con la foto ampliada. Es un ejemplo sencillo que me permite introducir un par de conceptos sobre Titanium y commonJS.</p>
<p>Primero veremos cómo personalizar objetos de Titanium para posteriormente crear múltiples instancias del mismo. Crearemos nuestro propio módulo commonJS que devuelve un TableViewRow ya personalizado con los datos de cada fila.</p>
<p>En segundo lugar, veremos cómo llamar a un servicio web remoto, cuya respuesta es asíncrona (esto es, no ocurre en el orden normal del hilo de ejecución, si no cuando llega la respuesta del servidor). Para gestionar esta respuesta asíncrona haremos uso de las funciones callback y haré una breve discusión sobre cuándo usar funciones callback y cuando usar eventos a nivel de aplicación, por si a Miguel Ángel no le quedó del todo claro.</p>
<p>Si no has seguido los anteriores posts, te recomiendo echar un vistazo <a href="http://www.criteriastudio.com/category/blog/" target="_blank">al blog con la introducción de JavaScript y commonJS para Titanium</a>.</p>
<p>Como siempre, empezamos con app.js y los módulos de la aplicación declarados en ModulePaths.js. La discusión de estos ficheros es la misma que <a href="http://www.criteriastudio.com/app-template-para-titanium/">hice en esta entrada</a>, así que no la repito.</p>
<h4>App.js</h4>
<p>gist id=3554525 file=app.js]</p>
<h4>ModulePaths.js</h4>
<p>gist id=3554525 file=ModulePaths.js]</p>
<h4>Styles.js</h4>
<p>gist id=3554525 file=Styles.js]</p>
<h4>AppWindow.js</h4>
<p>Esta es la ventana que se crea desde app.js, simplemente añade la tabla de fotos a la ventana y la devuelve para que app.js cree una instancia y la abra.</p>
<p>gist id=3554525 file=AppWindow.js]</p>
<h4>PhotosTableView.js</h4>
<p>Este módulo devuelve un tableView de Titanium, que llama a <code class="codecolorer text mac-classic"><span class="text">Feed.getData</span></code> (que veremos a continuación) y  le pasa como argumento <code class="codecolorer text mac-classic"><span class="text">callbackTableView</span></code>, que es el nombre de una función definida previamente. Feed se conecta con los servicios de Flickr y recibe un listado de fotografías. Si la información que devuelve <code class="codecolorer text mac-classic"><span class="text">Feed.getData</span></code> fuera local (de un fichero o una base de datos), podríamos hacer algo como <code class="codecolorer text mac-classic"><span class="text">tableview.data = Feed.getData()</span></code> (suponiendo que la info viniera ya formateada). Pero como <code class="codecolorer text mac-classic"><span class="text">Feed</span></code> va a conectar con un servidor remoto y no sabemos cuándo va a responder, lo que hacemos es pasarle como argumento la función que queremos que ejecute cuando ya tenga la respuesta del servidor.</p>
<p>De momento, basta saber que cuando <code class="codecolorer text mac-classic"><span class="text">Feed.getData</span></code> termine de hacer lo que tenga que hacer, llamará a <code class="codecolorer text mac-classic"><span class="text">callbackTableView</span></code></p>
<p>gist id=3554525 file=PhotosTableView.js]</p>
<p>Cuando <code class="codecolorer text mac-classic"><span class="text">Feed</span></code> tiene respuesta del servidor, llama a <code class="codecolorer text mac-classic"><span class="text">callbackTableView</span></code> y le pasa como argumento dicha respuesta. Dentro de <code class="codecolorer text mac-classic"><span class="text">callbackTableView</span></code>, si la respuesta es válida, se crean las instancias de <code class="codecolorer text mac-classic"><span class="text">PhotoRow</span></code>, que son cada una de las filas de la tabla. Finalmente se añaden a la tabla.</p>
<p>Después de la función de callback, digo a la tabla que escuche los eventos click que pueda recibir y, si la fila es válida, creará una instancia de <code class="codecolorer text mac-classic"><span class="text">PhotoViewer</span></code> para visualizar la foto en grande. Siempre es mejor añadir el eventListener al tableView y no a las tableViewRow, es más eficiente gestionar un sólo eventListener (uno por la tabla) que decenas o cientos de eventListeners (tantos como filas tenga la tabla). Por tanto, evita la tentación de usar eventListeners a nivel de fila.</p>
<p><code class="codecolorer text mac-classic"><span class="text">e.row</span></code> es el objeto fila que ha sido clickado y Titanium se encarga de devolvérnoslo siempre que se hace click en la tabla. <code class="codecolorer text mac-classic"><span class="text">e.row.data</span></code> es una propiedad creada por nosotros mismos en el módulo PhotoRow. Lo que hago es crear esta propiedad con toda la información del elemento devuelta por el servidor para poderla recuperar más adelante (en el siguiente apartado se termina de entender esto).</p>
<h4>PhotosTableViewRow.js</h4>
<p>Es cada una de las filas de la tabla. Este componente se va a reutilizar varias veces (al contrario que el resto, que sólo se usan una vez en la aplicación). Para hacerlo reutilizable, el componente recibe como argumento el item con la información que tiene que rellenar (en nuestro ejemplo, título y una foto) y usamos esta información para completar la creación de los componentes que forman la fila. En la fila 9, creo una propiedad <code class="codecolorer text mac-classic"><span class="text">data</span></code> en el <code class="codecolorer text mac-classic"><span class="text">TableViewRow</span></code> que me permitirá recuperar toda la información del elemento más tarde. Este es el mismo &#8220;data&#8221; que recupero en el eventListener de la tabla.</p>
<p>gist id=3554525 file=PhotosTableViewRow.js]</p>
<h4>PhotoViewer.js</h4>
<p>Este fichero no tiene mucha complejidad. Se tiene en cuenta si la plataforma es iOS o Android, para colocar o no un botón de cerrar (android no lo necesita, ya que dispones de el botón &#8220;volver&#8221;).</p>
<p>Para facilitar la escritura, en el fichero estilos he creado una propiedad iOS que será <code class="codecolorer text mac-classic"><span class="text">true</span></code> si el dispositivo es iPhone o iPad, así resulta más fácil de escribir (y de leer), tan simple como ver el valor de <code class="codecolorer text mac-classic"><span class="text">$$.iOS</span></code>.</p>
<p>Otro punto interesante, podemos agregar nuestros propios métodos a objetos Titanium. A <code class="codecolorer text mac-classic"><span class="text">win</span></code> le añado el método <code class="codecolorer text mac-classic"><span class="text">showImage</span></code>, que es una función que abrirá la ventana en forma modal. (Ojo! No es la mejor manera de hacer esto, pero para el ejemplo queda bien y es suficiente). Así, podemos extender el funcionamiento nativo de los componentes Titanium agregando métodos y propiedades.</p>
<p><strong>Importante</strong> saber que cuando añadamos métodos a objetos Titanium estos no deben nunca empezar con <code class="codecolorer text mac-classic"><span class="text">get</span></code> o <code class="codecolorer text mac-classic"><span class="text">set</span></code>. Es una limitación de la plataforma, fallará en silencio y podemos tirarnos un buen raton sin saber qué pasa o porqué no funciona.</p>
<p>gist id=3554525 file=PhotoViewer.js]</p>
<h4>flickrFeed.js</h4>
<p>Vistos todos los ficheros relativos a la interfaz de usuario, pasamos a ver cómo se gestiona la conexión con el servidor.</p>
<p>El cliente http establece una conexión con un puerto web y hace una petición GET o POST a la url que le indiquemos. HTTPclient permite definir varias funciones callback para gestionar la respuesta del servidor. En este ejemplo uso <code class="codecolorer text mac-classic"><span class="text">onload</span></code> y <code class="codecolorer text mac-classic"><span class="text">onerror</span></code>, pero tambien podemos capturar <code class="codecolorer text mac-classic"><span class="text">ondatastream</span></code> y <code class="codecolorer text mac-classic"><span class="text">onsendstream</span></code> para saber la cantidad de información enviada y recibida.</p>
<p>gist id=3554525 file=flickrFeed.js]</p>
<p>He definido la función <code class="codecolorer text mac-classic"><span class="text">exports.getData</span></code> para que reciba un argumento llamado <code class="codecolorer text mac-classic"><span class="text">callback</span></code>. Titanium llamará la función definida en <code class="codecolorer text mac-classic"><span class="text">onload</span></code> cuando tenga respuesta del servidor. Tras procesar la respuesta, se ejecuta <code class="codecolorer text mac-classic"><span class="text">callback</span></code>, pasándole como argumento la respuesta &#8211; ya procesada &#8211; del servidor. <code class="codecolorer text mac-classic"><span class="text">getData</span></code> no necesita saber qué es o a quién pertenece <code class="codecolorer text mac-classic"><span class="text">callback</span></code>, simplemente la intentará ejecutar suponiendo que se trata de una función y que sabrá como ejecutarse. En el ejemplo, lo que ocurrirá es que se llamará a <code class="codecolorer text mac-classic"><span class="text">callbackTableview</span></code>, que es la función que pasamos como argumento a <code class="codecolorer text mac-classic"><span class="text">Feed.getData</span></code> y si todo va bien, rellenará la tabla con las fotos.</p>
<p><em>He observardo que algunas tags en flickr generan una respuesta json que titanium no puede procesar, si haces pruebas cambiando las palabras en la URL, puede que falle por esto.</em></p>
<h4>Eventos vs. callbacks</h4>
<p>Espero dedicar en algún momento una entrada sólo a la creación y gestión de eventos, pero quiero hacer una pequeña aclaración de porqué es preferible usar callbacks a eventos a nivel de app. Primero, hay que diferenciar entre lo que son eventos de componentes gráficos (como <code class="codecolorer text mac-classic"><span class="text">click</span></code>, <code class="codecolorer text mac-classic"><span class="text">load</span></code>, etc.) y eventos de aplicación. Los eventos de aplicación son los que se gestionan desde <code class="codecolorer text mac-classic"><span class="text">Ti.App.addEventListener()</span></code> y <code class="codecolorer text mac-classic"><span class="text">Ti.App.fireEvent()</span></code>. Lo que explico a continuación afecta a ambos, pero especialmente a los segundos.</p>
<p>Por explicarlo de forma gráfica, una función callback es una conexión directa entre dos objetos. Un objeto llama a un método de otro objeto. No hay intermediarios. Fin de la historia.</p>
<p>Un evento de aplicación es más complejo. Se dispara un evento desde un punto de la aplicación, la aplicación recoge el evento y lo &#8220;reparte&#8221; entre los otros módulos que previamente estarán escuchando. El simple hecho de estar escuchando eventos ya tiene un coste. Como además, el evento es a nivel de app, salta de un módulo al objeto Ti.App y de éste a los que estén escuchando.</p>
<p>En casos en los que sólo queremos comunicar dos objetos es preferible usar callbacks.</p>
<p>Si estamos creando componentes reutilizables, normalmente componentes UI, podemos disparar nuestros propios eventos de componentes (por ejemplo, si nos inventamos un botón que implementa un evento <code class="codecolorer text mac-classic"><span class="text">tripleclick</span></code>)</p>
<p>Y sólo en los casos en que necesitemos llamar la atención de varios objetos no conectados entre sí desde un único punto de la aplicación nos plantearemos usar eventos de aplicación.</p>
<p>&nbsp;</p>
<p>Tienes <a href="https://github.com/jaraen/TitaniumBlogTablesAndCallbacks" target="_blank">los ficheros de este proyecto disponibles para descargar aquí.</a></p>
]]></content:encoded>
			<wfw:commentRss>https://www.criteriastudio.com/titanium-tablas-y-callbacks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>App Template para Titanium</title>
		<link>https://www.criteriastudio.com/app-template-para-titanium/</link>
		<comments>https://www.criteriastudio.com/app-template-para-titanium/#comments</comments>
		<pubDate>Sun, 12 Aug 2012 11:40:18 +0000</pubDate>
		<dc:creator><![CDATA[J. Rayon]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[commonJS]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[mobile web]]></category>
		<category><![CDATA[tabGroup]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[titanium]]></category>

		<guid isPermaLink="false">http://www.criteriastudio.com/?p=531</guid>
		<description><![CDATA[Hoy voy a crear un sencillo template de Titanium que podremos usar para empezar nuestras aplicaciones de cero. Nos servirá para sustituir el template que usa Titanium Studio al crear una aplicación en blanco. La aplicación por defecto de Titanium Studio crea un tabGroup con dos ventanas. Yo voy a crear la misma aplicación, pero [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Hoy voy a crear un sencillo template de Titanium que podremos usar para empezar nuestras aplicaciones de cero. Nos servirá para sustituir el template que usa Titanium Studio al crear una aplicación en blanco.</p>
<p>La aplicación por defecto de Titanium Studio crea un tabGroup con dos ventanas. Yo voy a crear la misma aplicación, pero usando módulos commonJS. Además, ya dejamos preparada la estructura de directorios para que nuestra app pueda crecer correctamente desde un principio.</p>
<blockquote><p>Antes de continuar, puede que te interesen estos artículos si no los has leído aún.<a href="http://www.criteriastudio.com/javascript-para-titanium-i/">JavaScript para Titanium (I)</a>, <a href="http://www.criteriastudio.com/javascript-para-titanium-ii/">JavaScript para Titanium (II)</a>, <a href="http://www.criteriastudio.com/commonjs-para-titanium/">CommonJS para Titanium</a></p></blockquote>
<h4>Resumen</h4>
<p>Crearemos una app con un TabGroup con 3 tabs (secciones). Cada tab abre una ventana diferente. El mismo código nos permitirá distribuir una aplicación nativa android, iPhone y mobile web.</p>
<h4>app.js</h4>
<p>Empezamos por el punto de arranque de la app. Recuerda que todas las apps titanium arrancan desde app.js.</p>
<div id="gist3331472" class="gist">
<div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
<div class="gist-data">
<div class="js-gist-file-update-container js-task-list-container">
<div id="file-app-js" class="file my-2">
<div itemprop="text"
      class="Box-body p-0 blob-wrapper data type-javascript  "
      style="overflow: auto" tabindex="0" role="region"
      aria-label="app.js content, created by jaraen on 11:24AM on August 12, 2012."
    ></p>
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">
<p>  <template class="js-file-alert-template"></p>
<div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"></p>
<path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg><br />
    <span><br />
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.<br />
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a><br />
    </span></p>
<div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters<br />
</a>
</div>
</div>
<p></template><br />
<template class="js-line-alert-template"><br />
  <span aria-label="This line has hidden Unicode characters" data-view-component="true" class="line-alert tooltipped tooltipped-e"><br />
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"></p>
<path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg><br />
</span></template></p>
<table data-hpc class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip data-tagsearch-path="app.js">
<tr>
<td id="file-app-js-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
<td id="file-app-js-LC1" class="blob-code blob-code-inner js-file-line">(function(){</td>
</tr>
<tr>
<td id="file-app-js-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
<td id="file-app-js-LC2" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-app-js-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
<td id="file-app-js-LC3" class="blob-code blob-code-inner js-file-line">	var Mods = require(&#39;/ModulePaths&#39;);</td>
</tr>
<tr>
<td id="file-app-js-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
<td id="file-app-js-LC4" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-app-js-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
<td id="file-app-js-LC5" class="blob-code blob-code-inner js-file-line">	var TabGroup = require(Mods.TABGROUP);</td>
</tr>
<tr>
<td id="file-app-js-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
<td id="file-app-js-LC6" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-app-js-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
<td id="file-app-js-LC7" class="blob-code blob-code-inner js-file-line">	var tabGroup = new TabGroup();</td>
</tr>
<tr>
<td id="file-app-js-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
<td id="file-app-js-LC8" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-app-js-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
<td id="file-app-js-LC9" class="blob-code blob-code-inner js-file-line">	tabGroup.open();</td>
</tr>
<tr>
<td id="file-app-js-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
<td id="file-app-js-LC10" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-app-js-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
<td id="file-app-js-LC11" class="blob-code blob-code-inner js-file-line">})();</td>
</tr>
</table>
</div></div>
</p></div>
</div></div>
<div class="gist-meta">
        <a href="https://gist.github.com/jaraen/3331472/raw/f4dfee80acfc139e396e44e60397f8c67818b914/app.js" style="float:right" class="Link--inTextBlock">view raw</a><br />
        <a href="https://gist.github.com/jaraen/3331472#file-app-js" class="Link--inTextBlock"><br />
          app.js<br />
        </a><br />
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
</p></div>
</div>
<p>Hay varias cosas que comentar. Primero, habrás observado que todo el fichero está envuelto en una función anónima que se autoejecuta (el hecho de que la función esté envuelta en unos paréntesis con otros paréntesis a continuación hace que la función se ejecute tras ser declarada). Como recordarás de la <a href="http://www.criteriastudio.com/javascript-para-titanium-ii/" target="_blank">introducción a JavaScript</a>, las funciones limitan el ámbito de las variables. Con esta función anónima, lo que hacemos es evitar que las variables Mods, TabGroup y tabGroup salten al ámbito global y por tanto puedan ser accesibles desde otras partes de la aplicación. Esta técnica sólo es necesaria (en principio) en el fichero app.js, ya que el resto de nuestros ficheros van a ser todos módulos commonJS, que  limitan de por sí el ámbito de sus variables.</p>
<p>Lo primero que hace app.js es cargar un módulo llamado ModulePaths. Aunque esto no es obligatorio y no lo verás en todas las apps, es una costumbre que he puesto en práctica y que me ha demostrado tener varias ventajas. De momento, basta saber que ModulePaths contiene todas las sendas y nombres de ficheros del proyecto para no tener que recordarlos.</p>
<p>A continuación, cargo el módulo TabGroup (explicado más adelante). La línea 9 crea una instancia del módulo y finalmente se da la orden de abrir el tabGroup. Mucho ojo a las mayúsculas y minúsculas. Es una buena costumbre cargar los módulos en variables con mayúsculas (TabGroup) y las instancias de módulos con minúsculas (tabGroup).</p>
<h4>app/ui/TabGroup.js</h4>
<p>Este módulo devuelve una instancia de Titanium.UI.TabGroup, ya adaptada a nuestras necesidades. El hecho de poder cargar un componente de Titanium, modificarlo y ampliarlo a nuestro gusto y devolverlo como un componente nuevo, es tremendamente útil y lo desarrollaré a fondo en próximas entregas.</p>
<p>En todos mis módulos siempre lo primero que hago es cargar ModulePaths, a continuación defino los módulos que voy a usar en este módulo y finalmente se implementa el módulo desde module.exports.</p>
<div id="gist3331472" class="gist">
<div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
<div class="gist-data">
<div class="js-gist-file-update-container js-task-list-container">
<div id="file-tabgroup-js" class="file my-2">
<div itemprop="text"
      class="Box-body p-0 blob-wrapper data type-javascript  "
      style="overflow: auto" tabindex="0" role="region"
      aria-label="TabGroup.js content, created by jaraen on 11:24AM on August 12, 2012."
    ></p>
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">
<p>  <template class="js-file-alert-template"></p>
<div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"></p>
<path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg><br />
    <span><br />
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.<br />
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a><br />
    </span></p>
<div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters<br />
</a>
</div>
</div>
<p></template><br />
<template class="js-line-alert-template"><br />
  <span aria-label="This line has hidden Unicode characters" data-view-component="true" class="line-alert tooltipped tooltipped-e"><br />
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"></p>
<path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg><br />
</span></template></p>
<table data-hpc class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip data-tagsearch-path="TabGroup.js">
<tr>
<td id="file-tabgroup-js-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
<td id="file-tabgroup-js-LC1" class="blob-code blob-code-inner js-file-line">var Mods = require(&#39;/ModulePaths&#39;);		//load module paths</td>
</tr>
<tr>
<td id="file-tabgroup-js-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
<td id="file-tabgroup-js-LC2" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-tabgroup-js-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
<td id="file-tabgroup-js-LC3" class="blob-code blob-code-inner js-file-line">var Window1 = require(Mods.WINDOW1),</td>
</tr>
<tr>
<td id="file-tabgroup-js-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
<td id="file-tabgroup-js-LC4" class="blob-code blob-code-inner js-file-line">	Window2 = require(Mods.WINDOW2),</td>
</tr>
<tr>
<td id="file-tabgroup-js-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
<td id="file-tabgroup-js-LC5" class="blob-code blob-code-inner js-file-line">	Window3 = require(Mods.WINDOW3);</td>
</tr>
<tr>
<td id="file-tabgroup-js-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
<td id="file-tabgroup-js-LC6" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-tabgroup-js-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
<td id="file-tabgroup-js-LC7" class="blob-code blob-code-inner js-file-line">module.exports = function(_args) {</td>
</tr>
<tr>
<td id="file-tabgroup-js-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
<td id="file-tabgroup-js-LC8" class="blob-code blob-code-inner js-file-line">	</td>
</tr>
<tr>
<td id="file-tabgroup-js-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
<td id="file-tabgroup-js-LC9" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-tabgroup-js-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
<td id="file-tabgroup-js-LC10" class="blob-code blob-code-inner js-file-line">	var tabGroup = Ti.UI.createTabGroup();</td>
</tr>
<tr>
<td id="file-tabgroup-js-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
<td id="file-tabgroup-js-LC11" class="blob-code blob-code-inner js-file-line">	</td>
</tr>
<tr>
<td id="file-tabgroup-js-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
<td id="file-tabgroup-js-LC12" class="blob-code blob-code-inner js-file-line">	var win1 = new Window1();</td>
</tr>
<tr>
<td id="file-tabgroup-js-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
<td id="file-tabgroup-js-LC13" class="blob-code blob-code-inner js-file-line">	</td>
</tr>
<tr>
<td id="file-tabgroup-js-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
<td id="file-tabgroup-js-LC14" class="blob-code blob-code-inner js-file-line">	var win2 = new Window2();</td>
</tr>
<tr>
<td id="file-tabgroup-js-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
<td id="file-tabgroup-js-LC15" class="blob-code blob-code-inner js-file-line">	</td>
</tr>
<tr>
<td id="file-tabgroup-js-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
<td id="file-tabgroup-js-LC16" class="blob-code blob-code-inner js-file-line">	var win3 = new Window3();</td>
</tr>
<tr>
<td id="file-tabgroup-js-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
<td id="file-tabgroup-js-LC17" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-tabgroup-js-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
<td id="file-tabgroup-js-LC18" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-tabgroup-js-L19" class="blob-num js-line-number js-blob-rnum" data-line-number="19"></td>
<td id="file-tabgroup-js-LC19" class="blob-code blob-code-inner js-file-line">	var tab1 = Ti.UI.createTab({</td>
</tr>
<tr>
<td id="file-tabgroup-js-L20" class="blob-num js-line-number js-blob-rnum" data-line-number="20"></td>
<td id="file-tabgroup-js-LC20" class="blob-code blob-code-inner js-file-line">		window: win1,</td>
</tr>
<tr>
<td id="file-tabgroup-js-L21" class="blob-num js-line-number js-blob-rnum" data-line-number="21"></td>
<td id="file-tabgroup-js-LC21" class="blob-code blob-code-inner js-file-line">		title:&#39;Window 1&#39;,</td>
</tr>
<tr>
<td id="file-tabgroup-js-L22" class="blob-num js-line-number js-blob-rnum" data-line-number="22"></td>
<td id="file-tabgroup-js-LC22" class="blob-code blob-code-inner js-file-line">		icon:&#39;KS_nav_ui.png&#39;</td>
</tr>
<tr>
<td id="file-tabgroup-js-L23" class="blob-num js-line-number js-blob-rnum" data-line-number="23"></td>
<td id="file-tabgroup-js-LC23" class="blob-code blob-code-inner js-file-line">	});</td>
</tr>
<tr>
<td id="file-tabgroup-js-L24" class="blob-num js-line-number js-blob-rnum" data-line-number="24"></td>
<td id="file-tabgroup-js-LC24" class="blob-code blob-code-inner js-file-line">	</td>
</tr>
<tr>
<td id="file-tabgroup-js-L25" class="blob-num js-line-number js-blob-rnum" data-line-number="25"></td>
<td id="file-tabgroup-js-LC25" class="blob-code blob-code-inner js-file-line">	var tab2 = Ti.UI.createTab({</td>
</tr>
<tr>
<td id="file-tabgroup-js-L26" class="blob-num js-line-number js-blob-rnum" data-line-number="26"></td>
<td id="file-tabgroup-js-LC26" class="blob-code blob-code-inner js-file-line">		window:  win2,</td>
</tr>
<tr>
<td id="file-tabgroup-js-L27" class="blob-num js-line-number js-blob-rnum" data-line-number="27"></td>
<td id="file-tabgroup-js-LC27" class="blob-code blob-code-inner js-file-line">		title:&#39;Window 2&#39;,</td>
</tr>
<tr>
<td id="file-tabgroup-js-L28" class="blob-num js-line-number js-blob-rnum" data-line-number="28"></td>
<td id="file-tabgroup-js-LC28" class="blob-code blob-code-inner js-file-line">		icon:&#39;KS_nav_views.png&#39;</td>
</tr>
<tr>
<td id="file-tabgroup-js-L29" class="blob-num js-line-number js-blob-rnum" data-line-number="29"></td>
<td id="file-tabgroup-js-LC29" class="blob-code blob-code-inner js-file-line">	});</td>
</tr>
<tr>
<td id="file-tabgroup-js-L30" class="blob-num js-line-number js-blob-rnum" data-line-number="30"></td>
<td id="file-tabgroup-js-LC30" class="blob-code blob-code-inner js-file-line">	</td>
</tr>
<tr>
<td id="file-tabgroup-js-L31" class="blob-num js-line-number js-blob-rnum" data-line-number="31"></td>
<td id="file-tabgroup-js-LC31" class="blob-code blob-code-inner js-file-line">	var tab3 = Ti.UI.createTab({</td>
</tr>
<tr>
<td id="file-tabgroup-js-L32" class="blob-num js-line-number js-blob-rnum" data-line-number="32"></td>
<td id="file-tabgroup-js-LC32" class="blob-code blob-code-inner js-file-line">		window:  win3,</td>
</tr>
<tr>
<td id="file-tabgroup-js-L33" class="blob-num js-line-number js-blob-rnum" data-line-number="33"></td>
<td id="file-tabgroup-js-LC33" class="blob-code blob-code-inner js-file-line">		title:&#39;Window 3&#39;,</td>
</tr>
<tr>
<td id="file-tabgroup-js-L34" class="blob-num js-line-number js-blob-rnum" data-line-number="34"></td>
<td id="file-tabgroup-js-LC34" class="blob-code blob-code-inner js-file-line">		icon:&#39;KS_nav_ui.png&#39;,</td>
</tr>
<tr>
<td id="file-tabgroup-js-L35" class="blob-num js-line-number js-blob-rnum" data-line-number="35"></td>
<td id="file-tabgroup-js-LC35" class="blob-code blob-code-inner js-file-line">	});</td>
</tr>
<tr>
<td id="file-tabgroup-js-L36" class="blob-num js-line-number js-blob-rnum" data-line-number="36"></td>
<td id="file-tabgroup-js-LC36" class="blob-code blob-code-inner js-file-line">	</td>
</tr>
<tr>
<td id="file-tabgroup-js-L37" class="blob-num js-line-number js-blob-rnum" data-line-number="37"></td>
<td id="file-tabgroup-js-LC37" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-tabgroup-js-L38" class="blob-num js-line-number js-blob-rnum" data-line-number="38"></td>
<td id="file-tabgroup-js-LC38" class="blob-code blob-code-inner js-file-line">	tabGroup.addTab(tab1);</td>
</tr>
<tr>
<td id="file-tabgroup-js-L39" class="blob-num js-line-number js-blob-rnum" data-line-number="39"></td>
<td id="file-tabgroup-js-LC39" class="blob-code blob-code-inner js-file-line">	tabGroup.addTab(tab2);</td>
</tr>
<tr>
<td id="file-tabgroup-js-L40" class="blob-num js-line-number js-blob-rnum" data-line-number="40"></td>
<td id="file-tabgroup-js-LC40" class="blob-code blob-code-inner js-file-line">	tabGroup.addTab(tab3);</td>
</tr>
<tr>
<td id="file-tabgroup-js-L41" class="blob-num js-line-number js-blob-rnum" data-line-number="41"></td>
<td id="file-tabgroup-js-LC41" class="blob-code blob-code-inner js-file-line">		</td>
</tr>
<tr>
<td id="file-tabgroup-js-L42" class="blob-num js-line-number js-blob-rnum" data-line-number="42"></td>
<td id="file-tabgroup-js-LC42" class="blob-code blob-code-inner js-file-line">	</td>
</tr>
<tr>
<td id="file-tabgroup-js-L43" class="blob-num js-line-number js-blob-rnum" data-line-number="43"></td>
<td id="file-tabgroup-js-LC43" class="blob-code blob-code-inner js-file-line">	return tabGroup;</td>
</tr>
<tr>
<td id="file-tabgroup-js-L44" class="blob-num js-line-number js-blob-rnum" data-line-number="44"></td>
<td id="file-tabgroup-js-LC44" class="blob-code blob-code-inner js-file-line">};</td>
</tr>
</table>
</div></div>
</p></div>
</div></div>
<div class="gist-meta">
        <a href="https://gist.github.com/jaraen/3331472/raw/f4dfee80acfc139e396e44e60397f8c67818b914/TabGroup.js" style="float:right" class="Link--inTextBlock">view raw</a><br />
        <a href="https://gist.github.com/jaraen/3331472#file-tabgroup-js" class="Link--inTextBlock"><br />
          TabGroup.js<br />
        </a><br />
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
</p></div>
</div>
<p>En este caso, declaro las tres ventanas que voy a necesitar en el proyecto (líneas 3-5) y defino el módulo en sí mismo con module.exports. Cada ventana Window1, Window2 y Window3 tiene un fichero .js donde se implementa su código. Más abajo muestro su contenido.</p>
<p>Línea 10, creo el tabGroup de titanium. Líneas 12-16 creo <strong>una instancia</strong> de cada una de las ventanas, líneas 19-40, creo los tabs del tabGroup, asigno las ventanas, títulos e iconos y finalmente devuelvo el tabGroup con todo listo para ser abierto.</p>
<p>&nbsp;</p>
<h4>app/ui/Window1.js</h4>
<p>Las tres ventanas son prácticamente iguales, así que sólo explico la primera.</p>
<div id="gist3331472" class="gist">
<div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
<div class="gist-data">
<div class="js-gist-file-update-container js-task-list-container">
<div id="file-window1-js" class="file my-2">
<div itemprop="text"
      class="Box-body p-0 blob-wrapper data type-javascript  "
      style="overflow: auto" tabindex="0" role="region"
      aria-label="Window1.js content, created by jaraen on 11:24AM on August 12, 2012."
    ></p>
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">
<p>  <template class="js-file-alert-template"></p>
<div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"></p>
<path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg><br />
    <span><br />
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.<br />
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a><br />
    </span></p>
<div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters<br />
</a>
</div>
</div>
<p></template><br />
<template class="js-line-alert-template"><br />
  <span aria-label="This line has hidden Unicode characters" data-view-component="true" class="line-alert tooltipped tooltipped-e"><br />
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"></p>
<path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg><br />
</span></template></p>
<table data-hpc class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip data-tagsearch-path="Window1.js">
<tr>
<td id="file-window1-js-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
<td id="file-window1-js-LC1" class="blob-code blob-code-inner js-file-line">module.exports = function(){</td>
</tr>
<tr>
<td id="file-window1-js-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
<td id="file-window1-js-LC2" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-window1-js-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
<td id="file-window1-js-LC3" class="blob-code blob-code-inner js-file-line">	var win = Ti.UI.createWindow({</td>
</tr>
<tr>
<td id="file-window1-js-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
<td id="file-window1-js-LC4" class="blob-code blob-code-inner js-file-line">		backgroundColor:&#39;#fff&#39;,</td>
</tr>
<tr>
<td id="file-window1-js-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
<td id="file-window1-js-LC5" class="blob-code blob-code-inner js-file-line">		title: &#39;win 1&#39;</td>
</tr>
<tr>
<td id="file-window1-js-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
<td id="file-window1-js-LC6" class="blob-code blob-code-inner js-file-line">	});</td>
</tr>
<tr>
<td id="file-window1-js-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
<td id="file-window1-js-LC7" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-window1-js-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
<td id="file-window1-js-LC8" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-window1-js-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
<td id="file-window1-js-LC9" class="blob-code blob-code-inner js-file-line">	var lbl = Ti.UI.createLabel({</td>
</tr>
<tr>
<td id="file-window1-js-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
<td id="file-window1-js-LC10" class="blob-code blob-code-inner js-file-line">		text:&#39;This is Window 1&#39;,</td>
</tr>
<tr>
<td id="file-window1-js-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
<td id="file-window1-js-LC11" class="blob-code blob-code-inner js-file-line">		color:&#39;#333&#39;</td>
</tr>
<tr>
<td id="file-window1-js-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
<td id="file-window1-js-LC12" class="blob-code blob-code-inner js-file-line">	});</td>
</tr>
<tr>
<td id="file-window1-js-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
<td id="file-window1-js-LC13" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-window1-js-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
<td id="file-window1-js-LC14" class="blob-code blob-code-inner js-file-line">	win.add(lbl);</td>
</tr>
<tr>
<td id="file-window1-js-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
<td id="file-window1-js-LC15" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-window1-js-L16" class="blob-num js-line-number js-blob-rnum" data-line-number="16"></td>
<td id="file-window1-js-LC16" class="blob-code blob-code-inner js-file-line">	return win;</td>
</tr>
<tr>
<td id="file-window1-js-L17" class="blob-num js-line-number js-blob-rnum" data-line-number="17"></td>
<td id="file-window1-js-LC17" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-window1-js-L18" class="blob-num js-line-number js-blob-rnum" data-line-number="18"></td>
<td id="file-window1-js-LC18" class="blob-code blob-code-inner js-file-line">}</td>
</tr>
</table>
</div></div>
</p></div>
</div></div>
<div class="gist-meta">
        <a href="https://gist.github.com/jaraen/3331472/raw/f4dfee80acfc139e396e44e60397f8c67818b914/Window1.js" style="float:right" class="Link--inTextBlock">view raw</a><br />
        <a href="https://gist.github.com/jaraen/3331472#file-window1-js" class="Link--inTextBlock"><br />
          Window1.js<br />
        </a><br />
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
</p></div>
</div>
<p>Es una ventana muy sencilla con una etiqueta. Como este módulo no tiene dependencias externas, no necesito llamar a ModulePaths ni ningún otro módulo. Simplemente crea una ventana de Titanium, le añade una etiqueta y devuelve la ventana.</p>
<p>Una de las ventajas de programar de esta manera, es que este módulo no se preocupa de cómo va a ser usado o por quién. En este caso, Window1 es instanciado por TabGroup en su línea 12, pero perfectamente nos la podríamos llevar a otro proyecto y reutilizarla sin a penas cambios.</p>
<h4>ModulePaths.js</h4>
<p>Como decía antes, el uso de un fichero índice de todos los ficheros del proyecto no es obligatorio. Perfectamente podríamos haber llamado cada ventana por su senda en TabGroup de este modo</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> Window1 <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/app/ui/Window1'</span><span style="color: #009900;">&#41;</span></div></td></tr></tbody></table></div>
<p>Sin embargo el uso de ModulePaths tiene varias ventajas.</p>
<p>Primero, que a medida que nuestro proyecto crezca, no necesitaremos recordar todas las sendas y nombres de archivo, sólo un identificador que asignaremos a cada módulo.</p>
<p>Segundo, que en proyectos complejos, podremos cambiar una versión de un fichero por otra, simplemente cambiando el nombre en ModulePaths. Por ejemplo, si tenemos un componente llamado VideoPlayer y queremos hacer pruebas con un fichero distinto sin modificar todo el proyecto, cambiaremos la senda en ModulePaths a un fichero nuevo (por ejemplo, VideoPlayerTest.js) y todo el proyecto cogerá esta referencia.</p>
<p>Tercero, más de una vez ocurre que hay que cambiar la estructura de carpetas de un proyecto. Si esto ocurriera, podemos mover los ficheros tranquilamente y después tan sólo tenemos que actualizar este fichero, y no cada módulo del proyecto.</p>
<p>Una última ventaja, si piensas desarrollar para mobile web, es que las sendas en esta plataforma no pueden empezar con la barra /, cosa que sí ocurre en el resto de plataformas. Trabajando con ModulePaths, podemos gestionar fácilmente estas diferencias.</p>
<div id="gist3331472" class="gist">
<div class="gist-file" translate="no" data-color-mode="light" data-light-theme="light">
<div class="gist-data">
<div class="js-gist-file-update-container js-task-list-container">
<div id="file-modulepaths-js" class="file my-2">
<div itemprop="text"
      class="Box-body p-0 blob-wrapper data type-javascript  "
      style="overflow: auto" tabindex="0" role="region"
      aria-label="ModulePaths.js content, created by jaraen on 11:24AM on August 12, 2012."
    ></p>
<div class="js-check-hidden-unicode js-blob-code-container blob-code-content">
<p>  <template class="js-file-alert-template"></p>
<div data-view-component="true" class="flash flash-warn flash-full d-flex flex-items-center">
  <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"></p>
<path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg><br />
    <span><br />
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.<br />
      <a class="Link--inTextBlock" href="https://github.co/hiddenchars" target="_blank">Learn more about bidirectional Unicode characters</a><br />
    </span></p>
<div data-view-component="true" class="flash-action">        <a href="{{ revealButtonHref }}" data-view-component="true" class="btn-sm btn">    Show hidden characters<br />
</a>
</div>
</div>
<p></template><br />
<template class="js-line-alert-template"><br />
  <span aria-label="This line has hidden Unicode characters" data-view-component="true" class="line-alert tooltipped tooltipped-e"><br />
    <svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert"></p>
<path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg><br />
</span></template></p>
<table data-hpc class="highlight tab-size js-file-line-container" data-tab-size="4" data-paste-markdown-skip data-tagsearch-path="ModulePaths.js">
<tr>
<td id="file-modulepaths-js-L1" class="blob-num js-line-number js-blob-rnum" data-line-number="1"></td>
<td id="file-modulepaths-js-LC1" class="blob-code blob-code-inner js-file-line">//avoid initial slash in paths under mobileweb platform</td>
</tr>
<tr>
<td id="file-modulepaths-js-L2" class="blob-num js-line-number js-blob-rnum" data-line-number="2"></td>
<td id="file-modulepaths-js-LC2" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-modulepaths-js-L3" class="blob-num js-line-number js-blob-rnum" data-line-number="3"></td>
<td id="file-modulepaths-js-LC3" class="blob-code blob-code-inner js-file-line">var firstSeparator = (Ti.Platform.name === &#39;mobileweb&#39;) ? &#39;&#39; : &#39;/&#39;;</td>
</tr>
<tr>
<td id="file-modulepaths-js-L4" class="blob-num js-line-number js-blob-rnum" data-line-number="4"></td>
<td id="file-modulepaths-js-LC4" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-modulepaths-js-L5" class="blob-num js-line-number js-blob-rnum" data-line-number="5"></td>
<td id="file-modulepaths-js-LC5" class="blob-code blob-code-inner js-file-line">var ui = firstSeparator + &#39;app/ui/&#39;;</td>
</tr>
<tr>
<td id="file-modulepaths-js-L6" class="blob-num js-line-number js-blob-rnum" data-line-number="6"></td>
<td id="file-modulepaths-js-LC6" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-modulepaths-js-L7" class="blob-num js-line-number js-blob-rnum" data-line-number="7"></td>
<td id="file-modulepaths-js-LC7" class="blob-code blob-code-inner js-file-line">module.exports = {</td>
</tr>
<tr>
<td id="file-modulepaths-js-L8" class="blob-num js-line-number js-blob-rnum" data-line-number="8"></td>
<td id="file-modulepaths-js-LC8" class="blob-code blob-code-inner js-file-line">	TABGROUP: ui + &#39;TabGroup&#39;,</td>
</tr>
<tr>
<td id="file-modulepaths-js-L9" class="blob-num js-line-number js-blob-rnum" data-line-number="9"></td>
<td id="file-modulepaths-js-LC9" class="blob-code blob-code-inner js-file-line">	WINDOW1:  ui + &#39;Window1&#39;,</td>
</tr>
<tr>
<td id="file-modulepaths-js-L10" class="blob-num js-line-number js-blob-rnum" data-line-number="10"></td>
<td id="file-modulepaths-js-LC10" class="blob-code blob-code-inner js-file-line">	WINDOW2:  ui + &#39;Window2&#39;,</td>
</tr>
<tr>
<td id="file-modulepaths-js-L11" class="blob-num js-line-number js-blob-rnum" data-line-number="11"></td>
<td id="file-modulepaths-js-LC11" class="blob-code blob-code-inner js-file-line">	WINDOW3:  ui + &#39;Window3&#39;,</td>
</tr>
<tr>
<td id="file-modulepaths-js-L12" class="blob-num js-line-number js-blob-rnum" data-line-number="12"></td>
<td id="file-modulepaths-js-LC12" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-modulepaths-js-L13" class="blob-num js-line-number js-blob-rnum" data-line-number="13"></td>
<td id="file-modulepaths-js-LC13" class="blob-code blob-code-inner js-file-line">	STYLES: ui + &#39;Styles&#39;</td>
</tr>
<tr>
<td id="file-modulepaths-js-L14" class="blob-num js-line-number js-blob-rnum" data-line-number="14"></td>
<td id="file-modulepaths-js-LC14" class="blob-code blob-code-inner js-file-line">
</td>
</tr>
<tr>
<td id="file-modulepaths-js-L15" class="blob-num js-line-number js-blob-rnum" data-line-number="15"></td>
<td id="file-modulepaths-js-LC15" class="blob-code blob-code-inner js-file-line">}</td>
</tr>
</table>
</div></div>
</p></div>
</div></div>
<div class="gist-meta">
        <a href="https://gist.github.com/jaraen/3331472/raw/f4dfee80acfc139e396e44e60397f8c67818b914/ModulePaths.js" style="float:right" class="Link--inTextBlock">view raw</a><br />
        <a href="https://gist.github.com/jaraen/3331472#file-modulepaths-js" class="Link--inTextBlock"><br />
          ModulePaths.js<br />
        </a><br />
        hosted with &#10084; by <a class="Link--inTextBlock" href="https://github.com">GitHub</a>
      </div>
</p></div>
</div>
<p>Como ves, el fichero únicamente asigna una senda a una clave que después es la que llamamos desde los módulos (por ejemplo Mods.WINDOW1 o Mods.TABGROUP).</p>
<h4>Y para terminar&#8230;</h4>
<p>Te recomiendo que vuelvas al código de app.js y vuelvas a leerlo desde el principio, ahora que ya sabes lo que contiene cada módulo te resultará más fácil entenderlo. El objetivo es dividir el código en partes funcionales lo más pequeñas posibles, lo que te permitirá crear código que reutilizarás con más facilidad en tus proyectos y mejorarán cuanto más los uses.</p>
<p>Y esto es todo! Puedes descargar el proyecto completo desde mi github en <a href="https://github.com/jaraen/TabGroupTemplate" target="_blank">https://github.com/jaraen/TabGroupTemplate</a></p>
<p>&nbsp;</p>
<div id="attachment_551" style="width: 310px" class="wp-caption aligncenter"><a href="http://www.criteriastudio.com/wp-content/uploads/2012/08/Captura-de-pantalla-2012-08-12-a-las-13.51.07.png"><img class="size-medium wp-image-551" title="App funcionando en el simulador de android" src="http://www.criteriastudio.com/wp-content/uploads/2012/08/Captura-de-pantalla-2012-08-12-a-las-13.51.07-300x226.png" alt="" width="300" height="226" /></a>
<p class="wp-caption-text">App funcionando en el simulador de android</p>
</div>
<p>&nbsp;</p>
<div id="attachment_550" style="width: 169px" class="wp-caption aligncenter"><a href="http://www.criteriastudio.com/wp-content/uploads/2012/08/Captura-de-pantalla-2012-08-12-a-las-13.49.51.png"><img class="size-medium wp-image-550" title="App funcionando en el simulador de iPhone" src="http://www.criteriastudio.com/wp-content/uploads/2012/08/Captura-de-pantalla-2012-08-12-a-las-13.49.51-159x300.png" alt="" width="159" height="300" /></a>
<p class="wp-caption-text">App funcionando en el simulador de iPhone</p>
</div>
<div id="attachment_552" style="width: 218px" class="wp-caption aligncenter"><a href="http://www.criteriastudio.com/wp-content/uploads/2012/08/Captura-de-pantalla-2012-08-12-a-las-13.52.02.png"><img class="size-medium wp-image-552" title="App funcionando en el navegador" src="http://www.criteriastudio.com/wp-content/uploads/2012/08/Captura-de-pantalla-2012-08-12-a-las-13.52.02-208x300.png" alt="" width="208" height="300" /></a>
<p class="wp-caption-text">App funcionando en el navegador</p>
</div>
]]></content:encoded>
			<wfw:commentRss>https://www.criteriastudio.com/app-template-para-titanium/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>CommonJS para Titanium</title>
		<link>https://www.criteriastudio.com/commonjs-para-titanium/</link>
		<comments>https://www.criteriastudio.com/commonjs-para-titanium/#comments</comments>
		<pubDate>Wed, 11 Jul 2012 12:19:11 +0000</pubDate>
		<dc:creator><![CDATA[J. Rayon]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[commonJS]]></category>
		<category><![CDATA[componentes]]></category>
		<category><![CDATA[titanium]]></category>

		<guid isPermaLink="false">http://www.criteriastudio.com/?p=404</guid>
		<description><![CDATA[CommonJS es un estandar de facto que permite encapsular código JavaScript en &#8220;módulos&#8221; que utilizaremos para crear nuestros propios componentes y librerías. Con encapsular me refiero a la habilidad de crear una &#8220;burbuja&#8221; con código que tiene su propio ámbito de variables, de manera que ninguna de las que definamos en su interior contamina el [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>CommonJS es un estandar de facto que permite encapsular código JavaScript en &#8220;módulos&#8221; que utilizaremos para crear nuestros propios componentes y librerías.</p>
<p>Con encapsular me refiero a la habilidad de crear una &#8220;burbuja&#8221; con código que tiene su propio ámbito de variables, de manera que ninguna de las que definamos en su interior contamina el ámbito global. En <a href="http://www.criteriastudio.com/javascript-para-titanium-i/">otro artículo</a> hago una breve explicación de porqué es malo contaminar el ámbito global y como evitarlo. commonJS supone un nivel más de control sobre el ámbito de las variables.</p>
<p>El programador define el interfaz del módulo (las funciones y variables &#8220;públicas&#8221; a las que se podrá acceder desde fuera), de modo que para usarlo sólo tendremos que preocuparnos por conocer este interfaz y no lo que ocurre en su interior.</p>
<p>El buen uso de los módulos CommonJS facilita la reutilización de componentes entre proyectos, hace la trazabilidad más sencilla y obliga a estudiar mejor la interdependencia entre partes del proyecto.</p>
<blockquote><p>Antes de continuar, si no sabes cómo se crean los objetos en JavaScript o quieres dar un repaso a las principales peculiaridades del lenguaje, echa un vistazo a los dos tutoriales de introducción a JavaScript para Titanium. Están aquí: <a href="http://www.criteriastudio.com/javascript-para-titanium-i/">1</a> y <a href="http://www.criteriastudio.com/javascript-para-titanium-ii/">2</a></p></blockquote>
<h4>¿Que pinta tiene un modulo commonJS?</h4>
<p>Se trata de un fichero JavaScript (.js) en el que encontraremos una serie de funciones y variables y un objeto especial llamado  <code class="codecolorer text mac-classic"><span class="text">exports</span></code> (no hay que definirlo, ya existe <em>per sé</em>).</p>
<p>Dentro del módulo pondremos todo nuestro código, pero sólo el que sea añadido a <code class="codecolorer text mac-classic"><span class="text">exports</span></code> será accesible desde fuera.<br />
<strong></strong></p>
<p><strong>TestModule.js:</strong></p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">//Estas variables están disponibles en el módulo, pero no fuera de él</span><br />
<span style="color: #003366; font-weight: bold;">var</span> variablePrivada1<span style="color: #339933;">,</span> varPrivada2<span style="color: #339933;">,</span> varPrivada3<span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//este método sólo es visible dentro del fichero .js</span><br />
<span style="color: #003366; font-weight: bold;">function</span> metodoPrivado<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//este método es visible dentro y fuera del fichero</span><br />
<span style="color: #006600; font-style: italic;">//por ser declarado como parte de exports</span><br />
exports.<span style="color: #660066;">metodoPublico</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
exports.<span style="color: #660066;">saluda</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'hola'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Podemos convertir un método de privado a público añadiéndolo a exports</span><br />
<span style="color: #006600; font-style: italic;">//Ojo, no ponemos parentesis, ya que lo que devuelve no es el resultado de metodoPrivado, si no la función en sí</span><br />
<br />
exports.<span style="color: #660066;">metodoYaNoEsPrivado</span> <span style="color: #339933;">=</span> metodoPrivado<span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Y lo mismo con una propiedad</span><br />
<br />
exports.<span style="color: #660066;">propiedadPublica</span> <span style="color: #339933;">=</span> variablePrivada1<span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<h4>Ciclo de ejecución</h4>
<p>Un aspecto importante a tener en cuenta es que un módulo commonJS sólo se interpreta la primera vez que es invocado. Esto implica varias cosas:</p>
<p>- Primero, que la carga de los distintos módulos se retrasa hasta que son necesarios, lo que hace que el arranque inicial suela ser más rápido</p>
<p>- Segundo y más importante: las variables que se declaren fuera de cualquier función del módulo tendrán un comportamiento estático (en el ejemplo, anterior, las declaradas en la línea 2). Solo se inicializan la primera vez y el resto de veces que invocamos al módulo no se inicializan de nuevo, conservando su último valor asignado. Aunque esto puede ser confuso al principio, es tremendamente útil a la hora de compartir información entre distintas partes del proyecto sin necesidad de usar variables globales.</p>
<h4>Llamada desde Titanium</h4>
<p>Para cargar un módulo commonJS desde Titanium utilizamos la orden <code class="codecolorer text mac-classic"><span class="text">require()</span></code></p>
<p>Dado un fichero  <code class="codecolorer text mac-classic"><span class="text">TestModule.js</span></code> que se encuentre en el raíz de nuestro proyecto (en la carpeta resources), lo cargaremos así (ojo, <strong>al hacer require no se pone la extensión del fichero</strong>)</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> myTestModule <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'/TestModule'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Podemos consultar una propiedad del módulo</span><br />
<br />
Ti.<span style="color: #660066;">API</span>.<span style="color: #660066;">info</span><span style="color: #009900;">&#40;</span>myTestModule.<span style="color: #660066;">propiedadPublica</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//y ejecutar sus métodos públicos</span><br />
<br />
myTestModule.<span style="color: #660066;">saluda</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Esta orden carga el módulo en una variable cuyo nombre, en este caso &#8216;myTestModule&#8217;, lo asignamos a nuestra conveniencia. Una vez cargado, myTestModule contiene el objeto <code class="codecolorer text mac-classic"><span class="text">exports</span></code> que hemos ido implementando en la definición del módulo.</p>
<h4>Patrones de uso</h4>
<p>Existen varios patrones de uso de los módulos commonJS que se repiten confrecuencia en Titanium y conviene conocer desde un principio. Comentaré dos de ellos que usaré a menudo en próximos artículos.</p>
<p><strong>Un Componente instanciable (o sea, reusable)</strong></p>
<p>Una instancia es una copia de un objeto que tiene su propio ciclo de vida. Esto permite que varias instancias puedan sobrevivir simultáneamente con ciclos de vida diferentes e incluso con comportamientos diferentes sin depender necesariamente una de otra. Ejemplos de instancias son la mayoría de componentes UI de Titanium: un botón, un label, una ventana&#8230; En este caso, querremos que cada instancia del objeto no colisiones con el resto.</p>
<p>Supongamos que queremos crear un componente propio que extienda de uno existente. Lo &#8220;envolveremos&#8221; en un módulo commonJS, añadiéndole las nuevas funcionalidades. Como ejemplo, vamos a crear un botón especial con dos estados, de manera que su color cambie cada vez que se pulsa el botón:</p>
<p>SwitchButton.js:</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">module.<span style="color: #660066;">exports</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//inicializa args para asegurarse que existe</span><br />
<span style="color: #003366; font-weight: bold;">var</span> args <span style="color: #339933;">=</span> args <span style="color: #339933;">||</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
args.<span style="color: #660066;">colorOn</span> <span style="color: #339933;">=</span> args.<span style="color: #660066;">colorOn</span> <span style="color: #339933;">||</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//si no se ha definido colorOn, asigna ''</span><br />
args.<span style="color: #660066;">colorOff</span> <span style="color: #339933;">=</span> args.<span style="color: #660066;">colorOff</span> <span style="color: #339933;">||</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Creamos el botón nativo de Titanium</span><br />
<span style="color: #003366; font-weight: bold;">var</span> btn <span style="color: #339933;">=</span> Ti.<span style="color: #660066;">UI</span>.<span style="color: #660066;">createButton</span><span style="color: #009900;">&#40;</span>args<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//quitamos la imagen de fondo, en iOS es necesario para ver bien el color</span><br />
btn.<span style="color: #660066;">backgroundImage</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'transparent'</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//método privado que determina la imagen de fondo del botón</span><br />
<span style="color: #003366; font-weight: bold;">function</span> setColor<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
btn.<span style="color: #660066;">backgroundColor</span> <span style="color: #339933;">=</span> btn.<span style="color: #660066;">value</span> <span style="color: #339933;">?</span> btn.<span style="color: #660066;">colorOn</span> <span style="color: #339933;">:</span> btn.<span style="color: #660066;">colorOff</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//al hacer click, cambia la imagen</span><br />
btn.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
btn.<span style="color: #660066;">value</span> <span style="color: #339933;">=</span> <span style="color: #339933;">!</span>btn.<span style="color: #660066;">value</span><span style="color: #339933;">;</span><br />
setColor<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//inicializa la imagen del botón</span><br />
setColor<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000066; font-weight: bold;">return</span> btn<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Para utilizar nuestro componente en Titanium, deberemos crearlo con el operador <code class="codecolorer text mac-classic"><span class="text">new</span></code></p>
<p>app.js:</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> win <span style="color: #339933;">=</span> Ti.<span style="color: #660066;">UI</span>.<span style="color: #660066;">createWindow</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Cargamos el módulo en un objeto &quot;Clase&quot;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> SwitchButton <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'SwitchButton'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//creamos nuestra instancia de la clase SwitchButton:</span><br />
<span style="color: #003366; font-weight: bold;">var</span> btn <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> SwitchButton<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
width<span style="color: #339933;">:</span><span style="color: #CC0000;">180</span><span style="color: #339933;">,</span> height<span style="color: #339933;">:</span><span style="color: #CC0000;">35</span><span style="color: #339933;">,</span> title<span style="color: #339933;">:</span><span style="color: #3366CC;">'hazme click!'</span><span style="color: #339933;">,</span><br />
colorOn<span style="color: #339933;">:</span> <span style="color: #3366CC;">'#fff'</span><span style="color: #339933;">,</span><br />
colorOff<span style="color: #339933;">:</span><span style="color: #3366CC;">'#999'</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
win.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span>btn<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
win.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Con esta técnica, podríamos añadir tantos botones como fueran necesarios, cada uno con sus características de tamaño y color y cada uno con sus propios addEventListeners.</p>
<p>Tienes un ejemplo más avanzado de SwitchButton usando imágenes de fondo y disparando un evento propio en mi proyecto <a title="SwitchButton en TitanTricks" href="https://github.com/jaraen/TitanTricks/blob/master/Resources/app/ui/components/SwitchButton.js" target="_blank">TitanTricks</a></p>
<p><strong>Patrón de configuración</strong></p>
<p>A menudo ocurre que distintas partes de la aplicación deben compartir una serie de datos &#8220;estáticos&#8221; sobre la aplicación. Cosas como el nombre de la app, la url de un servicio web al que debe acceder o distintas configuraciones de estilo.</p>
<p>Config.js</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> config <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'miApp'</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">//nombre de la aplicacion</span><br />
<br />
autoPlay<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">//iniciar video automáticamente</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Start and finish paths with a slash '/'</span><br />
photosPath<span style="color: #339933;">:</span> <span style="color: #3366CC;">'/content/photos/'</span><span style="color: #339933;">,</span><br />
<br />
imagesPath<span style="color: #339933;">:</span> <span style="color: #3366CC;">'/content/imgs/'</span><span style="color: #339933;">,</span><br />
<br />
songsPath<span style="color: #339933;">:</span> <span style="color: #3366CC;">'/content/audio/'</span><span style="color: #339933;">,</span><br />
<br />
serverUrl<span style="color: #339933;">:</span> <span style="color: #3366CC;">'http://www.myserver.com/webservice.php'</span><br />
<br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//decimos al módulo que el objeto exports es igual al objeto config</span><br />
module.<span style="color: #660066;">exports</span> <span style="color: #339933;">=</span> config<span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Como puedes ver, en vez de extender <code class="codecolorer text mac-classic"><span class="text">exports</span></code> con una propiedad config, en este caso directamente asignamos config al módulo. Esta técnica es igual de válida que la de extender <code class="codecolorer text mac-classic"><span class="text">exports</span></code>. Lo único que no debes hacer nunca dentro de un mismo módulo es mezclar ambas técnicas: o extiendes <code class="codecolorer text mac-classic"><span class="text">exports</span></code> o igualas <code class="codecolorer text mac-classic"><span class="text">module.exports</span></code> a un objeto tuyo. La experiencia te dirá cuando usar una u otra, te he mostrado un ejemplo de cada caso para que te suene a la hora de diseñar tu propio módulo.</p>
<p>Ahora, en nuestra aplicación, podremos invocar al módulo Config sin necesidad de instanciarlo:</p>
<p>App.js</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> Config <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Config'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Podemos usar Config sin necesidad de instanciarlo, porque exports ya contiene las propiedades que esperamos</span><br />
<br />
<span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Bienvenido a '</span> <span style="color: #339933;">+</span> Config.<span style="color: #000066;">name</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
Ti.<span style="color: #660066;">API</span>.<span style="color: #660066;">info</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Las fotos están en '</span> <span style="color: #339933;">+</span> Config.<span style="color: #660066;">photosPath</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Este tipo de patrón también es muy útil para separar los estilos de la programación pura. Podemos tener un fichero de estilos fácilmente reutilizables y modificables al que invocar desde cualquiera de nuestros módulos. Podríamos, por ejemplo, cambiar los colores de todas las ventanas sólo con cambiar el color en este fichero.</p>
<p>Styles.js</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">//Cargamos el módulo Config en nuestro módulo Styles</span><br />
<span style="color: #003366; font-weight: bold;">var</span> Config <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Config'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
module.<span style="color: #660066;">exports</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
<br />
Window<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
<br />
backgroundColor<span style="color: #339933;">:</span><span style="color: #3366CC;">'#fff'</span><br />
<br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
LabelTitle<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
<br />
top<span style="color: #339933;">:</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> width<span style="color: #339933;">:</span>Ti.<span style="color: #660066;">UI</span>.<span style="color: #660066;">FILL</span><span style="color: #339933;">,</span> height<span style="color: #339933;">:</span> <span style="color: #CC0000;">40</span><span style="color: #339933;">,</span><br />
text<span style="color: #339933;">:</span> Config.<span style="color: #000066;">name</span><span style="color: #339933;">,</span><br />
backgroundColor<span style="color: #339933;">:</span><span style="color: #3366CC;">'#000'</span><span style="color: #339933;">,</span><br />
color<span style="color: #339933;">:</span><span style="color: #3366CC;">'#fff'</span><span style="color: #339933;">,</span><br />
font<span style="color: #339933;">:</span><span style="color: #009900;">&#123;</span>fontSize<span style="color: #339933;">:</span><span style="color: #CC0000;">24</span><span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Y ahora en App.js&#8230;</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">//Cargamos los módulos necesarios</span><br />
<span style="color: #003366; font-weight: bold;">var</span> $$ <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Styles'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> LabelTitle <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'LabelTitle'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> SwitchButton <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'SwitchButton'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> win <span style="color: #339933;">=</span> Ti.<span style="color: #660066;">UI</span>.<span style="color: #660066;">createWindow</span><span style="color: #009900;">&#40;</span>$$.<span style="color: #660066;">Window</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> lblTile <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> LabelTitle<span style="color: #009900;">&#40;</span>$$.<span style="color: #660066;">LabelTitle</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//creamos nuestra instancia de la clase SwitchButton:</span><br />
<span style="color: #003366; font-weight: bold;">var</span> btn <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> SwitchButton<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
width<span style="color: #339933;">:</span><span style="color: #CC0000;">180</span><span style="color: #339933;">,</span> height<span style="color: #339933;">:</span><span style="color: #CC0000;">35</span><span style="color: #339933;">,</span> title<span style="color: #339933;">:</span><span style="color: #3366CC;">'hazme click!'</span><span style="color: #339933;">,</span><br />
colorOn<span style="color: #339933;">:</span> <span style="color: #3366CC;">'#fff'</span><span style="color: #339933;">,</span><br />
colorOff<span style="color: #339933;">:</span><span style="color: #3366CC;">'#999'</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
win.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span>lblTitle<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
win.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span>btn<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
win.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Me gusta usar <code class="codecolorer text mac-classic"><span class="text">$$</span></code> siempre como nombre del módulo de estilos. Es fácil de recordar, rápido de escribir y recordar (manía que adquirí del estilo de programación de <a href="https://github.com/appcelerator-titans/tweetanium" target="_blank">tweetanium</a>, una app que hizo escuela en los principios de Titanium). El hecho de que sean dos símbolos $$ no tiene ninguna otra implicación como nombre de variable.</p>
<h4>Esto es to, esto es todo amigos</h4>
<p><strong></strong>Estos dos patrones  son suficientes para empezar a montar la arquitectura de la aplicación.  Por supuesto que hay más e intentaré mostrarlos en sucesivos tutoriales.</p>
<p>Mi objetivo, una vez superados los conceptos básicos de JavaScript y sabiendo qué son y cómo funcionan los módulos commonJS, es mostraros como crear una arquitectura sólida, escalable y segura para una aplicación móvil con Titanium. En la próxima entrega crearemos una plantilla para comenzar todas nuestras aplicaciones desde una base e iremos viendo como superar los distintos obstáculos que nos encontraremos en la comunicación entre componentes. Siempre, por supuesto, intentando seguir el manual de buenas prácticas.</p>
<p>En entregas posteriores, desarrollaré algunos problemas típicos de programación, como la llamada a métodos asíncronos, componentes UI avanzados, optimización de código y lo que se me vaya ocurriendo (se aceptan retos, ruegos y sugerencias).</p>
<p>Hasta entonces, os recomiendo probar y desmenuzar la app <a title="TitanTricks" href="https://github.com/jaraen/TitanTricks" target="_blank">TitanTricks</a>, un proyecto iOS+Android de demostración/experimentación con Titanium. También existe <a title="TitanTricksMobileWeb" href="https://github.com/jaraen/TitanTricksMobileWeb" target="_blank">TitanTricksMobileWeb</a>, para su versión web.</p>
<blockquote><p>¿Te interesa Titanium y JavaScript? Sígueme en <strong><a href="http://www.twitter.com/jrayon">@jrayon</a></strong></p></blockquote>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>https://www.criteriastudio.com/commonjs-para-titanium/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>JavaScript para Titanium (I)</title>
		<link>https://www.criteriastudio.com/javascript-para-titanium-i/</link>
		<comments>https://www.criteriastudio.com/javascript-para-titanium-i/#comments</comments>
		<pubDate>Fri, 06 Jul 2012 08:42:43 +0000</pubDate>
		<dc:creator><![CDATA[J. Rayon]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[básico]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[titanium]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.criteriastudio.com/?p=258</guid>
		<description><![CDATA[Si estás empezando a trabajar con Titanium, lo mejor que puedes hacer antes de embarcarte en un proyecto real es adquirir una BUENA base de JavaScript. Lo mejor y lo peor de JavaScript es que lo aguanta todo. Puedes olvidarte de declarar las variables, no usar punto y coma al final de línea y ser un [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Si estás empezando a trabajar con <a href="http://www.appcelerator.com" target="_blank">Titanium</a>, lo mejor que puedes hacer antes de embarcarte en un proyecto real es adquirir una BUENA base de JavaScript.</p>
<p>Lo mejor y lo peor de JavaScript es que lo aguanta todo. Puedes olvidarte de declarar las variables, no usar punto y coma al final de línea y ser un desastre organizando el código. Es posible que, incluso así, el código funcione. Pero pobre del que tenga que revisar tu código, incluso si eres tú mismo, cuando algo deje de funcionar.</p>
<p>No me gusta convencer a la gente de que haga cosas sólo por miedo a que algo terrible ocurra (en este caso, el miedo a que algún día nuestro código sea un desastre). Y, aunque es un argumento de peso, JavaScript tiene bastantes alicientes como para motivar su aprendizaje a fondo sin otro objetivo que crear grandes aplicaciones y aprovechar al 100% las características del lenguaje.</p>
<p>JavaScript es un gran lenguaje de programación, a menudo incomprendido, porque ha sido el lenguaje que a movido la web durante años con tantos sabores como navegadores en el mercado. Quizá por eso mi primer consejo al empezar con Titanium es olvidarse del DOM, de JQuery y cualquier otro framework y forma de programar orientada a la web. Titanium no se ejecuta en una ventana de navegador, por tanto estamos hablando de JavaScript &#8220;puro&#8221;, ampliado y mejorado con la API de titanium, desarrollada en el código nativo de cada plataforma. Por eso Titanium es único, porque realmente ejecuta código nativo, que es llamado desde el intérprete JavaScript.</p>
<p>Este artículo pretende mostrar las &#8220;mínimas&#8221; cosas que uno debe saber de JavaScript, especialmente cuando viene de trabajar con otros lenguajes.</p>
<h3>Lo mas basico</h3>
<h4>Tipos</h4>
<p>Las variables no se declaran con un tipo específico y pueden cambiar de tipo durante su vida (pueden crearse siendo string y luego asignar un valor numérico sin hacer ningún tipo de cast).</p>
<p>Las cadenas se pueden delimitar con comillas simples y dobles indistintamente. Es exactamente lo mismo.</p>
<p>La mayoría de tipos (strings, arrays, objects&#8230;) son objetos. Así, al declarar una variable string como <code class="codecolorer javascript mac-classic"><span class="javascript">&nbsp;<span style="color: #003366; font-weight: bold;">var</span> str <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;hola&quot;</span></span></code>, ya podemos hacer uso de sus métodos y propiedades. Por ejemplo <code class="codecolorer text mac-classic"><span class="text">str.length</span></code> devolverá el valor 4.</p>
<p>Para declarar cualquier tipo de variable (sea array, string o cualquier otro tipo), utilizamos la palabra <code class="codecolorer text mac-classic"><span class="text">var</span></code>. En aplicaciones como las que haremos con Titanium <strong>debemos obligarnos</strong> a declarar siempre las variables ya que, de no hacerlo, éstas se crean con alcance global (y como ya puedes intuir esto es malo, malo). Que estén en global significa que nunca se liberan de memoria y que pueden llegar a colisionar con otras variables, creando aplicaciones muy difíciles de trazar.</p>
<p>Los números en JavaScript siempre son tratados internamente en coma flotante. Las variables numéricas por defecto están &#8220;unboxed&#8221; lo que quiere decir que no podemos tratarlas como objetos. Para tratarlas como objeto crearemos con el operador <code class="codecolorer text mac-classic"><span class="text">new</span></code>. Ocurre lo mismo con los booleanos.</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">//Unboxed: valor</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> x <span style="color: #339933;">=</span> <span style="color: #CC0000;">5</span><span style="color: #339933;">;</span><br />
<br />
x.<span style="color: #660066;">foo</span> <span style="color: #339933;">=</span> ’bar’<span style="color: #339933;">;</span>   <span style="color: #006600; font-style: italic;">// Esto falla “en silencio”</span><br />
<br />
x.<span style="color: #660066;">foo</span>            <span style="color: #006600; font-style: italic;">// undefined;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Boxed: referencia</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> x <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Number <span style="color: #009900;">&#40;</span><span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
x.<span style="color: #660066;">foo</span> <span style="color: #339933;">=</span> ’bar’<span style="color: #339933;">;</span><br />
<br />
x.<span style="color: #660066;">foo</span>            <span style="color: #006600; font-style: italic;">//’bar’; x es un puntero (una referencia, no un valor)</span></div></td></tr></tbody></table></div>
<p>Los arrays son muy flexibles, puedes crear arrays mezclando distintos tipos de variables, añadir índices en cualquier posición.</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> arr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> otroArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">5</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;una cadena&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>x<span style="color: #339933;">:</span><span style="color: #CC0000;">2</span><span style="color: #339933;">,</span> y<span style="color: #339933;">:</span><span style="color: #CC0000;">10</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//puedes combinar cualquier tipo de contenido en un array</span><br />
<br />
arr<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> “hola”<span style="color: #339933;">;</span><br />
<br />
arr<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> “adiós”<span style="color: #339933;">;</span><br />
<br />
arr<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">15</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> “ciao”<span style="color: #339933;">;</span><br />
<br />
arr.<span style="color: #660066;">push</span> <span style="color: #009900;">&#40;</span>“buenos dí<span style="color: #000066; font-weight: bold;">as</span>”<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//añade al final</span><br />
<br />
arr.<span style="color: #660066;">unshift</span> <span style="color: #009900;">&#40;</span>“buenas noches”<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//añade al principio</span><br />
<br />
<span style="color: #006600; font-style: italic;">//recorre todo el array</span><br />
<br />
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> j <span style="color: #339933;">=</span> arr.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> j<span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<br />
Ti.<span style="color: #660066;">API</span>.<span style="color: #660066;">info</span><span style="color: #009900;">&#40;</span>arr<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<h4>Comparaciones</h4>
<p>Lo que en otros lenguajes se compara con <strong>==</strong> ó <strong>!=</strong> (dos caracteres) en JavaScript se hace con tres (<strong>===</strong> y <strong>!==</strong>). Este es uno de los errores de principiante más comunes al empezar con JavaScript. Así que <strong>siempre hay que utilizar el comparador ternario</strong> (el de tres caracteres), a menos que sepas lo que estás haciendo. Como ejemplo de los líos en los que nos podemos meter, en JavaScript todas las siguientes sentencias son TRUE (en la mayoría de lenguajes serían FALSE):</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">==</span><span style="color: #CC0000;">0</span><br />
<span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">==</span>’’<br />
’’<span style="color: #339933;">==</span><span style="color: #CC0000;">0</span><br />
<span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">==</span><span style="color: #CC0000;">1</span><br />
<span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">==</span>’<span style="color: #CC0000;">1</span>’<br />
’<span style="color: #CC0000;">1</span>’<span style="color: #339933;">==</span><span style="color: #CC0000;">1</span></div></td></tr></tbody></table></div>
<p>Usando la comparación === hubieran dado false como resultado, que es lo que esperaríamos en la mayoría de casos.</p>
<h4>Ambito y declaracion de variables</h4>
<p>En JavaScript <strong>el ámbito de una variable es el de la función en la que es declarada</strong>. Si la variable no se declara dentro de una función, entonces se trata de una variable global. Esto puede llegar a ser un serio problema, ya que JavaScript permite usar variables sin declarar, lo que hace que se vayan cargando siempre al ámbito global de ejecución y por tanto nunca se liberen de la memoria. ¿Cómo resolver esto?</p>
<div class="grid_8">
<ul class="ul bullet_arrow_dark">
<ul>
<li>Primero: <strong>siempre</strong> declara las variables con la palabra clave <code class="codecolorer text mac-classic"><span class="text">var</span></code>. Acostúmbrate a hacerlo. Siempre.</li>
<li>Segundo: Dado que las variables tienen como ámbito la función que la contiene, da igual que la declares dentro de un bloque if, o dentro de un bucle for o cualquier otro sitio. Esa variable <strong>siempre existe desde el principio de la función</strong> y seguirá existiendo al terminar el bloque If o el bucle for. Por tanto, es una buena idea declarar siempre las variables al comienzo de la función y no a lo largo de la misma.</li>
<li>Tercero: restringe el uso de las variables globales. Más adelante hablaremos de los módulos CommonJS como forma de organizar el código. Valga decir que SI es posible crear aplicaciones con <strong>cero variables globales</strong> y este será nuestro objetivo.</li>
<li>Cuarto: podemos usar objetos como contenedores de variables para agrupar aquellas con una utilidad común. Por ejemplo, podemos tener un objeto &#8220;config&#8221; que contenga las variables de configuraciones de la aplicación:</li>
</ul>
</ul>
</div>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> config <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
title<span style="color: #339933;">:</span><span style="color: #3366CC;">'My app'</span><span style="color: #339933;">,</span><br />
support<span style="color: #339933;">:</span><span style="color: #3366CC;">'info@myapp.com'</span><span style="color: #339933;">,</span><br />
defaultTheme<span style="color: #339933;">:</span><span style="color: #3366CC;">'white'</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>(más adelante hablaremos de los objetos en JavaScript)<br />
::</p>
<div>
<p>En muchos lenguajes el ámbito de las variables está delimitado por bloques y esperamos este comportamiento, pero en JavaScript no ocurre así. Recuérdalo cuando hagas algo como esto:</p>
<div class="codecolorer-container javascript mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:600px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">function</span> miFuncion<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//aquí i sigue existiendo y vale 10</span><br />
<br />
<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<br />
<span style="color: #003366; font-weight: bold;">var</span> j <span style="color: #339933;">=</span> <span style="color: #CC0000;">15</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Aquí j sigue existiendo y vale 15;</span><br />
<br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #006600; font-style: italic;">//Aquí no existe i ni j</span></div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<h4>Punto y coma</h4>
<p>En JavaScript no es obligatorio usar punto y coma <code class="codecolorer text mac-classic"><span class="text">;</span></code> al final de todas las sentencias.  Hay un montón de gente que le encanta discutir sobre si, siendo algo opcional, debe usarse o no.</p>
<p>Mi opinión: <strong>debe usarse siempre</strong>. Además de que no cuesta nada y que ayuda visualmente a la lectura, hay un argumento de peso. Ayuda al intérprete de JavaScript a determinar cuando ha terminado una sentencia y empieza la siguiente, lo que en casos extremos puede evitar errores muy difíciles de detectar porque el intérprete JavaScript está entendiendo algo distinto a lo que nosotros creemos que debería hacer. Usa el punto y coma. Siempre. Asunto resuelto.</p>
<p>&nbsp;</p>
<p><a title="JavaScript para Titanium (I)" href="http://www.criteriastudio.com/javascript-para-titanium-ii/">Continuar con el siguiente artículo de la serie &gt;</a><br />
</p>
<blockquote><p>¿Te interesa Titanium y JavaScript? Sígueme en <strong><a href="http://www.twitter.com/jrayon">@jrayon</a></strong></p></blockquote>
<p>
</div>
]]></content:encoded>
			<wfw:commentRss>https://www.criteriastudio.com/javascript-para-titanium-i/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>We are Titanium Developers</title>
		<link>https://www.criteriastudio.com/we-are-titanium-developers/</link>
		<comments>https://www.criteriastudio.com/we-are-titanium-developers/#comments</comments>
		<pubDate>Fri, 04 Nov 2011 22:03:53 +0000</pubDate>
		<dc:creator><![CDATA[J. Rayon]]></dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[appcelerator]]></category>
		<category><![CDATA[criteria studio]]></category>
		<category><![CDATA[mobile development]]></category>
		<category><![CDATA[titanium]]></category>

		<guid isPermaLink="false">http://www.criteriastudio.com/?p=201</guid>
		<description><![CDATA[Since our first days creating mobile solutions, we have tried a lot of technologies, such as JQuery Mobile, HTML5, phoneGap, native development&#8230; But none of them has given to us and our clients so many benefits as Titanium, from Appcelerator. And we are so convinced of this, that we have spent the last months working [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Since our first days creating mobile solutions, we have tried a lot of technologies, such as JQuery Mobile, HTML5, phoneGap, native development&#8230;</p>
<p>But none of them has given to us and our clients so many benefits as Titanium, from <a href="http://www.appcelerator.com" target="_blank">Appcelerator</a>.</p>
<p>And we are so convinced of this, that we have spent the last months working only with Titanium mobile technologies, developing iPhone, iPad and Android projects, training developers, creating <a href="https://github.com/jaraen" target="_blank">open source projects</a> and contributing to the Titanium Community. Just myself have passed the <strong>Titanium Certificate App Developer</strong> test, which credits me as a professional and expert Titanium developer. And also, I&#8217;ve become a proud Appcelerator Titan user, which is a community leader and technology evangelist.</p>
<p>At this time, our commitment with Titanium is complete. We are training two new internal developers on Titanium to increase our development capacity. We are already planning the 2012 year, because we are pretty sure that it will be a great year, plenty of success and great projects that we have already in process. And we have the confidence and satisfaction of our clients, our most valuable treasure, because their success is the only aim we care.</p>
<p><em>The only constant is change</em>, said Isaac Asimov, and survive in a so changing technological environment is only possible if you choose right your partners. For this reason, and many others, we are very proud to say that We are Titanium Developers.</p>
<p>Javier Rayon,<br />
Consultant and Lead developer at Criteria Studio</p>
<p><a href="http://www.criteriastudio.com/wp-content/uploads/2011/11/tcad_color_mini.png"><img title="Titanium Certified App Developer" src="http://www.criteriastudio.com/wp-content/uploads/2011/11/tcad_color_mini.png" alt="" width="200" height="81" /></a> <img title="Titan User" src="http://developer.appcelerator.com/assets/img/badge_titan.png" alt="" width="75" height="75" /></p>
]]></content:encoded>
			<wfw:commentRss>https://www.criteriastudio.com/we-are-titanium-developers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
