<commit_before>var test = require('../test-tools/test')('“mouse navigation” plugin');
var mockPlugin = require('../test-tools/mockPlugin');
var async = require('async');

var mouseNavigation = require('../../module/plugins/mouseNavigation');

test(
  'Hides the dropdown.',
  function(is) {
    var frameThrottle = 100;
    is.plan(3);

    // Prepare a set of async tests – each operating on its own mock select.
    var tests = [

      // Unfold a select and pick an option. The select should fold.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        mock.model.patch.on('patch', function(patch) {is.equal(
          patch.unfolded,
          undefined,
          'when an option is clicked'
        );});

        // The unfold is throttled until the next frame. So we need to postpone
        // every test.
        setTimeout(function() {
          mock.view.dropdownElement.emit('click');
          done();
        }, frameThrottle);
      },

      // Unfold a select and blur it. It should fold back.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        mock.model.patch.on('patch', function(patch) {is.equal(
          patch.unfolded,
          undefined,
          'when the select loses focus'
        );});

        setTimeout(function () {
          mock.view.switchElement.emit('blur');
          done();
        }, frameThrottle);
      },

      // Unfold another one, and blur it by flicking the switch. After it has
      // been folded, it shouldn’t unfold upon the `click`.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        setTimeout(function() {
          mock.view.selectLabelElement.emit('mousedown');
          mock.view.switchElement.emit('blur');
          mock.model.state.emit('unfolded', {current:
            {unfolded: undefined}
          }); // We already know that a blur triggers a fold here.

          setTimeout(function () {
            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.pass(
                'keeps it hidden when the loss of focus came from flicking the ' +
                'switch'
              );},
            });

            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.fail(
                'doesn’t break the switch'
              );},
            });

            done();
          }, frameThrottle);
        }, frameThrottle);
      },

      // Again, unfold a select. Then blur its switch by pressing the pointer
      // over the select. Before releasing the pointer, move it away from the
      // select though. It shouldn’t affect the `click` event afterwards.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        setTimeout(function() {
          mock.view.selectLabelElement.emit('mousedown');
          mock.view.switchElement.emit('blur');

          setTimeout(function () {
            mock.view.selectLabelElement.emit('mouseleave');
            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.fail(
                'not when the switch has been mousedowned but not mouseupped'
              );}
            });

            done();
          }, frameThrottle);
        }, frameThrottle);
      },

      // Create a select while the switch is in focus. Flick the switch by
      // clicking on its label. It will be blurred while the pointer is
      // down. The select should still unfold though.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: undefined}});

        setTimeout(function() {
          mock.view.selectLabelElement.emit('mousedown');
          mock.view.switchElement.emit('blur');

          setTimeout(function () {
            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.fail(
                'not when we really want to unfold it'
              );}
            });

            done();
          }, frameThrottle);
        }, frameThrottle);
      },

      // Unfold a select. Click the switch without blurring it.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        setTimeout(function() {
          mock.view.selectLabelElement.emit('mousedown');

          setTimeout(function () {
            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.fail(
                'not when the switch has been mousedowned but not blurred'
              );}
            });

            done();
          }, frameThrottle);
        }, frameThrottle);
      },

      // Unfold another select, and blur it by clicking inside the dropdown.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        mock.model.patch.on('patch', function() {is.fail(
          'not when the blur was triggered by a click within the dropdown'
        );});

        setTimeout(function() {
          mock.view.switchElement.emit('blur');
          mock.view.dropdownElement.emit('mousedown');
          done();
        }, frameThrottle);
      },
    ];

    // Execute the async tests one after another.
    async.parallel(tests, function () {is.end();});
    is.timeoutAfter(2000);
  }
);

test(
  'Prevents the select from losing focus unintentionally.',
  function(is) {
    is.plan(1);

    // Prepare an unfolded select.
    var mock = mockPlugin(mouseNavigation);

    mock.view.update.on('focused', function(focused) {is.equal(
      focused.newValue,
      true,
      'when the blur was caused by a click inside the dropdown'
    );});

    // Trigger a `click` within the dropdown.
    mock.view.dropdownElement.emit('click');

    is.timeoutAfter(200);
  }
);

test(
  'Degrades silently.',
  function(is) {
    is.plan(1);

    var mock = mockPlugin(mouseNavigation);

    is.doesNotThrow(
      function () {
        mock.model.state.emit('unfolded', /something wrong/);
      },

      'when it gets a bad message from `model.state`'
    );

    is.end();
  }
);
<commit_msg>Specify new behavior of “mouse navigation” [ref #6894]<commit_after>var test = require('../test-tools/test')('“mouse navigation” plugin');
var mockPlugin = require('../test-tools/mockPlugin');
var async = require('async');

var mouseNavigation = require('../../module/plugins/mouseNavigation');

test(
  'Hides the dropdown.',
  function(is) {
    var frameThrottle = 100;
    is.plan(3);

    // Prepare a set of async tests – each operating on its own mock select.
    var tests = [

      // Unfold a select and pick an option. The select should fold.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        mock.view.update.on('unfolded', function(unfolded) {is.equal(
          unfolded.newValue,
          false,
          'when an option is clicked'
        );});

        // The unfold is throttled until the next frame. So we need to postpone
        // every test.
        setTimeout(function() {
          mock.view.dropdownElement.emit('click');
          done();
        }, frameThrottle);
      },

      // Unfold a select and blur it. It should fold back.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        mock.view.update.on('unfolded', function(unfolded) {is.equal(
          unfolded.newValue,
          false,
          'when the select loses focus'
        );});

        setTimeout(function () {
          mock.view.switchElement.emit('blur');
          done();
        }, frameThrottle);
      },

      // Unfold another one, and blur it by flicking the switch. After it has
      // been folded, it shouldn’t unfold upon the `click`.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        setTimeout(function() {
          mock.view.selectLabelElement.emit('mousedown');
          mock.view.switchElement.emit('blur');
          mock.model.state.emit('unfolded', {current:
            {unfolded: undefined}
          }); // We already know that a blur triggers a fold here.

          setTimeout(function () {
            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.pass(
                'keeps it hidden when the loss of focus came from flicking the ' +
                'switch'
              );},
            });

            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.fail(
                'doesn’t break the switch'
              );},
            });

            done();
          }, frameThrottle);
        }, frameThrottle);
      },

      // Again, unfold a select. Then blur its switch by pressing the pointer
      // over the select. Before releasing the pointer, move it away from the
      // select though. It shouldn’t affect the `click` event afterwards.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        setTimeout(function() {
          mock.view.selectLabelElement.emit('mousedown');
          mock.view.switchElement.emit('blur');

          setTimeout(function () {
            mock.view.selectLabelElement.emit('mouseleave');
            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.fail(
                'not when the switch has been mousedowned but not mouseupped'
              );}
            });

            done();
          }, frameThrottle);
        }, frameThrottle);
      },

      // Create a select while the switch is in focus. Flick the switch by
      // clicking on its label. It will be blurred while the pointer is
      // down. The select should still unfold though.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: undefined}});

        setTimeout(function() {
          mock.view.selectLabelElement.emit('mousedown');
          mock.view.switchElement.emit('blur');

          setTimeout(function () {
            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.fail(
                'not when we really want to unfold it'
              );}
            });

            done();
          }, frameThrottle);
        }, frameThrottle);
      },

      // Unfold a select. Click the switch without blurring it.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        setTimeout(function() {
          mock.view.selectLabelElement.emit('mousedown');

          setTimeout(function () {
            mock.view.selectLabelElement.emit('click', {
              preventDefault: function() {is.fail(
                'not when the switch has been mousedowned but not blurred'
              );}
            });

            done();
          }, frameThrottle);
        }, frameThrottle);
      },

      // Unfold another select, and blur it by clicking inside the dropdown.
      function(done) {
        var mock = mockPlugin(mouseNavigation);
        mock.model.state.emit('unfolded', {current: {unfolded: ''}});

        mock.view.update.on('unfolded', function() {is.fail(
          'not when the blur was triggered by a click within the dropdown'
        );});

        setTimeout(function() {
          mock.view.switchElement.emit('blur');
          mock.view.dropdownElement.emit('mousedown');
          done();
        }, frameThrottle);
      },
    ];

    // Execute the async tests one after another.
    async.parallel(tests, function () {is.end();});
    is.timeoutAfter(2000);
  }
);

test(
  'Prevents the select from losing focus unintentionally.',
  function(is) {
    is.plan(1);

    // Prepare an unfolded select.
    var mock = mockPlugin(mouseNavigation);

    mock.view.update.on('focused', function(focused) {is.equal(
      focused.newValue,
      true,
      'when the blur was caused by a click inside the dropdown'
    );});

    // Trigger a `click` within the dropdown.
    mock.view.dropdownElement.emit('click');

    is.timeoutAfter(200);
  }
);

test(
  'Degrades silently.',
  function(is) {
    is.plan(1);

    var mock = mockPlugin(mouseNavigation);

    is.doesNotThrow(
      function () {
        mock.model.state.emit('unfolded', /something wrong/);
      },

      'when it gets a bad message from `model.state`'
    );

    is.end();
  }
);
<|endoftext|>


