<commit_before>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

document.addEventListener('DOMContentLoaded', init);

async function init() {
  console.log('DOMContentLoaded');
  try {
    const enumerateDevices = await navigator.mediaDevices.enumerateDevices();
    gotSources(enumerateDevices);
  } catch (e) {
    console.log(e);
  }

  const getMediaButton = document.querySelector('button#getMedia');
  const createPeerConnectionButton = document.querySelector('button#createPeerConnection');
  const createOfferButton = document.querySelector('button#createOffer');
  const setOfferButton = document.querySelector('button#setOffer');
  const createAnswerButton = document.querySelector('button#createAnswer');
  const setAnswerButton = document.querySelector('button#setAnswer');
  const hangupButton = document.querySelector('button#hangup');
  let dataChannelDataReceived;

  getMediaButton.onclick = getMedia;
  createPeerConnectionButton.onclick = createPeerConnection;
  createOfferButton.onclick = createOffer;
  setOfferButton.onclick = setOffer;
  createAnswerButton.onclick = createAnswer;
  setAnswerButton.onclick = setAnswer;
  hangupButton.onclick = hangup;

  const offerSdpTextarea = document.querySelector('div#local textarea');
  const answerSdpTextarea = document.querySelector('div#remote textarea');

  const audioSelect = document.querySelector('select#audioSrc');
  const videoSelect = document.querySelector('select#videoSrc');

  audioSelect.onchange = videoSelect.onchange = getMedia;

  const localVideo = document.querySelector('div#local video');
  const remoteVideo = document.querySelector('div#remote video');

  const selectSourceDiv = document.querySelector('div#selectSource');

  let localPeerConnection;
  let remotePeerConnection;
  let localStream;
  let sendChannel;
  let receiveChannel;
  const dataChannelOptions = {ordered: true};
  let dataChannelCounter = 0;
  let sendDataLoop;
  const offerOptions = {
    offerToReceiveAudio: 1,
    offerToReceiveVideo: 1
  };

  function gotSources(sourceInfos) {
    selectSourceDiv.classList.remove('hidden');
    let audioCount = 0;
    let videoCount = 0;
    for (let i = 0; i < sourceInfos.length; i++) {
      const option = document.createElement('option');
      option.value = sourceInfos[i].deviceId;
      option.text = sourceInfos[i].label;
      if (sourceInfos[i].kind === 'audioinput') {
        audioCount++;
        if (option.text === '') {
          option.text = `Audio ${audioCount}`;
        }
        audioSelect.appendChild(option);
      } else if (sourceInfos[i].kind === 'videoinput') {
        videoCount++;
        if (option.text === '') {
          option.text = `Video ${videoCount}`;
        }
        videoSelect.appendChild(option);
      } else {
        console.log('unknown', JSON.stringify(sourceInfos[i]));
      }
    }
  }

  async function getMedia() {
    getMediaButton.disabled = true;
    createPeerConnectionButton.disabled = false;

    if (localStream) {
      localVideo.srcObject = null;
      localStream.getTracks().forEach(track => track.stop());
    }
    const audioSource = audioSelect.value;
    console.log(`Selected audio source: ${audioSource}`);
    const videoSource = videoSelect.value;
    console.log(`Selected video source: ${videoSource}`);

    const constraints = {
      audio: {
        optional: [{
          sourceId: audioSource
        }]
      },
      video: {
        optional: [{
          sourceId: videoSource
        }]
      }
    };
    console.log('Requested local stream');
    try {
      const userMedia = await navigator.mediaDevices.getUserMedia(constraints);
      gotStream(userMedia);
    } catch (e) {
      console.log('navigator.getUserMedia error: ', e);
    }
  }

  function gotStream(stream) {
    console.log('Received local stream');
    localVideo.srcObject = stream;
    localStream = stream;
  }

  function createPeerConnection() {
    createPeerConnectionButton.disabled = true;
    createOfferButton.disabled = false;
    createAnswerButton.disabled = false;
    setOfferButton.disabled = false;
    setAnswerButton.disabled = false;
    hangupButton.disabled = false;
    console.log('Starting call');
    const videoTracks = localStream.getVideoTracks();
    const audioTracks = localStream.getAudioTracks();

    if (videoTracks.length > 0) {
      console.log(`Using video device: ${videoTracks[0].label}`);
    }

    if (audioTracks.length > 0) {
      console.log(`Using audio device: ${audioTracks[0].label}`);
    }
    const servers = null;

    window.localPeerConnection = localPeerConnection = new RTCPeerConnection(servers);
    console.log('Created local peer connection object localPeerConnection');
    localPeerConnection.onicecandidate = e => onIceCandidate(localPeerConnection, e);
    sendChannel = localPeerConnection.createDataChannel('sendDataChannel', dataChannelOptions);
    sendChannel.onopen = onSendChannelStateChange;
    sendChannel.onclose = onSendChannelStateChange;
    sendChannel.onerror = onSendChannelStateChange;

    window.remotePeerConnection = remotePeerConnection = new RTCPeerConnection(servers);
    console.log('Created remote peer connection object remotePeerConnection');
    remotePeerConnection.onicecandidate = e => onIceCandidate(remotePeerConnection, e);
    remotePeerConnection.ontrack = gotRemoteStream;
    remotePeerConnection.ondatachannel = receiveChannelCallback;

    localStream.getTracks()
        .forEach(track => localPeerConnection.addTrack(track, localStream));
    console.log('Adding Local Stream to peer connection');
  }

  function onSetSessionDescriptionSuccess() {
    console.log('Set session description success.');
  }

  function onSetSessionDescriptionError(error) {
    console.log(`Failed to set session description: ${error.toString()}`);
  }

  async function createOffer() {
    try {
      const offer = await localPeerConnection.createOffer(offerOptions);
      gotDescription1(offer);
    } catch (e) {
      onCreateSessionDescriptionError(e);
    }
  }

  function onCreateSessionDescriptionError(error) {
    console.log(`Failed to create session description: ${error.toString()}`);
  }

  async function setOffer() {
    const sdp = offerSdpTextarea.value;
    const offer = {
      type: 'offer',
      sdp: sdp
    };
    console.log(`Modified Offer from localPeerConnection\n${sdp}`);

    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await localPeerConnection.setLocalDescription(offer);
      onSetSessionDescriptionSuccess();
    } catch (e) {
      onSetSessionDescriptionError(e);
    }

    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await remotePeerConnection.setRemoteDescription(offer);
      onSetSessionDescriptionSuccess();
    } catch (e) {
      onSetSessionDescriptionError(e);
    }
  }

  function gotDescription1(description) {
    offerSdpTextarea.disabled = false;
    offerSdpTextarea.value = description.sdp;
  }

  async function createAnswer() {
    // Since the 'remote' side has no media stream we need
    // to pass in the right constraints in order for it to
    // accept the incoming offer of audio and video.
    try {
      const answer = await remotePeerConnection.createAnswer();
      gotDescription2(answer);
    } catch (e) {
      onCreateSessionDescriptionError(e);
    }
  }

  async function setAnswer() {
    const sdp = answerSdpTextarea.value;
    const answer = {
      type: 'answer',
      sdp: sdp
    };

    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await remotePeerConnection.setLocalDescription(answer);
      onSetSessionDescriptionSuccess();
    } catch (e) {
      onSetSessionDescriptionError(e);
    }

    console.log(`Modified Answer from remotePeerConnection\n${sdp}`);
    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await localPeerConnection.setRemoteDescription(answer);
      onSetSessionDescriptionSuccess();
    } catch (e) {
      onSetSessionDescriptionError(e);
    }
  }

  function gotDescription2(description) {
    answerSdpTextarea.disabled = false;
    answerSdpTextarea.value = description.sdp;
  }

  function sendData() {
    if (sendChannel.readyState === 'open') {
      sendChannel.send(dataChannelCounter);
      console.log(`DataChannel send counter: ${dataChannelCounter}`);
      dataChannelCounter++;
    }
  }

  function hangup() {
    remoteVideo.srcObject = null;
    console.log('Ending call');
    localStream.getTracks().forEach(track => track.stop());
    sendChannel.close();
    if (receiveChannel) {
      receiveChannel.close();
    }
    localPeerConnection.close();
    remotePeerConnection.close();
    localPeerConnection = null;
    remotePeerConnection = null;
    offerSdpTextarea.disabled = true;
    answerSdpTextarea.disabled = true;
    getMediaButton.disabled = false;
    createPeerConnectionButton.disabled = true;
    createOfferButton.disabled = true;
    setOfferButton.disabled = true;
    createAnswerButton.disabled = true;
    setAnswerButton.disabled = true;
    hangupButton.disabled = true;
  }

  function gotRemoteStream(e) {
    if (remoteVideo.srcObject !== e.streams[0]) {
      remoteVideo.srcObject = e.streams[0];
      console.log('Received remote stream');
    }
  }

  function getOtherPc(pc) {
    return (pc === localPeerConnection) ? remotePeerConnection : localPeerConnection;
  }

  function getName(pc) {
    return (pc === localPeerConnection) ? 'localPeerConnection' : 'remotePeerConnection';
  }

  async function onIceCandidate(pc, event) {
    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await getOtherPc(pc).addIceCandidate(event.candidate);
      onAddIceCandidateSuccess(pc);
    } catch (e) {
      onAddIceCandidateError(pc, e);
    }

    console.log(`${getName(pc)} ICE candidate:\n${event.candidate ? event.candidate.candidate : '(null)'}`);
  }

  function onAddIceCandidateSuccess() {
    console.log('AddIceCandidate success.');
  }

  function onAddIceCandidateError(error) {
    console.log(`Failed to add Ice Candidate: ${error.toString()}`);
  }

  function receiveChannelCallback(event) {
    console.log('Receive Channel Callback');
    receiveChannel = event.channel;
    receiveChannel.onmessage = onReceiveMessageCallback;
    receiveChannel.onopen = onReceiveChannelStateChange;
    receiveChannel.onclose = onReceiveChannelStateChange;
  }

  function onReceiveMessageCallback(event) {
    dataChannelDataReceived = event.data;
    console.log(`DataChannel receive counter: ${dataChannelDataReceived}`);
  }

  function onSendChannelStateChange() {
    const readyState = sendChannel.readyState;
    console.log(`Send channel state is: ${readyState}`);
    if (readyState === 'open') {
      sendDataLoop = setInterval(sendData, 1000);
    } else {
      clearInterval(sendDataLoop);
    }
  }

  function onReceiveChannelStateChange() {
    const readyState = receiveChannel.readyState;
    console.log(`Receive channel state is: ${readyState}`);
  }
}<commit_msg>munge-sdp: restore CRLF (#1246)<commit_after>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

document.addEventListener('DOMContentLoaded', init);

async function init() {
  console.log('DOMContentLoaded');
  try {
    const enumerateDevices = await navigator.mediaDevices.enumerateDevices();
    gotSources(enumerateDevices);
  } catch (e) {
    console.log(e);
  }

  const getMediaButton = document.querySelector('button#getMedia');
  const createPeerConnectionButton = document.querySelector('button#createPeerConnection');
  const createOfferButton = document.querySelector('button#createOffer');
  const setOfferButton = document.querySelector('button#setOffer');
  const createAnswerButton = document.querySelector('button#createAnswer');
  const setAnswerButton = document.querySelector('button#setAnswer');
  const hangupButton = document.querySelector('button#hangup');
  let dataChannelDataReceived;

  getMediaButton.onclick = getMedia;
  createPeerConnectionButton.onclick = createPeerConnection;
  createOfferButton.onclick = createOffer;
  setOfferButton.onclick = setOffer;
  createAnswerButton.onclick = createAnswer;
  setAnswerButton.onclick = setAnswer;
  hangupButton.onclick = hangup;

  const offerSdpTextarea = document.querySelector('div#local textarea');
  const answerSdpTextarea = document.querySelector('div#remote textarea');

  const audioSelect = document.querySelector('select#audioSrc');
  const videoSelect = document.querySelector('select#videoSrc');

  audioSelect.onchange = videoSelect.onchange = getMedia;

  const localVideo = document.querySelector('div#local video');
  const remoteVideo = document.querySelector('div#remote video');

  const selectSourceDiv = document.querySelector('div#selectSource');

  let localPeerConnection;
  let remotePeerConnection;
  let localStream;
  let sendChannel;
  let receiveChannel;
  const dataChannelOptions = {ordered: true};
  let dataChannelCounter = 0;
  let sendDataLoop;
  const offerOptions = {
    offerToReceiveAudio: 1,
    offerToReceiveVideo: 1
  };

  function gotSources(sourceInfos) {
    selectSourceDiv.classList.remove('hidden');
    let audioCount = 0;
    let videoCount = 0;
    for (let i = 0; i < sourceInfos.length; i++) {
      const option = document.createElement('option');
      option.value = sourceInfos[i].deviceId;
      option.text = sourceInfos[i].label;
      if (sourceInfos[i].kind === 'audioinput') {
        audioCount++;
        if (option.text === '') {
          option.text = `Audio ${audioCount}`;
        }
        audioSelect.appendChild(option);
      } else if (sourceInfos[i].kind === 'videoinput') {
        videoCount++;
        if (option.text === '') {
          option.text = `Video ${videoCount}`;
        }
        videoSelect.appendChild(option);
      } else {
        console.log('unknown', JSON.stringify(sourceInfos[i]));
      }
    }
  }

  async function getMedia() {
    getMediaButton.disabled = true;
    createPeerConnectionButton.disabled = false;

    if (localStream) {
      localVideo.srcObject = null;
      localStream.getTracks().forEach(track => track.stop());
    }
    const audioSource = audioSelect.value;
    console.log(`Selected audio source: ${audioSource}`);
    const videoSource = videoSelect.value;
    console.log(`Selected video source: ${videoSource}`);

    const constraints = {
      audio: {
        optional: [{
          sourceId: audioSource
        }]
      },
      video: {
        optional: [{
          sourceId: videoSource
        }]
      }
    };
    console.log('Requested local stream');
    try {
      const userMedia = await navigator.mediaDevices.getUserMedia(constraints);
      gotStream(userMedia);
    } catch (e) {
      console.log('navigator.getUserMedia error: ', e);
    }
  }

  function gotStream(stream) {
    console.log('Received local stream');
    localVideo.srcObject = stream;
    localStream = stream;
  }

  function createPeerConnection() {
    createPeerConnectionButton.disabled = true;
    createOfferButton.disabled = false;
    createAnswerButton.disabled = false;
    setOfferButton.disabled = false;
    setAnswerButton.disabled = false;
    hangupButton.disabled = false;
    console.log('Starting call');
    const videoTracks = localStream.getVideoTracks();
    const audioTracks = localStream.getAudioTracks();

    if (videoTracks.length > 0) {
      console.log(`Using video device: ${videoTracks[0].label}`);
    }

    if (audioTracks.length > 0) {
      console.log(`Using audio device: ${audioTracks[0].label}`);
    }
    const servers = null;

    window.localPeerConnection = localPeerConnection = new RTCPeerConnection(servers);
    console.log('Created local peer connection object localPeerConnection');
    localPeerConnection.onicecandidate = e => onIceCandidate(localPeerConnection, e);
    sendChannel = localPeerConnection.createDataChannel('sendDataChannel', dataChannelOptions);
    sendChannel.onopen = onSendChannelStateChange;
    sendChannel.onclose = onSendChannelStateChange;
    sendChannel.onerror = onSendChannelStateChange;

    window.remotePeerConnection = remotePeerConnection = new RTCPeerConnection(servers);
    console.log('Created remote peer connection object remotePeerConnection');
    remotePeerConnection.onicecandidate = e => onIceCandidate(remotePeerConnection, e);
    remotePeerConnection.ontrack = gotRemoteStream;
    remotePeerConnection.ondatachannel = receiveChannelCallback;

    localStream.getTracks()
        .forEach(track => localPeerConnection.addTrack(track, localStream));
    console.log('Adding Local Stream to peer connection');
  }

  function onSetSessionDescriptionSuccess() {
    console.log('Set session description success.');
  }

  function onSetSessionDescriptionError(error) {
    console.log(`Failed to set session description: ${error.toString()}`);
  }

  async function createOffer() {
    try {
      const offer = await localPeerConnection.createOffer(offerOptions);
      gotDescription1(offer);
    } catch (e) {
      onCreateSessionDescriptionError(e);
    }
  }

  function onCreateSessionDescriptionError(error) {
    console.log(`Failed to create session description: ${error.toString()}`);
  }

  async function setOffer() {
    // Restore the SDP from the textarea. Ensure we use CRLF which is what is generated
    // even though https://tools.ietf.org/html/rfc4566#section-5 requires
    // parsers to handle both LF and CRLF.
    const sdp = offerSdpTextarea.value
        .split('\n')
        .map(l => l.trim())
        .join('\r\n');
    const offer = {
      type: 'offer',
      sdp: sdp
    };
    console.log(`Modified Offer from localPeerConnection\n${sdp}`);

    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await localPeerConnection.setLocalDescription(offer);
      onSetSessionDescriptionSuccess();
    } catch (e) {
      onSetSessionDescriptionError(e);
    }

    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await remotePeerConnection.setRemoteDescription(offer);
      onSetSessionDescriptionSuccess();
    } catch (e) {
      onSetSessionDescriptionError(e);
    }
  }

  function gotDescription1(description) {
    offerSdpTextarea.disabled = false;
    offerSdpTextarea.value = description.sdp;
  }

  async function createAnswer() {
    // Since the 'remote' side has no media stream we need
    // to pass in the right constraints in order for it to
    // accept the incoming offer of audio and video.
    try {
      const answer = await remotePeerConnection.createAnswer();
      gotDescription2(answer);
    } catch (e) {
      onCreateSessionDescriptionError(e);
    }
  }

  async function setAnswer() {
    // Restore the SDP from the textarea. Ensure we use CRLF which is what is generated
    // even though https://tools.ietf.org/html/rfc4566#section-5 requires
    // parsers to handle both LF and CRLF.
    const sdp = answerSdpTextarea.value
        .split('\n')
        .map(l => l.trim())
        .join('\r\n');
    const answer = {
      type: 'answer',
      sdp: sdp
    };

    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await remotePeerConnection.setLocalDescription(answer);
      onSetSessionDescriptionSuccess();
    } catch (e) {
      onSetSessionDescriptionError(e);
    }

    console.log(`Modified Answer from remotePeerConnection\n${sdp}`);
    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await localPeerConnection.setRemoteDescription(answer);
      onSetSessionDescriptionSuccess();
    } catch (e) {
      onSetSessionDescriptionError(e);
    }
  }

  function gotDescription2(description) {
    answerSdpTextarea.disabled = false;
    answerSdpTextarea.value = description.sdp;
  }

  function sendData() {
    if (sendChannel.readyState === 'open') {
      sendChannel.send(dataChannelCounter);
      console.log(`DataChannel send counter: ${dataChannelCounter}`);
      dataChannelCounter++;
    }
  }

  function hangup() {
    remoteVideo.srcObject = null;
    console.log('Ending call');
    localStream.getTracks().forEach(track => track.stop());
    sendChannel.close();
    if (receiveChannel) {
      receiveChannel.close();
    }
    localPeerConnection.close();
    remotePeerConnection.close();
    localPeerConnection = null;
    remotePeerConnection = null;
    offerSdpTextarea.disabled = true;
    answerSdpTextarea.disabled = true;
    getMediaButton.disabled = false;
    createPeerConnectionButton.disabled = true;
    createOfferButton.disabled = true;
    setOfferButton.disabled = true;
    createAnswerButton.disabled = true;
    setAnswerButton.disabled = true;
    hangupButton.disabled = true;
  }

  function gotRemoteStream(e) {
    if (remoteVideo.srcObject !== e.streams[0]) {
      remoteVideo.srcObject = e.streams[0];
      console.log('Received remote stream');
    }
  }

  function getOtherPc(pc) {
    return (pc === localPeerConnection) ? remotePeerConnection : localPeerConnection;
  }

  function getName(pc) {
    return (pc === localPeerConnection) ? 'localPeerConnection' : 'remotePeerConnection';
  }

  async function onIceCandidate(pc, event) {
    try {
      // eslint-disable-next-line no-unused-vars
      const ignore = await getOtherPc(pc).addIceCandidate(event.candidate);
      onAddIceCandidateSuccess(pc);
    } catch (e) {
      onAddIceCandidateError(pc, e);
    }

    console.log(`${getName(pc)} ICE candidate:\n${event.candidate ? event.candidate.candidate : '(null)'}`);
  }

  function onAddIceCandidateSuccess() {
    console.log('AddIceCandidate success.');
  }

  function onAddIceCandidateError(error) {
    console.log(`Failed to add Ice Candidate: ${error.toString()}`);
  }

  function receiveChannelCallback(event) {
    console.log('Receive Channel Callback');
    receiveChannel = event.channel;
    receiveChannel.onmessage = onReceiveMessageCallback;
    receiveChannel.onopen = onReceiveChannelStateChange;
    receiveChannel.onclose = onReceiveChannelStateChange;
  }

  function onReceiveMessageCallback(event) {
    dataChannelDataReceived = event.data;
    console.log(`DataChannel receive counter: ${dataChannelDataReceived}`);
  }

  function onSendChannelStateChange() {
    const readyState = sendChannel.readyState;
    console.log(`Send channel state is: ${readyState}`);
    if (readyState === 'open') {
      sendDataLoop = setInterval(sendData, 1000);
    } else {
      clearInterval(sendDataLoop);
    }
  }

  function onReceiveChannelStateChange() {
    const readyState = receiveChannel.readyState;
    console.log(`Receive channel state is: ${readyState}`);
  }
}
<|endoftext|>


