Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions example/fake-window.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title> JSChannel Fake Window Examples </title>
<style type="text/css" media="screen">
#body {
font-family: georgia, 'bitstream vera serif', serif;
}

.output {
font-family: 'lucida console', monaco, 'andale mono', 'bitstream vera sans mono', consolas, monospace;
font-size: 80%;
border : 1px dashed grey;
padding: 10px;
margin-bottom: 20px;
}
</style>
<!-- note, a debug version is also available to us, that would validate
all sorts stuff, including the inputs and outputs to our functions -->
<script src="../src/jschannel.js"></script>
</head>
<body>

<h2> JSChannel fake window example </h2>
<p>
Welcome to the JSChannel fake window example page. View source and you'll
get an idea of how you can use Channel.buildFactory() to use jschannel
as a generic RPC mechanism that's not limited to cross-document messaging.
</p>

First, here is basic function invocation:
<div class="output" id="output1"></div>

Next, here&apos;s error handling:
<div class="output" id="output2"></div>

Next, here&apos;s notification output:
<div class="output" id="output3"></div>

Finally, here&apos;s callback invocation output:
<div class="output" id="output4"></div>

</body>
<script>
function FakeWindow(name) {
var listener = null;
var self = {
name: name,
addEventListener: function(event, cb) {
if (listener) throw new Error("listener already set for " + origin);
listener = cb;
},
postMessage: function(data, origin) {
setTimeout(function() {
listener({
origin: "null",
data: data,
source: self.postMessage.source
});
}, 0);
},
JSON: window.JSON
};

self.Channel = Channel.buildFactory(self);

return self;
}

var clientWindow = FakeWindow("client");
var serverWindow = FakeWindow("server");

clientWindow.postMessage.source = serverWindow;
serverWindow.postMessage.source = clientWindow;

var chan = clientWindow.Channel.build({
debugOutput: true,
window: serverWindow,
origin: "*",
scope: "testScope"
});

var serverChannel = serverWindow.Channel.build({
debugOutput: true,
window: clientWindow,
origin: "*",
scope: "testScope"
});

serverChannel.bind("reverse", function(trans, s) {
if (typeof s !== 'string') {
throw [ "invalid_arguments", 'argument to reverse function should be a string' ];
}
return s.split("").reverse().join("");
});

serverChannel.bind("sendNotification", function(trans, s) {
serverChannel.notify({method: "notify", params: "Hi my name is Simon, and I like to do drawings!" });
});

serverChannel.bind("charify", function(trans, a) {
a.startParse();
for (var i = 0; i < a.word.length; i++) {
a.gotChar(a.word[i]);
}
a.parseComplete();
});
</script>
<script>
function docLog(which, m) {
var tag = 'output' + which.toString();
m = "> " + m;
var e = document.createElement('div');
if (typeof e.innerText !== 'undefined') e.innerText = m;
else e.textContent = m;
document.getElementById(tag).appendChild(e);
}

// first let's run a basic invocation
docLog(1, "invoking reverse method with args 'hello world!'");
chan.call({
method: "reverse",
params: "hello world!",
success: function(v) {
docLog(1, "function returns: '" + v + "'" );
}
});

// let's screw up the arguments and see what happens
docLog(2, "invoking reverse method again, now with bogus arguments");
chan.call({
method: "reverse",
params: ["this is not a string"],
error: function(error, message) { docLog(2, "ERROR: " + error + " (" + message + ")"); },
success: function(v) { docLog(2, "function returns: '" + v + "'" ); }
});

// now let's make the child send us a notification. She exports a single function
// that will invoke a notification with the method 'notify'

// step 1 is to bind a function to listen for the notification
chan.bind("notify", function(t, s) { docLog(3, "got notification: " + s); });

// step 2, invoke the function on our child which will cause him to send us a notification
chan.call({method: "sendNotification", success: function() { } });

// finally, let's explore the 'callback' mechanism, which allows callbacks to be passed
// *as arguments*, and the recipient may invoke these callbacks any number of times before
// the completion of the function call.
chan.call({
method: "charify",
params: {
gotChar: function(c) { docLog(4, "gotChar callback invoked: '" + c + "'"); },
startParse: function() { docLog(4, "word charification has begun!"); },
parseComplete: function() { docLog(4, "word charification has completed!"); },
word: "appelicious"
},
success: function(v) { docLog(4, "charify all done!" ); }
});


</script>
</html>
10 changes: 9 additions & 1 deletion src/jschannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
*/

;var Channel = (function() {
"use strict";
"use strict";

var buildFactory = function buildFactory(window) {
// current transaction id, start out at a random *odd* number between 1 and a million
// There is one current transaction counter id per page, and it's shared between
// channel instances. That means of all messages posted from a single javascript
Expand Down Expand Up @@ -611,4 +612,11 @@
return obj;
}
};
};

var Channel = buildFactory(window);
Channel.buildFactory = buildFactory;

return Channel;

})();