<commit_before>/*
  Temasys extended adapter
  version: 0.8.624
*/

var RTCPeerConnection = null;
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
var webrtcDetectedBrowser = null;
var webrtcDetectedVersion = null;

function trace(text) {
  // This function is used for logging.
  if (text[text.length - 1] == '\n') {
    text = text.substring(0, text.length - 1);
  }
  console.log(/*(performance.now() / 1000).toFixed(3) + ": " + */ text); //performance not available on every browser
}

function maybeFixConfiguration(pcConfig) {
  if (pcConfig === null) {
    return;
  }
  for (var i = 0; i < pcConfig.iceServers.length; i++) {
    if (pcConfig.iceServers[i].hasOwnProperty('urls')){
      pcConfig.iceServers[i]['url'] = pcConfig.iceServers[i]['urls'];
      delete pcConfig.iceServers[i]['urls'];
    }
  }
}

var TemPageId = Math.random().toString(36).slice(2); // Unique identifier of each opened page

TemPrivateWebRTCReadyCb = function() {
  // webRTC readu Cb, should only be called once.
  // Need to prevent Chrome + plugin form calling WebRTCReadyCb twice
  arguments.callee.StaticWasInit = arguments.callee.StaticWasInit || 1;
  if (arguments.callee.StaticWasInit == 1)
    if (typeof WebRTCReadyCb === 'function')
      WebRTCReadyCb();
  arguments.callee.StaticWasInit++;

  // WebRTCReadyCb is callback function called when the browser is webrtc ready
  // this can be because of the browser or because of the plugin
  // Override WebRTCReadyCb and use it to do whatever you need to do when the
  // page is ready

};
function plugin0() {
  return document.getElementById('plugin0');
}
plugin = plugin0; // use this function whenever you want to call the plugin

// !!! DO NOT OVERRIDE THIS FUNCTION !!!
// This function will be called when plugin is ready
// it sends necessary details to the plugin.
// If you need to do something once the page/plugin is ready, override
// TemPrivateWebRTCReadyCb instead.
// This function is not in the IE/Safari condition brackets so that
// TemPluginLoaded function might be called on Chrome/Firefox
function TemInitPlugin0() {
  trace("plugin loaded");
  plugin().setPluginId(TemPageId, "plugin0");
  plugin().setLogFunction(console);
  TemPrivateWebRTCReadyCb();
}

if (navigator.mozGetUserMedia) {
  console.log("This appears to be Firefox");

  webrtcDetectedBrowser = "firefox";

  webrtcDetectedVersion =
  parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);

  // The RTCPeerConnection object.
  var RTCPeerConnection = function(pcConfig, pcConstraints) {
    // .urls is not supported in FF yet.
    maybeFixConfiguration(pcConfig);
    return new mozRTCPeerConnection(pcConfig, pcConstraints);
  }

  // The RTCSessionDescription object.
  RTCSessionDescription = mozRTCSessionDescription;

  // The RTCIceCandidate object.
  RTCIceCandidate = mozRTCIceCandidate;

  // Get UserMedia (only difference is the prefix).
  // Code from Adam Barth.
  getUserMedia = navigator.mozGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Creates iceServer from the url for FF.
  createIceServer = function(url, username, password) {
    var iceServer = null;
    var url_parts = url.split(':');
    if (url_parts[0].indexOf('stun') === 0) {
      // Create iceServer with stun url.
      iceServer = { 'url': url };
    } else if (url_parts[0].indexOf('turn') === 0) {
      if (webrtcDetectedVersion < 27) {
        // Create iceServer with turn url.
        // Ignore the transport parameter from TURN url for FF version <=27.
        var turn_url_parts = url.split("?");
        // Return null for createIceServer if transport=tcp.
        if (turn_url_parts.length === 1 ||
          turn_url_parts[1].indexOf('transport=udp') === 0) {
          iceServer = {'url': turn_url_parts[0],
        'credential': password,
        'username': username};
      }
    } else {
        // FF 27 and above supports transport parameters in TURN url,
        // So passing in the full url to create iceServer.
        iceServer = {'url': url,
        'credential': password,
        'username': username};
      }
    }
    return iceServer;
  };

  createIceServers = function(urls, username, password) {
    var iceServers = [];
    // Use .url for FireFox.
    for (i = 0; i < urls.length; i++) {
      var iceServer = createIceServer(urls[i],
        username,
        password);
      if (iceServer !== null) {
        iceServers.push(iceServer);
      }
    }
    return iceServers;
  }

  // Attach a media stream to an element.
  attachMediaStream = function(element, stream) {
    console.log("Attaching media stream");
    element.mozSrcObject = stream;
    element.play();

    return element;
  };

  reattachMediaStream = function(to, from) {
    console.log("Reattaching media stream");
    to.mozSrcObject = from.mozSrcObject;
    to.play();

    return to;
  };

  // Fake get{Video,Audio}Tracks
  if (!MediaStream.prototype.getVideoTracks) {
    MediaStream.prototype.getVideoTracks = function() {
      return [];
    };
  }

  if (!MediaStream.prototype.getAudioTracks) {
    MediaStream.prototype.getAudioTracks = function() {
      return [];
    };
  }

  TemPrivateWebRTCReadyCb();
} else if (navigator.webkitGetUserMedia) {
  console.log("This appears to be Chrome");

  webrtcDetectedBrowser = "chrome";
  webrtcDetectedVersion =
  parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);

  // Creates iceServer from the url for Chrome M33 and earlier.
  createIceServer = function(url, username, password) {
    var iceServer = null;
    var url_parts = url.split(':');
    if (url_parts[0].indexOf('stun') === 0) {
      // Create iceServer with stun url.
      iceServer = { 'url': url };
    } else if (url_parts[0].indexOf('turn') === 0) {
      // Chrome M28 & above uses below TURN format.
      iceServer = {'url': url,
      'credential': password,
      'username': username};
    }
    return iceServer;
  };

  // Creates iceServers from the urls for Chrome M34 and above.
  createIceServers = function(urls, username, password) {
    var iceServers = [];
    if (webrtcDetectedVersion >= 34) {
      // .urls is supported since Chrome M34.
      iceServers = {'urls': urls,
      'credential': password,
      'username': username };
    } else {
      for (i = 0; i < urls.length; i++) {
        var iceServer = createIceServer(urls[i],
          username,
          password);
        if (iceServer !== null) {
          iceServers.push(iceServer);
        }
      }
    }
    return iceServers;
  };

  // The RTCPeerConnection object.
  var RTCPeerConnection = function(pcConfig, pcConstraints) {
    // .urls is supported since Chrome M34.
    if (webrtcDetectedVersion < 34) {
      maybeFixConfiguration(pcConfig);
    }
    return new webkitRTCPeerConnection(pcConfig, pcConstraints);
  }

  // Get UserMedia (only difference is the prefix).
  // Code from Adam Barth.
  getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Attach a media stream to an element.
  attachMediaStream = function(element, stream) {
    if (typeof element.srcObject !== 'undefined') {
      element.srcObject = stream;
    } else if (typeof element.mozSrcObject !== 'undefined') {
      element.mozSrcObject = stream;
    } else if (typeof element.src !== 'undefined') {
      element.src = URL.createObjectURL(stream);
    } else {
      console.log('Error attaching stream to element.');
    }

    return element;
  };

  reattachMediaStream = function(to, from) {
    to.src = from.src;

    return to;
  };

  TemPrivateWebRTCReadyCb();
} else if (navigator.userAgent.indexOf("Safari")) { ////////////////////////////////////////////////////////////////////////
  // Note: IE is detected as Safari...
  console.log("This appears to be either Safari or IE");
  webrtcDetectedBrowser = "Safari";

  // Browser identification // TODO: move this up and use it for implementation choice
  var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
    // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
  var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
  var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
    // At least Safari 3+: "[object HTMLElementConstructor]"
  var isChrome = !!window.chrome && !isOpera;              // Chrome 1+
  var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6

  // This function detects whether or not a plugin is installed
  // Com name : the company name,
  // plugName : the plugin name
  // installedCb : callback if the plugin is detected (no argument)
  // notInstalledCb : callback if the plugin is not detected (no argument)
  function isPluginInstalled(comName, plugName, installedCb, notInstalledCb) {
    if (isChrome || isSafari || isFirefox) { // Not IE (firefox, for example)
      var pluginArray = navigator.plugins;
      for (var i = 0; i < pluginArray.length; i++) {
        if (pluginArray[i].name.indexOf(plugName) >= 0) {
          installedCb();
          return;
        }
      }
      notInstalledCb();
    } else if (isIE) { // We're running IE
      try {
        new ActiveXObject(comName+"."+plugName);
      } catch(e) {
        notInstalledCb();
        return;
      }
      installedCb();
    } else {
      // Unsupported
      return;
    }
  }

  // defines webrtc's JS interface according to the plugin's implementation
  function defineWebRTCInterface() {
    // ==== UTIL FUNCTIONS ===
    function isDefined(variable) {
      return variable != null && variable != undefined;
    }

    injectPlugin = function() {
      var frag = document.createDocumentFragment();
      var temp = document.createElement('div');
      temp.innerHTML = '<object id="plugin0" type="application/x-temwebrtcplugin" width="0" height="0">'
      + '<param name="pluginId" value="plugin0" /> '
      + '<param name="onload" value="TemInitPlugin0" />'
      + '</object>';
      while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
      }
      document.body.appendChild(frag);
    }
    injectPlugin();

    // END OF UTIL FUNCTIONS

    // === WEBRTC INTERFACE ===
    createIceServer = function(url, username, password) {
      var iceServer = null;
      var url_parts = url.split(':');
      if (url_parts[0].indexOf('stun') === 0) {
          // Create iceServer with stun url.
          iceServer = { 'url': url, 'hasCredentials': false};
        } else if (url_parts[0].indexOf('turn') === 0) {
          iceServer = { 'url': url,
          'hasCredentials': true,
          'credential': password,
          'username': username };
        }
        return iceServer;
      };

    createIceServers = function(urls, username, password) {
      var iceServers = new Array();
      for (var i = 0; i < urls.length; ++i) {
        iceServers.push(createIceServer(urls[i], username, password));
      }
      return iceServers;
    }

    // The RTCSessionDescription object.
    RTCSessionDescription = function(info) {
      return plugin().ConstructSessionDescription(info.type, info.sdp);
    }

    // PEER CONNECTION
    RTCPeerConnection = function(servers, constraints) {
      var iceServers = null;
      if (servers) {
        iceServers = servers.iceServers;
        for (var i = 0; i < iceServers.length; i++) {
          if (iceServers[i].urls && !iceServers[i].url)
            iceServers[i].url = iceServers[i].urls;
          iceServers[i].hasCredentials = isDefined(iceServers[i].username) && isDefined(iceServers[i].credential);
        }
      }
      var mandatory = (constraints && constraints.mandatory) ? constraints.mandatory : null;
      var optional = (constraints && constraints.optional) ? constraints.optional : null;
      return plugin().PeerConnection(TemPageId, iceServers, mandatory, optional);
    }

    MediaStreamTrack = {};
    MediaStreamTrack.getSources = function(callback) {
      plugin().GetSources(callback);
    };

    getUserMedia = function(constraints, successCallback, failureCallback) {
      if (!constraints.audio)
        constraints.audio = false;

      plugin().getUserMedia(constraints, successCallback, failureCallback);
    };
    navigator.getUserMedia = getUserMedia;

    // Attach a media stream to an element.
    attachMediaStream = function(element, stream) {
      stream.enableSoundTracks(true);
      if (element.nodeName.toLowerCase() != "audio") {
        var elementId = element.id.length == 0 ? Math.random().toString(36).slice(2) : element.id;
        if (!element.isTemWebRTCPlugin || !element.isTemWebRTCPlugin()) {
          var frag = document.createDocumentFragment();
          var temp = document.createElement('div');
          var classHTML = element.className ? 'class="' + element.className + '" ' :  "";
          temp.innerHTML = '<object id="' + elementId + '" '
          + classHTML
          + 'type="application/x-temwebrtcplugin">'
          + '<param name="pluginId" value="' + elementId + '" /> '
          + '<param name="pageId" value="' + TemPageId + '" /> '
          + '<param name="streamId" value="' + stream.id + '" /> '
          + '</object>';
          while (temp.firstChild) {
            frag.appendChild(temp.firstChild);
          }

          var rectObject = element.getBoundingClientRect();
          element.parentNode.insertBefore(frag, element);
          frag = document.getElementById(elementId);
          frag.width = rectObject.width + "px";
          frag.height = rectObject.height + "px";
          element.parentNode.removeChild(element);

        } else {
          var children = element.children;
          for (var i = 0; i != children.length; ++i) {
            if (children[i].name == "streamId") {
              children[i].value = stream.id;
              break;
            }
          }
          element.setStreamId(stream.id);
        }

        var newElement = document.getElementById(elementId)
        newElement.onclick = element.onclick ? element.onclick : function(arg) {};
        newElement._TemOnClick = function(id) {
          var arg = {srcElement: document.getElementById(id)};
          newElement.onclick(arg);
        }
        return newElement;
      } else { // is audio element
        // The sound was enabled, there is nothing to do here
        return element;
      }
    };

    reattachMediaStream = function(to, from) {
      var stream = null;
      var children = from.children;
      for (var i = 0; i != children.length; ++i) {
        if (children[i].name == "streamId") {
          stream = plugin().getStreamWithId(TemPageId, children[i].value);
          break;
        }
      }

      if (stream != null)
        return attachMediaStream(to, stream);
      else
        alert("Could not find the stream associated with this element");
    };

    RTCIceCandidate = function(candidate) {
      if (!candidate.sdpMid)
        candidate.sdpMid = "";
      return plugin().ConstructIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.candidate);
    };
    // END OF WEBRTC INTERFACE
  };

  function pluginNeededButNotInstalledCb() {
    // This function will be called if the plugin is needed
    // (browser different from Chrome or Firefox),
    // but the plugin is not installed
    // Override it according to your application logic.

    alert("Your browser is not webrtc ready and Temasys plugin is not installed");
  }

  // Try to detect the plugin and act accordingly
  isPluginInstalled("Tem", "TemWebRTCPlugin", defineWebRTCInterface, pluginNeededButNotInstalledCb);
} else {
  console.log("Browser does not appear to be WebRTC-capable");
}
<commit_msg>BUG: getSources now returns the list of sources<commit_after>/*
  Temasys extended adapter
  version: 0.8.624
*/

