diff --git a/client/constants.js b/client/constants.js
index 967df39b..f6256cad 100644
--- a/client/constants.js
+++ b/client/constants.js
@@ -31,5 +31,7 @@ export const SET_PROJECTS = 'SET_PROJECTS';
export const SET_SELECTED_FILE = 'SET_SELECTED_FILE';
+export const CONSOLE_EVENT = 'CONSOLE_EVENT';
+
// eventually, handle errors more specifically and better
export const ERROR = 'ERROR';
diff --git a/client/modules/IDE/actions/ide.js b/client/modules/IDE/actions/ide.js
index 0bcbc414..eec73884 100644
--- a/client/modules/IDE/actions/ide.js
+++ b/client/modules/IDE/actions/ide.js
@@ -24,3 +24,10 @@ export function setSelectedFile(fileId) {
selectedFile: fileId
};
}
+
+export function dispatchConsoleEvent(...args) {
+ return {
+ type: ActionTypes.CONSOLE_EVENT,
+ event: args[0].data
+ };
+}
diff --git a/client/modules/IDE/components/Console.js b/client/modules/IDE/components/Console.js
new file mode 100644
index 00000000..06b39c8c
--- /dev/null
+++ b/client/modules/IDE/components/Console.js
@@ -0,0 +1,49 @@
+import React, { PropTypes } from 'react';
+
+const consoleMax = 5;
+
+class Console extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.children = [];
+ }
+
+ shouldComponentUpdate(nextProps) {
+ // clear children if paused, but only update when new consoleEvent happens
+ if (!nextProps.isPlaying) {
+ this.children = [];
+ }
+ return nextProps.consoleEvent !== this.props.consoleEvent;
+ }
+
+ render() {
+ const args = this.props.consoleEvent.arguments;
+ const method = this.props.consoleEvent.method;
+
+ const nextChild = (
+
+ {Object.keys(args).map((key) => {args[key]})}
+
+ );
+ this.children.push(nextChild);
+
+ if (this.children.length > consoleMax) {
+ this.children = this.children.slice(0, 1);
+ }
+
+ return (
+
+ {this.children}
+
+ );
+ }
+
+}
+
+Console.propTypes = {
+ consoleEvent: PropTypes.object,
+ isPlaying: PropTypes.bool.isRequired
+};
+
+export default Console;
diff --git a/client/modules/IDE/components/PreviewFrame.js b/client/modules/IDE/components/PreviewFrame.js
index b0313441..ac42e845 100644
--- a/client/modules/IDE/components/PreviewFrame.js
+++ b/client/modules/IDE/components/PreviewFrame.js
@@ -3,14 +3,68 @@ import ReactDOM from 'react-dom';
import escapeStringRegexp from 'escape-string-regexp';
import srcDoc from 'srcdoc-polyfill';
+const hijackConsoleScript = ``;
+
class PreviewFrame extends React.Component {
componentDidMount() {
- this.hijackConsole();
-
if (this.props.isPlaying) {
this.renderFrameContents();
}
+
+ window.addEventListener('message', (msg) => {
+ if (msg.data.source === 'sketch') {
+ this.props.dispatchConsoleEvent(msg);
+ }
+ });
}
componentDidUpdate(prevProps) {
@@ -53,29 +107,11 @@ class PreviewFrame extends React.Component {
// htmlHeadContents = htmlHeadContents.slice(1, htmlHeadContents.length - 2);
// htmlHeadContents += '\n';
// htmlFile = htmlFile.replace(/(?:)([\s\S]*?)(?:<\/head>)/gmi, `\n${htmlHeadContents}\n`);
+ htmlFile += hijackConsoleScript;
return htmlFile;
}
- hijackConsole() {
- const iframeWindow = ReactDOM.findDOMNode(this).contentWindow;
- const originalConsole = iframeWindow.console;
- iframeWindow.console = {};
-
- const methods = [
- 'debug', 'clear', 'error', 'info', 'log', 'warn'
- ];
-
- methods.forEach((method) => {
- iframeWindow.console[method] = (...theArgs) => {
- originalConsole[method].apply(originalConsole, theArgs);
-
- // TO DO: do something with the arguments
- // window.alert(JSON.stringify(theArgs));
- };
- });
- }
-
renderSketch() {
const doc = ReactDOM.findDOMNode(this);
if (this.props.isPlaying) {
@@ -107,7 +143,7 @@ class PreviewFrame extends React.Component {
frameBorder="0"
title="sketch output"
sandbox="allow-scripts allow-pointer-lock allow-same-origin allow-popups allow-modals allow-forms"
- >
+ />
);
}
}
@@ -120,7 +156,9 @@ PreviewFrame.propTypes = {
content: PropTypes.string.isRequired
}),
jsFiles: PropTypes.array.isRequired,
- cssFiles: PropTypes.array.isRequired
+ cssFiles: PropTypes.array.isRequired,
+ dispatchConsoleEvent: PropTypes.func.isRequired,
+ children: PropTypes.element
};
export default PreviewFrame;
diff --git a/client/modules/IDE/pages/IDEView.js b/client/modules/IDE/pages/IDEView.js
index c7308fa9..62f5956e 100644
--- a/client/modules/IDE/pages/IDEView.js
+++ b/client/modules/IDE/pages/IDEView.js
@@ -5,6 +5,7 @@ import PreviewFrame from '../components/PreviewFrame';
import Toolbar from '../components/Toolbar';
import Preferences from '../components/Preferences';
import Nav from '../../../components/Nav';
+import Console from '../components/Console';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as FileActions from '../actions/files';
@@ -77,8 +78,14 @@ class IDEView extends React.Component {
}
isPlaying={this.props.ide.isPlaying}
+ dispatchConsoleEvent={this.props.dispatchConsoleEvent}
+ />
+
+
);
}
}
@@ -92,7 +99,8 @@ IDEView.propTypes = {
createProject: PropTypes.func.isRequired,
saveProject: PropTypes.func.isRequired,
ide: PropTypes.shape({
- isPlaying: PropTypes.bool.isRequired
+ isPlaying: PropTypes.bool.isRequired,
+ consoleEvent: PropTypes.object
}).isRequired,
startSketch: PropTypes.func.isRequired,
stopSketch: PropTypes.func.isRequired,
@@ -125,7 +133,8 @@ IDEView.propTypes = {
setSelectedFile: PropTypes.func.isRequired,
htmlFile: PropTypes.object.isRequired,
jsFiles: PropTypes.array.isRequired,
- cssFiles: PropTypes.array.isRequired
+ cssFiles: PropTypes.array.isRequired,
+ dispatchConsoleEvent: PropTypes.func.isRequired
};
function mapStateToProps(state) {
diff --git a/client/modules/IDE/reducers/ide.js b/client/modules/IDE/reducers/ide.js
index 9c4c5b88..7fc1d033 100644
--- a/client/modules/IDE/reducers/ide.js
+++ b/client/modules/IDE/reducers/ide.js
@@ -2,7 +2,11 @@ import * as ActionTypes from '../../../constants';
const initialState = {
isPlaying: false,
- selectedFile: '1'
+ selectedFile: '1',
+ consoleEvent: {
+ method: undefined,
+ arguments: []
+ }
};
const ide = (state = initialState, action) => {
@@ -17,6 +21,8 @@ const ide = (state = initialState, action) => {
case ActionTypes.SET_PROJECT:
case ActionTypes.NEW_PROJECT:
return Object.assign({}, state, { selectedFile: action.selectedFile });
+ case ActionTypes.CONSOLE_EVENT:
+ return Object.assign({}, state, { consoleEvent: action.event });
default:
return state;
}
diff --git a/client/styles/components/_console.scss b/client/styles/components/_console.scss
new file mode 100644
index 00000000..f1502c46
--- /dev/null
+++ b/client/styles/components/_console.scss
@@ -0,0 +1,14 @@
+.preview-console {
+ position: fixed;
+ width:100%;
+ height:60px;
+ right:0px;
+ bottom: 0px;
+ background:grey;
+ z-index:1000;
+
+ & > {
+ position:relative;
+ text-align:left;
+ }
+}
\ No newline at end of file