<commit_before>/** File: createroom.js
 * Candy Plugin Create Room
 * Author: Melissa Adamaitis <madamei@mojolingo.com>
 */

var CandyShop = (function(self) { return self; }(CandyShop || {}));

CandyShop.CreateRoom = (function(self, Candy, $) {
  /** Object: about
   *
   * Contains:
   *  (String) name - Candy Plugin Create Room
   *  (Float) version - Candy Plugin Create Room
   */
  self.about = {
    name: 'Candy Plugin Create Room',
    version: '1.0'
  };

  /**
   * Initializes the CreateRoom plugin with the default settings.
   */
  self.init = function(){
    $(Candy).on('candy:view.room.after-add', function() {
      self.appendButton();
    });
  };

  self.appendButton = function(){
    if ($('#create-group').length === 0) {
      $('#chat-tabs').after(self.Template.create_button);
      $('#create-group').click(function () {
        self.showModal();
        $('#create-group-form').click(function(event) {
          event.stopPropagation();
        });
      });
    }
  };

  self.addFormHandler = function(){
    // Add focus to the form element when it's shown.
    $('#create-group-form-name').focus();

    $('#create-group-form').submit(function(event) {
      event.preventDefault();
      if ($('#create-group-form-name').val() === '') {
        // Notify that group name cannot be blank.
        $('.form-group.group-form-name-group').addClass('has-error');
        // Remove classes after user either starts typing or has pasted in a name.
        $('#create-group-form-name').focus(function() {
          $('.form-group.group-form-name-group').removeClass('has-error');
        });
      } else {
        var room_name = $('#create-group-form-name').val().trim();
        // Create a valid roomjid.
        var room_jid = room_name.replace(/[^A-Z0-9]+/ig, "_").toLowerCase() + '@conference.' +
                       Candy.Core.getConnection().domain;

        // Once we've joined the room, send configuration information.
        $(Candy).on('candy:view.room.after-add', function(ev, obj) {
          if (obj.roomJid.toUpperCase() === room_jid.toUpperCase()) {
            // Configuration items for setting room name.
            var config_form_type = $build('field', { 'var': 'FORM_TYPE' })
                                    .c('value').t('http://jabber.org/protocol/muc#roomconfig');
            var config_room_name = $build('field', { 'var': 'muc#roomconfig_roomname' }).c('value').t(room_name);
            var config = [config_form_type.tree(), config_room_name.tree()];
            // Send the configuration form to the server, and on success update our DOM.
            Candy.Core.getConnection().muc.saveConfiguration(room_jid, config, function(stanza) {
              var jid = $(stanza).attr('from');
              if (jid === room_jid) {
                Candy.View.Pane.Chat.getTab(room_jid).find('.label').html(room_name);
              }
            });
          }
        });

        // Join the room and close the modal.
        Candy.Core.Action.Jabber.Room.Join(room_jid, null);
        Candy.View.Pane.Chat.Modal.hide();
      }
    });
  };

  self.showModal = function(){
    Candy.View.Pane.Chat.Modal.show(self.Template.modal_form, true, false);
    self.addFormHandler();
  };

  self.Template = {
    create_button: '

+ Create Room

',
    modal_form: '
Create Room
<form id="create-group-form">' +
                '
' +
                'Name:' +
                '<input class="form-control" type="text" name="room-name" id="create-group-form-name" />' +
                '
<button type="submit">Create</button></form>'
  };

  return self;
}(CandyShop.CreateRoom || {}, Candy, jQuery));
<commit_msg>Switching create room to camelCase.<commit_after>/** File: createroom.js
 * Candy Plugin Create Room
 * Author: Melissa Adamaitis <madamei@mojolingo.com>
 */

