Repository: genekogan/p5js-osc Branch: master Commit: 42e1a698f3a5 Files: 40 Total size: 5.5 MB Directory structure: gitextract_v0gih5tc/ ├── .gitignore ├── Applications.md ├── README.md ├── bridge.js ├── p5-ableton/ │ ├── basic-percussion/ │ │ ├── Ableton Project Info/ │ │ │ └── Project8_1.cfg │ │ ├── Icon │ │ ├── basic-percussion.als │ │ └── receive-osc.amxd │ ├── index.html │ ├── libraries/ │ │ ├── p5.dom.js │ │ ├── p5.js │ │ ├── p5.sound.js │ │ └── socket.io.js │ └── sketch.js ├── p5-basic/ │ ├── ProcessingOSC/ │ │ └── ProcessingOSC.pde │ ├── index.html │ ├── libraries/ │ │ ├── p5.dom.js │ │ ├── p5.js │ │ ├── p5.sound.js │ │ └── socket.io.js │ └── sketch.js ├── p5-faceOsc/ │ ├── index.html │ ├── libraries/ │ │ ├── p5.dom.js │ │ ├── p5.js │ │ ├── p5.sound.js │ │ └── socket.io.js │ └── sketch.js ├── p5-faceOsc-flocking/ │ ├── index.html │ ├── libraries/ │ │ ├── p5.dom.js │ │ ├── p5.js │ │ ├── p5.sound.js │ │ └── socket.io.js │ └── sketch.js ├── p5-kinect/ │ ├── index.html │ ├── libraries/ │ │ ├── p5.dom.js │ │ ├── p5.js │ │ ├── p5.sound.js │ │ └── socket.io.js │ └── sketch.js └── package.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ node_modules/ .DS_Store package-lock.json ================================================ FILE: Applications.md ================================================ ### osc in p5.js adapted from [osc-web](https://github.com/automata/osc-web). #### setup 1) install [node](https://nodejs.org/) 2) $ git https://github.com/genekogan/p5js-osc $ cd p5js-osc/ $ npm install 3) $ node bridge.js This command runs the file in this repo called "bridge.js", it runs on the server. Is is a javascript file that creates a connection using socket.io. This file creates a listener on the server, which is where the computer is listening for packets sent using UDP. Any computer can support sending and receiving network packets, eg. it can request info, by sending an http request (UDP). (What is socket.io? Socket is one of the most common node modules which facilitates communication between the client and the server. bridge.js converts into socket which then passes it to OSC) We need to use something like OSC because p5js (unlike processing) does not have access to the drivers in your computer. This is for good reason, we wouldn't want javascript on a server to be able to access your drivers eh? So if you want to use something like p5 and the kinect, you need to send the data from the device, which needs access to your computer's drivers, and then send it to p5js over OSC (which is actually via UDP). So your computer is being both the server (node) and the client (p5). If you then open any of the index.html pages in the folders of the repo. You may need to start a local server if you start using video or images etc. in your sketch. When you open index.html from a sketch in a browser, it connects to bridge.js. Note: if you try to reload the index.html page in the browser. You'll notice you get an error and node will stop running. When you start node, the server communicates with your application over a particular port. It only allows one application to connect over a single port and it won't let anything else connect to it. So when you reload, you are not actually closing the connection, and node thinks you are another application trying to connect and will crash. So for now, you have to restart node everytime you refresh your browser (do this in the terminal where you are running bridge CRL-c to quit and then relaunch using as before: $node bridge.js 4) send OSC to p5 via port 3333. send OSC from p5 via port 3334 ###examples - basic (done) - in: kinect - in: leap-motion - in: faceosc - in: midi device? - out: ableton? ####Example sending OSC data from Processing and receiving in p5js: *In Processing:* - Install the osvP5 library from the import library menu in Processing. - Take a look at the simple Processing example called oscP5sendReceive. - Modify it to send the mouse coordinates over OSC everytime the mouse is pressed. *Getting this talking to p5:* - To get this running. Run the Processing sketch. Then, make sure you are running bridge.js in your terminal (always launch this on the server before you launch the p5 sketch). Then open index.html (from the p5-app folder) in your browser. - In your browser javascript console, you should then see the mouse coordinates print out when you click in the Processing sketch. - Note: The order you start everything here is really important. If you get an error. Close the p5 sketch in the browser. Kill node with CTRL c. Then launch the server (bridge.js) again and then open the p5 sketch again. - A quick way to do this in chrome is using the shortcut CMD + SHIFT + T (reopens the last tab, this helps to relaunch your p5) - In p5 you can animate something with these mouse coordinates. ####Example sending OSC data from OpenFrameworks Face tracker and receiving in p5js: *FaceOSC* - (SORRY at the moment facetracker is only released for mac) - Javascript is slow for facetracking so we can use OF facetracker to do the face work and send the data to javascript over OSC. - Download facetracker in OF from here. Get v 1.1 a the bottom of the page. - See the documentation of this in the repo. - Fun things to try with this. Draw a face on a piece of paper, can facetracker recognize it? *Facetracker options* - Pose and gesture refers to pose and gesture of the face. Direction of the face, size of eyes, width of mouth etc. - If you have raw on, you are sending raw data (the coordinates of the facial mesh) and it sends 1032 numbers 30 times a second. A lot of data! Note, if you are not using this it is a waste to send all this data unless you need it. - Syphon sends the image (but keep this off for now). - Now start index.html of p5-faceOsc. You should see the wireframe of your face in your browser. *FaceOSC-flocking* - try this, this is an example from Dan Shiffman to see more of what's possible. - See inside this example for more info on the data that faceOSC provides. ####Example using the Kinect - Download the OSC kinect 1 application made by jpbellona. Get the zip from the [repo here.](https://github.com/jpbellona/simpleKinect) - (If you have a windows machine you can use a kinect 2 and use [this repo.](https://github.com/microcosm/ofxKinectV2-OSC)) - Find the Processing sketch called simpleKinect in this repo. - This sketch sends kinect data to OSC. We can then use this in p5. - Careful, this still has some bugs. ####Example using Ableton - To get this working you need to download and install [Max for Live (M4L)](https://www.ableton.com/en/live/max-for-live/). M4L is a somewhat truncated version of MaxMSP. Ableton doesn't support OSC directly, but it does support M4L devices which can convert our OSC to midi so that ableton can receive data from our p5 app. - The example in this repo will play a note each time our ball in p5 hits a wall. - So you can create a p5 app and control ableton from it. *These are very rough notes from the p5 OSC workshop held at ITP in January 2016. Ableton example updated May 2021 by Billy Bennett* ================================================ FILE: README.md ================================================ ### osc in p5.js adapted from [osc-web](https://github.com/automata/osc-web). #### setup Install [node](https://nodejs.org/) Clone this repo and run npm to get required libraries. $ git clone https://github.com/genekogan/p5js-osc $ cd p5js-osc/ $ npm install Start node. $ node bridge.js Then run any of the sketches in a browser or from the editor. Can also be run locally (i.e. just open index.html). Inside each sketch, when you run `setupOSC` you give it the input and output ports (default 3333, 3334). ### Applications Thanks [Tega Brain](https://github.com/tegacodes) for extended [notes on the included applications](https://github.com/genekogan/p5js-osc/blob/master/Applications.md). There is a [demo video](https://vimeo.com/157024760) of the included examples. Examples: - Processing (needs [oscP5](www.sojamo.de/oscP5)) - Ableton Live (needs [M4L (Max For Live)](https://www.ableton.com/en/live/max-for-live/) and [KinectOSC](https://github.com/genekogan/KinectOSC/releases)) - FaceTracker (needs [FaseOSC](https://github.com/kylemcdonald/ofxFaceTracker/releases)) - Kinect (needs [KinectOSC](https://github.com/genekogan/KinectOSC/releases)) Low-hanging fruits. - [TouchOSC](http://hexler.net/software/touchosc) to control p5 from a phone/tablet ### p5.js - arduino bridge [@lorenzoromagnoli](https://github.com/lorenzoromagnoli) made this into a [standalone application](https://github.com/lorenzoromagnoli/p5js-osc) using [electron](https://electron.atom.io/) which bridges p5.js to arduino over OSC. ================================================ FILE: bridge.js ================================================ var osc = require('node-osc'); var io = require('socket.io')(8081); var oscServer, oscClient; var isConnected = false; io.sockets.on('connection', function (socket) { console.log('connection'); socket.on("config", function (obj) { isConnected = true; oscServer = new osc.Server(obj.server.port, obj.server.host); oscClient = new osc.Client(obj.client.host, obj.client.port); oscClient.send('/status', socket.sessionId + ' connected'); oscServer.on('message', function(msg, rinfo) { socket.emit("message", msg); }); socket.emit("connected", 1); }); socket.on("message", function (obj) { oscClient.send.apply(oscClient, obj); }); socket.on('disconnect', function(){ if (isConnected) { oscServer.kill(); oscClient.kill(); } }); }); ================================================ FILE: p5-ableton/basic-percussion/Icon ================================================ ================================================ FILE: p5-ableton/index.html ================================================ ================================================ FILE: p5-ableton/libraries/p5.dom.js ================================================ /*! p5.dom.js v0.2.6 November 10, 2015 */ /** *