<commit_before>function mistembed(streamname) {

  //find the current script
  var me;
  if (('currentScript' in document) && (document.currentScript)) {
    me = document.currentScript;
    //not supported in old browsers :(
  }
  else {
    var scripts = document.getElementsByTagName('script');
    me = scripts[scripts.length - 1];
    //not correct if the script is inserted dynamically, but this is how it used to be
  }

  // return the current flash version
  function flash_version() {
    var version = 0;

    try {
      // check in the mimeTypes
      version = navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin.description.replace(/([^0-9\.])/g, '').split('.')[0];
    } catch(e){}
    try {
      // for our special friend IE
      version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable("$version").replace(/([^0-9\,])/g, '').split(',')[0];
    } catch(e){}

    return parseInt(version, 10);
  };

  // return true if silverlight is installed
  function silverlight_installed() {
    var plugin;

    try {
      // check in the mimeTypes
      plugin = navigator.plugins["Silverlight Plug-In"];
      return !!plugin;
    } catch(e){}
    try {
      // for our special friend IE
      plugin = new ActiveXObject('AgControl.AgControl');
      return true;
    } catch(e){}

    return false;
  };

  // return true if the browser thinks it can play the mimetype
  function html5_video_type(type) {
    var support = false;

    if (type == 'video/mp4') {
      if ((navigator.userAgent.indexOf('MSIE') > -1) && (parseInt(navigator.userAgent.split('MSIE')[1]) <= 9)) {
        //IE <= 9 doesn't support MP4, Firefox seems to correctly see it now.
        return false;
      }
    }

    try {
      var v = document.createElement('video');

      if( v && v.canPlayType(type) != "" )
      {
        support = true; // true-ish, anyway
      }
    } catch(e){}

    return support;
  }

  //return true if rtsp is supported
  function rtsp_support() {
    var plugin;

    try {
      // check in the mimeTypes
      plugin = navigator.mimeTypes["application/x-google-vlc-plugin"];
      return !!plugin;
    } catch(e){}
    try {
      // for our special friend IE
      plugin = new ActiveXObject('VideoLAN.Vlcplugin.1');
      return true;
    } catch(e){}

    return false;
  }

  // parse a "type" string from the controller. Format:
  // xxx/# (e.g. flash/3) or xxx/xxx/xxx (e.g. html5/application/ogg)
  function parseType(type) {
    var split = type.split('/');

    if( split.length > 2 ) {
      split[1] += '/' + split[2];
    }

    return split;
  }

  // return true if a type is supported
  function hasSupport(type) {
    var typemime = parseType(type);

    switch(typemime[0]) {
      case 'flash':             return flash_version() >= parseInt(typemime[1], 10);            break;
      case 'html5':             return html5_video_type(typemime[1]);                           break;
      case 'rtsp':              return rtsp_support();                                          break;
      case 'silverlight':       return silverlight_installed();                                 break;
      default:                  return false;                                                   break;
    }
  }

  // build HTML for certain kinds of types
  function buildPlayer(src, container, videowidth, videoheight, vtype) {
    // used to recalculate the width/height
    var ratio;

    // get the container's width/height
    var containerwidth = parseInt(container.scrollWidth, 10);
    var containerheight = parseInt(container.scrollHeight, 10);

    if(videowidth > containerwidth && containerwidth > 0) {
      ratio = videowidth / containerwidth;

      videowidth /= ratio;
      videoheight /= ratio;
    }

    if(videoheight > containerheight && containerheight > 0) {
      ratio = videoheight / containerheight;

      videowidth /= ratio;
      videoheight /= ratio;
    }

    var maintype = parseType(src.type);
    mistvideo[streamname].embedded = src;

    switch(maintype[0]) {
      case 'flash':
        // maintype[1] is already checked (i.e. user has version > maintype[1])
        var flashplayer,
        url = encodeURIComponent(src.url) + '&controlBarMode=floating&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3' + (vtype == 'live' ? "&streamType=live" : "") + (autoplay ? '&autoPlay=true' : '');

        /*
        if( parseInt(maintype[1], 10) >= 10 ) {
          flashplayer = 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf';
        }
        else {
          flashplayer = 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf';
        }
        */
        flashplayer = src.player_url;

        container.innerHTML += '<object width="' + videowidth + '" height="' + videoheight + '">' +
                                '<param name="movie" value="' + flashplayer + '"></param>' +
                                '<param name="flashvars" value="src=' + url + '"></param>' +
                                '<param name="allowFullScreen" value="true"></param>' +
                                '<param name="allowscriptaccess" value="always"></param>' +
                                '<param name="wmode" value="direct"></param>' +
                                (autoplay ? '<param name="autoPlay" value="true">' : '') +
                                '<embed src="' + flashplayer + '" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="' + videowidth + '" height="' + videoheight + '" flashvars="src=' + url + '"></embed>' +
                              '</object>';
      break;

      case 'html5':
        container.innerHTML += '<video width="' + videowidth + '" height="' + videoheight + '" src="' + encodeURI(src.url) + '" controls="controls" '+(autoplay ? 'autoplay="autoplay"' : '')+'>No HTML5 video support</video>';
        break;

      case 'rtsp':
        /*container.innerHTML += '<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="'+videowidth+'" height="'+videoheight+'">'+
                                  '<param name="src" value="'+encodeURI(src.url)+'">'+
                                  '<param name="console" value="video1">'+
                                  '<param name="controls" value="All">'+
                                  '<param name="autostart" value="false">'+
                                  '<param name="loop" value="false">'+
                                  '<embed name="myMovie" src="'+encodeURI(src.url)+'" width="'+videowidth+'" height="'+videoheight+'" autostart="false" loop="false" nojava="true" console="video1" controls="All"></embed>'+
                                  '<noembed>Something went wrong.</noembed>'+
                                '</object>'; //realplayer, doesnt work */
        container.innerHTML +=  '<embed type="application/x-google-vlc-plugin"'+
                                  'pluginspage="http://www.videolan.org"'+
                                  'width="'+videowidth+'"'+
                                  'height="'+videoheight+'"'+
                                  'target="'+encodeURI(src.url)+'"'+
                                  'autoplay="'+(autoplay ? 'yes' : 'no')+'"'+
                                '>'+
                                '</embed>'+
                                '<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab">'+
                                '</object>'; //vlc, seems to work, sort of. it's trying anyway
      break;

      case 'silverlight':
        container.innerHTML +=  '<object data="data:application/x-silverlight," type="application/x-silverlight" width="' + videowidth + '" height="' + videoheight + '">'+
                                  '<param name="source" value="' + encodeURI(src.url) + '/player.xap"/>'+
                                  '<param name="onerror" value="onSilverlightError" />'+
                                  '<param name="autoUpgrade" value="true" />'+
                                  '<param name="background" value="white" />'+
                                  '<param name="enableHtmlAccess" value="true" />'+
                                  '<param name="minRuntimeVersion" value="3.0.40624.0" />'+
                                  '<param name="initparams" value =\'autoload=false,'+(autoplay ? 'autoplay=true' : 'autoplay=false')+',displaytimecode=false,enablecaptions=true,joinLive=true,muted=false,playlist=<playList><playListItems><playListItem title="Test" description="testing" mediaSource="' + encodeURI(src.url) + '" adaptiveStreaming="true" thumbSource="" frameRate="25.0" width="" height=""></playListItem></playListItems></playList>\' />'+
                                  ' '+
                                '</object>';
      break;
      default:
        container.innerHTML += 'Missing embed code for output type "'+src.type+'"';
        video.error = 'Missing embed code for output type "'+src.type;
    }
  }

  var video = mistvideo[streamname],
    container = document.createElement('div'),
    forceType = false,
    forceSupportCheck = false,
    autoplay = false,
    urlappend = false;

  if (me.parentNode.hasAttribute('data-forcetype')) {
    forceType = me.parentNode.getAttribute('data-forcetype');
  }
  if (me.parentNode.hasAttribute('data-forcesupportcheck')) {
    forceSupportCheck = true;
  }
  if (me.parentNode.hasAttribute('data-autoplay')) {
    autoplay = true;
  }
  if (me.parentNode.hasAttribute('data-urlappend')) {
    urlappend = me.parentNode.getAttribute('data-urlappend');
  }

  if (video.width == 0) { video.width = 250; }
  if (video.height == 0) { video.height = 250; }

  // create the container
  me.parentNode.insertBefore(container, me);
  // set the class to 'mistvideo'
  container.setAttribute('class', 'mistvideo');
  // remove script tag
  me.parentNode.removeChild(me);

  if(video.error) {
    // there was an error; display it
    container.innerHTML = ['Error: ', video.error, ''].join('');
  }
  else if ((typeof video.source == 'undefined') || (video.source.length < 1)) {
    // no stream sources
    container.innerHTML = 'Error: no protocols found';
  }
  else {
    // no error, and sources found. Check the video types and output the best
    // available video player.
    var i,
      vtype = (video.type ? video.type : 'unknown'),
      foundPlayer = false,
      len = video.source.length;

    for (var i in video.source) {
      var support = hasSupport(video.source[i].type);
      video.source[i].browser_support = support;
      if ((support) || (forceType)) {
        if ((!forceType) || ((forceType) && (video.source[i].type.indexOf(forceType) >= 0))) {
          if (foundPlayer === false) {
            foundPlayer = i;
            if (!forceSupportCheck) {
              break;
            }
          }
        }
      }
    }
    if (foundPlayer === false) {
      // of all the streams given, none was supported (eg. no flash and HTML5 video). Display error
      container.innerHTML = 'No support for any player found';
    }
    else {
      // we support this kind of video, so build it.
      var source = video.source[foundPlayer];
      if (urlappend) {
        source.url += urlappend;
        source.relurl += urlappend;
      }
      else if (me.src.indexOf('?') != -1) {
        var params = me.src.split('?');
        params.shift();
        params.join('?');
        source.url += '?'+params;
        source.relurl += '?'+params;
      }
      buildPlayer(source, container, video.width, video.height, vtype);
    }
  }

  return (mistvideo[streamname].embedded ? mistvideo[streamname].embedded.type : false);
  //keep empty line at end of file
}
<commit_msg>embed code: firefox and mp4 issues<commit_after>function mistembed(streamname) {

  //find the current script
  var me;
  if (('currentScript' in document) && (document.currentScript)) {
    me = document.currentScript;
    //not supported in old browsers :(
  }
  else {
    var scripts = document.getElementsByTagName('script');
    me = scripts[scripts.length - 1];
    //not correct if the script is inserted dynamically, but this is how it used to be
  }

  // return the current flash version
  function flash_version() {
    var version = 0;

    try {
      // check in the mimeTypes
      version = navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin.description.replace(/([^0-9\.])/g, '').split('.')[0];
    } catch(e){}
    try {
      // for our special friend IE
      version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable("$version").replace(/([^0-9\,])/g, '').split(',')[0];
    } catch(e){}

    return parseInt(version, 10);
  };

  // return true if silverlight is installed
  function silverlight_installed() {
    var plugin;

    try {
      // check in the mimeTypes
      plugin = navigator.plugins["Silverlight Plug-In"];
      return !!plugin;
    } catch(e){}
    try {
      // for our special friend IE
      plugin = new ActiveXObject('AgControl.AgControl');
      return true;
    } catch(e){}

    return false;
  };

  // return true if the browser thinks it can play the mimetype
  function html5_video_type(type) {
    var support = false;

    if (type == 'video/mp4') {
      if ((navigator.userAgent.indexOf('MSIE') > -1) && (parseInt(navigator.userAgent.split('MSIE')[1]) <= 9)) {
        //IE <= 9 doesn't support MP4, Firefox seems to correctly see it now.
        return false;
      }
      if (navigator.userAgent.indexOf('Firefox') > -1) {
        //firefox claims to support MP4 but doesn't when:
        //   - under win xp
        //   - the stream is live

        if (video.type == 'live') {
          return false;
        }
        //find "Windows NT X;" in user userAgent
        //sorry, I don't like regexes.. I avoid them when I can :$
        var s = navigator.userAgent.split('Windows NT ');
        if (s.length > 1) {
          s = s[1].split(';');
          s = s[0];
          if (Number(s) <= 5.1) {
            return false;
          }
        }
      }
    }

    try {
      var v = document.createElement('video');

      if( v && v.canPlayType(type) != "" )
      {
        support = true; // true-ish, anyway
      }
    } catch(e){}

    return support;
  }

  //return true if rtsp is supported
  function rtsp_support() {
    var plugin;

    try {
      // check in the mimeTypes
      plugin = navigator.mimeTypes["application/x-google-vlc-plugin"];
      return !!plugin;
    } catch(e){}
    try {
      // for our special friend IE
      plugin = new ActiveXObject('VideoLAN.Vlcplugin.1');
      return true;
    } catch(e){}

    return false;
  }

  // parse a "type" string from the controller. Format:
  // xxx/# (e.g. flash/3) or xxx/xxx/xxx (e.g. html5/application/ogg)
  function parseType(type) {
    var split = type.split('/');

    if( split.length > 2 ) {
      split[1] += '/' + split[2];
    }

    return split;
  }

  // return true if a type is supported
  function hasSupport(type) {
    var typemime = parseType(type);

    switch(typemime[0]) {
      case 'flash':             return flash_version() >= parseInt(typemime[1], 10);            break;
      case 'html5':             return html5_video_type(typemime[1]);                           break;
      case 'rtsp':              return rtsp_support();                                          break;
      case 'silverlight':       return silverlight_installed();                                 break;
      default:                  return false;                                                   break;
    }
  }

  // build HTML for certain kinds of types
  function buildPlayer(src, container, videowidth, videoheight, vtype) {
    // used to recalculate the width/height
    var ratio;

    // get the container's width/height
    var containerwidth = parseInt(container.scrollWidth, 10);
    var containerheight = parseInt(container.scrollHeight, 10);

    if(videowidth > containerwidth && containerwidth > 0) {
      ratio = videowidth / containerwidth;

      videowidth /= ratio;
      videoheight /= ratio;
    }

    if(videoheight > containerheight && containerheight > 0) {
      ratio = videoheight / containerheight;

      videowidth /= ratio;
      videoheight /= ratio;
    }

    var maintype = parseType(src.type);
    mistvideo[streamname].embedded = src;

    switch(maintype[0]) {
      case 'flash':
        // maintype[1] is already checked (i.e. user has version > maintype[1])
        var flashplayer,
        url = encodeURIComponent(src.url) + '&controlBarMode=floating&initialBufferTime=0.5&expandedBufferTime=5&minContinuousPlaybackTime=3' + (vtype == 'live' ? "&streamType=live" : "") + (autoplay ? '&autoPlay=true' : '');

        /*
        if( parseInt(maintype[1], 10) >= 10 ) {
          flashplayer = 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback_101.swf';
        }
        else {
          flashplayer = 'http://fpdownload.adobe.com/strobe/FlashMediaPlayback.swf';
        }
        */
        flashplayer = src.player_url;

        container.innerHTML += '<object width="' + videowidth + '" height="' + videoheight + '">' +
                                '<param name="movie" value="' + flashplayer + '"></param>' +
                                '<param name="flashvars" value="src=' + url + '"></param>' +
                                '<param name="allowFullScreen" value="true"></param>' +
                                '<param name="allowscriptaccess" value="always"></param>' +
                                '<param name="wmode" value="direct"></param>' +
                                (autoplay ? '<param name="autoPlay" value="true">' : '') +
                                '<embed src="' + flashplayer + '" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="' + videowidth + '" height="' + videoheight + '" flashvars="src=' + url + '"></embed>' +
                              '</object>';
      break;

      case 'html5':
        container.innerHTML += '<video width="' + videowidth + '" height="' + videoheight + '" src="' + encodeURI(src.url) + '" controls="controls" '+(autoplay ? 'autoplay="autoplay"' : '')+'>No HTML5 video support</video>';
        break;

      case 'rtsp':
        /*container.innerHTML += '<object classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="'+videowidth+'" height="'+videoheight+'">'+
                                  '<param name="src" value="'+encodeURI(src.url)+'">'+
                                  '<param name="console" value="video1">'+
                                  '<param name="controls" value="All">'+
                                  '<param name="autostart" value="false">'+
                                  '<param name="loop" value="false">'+
                                  '<embed name="myMovie" src="'+encodeURI(src.url)+'" width="'+videowidth+'" height="'+videoheight+'" autostart="false" loop="false" nojava="true" console="video1" controls="All"></embed>'+
                                  '<noembed>Something went wrong.</noembed>'+
                                '</object>'; //realplayer, doesnt work */
        container.innerHTML +=  '<embed type="application/x-google-vlc-plugin"'+
                                  'pluginspage="http://www.videolan.org"'+
                                  'width="'+videowidth+'"'+
                                  'height="'+videoheight+'"'+
                                  'target="'+encodeURI(src.url)+'"'+
                                  'autoplay="'+(autoplay ? 'yes' : 'no')+'"'+
                                '>'+
                                '</embed>'+
                                '<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab">'+
                                '</object>'; //vlc, seems to work, sort of. it's trying anyway
      break;

      case 'silverlight':
        container.innerHTML +=  '<object data="data:application/x-silverlight," type="application/x-silverlight" width="' + videowidth + '" height="' + videoheight + '">'+
                                  '<param name="source" value="' + encodeURI(src.url) + '/player.xap"/>'+
                                  '<param name="onerror" value="onSilverlightError" />'+
                                  '<param name="autoUpgrade" value="true" />'+
                                  '<param name="background" value="white" />'+
                                  '<param name="enableHtmlAccess" value="true" />'+
                                  '<param name="minRuntimeVersion" value="3.0.40624.0" />'+
                                  '<param name="initparams" value =\'autoload=false,'+(autoplay ? 'autoplay=true' : 'autoplay=false')+',displaytimecode=false,enablecaptions=true,joinLive=true,muted=false,playlist=<playList><playListItems><playListItem title="Test" description="testing" mediaSource="' + encodeURI(src.url) + '" adaptiveStreaming="true" thumbSource="" frameRate="25.0" width="" height=""></playListItem></playListItems></playList>\' />'+
                                  ' '+
                                '</object>';
      break;
      default:
        container.innerHTML += 'Missing embed code for output type "'+src.type+'"';
        video.error = 'Missing embed code for output type "'+src.type;
    }
  }

  var video = mistvideo[streamname],
    container = document.createElement('div'),
    forceType = false,
    forceSupportCheck = false,
    autoplay = false,
    urlappend = false;

  if (me.parentNode.hasAttribute('data-forcetype')) {
    forceType = me.parentNode.getAttribute('data-forcetype');
  }
  if (me.parentNode.hasAttribute('data-forcesupportcheck')) {
    forceSupportCheck = true;
  }
  if (me.parentNode.hasAttribute('data-autoplay')) {
    autoplay = true;
  }
  if (me.parentNode.hasAttribute('data-urlappend')) {
    urlappend = me.parentNode.getAttribute('data-urlappend');
  }

  if (video.width == 0) { video.width = 250; }
  if (video.height == 0) { video.height = 250; }

  // create the container
  me.parentNode.insertBefore(container, me);
  // set the class to 'mistvideo'
  container.setAttribute('class', 'mistvideo');
  // remove script tag
  me.parentNode.removeChild(me);

  if(video.error) {
    // there was an error; display it
    container.innerHTML = ['Error: ', video.error, ''].join('');
  }
  else if ((typeof video.source == 'undefined') || (video.source.length < 1)) {
    // no stream sources
    container.innerHTML = 'Error: no protocols found';
  }
  else {
    // no error, and sources found. Check the video types and output the best
    // available video player.
    var i,
      vtype = (video.type ? video.type : 'unknown'),
      foundPlayer = false,
      len = video.source.length;

    for (var i in video.source) {
      var support = hasSupport(video.source[i].type);
      video.source[i].browser_support = support;
      if ((support) || (forceType)) {
        if ((!forceType) || ((forceType) && (video.source[i].type.indexOf(forceType) >= 0))) {
          if (foundPlayer === false) {
            foundPlayer = i;
            if (!forceSupportCheck) {
              break;
            }
          }
        }
      }
    }
    if (foundPlayer === false) {
      // of all the streams given, none was supported (eg. no flash and HTML5 video). Display error
      container.innerHTML = 'No support for any player found';
    }
    else {
      // we support this kind of video, so build it.
      var source = video.source[foundPlayer];
      if (urlappend) {
        source.url += urlappend;
        source.relurl += urlappend;
      }
      else if (me.src.indexOf('?') != -1) {
        var params = me.src.split('?');
        params.shift();
        params.join('?');
        source.url += '?'+params;
        source.relurl += '?'+params;
      }
      buildPlayer(source, container, video.width, video.height, vtype);
    }
  }

  return (mistvideo[streamname].embedded ? mistvideo[streamname].embedded.type : false);
  //keep empty line at end of file
}
<|endoftext|>