var RTCPeerConnection = null;
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
var webrtcDetectedBrowser = null;
var webrtcDetectedVersion = null;

function trace(text) {
  // This function is used for logging.
  if (text[text.length - 1] == '\n') {
    text = text.substring(0, text.length - 1);
  }
  console.log(/*(performance.now() / 1000).toFixed(3) + ": " + */ text); //performance not available on every browser
}

function maybeFixConfiguration(pcConfig) {
  if (pcConfig === null) {
    return;
  }
  for (var i = 0; i < pcConfig.iceServers.length; i++) {
    if (pcConfig.iceServers[i].hasOwnProperty('urls')){
      pcConfig.iceServers[i]['url'] = pcConfig.iceServers[i]['urls'];
      delete pcConfig.iceServers[i]['urls'];
    }
  }
}

var TemPageId = Math.random().toString(36).slice(2); // Unique identifier of each opened page

TemPrivateWebRTCReadyCb = function() {
  // webRTC readu Cb, should only be called once.
  // Need to prevent Chrome + plugin form calling WebRTCReadyCb twice
  arguments.callee.StaticWasInit = arguments.callee.StaticWasInit || 1;
  if (arguments.callee.StaticWasInit == 1)
    if (typeof WebRTCReadyCb === 'function')
      WebRTCReadyCb();
  arguments.callee.StaticWasInit++;

  // WebRTCReadyCb is callback function called when the browser is webrtc ready
  // this can be because of the browser or because of the plugin
  // Override WebRTCReadyCb and use it to do whatever you need to do when the
  // page is ready

};
function plugin0() {
  return document.getElementById('plugin0');
}
plugin = plugin0; // use this function whenever you want to call the plugin

// !!! DO NOT OVERRIDE THIS FUNCTION !!!
// This function will be called when plugin is ready
// it sends necessary details to the plugin.
// If you need to do something once the page/plugin is ready, override
// TemPrivateWebRTCReadyCb instead.
// This function is not in the IE/Safari condition brackets so that
// TemPluginLoaded function might be called on Chrome/Firefox
function TemInitPlugin0() {
  trace("plugin loaded");
  plugin().setPluginId(TemPageId, "plugin0");
  plugin().setLogFunction(console);
  TemPrivateWebRTCReadyCb();
}