var CandyShop = (function(self) { return self; }(CandyShop || {}));

CandyShop.CreateRoom = (function(self, Candy, $) {
  /** Object: about
   *
   * Contains:
   *  (String) name - Candy Plugin Create Room
   *  (Float) version - Candy Plugin Create Room
   */
  self.about = {
    name: 'Candy Plugin Create Room',
    version: '1.0'
  };

  /**
   * Initializes the CreateRoom plugin with the default settings.
   */
  self.init = function(){
    $(Candy).on('candy:view.room.after-add', function() {
      self.appendButton();
    });
  };

  self.appendButton = function(){
    if ($('#create-group').length === 0) {
      $('#chat-tabs').after(self.Template.createButton);
      $('#create-group').click(function () {
        self.showModal();
        $('#create-group-form').click(function(event) {
          event.stopPropagation();
        });
      });
    }
  };

  self.addFormHandler = function(){
    // Add focus to the form element when it's shown.
    $('#create-group-form-name').focus();

    $('#create-group-form').submit(function(event) {
      event.preventDefault();
      if ($('#create-group-form-name').val() === '') {
        // Notify that group name cannot be blank.
        $('.form-group.group-form-name-group').addClass('has-error');
        // Remove classes after user either starts typing or has pasted in a name.
        $('#create-group-form-name').focus(function() {
          $('.form-group.group-form-name-group').removeClass('has-error');
        });
      } else {
        var roomName = $('#create-group-form-name').val().trim();
        // Create a valid roomjid.
        var roomJid = roomName.replace(/[^A-Z0-9]+/ig, "_").toLowerCase() + '@conference.' +
                       Candy.Core.getConnection().domain;

        // Once we've joined the room, send configuration information.
        $(Candy).on('candy:view.room.after-add', function(ev, obj) {
          if (obj.roomJid.toUpperCase() === roomJid.toUpperCase()) {
            // Configuration items for setting room name.
            var configFormType = $build('field', { 'var': 'FORM_TYPE' })
                                    .c('value').t('http://jabber.org/protocol/muc#roomconfig');
            var configRoomName = $build('field', { 'var': 'muc#roomconfigRoomName' }).c('value').t(roomName);
            var config = [configFormType.tree(), configRoomName.tree()];
            // Send the configuration form to the server, and on success update our DOM.
            Candy.Core.getConnection().muc.saveConfiguration(roomJid, config, function(stanza) {
              var jid = $(stanza).attr('from');
              if (jid === roomJid) {
                Candy.View.Pane.Chat.getTab(roomJid).find('.label').html(roomName);
              }
            });
          }
        });

        // Join the room and close the modal.
        Candy.Core.Action.Jabber.Room.Join(roomJid, null);
        Candy.View.Pane.Chat.Modal.hide();
      }
    });
  };

  self.showModal = function(){
    Candy.View.Pane.Chat.Modal.show(self.Template.modalForm, true, false);
    self.addFormHandler();
  };

  self.Template = {
    createButton: '

+ Create Room

',
    modalForm: '
Create Room
<form id="create-group-form">' +
                '
' +
                'Name:' +
                '<input class="form-control" type="text" name="room-name" id="create-group-form-name" />' +
                '
<button type="submit">Create</button></form>'
  };

  return self;
}(CandyShop.CreateRoom || {}, Candy, jQuery));
<|endoftext|>


<commit_before>function	evalwin(table, game)
{
	var		winners = new Array();
	var		idx = 1;
	var		best = 0;
	var		player;

	while (idx <= 6)
	{
		player = get_seat(table.seats, idx).player;
		//console.log("Player hand value: " + player.rank_value);
		if (player.rank_value)
		{
			if (!best || player.rank_value > best.rank_value)
				best = player;
			else if (player.rank_value === best.rank_value)
				winners.push(player);
		}
		++idx;
	}
	if (!winners.length)
		winners.push(best);
	//console.log("winners: " + winners);
	//console.log("best: " + best.rank_value);
	return winners;
}

function	show_down(table, game)
{
	var		winners; // Indeed, with a 's' at the end in case of split.
	var		player;

	table = get_table(table.id, tables);
	table.game.moment = "waiting end game";
	if (!(winners = evalwin(table, game)))
		console.log("Can't retrieve winner(s)! Game error!");
	console.log("And the winner is..." + winners[0].nickname);

	for (var i = 1; i < 7; i++) {
		io.to(get_private_id(table.private_ids, i)).emit("cancel buttons", "hidden");
	}

	if (winners.length == 1)
	{
		winners[0].bankroll += game.pot_amount;
		io.to(table.id).emit("bankroll modification", winners[0].seat_nb, winners[0]);
	}
	else
	{
		console.log("Split!");
		for (var idx = 0; idx < winners.length; ++idx)
		{
			winners[idx].bankroll += game.pot_amount / winners.length;
			io.to(table.id).emit("bankroll modification", winners[idx].seat_nb, winners[idx]);
		}
	}
	for (idx = 1; idx <= 6; ++idx)
	{
		if (table.playing_seats.indexOf(idx) != -1)
		{
			player = get_seat(table.seats, idx).player;
			io.to(table.id).emit("show down", player.card1, player.card2, idx);
		}
	}
	return end_game(table, game, winners, player);
}
<commit_msg>fold issue<commit_after>function	evalwin(table, game)
{
	var		winners = new Array();
	var		idx = 1;
	var		best = 0;
	var		player;

	while (idx <= 6)
	{
		player = get_seat(table.seats, idx).player;
		//console.log("Player hand value: " + player.rank_value);
		if (player.rank_value)
		{
			if (!best || player.rank_value > best.rank_value)
				best = player;
			else if (player.rank_value === best.rank_value)
				winners.push(player);
		}
		++idx;
	}
	if (!winners.length)
		winners.push(best);

	console.log("winners: " + winners);
	console.log("best: " + best.rank_value);
	return winners;
}

function	show_down(table, game)
{
	var		winners; // Indeed, with a 's' at the end in case of split.
	var		player;

	table = get_table(table.id, tables);
	table.game.moment = "waiting end game";
	if (!(winners = evalwin(table, game)))
		console.log("Can't retrieve winner(s)! Game error!");
	console.log("And the winner is..." + winners[0].nickname);

	for (var i = 1; i < 7; i++) {
		io.to(get_private_id(table.private_ids, i)).emit("cancel buttons", "hidden");
	}

	if (winners.length == 1)
	{
		winners[0].bankroll += game.pot_amount;
		io.to(table.id).emit("bankroll modification", winners[0].seat_nb, winners[0]);
	}
	else
	{
		console.log("Split!");
		for (var idx = 0; idx < winners.length; ++idx)
		{
			winners[idx].bankroll += game.pot_amount / winners.length;
			io.to(table.id).emit("bankroll modification", winners[idx].seat_nb, winners[idx]);
		}
	}
	for (idx = 1; idx <= 6; ++idx)
	{
		if (table.playing_seats.indexOf(idx) != -1)
		{
			player = get_seat(table.seats, idx).player;
			io.to(table.id).emit("show down", player.card1, player.card2, idx);
		}
	}
	return end_game(table, game, winners, player);
}
<|endoftext|>


<commit_before>import CanvasRenderer from '../../renderers/canvas/CanvasRenderer';
import { SCALE_MODES } from '../../const';
import { Matrix, GroupD8 } from '../../math';
import CanvasTinter from './CanvasTinter';