<commit_before>var util = require('util'),
    EventEmitter2 = require('eventemitter2').EventEmitter2,
    _ = require('lodash'),
    async = require('async');

/**
 * A deviceguider emits 'plug' for new attached devices,
 * 'unplug' for removed devices, emits 'connect' for connected devices
 * and emits 'disconnect' for disconnected devices.
 * @param {DeviceLoader} deviceLoader The deviceloader object.
 */
function DeviceGuider(deviceLoader) {
  var self = this;

  // call super class
  EventEmitter2.call(this, {
    wildcard: true,
    delimiter: ':',
    maxListeners: 1000 // default would be 10!
  });

  if (this.log) {
    this.log = _.wrap(this.log, function(func, msg) {
      func(self.constructor.name + ': ' + msg);
    });
  }

  this.deviceErrorSubscriptions = {};
  this.deviceLoader = deviceLoader;
  this.lookupStarted = false;
  this.currentState = {
    connectionMode: 'manualconnect',
    plugged: [],
    connected: [],
    getDevice: function(id) {
      return _.find(self.currentState.plugged, function(d) {
        return d.id === id;
      });
    },
    getConnection: function(id) {
      var found = _.find(self.currentState.connected, function(dc) {
        return dc.connection.id === id;
      });

      return found ? found.connection : null;
    },
    getConnectedDevice: function(id) {
      return _.find(self.currentState.connected, function(dc) {
        return dc.id === id;
      });
    },
    getDeviceByConnection: function(id) {
      return _.find(self.currentState.connected, function(dc) {
        return dc.connection.id === id;
      });
    },
    getConnectionByDevice: function(id) {
      var found =  _.find(self.currentState.connected, function(dc) {
        return dc.id === id;
      });

      return found ? found.connection : null;
    }
  };

  var connecting = false;

  this.deviceLoader.on('plug', function(device) {

    self.deviceErrorSubscriptions[device.id] = function(err) {
      self.emit('error', err);
    };
    device.on('error', self.deviceErrorSubscriptions[device.id]);

    self.currentState.plugged.push(device);

    if (self.log) self.log('plug device with id ' + device.id);
    self.emit('plug', device);

    if (self.currentState.connectionMode !== 'manualconnect') {
      if (self.currentState.connectionMode === 'autoconnect' || self.currentState.connectionMode === 'autoconnectOne' && self.currentState.connected.length === 0) {
        if (!connecting) {
          self.connectDevice(device, function() {
            connecting = false;
          });
          connecting = true;
        }
      }
    }
  });

  this.deviceLoader.on('unplug', function(device) {
    device.removeListener('error', self.deviceErrorSubscriptions[device.id]);
    delete self.deviceErrorSubscriptions[device.id];

    self.currentState.plugged = _.reject(self.currentState.plugged, function(d) {
      return d.id === device.id;
    });
    self.currentState.connected = _.reject(self.currentState.connected, function(dc) {
      return dc.id === device.id;
    });

    if (self.log) self.log('unplug device with id ' + device.id);
    self.emit('unplug', device);
  });
}

