<commit_before>/*global app, AppPort, WebRTC*/
/* jshint unused: false */
/**
 * Talkilla application.
 */
var ChatApp = (function(app, $, Backbone, _) {
  "use strict";

  function ChatApp() {
    this.appPort = new AppPort();
    this.user = new app.models.User();
    this.peer = new app.models.User();

    // Audio library
    this.audioLibrary = new app.utils.AudioLibrary({
      incoming: "/snd/incoming_call_ring.opus",
      outgoing: "/snd/outgoing_call_ring.opus"
    });

    this.webrtc = new WebRTC({
      forceFake: !!(app.options && app.options.FAKE_MEDIA_STREAMS)
    });

    this.webrtc.on("error", function(message) {
      // XXX: notify user that something went wrong
      console.error(message);
    });

    this.call = new app.models.Call({}, {
      media: this.webrtc,
      peer: this.peer
    });

    this.callControlsView = new app.views.CallControlsView({
      call: this.call,
      media: this.webrtc,
      el: $("#call-controls")
    });

    this.callView = new app.views.CallView({
      call: this.call,
      el: $("#call")
    });

    this.callOfferView = new app.views.CallOfferView({
      call: this.call,
      el: $("#offer")
    });

    this.callEstablishView = new app.views.CallEstablishView({
      call: this.call,
      peer: this.peer,
      audioLibrary: this.audioLibrary,
      el: $("#establish")
    });

    // Text chat
    // TODO: prefill the chat with history
    var history = [];

    this.textChat = new app.models.TextChat(history, {
      media: this.webrtc,
      user: this.user,
      peer: this.peer
    });

    this.textChatView = new app.views.TextChatView({
      call: this.call,
      collection: this.textChat
    });

    this.view = new app.views.ConversationView({
      call: this.call,
      textChat: this.textChat,
      peer: this.peer,
      user: this.user,
      el: 'html'
    });

    // User events
    this.user.on('signout', this._onUserSignout, this);

    // Incoming events
    this.appPort.on('talkilla.conversation-open',
                 this._onConversationOpen, this);
    this.appPort.on('talkilla.conversation-incoming',
                 this._onIncomingConversation, this);
    this.appPort.on('talkilla.call-establishment',
                 this._onCallEstablishment, this);
    this.appPort.on('talkilla.call-hangup', this._onCallShutdown, this);
    this.appPort.on('talkilla.ice-candidate', this._onIceCandidate, this);
    this.appPort.on('talkilla.user-joined', this._onUserJoined, this);
    this.appPort.on('talkilla.user-left', this._onUserLeft, this);
    this.appPort.on('talkilla.move-accept', this._onMoveAccept, this);
    this.appPort.on('talkilla.hold', this._onHold, this);
    this.appPort.on('talkilla.resume', this._onResume, this);

    // Outgoing events
    this.call.on('send-offer', this._onSendOffer, this);
    this.textChat.on('send-offer', this._onSendOffer, this);
    this.call.on('send-answer', this._onSendAnswer, this);
    this.textChat.on('send-answer', this._onSendAnswer, this);
    this.call.on('send-timeout', this._onSendTimeout, this);
    this.call.on('send-hangup', this._onCallHangup, this);
    this.call.on('transition:accept', this._onCallAccepted, this);
    this.call.on('initiate-move', this._onInitiateMove, this);
    // As we can get ice candidates for calls or text chats, just get this
    // straight from the media model.
    this.webrtc.on('ice:candidate-ready', this._onIceCandidateReady, this);

    // Internal events
    window.addEventListener("unload", this._onWindowClose.bind(this));

    this.appPort.post('talkilla.chat-window-ready', {});

    this._setupDebugLogging();
  }

  // Outgoing calls

  /**
   * Listens to the `talkilla.conversation-open` event.
   * @param {Object} context Conversation context object.
   */
  ChatApp.prototype._onConversationOpen = function(msg) {
    this.call.set({capabilities: msg.capabilities});
    this.user.set({nick: msg.user});
    if (msg.peer.fullName)
      this.peer.set({nick: msg.peer.username, presence: msg.peerPresence,
                     fullName: msg.peer.fullName},
                    {silent: true});
    else
      this.peer
          .set({nick: msg.peer.username, presence: msg.peerPresence},
               {silent: true});

    this.peer.trigger('change:nick', this.peer) // force triggering change event
             .trigger('change:presence', this.peer);
  };

  ChatApp.prototype._onCallAccepted = function() {
    this.audioLibrary.stop('incoming');
  };

  ChatApp.prototype._onInitiateMove = function(moveMsg) {
    this.appPort.post('talkilla.initiate-move', moveMsg.toJSON());
  };

  ChatApp.prototype._onCallEstablishment = function(data) {
    var sdp = new WebRTC.SDP(data.answer.sdp);

    // text chat conversation
    if (sdp.only("datachannel"))
      return this.textChat.establish(data.answer);

    // video/audio call
    this.call.establish(data);
  };

  // Incoming calls
  ChatApp.prototype._onIncomingConversation = function(msg) {
    var sdp = new WebRTC.SDP(msg.offer.offer.sdp);

    this.call.set({capabilities: msg.capabilities});
    this.user.set({nick: msg.user});

    if (!msg.offer.upgrade) {
      if (msg.peer.fullName)
        this.peer.set({nick: msg.peer.username, fullName: msg.peer.fullName,
                      presence: msg.peerPresence});
      else
        this.peer.set({nick: msg.peer.username, presence: msg.peerPresence});
    }

    // incoming text chat conversation
    if (sdp.only("datachannel"))
      return this.textChat.answer(msg.offer.offer);

    // incoming video/audio call
    this.call.incoming(new app.payloads.Offer(msg.offer));
    this.audioLibrary.play('incoming');
  };

  ChatApp.prototype._onIceCandidate = function(data) {
    this.webrtc.addIceCandidate(data.candidate);
  };

  /**
   * Called when initiating a call.
   *
   * @param {payloads.Offer} offerMsg the offer to send to initiate the call.
   */
  ChatApp.prototype._onSendOffer = function(offerMsg) {
    this.appPort.post('talkilla.call-offer', offerMsg);
  };

  /**
   * Called when accepting an incoming call.
   *
   * @param {payloads.Answer} answerMsg the answer to send to accept the call.
   */
  ChatApp.prototype._onSendAnswer = function(answerMsg) {
    this.appPort.post('talkilla.call-answer', answerMsg);
  };

  /**
   * Called when a call times out.
   *
   * @param {payloads.Hanging} hangupMsg the hangup to send to stop
   * the call.
   *
   */
  ChatApp.prototype._onSendTimeout = function(hangupMsg) {
    // Let the peer know that the call offer is no longer valid.
    // For this, we send call-hangup, the same as in the case where
    // the user decides to abandon the call attempt.
    this.appPort.post('talkilla.call-hangup', hangupMsg);
  };

  /**
   * Called to send an ice candidate to the peer.
   *
   * @param {mozRTCIceCandidate} The ICE Candidate to send.
   */
  ChatApp.prototype._onIceCandidateReady = function(candidate) {
    var iceCandidateMsg = new app.payloads.IceCandidate({
      peer: this.peer.get("nick"),
      candidate: candidate
    });
    this.appPort.post('talkilla.ice-candidate', iceCandidateMsg);
  };

  ChatApp.prototype._onMoveAccept = function(msg) {
    if (msg.callid === this.call.callid)
      this.call.hangup(false);
  };

  ChatApp.prototype._onHold = function(msg) {
    if (msg.callid === this.call.callid)
      this.call.hold();
  };

  ChatApp.prototype._onResume = function(msg) {
    if (msg.callid === this.call.callid)
      this.call.resume();
  };

  // Call Hangup
  ChatApp.prototype._onCallShutdown = function(hangupData) {
    var hangupMsg = new app.payloads.Hangup(hangupData);
    if (hangupMsg.callid !== this.call.callid)
      return;

    this.audioLibrary.stop('incoming');
    this.call.hangup(false);
    window.close();
  };

  /**
   * Called when hanging up a call.
   *
   * @param {payloads.Hanging} hangupMsg the hangup to send to stop
   * the call.
   *
   */
  ChatApp.prototype._onCallHangup = function(hangupMsg) {
    // Send a message as this is this user's call hangup
    this.appPort.post('talkilla.call-hangup', hangupMsg);
    window.close();
  };

  ChatApp.prototype._onWindowClose = function(data) {
    this.call.hangup(true);
  };

  ChatApp.prototype._onUserSignout = function() {
    // ensure this chat window is closed when the user signs out
    window.close();
  };

  ChatApp.prototype._onUserJoined = function(nick) {
    if (this.peer.get('nick') === nick)
      this.peer.set('presence', 'connected');
  };

  ChatApp.prototype._onUserLeft = function(nick) {
    if (this.peer.get('nick') === nick)
      this.peer.set('presence', 'disconnected');
  };

  // if debug is enabled, verbosely log object events to the console
  ChatApp.prototype._setupDebugLogging = function() {
    if (!app.options.DEBUG)
      return;

    // app object events logging
    ['webrtc', 'call', 'textChat'].forEach(function(prop) {
      this[prop].on("all", function() {
        var args = [].slice.call(arguments);
        console.log.apply(console, ['chatapp.' + prop].concat(args));
      });
    }, this);
  };

  return ChatApp;
})(app, jQuery, Backbone, _);
<commit_msg>Add fullName property, regardless if it exists because it will be checked before being displayed<commit_after>/*global app, AppPort, WebRTC*/
/* jshint unused: false */
/**
 * Talkilla application.
 */