if (navigator.mozGetUserMedia) {
  console.log("This appears to be Firefox");

  webrtcDetectedBrowser = "firefox";

  webrtcDetectedVersion =
  parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);

  // The RTCPeerConnection object.
  var RTCPeerConnection = function(pcConfig, pcConstraints) {
    // .urls is not supported in FF yet.
    maybeFixConfiguration(pcConfig);
    return new mozRTCPeerConnection(pcConfig, pcConstraints);
  }

  // The RTCSessionDescription object.
  RTCSessionDescription = mozRTCSessionDescription;

  // The RTCIceCandidate object.
  RTCIceCandidate = mozRTCIceCandidate;

  // Get UserMedia (only difference is the prefix).
  // Code from Adam Barth.
  getUserMedia = navigator.mozGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Creates iceServer from the url for FF.
  createIceServer = function(url, username, password) {
    var iceServer = null;
    var url_parts = url.split(':');
    if (url_parts[0].indexOf('stun') === 0) {
      // Create iceServer with stun url.
      iceServer = { 'url': url };
    } else if (url_parts[0].indexOf('turn') === 0) {
      if (webrtcDetectedVersion < 27) {
        // Create iceServer with turn url.
        // Ignore the transport parameter from TURN url for FF version <=27.
        var turn_url_parts = url.split("?");
        // Return null for createIceServer if transport=tcp.
        if (turn_url_parts.length === 1 ||
          turn_url_parts[1].indexOf('transport=udp') === 0) {
          iceServer = {'url': turn_url_parts[0],
        'credential': password,
        'username': username};
      }
    } else {
        // FF 27 and above supports transport parameters in TURN url,
        // So passing in the full url to create iceServer.
        iceServer = {'url': url,
        'credential': password,
        'username': username};
      }
    }
    return iceServer;
  };

  createIceServers = function(urls, username, password) {
    var iceServers = [];
    // Use .url for FireFox.
    for (i = 0; i < urls.length; i++) {
      var iceServer = createIceServer(urls[i],
        username,
        password);
      if (iceServer !== null) {
        iceServers.push(iceServer);
      }
    }
    return iceServers;
  }

  // Attach a media stream to an element.
  attachMediaStream = function(element, stream) {
    console.log("Attaching media stream");
    element.mozSrcObject = stream;
    element.play();

    return element;
  };

  reattachMediaStream = function(to, from) {
    console.log("Reattaching media stream");
    to.mozSrcObject = from.mozSrcObject;
    to.play();

    return to;
  };

  // Fake get{Video,Audio}Tracks
  if (!MediaStream.prototype.getVideoTracks) {
    MediaStream.prototype.getVideoTracks = function() {
      return [];
    };
  }

  if (!MediaStream.prototype.getAudioTracks) {
    MediaStream.prototype.getAudioTracks = function() {
      return [];
    };
  }

  TemPrivateWebRTCReadyCb();
} else if (navigator.webkitGetUserMedia) {
  console.log("This appears to be Chrome");

  webrtcDetectedBrowser = "chrome";
  webrtcDetectedVersion =
  parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);

  // Creates iceServer from the url for Chrome M33 and earlier.
  createIceServer = function(url, username, password) {
    var iceServer = null;
    var url_parts = url.split(':');
    if (url_parts[0].indexOf('stun') === 0) {
      // Create iceServer with stun url.
      iceServer = { 'url': url };
    } else if (url_parts[0].indexOf('turn') === 0) {
      // Chrome M28 & above uses below TURN format.
      iceServer = {'url': url,
      'credential': password,
      'username': username};
    }
    return iceServer;
  };

  // Creates iceServers from the urls for Chrome M34 and above.
  createIceServers = function(urls, username, password) {
    var iceServers = [];
    if (webrtcDetectedVersion >= 34) {
      // .urls is supported since Chrome M34.
      iceServers = {'urls': urls,
      'credential': password,
      'username': username };
    } else {
      for (i = 0; i < urls.length; i++) {
        var iceServer = createIceServer(urls[i],
          username,
          password);
        if (iceServer !== null) {
          iceServers.push(iceServer);
        }
      }
    }
    return iceServers;
  };

  // The RTCPeerConnection object.
  var RTCPeerConnection = function(pcConfig, pcConstraints) {
    // .urls is supported since Chrome M34.
    if (webrtcDetectedVersion < 34) {
      maybeFixConfiguration(pcConfig);
    }
    return new webkitRTCPeerConnection(pcConfig, pcConstraints);
  }

  // Get UserMedia (only difference is the prefix).
  // Code from Adam Barth.
  getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
  navigator.getUserMedia = getUserMedia;

  // Attach a media stream to an element.
  attachMediaStream = function(element, stream) {
    if (typeof element.srcObject !== 'undefined') {
      element.srcObject = stream;
    } else if (typeof element.mozSrcObject !== 'undefined') {
      element.mozSrcObject = stream;
    } else if (typeof element.src !== 'undefined') {
      element.src = URL.createObjectURL(stream);
    } else {
      console.log('Error attaching stream to element.');
    }

    return element;
  };

  reattachMediaStream = function(to, from) {
    to.src = from.src;

    return to;
  };

  TemPrivateWebRTCReadyCb();
} else if (navigator.userAgent.indexOf("Safari")) { ////////////////////////////////////////////////////////////////////////
  // Note: IE is detected as Safari...
  console.log("This appears to be either Safari or IE");
  webrtcDetectedBrowser = "Safari";

  // Browser identification // TODO: move this up and use it for implementation choice
  var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
    // Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
  var isFirefox = typeof InstallTrigger !== 'undefined';   // Firefox 1.0+
  var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
    // At least Safari 3+: "[object HTMLElementConstructor]"
  var isChrome = !!window.chrome && !isOpera;              // Chrome 1+
  var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6

  // This function detects whether or not a plugin is installed
  // Com name : the company name,
  // plugName : the plugin name
  // installedCb : callback if the plugin is detected (no argument)
  // notInstalledCb : callback if the plugin is not detected (no argument)
  function isPluginInstalled(comName, plugName, installedCb, notInstalledCb) {
    if (isChrome || isSafari || isFirefox) { // Not IE (firefox, for example)
      var pluginArray = navigator.plugins;
      for (var i = 0; i < pluginArray.length; i++) {
        if (pluginArray[i].name.indexOf(plugName) >= 0) {
          installedCb();
          return;
        }
      }
      notInstalledCb();
    } else if (isIE) { // We're running IE
      try {
        new ActiveXObject(comName+"."+plugName);
      } catch(e) {
        notInstalledCb();
        return;
      }
      installedCb();
    } else {
      // Unsupported
      return;
    }
  }

  // defines webrtc's JS interface according to the plugin's implementation
  function defineWebRTCInterface() {
    // ==== UTIL FUNCTIONS ===
    function isDefined(variable) {
      return variable != null && variable != undefined;
    }

    injectPlugin = function() {
      var frag = document.createDocumentFragment();
      var temp = document.createElement('div');
      temp.innerHTML = '<object id="plugin0" type="application/x-temwebrtcplugin" width="0" height="0">'
      + '<param name="pluginId" value="plugin0" /> '
      + '<param name="onload" value="TemInitPlugin0" />'
      + '</object>';
      while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
      }
      document.body.appendChild(frag);
    }
    injectPlugin();

    // END OF UTIL FUNCTIONS

    // === WEBRTC INTERFACE ===
    createIceServer = function(url, username, password) {
      var iceServer = null;
      var url_parts = url.split(':');
      if (url_parts[0].indexOf('stun') === 0) {
          // Create iceServer with stun url.
          iceServer = { 'url': url, 'hasCredentials': false};
        } else if (url_parts[0].indexOf('turn') === 0) {
          iceServer = { 'url': url,
          'hasCredentials': true,
          'credential': password,
          'username': username };
        }
        return iceServer;
      };

    createIceServers = function(urls, username, password) {
      var iceServers = new Array();
      for (var i = 0; i < urls.length; ++i) {
        iceServers.push(createIceServer(urls[i], username, password));
      }
      return iceServers;
    }

    // The RTCSessionDescription object.
    RTCSessionDescription = function(info) {
      return plugin().ConstructSessionDescription(info.type, info.sdp);
    }

    // PEER CONNECTION
    RTCPeerConnection = function(servers, constraints) {
      var iceServers = null;
      if (servers) {
        iceServers = servers.iceServers;
        for (var i = 0; i < iceServers.length; i++) {
          if (iceServers[i].urls && !iceServers[i].url)
            iceServers[i].url = iceServers[i].urls;
          iceServers[i].hasCredentials = isDefined(iceServers[i].username) && isDefined(iceServers[i].credential);
        }
      }
      var mandatory = (constraints && constraints.mandatory) ? constraints.mandatory : null;
      var optional = (constraints && constraints.optional) ? constraints.optional : null;
      return plugin().PeerConnection(TemPageId, iceServers, mandatory, optional);
    }

    MediaStreamTrack = {};
    MediaStreamTrack.getSources = function(callback) {
      return plugin().GetSources(callback);
    };

    getUserMedia = function(constraints, successCallback, failureCallback) {
      if (!constraints.audio)
        constraints.audio = false;

      plugin().getUserMedia(constraints, successCallback, failureCallback);
    };
    navigator.getUserMedia = getUserMedia;

    // Attach a media stream to an element.
    attachMediaStream = function(element, stream) {
      stream.enableSoundTracks(true);
      if (element.nodeName.toLowerCase() != "audio") {
        var elementId = element.id.length == 0 ? Math.random().toString(36).slice(2) : element.id;
        if (!element.isTemWebRTCPlugin || !element.isTemWebRTCPlugin()) {
          var frag = document.createDocumentFragment();
          var temp = document.createElement('div');
          var classHTML = element.className ? 'class="' + element.className + '" ' :  "";
          temp.innerHTML = '<object id="' + elementId + '" '
          + classHTML
          + 'type="application/x-temwebrtcplugin">'
          + '<param name="pluginId" value="' + elementId + '" /> '
          + '<param name="pageId" value="' + TemPageId + '" /> '
          + '<param name="streamId" value="' + stream.id + '" /> '
          + '</object>';
          while (temp.firstChild) {
            frag.appendChild(temp.firstChild);
          }

          var rectObject = element.getBoundingClientRect();
          element.parentNode.insertBefore(frag, element);
          frag = document.getElementById(elementId);
          frag.width = rectObject.width + "px";
          frag.height = rectObject.height + "px";
          element.parentNode.removeChild(element);

        } else {
          var children = element.children;
          for (var i = 0; i != children.length; ++i) {
            if (children[i].name == "streamId") {
              children[i].value = stream.id;
              break;
            }
          }
          element.setStreamId(stream.id);
        }

        var newElement = document.getElementById(elementId)
        newElement.onclick = element.onclick ? element.onclick : function(arg) {};
        newElement._TemOnClick = function(id) {
          var arg = {srcElement: document.getElementById(id)};
          newElement.onclick(arg);
        }
        return newElement;
      } else { // is audio element
        // The sound was enabled, there is nothing to do here
        return element;
      }
    };

    reattachMediaStream = function(to, from) {
      var stream = null;
      var children = from.children;
      for (var i = 0; i != children.length; ++i) {
        if (children[i].name == "streamId") {
          stream = plugin().getStreamWithId(TemPageId, children[i].value);
          break;
        }
      }

      if (stream != null)
        return attachMediaStream(to, stream);
      else
        alert("Could not find the stream associated with this element");
    };

    RTCIceCandidate = function(candidate) {
      if (!candidate.sdpMid)
        candidate.sdpMid = "";
      return plugin().ConstructIceCandidate(candidate.sdpMid, candidate.sdpMLineIndex, candidate.candidate);
    };
    // END OF WEBRTC INTERFACE
  };

  function pluginNeededButNotInstalledCb() {
    // This function will be called if the plugin is needed
    // (browser different from Chrome or Firefox),
    // but the plugin is not installed
    // Override it according to your application logic.

    alert("Your browser is not webrtc ready and Temasys plugin is not installed");
  }

  // Try to detect the plugin and act accordingly
  isPluginInstalled("Tem", "TemWebRTCPlugin", defineWebRTCInterface, pluginNeededButNotInstalledCb);
} else {
  console.log("Browser does not appear to be WebRTC-capable");
}
<|endoftext|>


<commit_before>ActiveRoutes.prototype.cleanPath = function cleanPath(path,params,only_path)
{
    if(!params.id)
    {
        path = path.replace(/\/?\:id/,'');
    }
    if(params.method == 'index')
    {
        path = path.replace(/\/?\:method/,'');
    }
    path = path.replace(/\/?index$/,'');
    if(path.charAt(0) != '/')
    {
        path = '/' + path;
    }
    path = only_path ? path : this.options.base + path;
    return path;
};

ActiveRoutes.performParamSubstitution = function performParamSubstitution(path,route,params)
{
    for(var p in params)
    {
        if(path.match(':' + p) && params[p])
        {
            if(route.params.requirements && route.params.requirements[p]){
                if(typeof(route.params.requirements[p]) == 'function' && !route.params.requirements[p](String(params[p])))
                {
                    continue;
                }
                else if(!route.params.requirements[p].exec(String(params[p])))
                {
                    continue;
                }
            }
            path = path.replace(':' + p,params[p].toString());
        }
        else if(p == 'path' && path.match(/\*/))
        {
            path = path.replace(/\*/,params[p]);
        }
    }
    return path;
};

/**
 * @alias ActiveRoutes.prototype.urlFor
 * @param {Object} [params]
 * @return {String}
 * @exception {ActiveRoutes.Errors.NamedRouteDoesNotExistError}
 * @example
 * var routes = new ActiveRoutes([['post','/blog/post/:id',{object:'blog',method: 'post'}]]);

 * routes.urlFor({object: 'blog',method: 'post', id: 5}) == '/blog/post/5';
 */
ActiveRoutes.prototype.urlFor = function urlFor(params)
{
    var only_path = false;
    if(params.only_path){
        only_path = true;
        delete params.only_path;
    }

    //get a named route with no params
    if(typeof(params) == 'string')
    {
        var found = false;
        for(var i = 0; i < this.routes.length; ++i)
        {
            if(this.routes[i].name && this.routes[i].name == params)
            {
                found = i;
                break;
            }
        }
        if(found === false)
        {
            return ActiveSupport.throwError(Errors.NamedRouteDoesNotExistError,params);
        }
        else
        {
            var final_params = {};
            var found_params = ActiveSupport.clone(this.routes[found].params);
            for(var name in found_params)
            {
                final_params[name] = found_params[name];
            }
            if(typeof(arguments[1]) == 'object')
            {
                for(var name in arguments[1])
                {
                    final_params[name] = arguments[1][name];
                }
            }
            return this.urlFor(final_params);
        }
    }

    if(!params.method)
    {
        params.method = 'index';
    }

    if(this.options.camelizeMethodName)
    {
        params.method = ActiveSupport.camelize(params.method,false);
    }

    if(this.options.camelizeObjectName)
    {
        params.object = ActiveSupport.camelize(params.object,true);
    }

    //first past for exact match
    for(var i = 0; i < this.routes.length; ++i)
    {
        var route = ActiveSupport.clone(this.routes[i]);
        route.params = ActiveSupport.clone(this.routes[i].params || {});
        var path = route.path;
        if((route.params.method || '').toLowerCase() == (params.method || '').toLowerCase() && (route.params.object || '').toLowerCase() == (params.object || '').toLowerCase())
        {
            path = ActiveRoutes.performParamSubstitution(path,route,params);
            var cleaned = this.cleanPath(path,params,only_path);
            if(!cleaned.match(':'))
            {
                return cleaned;
            }

        }
    }
    //match that requires param replacement
    for(var i = 0; i < this.routes.length; ++i)
    {
        var route = ActiveSupport.clone(this.routes[i]);
        route.params = ActiveSupport.clone(this.routes[i].params || {});
        var path = route.path;
        if(route.params.object == params.object)
        {
            path = ActiveRoutes.performParamSubstitution(path,route,params);
            var cleaned = this.cleanPath(path,params,only_path);
            if(!cleaned.match(':'))
            {
                return cleaned;
            }
        }
    }
    return false;
};