const canvasRenderWorldTransform = new Matrix();

/**
 * @author Mat Groves
 *
 * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
 * for creating the original PixiJS version!
 * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now
 * share 4 bytes on the vertex buffer
 *
 * Heavily inspired by LibGDX's CanvasSpriteRenderer:
 * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/CanvasSpriteRenderer.java
 */

/**
 * Renderer dedicated to drawing and batching sprites.
 *
 * @class
 * @private
 * @memberof PIXI
 */
export default class CanvasSpriteRenderer
{
    /**
     * @param {PIXI.WebGLRenderer} renderer -The renderer sprite this batch works for.
     */
    constructor(renderer)
    {
        this.renderer = renderer;
    }

    /**
     * Renders the sprite object.
     *
     * @param {PIXI.Sprite} sprite - the sprite to render when using this spritebatch
     */
    render(sprite)
    {
        const texture = sprite._texture;
        const renderer = this.renderer;

        const width = texture._frame.width;
        const height = texture._frame.height;

        let wt = sprite.transform.worldTransform;
        let dx = 0;
        let dy = 0;

        if (texture.orig.width <= 0 || texture.orig.height <= 0 || !texture.baseTexture.source)
        {
            return;
        }

        renderer.setBlendMode(sprite.blendMode);

        //  Ignore null sources
        if (texture.valid)
        {
            renderer.context.globalAlpha = sprite.worldAlpha;

            // If smoothingEnabled is supported and we need to change the smoothing property for sprite texture
            const smoothingEnabled = texture.baseTexture.scaleMode === SCALE_MODES.LINEAR;

            if (renderer.smoothProperty && renderer.context[renderer.smoothProperty] !== smoothingEnabled)
            {
                renderer.context[renderer.smoothProperty] = smoothingEnabled;
            }

            if (texture.trim)
            {
                dx = (texture.trim.width / 2) + texture.trim.x - (sprite.anchor.x * texture.orig.width);
                dy = (texture.trim.height / 2) + texture.trim.y - (sprite.anchor.y * texture.orig.height);
            }
            else
            {
                dx = (0.5 - sprite.anchor.x) * texture.orig.width;
                dy = (0.5 - sprite.anchor.y) * texture.orig.height;
            }

            if (texture.rotate)
            {
                wt.copy(canvasRenderWorldTransform);
                wt = canvasRenderWorldTransform;
                GroupD8.matrixAppendRotationInv(wt, texture.rotate, dx, dy);
                // the anchor has already been applied above, so lets set it to zero
                dx = 0;
                dy = 0;
            }

            dx -= width / 2;
            dy -= height / 2;

            // Allow for pixel rounding
            if (renderer.roundPixels)
            {
                renderer.context.setTransform(
                    wt.a,
                    wt.b,
                    wt.c,
                    wt.d,
                    (wt.tx * renderer.resolution) | 0,
                    (wt.ty * renderer.resolution) | 0
                );

                dx = dx | 0;
                dy = dy | 0;
            }
            else
            {
                renderer.context.setTransform(
                    wt.a,
                    wt.b,
                    wt.c,
                    wt.d,
                    wt.tx * renderer.resolution,
                    wt.ty * renderer.resolution
                );
            }

            const resolution = texture.baseTexture.resolution;

            if (sprite.tint !== 0xFFFFFF)
            {
                if (sprite.cachedTint !== sprite.tint || sprite.tintedTexture.tintId !== sprite._texture._updateID)
                {
                    sprite.cachedTint = sprite.tint;

                    // TODO clean up caching - how to clean up the caches?
                    sprite.tintedTexture = CanvasTinter.getTintedTexture(sprite, sprite.tint);
                }

                renderer.context.drawImage(
                    sprite.tintedTexture,
                    0,
                    0,
                    width * resolution,
                    height * resolution,
                    dx * renderer.resolution,
                    dy * renderer.resolution,
                    width * renderer.resolution,
                    height * renderer.resolution
                );
            }
            else
            {
                renderer.context.drawImage(
                    texture.baseTexture.source,
                    texture._frame.x * resolution,
                    texture._frame.y * resolution,
                    width * resolution,
                    height * resolution,
                    dx * renderer.resolution,
                    dy * renderer.resolution,
                    width * renderer.resolution,
                    height * renderer.resolution
                );
            }
        }
    }

    /**
     * destroy the sprite object.
     *
     */
    destroy()
    {
        this.renderer = null;
    }
}

CanvasRenderer.registerPlugin('sprite', CanvasSpriteRenderer);
<commit_msg>CanvasSpriteRenderer fix.<commit_after>import CanvasRenderer from '../../renderers/canvas/CanvasRenderer';
import { SCALE_MODES } from '../../const';
import { Matrix, GroupD8 } from '../../math';
import CanvasTinter from './CanvasTinter';

const canvasRenderWorldTransform = new Matrix();

/**
 * @author Mat Groves
 *
 * Big thanks to the very clever Matt DesLauriers <mattdesl> https://github.com/mattdesl/
 * for creating the original PixiJS version!
 * Also a thanks to https://github.com/bchevalier for tweaking the tint and alpha so that they now
 * share 4 bytes on the vertex buffer
 *
 * Heavily inspired by LibGDX's CanvasSpriteRenderer:
 * https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/g2d/CanvasSpriteRenderer.java
 */

/**
 * Renderer dedicated to drawing and batching sprites.
 *
 * @class
 * @private
 * @memberof PIXI
 */
export default class CanvasSpriteRenderer
{
    /**
     * @param {PIXI.WebGLRenderer} renderer -The renderer sprite this batch works for.
     */
    constructor(renderer)
    {
        this.renderer = renderer;
    }

    /**
     * Renders the sprite object.
     *
     * @param {PIXI.Sprite} sprite - the sprite to render when using this spritebatch
     */
    render(sprite)
    {
        const texture = sprite._texture;
        const renderer = this.renderer;

        const width = texture._frame.width;
        const height = texture._frame.height;

        let wt = sprite.transform.worldTransform;
        let dx = 0;
        let dy = 0;

        if (texture.orig.width <= 0 || texture.orig.height <= 0 || !texture.baseTexture.source)
        {
            return;
        }

        renderer.setBlendMode(sprite.blendMode);

        //  Ignore null sources
        if (texture.valid)
        {
            renderer.context.globalAlpha = sprite.worldAlpha;

            // If smoothingEnabled is supported and we need to change the smoothing property for sprite texture
            const smoothingEnabled = texture.baseTexture.scaleMode === SCALE_MODES.LINEAR;

            if (renderer.smoothProperty && renderer.context[renderer.smoothProperty] !== smoothingEnabled)
            {
                renderer.context[renderer.smoothProperty] = smoothingEnabled;
            }

            if (texture.trim)
            {
                dx = (texture.trim.width / 2) + texture.trim.x - (sprite.anchor.x * texture.orig.width);
                dy = (texture.trim.height / 2) + texture.trim.y - (sprite.anchor.y * texture.orig.height);
            }
            else
            {
                dx = (0.5 - sprite.anchor.x) * texture.orig.width;
                dy = (0.5 - sprite.anchor.y) * texture.orig.height;
            }

            if (texture.rotate)
            {
                wt.copy(canvasRenderWorldTransform);
                wt = canvasRenderWorldTransform;
                GroupD8.matrixAppendRotationInv(wt, texture.rotate, dx, dy);
                // the anchor has already been applied above, so lets set it to zero
                dx = 0;
                dy = 0;
            }

            dx -= texture.orig.width / 2;
            dy -= texture.orig.height / 2;

            // Allow for pixel rounding
            if (renderer.roundPixels)
            {
                renderer.context.setTransform(
                    wt.a,
                    wt.b,
                    wt.c,
                    wt.d,
                    (wt.tx * renderer.resolution) | 0,
                    (wt.ty * renderer.resolution) | 0
                );

                dx = dx | 0;
                dy = dy | 0;
            }
            else
            {
                renderer.context.setTransform(
                    wt.a,
                    wt.b,
                    wt.c,
                    wt.d,
                    wt.tx * renderer.resolution,
                    wt.ty * renderer.resolution
                );
            }

            const resolution = texture.baseTexture.resolution;

            if (sprite.tint !== 0xFFFFFF)
            {
                if (sprite.cachedTint !== sprite.tint || sprite.tintedTexture.tintId !== sprite._texture._updateID)
                {
                    sprite.cachedTint = sprite.tint;

                    // TODO clean up caching - how to clean up the caches?
                    sprite.tintedTexture = CanvasTinter.getTintedTexture(sprite, sprite.tint);
                }

                renderer.context.drawImage(
                    sprite.tintedTexture,
                    0,
                    0,
                    width * resolution,
                    height * resolution,
                    dx * renderer.resolution,
                    dy * renderer.resolution,
                    texture.orig.width * renderer.resolution,
                    texture.orig.height * renderer.resolution
                );
            }
            else
            {
                renderer.context.drawImage(
                    texture.baseTexture.source,
                    texture._frame.x * resolution,
                    texture._frame.y * resolution,
                    width * resolution,
                    height * resolution,
                    dx * renderer.resolution,
                    dy * renderer.resolution,
                    texture.orig.width * renderer.resolution,
                    texture.orig.height * renderer.resolution
                );
            }
        }
    }

    /**
     * destroy the sprite object.
     *
     */
    destroy()
    {
        this.renderer = null;
    }
}

CanvasRenderer.registerPlugin('sprite', CanvasSpriteRenderer);
<|endoftext|>