util.inherits(DeviceGuider, EventEmitter2);

/* Override of EventEmitter. */
DeviceGuider.prototype.on = function(eventname, callback) {
  if (this.deviceLoader && (eventname === 'plug' || eventname === 'unplug')) {
    this.deviceLoader.on.apply(this.deviceLoader, _.toArray(arguments));
    if (!this.deviceLoader.isRunning) {
      this.lookupStarted = true;
      this.deviceLoader.startLookup();
    }
  } else {
    EventEmitter2.prototype.on.apply(this, _.toArray(arguments));
  }
};

/* Override of EventEmitter. */
DeviceGuider.prototype.removeListener = function(eventname, callback) {
  if (this.deviceLoader && (eventname === 'plug' || eventname === 'unplug')) {
    this.deviceLoader.removeListener.apply(this.deviceLoader, _.toArray(arguments));
    if (this.deviceLoader.listeners('plug').length === 0 && this.deviceLoader.listeners('unplug').length === 0 ) {
      this.lookupStarted = false;
      this.deviceLoader.stopLookup();
    }
  } else {
    EventEmitter2.prototype.removeListener.apply(this, _.toArray(arguments));
  }
};

/* Same as removeListener */
DeviceGuider.prototype.off = DeviceGuider.prototype.removeListener;

/**
 * Checks if the connectionMode will change and returns true or false.
 * @param  {String} mode The new connectionMode.
 * @return {Boolean}     Returns true or false.
 */
DeviceGuider.prototype.checkConnectionMode = function(mode) {
  return mode !== this.currentState.connectionMode;
};

/**
 * Checks if the connectionMode will change and emits 'connectionModeChanged'.
 * @param  {String} mode The new connectionMode.
 * @return {Boolean}     Returns true or false.
 */
DeviceGuider.prototype.changeConnectionMode = function(mode) {
  var self = this;

  var somethingChanged = this.checkConnectionMode(mode);
  this.currentState.connectionMode = mode;

  if (somethingChanged) {
    this.emit('connectionModeChanged', this.currentState.connectionMode);
  }

  return somethingChanged;
};

/**
 * Calls the callback with the current state, containing the connectionMode,
 * the list of plugged devices and the list of connected devices.
 * @param  {Function} callback The function, that will be called when state is fetched.
 *                             `function(err, currentState){}` currentState is an object.
 */
DeviceGuider.prototype.getCurrentState = function(callback) {
  var self = this;

  if (this.currentState.plugged.length > 0) {
    if (callback) { callback(null, this.currentState); }
  } else {
    if (!this.deviceLoader.isRunning && !this.lookupStarted) {
      this.deviceLoader.startLookup(function(err, devices) {
        if (callback) { callback(null, self.currentState); }
      });
    } else {
      this.deviceLoader.trigger(function(err, devices) {
        if (callback) { callback(null, self.currentState); }
      });
    }
  }
};

/**
 * It emits 'connectionModeChanged'.
 * When plugging a device it will now automatically connect it and emit 'connect'.
 * Already plugged devices will connect immediately.
 */
DeviceGuider.prototype.autoconnect = function() {
  var self = this;

  if (this.changeConnectionMode('autoconnect')) {
    if (!this.deviceLoader.isRunning && !this.lookupStarted) {
      this.deviceLoader.startLookup();
    }

    var toConnect = _.reject(this.currentState.plugged, function(d) {
      return _.find(self.currentState.connected, function(c) {
        return c.id == d.id;
      });
    });

    _.each(toConnect, function(dev) {
      self.connectDevice(dev);
    });
  }
};

/**
 * [manualconnect description]
 * @param  {Boolean}   holdConnections If set established connections will not be closed. [optional]
 * @param  {Function} callback The function, that will be called when function has finished. [optional]
 *                             `function(err){}`
 */
DeviceGuider.prototype.manualconnect = function(holdConnections, callback) {
  var self = this;

  if (arguments.length === 1) {
    if (_.isFunction(holdConnections)) {
      callback = holdConnections;
      holdConnections = false;
    }
  }

  if (this.changeConnectionMode('manualconnect')) {
    if (this.currentState.connected.length === 0) {
      if (callback) { return callback(null); }
    }

    if (!holdConnections) {
      async.forEachSeries(this.currentState.connected, function(dc, clb) {
        self.closeConnection(dc.connection, clb);
      }, function(err) {
        if (callback) { return callback(err); }
      });
    } else {
      if (callback) { return callback(null); }
    }
  } else {
    if (callback) { return callback(null); }
  }
};

/**
 * It emits 'connectionModeChanged'.
 * When plugging one device it will now automatically connect one and emit 'connect'.
 * If there is already a plugged device, it will connect immediately and call the callback.
 * @param  {Function} callback The function, that will be called when one device is connected. [optional]
 *                             `function(err, connection){}` connection is a Connection object.
 */
DeviceGuider.prototype.autoconnectOne = function(callback) {
  var self = this;

  function doIt() {
    if (self.currentState.plugged.length > 0 && self.currentState.connected.length === 0) {
      self.connectDevice(self.currentState.plugged[0], callback);
    } else {
      if (callback) callback('No device available!');
    }
  }

  if (this.changeConnectionMode('autoconnectOne')) {
    if (!this.deviceLoader.isRunning && !this.lookupStarted) {
      this.deviceLoader.startLookup(doIt);
    } else {
      doIt();
    }
  } else {
    if (callback) { return callback(null); }
  }
};

/**
 * It will connect that device and call the callback.
 * @param  {Device || String}   deviceOrId The device object or the device id.
 * @param  {Function}           callback   The function, that will be called when the device is connected. [optional]
 *                                         `function(err, connection){}` connection is a Connection object.
 */
DeviceGuider.prototype.connectDevice = function(deviceOrId, callback) {
  var self = this,
      device = deviceOrId;

  if (_.isString(deviceOrId)) {
    device = this.currentState.getDevice(deviceOrId);
  }

  if (!this.deviceErrorSubscriptions[device.id]) {
    this.deviceErrorSubscriptions[device.id] = function(err) {
      self.emit('error', err);
    };
    this.on('error', this.deviceErrorSubscriptions[device.id]);
  }

  device.on('connecting', function(dev) {
    if (self.log) self.log('connecting device with id ' + dev.id);
    self.emit('connecting', dev);
  });

  device.connect(function(err, connection) {
    if (err) {
      if (self.log) self.log('error calling connect' + JSON.stringify(err));
      //self.emit('error', err);
      if (callback) {
        callback(err, connection);
      }
      return;
    }
    self.currentState.connected.push(device);

    connection.on('disconnecting', function(conn) {
      if (self.log) self.log('disconnecting device with id ' + conn.device.id + ' and connection id ' + conn.id);
      self.emit('disconnecting', conn);
    });

    connection.on('disconnect', function(conn) {
      self.currentState.connected = _.reject(self.currentState.connected, function(dc) {
        return dc.connection.id === conn.id;
      });

      if (self.log) self.log('disconnect device with id ' + conn.device.id + ' and connection id ' + conn.id);
      self.emit('disconnect', conn);
    });

    if (self.log) self.log('connect device with id ' + device.id + ' and connection id ' + connection.id);
    self.emit('connect', connection);

    if (callback) callback(err, connection);
  });
};

/**
 * It will disconnect that device and call the callback.
 * @param  {Device || String}   deviceOrId The device object or the device id.
 * @param  {Function}           callback  The function, that will be called when the device is disconnected. [optional]
 *                                        `function(err, connection){}` connection is a Connection object.
 */
DeviceGuider.prototype.disconnectDevice = function(deviceOrId, callback) {
  var self = this,
      device = deviceOrId;

  if (_.isString(deviceOrId)) {
    device = this.currentState.getConnectedDevice(deviceOrId);
  }

  if (!device) {
    if (this.log) this.log('Device not connected!');
    //self.emit('error', 'Device not connected!');
    if (callback) { callback('Device not connected!'); }
    return;
  }

  device.disconnect(function(err) {
    if (err) {
      if (self.log) self.log('error calling disconnect' + JSON.stringify(err));
      //self.emit('error', err);
      if (callback) {
        callback(err, device.connection);
      }
      return;
    }

    if (callback) callback(err, device.connection);
  });
};

/**
 * It will close that connection and call the callback.
 * @param  {Connection || String}   connectionOrId The connection object or the connection id.
 * @param  {Function}               callback      The function, that will be called when the connection is closed. [optional]
 *                                                `function(err, connection){}` connection is a Connection object.
 */
DeviceGuider.prototype.closeConnection = function(connectionOrId, callback) {
  var self = this,
      connection = connectionOrId;

  if (_.isString(connectionOrId)) {
    connection = this.currentState.getConnection(connectionOrId);
  }

  connection.close(function(err) {
    if (err) {
      if (self.log) self.log('error calling disconnect' + JSON.stringify(err));
      //self.emit('error', err);
      if (callback) {
        callback(err, connection);
      }
      return;
    }

    if (callback) callback(err, connection);
  });
};

module.exports = DeviceGuider;<commit_msg>little fix<commit_after>var util = require('util'),
    EventEmitter2 = require('eventemitter2').EventEmitter2,
    _ = require('lodash'),
    async = require('async');

/**
 * A deviceguider emits 'plug' for new attached devices,
 * 'unplug' for removed devices, emits 'connect' for connected devices
 * and emits 'disconnect' for disconnected devices.
 * @param {DeviceLoader} deviceLoader The deviceloader object.
 */
function DeviceGuider(deviceLoader) {
  var self = this;

  // call super class
  EventEmitter2.call(this, {
    wildcard: true,
    delimiter: ':',
    maxListeners: 1000 // default would be 10!
  });

  if (this.log) {
    this.log = _.wrap(this.log, function(func, msg) {
      func(self.constructor.name + ': ' + msg);
    });
  }

  this.deviceErrorSubscriptions = {};
  this.deviceLoader = deviceLoader;
  this.lookupStarted = false;
  this.currentState = {
    connectionMode: 'manualconnect',
    plugged: [],
    connected: [],
    getDevice: function(id) {
      return _.find(self.currentState.plugged, function(d) {
        return d.id === id;
      });
    },
    getConnection: function(id) {
      var found = _.find(self.currentState.connected, function(dc) {
        return dc.connection.id === id;
      });

      return found ? found.connection : null;
    },
    getConnectedDevice: function(id) {
      return _.find(self.currentState.connected, function(dc) {
        return dc.id === id;
      });
    },
    getDeviceByConnection: function(id) {
      return _.find(self.currentState.connected, function(dc) {
        return dc.connection.id === id;
      });
    },
    getConnectionByDevice: function(id) {
      var found =  _.find(self.currentState.connected, function(dc) {
        return dc.id === id;
      });

      return found ? found.connection : null;
    }
  };

  var connecting = false;

  this.deviceLoader.on('plug', function(device) {

    self.deviceErrorSubscriptions[device.id] = function(err) {
      self.emit('error', err);
    };
    device.on('error', self.deviceErrorSubscriptions[device.id]);

    self.currentState.plugged.push(device);

    if (self.log) self.log('plug device with id ' + device.id);
    self.emit('plug', device);

    if (self.currentState.connectionMode !== 'manualconnect') {
      if (self.currentState.connectionMode === 'autoconnect' || self.currentState.connectionMode === 'autoconnectOne' && self.currentState.connected.length === 0) {
        if (!connecting) {
          self.connectDevice(device, function() {
            connecting = false;
          });
          connecting = true;
        }
      }
    }
  });

  this.deviceLoader.on('unplug', function(device) {
    device.removeListener('error', self.deviceErrorSubscriptions[device.id]);
    delete self.deviceErrorSubscriptions[device.id];

    self.currentState.plugged = _.reject(self.currentState.plugged, function(d) {
      return d.id === device.id;
    });
    self.currentState.connected = _.reject(self.currentState.connected, function(dc) {
      return dc.id === device.id;
    });

    if (self.log) self.log('unplug device with id ' + device.id);
    self.emit('unplug', device);
  });
}