ActiveRoutes.prototype.generateMethodsForRoute = function generateMethodsForRoute(route)
{
    var current_route_set = this;
    if(route.name)
    {
        var params_for_method_name = route.name + '_params';
        var url_for_method_name = route.name + '_url';
        if(current_route_set.options.camelizeGeneratedMethods)
        {
            params_for_method_name = ActiveSupport.camelize(params_for_method_name.replace(/\_/g,'-'));
            url_for_method_name = ActiveSupport.camelize(url_for_method_name.replace(/\_/g,'-'));
        }

        current_route_set.scope[params_for_method_name] = function generated_params_for(params){
            var final_params = {};
            for(var name in route.params || {})
            {
                final_params[name] = route.params[name];
            }
            for(var name in params)
            {
                final_params[name] = params[name];
            }
            return final_params;
        };

        current_route_set.scope[url_for_method_name] = function generated_url_for(params){
            return current_route_set.urlFor(current_route_set.scope[params_for_method_name](params));
        };
    }
};<commit_msg>removed error handling from Routes generator<commit_after>ActiveRoutes.prototype.cleanPath = function cleanPath(path,params,only_path)
{
    if(!params.id)
    {
        path = path.replace(/\/?\:id/,'');
    }
    if(params.method == 'index')
    {
        path = path.replace(/\/?\:method/,'');
    }
    path = path.replace(/\/?index$/,'');
    if(path.charAt(0) != '/')
    {
        path = '/' + path;
    }
    path = only_path ? path : this.options.base + path;
    return path;
};

ActiveRoutes.performParamSubstitution = function performParamSubstitution(path,route,params)
{
    for(var p in params)
    {
        if(path.match(':' + p) && params[p])
        {
            if(route.params.requirements && route.params.requirements[p]){
                if(typeof(route.params.requirements[p]) == 'function' && !route.params.requirements[p](String(params[p])))
                {
                    continue;
                }
                else if(!route.params.requirements[p].exec(String(params[p])))
                {
                    continue;
                }
            }
            path = path.replace(':' + p,params[p].toString());
        }
        else if(p == 'path' && path.match(/\*/))
        {
            path = path.replace(/\*/,params[p]);
        }
    }
    return path;
};

/**
 * @alias ActiveRoutes.prototype.urlFor
 * @param {Object} [params]
 * @return {String}
 * @exception {ActiveRoutes.Errors.NamedRouteDoesNotExistError}
 * @example
 * var routes = new ActiveRoutes([['post','/blog/post/:id',{object:'blog',method: 'post'}]]);

 * routes.urlFor({object: 'blog',method: 'post', id: 5}) == '/blog/post/5';
 */
ActiveRoutes.prototype.urlFor = function urlFor(params)
{
    var only_path = false;
    if(params.only_path){
        only_path = true;
        delete params.only_path;
    }

    //get a named route with no params
    if(typeof(params) == 'string')
    {
        var found = false;
        for(var i = 0; i < this.routes.length; ++i)
        {
            if(this.routes[i].name && this.routes[i].name == params)
            {
                found = i;
                break;
            }
        }
        if(found === false)
        {
            throw Errors.NamedRouteDoesNotExistError.getErrorString(params);
        }
        else
        {
            var final_params = {};
            var found_params = ActiveSupport.clone(this.routes[found].params);
            for(var name in found_params)
            {
                final_params[name] = found_params[name];
            }
            if(typeof(arguments[1]) == 'object')
            {
                for(var name in arguments[1])
                {
                    final_params[name] = arguments[1][name];
                }
            }
            return this.urlFor(final_params);
        }
    }

    if(!params.method)
    {
        params.method = 'index';
    }

    if(this.options.camelizeMethodName)
    {
        params.method = ActiveSupport.camelize(params.method,false);
    }

    if(this.options.camelizeObjectName)
    {
        params.object = ActiveSupport.camelize(params.object,true);
    }

    //first past for exact match
    for(var i = 0; i < this.routes.length; ++i)
    {
        var route = ActiveSupport.clone(this.routes[i]);
        route.params = ActiveSupport.clone(this.routes[i].params || {});
        var path = route.path;
        if((route.params.method || '').toLowerCase() == (params.method || '').toLowerCase() && (route.params.object || '').toLowerCase() == (params.object || '').toLowerCase())
        {
            path = ActiveRoutes.performParamSubstitution(path,route,params);
            var cleaned = this.cleanPath(path,params,only_path);
            if(!cleaned.match(':'))
            {
                return cleaned;
            }

        }
    }
    //match that requires param replacement
    for(var i = 0; i < this.routes.length; ++i)
    {
        var route = ActiveSupport.clone(this.routes[i]);
        route.params = ActiveSupport.clone(this.routes[i].params || {});
        var path = route.path;
        if(route.params.object == params.object)
        {
            path = ActiveRoutes.performParamSubstitution(path,route,params);
            var cleaned = this.cleanPath(path,params,only_path);
            if(!cleaned.match(':'))
            {
                return cleaned;
            }
        }
    }
    return false;
};

ActiveRoutes.prototype.generateMethodsForRoute = function generateMethodsForRoute(route)
{
    var current_route_set = this;
    if(route.name)
    {
        var params_for_method_name = route.name + '_params';
        var url_for_method_name = route.name + '_url';
        if(current_route_set.options.camelizeGeneratedMethods)
        {
            params_for_method_name = ActiveSupport.camelize(params_for_method_name.replace(/\_/g,'-'));
            url_for_method_name = ActiveSupport.camelize(url_for_method_name.replace(/\_/g,'-'));
        }

        current_route_set.scope[params_for_method_name] = function generated_params_for(params){
            var final_params = {};
            for(var name in route.params || {})
            {
                final_params[name] = route.params[name];
            }
            for(var name in params)
            {
                final_params[name] = params[name];
            }
            return final_params;
        };

        current_route_set.scope[url_for_method_name] = function generated_url_for(params){
            return current_route_set.urlFor(current_route_set.scope[params_for_method_name](params));
        };
    }
};<|endoftext|>


<commit_before>(function() {

d3.hexbin = function() {
  var width = 1,
      height = 1,
      r,
      x = d3_hexbinX,
      y = d3_hexbinY,
      dx,
      dy;

  function hexbin(points) {
    var binsById = {};

    points.forEach(function(point, i) {
      var py = y.call(hexbin, point, i) / dy, pj = Math.round(py),
          px = x.call(hexbin, point, i) / dx - (pj & 1 ? .5 : 0), pi = Math.round(px),
          py1 = py - pj;

      if (Math.abs(py1) * 3 > 1) {
        var px1 = px - pi,
            pi2 = pi + (px < pi ? -1 : 1) / 2,
            pj2 = pj + (py < pj ? -1 : 1),
            px2 = px - pi2,
            py2 = py - pj2;
        if (px1 * px1 + py1 * py1 > px2 * px2 + py2 * py2) pi = pi2 + (pj & 1 ? 1 : -1) / 2, pj = pj2;
      }

      var id = pi + "-" + pj, bin = binsById[id];
      if (bin) bin.push(point); else {
        bin = binsById[id] = [point];
        bin.x = (pi + (pj & 1 ? 1 / 2 : 0)) * dx;
        bin.y = pj * dy;
      }
    });

    return d3.values(binsById);
  }

  hexbin.x = function(_) {
    if (!arguments.length) return x;
    x = _;
    return hexbin;
  };

  hexbin.y = function(_) {
    if (!arguments.length) return y;
    y = _;
    return hexbin;
  };

  hexbin.hexagon = function(radius) {
    var x0 = 0, y0 = 0;
    if (arguments.length < 1) radius = r;
    return "m" + d3_hexbinAngles.map(function(angle) {
      var x1 = Math.sin(angle) * radius,
          y1 = -Math.cos(angle) * radius,
          dx = x1 - x0,
          dy = y1 - y0;
      x0 = x1, y0 = y1;
      return [dx, dy];
    }).join("l") + "z";
  };

  hexbin.mesh = function() {
    var path = [], mesh = hexbin.hexagon().slice(0, 4).join("l");
    for (var y = 0, odd = false; y < height + r; y += dy, odd = !odd) {
      for (var x = odd ? dx / 2 : 0; x < width; x += dx) {
        path.push("M", x, ",", y, "m", mesh);
      }
    }
    return path.join("");
  };

  hexbin.size = function(_) {
    if (!arguments.length) return [width, height];
    width = +_[0], height = +_[1];
    return hexbin;
  };

  hexbin.radius = function(_) {
    if (!arguments.length) return r;
    r = +_;
    dx = r * 2 * Math.sin(Math.PI / 3);
    dy = r * 1.5;
    return hexbin;
  };

  return hexbin.radius(1);
};

var d3_hexbinAngles = d3.range(0, 2 * Math.PI, Math.PI / 3),
    d3_hexbinX = function(d) { return d[0]; },
    d3_hexbinY = function(d) { return d[1]; };

})();
<commit_msg>Fix a bug in hexbin.mesh.<commit_after>(function() {

d3.hexbin = function() {
  var width = 1,
      height = 1,
      r,
      x = d3_hexbinX,
      y = d3_hexbinY,
      dx,
      dy;

  function hexbin(points) {
    var binsById = {};

    points.forEach(function(point, i) {
      var py = y.call(hexbin, point, i) / dy, pj = Math.round(py),
          px = x.call(hexbin, point, i) / dx - (pj & 1 ? .5 : 0), pi = Math.round(px),
          py1 = py - pj;

      if (Math.abs(py1) * 3 > 1) {
        var px1 = px - pi,
            pi2 = pi + (px < pi ? -1 : 1) / 2,
            pj2 = pj + (py < pj ? -1 : 1),
            px2 = px - pi2,
            py2 = py - pj2;
        if (px1 * px1 + py1 * py1 > px2 * px2 + py2 * py2) pi = pi2 + (pj & 1 ? 1 : -1) / 2, pj = pj2;
      }

      var id = pi + "-" + pj, bin = binsById[id];
      if (bin) bin.push(point); else {
        bin = binsById[id] = [point];
        bin.x = (pi + (pj & 1 ? 1 / 2 : 0)) * dx;
        bin.y = pj * dy;
      }
    });

    return d3.values(binsById);
  }

  function hexagon() {
    var x0 = 0, y0 = 0;
    return d3_hexbinAngles.map(function(angle) {
      var x1 = Math.sin(angle) * radius,
          y1 = -Math.cos(angle) * radius,
          dx = x1 - x0,
          dy = y1 - y0;
      x0 = x1, y0 = y1;
      return [dx, dy];
    });
  }

  hexbin.x = function(_) {
    if (!arguments.length) return x;
    x = _;
    return hexbin;
  };

  hexbin.y = function(_) {
    if (!arguments.length) return y;
    y = _;
    return hexbin;
  };

  hexbin.hexagon = function(radius) {
    if (arguments.length < 1) radius = r;
    return "m" + hexagon().join("l") + "z";
  };

  hexbin.mesh = function() {
    var path = [], mesh = hexagon().slice(0, 4).join("l");
    for (var y = 0, odd = false; y < height + r; y += dy, odd = !odd) {
      for (var x = odd ? dx / 2 : 0; x < width; x += dx) {
        path.push("M", x, ",", y, "m", mesh);
      }
    }
    return path.join("");
  };

  hexbin.size = function(_) {
    if (!arguments.length) return [width, height];
    width = +_[0], height = +_[1];
    return hexbin;
  };

  hexbin.radius = function(_) {
    if (!arguments.length) return r;
    r = +_;
    dx = r * 2 * Math.sin(Math.PI / 3);
    dy = r * 1.5;
    return hexbin;
  };

  return hexbin.radius(1);
};

var d3_hexbinAngles = d3.range(0, 2 * Math.PI, Math.PI / 3),
    d3_hexbinX = function(d) { return d[0]; },
    d3_hexbinY = function(d) { return d[1]; };

})();
<|endoftext|>