<commit_before>asynctest(
  'browser.tinymce.core.fmt.PreviewTest',
  [
    'ephox.agar.api.Assertions',
    'ephox.agar.api.Pipeline',
    'ephox.agar.api.Step',
    'ephox.agar.api.Waiter',
    'ephox.katamari.api.Arr',
    'ephox.mcagar.api.LegacyUnit',
    'ephox.mcagar.api.TinyLoader',
    'tinymce.core.fmt.Preview',
    'tinymce.core.test.HtmlUtils',
    'tinymce.themes.modern.Theme'
  ],
  function (Assertions, Pipeline, Step, Waiter, Arr, LegacyUnit, TinyLoader, Preview, HtmlUtils, Theme) {
    var success = arguments[arguments.length - 2];
    var failure = arguments[arguments.length - 1];
    var suite = LegacyUnit.createSuite();

    Theme();

    var ok = function (value, label) {
      return LegacyUnit.equal(value, true, label);
    };

    var previewStyles = function () {
      return (
        'table .preview {' +
          'color: rgb(0, 255, 0);' + // green
        '}' +

        'ol .preview {' +
          'color: rgb(0, 0, 255);' + // blue
        '}' +

        '.preview {' +
          'color: rgb(255, 0, 0);' + // red
        '}'
      );
    };

    suite.test('Get preview css text for formats', function (editor) {
      var getCssText = function (format) {
        return Preview.getCssText(editor, format);
      };

      ok(/font-weight\:(bold|700)/.test(getCssText('bold')),
        'Bold not found in preview style');

      ok(/font-weight\:(bold|700)/.test(getCssText({ inline: 'b' })),
        'Bold not found in preview style');

      ok(!/font-weight\:(bold|700)/.test(getCssText({ inline: 'b', preview: 'font-size' })),
        'Bold should not be when we only preview font-size');

      ok(/color\:rgb\(255, 0, 0\)/.test(getCssText({ inline: 'custom', styles: { color: '#ff0000' } })),
        'Test preview of a custom element.');

      ok(/color\:rgb\(0, 255, 0\)/.test(getCssText({ selector: 'tr', classes: ['preview'] })),
        'Style is properly inherited in preview for partial element (like TR).');

      ok(/color\:rgb\(255, 0, 0\)/.test(getCssText({ selector: 'li', classes: ['preview'] })),
        'For LI element default required parent is UL.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({ selector: 'ol li', classes: ['preview'] })),
        'Parent explicitly present in the selector will have preference.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({ selector: 'ol > li', classes: ['preview'] })),
        'ol > li previewed properly.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({
        selector: 'ol.someClass > li#someId[title="someTitle"]',
        classes: ['preview']
      })),
        'ol.someClass > li#someId[title="someTitle"] previewed properly.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({
        selector: 'ul + ol.someClass > li#someId',
        classes: ['preview']
      })),
        'ul + ol.someClass > li#someId previewed properly.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({ selector: 'ul li ol li', classes: ['preview'] })),
        'ul li ol li previewed properly.');
    });

    suite.test('Preview.parseSelector()', function () {
      LegacyUnit.deepEqual(Preview.parseSelector('li.class1.class2#id1[attr1="1"]:disabled'), [
        {
          name: 'li',
          selector: 'li.class1.class2#id1[attr1="1"]:disabled',
          classes: ['class1', 'class2'],
          attrs: {
            id: 'id1',
            attr1: '1',
            disabled: 'disabled'
          }
        }
      ], 'li.class1.class2#id1 ok');

      LegacyUnit.deepEqual(Preview.parseSelector('ul.parent1 > li.class1.class2#id1'), [
        {
          name: 'li',
          selector: 'li.class1.class2#id1',
          classes: ['class1', 'class2'],
          attrs: {
            id: 'id1'
          }
        },
        {
          name: 'ul',
          selector: 'ul.parent1',
          classes: ['parent1'],
          attrs: {}
        }
      ], 'ul.parent1 > li.class1.class2#id1 ok');

      LegacyUnit.deepEqual(Preview.parseSelector('div.class1 > ol.class2 + ul > li:hover'), [
        {
          name: 'li',
          selector: 'li:hover',
          classes: [],
          attrs: {}
        },
        {
          name: 'ul',
          selector: 'ul',
          classes: [],
          attrs: {},
          siblings: [
            {
              name: 'ol',
              selector: 'ol.class2',
              classes: ['class2'],
              attrs: {}
            }
          ]
        },
        {
          name: 'div',
          selector: 'div.class1',
          classes: ['class1'],
          attrs: {}
        }
      ], 'div.class1 > ol.class2 + ul > li:hover ok');

      LegacyUnit.deepEqual(Preview.parseSelector('.class > *'), [
        {
          name: "div",
          selector: "*",
          attrs: {},
          classes: []
        },
        {
          name: "div",
          selector: ".class",
          classes: ["class"],
          attrs: {}
        }
      ], '.class > * ok');

      LegacyUnit.deepEqual(Preview.parseSelector('p + *'), [
        {
          name: "div",
          selector: "*",
          attrs: {},
          classes: [],
          siblings: [
            {
              name: "p",
              selector: "p",
              attrs: {},
              classes: []
            }
          ]
        }
      ], 'p + * ok');

      LegacyUnit.deepEqual(Preview.parseSelector('*.test'), [
        {
          name: "*",
          selector: "*.test",
          attrs: {},
          classes: ['test']
        }
      ], '*.test ok');
    });

    suite.test('Preview.selectorToHtml()', function () {
      var trimSpaces = function (str) {
        return str.replace(/>\s+</g, '><').replace(/^\s*|\s*$/g, '');
      };

      var selectorToHtml = function (selector) {
        return HtmlUtils.normalizeHtml(Preview.selectorToHtml(selector).outerHTML);
      };

      LegacyUnit.equal(selectorToHtml('ul > li.class1'), trimSpaces([
        '
',
        '
',
        '

',
        '
',
        '
'
      ].join('')), 'ul > li.class1 ok');

      LegacyUnit.equal(selectorToHtml('ol + ul#id1 > li.class1[title="Some Title"]'), trimSpaces([
        '
',
        '
',
        '

',
        '
',
        '

',
        '
',
        '
',
        '
'
      ].join('')), 'ol + ul#id1 > li.class1[title="Some Title"] ok');

      LegacyUnit.equal(selectorToHtml('tr > th + td'), trimSpaces([
        '
',
        '
',
        '
',
        '
',
        '	',
        '	',
        '
',
        '
',
        '
',
        '
'
      ].join('')), 'tr > th + td (required parental structure properly rebuilt) ok');

      LegacyUnit.equal(selectorToHtml('p li[title="Some Title"][alt="Some Alt"]'), trimSpaces([
        '
',
        '
',
        '
',
        '

',
        '
',
        '
',
        '
'
      ].join('')), 'p li[title="Some Title"][alt="Some Alt"] (test multiple spaced attributes) ok');
    });

    TinyLoader.setup(function (editor, onSuccess, onFailure) {
      Pipeline.async({}, Arr.flatten([
        [
          Step.sync(function () {
            editor.setContent('
x
');
          }),
          Waiter.sTryUntil(
            'Expected styles where not loaded',
            Step.sync(function () {
              var color = editor.dom.getStyle(editor.dom.select('p'), 'color', true);
              Assertions.assertEq('Did not get a color value of 255', true, color.indexOf('255') !== -1);
            }
          ), 10, 3000)
        ],
        suite.toSteps(editor)
      ]), onSuccess, onFailure);
    }, {
      selector: "textarea",
      add_unload_trigger: false,
      disable_nodechange: true,
      custom_elements: '~custom',
      extended_valid_elements: 'custom',
      entities: 'raw',
      indent: false,
      content_style: previewStyles(),
      skin_url: '/project/src/skins/lightgray/dist/lightgray'
    }, success, failure);
  }
);<commit_msg>TINY-1058: add test<commit_after>asynctest(
  'browser.tinymce.core.fmt.PreviewTest',
  [
    'ephox.agar.api.Assertions',
    'ephox.agar.api.Pipeline',
    'ephox.agar.api.Step',
    'ephox.agar.api.Waiter',
    'ephox.katamari.api.Arr',
    'ephox.mcagar.api.LegacyUnit',
    'ephox.mcagar.api.TinyLoader',
    'tinymce.core.fmt.Preview',
    'tinymce.core.test.HtmlUtils',
    'tinymce.themes.modern.Theme'
  ],
  function (Assertions, Pipeline, Step, Waiter, Arr, LegacyUnit, TinyLoader, Preview, HtmlUtils, Theme) {
    var success = arguments[arguments.length - 2];
    var failure = arguments[arguments.length - 1];
    var suite = LegacyUnit.createSuite();

    Theme();

    var ok = function (value, label) {
      return LegacyUnit.equal(value, true, label);
    };

    var previewStyles = function () {
      return (
        'table .preview {' +
          'color: rgb(0, 255, 0);' + // green
        '}' +

        'ol .preview {' +
          'color: rgb(0, 0, 255);' + // blue
        '}' +

        '.preview {' +
          'color: rgb(255, 0, 0);' + // red
        '}'
      );
    };

    suite.test('Get preview css text for formats', function (editor) {
      var getCssText = function (format) {
        return Preview.getCssText(editor, format);
      };

      ok(/font-weight\:(bold|700)/.test(getCssText('bold')),
        'Bold not found in preview style');

      ok(/font-weight\:(bold|700)/.test(getCssText({ inline: 'b' })),
        'Bold not found in preview style');

      ok(!/font-weight\:(bold|700)/.test(getCssText({ inline: 'b', preview: 'font-size' })),
        'Bold should not be when we only preview font-size');

      ok(/color\:rgb\(255, 0, 0\)/.test(getCssText({ inline: 'custom', styles: { color: '#ff0000' } })),
        'Test preview of a custom element.');

      ok(/color\:rgb\(255, 0, 0\)/.test(getCssText({ inline: 'invalid', styles: { color: '#ff0000' } })),
        "Test preview of an invalid element shouldn't crash the editor .");

      ok(/color\:rgb\(0, 255, 0\)/.test(getCssText({ selector: 'tr', classes: ['preview'] })),
        'Style is properly inherited in preview for partial element (like TR).');

      ok(/color\:rgb\(255, 0, 0\)/.test(getCssText({ selector: 'li', classes: ['preview'] })),
        'For LI element default required parent is UL.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({ selector: 'ol li', classes: ['preview'] })),
        'Parent explicitly present in the selector will have preference.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({ selector: 'ol > li', classes: ['preview'] })),
        'ol > li previewed properly.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({
        selector: 'ol.someClass > li#someId[title="someTitle"]',
        classes: ['preview']
      })),
        'ol.someClass > li#someId[title="someTitle"] previewed properly.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({
        selector: 'ul + ol.someClass > li#someId',
        classes: ['preview']
      })),
        'ul + ol.someClass > li#someId previewed properly.');

      ok(/color\:rgb\(0, 0, 255\)/.test(getCssText({ selector: 'ul li ol li', classes: ['preview'] })),
        'ul li ol li previewed properly.');
    });

    suite.test('Preview.parseSelector()', function () {
      LegacyUnit.deepEqual(Preview.parseSelector('li.class1.class2#id1[attr1="1"]:disabled'), [
        {
          name: 'li',
          selector: 'li.class1.class2#id1[attr1="1"]:disabled',
          classes: ['class1', 'class2'],
          attrs: {
            id: 'id1',
            attr1: '1',
            disabled: 'disabled'
          }
        }
      ], 'li.class1.class2#id1 ok');

      LegacyUnit.deepEqual(Preview.parseSelector('ul.parent1 > li.class1.class2#id1'), [
        {
          name: 'li',
          selector: 'li.class1.class2#id1',
          classes: ['class1', 'class2'],
          attrs: {
            id: 'id1'
          }
        },
        {
          name: 'ul',
          selector: 'ul.parent1',
          classes: ['parent1'],
          attrs: {}
        }
      ], 'ul.parent1 > li.class1.class2#id1 ok');

      LegacyUnit.deepEqual(Preview.parseSelector('div.class1 > ol.class2 + ul > li:hover'), [
        {
          name: 'li',
          selector: 'li:hover',
          classes: [],
          attrs: {}
        },
        {
          name: 'ul',
          selector: 'ul',
          classes: [],
          attrs: {},
          siblings: [
            {
              name: 'ol',
              selector: 'ol.class2',
              classes: ['class2'],
              attrs: {}
            }
          ]
        },
        {
          name: 'div',
          selector: 'div.class1',
          classes: ['class1'],
          attrs: {}
        }
      ], 'div.class1 > ol.class2 + ul > li:hover ok');

      LegacyUnit.deepEqual(Preview.parseSelector('.class > *'), [
        {
          name: "div",
          selector: "*",
          attrs: {},
          classes: []
        },
        {
          name: "div",
          selector: ".class",
          classes: ["class"],
          attrs: {}
        }
      ], '.class > * ok');

      LegacyUnit.deepEqual(Preview.parseSelector('p + *'), [
        {
          name: "div",
          selector: "*",
          attrs: {},
          classes: [],
          siblings: [
            {
              name: "p",
              selector: "p",
              attrs: {},
              classes: []
            }
          ]
        }
      ], 'p + * ok');

      LegacyUnit.deepEqual(Preview.parseSelector('*.test'), [
        {
          name: "*",
          selector: "*.test",
          attrs: {},
          classes: ['test']
        }
      ], '*.test ok');
    });

    suite.test('Preview.selectorToHtml()', function () {
      var trimSpaces = function (str) {
        return str.replace(/>\s+</g, '><').replace(/^\s*|\s*$/g, '');
      };

      var selectorToHtml = function (selector) {
        return HtmlUtils.normalizeHtml(Preview.selectorToHtml(selector).outerHTML);
      };

      LegacyUnit.equal(selectorToHtml('ul > li.class1'), trimSpaces([
        '
',
        '
',
        '

',
        '
',
        '
'
      ].join('')), 'ul > li.class1 ok');

      LegacyUnit.equal(selectorToHtml('ol + ul#id1 > li.class1[title="Some Title"]'), trimSpaces([
        '
',
        '
',
        '

',
        '
',
        '

',
        '
',
        '
',
        '
'
      ].join('')), 'ol + ul#id1 > li.class1[title="Some Title"] ok');

      LegacyUnit.equal(selectorToHtml('tr > th + td'), trimSpaces([
        '
',
        '
',
        '
',
        '
',
        '	',
        '	',
        '
',
        '
',
        '
',
        '
'
      ].join('')), 'tr > th + td (required parental structure properly rebuilt) ok');

      LegacyUnit.equal(selectorToHtml('p li[title="Some Title"][alt="Some Alt"]'), trimSpaces([
        '
',
        '
',
        '
',
        '

',
        '
',
        '
',
        '
'
      ].join('')), 'p li[title="Some Title"][alt="Some Alt"] (test multiple spaced attributes) ok');
    });

    TinyLoader.setup(function (editor, onSuccess, onFailure) {
      Pipeline.async({}, Arr.flatten([
        [
          Step.sync(function () {
            editor.setContent('
x
');
          }),
          Waiter.sTryUntil(
            'Expected styles where not loaded',
            Step.sync(function () {
              var color = editor.dom.getStyle(editor.dom.select('p'), 'color', true);
              Assertions.assertEq('Did not get a color value of 255', true, color.indexOf('255') !== -1);
            }
          ), 10, 3000)
        ],
        suite.toSteps(editor)
      ]), onSuccess, onFailure);
    }, {
      selector: "textarea",
      add_unload_trigger: false,
      disable_nodechange: true,
      custom_elements: '~custom',
      extended_valid_elements: 'custom',
      entities: 'raw',
      indent: false,
      content_style: previewStyles(),
      skin_url: '/project/src/skins/lightgray/dist/lightgray'
    }, success, failure);
  }
);<|endoftext|>