util.inherits(DeviceGuider, EventEmitter2);

/* Override of EventEmitter. */
DeviceGuider.prototype.on = function(eventname, callback) {
  if (this.deviceLoader && (eventname === 'plug' || eventname === 'unplug')) {
    this.deviceLoader.on.apply(this.deviceLoader, _.toArray(arguments));
    if (!this.deviceLoader.isRunning) {
      this.lookupStarted = true;
      this.deviceLoader.startLookup();
    }
  } else {
    EventEmitter2.prototype.on.apply(this, _.toArray(arguments));
  }
};

/* Override of EventEmitter. */
DeviceGuider.prototype.removeListener = function(eventname, callback) {
  if (this.deviceLoader && (eventname === 'plug' || eventname === 'unplug')) {
    this.deviceLoader.removeListener.apply(this.deviceLoader, _.toArray(arguments));
    if (this.deviceLoader.listeners('plug').length === 0 && this.deviceLoader.listeners('unplug').length === 0 ) {
      this.lookupStarted = false;
      this.deviceLoader.stopLookup();
    }
  } else {
    EventEmitter2.prototype.removeListener.apply(this, _.toArray(arguments));
  }
};

/* Same as removeListener */
DeviceGuider.prototype.off = DeviceGuider.prototype.removeListener;

/**
 * Checks if the connectionMode will change and returns true or false.
 * @param  {String} mode The new connectionMode.
 * @return {Boolean}     Returns true or false.
 */
DeviceGuider.prototype.checkConnectionMode = function(mode) {
  return mode !== this.currentState.connectionMode;
};

/**
 * Checks if the connectionMode will change and emits 'connectionModeChanged'.
 * @param  {String} mode The new connectionMode.
 * @return {Boolean}     Returns true or false.
 */
DeviceGuider.prototype.changeConnectionMode = function(mode) {
  var self = this;

  var somethingChanged = this.checkConnectionMode(mode);
  this.currentState.connectionMode = mode;

  if (somethingChanged) {
    this.emit('connectionModeChanged', this.currentState.connectionMode);
  }

  return somethingChanged;
};

/**
 * Calls the callback with the current state, containing the connectionMode,
 * the list of plugged devices and the list of connected devices.
 * @param  {Function} callback The function, that will be called when state is fetched.
 *                             `function(err, currentState){}` currentState is an object.
 */
DeviceGuider.prototype.getCurrentState = function(callback) {
  var self = this;

  if (this.currentState.plugged.length > 0) {
    if (callback) { callback(null, this.currentState); }
  } else {
    if (!this.deviceLoader.isRunning && !this.lookupStarted) {
      this.deviceLoader.startLookup(function(err, devices) {
        if (callback) { callback(null, self.currentState); }
      });
    } else {
      this.deviceLoader.trigger(function(err, devices) {
        if (callback) { callback(null, self.currentState); }
      });
    }
  }
};

/**
 * It emits 'connectionModeChanged'.
 * When plugging a device it will now automatically connect it and emit 'connect'.
 * Already plugged devices will connect immediately.
 */
DeviceGuider.prototype.autoconnect = function() {
  var self = this;

  if (this.changeConnectionMode('autoconnect')) {
    if (!this.deviceLoader.isRunning && !this.lookupStarted) {
      this.deviceLoader.startLookup();
    }

    var toConnect = _.reject(this.currentState.plugged, function(d) {
      return _.find(self.currentState.connected, function(c) {
        return c.id == d.id;
      });
    });

    _.each(toConnect, function(dev) {
      self.connectDevice(dev);
    });
  }
};

/**
 * [manualconnect description]
 * @param  {Boolean}   holdConnections If set established connections will not be closed. [optional]
 * @param  {Function} callback The function, that will be called when function has finished. [optional]
 *                             `function(err){}`
 */
DeviceGuider.prototype.manualconnect = function(holdConnections, callback) {
  var self = this;

  if (arguments.length === 1) {
    if (_.isFunction(holdConnections)) {
      callback = holdConnections;
      holdConnections = false;
    }
  }

  if (this.changeConnectionMode('manualconnect')) {
    if (this.currentState.connected.length === 0) {
      if (callback) { return callback(null); }
    }

    if (!holdConnections) {
      async.forEachSeries(this.currentState.connected, function(dc, clb) {
        self.closeConnection(dc.connection, clb);
      }, function(err) {
        if (callback) { return callback(err); }
      });
    } else {
      if (callback) { return callback(null); }
    }
  } else {
    if (callback) { return callback(null); }
  }
};

/**
 * It emits 'connectionModeChanged'.
 * When plugging one device it will now automatically connect one and emit 'connect'.
 * If there is already a plugged device, it will connect immediately and call the callback.
 * @param  {Function} callback The function, that will be called when one device is connected. [optional]
 *                             `function(err, connection){}` connection is a Connection object.
 */
DeviceGuider.prototype.autoconnectOne = function(callback) {
  var self = this;

  function doIt() {
    if (self.currentState.plugged.length > 0 && self.currentState.connected.length === 0) {
      self.connectDevice(self.currentState.plugged[0], callback);
    } else {
      if (callback) callback('No device available!');
    }
  }

  if (this.changeConnectionMode('autoconnectOne')) {
    if (!this.deviceLoader.isRunning && !this.lookupStarted) {
      this.deviceLoader.startLookup(doIt);
    } else {
      doIt();
    }
  } else {
    if (callback) { return callback(null); }
  }
};

/**
 * It will connect that device and call the callback.
 * @param  {Device || String}   deviceOrId The device object or the device id.
 * @param  {Function}           callback   The function, that will be called when the device is connected. [optional]
 *                                         `function(err, connection){}` connection is a Connection object.
 */
DeviceGuider.prototype.connectDevice = function(deviceOrId, callback) {
  var self = this,
      device = deviceOrId;

  if (_.isString(deviceOrId)) {
    device = this.currentState.getDevice(deviceOrId);
  }

  if (!this.deviceErrorSubscriptions[device.id]) {
    this.deviceErrorSubscriptions[device.id] = function(err) {
      self.emit('error', err);
    };
    this.on('error', this.deviceErrorSubscriptions[device.id]);
  }

  device.on('connecting', function(dev) {
    if (self.log) self.log('connecting device with id ' + dev.id);
    self.emit('connecting', dev);
  });

  device.connect(function(err, connection) {
    if (err) {
      if (self.log) self.log('error calling connect' + JSON.stringify(err));
      //self.emit('error', err);
      if (callback) {
        callback(err, connection);
      }
      return;
    }
    self.currentState.connected.push(device);

    connection.on('disconnecting', function(conn) {
      if (self.log) self.log('disconnecting device with id ' + conn.device.id + ' and connection id ' + conn.id);
      self.emit('disconnecting', conn.get('device'));
    });

    connection.on('disconnect', function(conn) {
      self.currentState.connected = _.reject(self.currentState.connected, function(dc) {
        return dc.connection.id === conn.id;
      });

      if (self.log) self.log('disconnect device with id ' + conn.device.id + ' and connection id ' + conn.id);
      self.emit('disconnect', conn);
    });

    if (self.log) self.log('connect device with id ' + device.id + ' and connection id ' + connection.id);
    self.emit('connect', connection);

    if (callback) callback(err, connection);
  });
};

/**
 * It will disconnect that device and call the callback.
 * @param  {Device || String}   deviceOrId The device object or the device id.
 * @param  {Function}           callback  The function, that will be called when the device is disconnected. [optional]
 *                                        `function(err, connection){}` connection is a Connection object.
 */
DeviceGuider.prototype.disconnectDevice = function(deviceOrId, callback) {
  var self = this,
      device = deviceOrId;

  if (_.isString(deviceOrId)) {
    device = this.currentState.getConnectedDevice(deviceOrId);
  }

  if (!device) {
    if (this.log) this.log('Device not connected!');
    //self.emit('error', 'Device not connected!');
    if (callback) { callback('Device not connected!'); }
    return;
  }

  device.disconnect(function(err) {
    if (err) {
      if (self.log) self.log('error calling disconnect' + JSON.stringify(err));
      //self.emit('error', err);
      if (callback) {
        callback(err, device.connection);
      }
      return;
    }

    if (callback) callback(err, device.connection);
  });
};

/**
 * It will close that connection and call the callback.
 * @param  {Connection || String}   connectionOrId The connection object or the connection id.
 * @param  {Function}               callback      The function, that will be called when the connection is closed. [optional]
 *                                                `function(err, connection){}` connection is a Connection object.
 */
DeviceGuider.prototype.closeConnection = function(connectionOrId, callback) {
  var self = this,
      connection = connectionOrId;

  if (_.isString(connectionOrId)) {
    connection = this.currentState.getConnection(connectionOrId);
  }

  connection.close(function(err) {
    if (err) {
      if (self.log) self.log('error calling disconnect' + JSON.stringify(err));
      //self.emit('error', err);
      if (callback) {
        callback(err, connection);
      }
      return;
    }

    if (callback) callback(err, connection);
  });
};

module.exports = DeviceGuider;<|endoftext|>


<commit_before>/*
 * Please see the included LICENSE.md file for license terms and conditions.
 */
