Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added 3.3 dir

  • Loading branch information...
commit fe08348d9610d3bf8535986f229d67656242b0b5 1 parent 31738ac
geremy cohen authored
Showing with 2,435 additions and 0 deletions.
  1. 0  titanium/{ → 3.1}/desktop/app.js
  2. 0  titanium/{ → 3.1}/desktop/index.html
  3. 0  titanium/{ → 3.1}/desktop/pubnub.js
  4. 0  titanium/{ → 3.1}/mobile/README
  5. 0  titanium/{ → 3.1}/mobile/app.js
  6. 0  titanium/{ → 3.1}/mobile/chat-example-app/.project
  7. 0  titanium/{ → 3.1}/mobile/chat-example-app/CHANGELOG.txt
  8. 0  titanium/{ → 3.1}/mobile/chat-example-app/LICENSE
  9. 0  titanium/{ → 3.1}/mobile/chat-example-app/LICENSE.txt
  10. 0  titanium/{ → 3.1}/mobile/chat-example-app/README
  11. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/KS_nav_ui.png
  12. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/KS_nav_views.png
  13. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/android/appicon.png
  14. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/android/default.png
  15. 0  ...tlong-land-hdpi → 3.1/mobile/chat-example-app/Resources/android/images/res-long-land-hdpi}/default.png
  16. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/android/images/res-long-land-ldpi/default.png
  17. 0  ...tlong-port-hdpi → 3.1/mobile/chat-example-app/Resources/android/images/res-long-port-hdpi}/default.png
  18. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/android/images/res-long-port-ldpi/default.png
  19. 0  ...ng-land-hdpi → 3.1/mobile/chat-example-app/Resources/android/images/res-notlong-land-hdpi}/default.png
  20. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/android/images/res-notlong-land-ldpi/default.png
  21. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/android/images/res-notlong-land-mdpi/default.png
  22. 0  ...ng-port-hdpi → 3.1/mobile/chat-example-app/Resources/android/images/res-notlong-port-hdpi}/default.png
  23. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/android/images/res-notlong-port-ldpi/default.png
  24. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/android/images/res-notlong-port-mdpi/default.png
  25. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/app.js
  26. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/iphone/Default-Landscape.png
  27. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/iphone/Default-Portrait.png
  28. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/iphone/Default.png
  29. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/iphone/Default@2x.png
  30. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/iphone/appicon.png
  31. 0  titanium/{ → 3.1}/mobile/chat-example-app/Resources/pubnub-chat.js
  32. 0  titanium/{mobile → 3.1/mobile/chat-example-app/Resources}/pubnub.js
  33. 0  titanium/{ → 3.1}/mobile/chat-example-app/manifest
  34. 0  titanium/{ → 3.1}/mobile/chat-example-app/tiapp.xml
  35. 0  titanium/{mobile/chat-example-app/Resources → 3.1/mobile}/pubnub.js
  36. +84 −0 titanium/3.3/desktop/app.js
  37. +75 −0 titanium/3.3/desktop/index.html
  38. +496 −0 titanium/3.3/desktop/pubnub.js
  39. +119 −0 titanium/3.3/mobile/README
  40. +48 −0 titanium/3.3/mobile/app.js
  41. +23 −0 titanium/3.3/mobile/chat-example-app/.project
  42. +1 −0  titanium/3.3/mobile/chat-example-app/CHANGELOG.txt
  43. +219 −0 titanium/3.3/mobile/chat-example-app/LICENSE
  44. +1 −0  titanium/3.3/mobile/chat-example-app/LICENSE.txt
  45. +18 −0 titanium/3.3/mobile/chat-example-app/README
  46. BIN  titanium/3.3/mobile/chat-example-app/Resources/KS_nav_ui.png
  47. BIN  titanium/3.3/mobile/chat-example-app/Resources/KS_nav_views.png
  48. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/appicon.png
  49. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/default.png
  50. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-long-land-hdpi/default.png
  51. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-long-land-ldpi/default.png
  52. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-long-port-hdpi/default.png
  53. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-long-port-ldpi/default.png
  54. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-land-hdpi/default.png
  55. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-land-ldpi/default.png
  56. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-land-mdpi/default.png
  57. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-port-hdpi/default.png
  58. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-port-ldpi/default.png
  59. BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-port-mdpi/default.png
  60. +26 −0 titanium/3.3/mobile/chat-example-app/Resources/app.js
  61. BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/Default-Landscape.png
  62. BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/Default-Portrait.png
  63. BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/Default.png
  64. BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/Default@2x.png
  65. BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/appicon.png
  66. +180 −0 titanium/3.3/mobile/chat-example-app/Resources/pubnub-chat.js
  67. +548 −0 titanium/3.3/mobile/chat-example-app/Resources/pubnub.js
  68. +8 −0 titanium/3.3/mobile/chat-example-app/manifest
  69. +41 −0 titanium/3.3/mobile/chat-example-app/tiapp.xml
  70. +548 −0 titanium/3.3/mobile/pubnub.js