<commit_before>(function() {

	var app = angular.module('app.projectSettingsCtrl', []);

	app.controller('app.projectSettingsCtrl', ['$scope', '$location', '$routeParams', 'app.appFactory', 'ndb_users.userFactory', 'app.dataFactory', function($scope, $location, $routeParams, appFactory, userFactory, dataFactory) {

		// Perform setup and reset $scope variables...
		$scope.init = function() {
			console.log('[app.projectSettingsCtrl] $scope.init(): call');
			appFactory.config({
				pageTitle: 'Project',
				navbar: {
					title: 'Loading...',
					link: '/projects/' + $routeParams.projectId
				}, sidebar: {
					selection: $routeParams.projectId
				}, projectsNav: {
					selection: 'settings'
				}
			});

			$scope.projectId = $routeParams.projectId;

			$scope.user = {};
			$scope.userLoaded = false;

			$scope.project = {};
			$scope.projectLoaded = true;

			$scope.projectDescriptionPreview = false;

			userFactory.user().then(function(response) {
				$scope.userLoaded = true;
				if (!response.error) {
					$scope.user = response;

					// Redirect if not logged in
					if (!response.email) {
						$location.path('/login');
					}

					dataFactory.project($scope.projectId).then(function(response) {
						$scope.projectLoaded = true;
						if (!response.error) {
							// Success
							$scope.project = response;

							// Copy variables we'll be editing...
							$scope.project._name = angular.copy(response.name);
							$scope.project._description = angular.copy(response.description);

							appFactory.config({
								pageTitle: 'Settings: ' + response.name,
								navbar: {
									title: response.name
								}, sidebar: {
									selection: response.id
								}
							});
						} else {
							// Error
						}
					});
				} else {
					alert('Error loading User.');
				}
			});
		};

		$scope.save = function() {
			console.log('[app.projectSettingsCtrl] $scope.save(): called');
			$scope.projectLoaded = false;
			dataFactory.updateProject($scope.project).then(function(response) {
				$scope.projectLoaded = true;
				if (!response.error) {
					$location.path('/projects/'+response.id);
				} else {
					alert('Error creating project.');
				}
			});
		};

		// Init
		$scope.init();
	}]);

})();<commit_msg>Replaced text for consistency with other Controllers<commit_after>(function() {

	var app = angular.module('app.projectSettingsCtrl', []);

	app.controller('app.projectSettingsCtrl', ['$scope', '$location', '$routeParams', 'app.appFactory', 'ndb_users.userFactory', 'app.dataFactory', function($scope, $location, $routeParams, appFactory, userFactory, dataFactory) {

		// Perform setup and reset $scope variables...
		$scope.init = function() {
			console.log('[app.projectSettingsCtrl] $scope.init(): call');
			appFactory.config({
				pageTitle: 'Loading...',
				navbar: {
					title: 'Loading...',
					link: '/projects/' + $routeParams.projectId
				}, sidebar: {
					selection: $routeParams.projectId
				}, projectsNav: {
					selection: 'settings'
				}
			});

			$scope.projectId = $routeParams.projectId;

			$scope.user = {};
			$scope.userLoaded = false;

			$scope.project = {};
			$scope.projectLoaded = true;

			$scope.projectDescriptionPreview = false;

			userFactory.user().then(function(response) {
				$scope.userLoaded = true;
				if (!response.error) {
					$scope.user = response;

					// Redirect if not logged in
					if (!response.email) {
						$location.path('/login');
					}

					dataFactory.project($scope.projectId).then(function(response) {
						$scope.projectLoaded = true;
						if (!response.error) {
							// Success
							$scope.project = response;

							// Copy variables we'll be editing...
							$scope.project._name = angular.copy(response.name);
							$scope.project._description = angular.copy(response.description);

							appFactory.config({
								pageTitle: 'Settings: ' + response.name,
								navbar: {
									title: response.name
								}, sidebar: {
									selection: response.id
								}
							});
						} else {
							// Error
						}
					});
				} else {
					alert('Error loading User.');
				}
			});
		};

		$scope.save = function() {
			console.log('[app.projectSettingsCtrl] $scope.save(): called');
			$scope.projectLoaded = false;
			dataFactory.updateProject($scope.project).then(function(response) {
				$scope.projectLoaded = true;
				if (!response.error) {
					$location.path('/projects/'+response.id);
				} else {
					alert('Error creating project.');
				}
			});
		};

		// Init
		$scope.init();
	}]);

})();<|endoftext|>


<commit_before>(function () {
    angular
        .module('dpShared')
        .constant('ACTIONS', {
            URL_CHANGE: 'URL_CHANGE',

            SHOW_SEARCH_RESULTS_BY_QUERY: 'SHOW_SEARCH_RESULTS_BY_QUERY',
            SHOW_SEARCH_RESULTS_BY_CLICK: 'SHOW_SEARCH_RESULTS_BY_CLICK',
            SHOW_SEARCH_RESULTS_CATEGORY: 'SHOW_SEARCH_RESULTS_CATEGORY',

            MAP_SET_BASELAYER: 'MAP_SET_BASELAYER',
            MAP_ADD_OVERLAY: 'MAP_ADD_OVERLAY',
            MAP_REMOVE_OVERLAY: 'MAP_REMOVE_OVERLAY',
            MAP_PAN: 'MAP_PAN',
            MAP_ZOOM: 'MAP_ZOOM',
            MAP_FULLSCREEN: 'MAP_FULLSCREEN',

            FETCH_DETAIL: 'FETCH_DETAIL',
            SHOW_DETAIL: 'SHOW_DETAIL',

            FETCH_STRAATBEELD: 'FETCH_STRAATBEELD',
            SHOW_STRAATBEELD_INITIAL: 'SHOW_STRAATBEELD_INITIAL',
            SHOW_STRAATBEELD_SUBSEQUENT: 'SHOW_STRAATBEELD_SUBSEQUENT',
            STRAATBEELD_SET_ORIENTATION: 'STRAATBEELD_SET_ORIENTATION',

            SHOW_DATA_SELECTION: 'SHOW_DATA_SELECTION',
            NAVIGATE_DATA_SELECTION: 'SHOW_DATA_SELECTION',

            SHOW_LAYER_SELECTION: 'SHOW_LAYER_SELECTION',
            HIDE_LAYER_SELECTION: 'HIDE_LAYER_SELECTION',

            SHOW_HOME: 'SHOW_HOME',
            SHOW_PAGE: 'SHOW_PAGE',

            SHOW_PRINT: 'SHOW_PRINT',
            HIDE_PRINT: 'HIDE_PRINT'
        });
})();
<commit_msg>Fixed ACTION name.<commit_after>(function () {
    angular
        .module('dpShared')
        .constant('ACTIONS', {
            URL_CHANGE: 'URL_CHANGE',

            SHOW_SEARCH_RESULTS_BY_QUERY: 'SHOW_SEARCH_RESULTS_BY_QUERY',
            SHOW_SEARCH_RESULTS_BY_CLICK: 'SHOW_SEARCH_RESULTS_BY_CLICK',
            SHOW_SEARCH_RESULTS_CATEGORY: 'SHOW_SEARCH_RESULTS_CATEGORY',

            MAP_SET_BASELAYER: 'MAP_SET_BASELAYER',
            MAP_ADD_OVERLAY: 'MAP_ADD_OVERLAY',
            MAP_REMOVE_OVERLAY: 'MAP_REMOVE_OVERLAY',
            MAP_PAN: 'MAP_PAN',
            MAP_ZOOM: 'MAP_ZOOM',
            MAP_FULLSCREEN: 'MAP_FULLSCREEN',

            FETCH_DETAIL: 'FETCH_DETAIL',
            SHOW_DETAIL: 'SHOW_DETAIL',

            FETCH_STRAATBEELD: 'FETCH_STRAATBEELD',
            SHOW_STRAATBEELD_INITIAL: 'SHOW_STRAATBEELD_INITIAL',
            SHOW_STRAATBEELD_SUBSEQUENT: 'SHOW_STRAATBEELD_SUBSEQUENT',
            STRAATBEELD_SET_ORIENTATION: 'STRAATBEELD_SET_ORIENTATION',

            SHOW_DATA_SELECTION: 'SHOW_DATA_SELECTION',
            NAVIGATE_DATA_SELECTION: 'NAVIGATE_DATA_SELECTION',

            SHOW_LAYER_SELECTION: 'SHOW_LAYER_SELECTION',
            HIDE_LAYER_SELECTION: 'HIDE_LAYER_SELECTION',

            SHOW_HOME: 'SHOW_HOME',
            SHOW_PAGE: 'SHOW_PAGE',

            SHOW_PRINT: 'SHOW_PRINT',
            HIDE_PRINT: 'HIDE_PRINT'
        });
})();
<|endoftext|>