/* jshint browser:true */
(function() {

    var myFirebaseRef;
    var myPlayerId = "player1";
	// Wait for DOM tree is ready for access
    document.addEventListener('DOMContentLoaded', function() {
        var canvas = document.getElementById('gameScene');
        // make canvas full screen
        var width = screen.availWidth;
        var height = screen.availHeight;
        canvas.width = width;
        canvas.height = height;

        // get canvas 2d context
        // With canvas 2d context, you can draw anything freely on the canvas.
        // See https://docs.webplatform.org/wiki/tutorials/canvas/canvas_tutorial
        // for tutorials of using canvas.
        var context = canvas.getContext('2d');

        // load and draw image on the canvas
        var img = new Image();
        img.onload = function() {
            context.drawImage(img, (width - img.width) / 2, (height - img.height) / 2);
        };
        img.src = "asset/logo.png";
    }, false);

    init();

    function init() {
      myFirebaseRef = new Firebase("https://battlepong.firebaseio.com/");
      myFirebaseRef.child('players').set({
          'player1': { score: 0},
          'player2': { score: 0}
      });
      watchForThrow();
      throwball(20, 100);
    }

    function throwball (yPercent, velocity) {
      myFirebaseRef.child('throws').push({
        'ypercent': yPercent,
        'velocity': velocity,
        'complete': false,
        'caught': false,
        'thrower': myPlayerId
      });
    }

    function watchForThrow () {
      myFirebaseRef.child("throws").on("child_added", function(snapshot,  prevChildKey) {
        if (snapshot.val().complete == false)
          startRoll(snapshot.key(), snapshot.val());
      });
    }

    function startRoll (id, snap) {
      catchBall(id);
      // missBall(id, snap.thrower);
    }

    function catchBall (throwId) {
      myFirebaseRef.child("throws").child(throwId).update({
        complete: true,
        caught: true,
      });

      updateScore(myPlayerId, 10);
    }

    function missBall (throwId, from) {
      myFirebaseRef.child("throws").child(throwId).update({
        complete: true
      });

      updateScore(from, 10);
    }

    function updateScore(playerId, change) {
      var scoreRef = myFirebaseRef.child('players').child(playerId).child('score');
      scoreRef.transaction(function(currentScore) {
        return currentScore+change;
      });
    }

}());
<commit_msg>Adding orientation lock<commit_after>/*
 * Please see the included LICENSE.md file for license terms and conditions.
 */
/* jshint browser:true */
(function() {
    document.addEventListener("intel.xdk.device.ready", onDeviceReady, false);
    function onDeviceReady(){
    // set orientation
    intel.xdk.device.setRotateOrientation('portrait');
}

    var myFirebaseRef;
    var myPlayerId = "player1";
	// Wait for DOM tree is ready for access
    document.addEventListener('DOMContentLoaded', function() {
        var canvas = document.getElementById('gameScene');
        // make canvas full screen
        var width = screen.availWidth;
        var height = screen.availHeight;
        canvas.width = width;
        canvas.height = height;

        // get canvas 2d context
        // With canvas 2d context, you can draw anything freely on the canvas.
        // See https://docs.webplatform.org/wiki/tutorials/canvas/canvas_tutorial
        // for tutorials of using canvas.
        var context = canvas.getContext('2d');

        // load and draw image on the canvas
        var img = new Image();
        img.onload = function() {
            context.drawImage(img, (width - img.width) / 2, (height - img.height) / 2);
        };
        img.src = "asset/logo.png";
    }, false);

    init();

    function init() {
      myFirebaseRef = new Firebase("https://battlepong.firebaseio.com/");
      myFirebaseRef.child('players').set({
          'player1': { score: 0},
          'player2': { score: 0}
      });
      watchForThrow();
      throwball(20, 100);
    }

    function throwball (yPercent, velocity) {
      myFirebaseRef.child('throws').push({
        'ypercent': yPercent,
        'velocity': velocity,
        'complete': false,
        'caught': false,
        'thrower': myPlayerId
      });
    }

    function watchForThrow () {
      myFirebaseRef.child("throws").on("child_added", function(snapshot,  prevChildKey) {
        if (snapshot.val().complete == false)
          startRoll(snapshot.key(), snapshot.val());
      });
    }

    function startRoll (id, snap) {
      catchBall(id);
      // missBall(id, snap.thrower);
    }

    function catchBall (throwId) {
      myFirebaseRef.child("throws").child(throwId).update({
        complete: true,
        caught: true,
      });

      updateScore(myPlayerId, 10);
    }

    function missBall (throwId, from) {
      myFirebaseRef.child("throws").child(throwId).update({
        complete: true
      });

      updateScore(from, 10);
    }

    function updateScore(playerId, change) {
      var scoreRef = myFirebaseRef.child('players').child(playerId).child('score');
      scoreRef.transaction(function(currentScore) {
        return currentScore+change;
      });
    }

}());
<|endoftext|>