<commit_before>L.Control.SlideMenu = L.Control.extend({
    options: {
        position: 'topleft',
        menuposition: 'topleft', // topleft,topright,bottomleft,bottomright
        width: '300px',
        height: '100%',
        direction: 'horizontal', // vertical or horizontal
        changeperc: '10',
        delay: '10'
    },

    initialize: function(innerHTML, options){
        L.Util.setOptions(this, options);
        this._innerHTML = innerHTML;
        this._isLeftPosition = this.options.menuposition == 'topleft' ||
            this.options.menuposition == 'bottomleft' ? true : false;
        this._isTopPosition = this.options.menuposition == 'topleft' ||
            this.options.menuposition == 'topright' ? true : false;
        this._isHorizontal = this.options.direction == 'horizontal' ? true : false;
    },

    onAdd: function(map){
        this._container = L.DomUtil.create('div', 'leaflet-control-slidemenu leaflet-bar leaflet-control');
        var link = L.DomUtil.create('a', 'leaflet-bar-part leaflet-bar-part-single', this._container);
        link.title = 'Menu';
        L.DomUtil.create('span', 'fa fa-bars', link);

        this._menu = L.DomUtil.create('div', 'leaflet-menu', map._container);

        this._menu.style.width = this.options.width;
        this._menu.style.height = this.options.height;

        if(this._isHorizontal){
            var frominit = -(parseInt(this.options.width, 10));
            if(this._isLeftPosition){
                this._menu.style.left = '-' + this.options.width;
            }
            else{
                this._menu.style.right = '-' + this.options.width;
            }

            if(this._isTopPosition){
                this._menu.style.top = '0px';
            }
            else{
                this._menu.style.bottom = '0px';
            }
        }
        else{
            var frominit = -(parseInt(this.options.height, 10));
            if(this._isLeftPosition){
                this._menu.style.left = '0px';
            }
            else{
                this._menu.style.right = '0px';
            }

            if(this._isTopPosition){
                this._menu.style.top = '-' + this.options.height;
            }
            else{
                this._menu.style.bottom = '-' + this.options.height;
            }
        }

        var closeButton = L.DomUtil.create('button', 'leaflet-menu-close-button fa', this._menu);

        if(this._isHorizontal){
            if(this._isLeftPosition){
                closeButton.style.float = 'right';
                L.DomUtil.addClass(closeButton, 'fa-chevron-left');
            }
            else{
                closeButton.style.float = 'left';
                L.DomUtil.addClass(closeButton, 'fa-chevron-right');
            }
        }
        else{
            if(this._isTopPosition){
                closeButton.style.float = 'right';
                L.DomUtil.addClass(closeButton, 'fa-chevron-up');
            }
            else{
                closeButton.style.float = 'right';
                L.DomUtil.addClass(closeButton, 'fa-chevron-down');
            }
        }

        this._contents = L.DomUtil.create('div', 'leaflet-menu-contents', this._menu);
        this._contents.innerHTML = this._innerHTML;
        this._contents.style.clear = 'both';

        if(this._isHorizontal){
            var ispx = this.options.width.slice(-1) == 'x' ? true : false;
            var unit = parseInt(this.options.width, 10) * parseInt(this.options.changeperc, 10) / 100;
        }
        else{
            var ispx = this.options.height.slice(-1) == 'x' ? true : false;
            var unit = parseInt(this.options.height, 10) * parseInt(this.options.changeperc, 10) / 100;
        }

        L.DomEvent.disableClickPropagation(this._menu);
        L.DomEvent
            .on(link, 'click', L.DomEvent.stopPropagation)
            .on(link, 'click', function(){
                // Open
                this._animate(this._menu, frominit, 0, true, ispx, unit);
            }, this)
            .on(closeButton, 'click', L.DomEvent.stopPropagation)
            .on(closeButton, 'click', function(){
                // Close
                this._animate(this._menu, 0, frominit, false, ispx, unit);
            }, this);
        L.DomEvent.on(this._menu, 'mouseover', function(){
            map.scrollWheelZoom.disable();
        });
        L.DomEvent.on(this._menu, 'mouseout', function(){
            map.scrollWheelZoom.enable();
        });

        return this._container;
    },

    onRemove: function(map){
        //Remove sliding menu from DOM
        map._container.removeChild(this._menu);
        delete this._menu;
    },

    setContents: function(innerHTML){
        this._innerHTML = innerHTML;
        this._contents.innerHTML = this._innerHTML;
    },

    _animate: function(menu, from, to, isOpen, ispx, unit){
        if(this._isHorizontal){
            if(this._isLeftPosition){
                menu.style.left = from + (ispx ? 'px' : '%');
            }
            else{
                menu.style.right = from + (ispx ? 'px' : '%');
            }
        }
        else{
            if(this._isTopPosition){
                menu.style.top = from + (ispx ? 'px' : '%');
            }
            else{
                menu.style.bottom = from + (ispx ? 'px' : '%');
            }
        }

        if(from != to){
            setTimeout(function(slideMenu){
                var value = isOpen ? from + unit : from - unit;
                slideMenu._animate(slideMenu._menu, value, to, isOpen, ispx, unit);
            }, parseInt(this.options.delay), this);
        }
        else{
            return;
        }
    }
});

L.control.slideMenu = function(innerHTML, options) {
    return new L.Control.SlideMenu(innerHTML, options);
};<commit_msg>Se permite configurar el icono del boton que abre el menu.<commit_after>L.Control.SlideMenu = L.Control.extend({
    options: {
        position: 'topleft',
        menuposition: 'topleft', // topleft,topright,bottomleft,bottomright
        width: '300px',
        height: '100%',
        direction: 'horizontal', // vertical or horizontal
        changeperc: '10',
        delay: '10',
        icon: 'fa-bars'
    },

    initialize: function(innerHTML, options){
        L.Util.setOptions(this, options);
        this._innerHTML = innerHTML;
        this._isLeftPosition = this.options.menuposition == 'topleft' ||
            this.options.menuposition == 'bottomleft' ? true : false;
        this._isTopPosition = this.options.menuposition == 'topleft' ||
            this.options.menuposition == 'topright' ? true : false;
        this._isHorizontal = this.options.direction == 'horizontal' ? true : false;
    },

    onAdd: function(map){
        this._container = L.DomUtil.create('div', 'leaflet-control-slidemenu leaflet-bar leaflet-control');
        var link = L.DomUtil.create('a', 'leaflet-bar-part leaflet-bar-part-single', this._container);
        link.title = 'Menu';
        L.DomUtil.create('span', 'fa ' + this.options.icon, link);

        this._menu = L.DomUtil.create('div', 'leaflet-menu', map._container);

        this._menu.style.width = this.options.width;
        this._menu.style.height = this.options.height;

        if(this._isHorizontal){
            var frominit = -(parseInt(this.options.width, 10));
            if(this._isLeftPosition){
                this._menu.style.left = '-' + this.options.width;
            }
            else{
                this._menu.style.right = '-' + this.options.width;
            }

            if(this._isTopPosition){
                this._menu.style.top = '0px';
            }
            else{
                this._menu.style.bottom = '0px';
            }
        }
        else{
            var frominit = -(parseInt(this.options.height, 10));
            if(this._isLeftPosition){
                this._menu.style.left = '0px';
            }
            else{
                this._menu.style.right = '0px';
            }

            if(this._isTopPosition){
                this._menu.style.top = '-' + this.options.height;
            }
            else{
                this._menu.style.bottom = '-' + this.options.height;
            }
        }

        var closeButton = L.DomUtil.create('button', 'leaflet-menu-close-button fa', this._menu);

        if(this._isHorizontal){
            if(this._isLeftPosition){
                closeButton.style.float = 'right';
                L.DomUtil.addClass(closeButton, 'fa-chevron-left');
            }
            else{
                closeButton.style.float = 'left';
                L.DomUtil.addClass(closeButton, 'fa-chevron-right');
            }
        }
        else{
            if(this._isTopPosition){
                closeButton.style.float = 'right';
                L.DomUtil.addClass(closeButton, 'fa-chevron-up');
            }
            else{
                closeButton.style.float = 'right';
                L.DomUtil.addClass(closeButton, 'fa-chevron-down');
            }
        }

        this._contents = L.DomUtil.create('div', 'leaflet-menu-contents', this._menu);
        this._contents.innerHTML = this._innerHTML;
        this._contents.style.clear = 'both';

        if(this._isHorizontal){
            var ispx = this.options.width.slice(-1) == 'x' ? true : false;
            var unit = parseInt(this.options.width, 10) * parseInt(this.options.changeperc, 10) / 100;
        }
        else{
            var ispx = this.options.height.slice(-1) == 'x' ? true : false;
            var unit = parseInt(this.options.height, 10) * parseInt(this.options.changeperc, 10) / 100;
        }

        L.DomEvent.disableClickPropagation(this._menu);
        L.DomEvent
            .on(link, 'click', L.DomEvent.stopPropagation)
            .on(link, 'click', function(){
                // Open
                this._animate(this._menu, frominit, 0, true, ispx, unit);
            }, this)
            .on(closeButton, 'click', L.DomEvent.stopPropagation)
            .on(closeButton, 'click', function(){
                // Close
                this._animate(this._menu, 0, frominit, false, ispx, unit);
            }, this);
        L.DomEvent.on(this._menu, 'mouseover', function(){
            map.scrollWheelZoom.disable();
        });
        L.DomEvent.on(this._menu, 'mouseout', function(){
            map.scrollWheelZoom.enable();
        });

        return this._container;
    },

    onRemove: function(map){
        //Remove sliding menu from DOM
        map._container.removeChild(this._menu);
        delete this._menu;
    },

    setContents: function(innerHTML){
        this._innerHTML = innerHTML;
        this._contents.innerHTML = this._innerHTML;
    },

    _animate: function(menu, from, to, isOpen, ispx, unit){
        if(this._isHorizontal){
            if(this._isLeftPosition){
                menu.style.left = from + (ispx ? 'px' : '%');
            }
            else{
                menu.style.right = from + (ispx ? 'px' : '%');
            }
        }
        else{
            if(this._isTopPosition){
                menu.style.top = from + (ispx ? 'px' : '%');
            }
            else{
                menu.style.bottom = from + (ispx ? 'px' : '%');
            }
        }

        if(from != to){
            setTimeout(function(slideMenu){
                var value = isOpen ? from + unit : from - unit;
                slideMenu._animate(slideMenu._menu, value, to, isOpen, ispx, unit);
            }, parseInt(this.options.delay), this);
        }
        else{
            return;
        }
    }
});