<commit_before>/* @flow */
/**
 * @jsx React.DOM

 */
"use strict";

var React               = require('react');
var joinClasses          = require('classnames');
var shallowCloneObject  = require('./shallowCloneObject');
var ColumnMetrics       = require('./ColumnMetrics');
var HeaderRow           = require('./HeaderRow');

type Column = {
  width: number
}

var Header = React.createClass({
  propTypes: {
    columnMetrics: React.PropTypes.shape({  width: React.PropTypes.number.isRequired }).isRequired,
    totalWidth: React.PropTypes.number,
    height: React.PropTypes.number.isRequired,
    headerRows : React.PropTypes.array.isRequired
  },

  render(): ?ReactElement {
    var state = this.state.resizing || this.props;

    var className = joinClasses({
      'react-grid-Header': true,
      'react-grid-Header--resizing': !!this.state.resizing
    });
    var headerRows = this.getHeaderRows();

    return (

      <div {...this.props} style={this.getStyle()} className={className}>
        {headerRows}
      </div>
    );
  },

  shouldComponentUpdate : function(nextProps: any, nextState: any): boolean{
    var update =  !(ColumnMetrics.sameColumns(this.props.columnMetrics.columns, nextProps.columnMetrics.columns, ColumnMetrics.sameColumn))
    || this.props.totalWidth != nextProps.totalWidth
    || (this.props.headerRows.length != nextProps.headerRows.length)
    || (this.state.resizing != nextState.resizing)
    || this.props.sortColumn != nextProps.sortColumn
    || this.props.sortDirection != nextProps.sortDirection;
    return update;
  },

  getHeaderRows(): Array<HeaderRow>{
    var columnMetrics = this.getColumnMetrics();
    var resizeColumn;
    if(this.state.resizing){
      resizeColumn = this.state.resizing.column;
    }
    var headerRows = [];
    this.props.headerRows.forEach((function(row, index){
      var headerRowStyle = {
        position: 'absolute',
        top: this.props.height * index,
        left: 0,
        width: this.props.totalWidth,
        overflow : 'hidden'
      };

      headerRows.push(<HeaderRow
        key={row.ref}
        ref={row.ref}
        style={headerRowStyle}
        onColumnResize={this.onColumnResize}
        onColumnResizeEnd={this.onColumnResizeEnd}
        width={columnMetrics.width}
        height={row.height || this.props.height}
        columns={columnMetrics.columns}
        resizing={resizeColumn}
        headerCellRenderer={row.headerCellRenderer}
        sortColumn={this.props.sortColumn}
        sortDirection={this.props.sortDirection}
        onSort={this.props.onSort}
        />)
    }).bind(this));
    return headerRows;
  },

  getInitialState(): {resizing: any} {
    return {resizing: null};
  },

  componentWillReceiveProps(nextProps: any) {
    this.setState({resizing: null});
  },

  onColumnResize(column: Column, width: number) {
    var state = this.state.resizing || this.props;

    var pos = this.getColumnPosition(column);

    if (pos != null) {
      var resizing = {
        columnMetrics: shallowCloneObject(state.columnMetrics)
      };
      resizing.columnMetrics = ColumnMetrics.resizeColumn(
          resizing.columnMetrics, pos, width);

      // we don't want to influence scrollLeft while resizing
      if (resizing.columnMetrics.totalWidth < state.columnMetrics.totalWidth) {
        resizing.columnMetrics.totalWidth = state.columnMetrics.totalWidth;
      }

      resizing.column = resizing.columnMetrics.columns[pos];
      this.setState({resizing});
    }
  },

  getColumnMetrics() {
    var columnMetrics;
    if(this.state.resizing){
      columnMetrics = this.state.resizing.columnMetrics;
    }else{
      columnMetrics = this.props.columnMetrics;
    }
    return columnMetrics;
  },

  getColumnPosition(column: Column): ?number {
    var columnMetrics = this.getColumnMetrics();
    var pos = -1;
    columnMetrics.columns.forEach((c,idx) => {
      if(c.key === column.key){
        pos = idx;
      }
    });
    return pos === -1 ? null : pos;
  },

  onColumnResizeEnd(column: Column, width: number) {
    var pos = this.getColumnPosition(column);
    if (pos !== null && this.props.onColumnResize) {
      this.props.onColumnResize(pos, width || column.width);
    }
  },

  setScrollLeft(scrollLeft: number) {
    var node = this.refs.row.getDOMNode();
    node.scrollLeft = scrollLeft;
    this.refs.row.setScrollLeft(scrollLeft);
  },

  getStyle(): {position: string; height: number} {
    return {
      position: 'relative',
      height: this.props.height * this.props.headerRows.length,
      overflow : 'hidden'
    };
  },
});

module.exports = Header;
<commit_msg>use columnUtils to getColumn<commit_after>/* @flow */
/**
 * @jsx React.DOM

 */
"use strict";

var React               = require('react');
var joinClasses          = require('classnames');
var shallowCloneObject  = require('./shallowCloneObject');
var ColumnMetrics       = require('./ColumnMetrics');
var ColumnUtils         = require('./ColumnUtils');
var HeaderRow           = require('./HeaderRow');

type Column = {
  width: number
}

var Header = React.createClass({
  propTypes: {
    columnMetrics: React.PropTypes.shape({  width: React.PropTypes.number.isRequired }).isRequired,
    totalWidth: React.PropTypes.number,
    height: React.PropTypes.number.isRequired,
    headerRows : React.PropTypes.array.isRequired
  },

  render(): ?ReactElement {
    var state = this.state.resizing || this.props;

    var className = joinClasses({
      'react-grid-Header': true,
      'react-grid-Header--resizing': !!this.state.resizing
    });
    var headerRows = this.getHeaderRows();

    return (

      <div {...this.props} style={this.getStyle()} className={className}>
        {headerRows}
      </div>
    );
  },

  shouldComponentUpdate : function(nextProps: any, nextState: any): boolean{
    var update =  !(ColumnMetrics.sameColumns(this.props.columnMetrics.columns, nextProps.columnMetrics.columns, ColumnMetrics.sameColumn))
    || this.props.totalWidth != nextProps.totalWidth
    || (this.props.headerRows.length != nextProps.headerRows.length)
    || (this.state.resizing != nextState.resizing)
    || this.props.sortColumn != nextProps.sortColumn
    || this.props.sortDirection != nextProps.sortDirection;
    return update;
  },

  getHeaderRows(): Array<HeaderRow>{
    var columnMetrics = this.getColumnMetrics();
    var resizeColumn;
    if(this.state.resizing){
      resizeColumn = this.state.resizing.column;
    }
    var headerRows = [];
    this.props.headerRows.forEach((function(row, index){
      var headerRowStyle = {
        position: 'absolute',
        top: this.props.height * index,
        left: 0,
        width: this.props.totalWidth,
        overflow : 'hidden'
      };

      headerRows.push(<HeaderRow
        key={row.ref}
        ref={row.ref}
        style={headerRowStyle}
        onColumnResize={this.onColumnResize}
        onColumnResizeEnd={this.onColumnResizeEnd}
        width={columnMetrics.width}
        height={row.height || this.props.height}
        columns={columnMetrics.columns}
        resizing={resizeColumn}
        headerCellRenderer={row.headerCellRenderer}
        sortColumn={this.props.sortColumn}
        sortDirection={this.props.sortDirection}
        onSort={this.props.onSort}
        />)
    }).bind(this));
    return headerRows;
  },

  getInitialState(): {resizing: any} {
    return {resizing: null};
  },

  componentWillReceiveProps(nextProps: any) {
    this.setState({resizing: null});
  },

  onColumnResize(column: Column, width: number) {
    var state = this.state.resizing || this.props;

    var pos = this.getColumnPosition(column);

    if (pos != null) {
      var resizing = {
        columnMetrics: shallowCloneObject(state.columnMetrics)
      };
      resizing.columnMetrics = ColumnMetrics.resizeColumn(
          resizing.columnMetrics, pos, width);

      // we don't want to influence scrollLeft while resizing
      if (resizing.columnMetrics.totalWidth < state.columnMetrics.totalWidth) {
        resizing.columnMetrics.totalWidth = state.columnMetrics.totalWidth;
      }

      resizing.column = ColumnUtils.getColumn(resizing.columnMetrics.columns, pos);
      this.setState({resizing});
    }
  },

  getColumnMetrics() {
    var columnMetrics;
    if(this.state.resizing){
      columnMetrics = this.state.resizing.columnMetrics;
    }else{
      columnMetrics = this.props.columnMetrics;
    }
    return columnMetrics;
  },

  getColumnPosition(column: Column): ?number {
    var columnMetrics = this.getColumnMetrics();
    var pos = -1;
    columnMetrics.columns.forEach((c,idx) => {
      if(c.key === column.key){
        pos = idx;
      }
    });
    return pos === -1 ? null : pos;
  },

  onColumnResizeEnd(column: Column, width: number) {
    var pos = this.getColumnPosition(column);
    if (pos !== null && this.props.onColumnResize) {
      this.props.onColumnResize(pos, width || column.width);
    }
  },

  setScrollLeft(scrollLeft: number) {
    var node = this.refs.row.getDOMNode();
    node.scrollLeft = scrollLeft;
    this.refs.row.setScrollLeft(scrollLeft);
  },

  getStyle(): {position: string; height: number} {
    return {
      position: 'relative',
      height: this.props.height * this.props.headerRows.length,
      overflow : 'hidden'
    };
  },
});

module.exports = Header;
<|endoftext|>


