arnaucube
arnaucube/imgProcessingProjectsPublic Self-hosted repository
imgProcessingProjects/clmtracker/libs/p5.dom.js
clmtracker/libs/p5.dom.jsRaw
  1/*! p5.dom.js v0.1.5 November 7, 2014 */
  2/**
  3 * <p>The web is much more than just canvas and p5.dom makes it easy to interact 
  4 * with other HTML5 objects, including text, hyperlink, image, input, video, 
  5 * audio, and webcam.</p>
  6 * <p>There is a set of creation methods, DOM manipulation methods, and
  7 * an extended p5.Element that supports a range of HTML elements. See the 
  8 * <a href="https://github.com/lmccart/p5.js/wiki/Beyond-the-canvas">
  9 * beyond the canvas tutorial</a> for a full overview of how this addon works.
 10 *
 11 * <p>Methods and properties shown in black are part of the p5.js core, items in
 12 * blue are part of the p5.dom library. You will need to include an extra file
 13 * in order to access the blue functions. See the
 14 * <a href="http://p5js.org/libraries/#using-a-library">using a library</a>
 15 * section for information on how to include this library. p5.dom comes with
 16 * <a href="http://p5js.org/download">p5 complete</a> or you can download the single file
 17 * <a href="https://raw.githubusercontent.com/lmccart/p5.js/master/lib/addons/p5.dom.js">
 18 * here</a>.</p>
 19 * <p>See <a href="https://github.com/lmccart/p5.js/wiki/Beyond-the-canvas">tutorial: beyond the canvas]</a>
 20 * for more info on how to use this libary.</a>
 21 *
 22 * @module p5.dom
 23 * @submodule p5.dom
 24 * @for p5.dom
 25 * @main
 26 */
 27
 28var p5DOM = (function(){
 29
 30// =============================================================================
 31//                         p5 additions
 32// =============================================================================
 33
 34  /**
 35   * Searches the page for an element with given ID and returns it as
 36   * a p5.Element. The DOM node itself can be accessed with .elt.
 37   * Returns null if none found.
 38   * 
 39   * @method getElement
 40   * @param  {String} id id of element to search for
 41   * @return {Object/p5.Element|Null} p5.Element containing node found
 42   */
 43  p5.prototype.getElement = function (e) {
 44    var res = document.getElementById(e);
 45    if (res) {
 46      return new p5.Element(res);
 47    } else {
 48      return null;
 49    }
 50  };
 51
 52  /**
 53   * Searches the page for elements with given class and returns an
 54   * array of p5.Elements. The DOM nodes themselves can be accessed
 55   * with .elt. Returns an empty array if none found.
 56   * 
 57   * @method getElements
 58   * @param  {String} class class name of elements to search for
 59   * @return {Array} array of p5.Element wrapped nodes found
 60   */
 61  p5.prototype.getElements = function (e) {
 62    var arr = [];
 63    var res = document.getElementsByClassName(e);
 64    if (res) {
 65      for (var j = 0; j < res.length; j++) {
 66        var obj = new p5.Element(res[j]);
 67        arr.push(obj);
 68      }
 69    }
 70    return arr;
 71  };
 72
 73  /**
 74   * Removes all elements created by p5, except any canvas / graphics
 75   * elements created by createCanvas or createGraphics.
 76   * Event handlers are removed, and element is removed from the DOM.
 77   * @method removeElements
 78   * @example
 79   * <div class='norender'><code>
 80   * function setup() {
 81   *   createCanvas(100, 100);
 82   *   createDiv('this is some text');
 83   *   createP('this is a paragraph'); 
 84   * }
 85   * function mousePressed() {
 86   *   removeElements(); // this will remove the div and p, not canvas
 87   * }
 88   * </code></div>
 89   *
 90   */
 91  p5.prototype.removeElements = function (e) {
 92    for (var i=0; i<this._elements.length; i++) {
 93      if (!(this._elements[i].elt instanceof HTMLCanvasElement)) {
 94        this._elements[i].remove();
 95      }
 96    }
 97  };
 98
 99  /**
100   * Helpers for create methods.
101   */  
102  function addElement(elt, pInst, media) {
103    var node = pInst._userNode ? pInst._userNode : document.body;
104    node.appendChild(elt);
105    var c = media ? new p5.MediaElement(elt) : new p5.Element(elt);
106    pInst._elements.push(c);
107    return c;
108  }
109
110  /**
111   * Creates a &lt;div&gt;&lt;/div&gt; element in the DOM with given inner HTML.
112   * Appends to the container node if one is specified, otherwise 
113   * appends to body.
114   * 
115   * @method createDiv
116   * @param  {String} html inner HTML for element created
117   * @return {Object/p5.Element} pointer to p5.Element holding created
118   *                           node
119   */
120
121  /**
122   * Creates a &lt;p&gt;&lt;/p&gt; element in the DOM with given inner HTML. Used
123   * for paragraph length text.
124   * Appends to the container node if one is specified, otherwise 
125   * appends to body.
126   * 
127   * @method createP
128   * @param  {String} html inner HTML for element created
129   * @return {Object/p5.Element} pointer to p5.Element holding created
130   *                           node
131   */
132
133  /**
134   * Creates a &lt;span&gt;&lt;/span&gt; element in the DOM with given inner HTML.
135   * Appends to the container node if one is specified, otherwise 
136   * appends to body.
137   * 
138   * @method createSpan
139   * @param  {String} html inner HTML for element created
140   * @return {Object/p5.Element} pointer to p5.Element holding created
141   *                           node
142   */
143  var tags = ['div', 'p', 'span'];
144  tags.forEach(function(tag) {
145    var method = 'create' + tag.charAt(0).toUpperCase() + tag.slice(1);
146    p5.prototype[method] = function(html) {
147      var elt = document.createElement(tag);
148      elt.innerHTML = html;
149      return addElement(elt, this);
150    }
151  });
152
153  /**
154   * Creates an &lt;img /&gt; element in the DOM with given src and
155   * alternate text. 
156   * Appends to the container node if one is specified, otherwise 
157   * appends to body.
158   * 
159   * @method createImg
160   * @param  {String} src src path or url for image
161   * @param  {String} alt alternate text to be used if image does not
162   *                  load
163   * @return {Object/p5.Element} pointer to p5.Element holding created
164   *                           node
165   */
166  p5.prototype.createImg = function(src, alt) {
167    var elt = document.createElement('img');
168    elt.src = src;
169    if (typeof alt !== 'undefined') {
170      elt.alt = alt;
171    }
172    return addElement(elt, this);
173  };
174
175
176  /**
177   * Creates an &lt;a&gt;&lt;/a&gt; element in the DOM for including a hyperlink.
178   * Appends to the container node if one is specified, otherwise 
179   * appends to body.
180   * 
181   * @method createA
182   * @param  {String} href       url of page to link to
183   * @param  {String} html       inner html of link element to display
184   * @param  {String} [target]   target where new link should open,
185   *                             could be _blank, _self, _parent, _top.
186   * @return {Object/p5.Element} pointer to p5.Element holding created
187   *                           node
188   */
189  p5.prototype.createA = function(href, html, target) {
190    var elt = document.createElement('a');
191    elt.href = href;
192    elt.innerHTML = html;
193    if (target) elt.target = target;
194    return addElement(elt, this);
195  };
196
197  /** INPUT **/
198
199
200  /**
201   * Creates a slider &lt;input&gt;&lt;/input&gt; element in the DOM.
202   * Use .size() to set the display length of the slider.
203   * Appends to the container node if one is specified, otherwise 
204   * appends to body.
205   * 
206   * @method createSlider
207   * @param  {Number} min minimum value of the slider
208   * @param  {Number} max maximum value of the slider
209   * @param  {Number} [value] default value of the slider
210   * @return {Object/p5.Element} pointer to p5.Element holding created
211   *                           node
212   */
213  p5.prototype.createSlider = function(min, max, value) {
214    var elt = document.createElement('input');
215    elt.type = 'range';
216    elt.min = min;
217    elt.max = max;
218    if (value) elt.value = value;
219    return addElement(elt, this);
220  };
221
222  /**
223   * Creates a &lt;button&gt;&lt;/button&gt; element in the DOM.
224   * Use .size() to set the display size of the button.
225   * Use .mousePressed() to specify behavior on press.
226   * Appends to the container node if one is specified, otherwise 
227   * appends to body.
228   * 
229   * @method createButton
230   * @param  {String} label label displayed on the button
231   * @param  {String} [value] value of the button
232   * @return {Object/p5.Element} pointer to p5.Element holding created
233   *                           node
234   */
235  p5.prototype.createButton = function(label, value) {
236    var elt = document.createElement('button');
237    elt.innerHTML = label;
238    elt.value = value;
239    if (value) elt.value = value;
240    return addElement(elt, this);
241  };
242
243  /**
244   * Creates an &lt;input&gt;&lt;/input&gt; element in the DOM for text input.
245   * Use .size() to set the display length of the box.
246   * Appends to the container node if one is specified, otherwise 
247   * appends to body.
248   * 
249   * @method createInput
250   * @param  {Number} [value] default value of the input box
251   * @return {Object/p5.Element} pointer to p5.Element holding created
252   *                           node
253   */
254  p5.prototype.createInput = function(value) {
255    var elt = document.createElement('input');
256    elt.type = 'text';
257    if (value) elt.value = value;
258    return addElement(elt, this);
259  };
260
261  /** VIDEO STUFF **/
262
263  function createMedia(pInst, type, src, callback) {
264    var elt = document.createElement(type);
265    if (typeof src === 'string') {
266      src = [src];
267    }
268    for (var i=0; i<src.length; i++) {
269      var source = document.createElement('source');
270      source.src = src[i];
271      elt.appendChild(source);
272    }
273    if (typeof callback !== 'undefined') {
274      elt.addEventListener('canplaythrough', function() {
275        callback();
276      });
277    }
278
279    var c = addElement(elt, pInst, true);
280    c.loadedmetadata = false;
281    // set width and height onload metadata
282    elt.addEventListener('loadedmetadata', function() {
283      c.width = elt.videoWidth;
284      c.height = elt.videoHeight;
285      c.loadedmetadata = true;
286    });
287    
288    return c;  
289  }
290  /**
291   * Creates an HTML5 &lt;video&gt; element in the DOM for simple playback
292   * of audio/video. Shown by default, can be hidden with .hide()
293   * and drawn into canvas using video(). Appends to the container
294   * node if one is specified, otherwise appends to body. The first parameter
295   * can be either a single string path to a video file, or an array of string
296   * paths to different formats of the same video. This is useful for ensuring
297   * that your video can play across different browsers, as each supports 
298   * different formats. See <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats">this
299   * page for further information about supported formats.
300   * 
301   * @method createVideo
302   * @param  {String|Array} src  path to a video file, or array of paths for
303   *                             supporting different browsers
304   * @param  {Object} [callback] callback function to be called upon 
305   *                             'canplaythrough' event fire, that is, when the
306   *                             browser can play the media, and estimates that 
307   *                             enough data has been loaded to play the media 
308   *                             up to its end without having to stop for 
309   *                             further buffering of content
310   * @return {Object/p5.Element} pointer to video p5.Element
311   */
312  p5.prototype.createVideo = function(src, callback) {
313    return createMedia(this, 'video', src, callback);
314  };
315
316  /** AUDIO STUFF **/
317
318  /**
319   * Creates a hidden HTML5 &lt;audio&gt; element in the DOM for simple audio 
320   * playback. Appends to the container node if one is specified, 
321   * otherwise appends to body. The first parameter
322   * can be either a single string path to a audio file, or an array of string
323   * paths to different formats of the same audio. This is useful for ensuring
324   * that your audio can play across different browsers, as each supports 
325   * different formats. See <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats">this
326   * page for further information about supported formats.
327   * 
328   * @method createAudio
329   * @param  {String|Array} src  path to an audio file, or array of paths for
330   *                             supporting different browsers
331   * @param  {Object} [callback] callback function to be called upon 
332   *                             'canplaythrough' event fire, that is, when the
333   *                             browser can play the media, and estimates that 
334   *                             enough data has been loaded to play the media 
335   *                             up to its end without having to stop for 
336   *                             further buffering of content
337   * @return {Object/p5.Element} pointer to audio p5.Element
338   */
339  p5.prototype.createAudio = function(src, callback) {
340    return createMedia(this, 'audio', src, callback);
341  };
342
343
344  /** CAMERA STUFF **/
345  
346  p5.prototype.VIDEO = 'video';
347  p5.prototype.AUDIO = 'audio';
348
349  navigator.getUserMedia  = navigator.getUserMedia ||
350                            navigator.webkitGetUserMedia ||
351                            navigator.mozGetUserMedia ||
352                            navigator.msGetUserMedia;
353
354  /**
355   * Creates a new &lt;video&gt; element that contains the audio/video feed
356   * from a webcam. This can be drawn onto the canvas using video().
357   *
358   * @method createCapture
359   * @param  {String/Constant}   type type of capture, either VIDEO or 
360   *                             AUDIO if none specified, default both
361   * @return {Object/p5.Element} capture video p5.Element
362   */
363  p5.prototype.createCapture = function(type) {
364    var useVideo, useAudio;
365    if (!type) {
366      useVideo = true;
367      useAudio = true;
368    } else if (type === p5.prototype.VIDEO) {
369      useVideo = true;
370    } else if (type === p5.prototype.AUDIO) {
371      useAudio = true;
372    }
373
374    if (navigator.getUserMedia) {
375      var elt = document.createElement('video');
376      navigator.getUserMedia({video: useVideo, audio: useAudio}, function(stream) {
377        elt.src = window.URL.createObjectURL(stream);
378        elt.play();
379      }, function(e) { console.log(e); });
380    } else {
381      throw 'getUserMedia not supported in this browser';
382    }
383    return addElement(elt, this);
384  };
385
386  /**
387   * Creates element with given tag in the DOM with given content.
388   * Appends to the container node if one is specified, otherwise 
389   * appends to body.
390   * 
391   * @method createElement
392   * @param  {String} tag tag for the new element
393   * @param  {String} [content] html content to be inserted into the element 
394   * @return {Object/p5.Element} pointer to p5.Element holding created
395   *                           node
396   */
397  p5.prototype.createElement = function(tag, content) {
398    var elt = document.createElement(tag);
399    if (typeof content !== 'undefined') {
400      elt.innerHTML = content;
401    }
402    return addElement(elt, this);
403  };
404
405
406// =============================================================================
407//                         p5.Element additions
408// =============================================================================
409  /**
410   *
411   * Adds specified class to the element.
412   *
413   * @for p5.Element
414   * @method addClass
415   * @param  {String} class name of class to add
416   * @return {p5.Element}
417   */
418  p5.Element.prototype.addClass = function(c) {
419    if (this.elt.className) {
420      // PEND don't add class more than once
421      //var regex = new RegExp('[^a-zA-Z\d:]?'+c+'[^a-zA-Z\d:]?');
422      //if (this.elt.className.search(/[^a-zA-Z\d:]?hi[^a-zA-Z\d:]?/) === -1) {
423      this.elt.className = this.elt.className+' '+c;
424      //}
425    } else {
426      this.elt.className = c;
427    }
428    return this;
429  }
430
431  /**
432   *
433   * Removes specified class from the element.
434   *
435   * @method removeClass
436   * @param  {String} class name of class to remove
437   * @return {p5.Element}
438   */
439  p5.Element.prototype.removeClass = function(c) {
440    var regex = new RegExp('(?:^|\\s)'+c+'(?!\\S)');
441    this.elt.className = this.elt.className.replace(regex, '');
442    this.elt.className = this.elt.className.replace(/^\s+|\s+$/g, ""); //prettify (optional)
443    return this;
444  }
445
446  /**
447   *
448   * Attaches the element  as a child to the parent specified. 
449   * Accepts either a string ID, DOM node, or p5.Element
450   *
451   * @method child
452   * @param  {String|Object} child the ID, DOM node, or p5.Element 
453   *                         to add to the current element
454   * @return {p5.Element}
455   * @example
456   * <div class='norender'><code>
457   * var div0 = createDiv('this is the parent');
458   * var div1 = createDiv('this is the child');
459   * div0.child(div1); // use p5.Element
460   * </code></div>
461   * <div class='norender'><code>
462   * var div0 = createDiv('this is the parent');
463   * var div1 = createDiv('this is the child');
464   * div1.id('apples');
465   * div0.child('apples'); // use id
466   * </code></div>
467   * <div class='norender'><code>
468   * var div0 = createDiv('this is the parent');
469   * var elt = document.getElementById('myChildDiv');
470   * div0.child(elt); // use element from page
471   * </code></div>
472   */ 
473  p5.Element.prototype.child = function(c) {
474    if (typeof c === 'string') {
475      c = document.getElementById(c);
476    } else if (c instanceof p5.Element) {
477      c = c.elt;
478    }
479    this.elt.appendChild(c);
480    return this;
481  };
482
483
484  /**
485   *
486   * If an argument is given, sets the inner HTML of the element, 
487   * replacing any existing html. If no arguments are given, returns
488   * the inner HTML of the element.
489   *
490   * @for p5.Element
491   * @method html
492   * @param  {String} [html] the HTML to be placed inside the element
493   * @return {p5.Element|String}
494   */
495  p5.Element.prototype.html = function(html) {
496    if (typeof html !== 'undefined') {
497      this.elt.innerHTML = html;
498      return this;
499    } else {
500      return this.elt.innerHTML;
501    }
502  };
503
504  /**
505   *
506   * Sets the position of the element relative to (0, 0) of the
507   * window. Essentially, sets position:absolute and left and top
508   * properties of style.
509   *
510   * @method position
511   * @param  {Number} x x-position relative to upper left of window
512   * @param  {Number} y y-position relative to upper left of window
513   * @return {p5.Element}
514   * @example
515   * <div><code class='norender'>
516   * function setup() {
517   *   var cnv = createCanvas(100, 100);
518   *   // positions canvas 50px to right and 100px
519   *   // below upper left corner of the window
520   *   cnv.position(50, 100);
521   * }
522   * </code></div>
523   */
524  p5.Element.prototype.position = function(x, y) {
525    this.elt.style.position = 'absolute';
526    this.elt.style.left = x+'px';
527    this.elt.style.top = y+'px';
528    return this;
529  };
530
531  /**
532   *
533   * Sets the given style (css) property of the element with the given value.
534   * If no value is specified, returns the value of the given property, 
535   * or undefined if the property is not.
536   *
537   * @method style
538   * @param  {String} property   property to be set
539   * @param  {String} [value]    value to assign to property
540   * @return {String|p5.Element} value of property, if no value is specified
541   *                             or p5.Element
542   * @example
543   * <div><code class="norender">
544   * var myDiv = createDiv("I like pandas.");
545   * myDiv.style("color", "#ff0000");
546   * myDiv.style("font-size", "18px");
547   * </code></div>
548   */
549  p5.Element.prototype.style = function(prop, val) {
550    if (typeof val === 'undefined') {
551      var attrs = prop.split(';');
552      for (var i=0; i<attrs.length; i++) {
553        var parts = attrs[i].split(':');
554        if (parts[0] && parts[1]) {
555          this.elt.style[parts[0].trim()] = parts[1].trim();
556        }
557      }
558      console.log(this.elt.style)
559    } else {
560      this.elt.style[prop] = val;
561    }
562    return this;
563  };
564
565
566  /**
567   *
568   * Adds a new attribute or changes the value of an existing attribute 
569   * on the specified element. If no value is specified, returns the
570   * value of the given attribute, or null if attribute is not set.
571   *
572   * @method attribute
573   * @param  {String} attr       attribute to set
574   * @param  {String} [value]    value to assign to attribute
575   * @return {String|p5.Element} value of attribute, if no value is 
576   *                             specified or p5.Element
577   * @example
578   * <div class="norender"><code>
579   * var myDiv = createDiv("I like pandas.");
580   *myDiv.attribute("align", "center");
581   * </code></div>
582   */
583  p5.Element.prototype.attribute = function(attr, value) {
584    if (typeof value === 'undefined') {
585      return this.elt.getAttribute(attr);
586    } else {
587      this.elt.setAttribute(attr, value);
588      return this;
589    }
590  };
591
592
593  /**
594   * Either returns the value of the element if no arguments
595   * given, or sets the value of the element.
596   * 
597   * @method value
598   * @param  {String|Number}     [value]
599   * @return {String|p5.Element} value of element, if no value is 
600   *                             specified or p5.Element
601   */
602  p5.Element.prototype.value = function() {
603    if (arguments.length > 0) {
604      this.elt.value = arguments[0];
605      return this;
606    } else {
607      if (this.elt.type === 'range') {
608        return parseFloat(this.elt.value);
609      }
610      else return this.elt.value;
611    }
612  };
613
614  /**
615   * 
616   * Shows the current element. Essentially, setting display:block for the style.
617   * 
618   * @method show
619   * @return {p5.Element}
620   */
621  p5.Element.prototype.show = function() {
622    this.elt.style.display = 'block';
623    return this;
624  };
625
626  /**
627   * Hides the current element. Essentially, setting display:none for the style.
628   * 
629   * @method hide
630   * @return {p5.Element}
631   */
632  p5.Element.prototype.hide = function() {
633    this.elt.style.display = 'none';
634    return this;
635  };
636
637  /**
638   * 
639   * Sets the width and height of the element. AUTO can be used to
640   * only adjust one dimension.
641   * 
642   * @method size
643   * @param  {Number} w width of the element
644   * @param  {Number} h height of the element
645   * @return {p5.Element}
646   */
647  p5.Element.prototype.size = function(w, h) {
648    var aW = w;
649    var aH = h;
650    var AUTO = p5.prototype.AUTO;
651
652    if (aW !== AUTO || aH !== AUTO) {
653      if (aW === AUTO) {
654        aW = h * this.elt.width / this.elt.height;
655      } else if (aH === AUTO) {
656        aH = w * this.elt.height / this.elt.width;
657      }
658      // set diff for cnv vs normal div
659      if (this.elt instanceof HTMLCanvasElement) {
660        var j = {};
661        var k  = this.elt.getContext('2d');        
662        for (var prop in k) {
663          j[prop] = k[prop];
664        }
665        this.elt.setAttribute('width', aW * this._pInst._pixelDensity);
666        this.elt.setAttribute('height', aH * this._pInst._pixelDensity);
667        this.elt.setAttribute('style', 'width:' + aW + 'px !important; height:' + aH + 'px !important;');
668        this._pInst.scale(this._pInst._pixelDensity, this._pInst._pixelDensity);
669        for (var prop in j) {
670          this.elt.getContext('2d')[prop] = j[prop];
671        }
672      } else {
673        this.elt.style.width = aW+'px';
674        this.elt.style.height = aH+'px';
675        this.elt.width = aW;
676        this.elt.height = aH;
677      }
678      this.width = this.elt.offsetWidth;
679      this.height = this.elt.offsetHeight;
680      if (this._pInst) { // main canvas associated with p5 instance
681        if (this._pInst._curElement.elt === this.elt) {
682          this._pInst._setProperty('width', this.elt.offsetWidth);
683          this._pInst._setProperty('height', this.elt.offsetHeight);
684        }
685      }
686    }
687    return this;
688  };
689
690  /**
691   * Removes the element and deregisters all listeners.
692   * @method remove
693   * @example
694   * <div class='norender'><code>
695   * var myDiv = createDiv('this is some text');
696   * myDiv.remove();
697   * </code></div>
698   */
699  p5.Element.prototype.remove = function() {
700    // deregister events
701    for (var ev in this._events) {
702      this.elt.removeEventListener(ev, this._events[ev]);
703    }
704    if (this.elt.parentNode) {
705      this.elt.parentNode.removeChild(this.elt);
706    }
707    delete(this);
708  };
709
710
711
712// =============================================================================
713//                         p5.MediaElement additions
714// =============================================================================
715
716
717  /**
718   * Extends p5.Element to handle audio and video. In addition to the methods
719   * of p5.Element, it also contains methods for controlling media. It is not
720   * called directly, but p5.MediaElements are created by calling createVideo,
721   * createAudio, and createCapture.
722   *
723   * @class p5.MediaElement
724   * @constructor
725   * @param {String} elt DOM node that is wrapped
726   * @param {Object} [pInst] pointer to p5 instance
727   */
728  p5.MediaElement = function(elt, pInst) {
729    p5.Element.call(this, elt, pInst);
730  };
731  p5.MediaElement.prototype = Object.create(p5.Element.prototype);
732
733
734
735
736  /**
737   * Play an HTML5 media element.
738   * 
739   * @method play
740   * @return {p5.Element}
741   */
742  p5.MediaElement.prototype.play = function() {
743    if (this.elt.currentTime === this.elt.duration) {
744      this.elt.currentTime = 0;
745    }
746    this.elt.play();
747    return this;
748  };  
749
750  /**
751   * Stops an HTML5 media element (sets current time to zero).
752   * 
753   * @method stop
754   * @return {p5.Element}
755   */
756  p5.MediaElement.prototype.stop = function() {
757    this.elt.pause();
758    this.elt.currentTime = 0;
759    return this;
760  };  
761
762  /**
763   * Pauses an HTML5 media element.
764   * 
765   * @method pause
766   * @return {p5.Element}
767   */
768  p5.MediaElement.prototype.pause = function() {
769    this.elt.pause();
770    return this;
771  };  
772
773  /**
774   * Set 'loop' to true for an HTML5 media element, and starts playing.
775   * 
776   * @method loop
777   * @return {p5.Element}
778   */
779  p5.MediaElement.prototype.loop = function() {
780    this.elt.setAttribute('loop', true);
781    this.play();
782    return this;
783  };
784  /**
785   * Set 'loop' to false for an HTML5 media element. Element will stop
786   * when it reaches the end.
787   * 
788   * @method noLoop
789   * @return {p5.Element}
790   */
791  p5.MediaElement.prototype.noLoop = function() {
792    this.elt.setAttribute('loop', false);
793    return this;
794  };
795
796
797  /**
798   * Set HTML5 media element to autoplay or not.
799   * 
800   * @method autoplay
801   * @param {Boolean} autoplay whether the element should autoplay
802   * @return {p5.Element}
803   */
804  p5.MediaElement.prototype.autoplay = function(val) {
805    this.elt.setAttribute('autoplay', val);
806    return this;
807  };
808
809  /**
810   * Sets volume for this HTML5 media element. If no argument is given,
811   * returns the current volume.
812   * 
813   * @param {Number}            [val] volume between 0.0 and 1.0
814   * @return {Number|p5.MediaElement} current volume or p5.MediaElement
815   * @method volume
816   */
817  p5.MediaElement.prototype.volume = function(val) {
818    if (typeof val === 'undefined') {
819      return this.elt.volume;
820    } else {
821      this.elt.volume = val;
822    }
823  };
824
825  /**
826   * If no arguments are given, returns the current time of the elmeent.
827   * If an argument is given the current time of the element is set to it.
828   * 
829   * @method time
830   * @param {Number} [time] time to jump to (in seconds)
831   * @return {Number|p5.MediaElement} current time (in seconds)
832   *                                  or p5.MediaElement
833   */
834  p5.MediaElement.prototype.time = function(val) {
835    if (typeof val === 'undefined') {
836      return this.elt.currentTime;
837    } else {
838      this.elt.currentTime = val;
839    }
840  };
841
842  /**
843   * Returns the duration of the HTML5 media element.
844   * 
845   * @method duration
846   * @return {Number} duration
847   */
848  p5.MediaElement.prototype.duration = function() {
849    return this.elt.duration;
850  };
851  p5.MediaElement.prototype.pixels = [];
852  p5.MediaElement.prototype.loadPixels = function() {
853    if (this.loadedmetadata) { // wait for metadata for w/h
854      if (!this.canvas) {
855        this.canvas = document.createElement('canvas');
856        this.canvas.width = this.width;
857        this.canvas.height = this.height;
858        this.drawingContext = this.canvas.getContext('2d');
859      }
860      this.drawingContext.drawImage(this.elt, 0, 0);
861      p5.prototype.loadPixels.call(this);
862    }
863    return this;
864  }
865  p5.MediaElement.prototype.updatePixels =  function(x, y, w, h){
866    if (this.loadedmetadata) { // wait for metadata
867      p5.prototype.updatePixels.call(this, x, y, w, h);
868    }
869    return this;
870  }
871  p5.MediaElement.prototype.get = function(x, y, w, h){
872    if (this.loadedmetadata) { // wait for metadata
873      return p5.prototype.get.call(this, x, y, w, h);
874    } else return [0, 0, 0, 255];
875  };
876  p5.MediaElement.prototype.set = function(x, y, imgOrCol){
877    if (this.loadedmetadata) { // wait for metadata
878      p5.prototype.set.call(this, x, y, imgOrCol);
879    }
880  };
881
882})();