L.control.slideMenu = function(innerHTML, options) {
    return new L.Control.SlideMenu(innerHTML, options);
};<|endoftext|>


<commit_before>var gulp = require('gulp'),
    fs = require("fs"),
    file = require('gulp-file'),
    runSequence = require('run-sequence');

var componentFileArr=[];

gulp.task('readFile',function(callback) {
    walk("src/component", function (path) {
        var ext = getFileExt(path);
        console.log(ext)
        if (ext === ".html" || ext === ".css") {
            componentFileArr.push(path);
        }
    }, function () {
        callback();
    })
})

gulp.task('doSomething', function () {
    var fileContent = fs.readFileSync("src/component/todo/index.html", "utf8");
    console.log(componentFileArr)
    return file("a.js", fileContentToStr(fileContent) , { src: true })
        .pipe(gulp.dest('dist/component'));
    //return gulp.src(dirs.src + '/templates/*.html')
    //  .pipe(myFunction(fileContent))
    //  .pipe(gulp.dest('destination/path'));
});

//http://www.tuicool.com/articles/rQvUbu2
gulp.task('default',  function (taskDone) {
    runSequence(
        'readFile',
        'doSomething',
        taskDone
    );
});

function getFileExt(filename) {
    var index1 = filename.lastIndexOf(".")
    var index2 = filename.length;
    return filename.substring(index1, index2).toLowerCase();
}

function  fileContentToStr(r) {
    var strVar = "tpl";
    var g = "";
    var arr = r.replace(/\r/g,"").split("\n");
    g += "var " + strVar + "=\n";
    var i = 0;
    for (; i < arr.length; i++) {
        var l = '';
        if (i === 0) {
            l += "'"
        }
        ;

        if (i === arr.length - 1) {
            l += arr[i] + "';\n";
        } else {
            l += arr[i] + "\\\n";
        }
        g += l;
    }
    return g;
}

function walk (path, handleFile, callback) {
    var len = 1,       // 文件|目录数，起始一个
        floor = 0;     // 第x个目录？

    function done () {
        // 完成任务, 运行回调函数
        if (--len === 0) {
            callback();
        }
    }

    function composeErr (err) {
        // 错误处理
        console.log('stat error');
        done();  // 以错误内容完成
    }

    function composeDir (path) {
        // 目录处理
        floor++;
        fs.readdir(path, function (err, files) {
            if (err) {
                console.log('read dir error');
                done();  // 目录完成
                return;
            }
            len += files.length;  // 子文件|子目录计数
            files.forEach(function (filename) {
                compose(path + '/' + filename);  // 子内容新的操作
            });
            done();  // 目录完成
        });
    }

    function composeFile (path) {
        // 文件处理
        handleFile(path, floor);
        done();  // 文件完成
    }

    function compose (path) {
        //同步
        fs.stat(path, function (err, stats) {
            if (err) {
                composeErr(err);
                return;
            }

            if (stats.isDirectory()) {
                composeDir(path);
                return;
            }

            composeFile(path);
        });
    }

    compose(path);
}
<commit_msg>scaffold<commit_after>var gulp = require('gulp'),
    fs = require("fs"),
    file = require('gulp-file'),
    runSequence = require('run-sequence');

var componentFileArr=[];

gulp.task('readFile',function(callback) {
    walk("src/component", function (path) {
        var ext = getFileExt(path);
        if (ext === ".html" || ext === ".css") {
            componentFileArr.push(path);
        }
    }, function () {
        var map=arrToObj(componentFileArr);
        console.log(map)
        for(var key in map){
            var paths=map[key];
            var i= 0,len=paths.length;
            var contentArr=[];
            for(;i<len;i++){
                var path=paths[i];

                contentArr.push(fileContentToStr(fs.readFileSync(path, "utf8")));

            }

            file(key+".js", contentArr.join("") , { src: true })
                .pipe(gulp.dest('dist/component'))

        }
        callback();
    })
})

gulp.task('doSomething', function () {
    var fileContent = fs.readFileSync("src/component/todo/index.html", "utf8");
    console.log(componentFileArr)
    return file("ab.js", fileContentToStr(fileContent) , { src: true })
        .pipe(gulp.dest('dist'));
    //return gulp.src(dirs.src + '/templates/*.html')
    //  .pipe(myFunction(fileContent))
    //  .pipe(gulp.dest('destination/path'));
});

//http://www.tuicool.com/articles/rQvUbu2
gulp.task('default',  function (taskDone) {
    runSequence(
        'readFile',
        'doSomething',
        taskDone
    );
});

function arrToObj(arr){
    var obj={};
    console.log(arr.length)
    for(var i= 0,len=arr.length;i<len;i++){
        var item=arr[i];
        var key=item.split("/")[2];
       console.log(obj[key])
        if(!obj[key]){
            obj[key]=[];
        }

        obj[key].push(item);

    }
    return obj;
}

function getFileExt(filename) {
    var index1 = filename.lastIndexOf(".")
    var index2 = filename.length;
    return filename.substring(index1, index2).toLowerCase();
}

function  fileContentToStr(r) {
    var strVar = "tpl";
    var g = "";
    var arr = r.replace(/\r/g,"").split("\n");
    g += "var " + strVar + "=\n";
    var i = 0;
    for (; i < arr.length; i++) {
        var l = '';
        if (i === 0) {
            l += "'"
        }
        ;

        if (i === arr.length - 1) {
            l += arr[i] + "';\n";
        } else {
            l += arr[i] + "\\\n";
        }
        g += l;
    }
    return g;
}

function walk (path, handleFile, callback) {
    var len = 1,       // 文件|目录数，起始一个
        floor = 0;     // 第x个目录？

    function done () {
        // 完成任务, 运行回调函数
        if (--len === 0) {
            callback();
        }
    }

    function composeErr (err) {
        // 错误处理
        console.log('stat error');
        done();  // 以错误内容完成
    }

    function composeDir (path) {
        // 目录处理
        floor++;
        fs.readdir(path, function (err, files) {
            if (err) {
                console.log('read dir error');
                done();  // 目录完成
                return;
            }
            len += files.length;  // 子文件|子目录计数
            files.forEach(function (filename) {
                compose(path + '/' + filename);  // 子内容新的操作
            });
            done();  // 目录完成
        });
    }

    function composeFile (path) {
        // 文件处理
        handleFile(path, floor);
        done();  // 文件完成
    }

    function compose (path) {
        //同步
        fs.stat(path, function (err, stats) {
            if (err) {
                composeErr(err);
                return;
            }

            if (stats.isDirectory()) {
                composeDir(path);
                return;
            }

            composeFile(path);
        });
    }

    compose(path);
}
<|endoftext|>


<commit_before>/**
 * @file LazyImage component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component, createRef} from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash/debounce';
import classNames from 'classnames';
import eventOn from 'dom-helpers/events/on';
import eventOff from 'dom-helpers/events/off';

import CircularLoading from '../CircularLoading';

import LazyLoadStatus from '../_statics/LazyLoadStatus';
import Event from '../_vendors/Event';

class LazyImage extends Component {

    static Status = LazyLoadStatus;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.wrapper = createRef();

        this.state = {
            status: LazyLoadStatus.PENDING
        };

    }

    handleScroll = debounce(() => {

        if (this.state.status > LazyLoadStatus.PENDING || !this.wrapperEl
            || this.wrapperEl.getBoundingClientRect().top > window.innerHeight) {
            return;
        }

        const {onImageLoadStart} = this.props;
        let result;

        if (onImageLoadStart) {
            result = onImageLoadStart();
        }

        if (result === false) {
            return;
        }

        this.setState({
            status: LazyLoadStatus.LOADING
        }, () => {

            const image = new Image();

            Event.addEvent(image, 'load', e => {
                this.setState({
                    status: LazyLoadStatus.FINISH
                }, () => {
                    const {onImageLoaded} = this.props;
                    onImageLoaded && onImageLoaded(e);
                });
            });

            image.src = this.props.src;

        });

    }, 250);

    componentDidMount() {
        this.wrapperEl = this.wrapper && this.wrapper.current;
        eventOn(this.props.scrollEl, 'scroll', this.handleScroll);
        this.handleScroll();
    }

    componentWillUnmount() {
        eventOff(this.props.scrollEl, 'scroll', this.handleScroll);
    }

    render() {

        const {className, style, src, alt, loadingWidth, loadingHeight, width, height, placeholder} = this.props,
            {status} = this.state,

            isFinish = status === LazyLoadStatus.FINISH;

        return (

                    {
                        placeholder ?
                            placeholder
                            :
                            <CircularLoading className="lazy-image-loading"/>
                    }

        );

    }
}

LazyImage.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Image src url.
     */
    src: PropTypes.string.isRequired,

    /**
     * Image alt text.
     */
    alt: PropTypes.string,

    /**
     * Loading width.
     */
    loadingWidth: PropTypes.number,

    /**
     * Loading height.
     */
    loadingHeight: PropTypes.number,

    /**
     * Image width.
     */
    width: PropTypes.number,

    /**
     * Image height.
     */
    height: PropTypes.number,

    /**
     * Image placeholder.
     */
    placeholder: PropTypes.any,

    scrollEl: PropTypes.object,

    /**
     * Image load start callback.
     */
    onImageLoadStart: PropTypes.func,

    /**
     * Image load end callback.
     */
    onImageLoaded: PropTypes.func

};

LazyImage.defaultProps = {

    alt: '',

    placeholder: '',
    scrollEl: document,

    loadingWidth: 100,
    loadingHeight: 100

};