var ChatApp = (function(app, $, Backbone, _) {
  "use strict";

  function ChatApp() {
    this.appPort = new AppPort();
    this.user = new app.models.User();
    this.peer = new app.models.User();

    // Audio library
    this.audioLibrary = new app.utils.AudioLibrary({
      incoming: "/snd/incoming_call_ring.opus",
      outgoing: "/snd/outgoing_call_ring.opus"
    });

    this.webrtc = new WebRTC({
      forceFake: !!(app.options && app.options.FAKE_MEDIA_STREAMS)
    });

    this.webrtc.on("error", function(message) {
      // XXX: notify user that something went wrong
      console.error(message);
    });

    this.call = new app.models.Call({}, {
      media: this.webrtc,
      peer: this.peer
    });

    this.callControlsView = new app.views.CallControlsView({
      call: this.call,
      media: this.webrtc,
      el: $("#call-controls")
    });

    this.callView = new app.views.CallView({
      call: this.call,
      el: $("#call")
    });

    this.callOfferView = new app.views.CallOfferView({
      call: this.call,
      el: $("#offer")
    });

    this.callEstablishView = new app.views.CallEstablishView({
      call: this.call,
      peer: this.peer,
      audioLibrary: this.audioLibrary,
      el: $("#establish")
    });

    // Text chat
    // TODO: prefill the chat with history
    var history = [];

    this.textChat = new app.models.TextChat(history, {
      media: this.webrtc,
      user: this.user,
      peer: this.peer
    });

    this.textChatView = new app.views.TextChatView({
      call: this.call,
      collection: this.textChat
    });

    this.view = new app.views.ConversationView({
      call: this.call,
      textChat: this.textChat,
      peer: this.peer,
      user: this.user,
      el: 'html'
    });

    // User events
    this.user.on('signout', this._onUserSignout, this);

    // Incoming events
    this.appPort.on('talkilla.conversation-open',
                 this._onConversationOpen, this);
    this.appPort.on('talkilla.conversation-incoming',
                 this._onIncomingConversation, this);
    this.appPort.on('talkilla.call-establishment',
                 this._onCallEstablishment, this);
    this.appPort.on('talkilla.call-hangup', this._onCallShutdown, this);
    this.appPort.on('talkilla.ice-candidate', this._onIceCandidate, this);
    this.appPort.on('talkilla.user-joined', this._onUserJoined, this);
    this.appPort.on('talkilla.user-left', this._onUserLeft, this);
    this.appPort.on('talkilla.move-accept', this._onMoveAccept, this);
    this.appPort.on('talkilla.hold', this._onHold, this);
    this.appPort.on('talkilla.resume', this._onResume, this);

    // Outgoing events
    this.call.on('send-offer', this._onSendOffer, this);
    this.textChat.on('send-offer', this._onSendOffer, this);
    this.call.on('send-answer', this._onSendAnswer, this);
    this.textChat.on('send-answer', this._onSendAnswer, this);
    this.call.on('send-timeout', this._onSendTimeout, this);
    this.call.on('send-hangup', this._onCallHangup, this);
    this.call.on('transition:accept', this._onCallAccepted, this);
    this.call.on('initiate-move', this._onInitiateMove, this);
    // As we can get ice candidates for calls or text chats, just get this
    // straight from the media model.
    this.webrtc.on('ice:candidate-ready', this._onIceCandidateReady, this);

    // Internal events
    window.addEventListener("unload", this._onWindowClose.bind(this));

    this.appPort.post('talkilla.chat-window-ready', {});

    this._setupDebugLogging();
  }

  // Outgoing calls

  /**
   * Listens to the `talkilla.conversation-open` event.
   * @param {Object} context Conversation context object.
   */
  ChatApp.prototype._onConversationOpen = function(msg) {
    this.call.set({capabilities: msg.capabilities});
    this.user.set({nick: msg.user});

    this.peer.set({nick: msg.peer.username, presence: msg.peerPresence,
                   fullName: msg.peer.fullName},
                  {silent: true})
             .trigger('change:nick', this.peer) // force triggering change event
             .trigger('change:presence', this.peer);
  };

  ChatApp.prototype._onCallAccepted = function() {
    this.audioLibrary.stop('incoming');
  };

  ChatApp.prototype._onInitiateMove = function(moveMsg) {
    this.appPort.post('talkilla.initiate-move', moveMsg.toJSON());
  };

  ChatApp.prototype._onCallEstablishment = function(data) {
    var sdp = new WebRTC.SDP(data.answer.sdp);

    // text chat conversation
    if (sdp.only("datachannel"))
      return this.textChat.establish(data.answer);

    // video/audio call
    this.call.establish(data);
  };

  // Incoming calls
  ChatApp.prototype._onIncomingConversation = function(msg) {
    var sdp = new WebRTC.SDP(msg.offer.offer.sdp);

    this.call.set({capabilities: msg.capabilities});
    this.user.set({nick: msg.user});

    if (!msg.offer.upgrade)
      this.peer.set({nick: msg.peer.username, fullName: msg.peer.fullName,
                    presence: msg.peerPresence});

    // incoming text chat conversation
    if (sdp.only("datachannel"))
      return this.textChat.answer(msg.offer.offer);

    // incoming video/audio call
    this.call.incoming(new app.payloads.Offer(msg.offer));
    this.audioLibrary.play('incoming');
  };

  ChatApp.prototype._onIceCandidate = function(data) {
    this.webrtc.addIceCandidate(data.candidate);
  };

  /**
   * Called when initiating a call.
   *
   * @param {payloads.Offer} offerMsg the offer to send to initiate the call.
   */
  ChatApp.prototype._onSendOffer = function(offerMsg) {
    this.appPort.post('talkilla.call-offer', offerMsg);
  };

  /**
   * Called when accepting an incoming call.
   *
   * @param {payloads.Answer} answerMsg the answer to send to accept the call.
   */
  ChatApp.prototype._onSendAnswer = function(answerMsg) {
    this.appPort.post('talkilla.call-answer', answerMsg);
  };

  /**
   * Called when a call times out.
   *
   * @param {payloads.Hanging} hangupMsg the hangup to send to stop
   * the call.
   *
   */
  ChatApp.prototype._onSendTimeout = function(hangupMsg) {
    // Let the peer know that the call offer is no longer valid.
    // For this, we send call-hangup, the same as in the case where
    // the user decides to abandon the call attempt.
    this.appPort.post('talkilla.call-hangup', hangupMsg);
  };

  /**
   * Called to send an ice candidate to the peer.
   *
   * @param {mozRTCIceCandidate} The ICE Candidate to send.
   */
  ChatApp.prototype._onIceCandidateReady = function(candidate) {
    var iceCandidateMsg = new app.payloads.IceCandidate({
      peer: this.peer.get("nick"),
      candidate: candidate
    });
    this.appPort.post('talkilla.ice-candidate', iceCandidateMsg);
  };

  ChatApp.prototype._onMoveAccept = function(msg) {
    if (msg.callid === this.call.callid)
      this.call.hangup(false);
  };

  ChatApp.prototype._onHold = function(msg) {
    if (msg.callid === this.call.callid)
      this.call.hold();
  };

  ChatApp.prototype._onResume = function(msg) {
    if (msg.callid === this.call.callid)
      this.call.resume();
  };

  // Call Hangup
  ChatApp.prototype._onCallShutdown = function(hangupData) {
    var hangupMsg = new app.payloads.Hangup(hangupData);
    if (hangupMsg.callid !== this.call.callid)
      return;

    this.audioLibrary.stop('incoming');
    this.call.hangup(false);
    window.close();
  };

  /**
   * Called when hanging up a call.
   *
   * @param {payloads.Hanging} hangupMsg the hangup to send to stop
   * the call.
   *
   */
  ChatApp.prototype._onCallHangup = function(hangupMsg) {
    // Send a message as this is this user's call hangup
    this.appPort.post('talkilla.call-hangup', hangupMsg);
    window.close();
  };

  ChatApp.prototype._onWindowClose = function(data) {
    this.call.hangup(true);
  };

  ChatApp.prototype._onUserSignout = function() {
    // ensure this chat window is closed when the user signs out
    window.close();
  };

  ChatApp.prototype._onUserJoined = function(nick) {
    if (this.peer.get('nick') === nick)
      this.peer.set('presence', 'connected');
  };

  ChatApp.prototype._onUserLeft = function(nick) {
    if (this.peer.get('nick') === nick)
      this.peer.set('presence', 'disconnected');
  };

  // if debug is enabled, verbosely log object events to the console
  ChatApp.prototype._setupDebugLogging = function() {
    if (!app.options.DEBUG)
      return;

    // app object events logging
    ['webrtc', 'call', 'textChat'].forEach(function(prop) {
      this[prop].on("all", function() {
        var args = [].slice.call(arguments);
        console.log.apply(console, ['chatapp.' + prop].concat(args));
      });
    }, this);
  };

  return ChatApp;
})(app, jQuery, Backbone, _);
<|endoftext|>


<commit_before>// From stackoverflow response, who borrowed it from Shopify--simple ordinal suffix.
var myLat, myLong;
var slowTimer;
var globalEnableLocation = 0;

function getGetOrdinal(n) {
    var s=["th","st","nd","rd"],
    v=n%100;
    return n+(s[(v-20)%10]||s[v]||s[0]);
 }

function congToYears(n) { return [1787+(2*n), 1787+(2*n)+2]; }

function lzPad(t)
{
	if(parseInt(t)<10) { return "0"+t; }
	else { return t; }
}

function loadText(t)
{
	$("#addressInput").val(t);
	latLongWrapper();
}

