Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Expose the public API for setting custom settings

  • Loading branch information...
commit 077214dba1017b5316a1ccd43950fdc74c52d072 1 parent 6005497
Remy Sharp remy authored
Showing with 201 additions and 31 deletions.
  1. +67 −0 public/js/chrome/sandbox.js
  2. +34 −31 public/js/jsbin.js
  3. +100 −0 public/sandbox.html
67 public/js/chrome/sandbox.js
View
@@ -0,0 +1,67 @@
+function Queue(processor) {
+ this.queue = [];
+ this.isReady = false;
+ this.processor = processor;
+}
+
+Queue.prototype = {
+ ready: function () {
+ if (!this.isReady) {
+ this.isReady = true;
+ this.queue.forEach(this.processor);
+ }
+ },
+ push: function (data) {
+ if (this.isReady) {
+ this.processor(data);
+ } else {
+ this.queue.push(data);
+ }
+ }
+};
+
+function Sandbox(url) {
+ function send(data) {
+ source.postMessage(data, frameHost);
+ }
+
+ var iframe = document.createElement('iframe');
+ frameHost = location.origin,
+ iframe.src = jsbin.root + '/sandbox.html?' + url,
+ body = document.body,
+ source = null,
+ guid = +new Date,
+ callbacks = {},
+ queue = new Queue(send);
+
+ iframe.style.display = 'none';
+ body.appendChild(iframe);
+
+ window.addEventListener('message', function (event) {
+ var result;
+
+ if (event.origin === frameHost) {
+ if (event.data === '__pong__') {
+ source = event.source;
+ queue.ready();
+ } else {
+ result = JSON.parse(event.data);
+ if (callbacks[result.guid]) {
+ callbacks[result.guid](result.data);
+ }
+ }
+ }
+ }, false);
+
+ iframe.onload = function () {
+ iframe.contentWindow.postMessage('__ping__', frameHost);
+ };
+
+ return {
+ get: function (what, callback) {
+ guid++;
+ callbacks[guid] = callback;
+ queue.push(JSON.stringify({ guid: guid, what: what }));
+ }
+ }
+}
65 public/js/jsbin.js
View
@@ -45,14 +45,17 @@ window['jsbin'] || (window['jsbin'] = {});
var storedSettings = localStorage.getItem('settings');
window.jsbin['settings'] = $.extend(JSON.parse(storedSettings || '{}'), jsbin['settings']);
+
// if the above code isn't dodgy, this for hellz bells is:
-jsbin['mobile'] = /WebKit.*Mobile.*/.test(navigator.userAgent);
+jsbin.mobile = /WebKit.*Mobile.*/.test(navigator.userAgent);
jsbin.tablet = /iPad/i.test(navigator.userAgent); // sue me.
-if (!storedSettings && window.location.toString() === jsbin.root + '/') {
+if (!storedSettings && window.location.toString() === jsbin.root + '/' ||
+ (location.search.indexOf('api=') !== -1 && window.location.toString().replace(/\?api=.*$/, '') === jsbin.root + '/')) {
// first timer - let's welcome them shall we, Dave?
localStorage.setItem('settings', '{}');
- window.location = jsbin.root + '/welcome/130/edit?html,live';
+ window.location = jsbin.root + '/welcome/130/edit?html,live'
+ + (location.search.indexOf('api=') !== -1 ? ',&' + location.search.substring(1) : '');
}
if (!jsbin.settings['codemirror']) {
@@ -90,27 +93,6 @@ jsbin.getURL = function () {
return url;
};
-function objectValue(path, context) {
- var props = path.split('.'),
- length = props.length,
- i = 1,
- currentProp = context || window,
- value; // = undefined
-
- if (currentProp[props[0]] !== undefined) {
- currentProp = currentProp[props[0]];
- for (; i < length; i++) {
- if (typeof currentProp[props[i]] === undefined) {
- break;
- } else if (i === length - 1) {
- value = currentProp[props[i]];
- }
- currentProp = currentProp[props[i]];
- }
- }
-
- return value;
-}
var $body = $('body'),
$document = $(document),
@@ -132,15 +114,36 @@ var $body = $('body'),
var panel = jsbin.panels.focused;
if (panel) sessionStorage.setItem('panel', panel.id);
- // try { // this causes errors in IE9 - so we'll use a try/catch to get through it
- // sessionStorage.setItem('line', editors[panel].getCursor().line);
- // sessionStorage.setItem('character', editors[panel].getCursor().ch);
- // } catch (e) {
- // sessionStorage.setItem('line', 0);
- // sessionStorage.setItem('character', 0);
- // }
};
+
+if (location.search.indexOf('api=') !== -1) {
+ (function () {
+ var urlParts = location.search.substring(1).split(','),
+ newUrlParts = [],
+ i = urlParts.length,
+ apiurl = '';
+
+ while (i--) {
+ if (urlParts[i].indexOf('api=') !== -1) {
+ apiurl = urlParts[i].replace(/&?api=/, '');
+ } else {
+ newUrlParts.push(urlParts[i]);
+ }
+ }
+
+ $.getScript(jsbin.root + '/js/chrome/sandbox.js', function () {
+ var sandbox = new Sandbox(apiurl);
+ sandbox.get('settings', function (data) {
+ $.extend(jsbin.settings, data);
+ window.location = location.pathname + (newUrlParts.length ? '?' + newUrlParts.join(',') : '');
+ });
+ });
+
+ }());
+}
+
+
$document.one('jsbinReady', function () {
$bin.removeAttr('style');
$body.addClass('ready');
100 public/sandbox.html
View
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8 />
+<title>iframe proxy</title>
+</head>
+<body>
+<script>
+// bashes the domain to set the port to null, disallowing writes from this frame upwards
+document.domain = document.domain;
+(function () {
+ function Queue(processor) {
+ this.queue = [];
+ this.isReady = false;
+ this.processor = processor;
+ }
+
+ Queue.prototype = {
+ ready: function () {
+ if (!this.isReady) {
+ this.isReady = true;
+ this.queue.forEach(this.processor);
+ }
+ },
+ push: function (data) {
+ if (this.isReady) {
+ this.processor(data);
+ } else {
+ this.queue.push(data);
+ }
+ }
+ };
+
+ var source = null,
+ origin = null,
+ queue = new Queue(send);
+
+ function objectValue(path, context) {
+ var props = path.split('.'),
+ length = props.length,
+ i = 1,
+ currentProp = context || window,
+ value = currentProp[path];
+ try {
+ if (currentProp[props[0]] !== undefined) {
+ currentProp = currentProp[props[0]];
+ for (; i < length; i++) {
+ if (typeof currentProp[props[i]] === undefined) {
+ break;
+ } else if (i === length - 1) {
+ value = currentProp[props[i]];
+ }
+ currentProp = currentProp[props[i]];
+ }
+ }
+ } catch (e) {
+ value = undefined;
+ }
+
+ return value;
+ }
+
+ function send(eventdata) {
+ var data = JSON.parse(eventdata),
+ result;
+ try {
+ result = JSON.stringify({ guid: data.guid, data: objectValue(data.what) });
+ } catch (e) {
+ result = JSON.stringify({ guid: data.guid, data: undefined });
+ }
+ source.postMessage(result, origin);
+ }
+
+ function ready() {
+ queue.ready();
+ }
+
+ if (location.search.substring(1)) {
+ (function () {
+ var script = document.createElement('script');
+ script.src = location.search.substring(1);
+ script.onreadystatechange = ready;
+ script.onload = ready;
+ document.body.appendChild(script);
+ }());
+ }
+
+ window.addEventListener('message', function (event) {
+ if (event.data === '__ping__') {
+ source = event.source;
+ origin = event.origin;
+ source.postMessage('__pong__', origin);
+ } else {
+ queue.push(event.data);
+ }
+ }, false);
+}());
+</script>
+</body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.