export default LazyImage;
<commit_msg>update LazyImage<commit_after>/**
 * @file LazyImage component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component, createRef} from 'react';
import PropTypes from 'prop-types';
import debounce from 'lodash/debounce';
import classNames from 'classnames';
import eventOn from 'dom-helpers/events/on';
import eventOff from 'dom-helpers/events/off';

import CircularLoading from '../CircularLoading';

import LazyLoadStatus from '../_statics/LazyLoadStatus';
import Event from '../_vendors/Event';

class LazyImage extends Component {

    static Status = LazyLoadStatus;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.wrapper = createRef();

        this.state = {
            status: LazyLoadStatus.PENDING
        };

    }

    handleScroll = debounce(() => {

        if (this.state.status > LazyLoadStatus.PENDING || !this.wrapperEl
            || this.wrapperEl.getBoundingClientRect().top > window.innerHeight) {
            return;
        }

        const {onImageLoadStart} = this.props;
        let result;

        if (onImageLoadStart) {
            result = onImageLoadStart();
        }

        if (result === false) {
            return;
        }

        this.setState({
            status: LazyLoadStatus.LOADING
        }, () => {

            const image = new Image();

            Event.addEvent(image, 'load', e => {
                this.setState({
                    status: LazyLoadStatus.FINISH
                }, () => {
                    const {onImageLoaded} = this.props;
                    onImageLoaded && onImageLoaded(e);
                });
            });

            image.src = this.props.src;

        });

    }, 250);

    componentDidMount() {

        this.wrapperEl = this.wrapper && this.wrapper.current;

        eventOn(this.props.scrollEl, 'scroll', this.handleScroll);

        this.handleScroll();

    }

    componentWillUnmount() {

        eventOff(this.props.scrollEl, 'scroll', this.handleScroll);

        if (this.handleScroll) {
            this.handleScroll.cancel();
        }

    }

    render() {

        const {className, style, src, alt, loadingWidth, loadingHeight, width, height, placeholder} = this.props,
            {status} = this.state,

            isFinish = status === LazyLoadStatus.FINISH;

        return (

                    {
                        placeholder ?
                            placeholder
                            :
                            <CircularLoading className="lazy-image-loading"/>
                    }

        );

    }
}

LazyImage.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Image src url.
     */
    src: PropTypes.string.isRequired,

    /**
     * Image alt text.
     */
    alt: PropTypes.string,

    /**
     * Loading width.
     */
    loadingWidth: PropTypes.number,

    /**
     * Loading height.
     */
    loadingHeight: PropTypes.number,

    /**
     * Image width.
     */
    width: PropTypes.number,

    /**
     * Image height.
     */
    height: PropTypes.number,

    /**
     * Image placeholder.
     */
    placeholder: PropTypes.any,

    scrollEl: PropTypes.object,

    /**
     * Image load start callback.
     */
    onImageLoadStart: PropTypes.func,

    /**
     * Image load end callback.
     */
    onImageLoaded: PropTypes.func

};

LazyImage.defaultProps = {

    alt: '',

    placeholder: '',
    scrollEl: document,

    loadingWidth: 100,
    loadingHeight: 100

};

export default LazyImage;
<|endoftext|>


<commit_before>var _ = require('lodash');

var MemberOfRestriction = module.exports = function(dsl, source_path) {
    this.dsl = dsl;
    this.source_path = source_path;
};

MemberOfRestriction.prototype.check_key = function(path, key, data_wrapper) {
    if (data_wrapper.get_keys(this.source_path).indexOf(key) < 0) {
        this.dsl.error(path, "Reference to unexisting key " + key + " at path " + this.source_path);
    }
};
<commit_msg>Remove lodash from MemberOfRestrictions source<commit_after>var MemberOfRestriction = module.exports = function(dsl, source_path) {
    this.dsl = dsl;
    this.source_path = source_path;
};

MemberOfRestriction.prototype.check_key = function(path, key, data_wrapper) {
    if (data_wrapper.get_keys(this.source_path).indexOf(key) < 0) {
        this.dsl.error(path, "Reference to unexisting key " + key + " at path " + this.source_path);
    }
};
<|endoftext|>


<commit_before>import React, {Component, Children, PropTypes} from 'react';
import {fade} from '../utils/colorManipulator';

export const makeSelectable = (MyComponent) => {
  return class extends Component {
    static propTypes = {
      children: PropTypes.node,
      onChange: PropTypes.func,
      selectedItemStyle: PropTypes.object,
      value: PropTypes.any,
    };

    static contextTypes = {
      muiTheme: PropTypes.object.isRequired,
    };

    extendChild(child, styles, selectedItemStyle) {
      if (child && child.type && child.type.muiName === 'ListItem') {
        const selected = this.isChildSelected(child, this.props);
        let selectedChildrenStyles;
        if (selected) {
          selectedChildrenStyles = Object.assign({}, styles, selectedItemStyle);
        }

        const mergedChildrenStyles = Object.assign({}, child.props.style, selectedChildrenStyles);

        this.keyIndex += 1;

        return React.cloneElement(child, {
          onTouchTap: (event) => {
            this.handleItemTouchTap(event, child);
            if (child.props.onTouchTap) {
              child.props.onTouchTap(event);
            }
          },
          key: this.keyIndex,
          style: mergedChildrenStyles,
          nestedItems: child.props.nestedItems.map((child) => this.extendChild(child, styles, selectedItemStyle)),
          initiallyOpen: this.isInitiallyOpen(child),
        });
      } else {
        return child;
      }
    }

    isInitiallyOpen(child) {
      if (child.props.initiallyOpen) {
        return child.props.initiallyOpen;
      }
      return this.hasSelectedDescendant(false, child);
    }

    hasSelectedDescendant = (previousValue, child) => {
      if (React.isValidElement(child) && child.props.nestedItems && child.props.nestedItems.length > 0) {
        return child.props.nestedItems.reduce(this.hasSelectedDescendant, previousValue);
      }
      return previousValue || this.isChildSelected(child, this.props);
    };

    isChildSelected(child, props) {
      return props.value === child.props.value;
    }

    handleItemTouchTap = (event, item) => {
      const itemValue = item.props.value;

      if (itemValue !== this.props.value) {
        this.props.onChange(event, itemValue);
      }
    };

    render() {
      const {
        children,
        selectedItemStyle,
        ...other
      } = this.props;

      this.keyIndex = 0;
      const styles = {};

      if (!selectedItemStyle) {
        const textColor = this.context.muiTheme.baseTheme.palette.textColor;
        styles.backgroundColor = fade(textColor, 0.2);
      }

      return (
        <MyComponent {...other} {...this.state}>
          {Children.map(children, (child) => (
            this.extendChild(child, styles, selectedItemStyle))
          )}
        </MyComponent>
      );
    }
  };
};