<commit_before>/*
 Copyright (C) 2017  Cloudbase Solutions SRL

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as
 published by the Free Software Foundation, either version 3 of the
 License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import Reflux from 'reflux';
import UserActions from '../../actions/UserActions';
import ConnectionsActions from '../../actions/ConnectionsActions'
import Location from '../../core/Location';
import Api from '../../components/ApiCaller';
import cookie from 'react-cookie';
import moment from 'moment';
import { servicesUrl } from '../../config'

class UserStore extends Reflux.Store
{
  user = {
    id: null,
    name: "-",
    email: "-",
    created: new Date(),
    project: {},
    roles: [],
    projects: null,
    token: null,
    settings: {
      notifications: true
    }
  }

  constructor() {
    super()
    this.listenables = UserActions

    this.state = {
      currentUser: this.user,
      loadingState: false
    }

    let token = cookie.load('token')
    let projectId = cookie.load('projectId')
    if (token && projectId) {
      UserActions.tokenLogin(token, projectId)
    }
  }

  onLogin() {
    Api.setDefaultHeader('X-Auth-Token', null)
    this.setState({ loadingState: true })
  }

  onLoginSuccess(response) {
    let token = response.headers['X-Subject-Token'] || response.headers['x-subject-token']
    Api.setDefaultHeader('X-Auth-Token', token)
    cookie.save('unscopedToken', token, { path: "/", expires: moment().add(1, 'hour').toDate() })
    UserActions.getScopedProjects(res => {
      if (res.data.projects) {
        let projectId = cookie.load('projectId')
        if (!projectId) {
          projectId = res.data.projects[0].id
        }
        UserActions.loginScope(token, projectId)
      } else {
        // TODO: Error case no scoped projects
      }
    })
  }

  onLoginScopeSuccess(response) {
    this.setState({ loadingState: false })

    let currentUser = this.state.currentUser
    currentUser.id = response.data.token.user.id
    currentUser.name = response.data.token.user.name
    currentUser.token = response.headers['X-Subject-Token'] || response.headers['x-subject-token']
    currentUser.project = response.data.token.project

    cookie.save('token', currentUser.token, { path: "/", expires: moment().add(1, 'hour').toDate() })
    cookie.save('projectId', currentUser.project.id, { path: "/", expires: moment().add(1, 'months').toDate() })
    Api.setDefaultHeader('X-Auth-Token', currentUser.token)

    this.setState({ currentUser: currentUser })

    ConnectionsActions.loadProviders()
    ConnectionsActions.loadConnections()
    UserActions.getScopedProjects()
    UserActions.getUserInfo(currentUser.id)

    if (window.location.pathname == "/" || window.location.pathname == "/login") {
      Location.push('/replicas');
    }
  }

  onLoginScopeFailed(token) {
    // In case the scoping the project id from cookie didn't work, fallback to first project in list
    UserActions.loginScope(token, this.state.currentUser.projects[0].id, false)
  }

  onLoginFailed() {
    this.setState({ loadingState: false })
  }

  onLogout() {
    Api.sendAjaxRequest({
      url: servicesUrl.identity,
      method: "DELETE",
      headers: { 'X-Subject-Token': this.state.currentUser.token }
    })
    .then(() => {
      cookie.remove('token');
      window.location.href = "/"
    })
    .catch(() => {
      cookie.remove('token');
      window.location.href = "/"
    })

    Api.resetHeaders()
  }

  onGetUserInfoCompleted(response) {
    let currentUser = this.state.currentUser
    currentUser.email = response.data.user.email
    this.setState({ currentUser: currentUser })
  }

  onSetUserInfoSuccess() {

  }

  onTokenLoginFailed() {
    cookie.remove('token');
    cookie.remove('projectId');
    Api.resetHeaders()
    Location.push('/login');
  }

  onLogoutSuccess() {
    cookie.remove('token');
    cookie.remove('projectId');
    Location.push('/login');
  }

  onSetCurrentUser(userId) {
    this.state.users.forEach(user => {
      if (user.id == userId) {
        this.setState({ currentUser: user })
      }
    }, this)
  }

  onSwitchProject(projectId) {
    if (projectId) {
      let token = cookie.load('unscopedToken')
      Api.setDefaultHeader('X-Auth-Token', null)
      UserActions.loginScope(token, projectId)
    }
  }

  onGetScopedProjectsCompleted(response) {
    let currentUser = this.state.currentUser
    currentUser.projects = response.data.projects

    this.setState({ currentUser: currentUser })
  }

  onFederateToken(token) {
    Api.setDefaultHeader('X-Auth-Token', token)
    cookie.save('unscopedToken', token, { path: "/", expires: moment().add(1, 'hour').toDate() })
    UserActions.getScopedProjects(response => {
      if (response.data.projects) {
        UserActions.loginScope(token, response.data.projects[0].id)
      } else {
        // TODO: Error case no scoped projects
      }
    })
  }
}

UserStore.id = "userStore"

export default UserStore;
<commit_msg>Logs out if unscoped token expired CORWEB-54<commit_after>/*
 Copyright (C) 2017  Cloudbase Solutions SRL

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as
 published by the Free Software Foundation, either version 3 of the
 License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import Reflux from 'reflux';
import UserActions from '../../actions/UserActions';
import ConnectionsActions from '../../actions/ConnectionsActions'
import Location from '../../core/Location';
import Api from '../../components/ApiCaller';
import cookie from 'react-cookie';
import moment from 'moment';
import { servicesUrl } from '../../config'

class UserStore extends Reflux.Store
{
  user = {
    id: null,
    name: "-",
    email: "-",
    created: new Date(),
    project: {},
    roles: [],
    projects: null,
    token: null,
    settings: {
      notifications: true
    }
  }

  constructor() {
    super()
    this.listenables = UserActions

    this.state = {
      currentUser: this.user,
      loadingState: false
    }

    let token = cookie.load('token')
    let projectId = cookie.load('projectId')
    if (token && projectId) {
      UserActions.tokenLogin(token, projectId)
    }
  }

  onLogin() {
    Api.setDefaultHeader('X-Auth-Token', null)
    this.setState({ loadingState: true })
  }

  onLoginSuccess(response) {
    let token = response.headers['X-Subject-Token'] || response.headers['x-subject-token']
    Api.setDefaultHeader('X-Auth-Token', token)
    cookie.save('unscopedToken', token, { path: "/", expires: moment().add(1, 'hour').toDate() })
    UserActions.getScopedProjects(res => {
      if (res.data.projects) {
        let projectId = cookie.load('projectId')
        if (!projectId) {
          projectId = res.data.projects[0].id
        }
        UserActions.loginScope(token, projectId)
      } else {
        // TODO: Error case no scoped projects
      }
    })
  }

  onLoginScopeSuccess(response) {
    this.setState({ loadingState: false })

    let currentUser = this.state.currentUser
    currentUser.id = response.data.token.user.id
    currentUser.name = response.data.token.user.name
    currentUser.token = response.headers['X-Subject-Token'] || response.headers['x-subject-token']
    currentUser.project = response.data.token.project

    cookie.save('token', currentUser.token, { path: "/", expires: moment().add(1, 'hour').toDate() })
    cookie.save('projectId', currentUser.project.id, { path: "/", expires: moment().add(1, 'months').toDate() })
    Api.setDefaultHeader('X-Auth-Token', currentUser.token)

    this.setState({ currentUser: currentUser })

    ConnectionsActions.loadProviders()
    ConnectionsActions.loadConnections()
    UserActions.getScopedProjects()
    UserActions.getUserInfo(currentUser.id)

    if (window.location.pathname == "/" || window.location.pathname == "/login") {
      Location.push('/replicas');
    }
  }

  onLoginScopeFailed(token) {
    // In case the scoping the project id from cookie didn't work, fallback to first project in list
    UserActions.loginScope(token, this.state.currentUser.projects[0].id, false)
  }

  onLoginFailed() {
    this.setState({ loadingState: false })
  }

  onLogout() {
    Api.sendAjaxRequest({
      url: servicesUrl.identity,
      method: "DELETE",
      headers: { 'X-Subject-Token': this.state.currentUser.token }
    })
    .then(() => {
      cookie.remove('token');
      window.location.href = "/"
    })
    .catch(() => {
      cookie.remove('token');
      window.location.href = "/"
    })

    Api.resetHeaders()
  }

  onGetUserInfoCompleted(response) {
    let currentUser = this.state.currentUser
    currentUser.email = response.data.user.email
    this.setState({ currentUser: currentUser })
  }

  onSetUserInfoSuccess() {

  }

  onTokenLoginFailed() {
    cookie.remove('token');
    cookie.remove('projectId');
    Api.resetHeaders()
    Location.push('/login');
  }

  onLogoutSuccess() {
    cookie.remove('token');
    cookie.remove('projectId');
    Location.push('/login');
  }

  onSetCurrentUser(userId) {
    this.state.users.forEach(user => {
      if (user.id == userId) {
        this.setState({ currentUser: user })
      }
    }, this)
  }

  onSwitchProject(projectId) {
    if (projectId) {
      let token = cookie.load('unscopedToken')
      if (token) {
        Api.setDefaultHeader('X-Auth-Token', null)
        UserActions.loginScope(token, projectId)
      } else {
        UserActions.logout()
      }
    }
  }

  onGetScopedProjectsCompleted(response) {
    let currentUser = this.state.currentUser
    currentUser.projects = response.data.projects

    this.setState({ currentUser: currentUser })
  }

  onFederateToken(token) {
    Api.setDefaultHeader('X-Auth-Token', token)
    cookie.save('unscopedToken', token, { path: "/", expires: moment().add(1, 'hour').toDate() })
    UserActions.getScopedProjects(response => {
      if (response.data.projects) {
        UserActions.loginScope(token, response.data.projects[0].id)
      } else {
        // TODO: Error case no scoped projects
      }
    })
  }
}

UserStore.id = "userStore"

export default UserStore;
<|endoftext|>


<commit_before>var d3 = require('d3'),
    vg = require('vega'),
    parameter = require('./parameter'),
    post = require('./post');

var config = {
  // URL for loading specs into editor
  editor_url: 'http://vega.github.io/vega-editor/',

  // HTML to inject within view source head element
  source_header: '',

  // HTML to inject before view source closing body tag
  source_footer: ''
};

function load(url, arg, el, callback) {
  vg.util.load({url: url}, function(err, data) {
    if (err || !data) {
      console.error(err || ('No data found at ' + url));
    } else {
      // marshal embedding spec and restart
      var opt = !arg ? JSON.parse(data) : vg.util.extend({source: data}, arg);
      embed(el, opt, callback);
    }
  });
}

// Embed a Vega visualization component in a web page.
// el: DOM element in which to place component (DOM node or CSS selector)
// opt: Embedding specification (parsed JSON or URL string)
// callback: invoked with the generated Vega View instance
function embed(el, opt, callback) {
  var params = [], source, spec;

  if (vg.util.isString(opt)) {
    return load(opt, null, el, callback);
  } else if (opt.source) {
    source = opt.source;
    spec = JSON.parse(source);
  } else if (opt.spec) {
    spec = opt.spec;
    source = JSON.stringify(spec, null, 2);
  } else if (opt.url) {
    return load(opt.url, opt, el, callback);
  } else {
    spec = opt;
    source = JSON.stringify(spec, null, 2);
    opt = {spec: spec, actions: false};
  }

  // ensure container div has class 'vega-embed'
  var div = d3.select(el)
    .classed('vega-embed', true)
    .html(''); // clear container

  // handle parameters
  if (opt.parameters) {
    var elp = opt.parameter_el ? d3.select(opt.parameter_el) : div;
    var pdiv = elp.append('div')
      .attr('class', 'vega-params');
    params = opt.parameters.map(function(p) {
      return parameter.init(pdiv, p, spec);
    });
  }

  vg.parse.spec(spec, function(chart) {
    var renderer = opt.renderer || 'canvas',
        isCanvas = renderer === 'canvas',
        actions  = opt.actions || {};

    var view = chart({
      el: el,
      data: opt.data || undefined,
      renderer: renderer
    });

    if (opt.actions !== false) {
      // add child div to house action links
      var ctrl = div.append('div')
        .attr('class', 'vega-actions');

      // add 'Export' action
      if (actions.export !== false) {
        ctrl.append('a')
          .text('Export as ' + (isCanvas ? 'PNG' : 'SVG'))
          .attr('href', '#')
          .attr('download', spec.name || 'vega')
          .on('mousedown', function() {
            var ren = view.renderer(),
                data, blob;

            if (isCanvas) {
              data = ren.scene().toDataURL('image/png');
            } else if (renderer === 'svg') {
              blob = new Blob([ren.svg()], {type: 'image/svg+xml'});
              data = window.URL.createObjectURL(blob);
            }

            this.href = data;
            d3.event.preventDefault();
          });
      }

      // add 'View Source' action
      if (actions.source !== false) {
        ctrl.append('a')
          .text('View Source')
          .attr('href', '#')
          .on('click', function() {
            viewSource(source);
            d3.event.preventDefault();
          });
      }

      // add 'Open in Vega Editor' action
      if (actions.editor !== false) {
        ctrl.append('a')
          .text('Open in Vega Editor')
          .attr('href', '#')
          .on('click', function() {
            post(window, embed.config.editor_url, {spec: source});
            d3.event.preventDefault();
          });
      }
    }

    // bind all parameter elements
    params.forEach(function(p) { parameter.bind(p, view); });

    // initialize and return visualization
    view.update();
    if (callback) callback(view, spec);
  });
}

function viewSource(source) {
  var header = '' + config.source_header + '' + '
';
  var footer = '
' + config.source_footer + '';
  var win = window.open('');
  win.document.write(header + source + footer);
  win.document.title = 'Vega JSON Source';
}

// make config externally visible
embed.config = config;

module.exports = embed;
<commit_msg>Make imageURL externally visible.<commit_after>var d3 = require('d3'),
    vg = require('vega'),
    parameter = require('./parameter'),
    post = require('./post');

var config = {
  // URL for loading specs into editor
  editor_url: 'http://vega.github.io/vega-editor/',

  // HTML to inject within view source head element
  source_header: '',

  // HTML to inject before view source closing body tag
  source_footer: ''
};

function load(url, arg, el, callback) {
  vg.util.load({url: url}, function(err, data) {
    if (err || !data) {
      console.error(err || ('No data found at ' + url));
    } else {
      // marshal embedding spec and restart
      var opt = !arg ? JSON.parse(data) : vg.util.extend({source: data}, arg);
      embed(el, opt, callback);
    }
  });
}

// Embed a Vega visualization component in a web page.
// el: DOM element in which to place component (DOM node or CSS selector)
// opt: Embedding specification (parsed JSON or URL string)
// callback: invoked with the generated Vega View instance
function embed(el, opt, callback) {
  var params = [], source, spec;

  if (vg.util.isString(opt)) {
    return load(opt, null, el, callback);
  } else if (opt.source) {
    source = opt.source;
    spec = JSON.parse(source);
  } else if (opt.spec) {
    spec = opt.spec;
    source = JSON.stringify(spec, null, 2);
  } else if (opt.url) {
    return load(opt.url, opt, el, callback);
  } else {
    spec = opt;
    source = JSON.stringify(spec, null, 2);
    opt = {spec: spec, actions: false};
  }

  // ensure container div has class 'vega-embed'
  var div = d3.select(el)
    .classed('vega-embed', true)
    .html(''); // clear container

  // handle parameters
  if (opt.parameters) {
    var elp = opt.parameter_el ? d3.select(opt.parameter_el) : div;
    var pdiv = elp.append('div')
      .attr('class', 'vega-params');
    params = opt.parameters.map(function(p) {
      return parameter.init(pdiv, p, spec);
    });
  }

  vg.parse.spec(spec, function(chart) {
    var renderer = opt.renderer || 'canvas',
        actions  = opt.actions || {};

    var view = chart({
      el: el,
      data: opt.data || undefined,
      renderer: renderer
    });

    if (opt.actions !== false) {
      // add child div to house action links
      var ctrl = div.append('div')
        .attr('class', 'vega-actions');

      // add 'Export' action
      if (actions.export !== false) {
        ctrl.append('a')
          .text('Export as ' + (renderer==='canvas' ? 'PNG' : 'SVG'))
          .attr('href', '#')
          .attr('download', spec.name || 'vega')
          .on('mousedown', function() {
            this.href = imageURL(view);
            d3.event.preventDefault();
          });
      }

      // add 'View Source' action
      if (actions.source !== false) {
        ctrl.append('a')
          .text('View Source')
          .attr('href', '#')
          .on('click', function() {
            viewSource(source);
            d3.event.preventDefault();
          });
      }

      // add 'Open in Vega Editor' action
      if (actions.editor !== false) {
        ctrl.append('a')
          .text('Open in Vega Editor')
          .attr('href', '#')
          .on('click', function() {
            post(window, embed.config.editor_url, {spec: source});
            d3.event.preventDefault();
          });
      }
    }

    // bind all parameter elements
    params.forEach(function(p) { parameter.bind(p, view); });

    // initialize and return visualization
    view.update();
    if (callback) callback(view, spec);
  });
}

function imageURL(view) {
  var ren = view.renderer(),
      scene = ren.scene();

  if (ren.svg) {
    var blob = new Blob([ren.svg()], {type: 'image/svg+xml'});
    return window.URL.createObjectURL(blob);
  } else if (scene.toDataURL) {
    return scene.toDataURL('image/png');
  } else {
    throw Error('Renderer does not support image export.');
  }
}

function viewSource(source) {
  var header = '' + config.source_header + '' + '
';
  var footer = '
' + config.source_footer + '';
  var win = window.open('');
  win.document.write(header + source + footer);
  win.document.title = 'Vega JSON Source';
}

// make config and imageURL externally visible
embed.config = config;
embed.imageURL = imageURL;

module.exports = embed;
<|endoftext|>


<commit_before>var route=""
var bus_stop=""
var direction=""
var travel_time=420
$( "#submit" ).click(function() {
    route = $(".route").text()
    bus_stop= $(".route").text()
    direction=$(".direction").text()
    travel_time=$(".travel_time").text();
    if($("#map").length){
        $("#map").remove()
        }
    $( "body" ).append( $newdiv1, [ newdiv2, existingdiv1 ] );
})
 function initMap() {

            var busLatLng = {lat: 39.95, lng: -75.1667};

            var map = new google.maps.Map(document.getElementById('map'), {
                  zoom: 100,
                  center: busLatLng
                });

            var bus_marker = new google.maps.Marker({
                  position: busLatLng,
                  map: map,
                  title: 'Your Location',
                  icon: 'img/bus_stop.png'
                    });

            var flightPlanCoordinates = [
                {lat: 39.772, lng: -75.214},
                {lat: 39.291, lng: -75.821},
                {lat: 39.142, lng: -75.431},
                {lat: 39.467, lng: -75.027}
              ];
            var flightPath = new google.maps.Polyline({
                path: flightPlanCoordinates,
                geodesic: true,
                strokeColor: '#FF0000',
                strokeOpacity: 1.0,
                strokeWeight: 2
              });

            flightPath.setMap(map);
        }<commit_msg>Added text input<commit_after>var route=""
var bus_stop=""
var direction=""
var travel_time=420
$( "#submit" ).click(function() {
    route = $(".route").text()
    bus_stop= $(".route").text()
    direction=$(".direction").text()
    travel_time=$(".travel_time").text();
    if($("#map").length){
        $("#map").remove()
        }
    $( "body" ).append( "

" );
})
 function initMap() {

            var busLatLng = {lat: 39.95, lng: -75.1667};

            var map = new google.maps.Map(document.getElementById('map'), {
                  zoom: 100,
                  center: busLatLng
                });

            var bus_marker = new google.maps.Marker({
                  position: busLatLng,
                  map: map,
                  title: 'Your Location',
                  icon: 'img/bus_stop.png'
                    });

            var flightPlanCoordinates = [
                {lat: 39.772, lng: -75.214},
                {lat: 39.291, lng: -75.821},
                {lat: 39.142, lng: -75.431},
                {lat: 39.467, lng: -75.027}
              ];
            var flightPath = new google.maps.Polyline({
                path: flightPlanCoordinates,
                geodesic: true,
                strokeColor: '#FF0000',
                strokeOpacity: 1.0,
                strokeWeight: 2
              });

            flightPath.setMap(map);
        }<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var util = require('util');
var byline = require('byline');

var votesFilePath = path.join(__dirname, 'votes.txt');

exports.login = function (req, res) {

    if (req.body.username == null || req.body.username == '') {
        res.setHeader('WWW-Authenticate', 'realm="My realm"');
        res.render('login');
    } else {
        req.session.username = req.body.username;

        res.redirect('/vote');
    }
};

exports.vote = function (req, res) {

    saveVote(req);

    res.redirect('/results');
};

exports.voteSafe = function (req, res) {

    if (isCrsfTokenPresent(req) && isCrsfTokenValid(req)) {
        saveVote(req);
    }

    res.redirect('/results');
};

exports.results = function (req, res) {
    var stream = fs.createReadStream(votesFilePath);
    stream = byline.createStream(stream);

    var counts = {
        'SF': 0,
        'SEA': 0
    };
    var votes = [];

    stream.on('data', function (line) {
        var fields = line.toString().split('\t');

        var vote = {
            date: fields[0],
            username: fields[1],
            vote: fields[2]
        };
        votes.push(vote);

        counts[vote.vote]++;
    });

    stream.on('end', function () {
        var viewModel = {
            votes: votes,
            counts: counts
        };

        res.render('results', viewModel);
    });
};

var saveVote = function (req) {

    var now = new Date();
    var date = util.format('%d/%d/%d %d:%d:%d', now.getMonth() + 1,
        now.getDate(), now.getFullYear(), now.getHours(), now.getMinutes(),
        now.getSeconds());
    var text = util.format('%s\t%s\t%s\n', date, req.session.username,
        req.body.vote);

    fs.appendFile(votesFilePath, text);
};

var isCrsfTokenPresent = function (req) {

    return (req.body.csrfToken != null && req.body.csrfToken != null);
};

var isCrsfTokenValid = function (req) {

    return (req.body.csrfToken == req.cookies.csrfToken);
};<commit_msg>Testing VS 2013 git integration<commit_after>var fs = require('fs');
var path = require('path');
var util = require('util');
var byline = require('byline');
var something = 'Testing VS2013'

var votesFilePath = path.join(__dirname, 'votes.txt');

exports.login = function (req, res) {

    if (req.body.username == null || req.body.username == '') {
        res.setHeader('WWW-Authenticate', 'realm="My realm"');
        res.render('login');
    } else {
        req.session.username = req.body.username;

        res.redirect('/vote');
    }
};

exports.vote = function (req, res) {

    saveVote(req);

    res.redirect('/results');
};

exports.voteSafe = function (req, res) {

    if (isCrsfTokenPresent(req) && isCrsfTokenValid(req)) {
        saveVote(req);
    }

    res.redirect('/results');
};

exports.results = function (req, res) {
    var stream = fs.createReadStream(votesFilePath);
    stream = byline.createStream(stream);

    var counts = {
        'SF': 0,
        'SEA': 0
    };
    var votes = [];

    stream.on('data', function (line) {
        var fields = line.toString().split('\t');

        var vote = {
            date: fields[0],
            username: fields[1],
            vote: fields[2]
        };
        votes.push(vote);

        counts[vote.vote]++;
    });

    stream.on('end', function () {
        var viewModel = {
            votes: votes,
            counts: counts
        };

        res.render('results', viewModel);
    });
};

var saveVote = function (req) {

    var now = new Date();
    var date = util.format('%d/%d/%d %d:%d:%d', now.getMonth() + 1,
        now.getDate(), now.getFullYear(), now.getHours(), now.getMinutes(),
        now.getSeconds());
    var text = util.format('%s\t%s\t%s\n', date, req.session.username,
        req.body.vote);

    fs.appendFile(votesFilePath, text);
};

var isCrsfTokenPresent = function (req) {

    return (req.body.csrfToken != null && req.body.csrfToken != null);
};

var isCrsfTokenValid = function (req) {

    return (req.body.csrfToken == req.cookies.csrfToken);
};<|endoftext|>


<commit_before>var line =
	"<xml>" +
		"<block type='controls_if' x='25' y='25'>" +
			"<value name='IF0'>" +
		      "<block type='sumorobot_line'>" +
		        "<field name='LINE'>MIDDLE</field>" +
		      "</block>" +
		    "</value>" +
			"<statement name='DO0'>" +
				"<block type='sumorobot_move'>" +
					"<field name='MOVE'>STOP</field>" +
				"</block>" +
			"</statement>" +
		"</block>" +
	"</xml>";

var enemy =
	"<xml>" +
		"<block type='controls_if' x='25' y='25'>" +
			"<value name='IF0'>" +
		      "<block type='sumorobot_enemy'>" +
		        "<field name='ENEMY'>FRONT</field>" +
		      "</block>" +
		    "</value>" +
			"<statement name='DO0'>" +
				"<block type='sumorobot_move'>" +
					"<field name='MOVE'>FORWARD</field>" +
				"</block>" +
			"</statement>" +
		"</block>" +
	"</xml>";

/* When code has changed */
var onCodeChanged = function onCodeChanged() {
	$('#arduino-code').val(Blockly.Arduino.workspaceToCode());
};