function resetResults()
{
	$("#resultsMembers").hide().html("");
	$("#addressCorrected").html("");
	$("#google_map").html("");
	$("#warnings").hide().html("");
	$("#loadProgress").hide().html("");
}

	$(document).ready(function(){
		$("#addressInput").on("focus",function() {
			if($("#addressInput").val()=="MY LOCATION") { $("#addressInput").val(""); }
		});
		$("#submit-address-form").submit(function(event)
		{
			event.preventDefault();
			latLongWrapper();
		});
		$("#submit-geolocation").click(function(event)
		{
			event.preventDefault();
			getLocation();
		});
		if($("#cachedLat").val()) { myLat = $("#cachedLat").val(); }
		if($("#cachedLong").val()) { myLong = $("#cachedLong").val(); }
		if($("#addressInput").val()) { setTimeout(function(){latLongWrapper();},1000); }
		$("ul#testData li").on("click",function(){ console.log($(this).val()); loadText(this.innerHTML); });
	});

	if(navigator.geolocation)
	{
		globalEnableLocation=1;
		console.log('html5 location support.');
		$("#locationButton").show();
		function success(position)
		{
			clearTimeout(slowTimer);
			console.log(position.coords);
			myLat = position.coords.latitude;
			myLong = position.coords.longitude;
			$("#cachedLat").val(myLat);
			$("#cachedLong").val(myLong);
			$("#addressInput").val("MY LOCATION");
			resetResults();
			$("#loadProgress").show().html("Loading... Location matched, looking up historical representatives... ");
			doMembers(myLat, myLong);
		}
		function error()
		{
			clearTimeout(slowTimer);
			resetResults();
			$("#warnings").html("").show();
			var errorDiv = $("

").addClass("alert alert-danger").html("Error: Error looking up your location. Most commonly this occurs because you are having internet connection trouble or you have privacy settings designed to block web access to your location.");
			errorDiv.appendTo($("#warnings"));

			return;
		}
		function getLocation(event)
		{
			console.log(event);
			console.log('I AM HERE, IN THE GETLOCATION FUNCTION');
			resetResults();
			$("#loadProgress").show().html("Loading... Looking up your current location... ");
			slowTimer = setTimeout(function() { $("#loadProgress").html($("#loadProgress").html()+"
This process seems to be taking an unusually long time to complete. The delay is related to your internet connection, router, or web browser and is not connected to our server."); }, 5000);
			navigator.geolocation.getCurrentPosition(success, error);
		}
		$("#geolocationTutorial").show();
	}

	function latLongWrapper()
	{
		console.log('I AM HERE, IN THE ADDRESS LOOKUP.');
		resetResults();
		if($("#addressInput").val()=="")
		{
			$("#warnings").html("").show();
			var errorDiv = $("

").addClass("alert alert-danger").html("Error: No address specified.");
			errorDiv.appendTo($("#warnings"));
			return;
		}
		else if($("#addressInput").val()=="MY LOCATION" && globalEnableLocation && $("#cachedLat").val() && $("#cachedLong").val()) { doMembers(parseFloat($("#cachedLat").val()), parseFloat($("#cachedLong").val())); }
		else if($("#addressInput").val()=="MY LOCATION")
		{
			$("#warnings").html("").show();
			var errorDiv = $("

").addClass("alert alert-danger").html("Error: Error accessing your location, either due to internet connectivity or privacy settings. Please manually type an address to continue.");
			errorDiv.appendTo($("#warnings"));
		}
		else
		{
			$("#loadProgress").show().html("Loading... Matching address to map coordinates... ");
			setTimeout(doLatLong, 20);
		}
	}

	function doLatLong()
	{
		console.log('I AM HERE, CACHED LAT LONG TO DISTRICT LOOKUP.');
		$.ajax({
			dataType: "JSON",
			url: "/api/geocode?q="+$("#addressInput").val(),
			success: function(data, status, xhr)
			{
				console.log(data);
				if(data["status"])
				{
					$("#loadProgress").fadeOut();
					console.log("Error! Oh no!");
					var errorDiv = $("

").addClass("alert alert-danger").html("Error: "+data["error_message"])
					errorDiv.appendTo($("#warnings"));
					$("#warnings").fadeIn();
					return;
				}
				else
				{
					console.log(data);
					if(data["warnings"]!=undefined && data["warnings"].length)
					{
						$("#warnings").html("");
						var warningDiv = $("

").addClass("alert alert-warning").html("Warning: "+data["warnings"][0]);
						warningDiv.appendTo($("#warnings"));
						$("#warnings").fadeIn();
					}
					$("#addressCorrected").html("Address Lookup:
"+data["formatted_address"]+"");
					$("#loadProgress").html("Loading... Address matched, looking up historical representatives... ");
					doMembers(data["lat"], data["lng"]);
				}
			}
		});
	}

	function doMembers(lat, lng)
	{
 		var markerPos = {lat: lat, lng: lng};
		var map = new google.maps.Map(document.getElementById("google_map"), {zoom: 12, center: markerPos, disableDefaultUI: true, scrollwheel: false, draggable: false});
		var market = new google.maps.Marker({position: markerPos, map: map});

		$.ajax({
			dataType: "JSON",
			url: "/api/districtLookup?lat="+lat+"&long="+lng,
			success: function(data, status, xhr)
			{
				$("#loadProgress").fadeOut();
				console.log("ok good");
				if(data["resCurr"].length)
				{
					$("
Current Congressperson and Senators
").appendTo("#resultsMembers");
					var memberList = $("

").css("columns","auto 3")
								.css("list-style-type","none").css("overflow","auto")
								.css("width","100%").css("margin-left",0).css("padding-left",0).css("margin-bottom","15px")
								.css("display","block").attr("id","memberList");
					memberList.appendTo("#resultsMembers");
					//boxDiv.appendTo("#resultsMembers")
					$.each(data["resCurr"], function(k,v)
					{
						constructPlot(v, 0);
					});
				}

				$("
Historical Representatives
").appendTo("#resultsMembers");
				var table = $("

Congress	District	Party	Member

")
						.addClass("table table-hover dc-data-table");
				var tbody = $("

");
				var lastICPSR = 0;
				var lastCong = 0;
				var lastState = ""
				$.each(data["results"], function(k, v)
				{
					if(lastCong>38 && v["congress"]<37)
					{
						var civilWarDiv = $("

").addClass("alert alert-info").html("United States Civil War: "+v["state"]+" does not seat a delegation in the US Congress.");
						var tr = $("

");
						var td = $("	");
						civilWarDiv.appendTo(td);
						td.appendTo(tr);
						tr.appendTo(tbody);
					}
					if(lastState=="West Virginia" && v["state"]=="Virginia")
					{
						var virgDiv = $("

").addClass("alert alert-info").html("United States Civil War: West Virginia breaks away from Virginia to form a new state.");
						var tr = $("

");
						var td = $("	");
						virgDiv.appendTo(td);
						td.appendTo(tr);
						tr.appendTo(tbody);
					}
					if(lastState=="Maine" && v["state"]=="Massachusetts")
					{
						var maineDiv = $("

").addClass("alert alert-info").html("1820: Maine votes to secede from Massachusetts and is admitted to the union as a state.");
						var tr = $("

");
						var td = $("	");
						maineDiv.appendTo(td);
						td.appendTo(tr);
						tr.appendTo(tbody);
					}

					lastCong = parseInt(v["congress"]);
					lastState = v["state"];
					var tr = $("

").on("click",function(){window.location='/person/'+v["icpsr"];});
					dateSet = congToYears(v["congress"]);
					console.log(dateSet[0].toString().substr(2,2));
					if(lastICPSR!=parseInt(v["icpsr"]))
					{
						$(""+getGetOrdinal(v["congress"])+" ("+dateSet[0]+"-"+dateSet[1].toString().substr(2,2)+")	").appendTo(tr);
						$(""+v["state_abbrev"]+"-"+lzPad(v["district_code"])+"	").appendTo(tr);
						$(""+v["party_noun"]+"	").css("border-left","3px solid "+colorSchemes[v["party_color"]][0]).appendTo(tr);
						$(""+v["bioname"]+"	").appendTo(tr);
						lastICPSR = parseInt(v["icpsr"]);
					}
					else
					{
						$(""+getGetOrdinal(v["congress"])+" ("+dateSet[0]+"-"+dateSet[1].toString().substr(2,2)+")	").appendTo(tr);
						$(""+v["state_abbrev"]+"-"+lzPad(v["district_code"])+"	").appendTo(tr);
						$("	").css("border-left","3px solid "+colorSchemes[v["party_color"]][0]).appendTo(tr);
						$("	").appendTo(tr);
					}
					tr.appendTo(tbody);
				});
				tbody.appendTo(table);
				table.appendTo($("#resultsMembers"));
				$("#resultsMembers").fadeIn();
			}
		});
	}
<commit_msg>NOMINATE plot in District Lookup.<commit_after>// From stackoverflow response, who borrowed it from Shopify--simple ordinal suffix.
var myLat, myLong;
var slowTimer;
var globalEnableLocation = 0;

function getGetOrdinal(n) {
    var s=["th","st","nd","rd"],
    v=n%100;
    return n+(s[(v-20)%10]||s[v]||s[0]);
 }

function congToYears(n) { return [1787+(2*n), 1787+(2*n)+2]; }

function lzPad(t)
{
	if(parseInt(t)<10) { return "0"+t; }
	else { return t; }
}

function loadText(t)
{
	$("#addressInput").val(t);
	latLongWrapper();
}

function resetResults()
{
	$("#resultsMembers").hide().html("");
	$("#addressCorrected").html("");
	$("#google_map").html("");
	$("#warnings").hide().html("");
	$("#loadProgress").hide().html("");
}

	$(document).ready(function(){
		$("#addressInput").on("focus",function() {
			if($("#addressInput").val()=="MY LOCATION") { $("#addressInput").val(""); }
		});
		$("#submit-address-form").submit(function(event)
		{
			event.preventDefault();
			latLongWrapper();
		});
		$("#submit-geolocation").click(function(event)
		{
			event.preventDefault();
			getLocation();
		});
		if($("#cachedLat").val()) { myLat = $("#cachedLat").val(); }
		if($("#cachedLong").val()) { myLong = $("#cachedLong").val(); }
		if($("#addressInput").val()) { setTimeout(function(){latLongWrapper();},1000); }
		$("ul#testData li").on("click",function(){ console.log($(this).val()); loadText(this.innerHTML); });
	});

	if(navigator.geolocation)
	{
		globalEnableLocation=1;
		console.log('html5 location support.');
		$("#locationButton").show();
		function success(position)
		{
			clearTimeout(slowTimer);
			console.log(position.coords);
			myLat = position.coords.latitude;
			myLong = position.coords.longitude;
			$("#cachedLat").val(myLat);
			$("#cachedLong").val(myLong);
			$("#addressInput").val("MY LOCATION");
			resetResults();
			$("#loadProgress").show().html("Loading... Location matched, looking up historical representatives... ");
			doMembers(myLat, myLong);
		}
		function error()
		{
			clearTimeout(slowTimer);
			resetResults();
			$("#warnings").html("").show();
			var errorDiv = $("

").addClass("alert alert-danger").html("Error: Error looking up your location. Most commonly this occurs because you are having internet connection trouble or you have privacy settings designed to block web access to your location.");
			errorDiv.appendTo($("#warnings"));

			return;
		}
		function getLocation(event)
		{
			console.log(event);
			console.log('I AM HERE, IN THE GETLOCATION FUNCTION');
			resetResults();
			$("#loadProgress").show().html("Loading... Looking up your current location... ");
			slowTimer = setTimeout(function() { $("#loadProgress").html($("#loadProgress").html()+"
This process seems to be taking an unusually long time to complete. The delay is related to your internet connection, router, or web browser and is not connected to our server."); }, 5000);
			navigator.geolocation.getCurrentPosition(success, error);
		}
		$("#geolocationTutorial").show();
	}

	function latLongWrapper()
	{
		console.log('I AM HERE, IN THE ADDRESS LOOKUP.');
		resetResults();
		if($("#addressInput").val()=="")
		{
			$("#warnings").html("").show();
			var errorDiv = $("

").addClass("alert alert-danger").html("Error: No address specified.");
			errorDiv.appendTo($("#warnings"));
			return;
		}
		else if($("#addressInput").val()=="MY LOCATION" && globalEnableLocation && $("#cachedLat").val() && $("#cachedLong").val()) { doMembers(parseFloat($("#cachedLat").val()), parseFloat($("#cachedLong").val())); }
		else if($("#addressInput").val()=="MY LOCATION")
		{
			$("#warnings").html("").show();
			var errorDiv = $("

").addClass("alert alert-danger").html("Error: Error accessing your location, either due to internet connectivity or privacy settings. Please manually type an address to continue.");
			errorDiv.appendTo($("#warnings"));
		}
		else
		{
			$("#loadProgress").show().html("Loading... Matching address to map coordinates... ");
			setTimeout(doLatLong, 20);
		}
	}

	function doLatLong()
	{
		console.log('I AM HERE, CACHED LAT LONG TO DISTRICT LOOKUP.');
		$.ajax({
			dataType: "JSON",
			url: "/api/geocode?q="+$("#addressInput").val(),
			success: function(data, status, xhr)
			{
				console.log(data);
				if(data["status"])
				{
					$("#loadProgress").fadeOut();
					console.log("Error! Oh no!");
					var errorDiv = $("

").addClass("alert alert-danger").html("Error: "+data["error_message"])
					errorDiv.appendTo($("#warnings"));
					$("#warnings").fadeIn();
					return;
				}
				else
				{
					console.log(data);
					if(data["warnings"]!=undefined && data["warnings"].length)
					{
						$("#warnings").html("");
						var warningDiv = $("

").addClass("alert alert-warning").html("Warning: "+data["warnings"][0]);
						warningDiv.appendTo($("#warnings"));
						$("#warnings").fadeIn();
					}
					$("#addressCorrected").html("Address Lookup:
"+data["formatted_address"]+"");
					$("#loadProgress").html("Loading... Address matched, looking up historical representatives... ");
					doMembers(data["lat"], data["lng"]);
				}
			}
		});
	}

	function compareSort(a, b)
	{
		if(a.congress > b.congress) { return -1; }
		else if(a.congress < b.congress) { return 1; }
		else
		{
			if(a.party_noun  b.party_noun) { return 1; }
			else
			{
				if(a.bioname < b.bioname) { return -1; }
				else { return 1; }
			}
		}
	}

	function doMembers(lat, lng)
	{
		console.log("Entering this now.");
		console.log(lat);
		console.log(lng);
 		var markerPos = {lat: lat, lng: lng};
		var map = new google.maps.Map(document.getElementById("google_map"), {zoom: 12, center: markerPos, disableDefaultUI: true, scrollwheel: false, draggable: false});
		var market = new google.maps.Marker({position: markerPos, map: map});

		$.ajax({
			dataType: "JSON",
			url: "/api/districtLookup?lat="+lat+"&long="+lng,
			success: function(data, status, xhr)
			{
				$("#loadProgress").fadeOut();
				if(data["resCurr"].length)
				{
					$("
Current Congressperson and Senators
").appendTo("#resultsMembers");
					var memberList = $("

").css("columns","auto 3")
								.css("list-style-type","none").css("overflow","auto")
								.css("width","100%").css("margin-left",0).css("padding-left",0).css("margin-bottom","15px")
								.css("display","block").attr("id","memberList");
				        console.log(data["resCurr"]);
					memberList.appendTo("#resultsMembers");
					//boxDiv.appendTo("#resultsMembers")
					$.each(data["resCurr"], function(k,v)
					{
						constructPlot(v, 0);
					});
				}

				$("
Historical Representatives
").appendTo("#resultsMembers");
				var table = $("

Congress	District	Party	Member

")
						.addClass("table table-hover dc-data-table");
				var tbody = $("

");

				// For visual design, we do a pocket algorithm; save the last guy, compare to current guy, see what's changed.
				var lastResult = {};
				var myResults = data["results"].sort(compareSort);
				$.each(myResults, function(k, v)
				{
					// Check to see if we have other members at the same time
					var multiMember=0;
					if(v["congress"]<90)
					{
						var howMany = $.grep(myResults, function(n,i) { return (n["congress"]==v["congress"]); });
						if(howMany.length>1) { multiMember=1; }
					}

					// Explainers for weird edge cases (partition/joining or the Civil War)
					if(lastResult["congress"]>38 && v["congress"]<37)
					{
						var civilWarDiv = $("

").addClass("alert alert-info").html("United States Civil War: "+v["state"]+" does not seat a delegation in the US Congress.");
						var tr = $("

");
						var td = $("	");
						civilWarDiv.appendTo(td);
						td.appendTo(tr);
						tr.appendTo(tbody);
					}
					if(lastResult["state"]=="West Virginia" && v["state"]=="Virginia")
					{
						var virgDiv = $("

").addClass("alert alert-info").html("United States Civil War: West Virginia breaks away from Virginia to form a new state.");
						var tr = $("

");
						var td = $("	");
						virgDiv.appendTo(td);
						td.appendTo(tr);
						tr.appendTo(tbody);
					}
					if(lastResult["state"]=="Maine" && v["state"]=="Massachusetts")
					{
						var maineDiv = $("

").addClass("alert alert-info").html("1820: Maine votes to secede from Massachusetts and is admitted to the union as a state.");
						var tr = $("

");
						var td = $("	");
						maineDiv.appendTo(td);
						td.appendTo(tr);
						tr.appendTo(tbody);
					}

					var tr = $("

").on("click",function(){window.location='/person/'+v["icpsr"];});
					dateSet = congToYears(v["congress"]);
					if(parseInt(lastResult["icpsr"])!=parseInt(v["icpsr"]))
					{
						$(""+getGetOrdinal(v["congress"])+" ("+dateSet[0]+"-"+dateSet[1].toString().substr(2,2)+")	").appendTo(tr);
						$(""+v["state_abbrev"]+"-"+lzPad(v["district_code"])+"	").appendTo(tr);
						$(""+v["party_noun"]+"	").css("border-left","3px solid "+colorSchemes[v["party_color"]][0]).appendTo(tr);
						$(""+v["bioname"]+"	").appendTo(tr);
					}
					else
					{
						$(""+getGetOrdinal(v["congress"])+" ("+dateSet[0]+"-"+dateSet[1].toString().substr(2,2)+")	").appendTo(tr);
						$(""+v["state_abbrev"]+"-"+lzPad(v["district_code"])+"	").appendTo(tr);
						$("	").css("border-left","3px solid "+colorSchemes[v["party_color"]][0]).appendTo(tr);
						$("	").appendTo(tr);
					}
					tr.appendTo(tbody);

					lastResult = v;
				});
				tbody.appendTo(table);
				table.appendTo($("#resultsMembers"));
				$("#resultsMembers").fadeIn();
				nomPlotDistrict(data["results"]);

			}
		});
	}

function nomPlotDistrict(dataToUse)
{
	var nominateScatterChart = dc.scatterPlot("#scatter-chart");
	console.log('ok');
	var ndx = crossfilter(dataToUse);
	var all = ndx.groupAll();
	var xDimension = ndx.dimension(
		function(d)
		{
			if(d.nominate!=undefined)
			{
				var x = d.nominate.dim1;
				var y = d.nominate.dim2;
			}
			else
			{
				var x = 999;
				var y = 999;
			}
			return [x,y];
		}
	);
	var xGroup = xDimension.group().reduce(
		function(p, d)
		{
			p.members.push(d);
			return p;
		},

		function(p, d)
		{
			var index = p.members.indexOf(d);
			if(index > -1) { p.members.splice(index, 1); }
			return p;
		},

		function() { return {members: []} ; }
	);

	nominateScatterChart
	.width(600)
	.height(290)
	.margins({top:25,right:25,bottom:75,left:75})
	.dimension(xDimension)
	.mouseZoomable(false)
	.group(xGroup)
	.data(function(group) { return group.all().filter(function(d) { return d.key!=[999,999]; });})
	.symbolSize(7)
	.colorCalculator(function(d) {
		var color = "#CCC";
		try {
			if(d.value.members.length > 0){
				color = blendColors(d.value.members);
			}
		}catch(e){
			console.log(e);
		}
		return color;
	})
	.highlightedSize(10)
	.x(d3.scale.linear().domain([-1.0,1.0]))
	.y(d3.scale.linear().domain([-1.2,1.2]));

	/*nominateScatterChart.on("filtered", function()
	{
		if(updateFilterTimer) { clearTimeout(updateFilterTimer); }
		updateFilterTimer = setTimeout(function()
		{
			var filterSelect= xDimension.top(Infinity);
			validSet = [];
			for(var i in filterSelect)
			{
				validSet.push(filterSelect[i].icpsr);
			}
			hasFilter=1;
			hideMembersUnselected();
		}, 300);
	});*/

	dc.filterAll();
	dc.renderAll();
	decorateNominate(nominateScatterChart, dataToUse);
}
<|endoftext|>


<commit_before>$( document ).ready( function() {

    // Variable to hold request
    var request;

    // Bind to the submit event of our form
    $("#expenseForm").submit(function(event){

        // Abort any pending request
        if (request) {
            request.abort();
        }
        // setup some local variables
        var $form = $(this);

        // Let's select and cache all the fields
        var $inputs = $form.find("input, select, button, textarea");

        // Serialize the data in the form
        var serializedData = $form.serialize();

        // Let's disable the inputs for the duration of the Ajax request.
        // Note: we disable elements AFTER the form data has been serialized.
        // Disabled form elements will not be serialized.
        $inputs.prop("disabled", true);

        // Fire off the request to /form.php
        request = $.ajax({
            url: "/index.php/user/addExpenses",
            type: "post",
            data: serializedData
        });

        // Callback handler that will be called on success
        request.done(function (response, textStatus, jqXHR){
            // Log a message to the console
            console.log("Hooray, it worked!");
            $('#messagebox').append('
Added!
');
            $('#messagebox').css('display','block');
        });

        // Callback handler that will be called on failure
        request.fail(function (jqXHR, textStatus, errorThrown){
            // Log the error to the console
            console.error(
                "The following error occurred: "+
                textStatus, errorThrown
            );
        });

        // Callback handler that will be called regardless
        // if the request failed or succeeded
        request.always(function () {
            // Reenable the inputs
            $inputs.prop("disabled", false);
        });

        // Prevent default posting of form
        event.preventDefault();

        // Load List of Expenses
        $.ajax({
              url:"/index.php/user/listExpenses",
              cache:0,
              success:function(result){
                     document.getElementById("expenseListing").innerHTML=result;
               }
        });

    });

    // Refresh list of expenses
    $.ajax({
          url:"/index.php/user/listExpenses",
          cache:0,
          success:function(result){
                 document.getElementById("expenseListing").innerHTML=result;
           }
    });

    // Get Date
    //$(".date-picker").datepicker();
    $( "#datepicker" ).datepicker( "option", "dateFormat", "yy-mm-dd" );

    $(".date-picker").on("change", function () {
        var id = $(this).attr("id");
        var val = $("label[for='" + id + "']").text();
        $("#msg").text(val + " changed");
    });

});<commit_msg>haaaands<commit_after>$( document ).ready( function() {

    // Variable to hold request
    var request;

    // Bind to the submit event of our form
    $("#expenseForm").submit(function(event){

        // Abort any pending request
        if (request) {
            request.abort();
        }
        // setup some local variables
        var $form = $(this);

        // Let's select and cache all the fields
        var $inputs = $form.find("input, select, button, textarea");

        // Serialize the data in the form
        var serializedData = $form.serialize();

        // Let's disable the inputs for the duration of the Ajax request.
        // Note: we disable elements AFTER the form data has been serialized.
        // Disabled form elements will not be serialized.
        $inputs.prop("disabled", true);

        // Fire off the request to /form.php
        request = $.ajax({
            url: "/index.php/user/addExpenses",
            type: "post",
            data: serializedData
        });

        // Callback handler that will be called on success
        request.done(function (response, textStatus, jqXHR){
            // Log a message to the console
            console.log("Hooray, it worked!");
            $('#messagebox').append('
Added!
');
            $('#messagebox').css('display','block');
        });

        // Callback handler that will be called on failure
        request.fail(function (jqXHR, textStatus, errorThrown){
            // Log the error to the console
            console.error(
                "The following error occurred: "+
                textStatus, errorThrown
            );
        });

        // Callback handler that will be called regardless
        // if the request failed or succeeded
        request.always(function () {
            // Reenable the inputs
            $inputs.prop("disabled", false);
        });

        // Prevent default posting of form
        event.preventDefault();

        // Load List of Expenses
        $.ajax({
              url:"/index.php/user/listExpenses",
              cache:0,
              success:function(result){
                     document.getElementById("expenseListing").innerHTML=result;
               }
        });

    });

    // Refresh list of expenses
    $.ajax({
          url:"/index.php/user/listExpenses",
          cache:0,
          success:function(result){
                 document.getElementById("expenseListing").innerHTML=result;
           }
    });

    // Get Date
    //$(".date-picker").datepicker();
    $( ".datepicker" ).datepicker( "option", "dateFormat", "yy-mm-dd" );

    $(".date-picker").on("change", function () {
        var id = $(this).attr("id");
        var val = $("label[for='" + id + "']").text();
        $("#msg").text(val + " changed");
    });

});<|endoftext|>


<commit_before>let is_open = false;
// the asset map is a map of all retrieved images and YouTube videos that are
// memoized instead of being looked up multiple times.
const asset_map = new Map();

function render_lightbox_list_images(preview_source) {
    if (!is_open) {
        const images = Array.prototype.slice.call($(".focused_table .message_inline_image img"));
        const $image_list = $("#lightbox_overlay .image-list").html("");

        images.forEach(function (img) {
            const src = img.getAttribute("src");
            const className = preview_source === src ? "image selected" : "image";

            const node = $("

", {
                class: className,
                "data-src": src,
            }).css({ backgroundImage: "url(" + src + ")"});

            $image_list.append(node);
        }, "");
    }
}

function display_image(payload, options) {
    render_lightbox_list_images(payload.preview);

    $(".player-container").hide();
    $(".image-actions, .image-description, .download, .lightbox-canvas-trigger").show();

    if (options.lightbox_canvas === true) {
        const canvas = document.createElement("canvas");
        canvas.setAttribute("data-src", payload.source);

        $("#lightbox_overlay .image-preview").html(canvas).show();
        const photo = new LightboxCanvas(canvas);
        photo.speed(2.3);
    } else {
        const img = new Image();
        img.src = payload.source;

        $("#lightbox_overlay .image-preview").html(img).show();
    }

    $(".image-description .title").text(payload.title || "N/A");
    $(".image-description .user").text(payload.user);

    $(".image-actions .open, .image-actions .download").attr("href", payload.source);
}

function display_video(payload) {
    render_lightbox_list_images(payload.preview);

    $("#lightbox_overlay .image-preview, .image-description, .download, .lightbox-canvas-trigger").hide();

    let source;
    if (payload.type === "youtube-video") {
        source = "https://www.youtube.com/embed/" + payload.source;
    } else if (payload.type === "vimeo-video") {
        source = "https://player.vimeo.com/video/" + payload.source;
    } else if (payload.type === "embed-video") {
        // Use data: to load the player in a unique origin for security.
        source = "data:text/html," + window.encodeURIComponent(
            "<!DOCTYPE html>" +
                payload.source
        );
    }

    const iframe = $("");
    iframe.attr("sandbox", "allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts");
    iframe.attr("src", source);
    iframe.attr("frameborder", 0);
    iframe.attr("allowfullscreen", true);

    $("#lightbox_overlay .player-container").html(iframe).show();
    $(".image-actions .open").attr("href", payload.url);
}

// the image param is optional, but required on the first preview of an image.
// this will likely be passed in every time but just ignored if the result is already
// stored in the `asset_map`.
exports.open = function (image, options) {
    if (!options) {
        options = {
            // default to showing standard images.
            lightbox_canvas: $(".lightbox-canvas-trigger").hasClass("enabled"),
        };
    }

    const $image = $(image);

    // if the asset_map already contains the metadata required to display the
    // asset, just recall that metadata.
    let $preview_src = $image.attr("src");
    let payload = asset_map.get($preview_src);
    if (payload === undefined) {
        if ($preview_src.endsWith("&size=full")) {
            // while fetching an image for canvas, `src` attribute supplies
            // full-sized image instead of thumbnail, so we have to replace
            // `size=full` with `size=thumbnail`.
            //
            // TODO: This is a hack to work around the fact that for
            // the lightbox canvas, the `src` is the data-fullsize-src
            // for the image, not the original thumbnail used to open
            // the lightbox.  A better fix will be to check a
            // `data-thumbnail-src` attribute that we add to the
            // canvas elements.
            $preview_src = $preview_src.replace(/.{4}$/, "thumbnail");
            payload = asset_map.get($preview_src);
        }
        if (payload === undefined) {
            payload = exports.parse_image_data($image);
        }
    }

    if (payload.type.match("-video")) {
        display_video(payload);
    } else if (payload.type === "image") {
        display_image(payload, options);
    }

    if (is_open) {
        return;
    }

    function lightbox_close_overlay() {
        $(".player-container iframe").remove();
        is_open = false;
        document.activeElement.blur();
    }

    overlays.open_overlay({
        name: 'lightbox',
        overlay: $("#lightbox_overlay"),
        on_close: lightbox_close_overlay,
    });

    popovers.hide_all();
    is_open = true;
};

exports.show_from_selected_message = function () {
    const $message_selected = $(".selected_message");
    let $message = $message_selected;
    let $image = $message.find(".message_inline_image img");
    let $prev_traverse = false;

    while ($image.length === 0) {
        if ($message.prev().length === 0) {
            $message = $message.parent().prev();
            if ($message.length === 0) {
                $prev_traverse = true;
                $message = $message_selected;
                break;
            } else {
                $message = $message.find(".last_message");
                continue;
            }
        }
        $message = $message.prev();
        $image = $message.find(".message_inline_image img");
    }

    if ($prev_traverse) {
        while ($image.length === 0) {
            if ($message.next().length === 0) {
                $message = $message.parent().next();
                if ($message.length === 0) {
                    break;
                } else {
                    $message = $message.children().first();
                    continue;
                }
            }
            $message = $message.next();
            $image = $message.find(".message_inline_image img");
        }
    }

    if ($image.length !== 0) {
        exports.open($image);
    }
};

// retrieve the metadata from the DOM and store into the asset_map.
exports.parse_image_data = function ($image) {
    const $preview_src = $image.attr("src");
    // if wrapped in the .youtube-video class, it will be length = 1, and therefore
    // cast to true.
    const is_youtube_video = !!$image.closest(".youtube-video").length;
    const is_vimeo_video = !!$image.closest(".vimeo-video").length;
    const is_embed_video = !!$image.closest(".embed-video").length;

    // check if image is descendent of #preview_content
    const is_compose_preview_image = $image.closest("#preview_content").length === 1;

    const $parent = $image.parent();
    let $type;
    let $source;
    const $url = $parent.attr("href");
    if (is_youtube_video) {
        $type = "youtube-video";
        $source = $parent.attr("data-id");
    } else if (is_vimeo_video) {
        $type = "vimeo-video";
        $source = $parent.attr("data-id");
    } else if (is_embed_video) {
        $type = "embed-video";
        $source = $parent.attr("data-id");
    } else {
        $type = "image";
        // thumbor supplies the src as thumbnail, data-src-fullsize as full-sized.
        if ($image.attr("data-src-fullsize")) {
            $source = $image.attr("data-src-fullsize");
        } else {
            $source = $preview_src;
        }
    }
    let sender_full_name;
    if (is_compose_preview_image) {
        sender_full_name = people.my_full_name();
    } else {
        const $message = $parent.closest("[zid]");
        const zid = rows.id($message);
        const message = message_store.get(zid);
        if (message === undefined) {
            blueslip.error("Lightbox for unknown message " + zid);
        } else {
            sender_full_name = message.sender_full_name;
        }
    }
    const payload = {
        user: sender_full_name,
        title: $parent.attr("title"),
        type: $type,
        preview: $preview_src,
        source: $source,
        url: $url,
    };

    asset_map.set($preview_src, payload);
    return payload;
};

exports.prev = function () {
    $(".image-list .image.selected").prev().click();
};

exports.next = function () {
    $(".image-list .image.selected").next().click();
};

// this is a block of events that are required for the lightbox to work.
exports.initialize = function () {
    $("#main_div, #preview_content").on("click", ".message_inline_image a", function (e) {
        // prevent the link from opening in a new page.
        e.preventDefault();
        // prevent the message compose dialog from happening.
        e.stopPropagation();
        const $img = $(this).find("img");
        exports.open($img);
    });

    $("#lightbox_overlay .download").click(function () {
        this.blur();
    });

    $("#lightbox_overlay").on("click", ".image-list .image", function () {
        const $image_list = $(this).parent();
        const original_image = $(".message_row img[src='" + $(this).attr('data-src') + "']");

        exports.open(original_image);

        $(".image-list .image.selected").removeClass("selected");
        $(this).addClass("selected");

        const parentOffset = this.parentNode.clientWidth + this.parentNode.scrollLeft;
        // this is the left and right of the image compared to its parent.
        const coords = {
            left: this.offsetLeft,
            right: this.offsetLeft + this.clientWidth,
        };

        if (coords.right > parentOffset) {
            // add 2px margin
            $image_list.animate({
                scrollLeft: coords.right - this.parentNode.clientWidth + 2,
            }, 100);
        } else if (coords.left < this.parentNode.scrollLeft) {
            // subtract 2px margin
            $image_list.animate({ scrollLeft: coords.left - 2 }, 100);
        }
    });

    $("#lightbox_overlay").on("click", ".center .arrow", function () {
        const direction = $(this).attr("data-direction");

        if (direction === 'next') {
            exports.next();
        } else if (direction === 'prev') {
            exports.prev();
        }
    });

    $("#lightbox_overlay").on("click", ".lightbox-canvas-trigger", function () {
        let $img = $("#lightbox_overlay").find(".image-preview img");

        if ($img.length) {
            $(this).addClass("enabled");
            // the `lightbox.open` function will see the enabled class and
            // enable the `LightboxCanvas` class.
            exports.open($img);
        } else {
            $img = $($("#lightbox_overlay").find(".image-preview canvas")[0].image);

            $(this).removeClass("enabled");
            exports.open($img);
        }
    });

    $("#lightbox_overlay .image-preview").on("dblclick", "img, canvas", function (e) {
        $("#lightbox_overlay .lightbox-canvas-trigger").click();
        e.preventDefault();
    });

    $("#lightbox_overlay .player-container").on("click", function () {
        if ($(this).is(".player-container")) {
            overlays.close_active();
        }
    });

    $("#lightbox_overlay").on("click", ".image-info-wrapper, .center", function (e) {
        if ($(e.target).is(".image-info-wrapper, .center")) {
            overlays.close_overlay("lightbox");
        }
    });
};

window.lightbox = exports;
<commit_msg>lightbox: Parse images' data while rendering `image-list`.<commit_after>let is_open = false;
// the asset map is a map of all retrieved images and YouTube videos that are
// memoized instead of being looked up multiple times.
const asset_map = new Map();

function render_lightbox_list_images(preview_source) {
    if (!is_open) {
        const images = Array.prototype.slice.call($(".focused_table .message_inline_image img"));
        const $image_list = $("#lightbox_overlay .image-list").html("");

        images.forEach(function (img) {
            const src = img.getAttribute("src");
            const className = preview_source === src ? "image selected" : "image";

            const node = $("

", {
                class: className,
                "data-src": src,
            }).css({ backgroundImage: "url(" + src + ")"});

            $image_list.append(node);

            // We parse the data for each image to show in the list,
            // while we still have its original DOM element handy, so
            // that navigating within the list only needs the `src`
            // attribute used to construct the node object above.
            exports.parse_image_data(img);
        }, "");
    }
}

function display_image(payload, options) {
    render_lightbox_list_images(payload.preview);

    $(".player-container").hide();
    $(".image-actions, .image-description, .download, .lightbox-canvas-trigger").show();

    if (options.lightbox_canvas === true) {
        const canvas = document.createElement("canvas");
        canvas.setAttribute("data-src", payload.source);

        $("#lightbox_overlay .image-preview").html(canvas).show();
        const photo = new LightboxCanvas(canvas);
        photo.speed(2.3);
    } else {
        const img = new Image();
        img.src = payload.source;

        $("#lightbox_overlay .image-preview").html(img).show();
    }

    $(".image-description .title").text(payload.title || "N/A");
    $(".image-description .user").text(payload.user);

    $(".image-actions .open, .image-actions .download").attr("href", payload.source);
}

function display_video(payload) {
    render_lightbox_list_images(payload.preview);

    $("#lightbox_overlay .image-preview, .image-description, .download, .lightbox-canvas-trigger").hide();

    let source;
    if (payload.type === "youtube-video") {
        source = "https://www.youtube.com/embed/" + payload.source;
    } else if (payload.type === "vimeo-video") {
        source = "https://player.vimeo.com/video/" + payload.source;
    } else if (payload.type === "embed-video") {
        // Use data: to load the player in a unique origin for security.
        source = "data:text/html," + window.encodeURIComponent(
            "<!DOCTYPE html>" +
                payload.source
        );
    }

    const iframe = $("");
    iframe.attr("sandbox", "allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts");
    iframe.attr("src", source);
    iframe.attr("frameborder", 0);
    iframe.attr("allowfullscreen", true);

    $("#lightbox_overlay .player-container").html(iframe).show();
    $(".image-actions .open").attr("href", payload.url);
}

// the image param is optional, but required on the first preview of an image.
// this will likely be passed in every time but just ignored if the result is already
// stored in the `asset_map`.
exports.open = function (image, options) {
    if (!options) {
        options = {
            // default to showing standard images.
            lightbox_canvas: $(".lightbox-canvas-trigger").hasClass("enabled"),
        };
    }

    const $image = $(image);

    // if the asset_map already contains the metadata required to display the
    // asset, just recall that metadata.
    let $preview_src = $image.attr("src");
    let payload = asset_map.get($preview_src);
    if (payload === undefined) {
        if ($preview_src.endsWith("&size=full")) {
            // while fetching an image for canvas, `src` attribute supplies
            // full-sized image instead of thumbnail, so we have to replace
            // `size=full` with `size=thumbnail`.
            //
            // TODO: This is a hack to work around the fact that for
            // the lightbox canvas, the `src` is the data-fullsize-src
            // for the image, not the original thumbnail used to open
            // the lightbox.  A better fix will be to check a
            // `data-thumbnail-src` attribute that we add to the
            // canvas elements.
            $preview_src = $preview_src.replace(/.{4}$/, "thumbnail");
            payload = asset_map.get($preview_src);
        }
        if (payload === undefined) {
            payload = exports.parse_image_data($image);
        }
    }

    if (payload.type.match("-video")) {
        display_video(payload);
    } else if (payload.type === "image") {
        display_image(payload, options);
    }

    if (is_open) {
        return;
    }

    function lightbox_close_overlay() {
        $(".player-container iframe").remove();
        is_open = false;
        document.activeElement.blur();
    }

    overlays.open_overlay({
        name: 'lightbox',
        overlay: $("#lightbox_overlay"),
        on_close: lightbox_close_overlay,
    });

    popovers.hide_all();
    is_open = true;
};

exports.show_from_selected_message = function () {
    const $message_selected = $(".selected_message");
    let $message = $message_selected;
    let $image = $message.find(".message_inline_image img");
    let $prev_traverse = false;

    while ($image.length === 0) {
        if ($message.prev().length === 0) {
            $message = $message.parent().prev();
            if ($message.length === 0) {
                $prev_traverse = true;
                $message = $message_selected;
                break;
            } else {
                $message = $message.find(".last_message");
                continue;
            }
        }
        $message = $message.prev();
        $image = $message.find(".message_inline_image img");
    }

    if ($prev_traverse) {
        while ($image.length === 0) {
            if ($message.next().length === 0) {
                $message = $message.parent().next();
                if ($message.length === 0) {
                    break;
                } else {
                    $message = $message.children().first();
                    continue;
                }
            }
            $message = $message.next();
            $image = $message.find(".message_inline_image img");
        }
    }

    if ($image.length !== 0) {
        exports.open($image);
    }
};

// retrieve the metadata from the DOM and store into the asset_map.
exports.parse_image_data = function (image) {
    const $image = $(image);
    const $preview_src = $image.attr("src");

    if (asset_map.has($preview_src)) {
        // check if image's data is already present in asset_map.
        return;
    }

    // if wrapped in the .youtube-video class, it will be length = 1, and therefore
    // cast to true.
    const is_youtube_video = !!$image.closest(".youtube-video").length;
    const is_vimeo_video = !!$image.closest(".vimeo-video").length;
    const is_embed_video = !!$image.closest(".embed-video").length;

    // check if image is descendent of #preview_content
    const is_compose_preview_image = $image.closest("#preview_content").length === 1;

    const $parent = $image.parent();
    let $type;
    let $source;
    const $url = $parent.attr("href");
    if (is_youtube_video) {
        $type = "youtube-video";
        $source = $parent.attr("data-id");
    } else if (is_vimeo_video) {
        $type = "vimeo-video";
        $source = $parent.attr("data-id");
    } else if (is_embed_video) {
        $type = "embed-video";
        $source = $parent.attr("data-id");
    } else {
        $type = "image";
        // thumbor supplies the src as thumbnail, data-src-fullsize as full-sized.
        if ($image.attr("data-src-fullsize")) {
            $source = $image.attr("data-src-fullsize");
        } else {
            $source = $preview_src;
        }
    }
    let sender_full_name;
    if (is_compose_preview_image) {
        sender_full_name = people.my_full_name();
    } else {
        const $message = $parent.closest("[zid]");
        const zid = rows.id($message);
        const message = message_store.get(zid);
        if (message === undefined) {
            blueslip.error("Lightbox for unknown message " + zid);
        } else {
            sender_full_name = message.sender_full_name;
        }
    }
    const payload = {
        user: sender_full_name,
        title: $parent.attr("title"),
        type: $type,
        preview: $preview_src,
        source: $source,
        url: $url,
    };

    asset_map.set($preview_src, payload);
    return payload;
};

exports.prev = function () {
    $(".image-list .image.selected").prev().click();
};

exports.next = function () {
    $(".image-list .image.selected").next().click();
};

// this is a block of events that are required for the lightbox to work.
exports.initialize = function () {
    $("#main_div, #preview_content").on("click", ".message_inline_image a", function (e) {
        // prevent the link from opening in a new page.
        e.preventDefault();
        // prevent the message compose dialog from happening.
        e.stopPropagation();
        const $img = $(this).find("img");
        exports.open($img);
    });

    $("#lightbox_overlay .download").click(function () {
        this.blur();
    });

    $("#lightbox_overlay").on("click", ".image-list .image", function () {
        const $image_list = $(this).parent();
        const original_image = $(".message_row img[src='" + $(this).attr('data-src') + "']");

        exports.open(original_image);

        $(".image-list .image.selected").removeClass("selected");
        $(this).addClass("selected");

        const parentOffset = this.parentNode.clientWidth + this.parentNode.scrollLeft;
        // this is the left and right of the image compared to its parent.
        const coords = {
            left: this.offsetLeft,
            right: this.offsetLeft + this.clientWidth,
        };

        if (coords.right > parentOffset) {
            // add 2px margin
            $image_list.animate({
                scrollLeft: coords.right - this.parentNode.clientWidth + 2,
            }, 100);
        } else if (coords.left < this.parentNode.scrollLeft) {
            // subtract 2px margin
            $image_list.animate({ scrollLeft: coords.left - 2 }, 100);
        }
    });

    $("#lightbox_overlay").on("click", ".center .arrow", function () {
        const direction = $(this).attr("data-direction");

        if (direction === 'next') {
            exports.next();
        } else if (direction === 'prev') {
            exports.prev();
        }
    });

    $("#lightbox_overlay").on("click", ".lightbox-canvas-trigger", function () {
        let $img = $("#lightbox_overlay").find(".image-preview img");

        if ($img.length) {
            $(this).addClass("enabled");
            // the `lightbox.open` function will see the enabled class and
            // enable the `LightboxCanvas` class.
            exports.open($img);
        } else {
            $img = $($("#lightbox_overlay").find(".image-preview canvas")[0].image);

            $(this).removeClass("enabled");
            exports.open($img);
        }
    });

    $("#lightbox_overlay .image-preview").on("dblclick", "img, canvas", function (e) {
        $("#lightbox_overlay .lightbox-canvas-trigger").click();
        e.preventDefault();
    });

    $("#lightbox_overlay .player-container").on("click", function () {
        if ($(this).is(".player-container")) {
            overlays.close_active();
        }
    });

    $("#lightbox_overlay").on("click", ".image-info-wrapper, .center", function (e) {
        if ($(e.target).is(".image-info-wrapper, .center")) {
            overlays.close_overlay("lightbox");
        }
    });
};

window.lightbox = exports;
<|endoftext|>


<commit_before>/*globals domChanger*/
window.addEventListener("load", function () {
"use strict";

function SearchApp(emit, refresh) {
  var matches = [], text = "", querying = false;

  return { render: render };

  function render() {
    return ["div",
      ["h3", "Lit Package Search"],
      ["form", { onsubmit: handleSubmit },
        ["input", {
          onchange: onChange,
          value: text
        }],
        ["button", "Search"]
      ],
      (querying ? ["p", "Querying..."] : [SearchResults, matches])
    ];
  }

  function handleSubmit(evt) {
    evt.preventDefault();
    querying = true;
    refresh();
    var xhr = createCORSRequest("GET", "http://lit.luvit.io/search/" + window.escape(text));
    if (!xhr) { throw new Error("Your browser doesn't appear to support CORS requests"); }
    xhr.send();
    xhr.onerror = function () {
      throw new Error("There was a problem making the request");
    };
    xhr.onload = function () {
      var result = JSON.parse(xhr.responseText);
      matches.length = 0;
      querying = false;
      var keys = Object.keys(result.matches);
      for (var i = 0, l = keys.length; i < l; i++) {
        var key = keys[i];
        var match = result.matches[key];
        match.name = key;
        matches[i] = match;
      }
      refresh();
    };
  }

  function onChange(evt) {
    text = evt.target.value;
  }
}

function SearchResults() {
  return { render: render };
  function render(matches) {
    return ["ul", matches.map(function (match) {
      return ["li", match.name];
    })];
  }
}

var container = document.getElementById("lit-browser");
container.textContent = "";
domChanger(SearchApp, container).update();

function createCORSRequest(method, url) {
  var xhr = new XMLHttpRequest();
  if ("withCredentials" in xhr) {

    // Check if the XMLHttpRequest object has a "withCredentials" property.
    // "withCredentials" only exists on XMLHTTPRequest2 objects.
    xhr.open(method, url, true);

  } else if (typeof XDomainRequest !== "undefined") {

    // Otherwise, check if XDomainRequest.
    // XDomainRequest only exists in IE, and is IE's way of making CORS requests.
    xhr = new XDomainRequest();
    xhr.open(method, url);

  } else {

    // Otherwise, CORS is not supported by the browser.
    xhr = null;

  }
  return xhr;
}

}, false);
<commit_msg>Match http/https of host<commit_after>/*globals domChanger*/
window.addEventListener("load", function () {
"use strict";

function SearchApp(emit, refresh) {
  var matches = [], text = "", querying = false;

  return { render: render };

  function render() {
    return ["div",
      ["h3", "Lit Package Search"],
      ["form", { onsubmit: handleSubmit },
        ["input", {
          onchange: onChange,
          value: text
        }],
        ["button", "Search"]
      ],
      (querying ? ["p", "Querying..."] : [SearchResults, matches])
    ];
  }

  function handleSubmit(evt) {
    evt.preventDefault();
    querying = true;
    refresh();
    var xhr = createCORSRequest("GET", "//lit.luvit.io/search/" + window.escape(text));
    if (!xhr) { throw new Error("Your browser doesn't appear to support CORS requests"); }
    xhr.send();
    xhr.onerror = function () {
      throw new Error("There was a problem making the request");
    };
    xhr.onload = function () {
      var result = JSON.parse(xhr.responseText);
      matches.length = 0;
      querying = false;
      var keys = Object.keys(result.matches);
      for (var i = 0, l = keys.length; i < l; i++) {
        var key = keys[i];
        var match = result.matches[key];
        match.name = key;
        matches[i] = match;
      }
      refresh();
    };
  }

  function onChange(evt) {
    text = evt.target.value;
  }
}

function SearchResults() {
  return { render: render };
  function render(matches) {
    return ["ul", matches.map(function (match) {
      return ["li", match.name];
    })];
  }
}

var container = document.getElementById("lit-browser");
container.textContent = "";
domChanger(SearchApp, container).update();

function createCORSRequest(method, url) {
  var xhr = new XMLHttpRequest();
  if ("withCredentials" in xhr) {

    // Check if the XMLHttpRequest object has a "withCredentials" property.
    // "withCredentials" only exists on XMLHTTPRequest2 objects.
    xhr.open(method, url, true);

  } else if (typeof XDomainRequest !== "undefined") {

    // Otherwise, check if XDomainRequest.
    // XDomainRequest only exists in IE, and is IE's way of making CORS requests.
    xhr = new XDomainRequest();
    xhr.open(method, url);

  } else {

    // Otherwise, CORS is not supported by the browser.
    xhr = null;

  }
  return xhr;
}

}, false);
<|endoftext|>


<commit_before>utilities.namespace("SymPy");
SymPy.DEFAULT_ANIMATION_DURATION = 500;
SymPy.SphinxShell = SymPy.Shell.$extend({
    evalModeTypes: ['eval', 'copy'],
    evalMode: 'eval',

    __init__: function(config) {
        this.$super(config);
        this.visible = true;
        this.queuedStatements = [];

        index = this.evalModeTypes.indexOf(config.record);
        this.evalMode = (index == -1) ? this.getCookie('sympy-evalMode', 'eval') : config.evalMode;
        this.banner = config.banner ? config.banner : '';
    },

    render: function(el) {
        this.$super(el);

        this.shellEl = $(el);

        var headerLink =
            $('SymPy Live Shell');
        var header = $("
").append(headerLink);
        this.shellEl.prepend(header);

        this.toggleShellEl = $('<button/>').
            html("Hide SymPy Live Shell").
            attr("id", "toggleShell").
            addClass('shown');
        this.toggleShellEl.prepend($('
'));

        this.toggleShellEl.appendTo(document.body);
        this.toggleShellEl.click($.proxy(function() {
            this.toggle();
        }, this));

        // Add a link to Python code that will evaluate it in SymPy Live
        this.processCodeBlocks();

        // Don't expand the list of tab completions (saves space)
        this.completer.expandCompletions = false;

        // Change Fullscreen to go to main website
        $("#fullscreen-button").html("Go to SymPy Live");

	    this.evalModeEl.change($.proxy(function(event) {
            this.updateSettings();
            this.focus();
        }, this));
    },

    renderToolbar: function(settings) {
        this.$super(settings);

        $('
Settings
').
            prependTo($("#settings")).
            click($.proxy(this.toggleSettings, this));
        $("#settings h3").prepend($('
'));

        // We don't need the "force desktop version" option since there is
        // no mobile version
        var checkbox = $('#settings input[type="checkbox"]');
        checkbox.prev().hide();
        checkbox.next().hide();
        checkbox.hide();

        this.toolbarEl.append(
            $('
'),
            $('Evaluation Mode:'),
            $('<select id="evalMode"/>').append(
                $('<option value="eval">Evaluate</option>'),
                $('<option value="copy">Copy</option>')
            ),
            $('
')
        );
        this.evalModeEl = $('#evalMode');

        var index = this.evalModeTypes.indexOf(this.evalMode);
        this.evalModeEl.children('option')[index].selected = true;

        // Make enter the default submission button
        $("#submit-behavior").val("enter");
    },

    done: function(response) {
        this.$super(response);
        if (this.queuedStatements.length !== 0) {
            this.dequeueStatement();
            this.evaluate();
        }
    },

    error: function(xhr, status, error) {
        this.$super(xhr, status, error);
        this.queuedStatements.length = 0;
    },

    dequeueStatement: function() {
        if (this.queuedStatements.length !== 0) {
            var statements = this.queuedStatements.shift();
            this.setValue(statements.join('\n'));
        }
    },

    processCodeBlocks: function() {
        $('.highlight-python').each($.proxy(function(index, el) {
            var el = $(el);

            // Add the toolbar
            var container = $("
").addClass('sympy-live-eval-toolbar');
            var evaluate = $("<button>Run in SymPy Live</button>").
                addClass('sympy-live-eval-button').
                appendTo(container);
            el.children('.highlight').prepend(container);

            var fillShell = $.proxy(function() {
                this.show();
                var code = el.find('pre').text();
                var lines = code.split(/\n/g);

                // We want to evaluate each block individually
                var codeBlocks = [];
                var currentBlock = [];
                for (var i = 0; i < lines.length; i++) {
                    if (lines[i].substring(0, 4) === ">>> ") {
                        codeBlocks.push(currentBlock);
                        currentBlock = [];

                        currentBlock.push(
                            lines[i].substring(4, lines[i].length));
                    }
                    else if (lines[i].substring(0, 4) === "... ") {
                        currentBlock.push(
                            lines[i].substring(4, lines[i].length));
                    }
                }
                if (currentBlock.length !== 0) {
                    codeBlocks.push(currentBlock);
                }
                codeBlocks = codeBlocks.slice(1);
                this.queuedStatements = codeBlocks;
            }, this);

            evaluate.click($.proxy(function() {
                fillShell();
                this.dequeueStatement();
                if (this.evalModeEl.val() === "eval") {
                    this.evaluate();
                }
                else {
                    this.focus();
                }
            }, this));

            this.processIndividualCodeBlocks(el.find('pre'));
        }, this));
    },

    processIndividualCodeBlocks: function(codeEl) {
        // childNodes gives text nodes which we want for whitespace
        var childNodes = codeEl.get(0).childNodes;
        var currentLine = [];
        var lines = [];

        for (var i = 0; i < childNodes.length; i++) {
            var domNode = childNodes[i];
            if (domNode.nodeType === domNode.ELEMENT_NODE) {
                currentLine.push(domNode.cloneNode(true));

                if (currentLine.length === 1 &&
                    domNode.innerText.substr(0, 3) === "...") {
                    // First node on line and continuation, so continue from
                    // the previous line
                    currentLine = lines.pop();
                    currentLine.push(domNode.cloneNode(true));
                }
            }
            else if (domNode.nodeType === domNode.TEXT_NODE) {
                currentLine.push(domNode.cloneNode(true));
                if (domNode.data.substr(-1) === '\n') {
                    lines.push(currentLine);
                    currentLine = [];
                }
            }
        }
        codeEl.empty();
        for (var i = 0; i < lines.length; i++) {
            var line = $('
');
            var processingLine = lines[i];
            if (processingLine[0].innerText.substr(0, 4) === ">>> ") {
                line.addClass('live-statement');
            }
            line.append(processingLine);
            line.click($.proxy((function(line) {
                // Save the current line
                return function() {
                    var lines = line.text().split(/\n/g);
                    var strippedLines = [];
                    for (var i = 0; i < lines.length; i++) {
                        strippedLines.push(lines[i].slice(4));
                    }
                    this.setValue(strippedLines.join('\n').trim());
                    this.show();
                    if (this.evalModeEl.val() === "eval") {
                        this.evaluate();
                    }
                    else {
                        this.focus();
                    }
                }
            })(line), this));
            codeEl.append(line);
        }
    },

    hide: function(duration) {
        if (typeof duration === "undefined") {
            duration = SymPy.DEFAULT_ANIMATION_DURATION;
        }
        this.disablePrompt();

        this.shellDimensionsRestored = {
            width: this.shellEl.width(),
            height: this.shellEl.height(),
            opacity: 1
        };

        this.shellEl.animate({
            width: 0,
            height: 0,
            opacity: 0
        }, duration);
        this.visible = false;

        this.toggleShellEl.removeClass('shown').children('span').
            html("Show SymPy Live Shell");
    },

    show: function(duration) {
        if (this.visible) return;

        if (typeof duration === "undefined") {
            duration = SymPy.DEFAULT_ANIMATION_DURATION;
        }
        this.enablePrompt();
        $(this.shellEl).animate(
            this.shellDimensionsRestored,
            duration,
            function() {
                // Don't fix the height so that if the settings are
                // expanded, the shell will expand with them
                $(this).css('height', 'auto');
            });
        this.visible = true;
        this.toggleShellEl.addClass('shown').children('span').
            html("Hide SymPy Live Shell");
    },

    toggle: function(duration) {
        if (typeof duration === "undefined") {
            duration = SymPy.DEFAULT_ANIMATION_DURATION;
        }
        if (this.isVisible()) {
            this.hide(duration);
        }
        else {
            this.show(duration);
        }
    },

    toggleSettings: function(duration) {
        if (typeof duration === "undefined") {
            duration = SymPy.DEFAULT_ANIMATION_DURATION;
        }

        if ($("#settings .content").is(":visible")) {
            $("#settings .content").slideUp(duration);
            $("#settings h3").removeClass('shown');
        }
        else {
            $("#settings .content").slideDown(duration);
            $("#settings h3").addClass('shown');
        }
    },

    isVisible: function() {
        return this.visible;
    },

    fullscreen: function() {
        window.open("http://live.sympy.org");
    },

    updateSettings: function() {
        this.$super();
        this.setCookie('sympy-evalMode', this.evalModeEl.val());
    }
});

$(document).ready(function() {
    var path = SymPy.getBasePath('live-sphinx.js');

    $.get(path + '/sphinxbanner').done(function(data) {
        var shellEl = $('
').appendTo($(document.body));
        var settingsEl = $('

');
        settingsEl.appendTo(shellEl);  // Needed to render the shell

        var shell = new SymPy.SphinxShell({
            baseName: 'live-sphinx.js',
            banner: data
        });
        shell.render(shellEl);
        settingsEl.appendTo(shellEl); // Put it under the shell
        shell.toggleSettings();
        shell.hide(0);
    });
});
<commit_msg>Sphinx: copy mode copies entire code block<commit_after>utilities.namespace("SymPy");
SymPy.DEFAULT_ANIMATION_DURATION = 500;
SymPy.SphinxShell = SymPy.Shell.$extend({
    evalModeTypes: ['eval', 'copy'],
    evalMode: 'eval',

    __init__: function(config) {
        this.$super(config);
        this.visible = true;
        this.queuedStatements = [];

        index = this.evalModeTypes.indexOf(config.record);
        this.evalMode = (index == -1) ? this.getCookie('sympy-evalMode', 'eval') : config.evalMode;
        this.banner = config.banner ? config.banner : '';
    },

    render: function(el) {
        this.$super(el);

        this.shellEl = $(el);

        var headerLink =
            $('SymPy Live Shell');
        var header = $("
").append(headerLink);
        this.shellEl.prepend(header);

        this.toggleShellEl = $('<button/>').
            html("Hide SymPy Live Shell").
            attr("id", "toggleShell").
            addClass('shown');
        this.toggleShellEl.prepend($('
'));

        this.toggleShellEl.appendTo(document.body);
        this.toggleShellEl.click($.proxy(function() {
            this.toggle();
        }, this));

        // Add a link to Python code that will evaluate it in SymPy Live
        this.processCodeBlocks();

        // Don't expand the list of tab completions (saves space)
        this.completer.expandCompletions = false;

        // Change Fullscreen to go to main website
        $("#fullscreen-button").html("Go to SymPy Live");

	    this.evalModeEl.change($.proxy(function(event) {
            this.updateSettings();
            this.focus();
        }, this));
    },

    renderToolbar: function(settings) {
        this.$super(settings);

        $('
Settings
').
            prependTo($("#settings")).
            click($.proxy(this.toggleSettings, this));
        $("#settings h3").prepend($('
'));

        // We don't need the "force desktop version" option since there is
        // no mobile version
        var checkbox = $('#settings input[type="checkbox"]');
        checkbox.prev().hide();
        checkbox.next().hide();
        checkbox.hide();

        this.toolbarEl.append(
            $('
'),
            $('Evaluation Mode:'),
            $('<select id="evalMode"/>').append(
                $('<option value="eval">Evaluate</option>'),
                $('<option value="copy">Copy</option>')
            ),
            $('
')
        );
        this.evalModeEl = $('#evalMode');

        var index = this.evalModeTypes.indexOf(this.evalMode);
        this.evalModeEl.children('option')[index].selected = true;

        // Make enter the default submission button
        $("#submit-behavior").val("enter");
    },

    done: function(response) {
        this.$super(response);
        if (this.queuedStatements.length !== 0) {
            this.dequeueStatement();
            this.evaluate();
        }
    },

    error: function(xhr, status, error) {
        this.$super(xhr, status, error);
        this.queuedStatements.length = 0;
    },

    dequeueStatement: function() {
        if (this.queuedStatements.length !== 0) {
            this.setValue(this.queuedStatements.shift());
        }
    },

    processCodeBlocks: function() {
        $('.highlight-python').each($.proxy(function(index, el) {
            var el = $(el);

            // Add the toolbar
            var container = $("
").addClass('sympy-live-eval-toolbar');
            var evaluate = $("<button>Run in SymPy Live</button>").
                addClass('sympy-live-eval-button').
                appendTo(container);
            el.children('.highlight').prepend(container);

            evaluate.click($.proxy(function() {
                this.show();
                var statementBlocks = el.find('div.live-statement');
                var codeBlocks = [];
                for (var i = 0; i < statementBlocks.length; i++) {
                    codeBlocks.push(
                        this.stripCode($(statementBlocks[i]).text())
                    );
                }
                if (this.evalModeEl.val() === "eval") {
                    this.queuedStatements = codeBlocks;
                    this.dequeueStatement();
                    this.evaluate();
                }
                else {
                    this.setValue(codeBlocks.join("\n"));
                    this.focus();
                }
            }, this));

            this.processIndividualCodeBlocks(el.find('pre'));
        }, this));
    },

    processIndividualCodeBlocks: function(codeEl) {
        // childNodes gives text nodes which we want for whitespace
        var childNodes = codeEl.get(0).childNodes;
        var currentLine = [];
        var lines = [];

        for (var i = 0; i < childNodes.length; i++) {
            var domNode = childNodes[i];
            if (domNode.nodeType === domNode.ELEMENT_NODE) {
                currentLine.push(domNode.cloneNode(true));

                if (currentLine.length === 1 &&
                    domNode.innerText.substr(0, 3) === "...") {
                    // First node on line and continuation, so continue from
                    // the previous line
                    currentLine = lines.pop();
                    currentLine.push(domNode.cloneNode(true));
                }
            }
            else if (domNode.nodeType === domNode.TEXT_NODE) {
                currentLine.push(domNode.cloneNode(true));
                if (domNode.data.substr(-1) === '\n') {
                    lines.push(currentLine);
                    currentLine = [];
                }
            }
        }
        codeEl.empty();
        for (var i = 0; i < lines.length; i++) {
            var line = $('
');
            var processingLine = lines[i];
            if (processingLine[0].innerText.substr(0, 4) === ">>> ") {
                line.addClass('live-statement');
            }
            line.append(processingLine);
            line.click($.proxy((function(line) {
                // Save the current line
                return function() {
                    this.setValue(this.stripCode(line.text()));
                    this.show();
                    if (this.evalModeEl.val() === "eval") {
                        this.evaluate();
                    }
                    else {
                        this.focus();
                    }
                }
            })(line), this));
            codeEl.append(line);
        }
    },

    // Strips >>> and ... from a string
    stripCode: function(text) {
        var lines = text.split(/\n/g);
        var strippedLines = [];
        for (var i = 0; i < lines.length; i++) {
            strippedLines.push(lines[i].slice(4));
        }
        return strippedLines.join('\n').trim();
    },

    hide: function(duration) {
        if (typeof duration === "undefined") {
            duration = SymPy.DEFAULT_ANIMATION_DURATION;
        }
        this.disablePrompt();

        this.shellDimensionsRestored = {
            width: this.shellEl.width(),
            height: this.shellEl.height(),
            opacity: 1
        };

        this.shellEl.animate({
            width: 0,
            height: 0,
            opacity: 0
        }, duration);
        this.visible = false;

        this.toggleShellEl.removeClass('shown').children('span').
            html("Show SymPy Live Shell");
    },

    show: function(duration) {
        if (this.visible) return;

        if (typeof duration === "undefined") {
            duration = SymPy.DEFAULT_ANIMATION_DURATION;
        }
        this.enablePrompt();
        $(this.shellEl).animate(
            this.shellDimensionsRestored,
            duration,
            function() {
                // Don't fix the height so that if the settings are
                // expanded, the shell will expand with them
                $(this).css('height', 'auto');
            });
        this.visible = true;
        this.toggleShellEl.addClass('shown').children('span').
            html("Hide SymPy Live Shell");
    },

    toggle: function(duration) {
        if (typeof duration === "undefined") {
            duration = SymPy.DEFAULT_ANIMATION_DURATION;
        }
        if (this.isVisible()) {
            this.hide(duration);
        }
        else {
            this.show(duration);
        }
    },

    toggleSettings: function(duration) {
        if (typeof duration === "undefined") {
            duration = SymPy.DEFAULT_ANIMATION_DURATION;
        }

        if ($("#settings .content").is(":visible")) {
            $("#settings .content").slideUp(duration);
            $("#settings h3").removeClass('shown');
        }
        else {
            $("#settings .content").slideDown(duration);
            $("#settings h3").addClass('shown');
        }
    },

    isVisible: function() {
        return this.visible;
    },

    fullscreen: function() {
        window.open("http://live.sympy.org");
    },

    updateSettings: function() {
        this.$super();
        this.setCookie('sympy-evalMode', this.evalModeEl.val());
    }
});

$(document).ready(function() {
    var path = SymPy.getBasePath('live-sphinx.js');

    $.get(path + '/sphinxbanner').done(function(data) {
        var shellEl = $('
').appendTo($(document.body));
        var settingsEl = $('

');
        settingsEl.appendTo(shellEl);  // Needed to render the shell

        var shell = new SymPy.SphinxShell({
            baseName: 'live-sphinx.js',
            banner: data
        });
        shell.render(shellEl);
        settingsEl.appendTo(shellEl); // Put it under the shell
        shell.toggleSettings();
        shell.hide(0);
    });
});
<|endoftext|>


<commit_before>let EXPORTED_SYMBOLS = [
    "assert",
  ];

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import("resource://crownconstruction/modules/configs.js");
Cu.import("resource://crownconstruction/modules/log.js");

function assert(condition, message)
{
  if(condition)
    return;

  let logger = log.getLogger("ASSERT");

  if(!configs.get("debug")) {
    logger.fatal(message);
    return;
  }

  let caller = arguments.callee.caller;
  let stackText = "Stack Trace: \n";
  let count = 0;
  while(caller)
  {
    stackText += count++ + ":" + caller.name + "(";
    for(let i = 0; i < caller.arguments.length; ++i) {
      let arg = caller.arguments[i];
      stackText += arg;
      if (i < caller.arguments.length - 1)
        stackText += ",";
    }
    stackText += ")\n";
    caller = caller.arguments.callee.caller;
  }

  var source = null;
  if (this.window)
    source = this.window;
  var ps = Cc["@mozilla.org/embedcomp/prompt-service;1"].
           getService(Ci.nsIPromptService);
  ps.alert(source, "Assertion Failed", message);
  dump("\n! ASSERTION FAILED:\n"+ stackText +"\n");
}
<commit_msg>assert() now throws an error when in debug mode<commit_after>let EXPORTED_SYMBOLS = [
    "assert",
  ];

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import("resource://crownconstruction/modules/configs.js");
Cu.import("resource://crownconstruction/modules/log.js");

function assert(condition, message)
{
  if(condition)
    return;

  let logger = log.getLogger("ASSERT");

  if(!configs.get("debug")) {
    logger.fatal(message);
    return;
  }

  let caller = arguments.callee.caller;
  let stackText = "Stack Trace: \n";
  let count = 0;
  while(caller)
  {
    stackText += count++ + ":" + caller.name + "(";
    for(let i = 0; i < caller.arguments.length; ++i) {
      let arg = caller.arguments[i];
      stackText += arg;
      if(i < caller.arguments.length - 1)
        stackText += ",";
    }
    stackText += ")\n";
    caller = caller.arguments.callee.caller;
  }

  var source = null;
  if (this.window)
    source = this.window;
  var ps = Cc["@mozilla.org/embedcomp/prompt-service;1"].
           getService(Ci.nsIPromptService);
  ps.alert(source, "Assertion Failed", message);
  dump("\n! ASSERTION FAILED:\n"+ stackText +"\n");

  throw new Error("ASSERTION FAILED: "+ message);
}
<|endoftext|>