export default makeSelectable;
<commit_msg>[makeSelectable] Fix missing check for existence of `onChange`  (#5589)<commit_after>import React, {Component, Children, PropTypes} from 'react';
import {fade} from '../utils/colorManipulator';

export const makeSelectable = (MyComponent) => {
  return class extends Component {
    static propTypes = {
      children: PropTypes.node,
      onChange: PropTypes.func,
      selectedItemStyle: PropTypes.object,
      value: PropTypes.any,
    };

    static contextTypes = {
      muiTheme: PropTypes.object.isRequired,
    };

    extendChild(child, styles, selectedItemStyle) {
      if (child && child.type && child.type.muiName === 'ListItem') {
        const selected = this.isChildSelected(child, this.props);
        let selectedChildrenStyles;
        if (selected) {
          selectedChildrenStyles = Object.assign({}, styles, selectedItemStyle);
        }

        const mergedChildrenStyles = Object.assign({}, child.props.style, selectedChildrenStyles);

        this.keyIndex += 1;

        return React.cloneElement(child, {
          onTouchTap: (event) => {
            this.handleItemTouchTap(event, child);
            if (child.props.onTouchTap) {
              child.props.onTouchTap(event);
            }
          },
          key: this.keyIndex,
          style: mergedChildrenStyles,
          nestedItems: child.props.nestedItems.map((child) => this.extendChild(child, styles, selectedItemStyle)),
          initiallyOpen: this.isInitiallyOpen(child),
        });
      } else {
        return child;
      }
    }

    isInitiallyOpen(child) {
      if (child.props.initiallyOpen) {
        return child.props.initiallyOpen;
      }
      return this.hasSelectedDescendant(false, child);
    }

    hasSelectedDescendant = (previousValue, child) => {
      if (React.isValidElement(child) && child.props.nestedItems && child.props.nestedItems.length > 0) {
        return child.props.nestedItems.reduce(this.hasSelectedDescendant, previousValue);
      }
      return previousValue || this.isChildSelected(child, this.props);
    };

    isChildSelected(child, props) {
      return props.value === child.props.value;
    }

    handleItemTouchTap = (event, item) => {
      const itemValue = item.props.value;

      if (itemValue !== this.props.value) {
        if (this.props.onChange) {
          this.props.onChange(event, itemValue);
        }
      }
    };

    render() {
      const {
        children,
        selectedItemStyle,
        ...other
      } = this.props;

      this.keyIndex = 0;
      const styles = {};

      if (!selectedItemStyle) {
        const textColor = this.context.muiTheme.baseTheme.palette.textColor;
        styles.backgroundColor = fade(textColor, 0.2);
      }

      return (
        <MyComponent {...other} {...this.state}>
          {Children.map(children, (child) => (
            this.extendChild(child, styles, selectedItemStyle))
          )}
        </MyComponent>
      );
    }
  };
};

export default makeSelectable;
<|endoftext|>


<commit_before>var Class = require('./Class');
var LangParser = require('./parser');

/**
 * regex for any coordinate (x, y, direction) specification for an object.
 * This is used to match both:
 *   ROBOT 5 5 N 3 #a robot at (5, 5) facing North with 3 beepers.
 * and
 *   WALL 5 5 E 2 #2 walls eastern walls starting at 5,5 going north.
 * @constant
 */
var SPEC = /^\s*(\w+)\s+(\d+)\s+(\d+)\s+([NESW])(\s+\d+)?\s*$/;

/**
 * regex for beepers.  Should match something like:
 *   BEEPERS 1 2 5
 * which means 5 beepers at coordinates (1,2)
 * @constant
 */
var BEEPERS = /^\s*(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s*$/;

/**
 * @constant
 */
var EMPTY_LINE = LangParser.EMPTY_LINE;

var WorldParser = Class.extend(
  /**
   * @lends WorldParser#
   */
  {
    /**
     * @class parse lines into a world.
     * @constructs
     * @param lines See {@link WorldParser#lines}
     * @param world See {@link WorldParser#world}
     */
    init: function(lines, world){
      /**
       * The lines to parse
       * @type Array
       */
      this.lines = lines;

      /**
       * The world to update with the results of parsing.
       * @type gvr.world.World
       */
      this.world = world;
    },

    /**
     * parse the lines in the world.
     */
    parse: function (){
      var name,xCoord,yCoord,count;
      for (var i =0; i < this.lines.length; i++){
        var line = LangParser.removeComment(this.lines[i]);
        if (line.match(EMPTY_LINE)){
          continue;
        }
        var specMatch = line.match(SPEC);
        if (specMatch){
          name = specMatch[1].toUpperCase();
          xCoord = parseInt(specMatch[2],10);
          yCoord = parseInt(specMatch[3],10);
          var direction = {N:"NORTH",S:"SOUTH",E:"EAST",W:"WEST"}[specMatch[4]];
          count = parseInt(specMatch[5],10);
          if (count == NaN) {
            count = 0;
          }
          if (name === "ROBOT"){
            this.world.robot.x = xCoord;
            this.world.robot.y = yCoord;
            this.world.robot.beepers = count;
            this.world.robot.direction = direction;
          }
          if (name === "WALL"){
            this.world.setWall(xCoord, yCoord, direction, count);
          }
        }
        var beepersMatch = line.match(BEEPERS);
        if (beepersMatch){
          name = beepersMatch[1].toUpperCase();
          if (name == "BEEPERS"){
            xCoord = parseInt(beepersMatch[2],10);
            yCoord = parseInt(beepersMatch[3],10);
            count =  parseInt(beepersMatch[4],10);
            this.world.setBeepers(xCoord, yCoord, count);
          }
        }

      }
    }
  });

module.exports = WorldParser;<commit_msg>fix stupid NaN check bug. derp.<commit_after>var Class = require('./Class');
var LangParser = require('./parser');

/**
 * regex for any coordinate (x, y, direction) specification for an object.
 * This is used to match both:
 *   ROBOT 5 5 N 3 #a robot at (5, 5) facing North with 3 beepers.
 * and
 *   WALL 5 5 E 2 #2 walls eastern walls starting at 5,5 going north.
 * @constant
 */
var SPEC = /^\s*(\w+)\s+(\d+)\s+(\d+)\s+([NESW])(\s+\d+)?\s*$/;

/**
 * regex for beepers.  Should match something like:
 *   BEEPERS 1 2 5
 * which means 5 beepers at coordinates (1,2)
 * @constant
 */
var BEEPERS = /^\s*(\w+)\s+(\d+)\s+(\d+)\s+(\d+)\s*$/;

/**
 * @constant
 */
var EMPTY_LINE = LangParser.EMPTY_LINE;

var WorldParser = Class.extend(
  /**
   * @lends WorldParser#
   */
  {
    /**
     * @class parse lines into a world.
     * @constructs
     * @param lines See {@link WorldParser#lines}
     * @param world See {@link WorldParser#world}
     */
    init: function(lines, world){
      /**
       * The lines to parse
       * @type Array
       */
      this.lines = lines;

      /**
       * The world to update with the results of parsing.
       * @type gvr.world.World
       */
      this.world = world;
    },

    /**
     * parse the lines in the world.
     */
    parse: function (){
      var name,xCoord,yCoord,count;
      for (var i =0; i < this.lines.length; i++){
        var line = LangParser.removeComment(this.lines[i]);
        if (line.match(EMPTY_LINE)){
          continue;
        }
        var specMatch = line.match(SPEC);
        if (specMatch){
          name = specMatch[1].toUpperCase();
          xCoord = parseInt(specMatch[2],10);
          yCoord = parseInt(specMatch[3],10);
          var direction = {N:"NORTH",S:"SOUTH",E:"EAST",W:"WEST"}[specMatch[4]];
          count = parseInt(specMatch[5],10);
          if (isNaN(count)) {
            count = 0;
          }
          if (name === "ROBOT"){
            this.world.robot.x = xCoord;
            this.world.robot.y = yCoord;
            this.world.robot.beepers = count;
            this.world.robot.direction = direction;
          }
          if (name === "WALL"){
            this.world.setWall(xCoord, yCoord, direction, count);
          }
        }
        var beepersMatch = line.match(BEEPERS);
        if (beepersMatch){
          name = beepersMatch[1].toUpperCase();
          if (name == "BEEPERS"){
            xCoord = parseInt(beepersMatch[2],10);
            yCoord = parseInt(beepersMatch[3],10);
            count =  parseInt(beepersMatch[4],10);
            this.world.setBeepers(xCoord, yCoord, count);
          }
        }

      }
    }
  });

module.exports = WorldParser;<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import ReactNative, {
  View,
  Text,
  StyleSheet,
  Image,
  LayoutAnimation,
  TouchableOpacity,
} from 'react-native';

import Icons from "./Icons";
import CCInput from "./CCInput";
import { removeNonNumber } from "./Utilities";
import { InjectedProps } from "./connectToState";

const s = StyleSheet.create({
  container: {
    paddingLeft: 10,
    paddingRight: 10,
    flexDirection: "row",
    alignItems: "center",
  },
  icon: {
    width: 48,
    height: 40,
    resizeMode: "contain",
  },
  number: {
  },
  rightPart: {
    flexDirection: "row",
    marginLeft: 10,
  },
  last4: {
    flex: 1,
    justifyContent: "center",
  },
  expiry: {
    width: 90,
  },
  cvc: {
    width: 90,
  },
});

export default class LiteCreditCardInput extends Component {
  static propTypes = {
    ...InjectedProps,

    placeholders: PropTypes.object,

    inputStyle: Text.propTypes.style,

    validColor: PropTypes.string,
    invalidColor: PropTypes.string,
    placeholderColor: PropTypes.string,
  };

  componentDidMount = () => this._focus(this.props.focused);

  componentWillReceiveProps = newProps => {
    if (this.props.focused !== newProps.focused) this._focus(newProps.focused);
  };

  _focusNumber = () => this._focus("number");

  _focus = field => {
    if (!field) return;
    this.refs[field].focus();
    LayoutAnimation.easeInEaseOut();
  }

  _inputProps = field => {
    const {
      inputStyle, validColor, invalidColor, placeholderColor,
      placeholders,  values, status,
      onFocus, onChange, onBecomeEmpty, onBecomeValid
    } = this.props;

    return {
      inputStyle, validColor, invalidColor, placeholderColor,
      ref: field, field: field,

      label: "",
      placeholder: placeholders[field],
      value: values[field],
      status: status[field],

      onFocus, onChange, onBecomeEmpty, onBecomeValid,
    }
  };

  _iconToShow = () => {
    const { focused, values: { type } } = this.props;
    if (focused === "cvc" && type === "american-express") return "cvc_amex";
    if (focused === "cvc") return "cvc";
    if (type) return type;
    return "placeholder";
  }

  render() {
    const { focused, values: { number }, inputStyle } = this.props;
    const showRightPart = (focused === "expiry" || focused === "cvc");

    return (
      <View style={s.container}>
        <View style={[s.number,
          showRightPart ? { width: 1 } : { flex: 1 } ]}>
          <CCInput {...this._inputProps("number")} />
        </View>
        <Image style={s.icon}
            source={{ uri: Icons[this._iconToShow()] }} />
        <View style={[
          s.rightPart,
          showRightPart ? { flex: 1 } : { width: 1 }
        ]}>
          <TouchableOpacity onPress={this._focusNumber}
              style={s.last4}>
            <Text style={[inputStyle, { height: null }]}>
              { number.substr(number.length - 4, 4) }
            </Text>
          </TouchableOpacity>
          <View style={s.expiry}>
            <CCInput {...this._inputProps("expiry")} />
          </View>
          <View style={s.cvc}>
            <CCInput {...this._inputProps("cvc")} />
          </View>
        </View>
      </View>
    );
  }
}

LiteCreditCardInput.defaultProps = {
  placeholders: {
    number: "1234 5678 1234 5678",
    expiry: "MM/YY",
    cvc: "CVC",
  },
  validColor: "",
  invalidColor: "red",
  placeholderColor: "gray",
};
<commit_msg>Prevent card number input from disappearing when its container is shrunk<commit_after>import React, { Component, PropTypes } from 'react';
import ReactNative, {
  View,
  Text,
  TextInput,
  StyleSheet,
  Image,
  LayoutAnimation,
  TouchableOpacity,
} from 'react-native';

import Icons from "./Icons";
import CCInput from "./CCInput";
import { removeNonNumber } from "./Utilities";
import { InjectedProps } from "./connectToState";

const INFINITE_WIDTH = 1000;

const s = StyleSheet.create({
  container: {
    paddingLeft: 10,
    paddingRight: 10,
    flexDirection: "row",
    alignItems: "center",
    overflow: "hidden",
  },
  icon: {
    width: 48,
    height: 40,
    resizeMode: "contain",
  },
  expanded: {
    flex: 1,
  },
  hidden: {
    width: 0,
  },
  leftPart: {
    overflow: "hidden",
  },
  rightPart: {
    overflow: "hidden",
    flexDirection: "row",
    marginLeft: 10,
  },
  last4: {
    flex: 1,
    justifyContent: "center",
  },
  numberInput: {
    width: INFINITE_WIDTH,
  },
  expiryInput: {
    width: 80,
  },
  cvcInput: {
    width: 80,
  },
});

export default class LiteCreditCardInput extends Component {
  static propTypes = {
    ...InjectedProps,

    placeholders: PropTypes.object,

    inputStyle: Text.propTypes.style,

    validColor: PropTypes.string,
    invalidColor: PropTypes.string,
    placeholderColor: PropTypes.string,
  };

  componentDidMount = () => this._focus(this.props.focused);

  componentWillReceiveProps = newProps => {
    if (this.props.focused !== newProps.focused) this._focus(newProps.focused);
  };

  _focusNumber = () => this._focus("number");

  _focus = field => {
    if (!field) return;
    this.refs[field].focus();
    LayoutAnimation.easeInEaseOut();
  }

  _inputProps = field => {
    const {
      inputStyle, validColor, invalidColor, placeholderColor,
      placeholders, values, status,
      onFocus, onChange, onBecomeEmpty, onBecomeValid
    } = this.props;

    return {
      inputStyle, validColor, invalidColor, placeholderColor,
      ref: field, field: field,

      placeholder: placeholders[field],
      value: values[field],
      status: status[field],

      onFocus, onChange, onBecomeEmpty, onBecomeValid,
    }
  };

  _iconToShow = () => {
    const { focused, values: { type } } = this.props;
    if (focused === "cvc" && type === "american-express") return "cvc_amex";
    if (focused === "cvc") return "cvc";
    if (type) return type;
    return "placeholder";
  }

  render() {
    const { focused, values: { number }, inputStyle } = this.props;
    const showRightPart = (focused === "expiry" || focused === "cvc");

    return (
      <View style={s.container}>
        <View style={[
          s.leftPart,
          showRightPart ? s.hidden : s.expanded,
        ]}>
          <CCInput {...this._inputProps("number")}
              containerStyle={s.numberInput} />
        </View>
        <Image style={s.icon}
            source={{ uri: Icons[this._iconToShow()] }} />
        <View style={[
          s.rightPart,
          showRightPart ? s.expanded : s.hidden,
        ]}>
          <TouchableOpacity onPress={this._focusNumber}
              style={s.last4}>
            <View pointerEvents={"none"}>
              <TextInput editable={false}
                  underlineColorAndroid={"transparent"}
                  style={[inputStyle]}
                  value={number.substr(number.length - 4, 4)} />
            </View>
          </TouchableOpacity>
          <CCInput {...this._inputProps("expiry")}
              containerStyle={s.expiryInput} />
          <CCInput {...this._inputProps("cvc")}
              containerStyle={s.cvcInput} />
        </View>
      </View>
    );
  }
}

LiteCreditCardInput.defaultProps = {
  placeholders: {
    number: "1234 5678 1234 5678",
    expiry: "MM/YY",
    cvc: "CVC",
  },
  validColor: "",
  invalidColor: "red",
  placeholderColor: "gray",
};
<|endoftext|>