/* Example code snippets */
var showExample = function showExample(exampleXML) {
	Blockly.mainWorkspace.clear();
	var xml = Blockly.Xml.textToDom(exampleXML);
	Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);
};

/* Send the code */
var sendCode = function sendCode() {
	socket.emit('send-sumorobot-code', Blockly.Arduino.workspaceToCode());
};

/* Get a users code */
var getCode = function getCode(userEmail) {
	socket.emit('get-code', 'sumorobot', userEmail);
};

/* Show the code */
var showCode = function showCode() {
	alert(Blockly.Arduino.workspaceToCode());
};

/* When DOM has been loaded */
window.onload = function() {
	// initialize blockly
	Blockly.inject(document.getElementById('blockly-div'), {
		trashcan: true,
		path: '/js/blockly/',
		toolbox: document.getElementById('toolbox')
	});
	Blockly.addChangeListener(onCodeChanged);
}<commit_msg>public/js/sumorobot.js added sockets<commit_after>var line =
	"<xml>" +
		"<block type='controls_if' x='25' y='25'>" +
			"<value name='IF0'>" +
		      "<block type='sumorobot_line'>" +
		        "<field name='LINE'>MIDDLE</field>" +
		      "</block>" +
		    "</value>" +
			"<statement name='DO0'>" +
				"<block type='sumorobot_move'>" +
					"<field name='MOVE'>STOP</field>" +
				"</block>" +
			"</statement>" +
		"</block>" +
	"</xml>";

var enemy =
	"<xml>" +
		"<block type='controls_if' x='25' y='25'>" +
			"<value name='IF0'>" +
		      "<block type='sumorobot_enemy'>" +
		        "<field name='ENEMY'>FRONT</field>" +
		      "</block>" +
		    "</value>" +
			"<statement name='DO0'>" +
				"<block type='sumorobot_move'>" +
					"<field name='MOVE'>FORWARD</field>" +
				"</block>" +
			"</statement>" +
		"</block>" +
	"</xml>";

var socket = null;

/* When code has changed */
var onCodeChanged = function onCodeChanged() {
	$('#arduino-code').val(Blockly.Arduino.workspaceToCode());
};

/* Example code snippets */
var showExample = function showExample(exampleXML) {
	Blockly.mainWorkspace.clear();
	var xml = Blockly.Xml.textToDom(exampleXML);
	Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);
};

/* Send the code */
var sendCode = function sendCode() {
	$('#upload').attr('disabled', 'disabled');
	$('#upload').html('UPLOADING...');
	socket.emit('send-sumorobot-code', Blockly.Arduino.workspaceToCode());
};

/* Get a users code */
var getCode = function getCode(user) {
	socket.emit('get-sumorobot-code', user);
};

/* Show the code */
var showCode = function showCode() {
	alert(Blockly.Arduino.workspaceToCode());
};

/* When DOM has been loaded */
window.onload = function() {
	/* Initialize blockly */
	Blockly.inject(document.getElementById('blockly-div'), {
		trashcan: true,
		path: '/js/blockly/',
		toolbox: document.getElementById('toolbox')
	});
	Blockly.addChangeListener(onCodeChanged);

	/* Initialize sockets */
	socket = io.connect();

	/* Receive messages */
	socket.on('sumorobot-message', function(message) {
		$('#upload').html('UPLOAD CODE');
		$('#upload').removeAttr('disabled');
		alert(message);
	});
}<|endoftext|>