The web is much more than just canvas and p5.dom makes it easy to interact * with other HTML5 objects, including text, hyperlink, image, input, video, * audio, and webcam.

*

There is a set of creation methods, DOM manipulation methods, and * an extended p5.Element that supports a range of HTML elements. See the * * beyond the canvas tutorial for a full overview of how this addon works. * *

Methods and properties shown in black are part of the p5.js core, items in * blue are part of the p5.dom library. You will need to include an extra file * in order to access the blue functions. See the * using a library * section for information on how to include this library. p5.dom comes with * p5 complete or you can download the single file * * here.

*

See tutorial: beyond the canvas * for more info on how to use this libary. * * @module p5.dom * @submodule p5.dom * @for p5.dom * @main */ (function (root, factory) { if (typeof define === 'function' && define.amd) define('p5.dom', ['p5'], function (p5) { (factory(p5));}); else if (typeof exports === 'object') factory(require('../p5')); else factory(root['p5']); }(this, function (p5) { // ============================================================================= // p5 additions // ============================================================================= /** * Searches the page for an element with the given ID, class, or tag name (using the '#' or '.' * prefixes to specify an ID or class respectively, and none for a tag) and returns it as * a p5.Element. If a class or tag name is given with more than 1 element, * only the first element will be returned. * The DOM node itself can be accessed with .elt. * Returns null if none found. You can also specify a container to search within. * * @method select * @param {String} name id, class, or tag name of element to search for * @param {String} [container] id, p5.Element, or HTML element to search within * @return {Object/p5.Element|Null} p5.Element containing node found * @example *

* function setup() { * createCanvas(100,100); * //translates canvas 50px down * select('canvas').translate(0,50); * } *
*
* // these are all valid calls to select() * var a = select('#moo'); * var b = select('#blah', '#myContainer'); * var c = select('#foo', b); * var d = document.getElementById('beep'); * var e = select('p', d); *
* */ p5.prototype.select = function (e, p) { var res = null; var container = getContainer(p); if (e[0] === '.'){ e = e.slice(1); res = container.getElementsByClassName(e); if (res.length) { res = res[0]; } else { res = null; } }else if (e[0] === '#'){ e = e.slice(1); res = container.getElementById(e); }else { res = container.getElementsByTagName(e); if (res.length) { res = res[0]; } else { res = null; } } if (res) { return wrapElement(res); } else { return null; } }; /** * Searches the page for elements with the given class or tag name (using the '.' prefix * to specify a class and no prefix for a tag) and returns them as p5.Elements * in an array. * The DOM node itself can be accessed with .elt. * Returns an empty array if none found. * You can also specify a container to search within. * * @method selectAll * @param {String} name class or tag name of elements to search for * @param {String} [container] id, p5.Element, or HTML element to search within * @return {Array} Array of p5.Elements containing nodes found * @example *
* function setup() { * createButton('btn'); * createButton('2nd btn'); * createButton('3rd btn'); * var buttons = selectAll('button'); * * for (var i = 0; i < buttons.length; i++){ * buttons[i].size(100,100); * } * } *
*
* // these are all valid calls to selectAll() * var a = selectAll('.moo'); * var b = selectAll('div'); * var c = selectAll('button', '#myContainer'); * var d = select('#container'); * var e = selectAll('p', d); * var f = document.getElementById('beep'); * var g = select('.blah', f); *
* */ p5.prototype.selectAll = function (e, p) { var arr = []; var res; var container = getContainer(p); if (e[0] === '.'){ e = e.slice(1); res = container.getElementsByClassName(e); } else { res = container.getElementsByTagName(e); } if (res) { for (var j = 0; j < res.length; j++) { var obj = wrapElement(res[j]); arr.push(obj); } } return arr; }; /** * Helper function for select and selectAll */ function getContainer(p) { var container = document; if (typeof p === 'string' && p[0] === '#'){ p = p.slice(1); container = document.getElementById(p) || document; } else if (p instanceof p5.Element){ container = p.elt; } else if (p instanceof HTMLElement){ container = p; } return container; } /** * Helper function for getElement and getElements. */ function wrapElement(elt) { if(elt.tagName === "INPUT" && elt.type === "checkbox") { var converted = new p5.Element(elt); converted.checked = function(){ if (arguments.length === 0){ return this.elt.checked; } else if(arguments[0]) { this.elt.checked = true; } else { this.elt.checked = false; } return this; }; return converted; } else if (elt.tagName === "VIDEO" || elt.tagName === "AUDIO") { return new p5.MediaElement(elt); } else { return new p5.Element(elt); } } /** * Removes all elements created by p5, except any canvas / graphics * elements created by createCanvas or createGraphics. * Event handlers are removed, and element is removed from the DOM. * @method removeElements * @example *
* function setup() { * createCanvas(100, 100); * createDiv('this is some text'); * createP('this is a paragraph'); * } * function mousePressed() { * removeElements(); // this will remove the div and p, not canvas * } *
* */ p5.prototype.removeElements = function (e) { for (var i=0; i * var myDiv; * function setup() { * myDiv = createDiv('this is some text'); * } * */ /** * Creates a <p></p> element in the DOM with given inner HTML. Used * for paragraph length text. * Appends to the container node if one is specified, otherwise * appends to body. * * @method createP * @param {String} html inner HTML for element created * @return {Object/p5.Element} pointer to p5.Element holding created node * @example *
* var myP; * function setup() { * myP = createP('this is some text'); * } *
*/ /** * Creates a <span></span> element in the DOM with given inner HTML. * Appends to the container node if one is specified, otherwise * appends to body. * * @method createSpan * @param {String} html inner HTML for element created * @return {Object/p5.Element} pointer to p5.Element holding created node * @example *
* var mySpan; * function setup() { * mySpan = createSpan('this is some text'); * } *
*/ var tags = ['div', 'p', 'span']; tags.forEach(function(tag) { var method = 'create' + tag.charAt(0).toUpperCase() + tag.slice(1); p5.prototype[method] = function(html) { var elt = document.createElement(tag); elt.innerHTML = typeof html === undefined ? "" : html; return addElement(elt, this); } }); /** * Creates an <img /> element in the DOM with given src and * alternate text. * Appends to the container node if one is specified, otherwise * appends to body. * * @method createImg * @param {String} src src path or url for image * @param {String} [alt] alternate text to be used if image does not load * @param {Function} [successCallback] callback to be called once image data is loaded * @return {Object/p5.Element} pointer to p5.Element holding created node * @example *
* var img; * function setup() { * img = createImg('http://p5js.org/img/asterisk-01.png'); * } *
*/ p5.prototype.createImg = function() { var elt = document.createElement('img'); var args = arguments; var self; var setAttrs = function(){ self.width = elt.offsetWidth; self.height = elt.offsetHeight; if (args.length > 1 && typeof args[1] === 'function'){ self.fn = args[1]; self.fn(); }else if (args.length > 1 && typeof args[2] === 'function'){ self.fn = args[2]; self.fn(); } }; elt.src = args[0]; if (args.length > 1 && typeof args[1] === 'string'){ elt.alt = args[1]; } elt.onload = function(){ setAttrs(); } self = addElement(elt, this); return self; }; /** * Creates an <a></a> element in the DOM for including a hyperlink. * Appends to the container node if one is specified, otherwise * appends to body. * * @method createA * @param {String} href url of page to link to * @param {String} html inner html of link element to display * @param {String} [target] target where new link should open, * could be _blank, _self, _parent, _top. * @return {Object/p5.Element} pointer to p5.Element holding created node * @example *
* var myLink; * function setup() { * myLink = createA('http://p5js.org/', 'this is a link'); * } *
*/ p5.prototype.createA = function(href, html, target) { var elt = document.createElement('a'); elt.href = href; elt.innerHTML = html; if (target) elt.target = target; return addElement(elt, this); }; /** INPUT **/ /** * Creates a slider <input></input> element in the DOM. * Use .size() to set the display length of the slider. * Appends to the container node if one is specified, otherwise * appends to body. * * @method createSlider * @param {Number} min minimum value of the slider * @param {Number} max maximum value of the slider * @param {Number} [value] default value of the slider * @return {Object/p5.Element} pointer to p5.Element holding created node * @example *
* var slider; * function setup() { * slider = createSlider(0, 255, 100); * slider.position(10, 10); * slider.style('width', '80px'); * } * * function draw() { * var val = slider.value(); * background(val); * } *
*/ p5.prototype.createSlider = function(min, max, value, step) { var elt = document.createElement('input'); elt.type = 'range'; elt.min = min; elt.max = max; if (step) elt.step = step; if (typeof(value) === "number") elt.value = value; return addElement(elt, this); }; /** * Creates a <button></button> element in the DOM. * Use .size() to set the display size of the button. * Use .mousePressed() to specify behavior on press. * Appends to the container node if one is specified, otherwise * appends to body. * * @method createButton * @param {String} label label displayed on the button * @param {String} [value] value of the button * @return {Object/p5.Element} pointer to p5.Element holding created node * @example *
* var button; * function setup() { * createCanvas(100, 100); * background(0); * button = createButton('click me'); * button.position(19, 19); * button.mousePressed(changeBG); * } * * function changeBG() { * var val = random(255); * background(val); * } *
*/ p5.prototype.createButton = function(label, value) { var elt = document.createElement('button'); elt.innerHTML = label; elt.value = value; if (value) elt.value = value; return addElement(elt, this); }; /** * Creates a checkbox <input></input> element in the DOM. * Calling .checked() on a checkbox returns if it is checked or not * * @method createCheckbox * @param {String} [label] label displayed after checkbox * @param {boolean} [value] value of the checkbox; checked is true, unchecked is false.Unchecked if no value given * @return {Object/p5.Element} pointer to p5.Element holding created node * @example *
* var checkbox; * * function setup() { * checkbox = createCheckbox('label', false); * checkbox.changed(myCheckedEvent); * } * * function myCheckedEvent() { * if (this.checked()) { * console.log("Unchecking!"); * } else { * console.log("Checking!"); * } * *
*/ p5.prototype.createCheckbox = function() { var elt = document.createElement('input'); elt.type = 'checkbox'; //checkbox must be wrapped in p5.Element before label so that label appears after var self = addElement(elt, this); self.checked = function(){ if (arguments.length === 0){ return self.elt.checked; }else if(arguments[0]){ self.elt.checked = true; }else{ self.elt.checked = false; } return self; }; this.value = function(val){ self.value = val; return this; }; if (arguments[0]){ var ran = Math.random().toString(36).slice(2); var label = document.createElement('label'); elt.setAttribute('id', ran); label.htmlFor = ran; self.value(arguments[0]); label.appendChild(document.createTextNode(arguments[0])); addElement(label, this); } if (arguments[1]){ elt.checked = true; } return self; }; /** * Creates a dropdown menu <select></select> element in the DOM. * @method createSelect * @param {boolean} [multiple] [true if dropdown should support multiple selections] * @return {Object/p5.Element} pointer to p5.Element holding created node * @example *
* var sel; * * function setup() { * textAlign(CENTER); * background(200); * sel = createSelect(); * sel.position(10, 10); * sel.option('pear'); * sel.option('kiwi'); * sel.option('grape'); * sel.changed(mySelectEvent); * } * * function mySelectEvent() { * var item = sel.value(); * background(200); * text("it's a "+item+"!", 50, 50); * } *
*/ p5.prototype.createSelect = function(mult) { var elt = document.createElement('select'); if (mult){ elt.setAttribute('multiple', 'true'); } var self = addElement(elt, this); self.option = function(name, value){ var opt = document.createElement('option'); opt.innerHTML = name; if (arguments.length > 1) opt.value = value; else opt.value = name; elt.appendChild(opt); }; self.selected = function(value){ var arr = []; if (arguments.length > 0){ for (var i = 0; i < this.elt.length; i++){ if (value.toString() === this.elt[i].value){ this.elt.selectedIndex = i; } } return this; }else{ if (mult){ for (var i = 0; i < this.elt.selectedOptions.length; i++){ arr.push(this.elt.selectedOptions[i].value); } return arr; }else{ return this.elt.value; } } }; return self; }; /** * Creates a radio button <input></input> element in the DOM. * * @method createRadio * @param {String} [divId] the id and name of the created div and input field respectively * @return {Object/p5.Element} pointer to p5.Element holding created node */ p5.prototype.createRadio = function() { var radios = document.querySelectorAll("input[type=radio]"); var count = 0; if(radios.length > 1){ console.log(radios,radios[0].name); var length = radios.length; var prev=radios[0].name; var current = radios[1].name; count=1; for(var i = 1; i < length; i++ ){ current = radios[i].name; if(prev != current){ count++; } prev = current; } } else if (radios.length == 1){ count = 1; } var elt = document.createElement('div'); var self = addElement(elt, this); var times = -1; self.option = function(name, value){ var opt = document.createElement('input'); opt.type = 'radio'; opt.innerHTML = name; if (arguments.length > 1) opt.value = value; else opt.value = name; opt.setAttribute('name',"defaultradio"+count); elt.appendChild(opt); if (name){ times++; var ran = Math.random().toString(36).slice(2); var label = document.createElement('label'); opt.setAttribute('id', "defaultradio"+count+"-"+times); label.htmlFor = "defaultradio"+count+"-"+times; label.appendChild(document.createTextNode(name)); elt.appendChild(label); } return opt; }; self.selected = function(){ var length = this.elt.childNodes.length; if(arguments[0]) { for (var i = 0; i < length; i+=2){ if(this.elt.childNodes[i].value == arguments[0]) this.elt.childNodes[i].checked = true; } return this; } else { for (var i = 0; i < length; i+=2){ if(this.elt.childNodes[i].checked == true) return this.elt.childNodes[i].value; } } }; self.value = function(){ var length = this.elt.childNodes.length; if(arguments[0]) { for (var i = 0; i < length; i+=2){ if(this.elt.childNodes[i].value == arguments[0]) this.elt.childNodes[i].checked = true; } return this; } else { for (var i = 0; i < length; i+=2){ if(this.elt.childNodes[i].checked == true) return this.elt.childNodes[i].value; } return ""; } }; return self }; /** * Creates an <input></input> element in the DOM for text input. * Use .size() to set the display length of the box. * Appends to the container node if one is specified, otherwise * appends to body. * * @method createInput * @param {Number} [value] default value of the input box * @return {Object/p5.Element} pointer to p5.Element holding created node * @example *
* function setup(){ * var inp = createInput(''); * inp.input(myInputEvent); * } * * function myInputEvent(){ * console.log('you are typing: ', this.value()); * } * *
*/ p5.prototype.createInput = function(value) { var elt = document.createElement('input'); elt.type = 'text'; if (value) elt.value = value; return addElement(elt, this); }; /** * Creates an <input></input> element in the DOM of type 'file'. * This allows users to select local files for use in a sketch. * * @method createFileInput * @param {Function} [callback] callback function for when a file loaded * @param {String} [multiple] optional to allow multiple files selected * @return {Object/p5.Element} pointer to p5.Element holding created DOM element */ p5.prototype.createFileInput = function(callback, multiple) { // Is the file stuff supported? if (window.File && window.FileReader && window.FileList && window.Blob) { // Yup, we're ok and make an input file selector var elt = document.createElement('input'); elt.type = 'file'; // If we get a second argument that evaluates to true // then we are looking for multiple files if (multiple) { // Anything gets the job done elt.multiple = 'multiple'; } // Function to handle when a file is selected // We're simplifying life and assuming that we always // want to load every selected file function handleFileSelect(evt) { // These are the files var files = evt.target.files; // Load each one and trigger a callback for (var i = 0; i < files.length; i++) { var f = files[i]; var reader = new FileReader(); function makeLoader(theFile) { // Making a p5.File object var p5file = new p5.File(theFile); return function(e) { p5file.data = e.target.result; callback(p5file); }; }; reader.onload = makeLoader(f); // Text or data? // This should likely be improved if (f.type.indexOf('text') > -1) { reader.readAsText(f); } else { reader.readAsDataURL(f); } } } // Now let's handle when a file was selected elt.addEventListener('change', handleFileSelect, false); return addElement(elt, this); } else { console.log('The File APIs are not fully supported in this browser. Cannot create element.'); } }; /** VIDEO STUFF **/ function createMedia(pInst, type, src, callback) { var elt = document.createElement(type); if (typeof src === 'string') { src = [src]; } for (var i=0; i