Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

Monday, 4 March 2013

Facebook Connect with PhoneGap Build

This is really fiddly to get working. Here are two big "gotchas" that caught me out.

1. FB.login() requires extra paramters

Wrong:
FB.login(myCallbackFunction);
Right:
FB.login(myCallbackFunction, { scope: 'email' });
Even if you don't want the users email, you MUST supply this scope or the login call will fail wit h really weird JS errors.

2. Your Facebook iOS App ID must match your ID in the Apple Portal (not in PG config.xml)
The App ID which you define in your config.xml (widget id='x') is NOT the one which matters.

What matters is the App ID you configured when you generated the provisioning profile for your app via the Apple Portal. This is the App ID which you must enter into your Facebook App:
Native iOS App > Bundle ID > com.me.myApp
But do not include the prefix (SDGH34SD style) that you see in the Apple Portal.

More links covering other issues here:
http://pjsdev.blogspot.com.au/2013/02/phonegap-build-facebook-connect.html

Friday, 9 November 2012

Sexy documentation with Markdown and mdoc

I've been looking for a way to standardise our company's internal documentation.

Goals:

  • Super easy to and quick to edit.
  • Nice HTML output with solid sidebar navigation.
  • Decent search built-in.

First I tried a FogBugz Wiki. Then I started looking at DocBook, then Sphynx, and then AsciiDoc was looking good. Then I found mdoc. Yeah baby!

Look at the output. Isn't that beautiful?

Using mdoc on Windows

  1. Install NodeJS. The installer isn't perfect, you might need to add it manually to your windows PATH variables.
  2. Install mdoc (npm install mdoc).
  3. Write some Markdown.
  4. Run mdoc on it - mdoc --title MyDocs -i InputDir -o OutputDir
  5. Done.
Note - you need to view your generated docs via a webserver if you wanna get the automatic sidebar action (it loads in via JS).

Saturday, 16 June 2007

Generating JSON in ASP/VBScript

JSON is damn cool - we've been using it for a while now at work. Unfortunately though, VBScript lacks the OO functionality to properly handle converting JSON to and from object structures, so we've been painfully generating JSON responses manually from the server via string building.

However, after mixing JScript with VBScript (the other day), I got thinking, had a little play around, and realised that wee bit of server-side JS can make JSON production super easy:

<%@ LANGUAGE=VBScript LCID=5129 %>
<%
 
Dim sJSON, package, book, author
 
Set package          = JsInterop.Object("VbInterop.Json.RpcResponse")
Set package.result      = JsInterop.Object("VbInterop.Json.BooksCollection")
Set package.result.books  = JsInterop.NewArray()
 
For i = 1 to 3
 
  Set book      = JsInterop.Object("VbInterop.Json.Book")
  book.title      = "Slack"
  book.year      = 2002
  book.available    = True
  book.publisher    = "BroadwayBooks"
 
    Set book.authors  = JsInterop.NewArray()
 
    Set author      = JsInterop.Object("VbInterop.Json.Author")
    author.firstName  = "Tom"
    author.lastName    = "DeMarco"
    book.authors.push(author)
 
  package.result.books.push(book)
 
Next
 
Response.Write package.toJSON()
 
%>
<script language="jscript" runat="server" src="vb-interop.js"></script>
<script language="jscript" runat="server">
 
// Books collection
VbInterop.Json.BooksCollection = function () {
  this.books      = OBJ;
};
 
// Book class
VbInterop.Json.Book = function () {
  this.title      = STR;
  this.year      = NUM;
  this.available    = BOOL;
  this.authors    = RG;
  this.publisher    = STR;
};
 
// Author class
VbInterop.Json.Author = function () {
  this.firstName    = STR;
  this.lastName    = STR;
};
 
</script>