View
0  titanium/desktop/app.js → titanium/3.1/desktop/app.js
File renamed without changes
View
0  titanium/desktop/index.html → titanium/3.1/desktop/index.html
File renamed without changes
View
0  titanium/desktop/pubnub.js → titanium/3.1/desktop/pubnub.js
File renamed without changes
View
0  titanium/mobile/README → titanium/3.1/mobile/README
File renamed without changes
View
0  titanium/mobile/app.js → titanium/3.1/mobile/app.js
File renamed without changes
View
0  titanium/mobile/chat-example-app/.project → ...nium/3.1/mobile/chat-example-app/.project
File renamed without changes
View
0  ...ium/mobile/chat-example-app/CHANGELOG.txt → ...3.1/mobile/chat-example-app/CHANGELOG.txt
File renamed without changes
View
0  titanium/mobile/chat-example-app/LICENSE → titanium/3.1/mobile/chat-example-app/LICENSE
File renamed without changes
View
0  titanium/mobile/chat-example-app/LICENSE.txt → ...m/3.1/mobile/chat-example-app/LICENSE.txt
File renamed without changes
View
0  titanium/mobile/chat-example-app/README → titanium/3.1/mobile/chat-example-app/README
File renamed without changes
View
0  .../chat-example-app/Resources/KS_nav_ui.png → .../chat-example-app/Resources/KS_nav_ui.png
File renamed without changes
View
0  ...at-example-app/Resources/KS_nav_views.png → ...at-example-app/Resources/KS_nav_views.png
File renamed without changes
View
0  ...example-app/Resources/android/appicon.png → ...example-app/Resources/android/appicon.png
File renamed without changes
View
0  ...example-app/Resources/android/default.png → ...example-app/Resources/android/default.png
File renamed without changes
View
0  .../images/res-notlong-land-hdpi/default.png → ...oid/images/res-long-land-hdpi/default.png
File renamed without changes
View
0  ...oid/images/res-long-land-ldpi/default.png → ...oid/images/res-long-land-ldpi/default.png
File renamed without changes
View
0  .../images/res-notlong-port-hdpi/default.png → ...oid/images/res-long-port-hdpi/default.png
File renamed without changes
View
0  ...oid/images/res-long-port-ldpi/default.png → ...oid/images/res-long-port-ldpi/default.png
File renamed without changes
View
0  ...oid/images/res-long-land-hdpi/default.png → .../images/res-notlong-land-hdpi/default.png
File renamed without changes
View
0  .../images/res-notlong-land-ldpi/default.png → .../images/res-notlong-land-ldpi/default.png
File renamed without changes
View
0  .../images/res-notlong-land-mdpi/default.png → .../images/res-notlong-land-mdpi/default.png
File renamed without changes
View
0  ...oid/images/res-long-port-hdpi/default.png → .../images/res-notlong-port-hdpi/default.png
File renamed without changes
View
0  .../images/res-notlong-port-ldpi/default.png → .../images/res-notlong-port-ldpi/default.png
File renamed without changes
View
0  .../images/res-notlong-port-mdpi/default.png → .../images/res-notlong-port-mdpi/default.png
File renamed without changes
View
0  .../mobile/chat-example-app/Resources/app.js → .../mobile/chat-example-app/Resources/app.js
File renamed without changes
View
0  ...pp/Resources/iphone/Default-Landscape.png → ...pp/Resources/iphone/Default-Landscape.png
File renamed without changes
View
0  ...app/Resources/iphone/Default-Portrait.png → ...app/Resources/iphone/Default-Portrait.png
File renamed without changes
View
0  ...-example-app/Resources/iphone/Default.png → ...-example-app/Resources/iphone/Default.png
File renamed without changes
View
0  ...ample-app/Resources/iphone/Default@2x.png → ...ample-app/Resources/iphone/Default@2x.png
File renamed without changes
View
0  ...-example-app/Resources/iphone/appicon.png → ...-example-app/Resources/iphone/appicon.png
File renamed without changes
View
0  ...chat-example-app/Resources/pubnub-chat.js → ...chat-example-app/Resources/pubnub-chat.js
File renamed without changes
View
0  titanium/mobile/pubnub.js → ...bile/chat-example-app/Resources/pubnub.js
File renamed without changes
View
0  titanium/mobile/chat-example-app/manifest → ...nium/3.1/mobile/chat-example-app/manifest
File renamed without changes
View
0  titanium/mobile/chat-example-app/tiapp.xml → ...ium/3.1/mobile/chat-example-app/tiapp.xml
File renamed without changes
View
0  ...bile/chat-example-app/Resources/pubnub.js → titanium/3.1/mobile/pubnub.js
File renamed without changes
View
84 titanium/3.3/desktop/app.js
@@ -0,0 +1,84 @@
+(function(){
+
+// --
+// -- DOM ELEMENT POINTERS
+// --
+var logger = PUBNUB.$('pubnub-logger')
+, publish_button = PUBNUB.$('publish-button')
+, subscribe_button = PUBNUB.$('subscribe-button')
+, subscribe_channel = PUBNUB.$('subscribe-channel')
+, publish_text = PUBNUB.$('publish-text')
+, connected = PUBNUB.$('pubnub-connected')
+, channel_name = '';
+
+
+// --
+// -- BASIC LOG OUTPUT FUNCTION
+// --
+function log(data) {
+ logger.innerHTML =
+ '\n' + log.line++ + ': ' +
+ JSON.stringify(data) + (
+ channel_name ?
+ ' - from "' + channel_name + '" Channel.' :
+ '' ) + logger.innerHTML;
+}
+log.line = 1;
+
+
+// --
+// -- SEND A MESSAGE FUNCTION
+// --
+function send_message(message) {
+ PUBNUB.publish({
+ channel : channel_name,
+ message : message
+ });
+}
+
+
+// --
+// -- LISTING FOR MESSAGES
+// --
+function listen(channel) {
+ // -- UNSUBSCRIBE FROM PREVIOUS CHANNEL
+ PUBNUB.unsubscribe({ channel : channel_name});
+
+ // -- SAVE NEW CHANNEL NAME
+ channel_name = channel || 'titanium-demo';
+
+ // -- SUBSCRIBE TO NEW CHANNEL
+ PUBNUB.subscribe({
+ channel : channel_name,
+ callback : log
+ });
+
+ // -- UPDATE CONNECTED STATUS
+ connected.innerHTML = 'CONNECTED to "' + channel_name + '"';
+ PUBNUB.css( connected, { color : "green" } );
+}
+
+
+// --
+// -- BIND SUBSCRIBE BUTTON
+// --
+PUBNUB.bind( 'mousedown,touchstart', subscribe_button, function() {
+ listen(subscribe_channel.value);
+} );
+
+
+// --
+// -- BIND PUBLISH BUTTON
+// --
+PUBNUB.bind( 'mousedown,touchstart', publish_button, function() {
+ // -- PUBLISH THE VALUE OF THE TEXTBOX INPUT
+ send_message( publish_text.value || 'EMPTY MESSAGE' );
+} );
+
+
+// --
+// -- GENERAL STARTUP COMPLETE MESSAGE
+// --
+log("Startup Complete");
+
+})();
View
75 titanium/3.3/desktop/index.html
@@ -0,0 +1,75 @@
+<html>
+<body>
+ <!-- GENERIC VANILLA STYLES -->
+ <style>
+ body, button, input, div {
+ color: #444;
+ font-family: Arial;
+ font-size: 12px;
+ line-height: 14px;
+ margin: 5px;
+ padding: 10px;
+ }
+
+ #pubnub-logger {
+ border: 2px solid #eee;
+ -webkit-box-shadow: 0 0 30px #ff0;
+ -webkit-border-radius: 10px;
+ margin: 20px;
+ padding: 10px;
+ }
+
+ #pubnub-connected {
+ color: red;
+ font-weight: bold;
+ }
+
+ button {
+ width: 150px;
+ }
+
+ input {
+ width: 200px;
+ }
+ </style>
+
+
+ <!-- SUBSCRIBE CHANNEL -->
+ <div>
+ <!-- SUBSCRIBE BUTTON -->
+ <button id=subscribe-button>SUBSCRIBE TO: </button>
+
+ <!-- CHANNEL NAME -->
+ <input id=subscribe-channel value=my-titanium-channel />
+
+ <!-- CONNECTION STATUS -->
+ <span id=pubnub-connected>NOT CONNECTED</span>
+ </div>
+
+
+ <!-- PUBLISH MESSAGE -->
+ <div>
+ <!-- PUBLISH BUTTON -->
+ <button id=publish-button>PUBLISH</button>
+
+ <!-- MESSAGE TEXT TO SEND -->
+ <input id=publish-text value=text-to-send />
+ </div>
+
+
+ <!-- LOG OUTPUT AREA -->
+ <pre id=pubnub-logger>...</pre>
+
+
+ <!-- PUBNUB SETUP -->
+ <div
+ id=pubnub
+ pub-key="demo"
+ sub-key="demo"
+ ssl="off"
+ origin="pubsub.pubnub.com"
+ ></div>
+ <script src="pubnub.js"></script>
+ <script src="app.js"></script>
+</body>
+</html>
View
496 titanium/3.3/desktop/pubnub.js
@@ -0,0 +1,496 @@
+/*
+ WAIT! - This file depends on instructions from the PUBNUB Cloud.
+
+ http://www.pubnub.com/account
+*/
+
+/*
+ PubNub Real Time Push APIs and Notifications Framework
+ Copyright (c) 2010 Stephen Blum
+ http://www.google.com/profiles/blum.stephen
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* =-=====================================================================-= */
+/* =-=====================================================================-= */
+/* =-======================== DOM UTIL ===========================-= */
+/* =-=====================================================================-= */
+/* =-=====================================================================-= */
+
+window['PUBNUB'] || (function() {
+
+/**
+ * CONSOLE COMPATIBILITY
+ */
+window.console||(window.console=window.console||{});
+console.log||(console.log=((window.opera||{}).postError||function(){}));
+
+/**
+ * UTIL LOCALS
+ */
+var NOW = 1
+, MAGIC = /\$?{([\w\-]+)}/g
+, ASYNC = 'async'
+, URLBIT = '/'
+, XHRTME = 140000
+, XORIGN = 1;
+
+/**
+ * UNIQUE
+ * ======
+ * var timestamp = unique();
+ */
+function unique() { return'x'+ ++NOW+''+(+new Date) }
+
+/**
+ * $
+ * =
+ * var div = $('divid');
+ */
+function $(id) { return document.getElementById(id) }
+
+/**
+ * LOG
+ * ===
+ * log('message');
+ */
+function log(message) { console['log'](message) }
+
+/**
+ * SEARCH
+ * ======
+ * var elements = search('a div span');
+ */
+function search(elements) {
+ var list = [];
+ each( elements.split(/\s+/), function(el) {
+ each( document.getElementsByTagName(el), function(node) {
+ list.push(node);
+ } );
+ } );
+ return list;
+}
+
+/**
+ * EACH
+ * ====
+ * each( [1,2,3], function(item) { console.log(item) } )
+ */
+function each( o, f ) {
+ if ( !o || !f ) return;
+
+ if ( typeof o[0] != 'undefined' ) for ( var i = 0, l = o.length; i < l; )
+ f.call( o[i], o[i], i++ );
+ else for ( var i in o )
+ o.hasOwnProperty &&
+ o.hasOwnProperty(i) &&
+ f.call( o[i], i, o[i] );
+}
+
+/**
+ * MAP
+ * ===
+ * var list = map( [1,2,3], function(item) { return item + 1 } )
+ */
+function map( list, fun ) {
+ var fin = [];
+ each( list || [], function( k, v ) { fin.push(fun( k, v )) } );
+ return fin;
+}
+
+/**
+ * GREP
+ * ====
+ * var list = grep( [1,2,3], function(item) { return item % 2 } )
+ */
+function grep( list, fun ) {
+ var fin = [];
+ each( list || [], function(l) { fun(l) && fin.push(l) } );
+ return fin
+}
+
+/**
+ * SUPPLANT
+ * ========
+ * var text = supplant( 'Hello {name}!', { name : 'John' } )
+ */
+function supplant( str, values ) {
+ return str.replace( MAGIC, function( _, match ) {
+ return ''+values[match] || ''
+ } );
+}
+
+/**
+ * BIND
+ * ====
+ * bind( 'keydown', search('a')[0], function(element) {
+ * console.log( element, '1st anchor' )
+ * } );
+ */
+function bind( type, el, fun ) {
+ each( type.split(','), function(etype) {
+ var rapfun = function(e) {
+ if (!e) var e = window.event;
+ if (!fun(e)) {
+ e.cancelBubble = true;
+ e.returnValue = false;
+ e.preventDefault && e.preventDefault();
+ e.stopPropagation && e.stopPropagation();
+ }
+ };
+
+ if ( el.addEventListener ) el.addEventListener( etype, rapfun, false );
+ else if ( el.attachEvent ) el.attachEvent( 'on' + etype, rapfun );
+ else el[ 'on' + etype ] = rapfun;
+ } );
+}
+
+/**
+ * UNBIND
+ * ======
+ * unbind( 'keydown', search('a')[0] );
+ */
+function unbind( type, el, fun ) {
+ if ( el.removeEventListener ) el.removeEventListener( type, false );
+ else if ( el.detachEvent ) el.detachEvent( 'on' + type, false );
+ else el[ 'on' + type ] = null;
+}
+
+/**
+ * HEAD
+ * ====
+ * head().appendChild(elm);
+ */
+function head() { return search('head')[0] }
+
+/**
+ * ATTR
+ * ====
+ * var attribute = attr( node, 'attribute' );
+ */
+function attr( node, attribute, value ) {
+ if (value) node.setAttribute( attribute, value );
+ else return node && node.getAttribute && node.getAttribute(attribute);
+}
+
+/**
+ * CSS
+ * ===
+ * var obj = create('div');
+ */
+function css( element, styles ) {
+ for (var style in styles) if (styles.hasOwnProperty(style))
+ try {element.style[style] = styles[style] + (
+ '|width|height|top|left|'.indexOf(style) > 0 &&
+ typeof styles[style] == 'number'
+ ? 'px' : ''
+ )}catch(e){}
+}
+
+/**
+ * CREATE
+ * ======
+ * var obj = create('div');
+ */
+function create(element) { return document.createElement(element) }
+
+/**
+ * timeout
+ * =======
+ * timeout( function(){}, 100 );
+ */
+function timeout( fun, wait ) { return setTimeout( fun, wait ) }
+
+/**
+ * jsonp_cb
+ * ========
+ * var callback = jsonp_cb();
+ */
+function jsonp_cb() { return XORIGN ? 0 : unique() }
+
+/**
+ * ENCODE
+ * ======
+ * var encoded_path = encode('path');
+ */
+function encode(path) {
+ return map( (''+path).split(''), function(chr) {
+ return " ~`!@#$%^&*()+=[]\\{}|;':\",./<>?".indexOf(chr) > -1 ?
+ "%"+chr.charCodeAt(0).toString(16).toUpperCase() : chr
+ } ).join('');
+}
+
+/**
+ * Titanium XHR Request
+ * ====================
+ * xdr({
+ * url : ['http://www.blah.com/url'],
+ * success : function(response) {},
+ * fail : function() {}
+ * });
+ */
+function xdr( setup ) {
+ var xhr
+ , finished = function() {
+ if (loaded) return;
+ loaded = 1;
+
+ clearTimeout(timer);
+
+ try { response = JSON['parse'](xhr.responseText); }
+ catch (r) { return done(1); }
+
+ success(response);
+ }
+ , complete = 0
+ , loaded = 0
+ , timer = timeout( function(){done(1)}, XHRTME )
+ , fail = setup.fail || function(){}
+ , success = setup.success || function(){}
+ , done = function(failed) {
+ if (complete) return;
+ complete = 1;
+
+ clearTimeout(timer);
+
+ if (xhr) {
+ xhr.onerror = xhr.onload = null;
+ xhr.abort && xhr.abort();
+ xhr = null;
+ }
+
+ failed && fail();
+ };
+
+ // Send
+ try {
+ xhr = Titanium.Network.createHTTPClient();
+ xhr.onerror = function(){ done(1) };
+ xhr.onload = finished;
+ xhr.timeout = XHRTME;
+
+ xhr.open( 'GET', setup.url.join(URLBIT), true );
+ xhr.send();
+ }
+ catch(eee) {
+ done(0);
+ return xdr(setup);
+ }
+
+ // Return 'done'
+ return done;
+}
+
+
+/* =-=====================================================================-= */
+/* =-=====================================================================-= */
+/* =-========================= PUBNUB ============================-= */
+/* =-=====================================================================-= */
+/* =-=====================================================================-= */
+
+var PN = $('pubnub')
+, DEMO = 'demo'
+, PUBLISH_KEY = attr( PN, 'pub-key' ) || DEMO
+, SUBSCRIBE_KEY = attr( PN, 'sub-key' ) || DEMO
+, SSL = attr( PN, 'ssl' ) == 'on' ? 's' : ''
+, ORIGIN = 'http'+SSL+'://'+(attr(PN,'origin')||'pubsub.pubnub.com')
+, LIMIT = 1800
+, READY_BUFFER = []
+, CHANNELS = {}
+, PUBNUB = {
+ /*
+ PUBNUB.history({
+ channel : 'my_chat_channel',
+ limit : 100,
+ callback : function(messages) { console.log(messages) }
+ });
+ */
+ 'history' : function( args, callback ) {
+ var callback = args['callback'] || callback
+ , limit = args['limit'] || 100
+ , channel = args['channel']
+ , jsonp = jsonp_cb();
+
+ // Make sure we have a Channel
+ if (!channel) return log('Missing Channel');
+ if (!callback) return log('Missing Callback');
+
+ // Send Message
+ xdr({
+ callback : jsonp,
+ url : [
+ ORIGIN, 'history',
+ SUBSCRIBE_KEY, encode(channel),
+ jsonp, limit
+ ],
+ success : function(response) { callback(response) },
+ fail : function(response) { log(response) }
+ });
+ },
+
+ /*
+ PUBNUB.time(function(time){ console.log(time) });
+ */
+ 'time' : function(callback) {
+ var jsonp = jsonp_cb();
+ xdr({
+ callback : jsonp,
+ url : [ORIGIN, 'time', jsonp],
+ success : function(response) { callback(response[0]) },
+ fail : function() { callback(0) }
+ });
+ },
+
+ /*
+ PUBNUB.uuid(function(uuid) { console.log(uuid) });
+ */
+ 'uuid' : function(callback) {
+ var jsonp = jsonp_cb();
+ xdr({
+ callback : jsonp,
+ url : [
+ 'http' + SSL +
+ '://pubnub-prod.appspot.com/uuid?callback=' + jsonp
+ ],
+ success : function(response) { callback(response[0]) },
+ fail : function() { callback(0) }
+ });
+ },
+
+ /*
+ PUBNUB.publish({
+ channel : 'my_chat_channel',
+ message : 'hello!'
+ });
+ */
+ 'publish' : function( args, callback ) {
+ var callback = callback || args['callback'] || function(){}
+ , message = args['message']
+ , channel = args['channel']
+ , jsonp = jsonp_cb();
+
+ if (!message) return log('Missing Message');
+ if (!channel) return log('Missing Channel');
+ if (!PUBLISH_KEY) return log('Missing Publish Key');
+
+ // If trying to send Object
+ message = JSON['stringify'](message);
+
+ // Make sure message is small enough.
+ if (message.length > LIMIT) return log('Message Too Big');
+
+ // Send Message
+ xdr({
+ callback : jsonp,
+ success : function(response) { callback(response) },
+ fail : function() { callback([ 0, 'Disconnected' ]) },
+ url : [
+ ORIGIN, 'publish',
+ PUBLISH_KEY, SUBSCRIBE_KEY,
+ 0, encode(channel),
+ jsonp, encode(message)
+ ]
+ });
+ },
+
+ /*
+ PUBNUB.unsubscribe({ channel : 'my_chat' });
+ */
+ 'unsubscribe' : function(args) {
+ var channel = args['channel'];
+
+ // Leave if there never was a channel.
+ if (!(channel in CHANNELS)) return;
+
+ // Disable Channel
+ CHANNELS[channel].connected = 0;
+
+ // Abort and Remove Script
+ CHANNELS[channel].done &&
+ CHANNELS[channel].done(0);
+ },
+
+ /*
+ PUBNUB.subscribe({
+ channel : 'my_chat'
+ callback : function(message) { console.log(message) }
+ });
+ */
+ 'subscribe' : function( args, callback ) {
+ var channel = args['channel']
+ , callback = callback || args['callback']
+ , timetoken = 0
+ , error = args['error'] || function(){};
+
+ // Make sure we have a Channel
+ if (!channel) return log('Missing Channel');
+ if (!callback) return log('Missing Callback');
+ if (!SUBSCRIBE_KEY) return log('Missing Subscribe Key');
+
+ if (!(channel in CHANNELS)) CHANNELS[channel] = {};
+
+ // Make sure we have a Channel
+ if (CHANNELS[channel].connected) return log('Already Connected');
+ CHANNELS[channel].connected = 1;
+
+ // Recurse Subscribe
+ function pubnub() {
+ var jsonp = jsonp_cb();
+
+ // Stop Connection
+ if (!CHANNELS[channel].connected) return;
+
+ // Connect to PubNub Subscribe Servers
+ CHANNELS[channel].done = xdr({
+ callback : jsonp,
+ url : [
+ ORIGIN, 'subscribe',
+ SUBSCRIBE_KEY, encode(channel),
+ jsonp, timetoken
+ ],
+ fail : function() { timeout( pubnub, 1000 ); error() },
+ success : function(message) {
+ if (!CHANNELS[channel].connected) return;
+ timetoken = message[1];
+ timeout( pubnub, 10 );
+ each( message[0], function(msg) { callback(msg) } );
+ }
+ });
+ }
+
+ // Begin Recursive Subscribe
+ pubnub();
+ },
+
+ // Expose PUBNUB Functions
+ 'xdr' : xdr,
+ 'each' : each,
+ 'map' : map,
+ 'css' : css,
+ '$' : $,
+ 'create' : create,
+ 'bind' : bind,
+ 'supplant' : supplant,
+ 'head' : head,
+ 'search' : search,
+ 'attr' : attr,
+ 'now' : unique
+};
+
+// Provide Global Interfaces
+window['jQuery'] && (window['jQuery']['PUBNUB'] = PUBNUB);
+window['PUBNUB'] = PUBNUB;
+
+})();
View
119 titanium/3.3/mobile/README
@@ -0,0 +1,119 @@
+## ------------------------------------------------------
+##
+## (FREE VERSION) USE "demo" KEYS As Shown Below
+##
+## (PAID VERSION) GET YOUR OWN API KEYS:
+## http://www.pubnub.com/account
+##
+## ------------------------------------------------------
+
+## ------------------------------------------------------
+## ALERT!!! ANDROID FIX!!!
+## ------------------------------------------------------
+##
+## You must update the tiapp.xml and add the following:
+##
+## <property name="ti.android.threadstacksize" type="int">327680</property>
+##
+## ------------------------------------------------------
+
+## ----------------------------------------------------------------
+## PubNub 3.1 Real-time Cloud Push API - JAVASCRIPT TITANIUM MOBILE
+## ----------------------------------------------------------------
+##
+## www.pubnub.com - PubNub Real-time Push Service in the Cloud.
+## http://www.pubnub.com/tutorial/javascript-push-api
+##
+## PubNub is a Massively Scalable Real-time Service for Web and Mobile Games.
+## This is a cloud-based service for broadcasting Real-time messages
+## to millions of web and mobile clients simultaneously.
+
+
+/* ====================================================== */
+/* SIMPLE EXAMPLE USE PUBNUB API (ADVANCED EXAMPLE BELOW) */
+/* ====================================================== */
+
+Ti.include('pubnub.js');
+
+// ----------------------------------
+// INIT PUBNUB
+// ----------------------------------
+var pubnub = PUBNUB.init({
+ publish_key : 'demo',
+ subscribe_key : 'demo',
+ ssl : false,
+ origin : 'pubsub.pubnub.com'
+});
+
+
+// -------------------
+// LISTEN FOR MESSAGES
+// -------------------
+pubnub.subscribe({
+ channel : "hello_world",
+ callback : function(message) { Ti.API.log(message) }
+})
+
+// ------------
+// SEND MESSAGE
+// ------------
+pubnub.publish({
+ channel : "hello_world",
+ message : "Hi."
+})
+
+/* =============================== */
+/* ADVANCED EXAMPLE USE PUBNUB API */
+/* =============================== */
+
+Ti.include('pubnub.js');
+
+(function(){
+
+ // ----------------------------------
+ // INIT PUBNUB
+ // ----------------------------------
+ var pubnub = PUBNUB.init({
+ publish_key : 'demo',
+ subscribe_key : 'demo',
+ ssl : false,
+ origin : 'pubsub.pubnub.com'
+ });
+
+ // ----------------------------------
+ // LISTEN FOR MESSAGES
+ // ----------------------------------
+ pubnub.subscribe({
+ channel : 'test',
+ connect : function() {
+ // You can Receive Messages!
+ send_a_message("Hello World! #1");
+ send_a_message("Hello World! #2");
+ send_a_message("Hello World! #3");
+ },
+ callback : function(message) {
+ // Message RECEIVED!
+ Ti.API.log(JSON.stringify(message));
+ },
+ error : function() {
+ // The internet is gone.
+ Ti.API.log("Connection Lost");
+ }
+ });
+
+ // ----------------------------------
+ // SEND MESSAGE
+ // ----------------------------------
+ function send_a_message(message) {
+ pubnub.publish({
+ channel : 'test',
+ message : { example : message },
+ callback : function(info) {
+ if (info[0]) Ti.API.log("Successfully Sent Message!");
+ if (!info[0]) Ti.API.log("Failed Because: " + info[1]);
+ }
+ });
+ }
+
+})();
+
View
48 titanium/3.3/mobile/app.js
@@ -0,0 +1,48 @@
+(function(){
+
+ // -------------------------------------
+ // INIT PUBNUB
+ // -------------------------------------
+ var pubnub = require('pubnub').init({
+ publish_key : 'demo',
+ subscribe_key : 'demo',
+ ssl : false,
+ origin : 'pubsub.pubnub.com'
+ });
+
+ // -------------------------------------
+ // LISTEN FOR MESSAGES
+ // -------------------------------------
+ pubnub.subscribe({
+ channel : 'test',
+ connect : function() {
+ // You can Receive Messages!
+ send_a_message("Hello World! #1");
+ send_a_message("Hello World! #2");
+ send_a_message("Hello World! #3");
+ },
+ callback : function(message) {
+ // Message RECEIVED!
+ Ti.API.log(JSON.stringify(message));
+ },
+ error : function() {
+ // The internet is gone.
+ Ti.API.log("Connection Lost");
+ }
+ });
+
+ // ----------------------------------
+ // SEND MESSAGE
+ // ----------------------------------
+ function send_a_message(message) {
+ pubnub.publish({
+ channel : 'test',
+ message : { example : message },
+ callback : function(info) {
+ if (info[0]) Ti.API.log("Successfully Sent Message!");
+ if (!info[0]) Ti.API.log("Failed Because: " + info[1]);
+ }
+ });
+ }
+
+})();
View
23 titanium/3.3/mobile/chat-example-app/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>chat-example-app</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.appcelerator.titanium.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.aptana.ide.core.unifiedBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.appcelerator.titanium.mobile.nature</nature>
+ <nature>com.aptana.projects.webnature</nature>
+ </natures>
+</projectDescription>
View
1  titanium/3.3/mobile/chat-example-app/CHANGELOG.txt
@@ -0,0 +1 @@
+Place your change log text here. This file will be incorporated with your app at package time.
View
219 titanium/3.3/mobile/chat-example-app/LICENSE
@@ -0,0 +1,219 @@
+Copyright 2009 Appcelerator, Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ (or the full text of the license is below)
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
View
1  titanium/3.3/mobile/chat-example-app/LICENSE.txt
@@ -0,0 +1 @@
+Place your license text here. This file will be incorporated with your app at package time.
View
18 titanium/3.3/mobile/chat-example-app/README
@@ -0,0 +1,18 @@
+Welcome to your Appcelerator Titanium Mobile Project
+
+This is a blank project. Start by editing your application's app.js to
+make your first mobile project using Titanium.
+
+
+
+----------------------------------
+Stuff our legal folk make us say:
+
+Appcelerator, Appcelerator Titanium and associated marks and logos are
+trademarks of Appcelerator, Inc.
+
+Titanium is Copyright (c) 2009-2010 by Appcelerator, Inc. All Rights Reserved.
+
+Titanium is licensed under the Apache Public License (Version 2). Please
+see the LICENSE file for the full license.
+
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/KS_nav_ui.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/KS_nav_views.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/android/appicon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/android/default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-long-land-hdpi/default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-long-land-ldpi/default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-long-port-hdpi/default.png
Diff not rendered
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/android/images/res-long-port-ldpi/default.png
Diff not rendered
View
BIN  ...um/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-land-hdpi/default.png
Diff not rendered
View
BIN  ...um/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-land-ldpi/default.png
Diff not rendered
View
BIN  ...um/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-land-mdpi/default.png
Diff not rendered
View
BIN  ...um/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-port-hdpi/default.png
Diff not rendered
View
BIN  ...um/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-port-ldpi/default.png
Diff not rendered
View
BIN  ...um/3.3/mobile/chat-example-app/Resources/android/images/res-notlong-port-mdpi/default.png
Diff not rendered
View
26 titanium/3.3/mobile/chat-example-app/Resources/app.js
@@ -0,0 +1,26 @@
+// -------------------------------------------------------------------------
+// INCLUDE PUBNUB CHAT MODULE
+// -------------------------------------------------------------------------
+Ti.include('./pubnub-chat.js');
+
+// -------------------------------------------------------------------------
+// CREATE PUBNUB CHAT WINDOW
+// -------------------------------------------------------------------------
+//
+// Returns an Object with Titanium Window Inside
+//
+var pubnub_chat_window = Ti.App.Chat({
+ "chat-room" : "my-random-conversation",
+ "window" : {
+ title : 'My Chat Room',
+ backgroundColor : '#fff'
+ }
+});
+
+// -------------------------------------------------------------------------
+// TITANIUM WINDOW OBJECT
+// -------------------------------------------------------------------------
+//
+// Open Chat Window
+//
+pubnub_chat_window.chat_window.open();
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/Default-Landscape.png
Diff not rendered
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/Default-Portrait.png
Diff not rendered
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/Default.png
Diff not rendered
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/Default@2x.png
Diff not rendered
View
BIN  titanium/3.3/mobile/chat-example-app/Resources/iphone/appicon.png
Diff not rendered
View
180 titanium/3.3/mobile/chat-example-app/Resources/pubnub-chat.js
@@ -0,0 +1,180 @@
+// ----------------------------------
+// Detect Platform
+// ----------------------------------
+var isAndroid = Ti.Platform.osname === 'android';
+
+// ----------------------------------
+// INIT PUBNUB
+// ----------------------------------
+var pubnub = require('pubnub').init({
+ publish_key : 'demo',
+ subscribe_key : 'demo',
+ ssl : false,
+ origin : 'pubsub.pubnub.com'
+});
+
+// ----------------------------------
+// RANDOM COLOR
+// ----------------------------------
+function rnd_hex(light) { return Math.ceil(Math.random()*9) }
+function rnd_color() {
+ return '#'+pubnub.map(
+ Array(3).join().split(','), rnd_hex
+ ).join('');
+}
+
+Ti.App.Chat = function(setup) {
+ // ----------------------------------
+ // LISTEN FOR MESSAGES
+ // ----------------------------------
+ pubnub.subscribe({
+ channel : setup['chat-room'],
+ connect : function() {
+ append_chat_message("Entered Chat...");
+ },
+ callback : function(message) {
+ append_chat_message( message.text, message.color );
+ },
+ error : function() {
+ append_chat_message( "Lost Connection...", "#f00" );
+ }
+ });
+
+ // ----------------------------------
+ // SEND MESSAGE
+ // ----------------------------------
+ function send_a_message(message) {
+ if (!message) return;
+
+ pubnub.publish({
+ channel : setup['chat-room'],
+ message : { text : message, color : this.my_color },
+ callback : function(info) {
+ if (!info[0]) setTimeout(function() {
+ send_a_message(message)
+ }, 2000 );
+ }
+ });
+ }
+
+
+ // ----------------------------------
+ // CREATE BASE UI TAB AND ROOT WINDOW
+ // ----------------------------------
+ var chat_window = Ti.UI.createWindow(setup['window']);
+ var textfield = Ti.UI.createTextField({
+ width : (isAndroid) ? '75%' : 247,
+ height : (isAndroid) ? '50dp' : 30,
+ left : 4,
+ top : 4,
+ color : "#111",
+ value : "",
+ border : 1,
+ borderStyle : Ti.UI.INPUT_BORDERSTYLE_ROUNDED,
+ borderRadius : 4,
+ font : {
+ fontSize : (isAndroid) ? '18dp' : 14,
+ fontWeight : 'bold'
+ }
+ });
+
+ // Text Chat History
+ var table = Ti.UI.createTableView({
+ separatorColor : (isAndroid) ? '#000' : '#fff',
+ top : (isAndroid) ? '60dp' : 40,
+ height : '80%'
+ });
+
+ // Send Button
+ var button = Ti.UI.createButton({
+ title : 'Send',
+ top : 4,
+ right : 4,
+ width : (isAndroid) ? '60dp' : 60,
+ height : (isAndroid) ? '50dp' : 30,
+ borderRadius : 6,
+ shadowColor : "#001",
+ shadowOffset : { x : 1, y : 1 },
+ style : Ti.UI.iPhone.SystemButtonStyle.PLAIN,
+ font : {
+ fontSize : (isAndroid) ? '18dp' : 16,
+ fontWeight : 'bold'
+ },
+ backgroundGradient : {
+ type : 'linear',
+ colors : [ '#058cf5', '#015fe6' ],
+ startPoint : { x : 0, y : 0 },
+ endPoint : { x : 2, y : 50 },
+ backFillStart : false
+ }
+ });
+
+ // Append First Row (Blank)
+ table.appendRow(Ti.UI.createTableViewRow({
+ className : "pubnub_chat"
+ }));
+
+ // Append New Chat Message
+ function append_chat_message( message, color ) {
+ var row = Ti.UI.createTableViewRow({
+ className : "pubnub_chat",
+ backgroundGradient : {
+ type : 'linear',
+ colors : [ "#fff", '#eeeeed' ],
+ startPoint : { x : 0, y : 0 },
+ endPoint : { x : 0, y : 70 },
+ backFillStart : false
+ }
+ });
+
+ var label = Ti.UI.createLabel({
+ text : message || "no-message",
+ height : (isAndroid) ? '50dp' : 'auto',
+ width : 'auto',
+ color : color || "#111",
+ left : 10,
+ font : {
+ fontSize : (isAndroid) ? '19dp' : 14,
+ fontWeight: (isAndroid) ? 'bold' : 'normal'
+ }
+ });
+
+ row.add(label);
+ table.insertRowBefore( 0, row );
+ }
+
+ // Listen for Send Button Touch
+ button.addEventListener( 'touchstart', function(e) {
+ send_a_message(textfield.value);
+ textfield.value = "";
+ textfield.focus();
+ });
+
+ // Listen for Return Key Press
+ textfield.addEventListener( 'return', function(e) {
+ send_a_message(textfield.value);
+ textfield.value = "";
+ textfield.focus();
+ });
+
+ // Listen for Return Key Press
+ chat_window.addEventListener( 'open', function(e) {
+ textfield.focus();
+ });
+
+ chat_window.add(table);
+ chat_window.add(button);
+ chat_window.add(textfield);
+
+ this.chat_window = chat_window;
+ this.my_color = rnd_color();
+ this.pubnub = pubnub;
+
+ append_chat_message(" ");
+ append_chat_message(" ");
+ append_chat_message(" ");
+ append_chat_message("Connecting...");
+
+ return this;
+};
+
View
548 titanium/3.3/mobile/chat-example-app/Resources/pubnub.js
@@ -0,0 +1,548 @@
+/* ---------------------------------------------------------------------------
+WAIT! - This file depends on instructions from the PUBNUB Cloud.
+http://www.pubnub.com/account
+--------------------------------------------------------------------------- */
+
+/* ---------------------------------------------------------------------------
+PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
+Copyright (c) 2011 TopMambo Inc.
+http://www.pubnub.com/
+http://www.pubnub.com/terms
+--------------------------------------------------------------------------- */
+
+/* ---------------------------------------------------------------------------
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+--------------------------------------------------------------------------- */
+
+(function() {
+
+/**
+ * UTIL LOCALS
+ */
+var NOW = 1
+, MAGIC = /\$?{([\w\-]+)}/g
+, URLBIT = '/'
+, SECOND = 1000
+, ANDROID = Ti.Platform.name.toLowerCase().indexOf('android') >= 0
+, XHRTME = 140000;
+
+/**
+ * UTILITIES
+ */
+function unique() { return'x'+ ++NOW+''+(+new Date) }
+function rnow() { return+new Date }
+
+/**
+ * LOCAL STORAGE OR COOKIE
+ */
+var db = (function(){
+ return {
+ get : function(key) {
+ Ti.App.Properties.getString(''+key);
+ },
+ set : function( key, value ) {
+ Ti.App.Properties.setString( ''+key, ''+value );
+ }
+ };
+})();
+
+/**
+ * NEXTORIGIN
+ * ==========
+ * var next_origin = nextorigin();
+ */
+var nextorigin = (function() {
+ var ori = Math.floor(Math.random() * 9) + 1;
+ return function(origin) {
+ return origin.indexOf('pubsub') > 0
+ && origin.replace(
+ 'pubsub', 'ps' + (++ori < 10 ? ori : ori=1)
+ ) || origin;
+ }
+})();
+
+/**
+ * UPDATER
+ * =======
+ * var timestamp = unique();
+ */
+function updater( fun, rate ) {
+ var timeout
+ , last = 0
+ , runnit = function() {
+ if (last + rate > rnow()) {
+ clearTimeout(timeout);
+ timeout = setTimeout( runnit, rate );
+ }
+ else {
+ last = rnow();
+ fun();
+ }
+ };
+
+ return runnit;
+}
+
+
+/**
+ * LOG
+ * ===
+ * log('message');
+ */
+function log(message) { Ti.API.info(message) }
+
+/**
+ * EACH
+ * ====
+ * each( [1,2,3], function(item) { console.log(item) } )
+ */
+function each( o, f ) {
+ if ( !o || !f ) return;
+
+ if ( typeof o[0] != 'undefined' ) for ( var i = 0, l = o.length; i < l; )
+ f.call( o[i], o[i], i++ );
+ else for ( var i in o )
+ o.hasOwnProperty &&
+ o.hasOwnProperty(i) &&
+ f.call( o[i], i, o[i] );
+}
+
+/**
+ * MAP
+ * ===
+ * var list = map( [1,2,3], function(item) { return item + 1 } )
+ */
+function map( list, fun ) {
+ var fin = [];
+ each( list || [], function( k, v ) { fin.push(fun( k, v )) } );
+ return fin;
+}
+
+/**
+ * GREP
+ * ====
+ * var list = grep( [1,2,3], function(item) { return item % 2 } )
+ */
+function grep( list, fun ) {
+ var fin = [];
+ each( list || [], function(l) { fun(l) && fin.push(l) } );
+ return fin
+}
+
+/**
+ * SUPPLANT
+ * ========
+ * var text = supplant( 'Hello {name}!', { name : 'John' } )
+ */
+function supplant( str, values ) {
+ return str.replace( MAGIC, function( _, match ) {
+ return ''+values[match] || ''
+ } );
+}
+
+/**
+ * timeout
+ * =======
+ * timeout( function(){}, 100 );
+ */
+function timeout( fun, wait ) { return setTimeout( fun, wait ) }
+
+/**
+ * jsonp_cb
+ * ========
+ * var callback = jsonp_cb();
+ */
+function jsonp_cb() { return '0' }
+
+/**
+ * ENCODE
+ * ======
+ * var encoded_path = encode('path');
+ */
+function encode(path) {
+ return map( (''+path).split(''), function(chr) {
+ return " ~`!@#$%^&*()+=[]\\{}|;':\",./<>?".indexOf(chr) > -1 ?
+ "%"+chr.charCodeAt(0).toString(16).toUpperCase() : chr
+ } ).join('');
+}
+
+/**
+ * Titanium XHR Request (Android)
+ * ==============================
+ * xdr({
+ * url : ['http://www.blah.com/url'],
+ * success : function(response) {},
+ * fail : function() {}
+ * });
+ */
+function xdra( setup ) {
+ var xhr
+ , finished = function() {
+ if (loaded) return;
+ loaded = 1;
+
+ clearTimeout(timer);
+
+ try { response = JSON['parse'](xhr.responseText); }
+ catch (r) { return done(1); }
+
+ success(response);
+ }
+ , complete = 0
+ , loaded = 0
+ , timer = timeout( function(){done(1)}, XHRTME )
+ , fail = setup.fail || function(){}
+ , success = setup.success || function(){}
+ , done = function(failed) {
+ if (complete) return;
+ complete = 1;
+
+ clearTimeout(timer);
+
+ if (xhr) {
+ xhr.onerror = xhr.onload = null;
+ xhr.abort && xhr.abort();
+ xhr = null;
+ }
+
+ failed && fail();
+ };
+
+ // Send
+ try {
+ xhr = Ti.Network.createHTTPClient();
+ xhr.onerror = function(){ done(1) };
+ xhr.onload = finished;
+ xhr.timeout = XHRTME;
+
+ xhr.open( 'GET', setup.url.join(URLBIT), true );
+ xhr.send();
+ }
+ catch(eee) {
+ done(0);
+ return xdr(setup);
+ }
+
+ // Return 'done'
+ return done;
+}
+
+/**
+ * Titanium TCP Sockets
+ * ====================
+ * xdr({
+ * url : ['http://www.blah.com/url'],
+ * success : function(response) {},
+ * fail : function() {}
+ * });
+ */
+function xdr(setup) {
+ if (ANDROID) return xdra(setup);
+
+ var url = setup.url.join(URLBIT)
+ , body = []
+ , data = ""
+ , rbuffer = Ti.createBuffer({ length : 2048 })
+ , wbuffer = Ti.createBuffer({ value : "GET " + url + " HTTP/1.0\n\n"})
+ , failed = 0
+ , fail = function() {
+ if (failed) return;
+ failed = 1;
+ (setup.fail || function(){})();
+ }
+ , success = setup.success || function(){}
+ , sock = Ti.Network.Socket.createTCP({
+ host : url.split(URLBIT)[2],
+ port : 80,
+ mode : Ti.Network.READ_WRITE_MODE,
+ timeout : XHRTME,
+ error : fail,
+ connected : function() {
+ sock.write(wbuffer);
+ read();
+ }
+ });
+
+ function read() {
+ Ti.Stream.read( sock, rbuffer, function(stream) {
+ if (+stream.bytesProcessed > -1) {
+ data = Ti.Codec.decodeString({
+ source : rbuffer,
+ length : +stream.bytesProcessed
+ });
+
+ body.push(data);
+ rbuffer.clear();
+
+ return timeout( read, 1 );
+ }
+
+ try {
+ data = JSON['parse'](
+ body.join('').split('\r\n').slice(-1)
+ );
+ }
+ catch (r) {
+ return fail();
+ }
+
+ sock.close();
+ success(data);
+ } );
+ }
+
+ try { sock.connect() }
+ catch(k) { return fail() }
+}
+
+
+/* =-====================================================================-= */
+/* =-====================================================================-= */
+/* =-========================= PUBNUB ===========================-= */
+/* =-====================================================================-= */
+/* =-====================================================================-= */
+
+var DEMO = 'demo'
+, LIMIT = 1700
+, CREATE_PUBNUB = function(setup) {
+ var CHANNELS = {}
+ , PUBLISH_KEY = setup['publish_key'] || DEMO
+ , SUBSCRIBE_KEY = setup['subscribe_key'] || DEMO
+ , SSL = setup['ssl'] ? 's' : ''
+ , ORIGIN = 'http' + SSL + '://' +
+ (setup['origin'] || 'pubsub.pubnub.com')
+ , SELF = {
+ /*
+ PUBNUB.history({
+ channel : 'my_chat_channel',
+ limit : 100,
+ callback : function(messages) { console.log(messages) }
+ });
+ */
+ 'history' : function( args, callback ) {
+ var callback = args['callback'] || callback
+ , limit = args['limit'] || 100
+ , channel = args['channel'];
+
+ // Make sure we have a Channel
+ if (!channel) return log('Missing Channel');
+ if (!callback) return log('Missing Callback');
+
+ // Send Message
+ xdr({
+ url : [
+ ORIGIN, 'history',
+ SUBSCRIBE_KEY, encode(channel),
+ 0, limit
+ ],
+ success : function(response) { callback(response) },
+ fail : function(response) { log(response) }
+ });
+ },
+
+ /*
+ PUBNUB.time(function(time){ console.log(time) });
+ */
+ 'time' : function(callback) {
+ xdr({
+ url : [ORIGIN, 'time', 0],
+ success : function(response) { callback(response[0]) },
+ fail : function() { callback(0) }
+ });
+ },
+
+ /*
+ PUBNUB.uuid(function(uuid) { console.log(uuid) });
+ */
+ 'uuid' : function(callback) {
+ xdr({
+ url : [
+ 'http' + SSL +
+ '://pubnub-prod.appspot.com/uuid?callback=0'
+ ],
+ success : function(response) { callback(response[0]) },
+ fail : function() { callback(0) }
+ });
+ },
+
+ /*
+ PUBNUB.publish({
+ channel : 'my_chat_channel',
+ message : 'hello!'
+ });
+ */
+ 'publish' : function( args, callback ) {
+ var callback = callback || args['callback'] || function(){}
+ , message = args['message']
+ , channel = args['channel'];
+
+ if (!message) return log('Missing Message');
+ if (!channel) return log('Missing Channel');
+ if (!PUBLISH_KEY) return log('Missing Publish Key');
+
+ // If trying to send Object
+ message = JSON['stringify'](message);
+
+ // Make sure message is small enough.
+ if (message.length > LIMIT) return log('Message Too Big');
+
+ // Send Message
+ xdr({
+ success : function(response) { callback(response) },
+ fail : function() { callback([ 0, 'Disconnected' ]) },
+ url : [
+ ORIGIN, 'publish',
+ PUBLISH_KEY, SUBSCRIBE_KEY,
+ 0, encode(channel),
+ 0, encode(message)
+ ]
+ });
+ },
+
+ /*
+ PUBNUB.unsubscribe({ channel : 'my_chat' });
+ */
+ 'unsubscribe' : function(args) {
+ var channel = args['channel'];
+
+ // Leave if there never was a channel.
+ if (!(channel in CHANNELS)) return;
+
+ // Disable Channel
+ CHANNELS[channel].connected = 0;
+
+ // Abort and Remove Script
+ CHANNELS[channel].done &&
+ CHANNELS[channel].done(0);
+ },
+
+ /*
+ PUBNUB.subscribe({
+ channel : 'my_chat'
+ callback : function(message) { console.log(message) }
+ });
+ */
+ 'subscribe' : function( args, callback ) {
+
+ var channel = args['channel']
+ , callback = callback || args['callback']
+ , restore = args['restore']
+ , timetoken = 0
+ , error = args['error'] || function(){}
+ , connect = args['connect'] || function(){}
+ , reconnect = args['reconnect'] || function(){}
+ , disconnect = args['disconnect'] || function(){}
+ , disconnected = 0
+ , connected = 0
+ , origin = nextorigin(ORIGIN);
+
+ // Make sure we have a Channel
+ if (!channel) return log('Missing Channel');
+ if (!callback) return log('Missing Callback');
+ if (!SUBSCRIBE_KEY) return log('Missing Subscribe Key');
+
+ if (!(channel in CHANNELS)) CHANNELS[channel] = {};
+
+ // Make sure we have a Channel
+ if (CHANNELS[channel].connected) return log('Already Connected');
+ CHANNELS[channel].connected = 1;
+
+ // Recurse Subscribe
+ function pubnub() {
+ var jsonp = jsonp_cb();
+
+ // Stop Connection
+ if (!CHANNELS[channel].connected) return;
+
+ // Connect to PubNub Subscribe Servers
+ CHANNELS[channel].done = xdr({
+ callback : jsonp,
+ url : [
+ origin, 'subscribe',
+ SUBSCRIBE_KEY, encode(channel),
+ jsonp, timetoken
+ ],
+ fail : function() {
+ // Disconnect
+ if (!disconnected) {
+ disconnected = 1;
+ disconnect();
+ }
+ timeout( pubnub, SECOND );
+ SELF['time'](function(success){
+ success || error();
+ });
+ },
+ success : function(messages) {
+ if (!CHANNELS[channel].connected) return;
+
+ // Connect
+ if (!connected) {
+ connected = 1;
+ connect();
+ }
+
+ // Reconnect
+ if (disconnected) {
+ disconnected = 0;
+ reconnect();
+ }
+
+ // Restore Previous Connection Point if Needed
+ // Also Update Timetoken
+ restore = db.set(
+ SUBSCRIBE_KEY + channel,
+ timetoken = restore && db.get(
+ SUBSCRIBE_KEY + channel
+ ) || messages[1]
+ );
+
+ each( messages[0], function(msg) {
+ callback( msg, messages );
+ } );
+
+ timeout( pubnub, 10 );
+ }
+ });
+ }
+
+ // Begin Recursive Subscribe
+ pubnub();
+ },
+
+ // Expose PUBNUB Functions
+ 'db' : db,
+ 'each' : each,
+ 'map' : map,
+ 'supplant' : supplant,
+ 'now' : unique,
+ 'init' : CREATE_PUBNUB
+ };
+
+ return SELF;
+};
+
+module.exports = CREATE_PUBNUB({
+ 'publish_key' : 'demo',
+ 'subscribe_key' : 'demo',
+ 'ssl' : false,
+ 'origin' : 'pubsub.pubnub.com'
+});
+
+})();
View
8 titanium/3.3/mobile/chat-example-app/manifest
@@ -0,0 +1,8 @@
+#appname: Andriod Fix
+#publisher: stephen
+#url: http://www.pubnub.com/
+#image: appicon.png
+#appid: com.pubnub.android
+#desc: undefined
+#type: ipad
+#guid: 42667a7c-de7a-4f61-834c-3f0fab1da412
View
41 titanium/3.3/mobile/chat-example-app/tiapp.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ti:app xmlns:ti="http://ti.appcelerator.org">
+ <sdk-version>1.8.1</sdk-version>
+ <property name="ti.android.threadstacksize" type="int">327680</property>
+ <deployment-targets>
+ <target device="mobileweb">false</target>
+ <target device="iphone">true</target>
+ <target device="ipad">true</target>
+ <target device="android">true</target>
+ <target device="blackberry">false</target>
+ </deployment-targets>
+ <id>com.pubnub.android</id>
+ <name>Andriod Fix</name>
+ <version>1.0</version>
+ <publisher>stephen</publisher>
+ <url>http://www.pubnub.com/</url>
+ <description>not specified</description>
+ <copyright>2011 by stephen</copyright>
+ <icon>appicon.png</icon>
+ <persistent-wifi>false</persistent-wifi>
+ <prerendered-icon>false</prerendered-icon>
+ <statusbar-style>default</statusbar-style>
+ <statusbar-hidden>false</statusbar-hidden>
+ <fullscreen>false</fullscreen>
+ <navbar-hidden>false</navbar-hidden>
+ <analytics>true</analytics>
+ <guid>42667a7c-de7a-4f61-834c-3f0fab1da412</guid>
+ <iphone>
+ <orientations device="iphone">
+ <orientation>Ti.UI.PORTRAIT</orientation>
+ </orientations>
+ <orientations device="ipad">
+ <orientation>Ti.UI.PORTRAIT</orientation>
+ <orientation>Ti.UI.UPSIDE_PORTRAIT</orientation>
+ <orientation>Ti.UI.LANDSCAPE_LEFT</orientation>
+ <orientation>Ti.UI.LANDSCAPE_RIGHT</orientation>
+ </orientations>
+ </iphone>
+ <android xmlns:android="http://schemas.android.com/apk/res/android"/>
+ <modules/>
+</ti:app>
View
548 titanium/3.3/mobile/pubnub.js
@@ -0,0 +1,548 @@
+/* ---------------------------------------------------------------------------
+WAIT! - This file depends on instructions from the PUBNUB Cloud.
+http://www.pubnub.com/account
+--------------------------------------------------------------------------- */
+
+/* ---------------------------------------------------------------------------
+PubNub Real-time Cloud-Hosted Push API and Push Notification Client Frameworks
+Copyright (c) 2011 TopMambo Inc.
+http://www.pubnub.com/
+http://www.pubnub.com/terms
+--------------------------------------------------------------------------- */
+
+/* ---------------------------------------------------------------------------
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+--------------------------------------------------------------------------- */
+
+(function() {
+
+/**
+ * UTIL LOCALS
+ */
+var NOW = 1
+, MAGIC = /\$?{([\w\-]+)}/g
+, URLBIT = '/'
+, SECOND = 1000
+, ANDROID = Ti.Platform.name.toLowerCase().indexOf('android') >= 0
+, XHRTME = 140000;
+
+/**
+ * UTILITIES
+ */
+function unique() { return'x'+ ++NOW+''+(+new Date) }
+function rnow() { return+new Date }
+
+/**
+ * LOCAL STORAGE OR COOKIE
+ */
+var db = (function(){
+ return {
+ get : function(key) {
+ Ti.App.Properties.getString(''+key);
+ },
+ set : function( key, value ) {
+ Ti.App.Properties.setString( ''+key, ''+value );
+ }
+ };
+})();
+
+/**
+ * NEXTORIGIN
+ * ==========
+ * var next_origin = nextorigin();
+ */
+var nextorigin = (function() {
+ var ori = Math.floor(Math.random() * 9) + 1;
+ return function(origin) {
+ return origin.indexOf('pubsub') > 0
+ && origin.replace(
+ 'pubsub', 'ps' + (++ori < 10 ? ori : ori=1)
+ ) || origin;
+ }
+})();
+
+/**
+ * UPDATER
+ * =======
+ * var timestamp = unique();
+ */
+function updater( fun, rate ) {
+ var timeout
+ , last = 0
+ , runnit = function() {
+ if (last + rate > rnow()) {
+ clearTimeout(timeout);
+ timeout = setTimeout( runnit, rate );
+ }
+ else {
+ last = rnow();
+ fun();
+ }
+ };
+
+ return runnit;
+}
+
+
+/**
+ * LOG
+ * ===
+ * log('message');
+ */
+function log(message) { Ti.API.info(message) }
+
+/**
+ * EACH
+ * ====
+ * each( [1,2,3], function(item) { console.log(item) } )
+ */
+function each( o, f ) {
+ if ( !o || !f ) return;
+
+ if ( typeof o[0] != 'undefined' ) for ( var i = 0, l = o.length; i < l; )
+ f.call( o[i], o[i], i++ );
+ else for ( var i in o )
+ o.hasOwnProperty &&
+ o.hasOwnProperty(i) &&
+ f.call( o[i], i, o[i] );
+}
+
+/**
+ * MAP
+ * ===
+ * var list = map( [1,2,3], function(item) { return item + 1 } )
+ */
+function map( list, fun ) {
+ var fin = [];
+ each( list || [], function( k, v ) { fin.push(fun( k, v )) } );
+ return fin;
+}
+
+/**
+ * GREP
+ * ====
+ * var list = grep( [1,2,3], function(item) { return item % 2 } )
+ */
+function grep( list, fun ) {
+ var fin = [];
+ each( list || [], function(l) { fun(l) && fin.push(l) } );
+ return fin
+}
+
+/**
+ * SUPPLANT
+ * ========
+ * var text = supplant( 'Hello {name}!', { name : 'John' } )
+ */
+function supplant( str, values ) {
+ return str.replace( MAGIC, function( _, match ) {
+ return ''+values[match] || ''
+ } );
+}
+
+/**
+ * timeout
+ * =======
+ * timeout( function(){}, 100 );
+ */
+function timeout( fun, wait ) { return setTimeout( fun, wait ) }
+
+/**
+ * jsonp_cb
+ * ========
+ * var callback = jsonp_cb();
+ */
+function jsonp_cb() { return '0' }
+
+/**
+ * ENCODE
+ * ======
+ * var encoded_path = encode('path');
+ */
+function encode(path) {
+ return map( (''+path).split(''), function(chr) {
+ return " ~`!@#$%^&*()+=[]\\{}|;':\",./<>?".indexOf(chr) > -1 ?
+ "%"+chr.charCodeAt(0).toString(16).toUpperCase() : chr
+ } ).join('');
+}
+
+/**
+ * Titanium XHR Request (Android)
+ * ==============================
+ * xdr({
+ * url : ['http://www.blah.com/url'],
+ * success : function(response) {},
+ * fail : function() {}
+ * });
+ */
+function xdra( setup ) {
+ var xhr
+ , finished = function() {
+ if (loaded) return;
+ loaded = 1;
+
+ clearTimeout(timer);
+
+ try { response = JSON['parse'](xhr.responseText); }
+ catch (r) { return done(1); }
+
+ success(response);
+ }
+ , complete = 0
+ , loaded = 0
+ , timer = timeout( function(){done(1)}, XHRTME )
+ , fail = setup.fail || function(){}
+ , success = setup.success || function(){}
+ , done = function(failed) {
+ if (complete) return;
+ complete = 1;
+
+ clearTimeout(timer);
+
+ if (xhr) {
+ xhr.onerror = xhr.onload = null;
+ xhr.abort && xhr.abort();
+ xhr = null;
+ }
+
+ failed && fail();