<commit_before>import React from 'react';
import { Navbar, Nav, NavDropdown, MenuItem } from 'react-bootstrap';
import AboutDialog from './dialogs/AboutDialog.js';
import BenchmarkDialog from './dialogs/BenchmarkDialog.js';
import AuthorDialog from './dialogs/AuthorDialog.js';
import ThanksDialog from './dialogs/ThanksDialog.js';

class Header extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            showAbout: false,
            showBenchmark: false,
            showAuthor: false,
            showThanks: false
        };
    }
    openInfo(key) {
        if (key) {
            if (key === 'about') {
                this.openAbout();
            } else if (key === 'benchmark') {
                this.openBenchmark();
            } else if (key === 'author') {
                this.openAuthor();
            } else if (key === 'favicon') {
                this.openFavicon();
            }
        }
    }
    openAbout() {
        this.setState({ showAbout: true });
    }
    closeAbout() {
        this.setState({ showAbout: false });
    }
    openBenchmark() {
        this.setState({ showBenchmark: true });
    }
    closeBenchmark() {
        this.setState({ showBenchmark: false });
    }
    openAuthor() {
        this.setState({ showAuthor: true });
    }
    closeAuthor() {
        this.setState({ showAuthor: false });
    }
    openFavicon() {
        this.setState({ showThanks: true });
    }
    closeFavicon() {
        this.setState({ showThanks: false });
    }

    render() {
        return (
            <Navbar inverse collapseOnSelect>
                <Navbar.Header>
                    <Navbar.Brand>
                        Quick C++ Benchmark
                    </Navbar.Brand>
                    <Navbar.Toggle />
                </Navbar.Header>
                <Navbar.Collapse>

                        <NavDropdown title="Support Quick Bench" id="basic-nav-dropdown">
                            <MenuItem href="https://www.patreon.com/bePatron?u=8599781" target="_blank"> Support on Patreon</MenuItem>
                        </NavDropdown>
                        <NavDropdown title="More" id="basic-nav-dropdown" onSelect={this.openInfo.bind(this)}>
                            <MenuItem eventKey="about">About Quick-bench</MenuItem>
                            <MenuItem eventKey="benchmark">How to write my benchmarks</MenuItem>
                            <MenuItem divider />
                            <MenuItem href="https://github.com/FredTingaud/quick-bench-front-end" target="_blank">GitHub project - front-end</MenuItem>
                            <MenuItem href="https://github.com/FredTingaud/quick-bench-back-end" target="_blank">GitHub project - back-end</MenuItem>
                            <MenuItem divider />
                            <MenuItem eventKey="favicon">Thanks</MenuItem>
                            <MenuItem eventKey="author">About the author</MenuItem>
                        </NavDropdown>

                </Navbar.Collapse>
                <AboutDialog show={this.state.showAbout} onHide={this.closeAbout.bind(this)} />
                <BenchmarkDialog show={this.state.showBenchmark} onHide={this.closeBenchmark.bind(this)} />
                <AuthorDialog show={this.state.showAuthor} onHide={this.closeAuthor.bind(this)} />
                <ThanksDialog show={this.state.showThanks} onHide={this.closeFavicon.bind(this)}/>
            </Navbar>
        );
    }
}

export default Header;
<commit_msg>Correct accessibility issue on patreon link.<commit_after>import React from 'react';
import { Navbar, Nav, NavDropdown, MenuItem } from 'react-bootstrap';
import AboutDialog from './dialogs/AboutDialog.js';
import BenchmarkDialog from './dialogs/BenchmarkDialog.js';
import AuthorDialog from './dialogs/AuthorDialog.js';
import ThanksDialog from './dialogs/ThanksDialog.js';

class Header extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            showAbout: false,
            showBenchmark: false,
            showAuthor: false,
            showThanks: false
        };
    }
    openInfo(key) {
        if (key) {
            if (key === 'about') {
                this.openAbout();
            } else if (key === 'benchmark') {
                this.openBenchmark();
            } else if (key === 'author') {
                this.openAuthor();
            } else if (key === 'favicon') {
                this.openFavicon();
            }
        }
    }
    openAbout() {
        this.setState({ showAbout: true });
    }
    closeAbout() {
        this.setState({ showAbout: false });
    }
    openBenchmark() {
        this.setState({ showBenchmark: true });
    }
    closeBenchmark() {
        this.setState({ showBenchmark: false });
    }
    openAuthor() {
        this.setState({ showAuthor: true });
    }
    closeAuthor() {
        this.setState({ showAuthor: false });
    }
    openFavicon() {
        this.setState({ showThanks: true });
    }
    closeFavicon() {
        this.setState({ showThanks: false });
    }

    render() {
        return (
            <Navbar inverse collapseOnSelect>
                <Navbar.Header>
                    <Navbar.Brand>
                        Quick C++ Benchmark
                    </Navbar.Brand>
                    <Navbar.Toggle />
                </Navbar.Header>
                <Navbar.Collapse>

                        <NavDropdown title="Support Quick Bench" id="basic-nav-dropdown">
                            <MenuItem href="https://www.patreon.com/bePatron?u=8599781" target="_blank"> Support on Patreon</MenuItem>
                        </NavDropdown>
                        <NavDropdown title="More" id="basic-nav-dropdown" onSelect={this.openInfo.bind(this)}>
                            <MenuItem eventKey="about">About Quick-bench</MenuItem>
                            <MenuItem eventKey="benchmark">How to write my benchmarks</MenuItem>
                            <MenuItem divider />
                            <MenuItem href="https://github.com/FredTingaud/quick-bench-front-end" target="_blank">GitHub project - front-end</MenuItem>
                            <MenuItem href="https://github.com/FredTingaud/quick-bench-back-end" target="_blank">GitHub project - back-end</MenuItem>
                            <MenuItem divider />
                            <MenuItem eventKey="favicon">Thanks</MenuItem>
                            <MenuItem eventKey="author">About the author</MenuItem>
                        </NavDropdown>

                </Navbar.Collapse>
                <AboutDialog show={this.state.showAbout} onHide={this.closeAbout.bind(this)} />
                <BenchmarkDialog show={this.state.showBenchmark} onHide={this.closeBenchmark.bind(this)} />
                <AuthorDialog show={this.state.showAuthor} onHide={this.closeAuthor.bind(this)} />
                <ThanksDialog show={this.state.showThanks} onHide={this.closeFavicon.bind(this)}/>
            </Navbar>
        );
    }
}

export default Header;
<|endoftext|>


<commit_before>// Copyright 2017, University of Colorado Boulder

/**
 * Semi-transparent black barrier used to block input events when a dialog
 * (or other popup) is present, and fade out the background.
 *
 * @author - Michael Kauzmann (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var joist = require( 'JOIST/joist' );
  var Emitter = require( 'AXON/Emitter' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var ButtonListener = require( 'SCENERY/input/ButtonListener' );

  // phet-io modules
  var TBarrierRectangle = require( 'ifphetio!PHET_IO/types/scenery/nodes/TBarrierRectangle' );

  /**
   * @param x
   * @param y
   * @param width
   * @param height
   * @param cornerXRadius
   * @param cornerYRadius
   * @param {ObservableArray} modalNodeStack - see usage in Sim.js
   * @param {Object} [options]
   * @constructor
   */
  function BarrierRectangle( x, y, width, height, modalNodeStack, options ) {

    options = _.extend( {
      cornerRadius: 0
    }, options );

    var self = this;

    var tandem = options.tandem;

    // This will be passed up to parents
    options.tandem = tandem.createSupertypeTandem();

    //TODO #394 don't pass options to both Rectangle.call and mutate
    Rectangle.call( this, x, y, width, height, options );

    this.startedCallbacksForFiredEmitter = new Emitter();
    this.endedCallbacksForFiredEmitter = new Emitter();

    //TODO #394 implement dispose or document why unlink is unnecessary
    modalNodeStack.lengthProperty.link( function( numBarriers ) {
      self.visible = numBarriers > 0;
    } );

    this.addInputListener( new ButtonListener( {
      fire: function( event ) {
        self.startedCallbacksForFiredEmitter.emit();
        assert && assert( modalNodeStack.length > 0 );
        modalNodeStack.get( modalNodeStack.length - 1 ).hide();
        self.endedCallbacksForFiredEmitter.emit();
      }
    } ) );

    //TODO #394 don't pass options to both Rectangle.call and mutate
    this.mutate( {
      tandem: tandem, //TODO #394 this is not the tandem that you passed to Rectangle.call, bug?
      phetioType: TBarrierRectangle
    } );
  }

  joist.register( 'BarrierRectangle', BarrierRectangle );

  return inherit( Rectangle, BarrierRectangle );
} );<commit_msg>delete doc for vestigial params, #394<commit_after>// Copyright 2017, University of Colorado Boulder

/**
 * Semi-transparent black barrier used to block input events when a dialog
 * (or other popup) is present, and fade out the background.
 *
 * @author - Michael Kauzmann (PhET Interactive Simulations)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var joist = require( 'JOIST/joist' );
  var Emitter = require( 'AXON/Emitter' );
  var Rectangle = require( 'SCENERY/nodes/Rectangle' );
  var ButtonListener = require( 'SCENERY/input/ButtonListener' );

  // phet-io modules
  var TBarrierRectangle = require( 'ifphetio!PHET_IO/types/scenery/nodes/TBarrierRectangle' );

  /**
   * @param x
   * @param y
   * @param width
   * @param height
   * @param {ObservableArray} modalNodeStack - see usage in Sim.js
   * @param {Object} [options]
   * @constructor
   */
  function BarrierRectangle( x, y, width, height, modalNodeStack, options ) {

    options = _.extend( {
      cornerRadius: 0
    }, options );

    var self = this;

    var tandem = options.tandem;

    // This will be passed up to parents
    options.tandem = tandem.createSupertypeTandem();

    //TODO #394 don't pass options to both Rectangle.call and mutate
    Rectangle.call( this, x, y, width, height, options );

    this.startedCallbacksForFiredEmitter = new Emitter();
    this.endedCallbacksForFiredEmitter = new Emitter();

    //TODO #394 implement dispose or document why unlink is unnecessary
    modalNodeStack.lengthProperty.link( function( numBarriers ) {
      self.visible = numBarriers > 0;
    } );

    this.addInputListener( new ButtonListener( {
      fire: function( event ) {
        self.startedCallbacksForFiredEmitter.emit();
        assert && assert( modalNodeStack.length > 0 );
        modalNodeStack.get( modalNodeStack.length - 1 ).hide();
        self.endedCallbacksForFiredEmitter.emit();
      }
    } ) );

    //TODO #394 don't pass options to both Rectangle.call and mutate
    this.mutate( {
      tandem: tandem, //TODO #394 this is not the tandem that you passed to Rectangle.call, bug?
      phetioType: TBarrierRectangle
    } );
  }

  joist.register( 'BarrierRectangle', BarrierRectangle );

  return inherit( Rectangle, BarrierRectangle );
} );<|endoftext|>