I don't really understand the workings of JS and VBs interop, but in a very rough sense it seems that:
a) Any JS features implemented via the IDispatchEx interface (see http://blogs.msdn.com/ericlippert/archive/2004/10/07/239289.aspx) cannot be used in VB.
b) JS/VB arrays do not play dice (see http://blogs.msdn.com/ericlippert/archive/2003/09/22/53061.aspx).

So, the two key features needed for JSON generation in a 'nice' fashion are:
1. New object creation (which requires a constructor) and
2. Arrays

#1 can easily be achieved by using an intermediary JS function to instantiate new objects from JS, then return them to VB:

JsInterop.Object = function ( sClass ) {
  var obj      = eval('new '+ sClass + '()');
  obj.toJson    = Object.prototype.toJSONString;
  return obj;
}


#2 is slightly more fiddly. Instead of an actual array, create an object with a public .push() method and a private array variable:

JsInterop.NewArray: function () {
  return new VbInterop.Array();
}
 
VbInterop.Array = function () {
 
  var rg = [];
 
  this.push = function( variant ) {
    rg.push(variant);
  }
 
  this.toJson = function () {
    return rg.toJSONString();
  }
}

Pop() and Get/Set methods could also be added here if desired.

Note the augumentation of a .toJson() method that utilizes Douglas Crockford's json.js jsonification. This is where the disco happens.

Suffice to say it's all pretty simple, and the code is self-explanatory, so take a look if you're interested:

VB-INTEROP.JS

//  vb-interop.js
//  Utility code to build an object structure in VBScript that can be serialized into JSON
 
//  VBScript-facing static class
//  An intermediary for new object creation, required as we cannot directly instantiate JS classes from VBScript
var JsInterop = {
 
  NewObject: function () {
    var obj      = {};
    obj.toJson    = Object.prototype.toJSONString;
    return obj;
  }
 
  , NewArray: function () {
    return new VbInterop.Array();
  }
 
  , Object: function ( sClass ) {
    var obj      = eval('new '+ sClass + '()');
    obj.toJson    = Object.prototype.toJSONString;
    return obj;
  }
};
 
//  JScript-facing static class
//  Interop namespace
var VbInterop = {};
 
//  Seperate namespace for JSON class definitions
VbInterop.Json = {};
 
//  VBScript-compatible Pseudo-array class
//  Note that the actual array variable *must* be private, if it is public then VBScript will setup-the-bomb on it and launch all ships..
VbInterop.Array = function () {
 
  var rg = [];
 
  this.push = function( variant ) {
    rg.push(variant);
  }
 
  this.toJson = function () {
    return rg.toJSONString();
  }
};
 
//  Simple constants for clean data-typed class definitions
var STR   = '';
var OBJ   = {};
var BOOL   = false;
var RG     = {};     // We are using objects to emulate arrays in VBs
var NUM   = -1;
var DT    = '';     // No literal syntax exists for dates, so we will treat them as strings.
 
// Example JSON-RPC Response class
VbInterop.Json.RpcResponse = function () {
  this.id        = NUM;
  this.result      = OBJ;
  this.error      = OBJ;
};


JSON.JS MODIFICATIONS

            object: function (x) {
                if (x) {
                    if (x instanceof Array) {
                        return s.array(x);
                    }
 
                    /* begin vb-interop.js addition */
                    if (VbInterop && x instanceof VbInterop.Array) {
            return x.toJson();
          }
          /* end vb-interop.js addition */


INTEROP-TESTS.ASP

<%@ LANGUAGE=VBScript LCID=5129 %>
<%
 
' VALID
Response.Write    test1.property
 
' INVALID (Class not defined)
'Set foo = New test2
 
' VALID
Set foo = test2a()
Response.Write foo.property
Response.Write test3.property.[0]
Response.Write test3.property.[1]
 
' INVALID (Property/method not supported)
'i = 0
'Response.Write test3.property.[i]
 
' VALID
Set foo = test4()
Response.Write foo.get(0)
 
' VALID
Set foo = test5()
Response.Write foo.get(0).bar
 
%>
<script language="jscript" runat="server">
 
var test1 = {
  property: 'test1'
}
 
var test2 = function () {
  this.property = 'test2';
}
 
var test2a = function () {
  return new test2();
}
 
var test3 = {
  property: ['test3', 'test3b']
}
 
var test4 = function () {
  return new test4a();
}
var test4a = function () {
  var property = ['test4'];
 
  this.get = function (ix) {
    return property[ix];
  }
}
 
var test5 = function () {
  return new test5a();
}
var test5a = function () {
  var property = [
    { bar: "test5" }
  ];
 
  this.get = function (ix) {
    return property[ix];
  }
}
 
</script>


Finally, muchos graci to Eric Lippert for helpful responses to ignorant queries I had in on all this.