<commit_before>process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';  // We need this for testing with self signed certs

const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // eslint-disable-line import/no-extraneous-dependencies
const newIo = require('socket.io-client'); // eslint-disable-line import/no-extraneous-dependencies
const nodeUrl = require('url');
const Erizo = require('./erizofc');
const NativeStream = require('./NativeStream.js');
const NativeStack = require('./NativeStack.js');
const logger = require('./logger').logger;

const fakeConnection = NativeStack;
const log = logger.getLogger('ErizoSimpleNativeConnection');

exports.ErizoSimpleNativeConnection = (spec, callback, error) => {
  const that = {};

  let localStream = {};
  const availableStreams = new Map();

  let room = '';
  that.isActive = false;
  localStream.getID = () => 0;
  const createToken = (userName, role, tokenCallback) => {
    const req = new XMLHttpRequest();
    const theUrl = nodeUrl.parse(spec.serverUrl, true);
    if (theUrl.protocol !== 'https') {
      log.warn('Protocol is not https');
    }

    if (theUrl.query.room) {
      room = theUrl.query.room;
      log.info('will Connect to Room', room);
    }

    theUrl.pathname += 'createToken/';

    const url = nodeUrl.format(theUrl);
    log.info('Url to createToken', url);
    const body = { username: userName, role };

    req.onreadystatechange = () => {
      if (req.readyState === 4) {
        if (req.status === 200) {
          tokenCallback(req.responseText);
        } else {
          log.error('Could not get token');
          tokenCallback('error');
        }
      }
    };

    req.open('POST', url, true);
    req.setRequestHeader('Content-Type', 'application/json');
    req.send(JSON.stringify(body));
  };

  const subscribeToStreams = (streams) => {
    streams.forEach((stream) => {
      if (spec.subscribeConfig) {
        log.info('Should subscribe', spec.subscribeConfig);
        room.subscribe(stream, spec.subscribeConfig);
      }
    });
  };

  const createConnection = () => {
    createToken('name', 'presenter', (token) => {
      log.info('Getting token', token);
      if (token === 'error') {
        error(`Could not get token from nuve in ${spec.serverUrl}`);
        return;
      }
      room = Erizo.Room(newIo, fakeConnection, { token });

      room.addEventListener('room-connected', (roomEvent) => {
        log.info('Connected to room');
        callback('room-connected');
        that.isActive = true;
        subscribeToStreams(roomEvent.streams);
        if (spec.publishConfig) {
          log.info('Will publish with config', spec.publishConfig);
          localStream = NativeStream.Stream(fakeConnection, spec.publishConfig);
          room.publish(localStream, spec.publishConfig, (id, message) => {
            if (id === undefined) {
              log.error('ERROR when publishing', message);
              error(message);
            }
          });
        }
      });

      room.addEventListener('stream-added', (roomEvent) => {
        log.info('stream added', roomEvent.stream.getID());
        callback('stream-added');
        if (roomEvent.stream.getID() !== localStream.getID()) {
          const streams = [];
          streams.push(roomEvent.stream);
          subscribeToStreams(streams);
        } else {
          log.error('Adding localStream, id', localStream.getID());
          availableStreams.set(localStream.getID(), localStream);
        }
      });

      room.addEventListener('stream-removed', (roomEvent) => {
        callback('stream-removed');
        const eventStreamId = roomEvent.stream.getID();
        if (eventStreamId !== localStream.getID()) {
          room.unsubscribe(roomEvent.stream);
          log.info('stream removed', eventStreamId);
        }
        availableStreams.delete(eventStreamId);
      });

      room.addEventListener('stream-subscribed', (streamEvent) => {
        log.info('stream-subscribed');
        callback('stream-subscribed');
        availableStreams.set(streamEvent.stream.getID(), streamEvent.stream);
      });

      room.addEventListener('room-error', (roomEvent) => {
        log.error('Room Error', roomEvent.type, roomEvent.message);
        error(roomEvent.message);
      });

      room.addEventListener('room-disconnected', (roomEvent) => {
        log.info('Room Disconnected', roomEvent.type, roomEvent.message);
        callback(roomEvent.type + roomEvent.message);
      });

      room.connect();
    });

    that.sendData = () => {
      localStream.sendData({ msg: 'Testing Data Connection' });
    };
  };

  that.close = () => {
    log.info('Close');
    room.disconnect();
  };

  that.getStats = () => {
    const promises = [];
    availableStreams.forEach((stream, streamId) => {
      if (stream.pc && stream.pc.peerConnection && stream.pc.peerConnection.connected) {
        promises.push(stream.pc.peerConnection.getStats());
      } else {
        log.warn('No stream to ask for stats: ', streamId);
        promises.push('failed');
      }
    });
    return Promise.all(promises);
  };

  that.getStatus = () => {
    if (availableStreams.length === 0) {
      return ['disconnected'];
    }
    const connectionStatus = [];
    availableStreams.forEach((stream) => {
      if (!stream.pc || !stream.pc.peerConnection || !stream.pc.peerConnection.connected) {
        connectionStatus.push('disconnected');
      }
      connectionStatus.push('connected');
    });
    return connectionStatus;
  };

  createConnection();
  return that;
};
<commit_msg>Fix Spine to use different rooms (#1020)<commit_after>process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';  // We need this for testing with self signed certs

const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; // eslint-disable-line import/no-extraneous-dependencies
const newIo = require('socket.io-client'); // eslint-disable-line import/no-extraneous-dependencies
const nodeUrl = require('url');
const Erizo = require('./erizofc');
const NativeStream = require('./NativeStream.js');
const NativeStack = require('./NativeStack.js');
const logger = require('./logger').logger;

const fakeConnection = NativeStack;
const log = logger.getLogger('ErizoSimpleNativeConnection');

exports.ErizoSimpleNativeConnection = (spec, callback, error) => {
  const that = {};

  let localStream = {};
  const availableStreams = new Map();

  let room = '';
  that.isActive = false;
  localStream.getID = () => 0;
  const createToken = (userName, role, tokenCallback) => {
    const req = new XMLHttpRequest();
    const theUrl = nodeUrl.parse(spec.serverUrl, true);
    if (theUrl.protocol !== 'https') {
      log.warn('Protocol is not https');
    }

    if (theUrl.query.room) {
      room = theUrl.query.room;
      log.info('will Connect to Room', room);
    }

    theUrl.pathname += 'createToken/';

    const url = nodeUrl.format(theUrl);
    log.info('Url to createToken', url);
    const body = { username: userName, role, room };

    req.onreadystatechange = () => {
      if (req.readyState === 4) {
        if (req.status === 200) {
          tokenCallback(req.responseText);
        } else {
          log.error('Could not get token');
          tokenCallback('error');
        }
      }
    };

    req.open('POST', url, true);
    req.setRequestHeader('Content-Type', 'application/json');
    req.send(JSON.stringify(body));
  };

  const subscribeToStreams = (streams) => {
    streams.forEach((stream) => {
      if (spec.subscribeConfig) {
        log.info('Should subscribe', spec.subscribeConfig);
        room.subscribe(stream, spec.subscribeConfig);
      }
    });
  };

  const createConnection = () => {
    createToken('name', 'presenter', (token) => {
      log.info('Getting token', token);
      if (token === 'error') {
        error(`Could not get token from nuve in ${spec.serverUrl}`);
        return;
      }
      room = Erizo.Room(newIo, fakeConnection, { token });

      room.addEventListener('room-connected', (roomEvent) => {
        log.info('Connected to room');
        callback('room-connected');
        that.isActive = true;
        subscribeToStreams(roomEvent.streams);
        if (spec.publishConfig) {
          log.info('Will publish with config', spec.publishConfig);
          localStream = NativeStream.Stream(fakeConnection, spec.publishConfig);
          room.publish(localStream, spec.publishConfig, (id, message) => {
            if (id === undefined) {
              log.error('ERROR when publishing', message);
              error(message);
            }
          });
        }
      });

      room.addEventListener('stream-added', (roomEvent) => {
        log.info('stream added', roomEvent.stream.getID());
        callback('stream-added');
        if (roomEvent.stream.getID() !== localStream.getID()) {
          const streams = [];
          streams.push(roomEvent.stream);
          subscribeToStreams(streams);
        } else {
          log.error('Adding localStream, id', localStream.getID());
          availableStreams.set(localStream.getID(), localStream);
        }
      });

      room.addEventListener('stream-removed', (roomEvent) => {
        callback('stream-removed');
        const eventStreamId = roomEvent.stream.getID();
        if (eventStreamId !== localStream.getID()) {
          room.unsubscribe(roomEvent.stream);
          log.info('stream removed', eventStreamId);
        }
        availableStreams.delete(eventStreamId);
      });

      room.addEventListener('stream-subscribed', (streamEvent) => {
        log.info('stream-subscribed');
        callback('stream-subscribed');
        availableStreams.set(streamEvent.stream.getID(), streamEvent.stream);
      });

      room.addEventListener('room-error', (roomEvent) => {
        log.error('Room Error', roomEvent.type, roomEvent.message);
        error(roomEvent.message);
      });

      room.addEventListener('room-disconnected', (roomEvent) => {
        log.info('Room Disconnected', roomEvent.type, roomEvent.message);
        callback(roomEvent.type + roomEvent.message);
      });

      room.connect();
    });

    that.sendData = () => {
      localStream.sendData({ msg: 'Testing Data Connection' });
    };
  };

  that.close = () => {
    log.info('Close');
    room.disconnect();
  };

  that.getStats = () => {
    const promises = [];
    availableStreams.forEach((stream, streamId) => {
      if (stream.pc && stream.pc.peerConnection && stream.pc.peerConnection.connected) {
        promises.push(stream.pc.peerConnection.getStats());
      } else {
        log.warn('No stream to ask for stats: ', streamId);
        promises.push('failed');
      }
    });
    return Promise.all(promises);
  };

  that.getStatus = () => {
    if (availableStreams.length === 0) {
      return ['disconnected'];
    }
    const connectionStatus = [];
    availableStreams.forEach((stream) => {
      if (!stream.pc || !stream.pc.peerConnection || !stream.pc.peerConnection.connected) {
        connectionStatus.push('disconnected');
      }
      connectionStatus.push('connected');
    });
    return connectionStatus;
  };

  createConnection();
  return that;
};
<|endoftext|>


<commit_before>//* @protected
enyo.xhr = {
	/**
		inParams is an Object that may contain these properties:

		- _url_: The URL to request (required).
		- _method_: The HTTP method to use for the request. Defaults to GET.
		- _callback_: Called when request is completed.
		- _body_: Specific contents for the request body for POST method.
		- _headers_: Request headers.
		- _username_: The optional user name to use for authentication purposes.
		- _password_: The optional password to use for authentication purposes.
		- _xhrFields_: Optional object containing name/value pairs to mix directly into the generated xhr object.
		- _mimeType_: Optional string to override the MIME-Type.
	*/
	request: function(inParams) {
		var xhr = this.getXMLHttpRequest(inParams.url);
		//
		var method = inParams.method || "GET";
		var async = ("sync" in inParams) ? !inParams.sync : true;
		//
		if (inParams.username) {
			xhr.open(method, enyo.path.rewrite(inParams.url), async, inParams.username, inParams.password);
		} else {
			xhr.open(method, enyo.path.rewrite(inParams.url), async);
		}
		//
		enyo.mixin(xhr, inParams.xhrFields);
		//
		this.makeReadyStateHandler(xhr, inParams.callback);
		if (inParams.headers) {
			for (var key in inParams.headers) {
				xhr.setRequestHeader(key, inParams.headers[key]);
			}
		}
		//
		if(typeof(xhr.overrideMimeType) == "function" && inParams.mimeType) {
			xhr.overrideMimeType(inParams.mimeType);
		}
		//
		xhr.send(inParams.body || null);
		if (!async) {
			xhr.onreadystatechange(xhr);
		}
		return xhr;
	},
	//* @protected
	makeReadyStateHandler: function(inXhr, inCallback) {
		if (window.XDomainRequest && inXhr instanceof XDomainRequest) {
			inXhr.onload = function() {
				inCallback && inCallback.apply(null, [inXhr.responseText, inXhr]);
			};
		}
		inXhr.onreadystatechange = function() {
			if (inXhr.readyState == 4) {
				inCallback && inCallback.apply(null, [inXhr.responseText, inXhr]);
			}
		};
	},
	inOrigin: function(inUrl) {
		var a = document.createElement("a"), result = false;
		a.href = inUrl;
		if (a.protocol === ":" ||
				(a.protocol === window.location.protocol &&
					a.hostname === window.location.hostname &&
					a.port === (window.location.port || 80))) {
			result = true;
		}
		return result;
	},
	getXMLHttpRequest: function(inUrl) {
		try {
			if (window.XDomainRequest && !this.inOrigin(inUrl) && !/^file:\/\//.test(window.location.href)) {
				return new XDomainRequest();
			}
		} catch(e) {}
		try {
			return new XMLHttpRequest();
		} catch(e) {}
		try {
			return new ActiveXObject('Msxml2.XMLHTTP');
		} catch(e) {}
		try {
			return new ActiveXObject('Microsoft.XMLHTTP');
		} catch(e) {}
		return null;
	}
};
<commit_msg>Update source/ajax/xhr.js<commit_after>//* @protected
enyo.xhr = {
	/**
		inParams is an Object that may contain these properties:

		- _url_: The URL to request (required).
		- _method_: The HTTP method to use for the request. Defaults to GET.
		- _callback_: Called when request is completed.
		- _body_: Specific contents for the request body for POST method.
		- _headers_: Request headers.
		- _username_: The optional user name to use for authentication purposes.
		- _password_: The optional password to use for authentication purposes.
		- _xhrFields_: Optional object containing name/value pairs to mix directly into the generated xhr object.
		- _mimeType_: Optional string to override the MIME-Type.
	*/
	request: function(inParams) {
		var xhr = this.getXMLHttpRequest(inParams.url);
		//
		var method = inParams.method || "GET";
		var async = ("sync" in inParams) ? !inParams.sync : true;
		//
		if (inParams.username) {
			xhr.open(method, enyo.path.rewrite(inParams.url), async, inParams.username, inParams.password);
		} else {
			xhr.open(method, enyo.path.rewrite(inParams.url), async);
		}
		//
		enyo.mixin(xhr, inParams.xhrFields);
		//
		this.makeReadyStateHandler(xhr, inParams.callback);
		if (inParams.headers) {
			for (var key in inParams.headers) {
				xhr.setRequestHeader(key, inParams.headers[key]);
			}
		}
		//
		if(typeof(xhr.overrideMimeType) == "function" && inParams.mimeType) {
			xhr.overrideMimeType(inParams.mimeType);
		}
		//
		xhr.send(inParams.body || null);
		if (!async) {
			xhr.onreadystatechange(xhr);
		}
		return xhr;
	},
	//* @protected
	makeReadyStateHandler: function(inXhr, inCallback) {
		if (window.XDomainRequest && inXhr instanceof XDomainRequest) {
			inXhr.onload = function() {
				inCallback && inCallback.apply(null, [inXhr.responseText, inXhr]);
			};
		}
		inXhr.onreadystatechange = function() {
			if (inXhr.readyState == 4) {
				inCallback && inCallback.apply(null, [inXhr.responseText, inXhr]);
			}
		};
	},
	inOrigin: function(inUrl) {
		var a = document.createElement("a"), result = false;
		a.href = inUrl;
		if (a.protocol === ":" ||
				(a.protocol === window.location.protocol &&
					a.hostname === window.location.hostname &&
					a.port === (window.location.port || "80"))) {
			result = true;
		}
		return result;
	},
	getXMLHttpRequest: function(inUrl) {
		try {
			if (window.XDomainRequest && !this.inOrigin(inUrl) && !/^file:\/\//.test(window.location.href)) {
				return new XDomainRequest();
			}
		} catch(e) {}
		try {
			return new XMLHttpRequest();
		} catch(e) {}
		try {
			return new ActiveXObject('Msxml2.XMLHTTP');
		} catch(e) {}
		try {
			return new ActiveXObject('Microsoft.XMLHTTP');
		} catch(e) {}
		return null;
	}
};
<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name reviveError
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/error/reviver}
*/
setReadOnly( ns, 'reviveError', require( '@stdlib/error/reviver' ) );

/**
* @name error2json
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/error/to-json}
*/
setReadOnly( ns, 'error2json', require( '@stdlib/error/to-json' ) );

// EXPORTS //

module.exports = ns;
<commit_msg>Add comment indicating that tools shall not be exported<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

/*
* The following modules are intentionally not exported: tools
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name reviveError
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/error/reviver}
*/
setReadOnly( ns, 'reviveError', require( '@stdlib/error/reviver' ) );

/**
* @name error2json
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/error/to-json}
*/
setReadOnly( ns, 'error2json', require( '@stdlib/error/to-json' ) );

// EXPORTS //

module.exports = ns;
<|endoftext|>


<commit_before>
// Constants
const NEXT_BLOCK_LABELS = ["next block", "2nd block", "3rd block"]

// State
var chart
var lastMempoolDataUpdate = 0
var processedMempool = null
var currentTx = null

function generateColorPattern(patternAreas) {

  const patternColors = [
    ['LightGreen', 'YellowGreen'],
    ['YellowGreen', 'Bisque'],
    ['Bisque', 'Salmon'],
    ['Salmon', 'HotPink'],
  ]

  var colorPattern = []
  var c_counter = 0
  for (area in patternAreas) {
    logLimits = chroma.limits(patternAreas[area], 'l', patternAreas[area].length);
    pattern = chroma.scale(patternColors[c_counter])
      .mode('lch').classes(logLimits)
      .colors(patternAreas[area].length);

    colorPattern = colorPattern.concat(pattern)
    c_counter++
  }

  return colorPattern
}

function processApiMempoolDataForChart(response) {

  console.log('Mempool data written to db @', response.timestamp)
  lastMempoolDataUpdate = response.timestamp

  const mempoolSize = +(response.mempoolSize / 1000000).toFixed(2)

  const patternAreas = {
    '0to10': [],
    '11to100': [],
    '101to1k': [],
    'from1001': []
  }

  const ticks = []
  const lines = []
  const blocks = []
  const rowData = [
    [],[]
  ]

  for (var feerate in response.mempoolData) {
    rowData[0].push(feerate.toString())
    rowData[1].push(response.mempoolData[feerate])

    // TODO: (0xb10c) Why do we do this and what does it?
    log1pOfCount = response.mempoolData[feerate]
    if (feerate <= 10) {
      patternAreas['0to10'].push(log1pOfCount)
    } else if (feerate <= 100) {
      patternAreas['11to100'].push(log1pOfCount)
    } else if (feerate <= 1000) {
      patternAreas['101to1k'].push(log1pOfCount)
    } else {
      patternAreas['from1001'].push(log1pOfCount)
    }
  }

  for (var position in response.positionsInGreedyBlocks) {
    if (position < 3) {
      blocks.push(response.positionsInGreedyBlocks[position])
      // add lines to show estimated next blocks on the mempool graph
      lines.push({
        value: response.positionsInGreedyBlocks[position]
      })
    }
  }

  let colorPattern = generateColorPattern(patternAreas)

  // Sum all txs to get the total number of tx in the mempool
  const sum = Object.values(rowData[1]).reduce((a, b) => a + b, 0)
  return {
    "mempoolSize": mempoolSize,
    "blocks": blocks,
    "colorPattern": colorPattern,
    "lines": lines,
    "rowData": rowData,
    "sum": sum
  }
}

window.onload = function () {
  // Add event listeners to the search bar
  document.getElementById('button-lookup-txid').addEventListener('click', handleTxSearch)

  // add scroll listener for icon
  $(window).scroll(function() {
    if ($(".navbar").offset().top > 60) {
        $(".navbar").addClass("scrolled");
    } else {
        $(".navbar").removeClass("scrolled");
    }
  });

  // Get the mempool data
  axios.get('https://mempool.observer/api/mempool')
    .then(function (response) {
      console.log(response.data)
      processedMempool = processApiMempoolDataForChart(response.data)
      draw(processedMempool)
      updateCurrentMempoolCard(processedMempool)
      redraw() // init redraw loop
    })
}

function draw(processed) {
  chart = c3.generate({
    data: {
      rows: processed.rowData,
      type: 'bar',
      groups: [processed.rowData[0]],
      order: null,
    },
    point: {
      show: false
    },
    legend: {
      show: false
    },
    tooltip: {
      grouped: false,
      format: {
        name: function (name) {return name + ' sat/vbyte'},
        value: function (value) {return value + ' transactions'},
      }
    },
    size: {
      height: 750
    },
    padding: {
      top: 20
    },
    color: {
      pattern: processed.colorPattern
    },
    grid: {
      y: {
        lines: processed.lines
      }
    },
    axis: {
      y: {
        padding: {top: 0},
        show: true,
        label: {
          text: 'unconfirmed transactions'
        },
      },
      y2: {
        outer: false,
        padding: {top: 0, bottom:0},
        default: [0, processed.sum],
        label: {
          text: 'estimated blocks'
        },
        show: true,
        tick: {
          format: function (d) {return NEXT_BLOCK_LABELS[processed.blocks.indexOf(d)]},
          values: processed.blocks
        }
      }
    }
  })

  if(currentTx != null){
    const feeRate = Math.floor(currentTx.fee/currentTx.size)
    drawTxIdInChartByFeeRate(currentTx.txid, feeRate)
  }

}

function redraw() {
  setTimeout(function () {
    axios.get('https://mempool.observer/api/mempool')
      .then(function (response) {
        processed = processApiMempoolDataForChart(response.data)
        draw(processed)
        updateCurrentMempoolCard(processed)
        redraw()
      });
  }, 60000);
}

function updateCurrentMempoolCard(processed) { //TODO: Change name of function

  const spanTxCount = document.getElementById('current-mempool-count')
  const spanMempoolSize = document.getElementById('current-mempool-size')

  const txCountInMempool = processed.sum
  const txSizeInMempool = processed.mempoolSize

  spanTxCount.innerHTML = txCountInMempool
  spanMempoolSize.innerHTML = txSizeInMempool

  timeSinceLastUpdate = 0
  updateCurrentMempoolCardLastUpdated()
}

function updateCurrentMempoolCardLastUpdated() {
  // format as milliseconds since 1.1.1970 UTC
  // * 1000 to convert from seconds to milliseconds
  const millislastMempoolDataUpdate = lastMempoolDataUpdate * 1000
  const minutes = Math.floor((Date.now() -  millislastMempoolDataUpdate) / 1000 / 60)

  document.getElementById('current-mempool-last-update').innerHTML = (minutes)
}

// Update the 'Time since last update' text
setInterval(function() {
  updateCurrentMempoolCardLastUpdated()
}, 10000);

async function handleTxSearch() {
  $('#input-lookup-txid').removeClass("is-invalid" ) // Clear alerts

  txId = document.getElementById('input-lookup-txid').value

  // Check if txid is invalid
  if (/^[a-fA-F0-9]{64}$/.test(txId) == false) {
    $('#invalid-feedback').html('Invalid Bitcoin transaction id.') // Set alert message
    $('#input-lookup-txid').addClass("is-invalid")  // Show alert
  } else {
    try {
      const tx = await getTxFromApi(txId) // in sat/vbyte
      currentTx = tx

      if (tx.status.confirmed){

        let minutes_since_confirmation = Math.floor((Date.now() -  tx.status.block_time * 1000) / 1000 / 60)
        error = `The transaction confirmed. (Block ${tx.status.block_height}, ${minutes_since_confirmation} minutes ago)`
        console.error(error)

        $('#invalid-feedback').html(error)
        $('#input-lookup-txid').addClass("is-invalid")
      } else {
        const feeRate =  Math.floor(tx.fee/tx.size)
        drawTxIdInChartByFeeRate(tx.txid, feeRate)
      }

    } catch (error) {
      console.error(error)
      $('#invalid-feedback').html(error)
      $('#input-lookup-txid').addClass("is-invalid")
    }
  }
}

function drawTxIdInChartByFeeRate(txid,feeRate){
  const position = getTxPostionInChartByFeeRate(feeRate)
  chart.ygrids.remove({class:'user-tx'});
  chart.ygrids.add([{value: position, text: txid.substring(0, 8) + "...", class:'user-tx', position: 'middle'}]);
  chart.tooltip.show({x: feeRate, index: 0, id: '1' })
}

function getTxPostionInChartByFeeRate(feeRate){
  let position = 0
  for(index in processedMempool.rowData[0]){
    if(processedMempool.rowData[0][index] <= feeRate){
      position += processedMempool.rowData[1][index]
    }else{
      break;
    }
  }
  return position
}

function getTxFromApi(txId) {
  return axios.get(`https://blockstream.info/api/tx/${txId}`)
    .then(res => res.data)
    .catch(e => {
      console.log('Error getting data from explorer:', e)
      throw new Error('Could not find your transaction in the bitcoin network. Wait a few minutes before trying again.')
    })
}

<commit_msg>Improve error message<commit_after>
// Constants
const NEXT_BLOCK_LABELS = ["next block", "2nd block", "3rd block"]

// State
var chart
var lastMempoolDataUpdate = 0
var processedMempool = null
var currentTx = null

function generateColorPattern(patternAreas) {

  const patternColors = [
    ['LightGreen', 'YellowGreen'],
    ['YellowGreen', 'Bisque'],
    ['Bisque', 'Salmon'],
    ['Salmon', 'HotPink'],
  ]

  var colorPattern = []
  var c_counter = 0
  for (area in patternAreas) {
    logLimits = chroma.limits(patternAreas[area], 'l', patternAreas[area].length);
    pattern = chroma.scale(patternColors[c_counter])
      .mode('lch').classes(logLimits)
      .colors(patternAreas[area].length);

    colorPattern = colorPattern.concat(pattern)
    c_counter++
  }

  return colorPattern
}

function processApiMempoolDataForChart(response) {

  console.log('Mempool data written to db @', response.timestamp)
  lastMempoolDataUpdate = response.timestamp

  const mempoolSize = +(response.mempoolSize / 1000000).toFixed(2)

  const patternAreas = {
    '0to10': [],
    '11to100': [],
    '101to1k': [],
    'from1001': []
  }

  const ticks = []
  const lines = []
  const blocks = []
  const rowData = [
    [],[]
  ]

  for (var feerate in response.mempoolData) {
    rowData[0].push(feerate.toString())
    rowData[1].push(response.mempoolData[feerate])

    // TODO: (0xb10c) Why do we do this and what does it?
    log1pOfCount = response.mempoolData[feerate]
    if (feerate <= 10) {
      patternAreas['0to10'].push(log1pOfCount)
    } else if (feerate <= 100) {
      patternAreas['11to100'].push(log1pOfCount)
    } else if (feerate <= 1000) {
      patternAreas['101to1k'].push(log1pOfCount)
    } else {
      patternAreas['from1001'].push(log1pOfCount)
    }
  }

  for (var position in response.positionsInGreedyBlocks) {
    if (position < 3) {
      blocks.push(response.positionsInGreedyBlocks[position])
      // add lines to show estimated next blocks on the mempool graph
      lines.push({
        value: response.positionsInGreedyBlocks[position]
      })
    }
  }

  let colorPattern = generateColorPattern(patternAreas)

  // Sum all txs to get the total number of tx in the mempool
  const sum = Object.values(rowData[1]).reduce((a, b) => a + b, 0)
  return {
    "mempoolSize": mempoolSize,
    "blocks": blocks,
    "colorPattern": colorPattern,
    "lines": lines,
    "rowData": rowData,
    "sum": sum
  }
}

window.onload = function () {
  // Add event listeners to the search bar
  document.getElementById('button-lookup-txid').addEventListener('click', handleTxSearch)

  // add scroll listener for icon
  $(window).scroll(function() {
    if ($(".navbar").offset().top > 60) {
        $(".navbar").addClass("scrolled");
    } else {
        $(".navbar").removeClass("scrolled");
    }
  });

  // Get the mempool data
  axios.get('https://mempool.observer/api/mempool')
    .then(function (response) {
      console.log(response.data)
      processedMempool = processApiMempoolDataForChart(response.data)
      draw(processedMempool)
      updateCurrentMempoolCard(processedMempool)
      redraw() // init redraw loop
    })
}

function draw(processed) {
  chart = c3.generate({
    data: {
      rows: processed.rowData,
      type: 'bar',
      groups: [processed.rowData[0]],
      order: null,
    },
    point: {
      show: false
    },
    legend: {
      show: false
    },
    tooltip: {
      grouped: false,
      format: {
        name: function (name) {return name + ' sat/vbyte'},
        value: function (value) {return value + ' transactions'},
      }
    },
    size: {
      height: 750
    },
    padding: {
      top: 20
    },
    color: {
      pattern: processed.colorPattern
    },
    grid: {
      y: {
        lines: processed.lines
      }
    },
    axis: {
      y: {
        padding: {top: 0},
        show: true,
        label: {
          text: 'unconfirmed transactions'
        },
      },
      y2: {
        outer: false,
        padding: {top: 0, bottom:0},
        default: [0, processed.sum],
        label: {
          text: 'estimated blocks'
        },
        show: true,
        tick: {
          format: function (d) {return NEXT_BLOCK_LABELS[processed.blocks.indexOf(d)]},
          values: processed.blocks
        }
      }
    }
  })

  if(currentTx != null){
    const feeRate = Math.floor(currentTx.fee/currentTx.size)
    drawTxIdInChartByFeeRate(currentTx.txid, feeRate)
  }

}

function redraw() {
  setTimeout(function () {
    axios.get('https://mempool.observer/api/mempool')
      .then(function (response) {
        processed = processApiMempoolDataForChart(response.data)
        draw(processed)
        updateCurrentMempoolCard(processed)
        redraw()
      });
  }, 60000);
}

function updateCurrentMempoolCard(processed) { //TODO: Change name of function

  const spanTxCount = document.getElementById('current-mempool-count')
  const spanMempoolSize = document.getElementById('current-mempool-size')

  const txCountInMempool = processed.sum
  const txSizeInMempool = processed.mempoolSize

  spanTxCount.innerHTML = txCountInMempool
  spanMempoolSize.innerHTML = txSizeInMempool

  timeSinceLastUpdate = 0
  updateCurrentMempoolCardLastUpdated()
}

function updateCurrentMempoolCardLastUpdated() {
  // format as milliseconds since 1.1.1970 UTC
  // * 1000 to convert from seconds to milliseconds
  const millislastMempoolDataUpdate = lastMempoolDataUpdate * 1000
  const minutes = Math.floor((Date.now() -  millislastMempoolDataUpdate) / 1000 / 60)

  document.getElementById('current-mempool-last-update').innerHTML = (minutes)
}

// Update the 'Time since last update' text
setInterval(function() {
  updateCurrentMempoolCardLastUpdated()
}, 10000);

async function handleTxSearch() {
  $('#input-lookup-txid').removeClass("is-invalid" ) // Clear alerts

  txId = document.getElementById('input-lookup-txid').value

  // Check if txid is invalid
  if (/^[a-fA-F0-9]{64}$/.test(txId) == false) {
    $('#invalid-feedback').html('Invalid Bitcoin transaction id.') // Set alert message
    $('#input-lookup-txid').addClass("is-invalid")  // Show alert
  } else {
    try {
      const tx = await getTxFromApi(txId) // in sat/vbyte
      currentTx = tx

      if (tx.status.confirmed){

        let minutes_since_confirmation = Math.floor((Date.now() -  tx.status.block_time * 1000) / 1000 / 60)
        let error = `The transaction is already confirmed and therefore not in the mempool. (block ${tx.status.block_height}, ${minutes_since_confirmation} minutes ago)`
        console.error(error)

        $('#invalid-feedback').html(error)
        $('#input-lookup-txid').addClass("is-invalid")
      } else {
        const feeRate =  Math.floor(tx.fee/tx.size)
        drawTxIdInChartByFeeRate(tx.txid, feeRate)
      }

    } catch (error) {
      console.error(error)
      $('#invalid-feedback').html(error)
      $('#input-lookup-txid').addClass("is-invalid")
    }
  }
}

function drawTxIdInChartByFeeRate(txid,feeRate){
  const position = getTxPostionInChartByFeeRate(feeRate)
  chart.ygrids.remove({class:'user-tx'});
  chart.ygrids.add([{value: position, text: txid.substring(0, 8) + "...", class:'user-tx', position: 'middle'}]);
  chart.tooltip.show({x: feeRate, index: 0, id: '1' })
}

function getTxPostionInChartByFeeRate(feeRate){
  let position = 0
  for(index in processedMempool.rowData[0]){
    if(processedMempool.rowData[0][index] <= feeRate){
      position += processedMempool.rowData[1][index]
    }else{
      break;
    }
  }
  return position
}

function getTxFromApi(txId) {
  return axios.get(`https://blockstream.info/api/tx/${txId}`)
    .then(res => res.data)
    .catch(e => {
      console.log('Error getting data from explorer:', e)
      throw new Error('Could not find your transaction in the bitcoin network. Wait a few minutes before trying again.')
    })
}

<|endoftext|>


<commit_before>var _ohanhi$elm_native_ui$Native_NativeUi = (function () {

  var ReactNative = require('react-native');
  var React = require('react');
  var toArray = _elm_lang$core$Native_List.toArray;

  // PROPS

  /**
   * Declares a message decoder to be run on an event for a particular node
   */
  function on(eventName, decoder) {
    return {
      type: 'event',
      eventName: eventName,
      decoder: decoder
    };
  }
  /**
   * Declares a ref attribute for a node, callback receives the reference of the node
   */
  function ref(callback) {
    return {
      type: 'ref',
      callback: callback,
    }
  }
  /**
   * Declares a style attribute for a node, expressed as an inline styles for
   * the moment.
   */
  function style(attrs) {
    return {
      type: 'style',
      sheet: attrs
    };
  }

  /**
   * Declares any other kind of property for a node.
   */
  function property(propName, value) {
    return {
      type: 'prop',
      propName: propName,
      value: value
    };
  }

  function renderProperty(propName, value) {
    return {
      type: 'renderProp',
      propName: propName,
      value: value,
    };
  }

  function unsafeRenderDecodedProperty(propName, decoder, value) {
    return {
      type: 'renderDecodedProp',
      propName: propName,
      value: value,
      decoder: decoder
    };
  }

  // ELEMENTS

  /**
   * A plain string node
   */
  function string(text) {
    return {
      type: 'string',
      string: text
    };
  }

  /**
   * A node that renders a React Native component with props and children
   */
  function node(tagName) {
    return F2(function(factList, childList) {
      return {
        type: 'component',
        tagName: tagName,
        facts: toArray(factList),
        children: toArray(childList)
      };
    });
  }

  /**
   * A node that renders a React Native component with props, but no children.
   * This can improve performance by reducing function calls during
   * tree-building and can allow for optimizations later on as well.
   */
  function voidNode(tagName) {
    return function (factList) {
      return {
        type: 'component',
        tagName: tagName,
        facts: toArray(factList),
        children: []
      };
    };
  }

  /**
   * A non-standard node that renders a React Native component with props and children
   */
  function customNode(tagName, nativeComponent) {
    return F2(function(factList, childList) {
      return {
        type: 'component',
        tagName: tagName,
        facts: toArray(factList),
        children: toArray(childList),
        nativeComponent: nativeComponent
      };
    });
  }

  /**
   * Maps another node onto a different message type
   */
  function map(tagger, node) {
    return {
      type: 'tagger',
      tagger: tagger,
      node: node
    };
  }

  // RENDER

  /**
   * Converts a stack of `on` handlers and `map` nodes into a final function
   * that can be passed into a React Native component's `onSomeEvent` props
   */
  function makeEventHandler(eventNode, decoder) {
    function eventHandler(event) {
      var decoder = eventHandler.decoder;
      var message = decodeValue(eventHandler.decoder, event);

      var currentEventNode = eventNode;
      while (currentEventNode) {
        var tagger = currentEventNode.tagger;

        if (typeof tagger === 'function') {
          message = tagger(message);
        } else {
          for (var i = tagger.length; i--; ) {
            message = tagger[i](message);
          }
        }

        currentEventNode = currentEventNode.parent;
      }
    }

    eventHandler.decoder = decoder;

    return eventHandler;
  }

  /**
   * Converts a fact whose value is a function that renders a subTree into a
   * function that constructs the subTree to render with the provided props.
   * This is used by NavigationExperimental to pass the header and scene views
   * into the component
   */
  function makeRenderNodePropHandler(fact, eventNode, key) {
    function handler(props) {
      return renderTree(handler.component(props), eventNode, key);
    };

    handler.component = fact.value;

    return handler;
  }

  /**
   * Converts a fact whose value is a function that renders a subTree into a
   * function that constructs the subTree to render with the provided props.
   * This is used by NavigationExperimental to pass the header and scene views
   * into the component
   */
  function makeRenderNodeDecodedPropHandler(fact, eventNode, key) {
    function handler(props) {
      var decodedProps = decodeValue(handler.decoder, props);

      return renderTree(handler.component(decodedProps), eventNode, key);
    };

    handler.component = fact.value;
    handler.decoder = fact.decoder;

    return handler;
  }

  /**
   * Decodes properties from elm into json props for react-native
   */
  function decodeValue(decoder, value) {
    var decodedValue = A2(_elm_lang$core$Native_Json.run, decoder, value);

    if (decodedValue.ctor !== 'Ok') {
      throw Error(decodedValue._0);
    }

    return decodedValue._0;
  }

  /**
   * Converts a string node back to a plain string for React Native to render
   */
  function renderString(node) {
    return node.string;
  }

  /**
   * Composes taggers created by `map`
   */
  function renderTagger(node, eventNode, key) {
    var subNode = node.node;
    var tagger = node.tagger;

    while (subNode.type === 'tagger') {
      typeof tagger !== 'object' ?
        tagger = [tagger, subNode.tagger] :
        tagger.push(subNode.tagger);

      subNode = subNode.node;
    }

    var subEventRoot = { tagger: tagger, parent: eventNode };
    return renderTree(subNode, subEventRoot, key);
  }

  /**
   * Converts a component node into an actual React Native node. Builds the
   * children array and props object, looks up the component by name on the
   * React Native module and calls into React.createElement.
   */
  function renderComponent(node, eventNode, key) {
    var children = [];
    for (var i = 0; i < node.children.length; i++) {
      children.push(renderTree(node.children[i], eventNode, i));
    }

    var finalProps = {};

    for (var j = 0; j < node.facts.length; j++) {
      var fact = node.facts[j];

      switch (fact.type) {
        case 'prop':
          finalProps[fact.propName] = fact.value;
          break;
        case 'ref':
          finalProps['ref'] = fact.callback;
          break;
        case 'renderProp':
          finalProps[fact.propName] = makeRenderNodePropHandler(fact, eventNode, key);
          break;

        case 'renderDecodedProp':
          finalProps[fact.propName] = makeRenderNodeDecodedPropHandler(fact, eventNode, key);
          break;

        case 'event':
          finalProps[fact.eventName] = makeEventHandler(eventNode, fact.decoder);
          break;

        case 'style':
          finalProps.style = fact.sheet;
          break;
      }
    }

    if(!finalProps.key) {
      finalProps.key = 'elm-native-ui-auto-added-' + key;
    }

    if (children.length === 1) {
      finalProps.children = children[0];
    } else if (children.length) {
      finalProps.children = children;
    }
    // ignore MapView exported from current react-native package since we want to use one from react-native-maps
    // release of 0.42 will remove this.
    if (node.tagName !== 'MapView' && ReactNative[node.tagName]) {
      return React.createElement(ReactNative[node.tagName], finalProps);
    } else {
      if (!node.nativeComponent) {
          throw Error('Unable to find a node called ' + node.tagName + ' in ReactNative. Try defining it as a customNode');
      }

      return React.createElement(node.nativeComponent, finalProps);
    }
  }

  /**
   * Renders the whole tree!
   */
  function renderTree(node, eventNode, key) {
    switch (node.type) {
      case 'string':
        return renderString(node);

      case 'tagger':
        return renderTagger(node, eventNode, key);

      case 'component':
        return renderComponent(node, eventNode, key);

    }
  }

  // PROGRAM

  /**
   * Takes am Elm Native UI program implementation and turns into a React
   * component that will begin rendering the virtual tree as soon as the Elm
   * program starts running
   */
  function makeComponent(impl, onAppReady, flags) {
    return React.createClass({
      getInitialState: function getInitialState() {
        return {};
      },

      onAppReady: onAppReady,

      componentDidMount: function componentDidMount() {
        this.eventNode = { tagger: function() {}, parent: undefined };

        this._app = _elm_lang$core$Native_Platform.initialize(
          typeof flags === 'undefined' ? impl.init : impl.init(flags),
          impl.update,
          impl.subscriptions,
          this.renderer
        );

        if (typeof this.onAppReady === "function") {
          this.onAppReady(this._app);
        }
      },

      renderer: function renderer(onMessage, initialModel) {
        this.eventNode.tagger = onMessage;
        this.updateModel(initialModel);
        return this.updateModel;
      },

      updateModel: function updateModel(model) {
        this.setState({ model: model });
      },

      render: function render() {
        // There won't be a model to render right away so we'll check that it
        // exists before trying to call the view function
        return typeof this.state.model !== 'undefined' ?
          renderTree(impl.view(this.state.model), this.eventNode, 0) :
          null;
      }
    });
  }

  /**
   * Makes an Elm program from the standard init, model, update, view
   * specification and adds a function to your module called `start` that,
   * when called in JavaScript-land, will return a React component that you can
   * render or register with the AppRegistry. In the future this function will
   * also deal with decoding flags from JavaScript and setting up debugging
   * facilities. But for now it just returns a `Program Never model msg` that
   * you can pass to `main`.
   */
  function program(impl) {
    return function(flagDecoder) {
      return function(object, moduleName, debugMetadata) {
        object.start = function start(onAppReady) {
          return makeComponent(impl, onAppReady);
        };
      };
    };
  }

  /**
   * Run the provided `flagDecoder` before passing to Elm code for type safety.
   */
  function programWithFlags(impl) {
    return function(flagDecoder) {
      return function(object, moduleName, debugMetadata) {
        object.start = function start(onAppReady, flags = {}) {
          if (typeof flagDecoder === 'undefined') {
            throw new Error(
              'Are you trying to sneak a Never value into Elm? Trickster!\n'
              + 'It looks like ' + moduleName + '.main is defined with `programWithFlags` but has type `Program Never`.\n'
              + 'Use `program` instead if you do not want flags.'
            );
          }
          var result = A2(_elm_lang$core$Native_Json.run, flagDecoder, flags);
          if (result.ctor === 'Err')
          {
          	throw new Error(
          		moduleName + '.start(...) was called with an unexpected argument.\n'
          		+ 'I tried to convert it to an Elm value, but ran into this problem:\n\n'
          		+ result._0
          	);
          }
          return makeComponent(impl, onAppReady, result);
        };
      };
    };
  }

  // UTILS

  /**
   * Useful for encoding a Date.Date as a Json.Encode.Value since Date.Date is
   * just a plain JavaScript Date. This can be used for props on things like
   * DatePickerIOS that expect date values.
   */
  function identity(value) {
    return value;
  }

  /**
   * When combined with `Decode.andThen`, creates a decoder for a Date.Date from
   * a plain JavaScript Date. This can be used for event handlers that pass a
   * Date.
   */
  function parseDate(value) {
    if (value instanceof Date) {
      return _elm_lang$core$Native_Json.succeed(value);
    } else {
      return _elm_lang$core$Native_Json.fail('Expected a Date, but did not find one');
    }
  }

  return {
    program: program,
    programWithFlags: programWithFlags,
    node: node,
    voidNode: voidNode,
    customNode: F2(customNode),
    string: string,
    map: F2(map),
    on: F2(on),
    ref: ref,
    style: style,
    property: F2(property),
    renderProperty: F2(renderProperty),
    unsafeRenderDecodedProperty: F3(unsafeRenderDecodedProperty),
    encodeDate: identity,
    parseDate: parseDate
  };
}());
<commit_msg>fix missing property<commit_after>var _ohanhi$elm_native_ui$Native_NativeUi = (function () {

  var ReactNative = require('react-native');
  var React = require('react');
  var toArray = _elm_lang$core$Native_List.toArray;

  // PROPS

  /**
   * Declares a message decoder to be run on an event for a particular node
   */
  function on(eventName, decoder) {
    return {
      type: 'event',
      eventName: eventName,
      decoder: decoder
    };
  }
  /**
   * Declares a ref attribute for a node, callback receives the reference of the node
   */
  function ref(callback) {
    return {
      type: 'ref',
      callback: callback,
    }
  }
  /**
   * Declares a style attribute for a node, expressed as an inline styles for
   * the moment.
   */
  function style(attrs) {
    return {
      type: 'style',
      sheet: attrs
    };
  }

  /**
   * Declares any other kind of property for a node.
   */
  function property(propName, value) {
    return {
      type: 'prop',
      propName: propName,
      value: value
    };
  }

  function renderProperty(propName, value) {
    return {
      type: 'renderProp',
      propName: propName,
      value: value,
    };
  }

  function unsafeRenderDecodedProperty(propName, decoder, value) {
    return {
      type: 'renderDecodedProp',
      propName: propName,
      value: value,
      decoder: decoder
    };
  }

  // ELEMENTS

  /**
   * A plain string node
   */
  function string(text) {
    return {
      type: 'string',
      string: text
    };
  }

  /**
   * A node that renders a React Native component with props and children
   */
  function node(tagName) {
    return F2(function(factList, childList) {
      return {
        type: 'component',
        tagName: tagName,
        facts: toArray(factList),
        children: toArray(childList)
      };
    });
  }

  /**
   * A node that renders a React Native component with props, but no children.
   * This can improve performance by reducing function calls during
   * tree-building and can allow for optimizations later on as well.
   */
  function voidNode(tagName) {
    return function (factList) {
      return {
        type: 'component',
        tagName: tagName,
        facts: toArray(factList),
        children: []
      };
    };
  }

  /**
   * A non-standard node that renders a React Native component with props and children
   */
  function customNode(tagName, nativeComponent) {
    return F2(function(factList, childList) {
      return {
        type: 'component',
        tagName: tagName,
        facts: toArray(factList),
        children: toArray(childList),
        nativeComponent: nativeComponent
      };
    });
  }

  /**
   * Maps another node onto a different message type
   */
  function map(tagger, node) {
    return {
      type: 'tagger',
      tagger: tagger,
      node: node
    };
  }

  // RENDER

  /**
   * Converts a stack of `on` handlers and `map` nodes into a final function
   * that can be passed into a React Native component's `onSomeEvent` props
   */
  function makeEventHandler(eventNode, decoder) {
    function eventHandler(event) {
      var decoder = eventHandler.decoder;
      var message = decodeValue(eventHandler.decoder, event);

      var currentEventNode = eventNode;
      while (currentEventNode) {
        var tagger = currentEventNode.tagger;

        if (typeof tagger === 'function') {
          message = tagger(message);
        } else {
          for (var i = tagger.length; i--; ) {
            message = tagger[i](message);
          }
        }

        currentEventNode = currentEventNode.parent;
      }
    }

    eventHandler.decoder = decoder;

    return eventHandler;
  }

  /**
   * Converts a fact whose value is a function that renders a subTree into a
   * function that constructs the subTree to render with the provided props.
   * This is used by NavigationExperimental to pass the header and scene views
   * into the component
   */
  function makeRenderNodePropHandler(fact, eventNode, key) {
    function handler(props) {
      return renderTree(handler.component(props), eventNode, key);
    };

    handler.component = fact.value;

    return handler;
  }

  /**
   * Converts a fact whose value is a function that renders a subTree into a
   * function that constructs the subTree to render with the provided props.
   * This is used by NavigationExperimental to pass the header and scene views
   * into the component
   */
  function makeRenderNodeDecodedPropHandler(fact, eventNode, key) {
    function handler(props) {
      var decodedProps = decodeValue(handler.decoder, props);

      return renderTree(handler.component(decodedProps), eventNode, key);
    };

    handler.component = fact.value;
    handler.decoder = fact.decoder;

    return handler;
  }

  /**
   * Decodes properties from elm into json props for react-native
   */
  function decodeValue(decoder, value) {
    var decodedValue = A2(_elm_lang$core$Native_Json.run, decoder, value);

    if (decodedValue.ctor !== 'Ok') {
      throw Error(decodedValue._0);
    }

    return decodedValue._0;
  }

  /**
   * Converts a string node back to a plain string for React Native to render
   */
  function renderString(node) {
    return node.string;
  }

  /**
   * Composes taggers created by `map`
   */
  function renderTagger(node, eventNode, key) {
    var subNode = node.node;
    var tagger = node.tagger;

    while (subNode.type === 'tagger') {
      typeof tagger !== 'object' ?
        tagger = [tagger, subNode.tagger] :
        tagger.push(subNode.tagger);

      subNode = subNode.node;
    }

    var subEventRoot = { tagger: tagger, parent: eventNode };
    return renderTree(subNode, subEventRoot, key);
  }

  /**
   * Converts a component node into an actual React Native node. Builds the
   * children array and props object, looks up the component by name on the
   * React Native module and calls into React.createElement.
   */
  function renderComponent(node, eventNode, key) {
    var children = [];
    for (var i = 0; i < node.children.length; i++) {
      children.push(renderTree(node.children[i], eventNode, i));
    }

    var finalProps = {};

    for (var j = 0; j < node.facts.length; j++) {
      var fact = node.facts[j];

      switch (fact.type) {
        case 'prop':
          finalProps[fact.propName] = fact.value;
          break;
        case 'ref':
          finalProps['ref'] = fact.callback;
          break;
        case 'renderProp':
          finalProps[fact.propName] = makeRenderNodePropHandler(fact, eventNode, key);
          break;

        case 'renderDecodedProp':
          finalProps[fact.propName] = makeRenderNodeDecodedPropHandler(fact, eventNode, key);
          break;

        case 'event':
          finalProps[fact.eventName] = makeEventHandler(eventNode, fact.decoder);
          break;

        case 'style':
          finalProps.style = fact.sheet;
          break;
      }
    }

    if(!finalProps.key) {
      finalProps.key = 'elm-native-ui-auto-added-' + key;
    }

    if (children.length === 1) {
      finalProps.children = children[0];
    } else if (children.length) {
      finalProps.children = children;
    }
    // ignore MapView exported from current react-native package since we want to use one from react-native-maps
    // release of 0.42 will remove this.
    if (node.tagName !== 'MapView' && ReactNative[node.tagName]) {
      return React.createElement(ReactNative[node.tagName], finalProps);
    } else {
      if (!node.nativeComponent) {
          throw Error('Unable to find a node called ' + node.tagName + ' in ReactNative. Try defining it as a customNode');
      }

      return React.createElement(node.nativeComponent, finalProps);
    }
  }

  /**
   * Renders the whole tree!
   */
  function renderTree(node, eventNode, key) {
    switch (node.type) {
      case 'string':
        return renderString(node);

      case 'tagger':
        return renderTagger(node, eventNode, key);

      case 'component':
        return renderComponent(node, eventNode, key);

    }
  }

  // PROGRAM

  /**
   * Takes am Elm Native UI program implementation and turns into a React
   * component that will begin rendering the virtual tree as soon as the Elm
   * program starts running
   */
  function makeComponent(impl, onAppReady, flags) {
    return React.createClass({
      getInitialState: function getInitialState() {
        return {};
      },

      onAppReady: onAppReady,

      componentDidMount: function componentDidMount() {
        this.eventNode = { tagger: function() {}, parent: undefined };

        this._app = _elm_lang$core$Native_Platform.initialize(
          typeof flags === 'undefined' ? impl.init : impl.init(flags),
          impl.update,
          impl.subscriptions,
          this.renderer
        );

        if (typeof this.onAppReady === "function") {
          this.onAppReady(this._app);
        }
      },

      renderer: function renderer(onMessage, initialModel) {
        this.eventNode.tagger = onMessage;
        this.updateModel(initialModel);
        return this.updateModel;
      },

      updateModel: function updateModel(model) {
        this.setState({ model: model });
      },

      render: function render() {
        // There won't be a model to render right away so we'll check that it
        // exists before trying to call the view function
        return typeof this.state.model !== 'undefined' ?
          renderTree(impl.view(this.state.model), this.eventNode, 0) :
          null;
      }
    });
  }

  /**
   * Makes an Elm program from the standard init, model, update, view
   * specification and adds a function to your module called `start` that,
   * when called in JavaScript-land, will return a React component that you can
   * render or register with the AppRegistry. In the future this function will
   * also deal with decoding flags from JavaScript and setting up debugging
   * facilities. But for now it just returns a `Program Never model msg` that
   * you can pass to `main`.
   */
  function program(impl) {
    return function(flagDecoder) {
      return function(object, moduleName, debugMetadata) {
        object.start = function start(onAppReady) {
          return makeComponent(impl, onAppReady);
        };
      };
    };
  }

  /**
   * Run the provided `flagDecoder` before passing to Elm code for type safety.
   */
  function programWithFlags(impl) {
    return function(flagDecoder) {
      return function(object, moduleName, debugMetadata) {
        object.start = function start(onAppReady, flags = {}) {
          if (typeof flagDecoder === 'undefined') {
            throw new Error(
              'Are you trying to sneak a Never value into Elm? Trickster!\n'
              + 'It looks like ' + moduleName + '.main is defined with `programWithFlags` but has type `Program Never`.\n'
              + 'Use `program` instead if you do not want flags.'
            );
          }
          var result = A2(_elm_lang$core$Native_Json.run, flagDecoder, flags);
          if (result.ctor === 'Err')
          {
          	throw new Error(
          		moduleName + '.start(...) was called with an unexpected argument.\n'
          		+ 'I tried to convert it to an Elm value, but ran into this problem:\n\n'
          		+ result._0
          	);
          }
          return makeComponent(impl, onAppReady, result._0);
        };
      };
    };
  }

  // UTILS

  /**
   * Useful for encoding a Date.Date as a Json.Encode.Value since Date.Date is
   * just a plain JavaScript Date. This can be used for props on things like
   * DatePickerIOS that expect date values.
   */
  function identity(value) {
    return value;
  }

  /**
   * When combined with `Decode.andThen`, creates a decoder for a Date.Date from
   * a plain JavaScript Date. This can be used for event handlers that pass a
   * Date.
   */
  function parseDate(value) {
    if (value instanceof Date) {
      return _elm_lang$core$Native_Json.succeed(value);
    } else {
      return _elm_lang$core$Native_Json.fail('Expected a Date, but did not find one');
    }
  }

  return {
    program: program,
    programWithFlags: programWithFlags,
    node: node,
    voidNode: voidNode,
    customNode: F2(customNode),
    string: string,
    map: F2(map),
    on: F2(on),
    ref: ref,
    style: style,
    property: F2(property),
    renderProperty: F2(renderProperty),
    unsafeRenderDecodedProperty: F3(unsafeRenderDecodedProperty),
    encodeDate: identity,
    parseDate: parseDate
  };
}());
<|endoftext|>


<commit_before>/* ========================================================================
 * Bikram Scripts
 * by Gabor Szabo - http://hydrogene.hu
 * ======================================================================== */

(function($) {
})(jQuery); // Fully reference jQuery after this point.

$(document).foundation();
<commit_msg>semmi<commit_after>/* ========================================================================
 * Bikram Scripts
 * by Gabor Szabo - http://hydrogene.hu
 * ======================================================================== */

(function($) {
})(jQuery); // Fully reference jQuery after this point.

$(document).foundation();
<|endoftext|>


<commit_before>/*!
 * wwwhisper - web access control.
 * Copyright (C) 2012 Jan Wrobel
 *
 * Licensed under the GPL License version 3 or any later version:
 * https://www.gnu.org/licenses/gpl-3.0.html
 */
(function () {
  'use strict';
  var stub = new wwwhisper.Stub();

  /**
   * Sends an assertion from a BrowserID sign-in window to the
   * authentication back-end. Reloads the page if login succeeded.
   */
  function login(assertion) {
    if (assertion) {
      stub.ajax('POST', '/auth/api/login/',
                { 'assertion' : assertion.toString() },
                function() {
                  window.location.reload(true);
                },
                function(errorMessage, errorStatus) {
                  if (errorStatus === 403) {
                    // Login failed because the user is unknown.
                    $('#login-required').addClass('hide');
                    $('#nothing-shared').removeClass('hide');
                  } else {
                    // Other error.
                    $('body').html(errorMessage);
                  }
                });
    }
  }

  /**
   * Executes callback if the user is not authenticated, otherwise
   * takes the user to the logout page.
   */
  function executeIfLoggedOut(callback) {
    // Whoami succeeds only for authenticated users.
    stub.ajax('GET', '/auth/api/whoami/', null,
              function() {
                // Logged in, go to the logout page.
                window.location = '/auth/logout';
              },
              function(errorMessage, errorStatus) {
                if (errorStatus === 401) {
                  // Logget out.
                  callback();
                } else {
                  // Other error.
                  $('body').html(errorMessage);
                }
              });
  }

  executeIfLoggedOut(function() {
    $('#nothing-shared').addClass('hide');
    // Register a callback to process a BrowserID assertion.
    $('#login').click(function() {
      navigator.id.get(login);
      return false;
    });
  });
}());
<commit_msg>Let Persona dialog inform a user about disabled cookies.<commit_after>/*!
 * wwwhisper - web access control.
 * Copyright (C) 2012 Jan Wrobel
 *
 * Licensed under the GPL License version 3 or any later version:
 * https://www.gnu.org/licenses/gpl-3.0.html
 */
(function () {
  'use strict';
  var stub = new wwwhisper.Stub();

  /**
   * Sends an assertion from a BrowserID sign-in window to the
   * authentication back-end. Reloads the page if login succeeded.
   */
  function login(assertion) {
    if (assertion) {
      stub.ajax('POST', '/auth/api/login/',
                { 'assertion' : assertion.toString() },
                function() {
                  window.location.reload(true);
                },
                function(errorMessage, errorStatus) {
                  if (errorStatus === 403) {
                    // Login failed because the user is unknown.
                    $('#login-required').addClass('hide');
                    $('#nothing-shared').removeClass('hide');
                  } else {
                    // Other error.
                    $('body').html(errorMessage);
                  }
                });
    }
  }

  /**
   * Executes callback if the user is not authenticated, otherwise
   * takes the user to the logout page.
   */
  function executeIfLoggedOut(callback) {
    // Whoami succeeds only for authenticated users.
    stub.ajax('GET', '/auth/api/whoami/', null,
              function() {
                // Logged in, go to the logout page.
                window.location = '/auth/logout';
              },
              function(errorMessage, errorStatus) {
                // Logget out (errorStatus 401) or some other error.
                // If error was caused by disabled cookies (CSRF token
                // missing), Persona dialog will inform the user how
                // to enable cookies.
                callback();
              });
  }

  executeIfLoggedOut(function() {
    $('#nothing-shared').addClass('hide');
    // Register a callback to process a BrowserID assertion.
    $('#login').click(function() {
      navigator.id.get(login);
      return false;
    });
  });
}());
<|endoftext|>


<commit_before>"use strict";

var connect = require("connect"),
    logger = connect.logger(":method :url :status - :response-time ms");

var config = require("../../../shared/config"),
    paths = config.paths,
    env = require("../../../shared/env.js");

var Bundler = require("../../../core/bundle/Bundler.class.js"),
    parseURL = require("./middleware/parseURL.js"),
    serveInitPageShortcut = require("./middleware/serveInitPageShortcut.js"),
    serveInitPage = require("./middleware/serveInitPage.js"),
    notFoundAsset = require("./middleware/notFoundAsset.js"),
    staticFileHandler = require("./middleware/staticFileHandler.js"),
    defaultHeaders = require("./middleware/defaultHeaders.js"),
    checkContentType = require("./middleware/checkContentType.js"),
    httpAdapter = require("./middleware/httpAdapter.js");

//ON REQUEST
exports.request = [
    parseURL,
    connect.json(),
    connect.urlencoded(),
    serveInitPageShortcut
];

//SERVICE REQUEST
exports.serviceRequest = [
    checkContentType(["application/json"]),
    defaultHeaders.setServiceHeader,
    httpAdapter
];

//VALIDATOR REQUEST
exports.validatorRequest = [
    checkContentType(["application/json"]),
    defaultHeaders.setValidatorHeader,
    httpAdapter
];

//STATIC REQUEST
var staticRequestMiddleware = [
    staticFileHandler
];

function staticRequest() {
    var bundler;

    if (env.isDevelopment()) {
        bundler = new Bundler();

        staticRequestMiddleware.unshift(logger);
        staticRequestMiddleware.unshift(bundler.getDevMiddleware());
    }

    return staticRequestMiddleware;
}

exports.staticRequest = staticRequest();

//UNHANDLED REQUEST
exports.unhandledRequest = [
    notFoundAsset,
    serveInitPage
];

//ON REQUEST ERROR
/**
 * Handler for errors within middleware-pipeline
 * ends the request and returns error-message depending on mode
 * @param err
 * @param req
 * @param res
 */
exports.requestError = function (err, req, res) {

    if (err) {

        if (env.isDevelopment()) {
            console.log(err.stack);
            res.end(err.toString(), "utf-8");
            return;
        }

        res.statusCode = 500;
        res.end("(alamid) Internal Server Error.");
    }
};<commit_msg>- added additional check for config.use.bundle<commit_after>"use strict";

var connect = require("connect"),
    logger = connect.logger(":method :url :status - :response-time ms");

var config = require("../../../shared/config"),
    paths = config.paths,
    env = require("../../../shared/env.js");

var Bundler = require("../../../core/bundle/Bundler.class.js"),
    parseURL = require("./middleware/parseURL.js"),
    serveInitPageShortcut = require("./middleware/serveInitPageShortcut.js"),
    serveInitPage = require("./middleware/serveInitPage.js"),
    notFoundAsset = require("./middleware/notFoundAsset.js"),
    staticFileHandler = require("./middleware/staticFileHandler.js"),
    defaultHeaders = require("./middleware/defaultHeaders.js"),
    checkContentType = require("./middleware/checkContentType.js"),
    httpAdapter = require("./middleware/httpAdapter.js");

//ON REQUEST
exports.request = [
    parseURL,
    connect.json(),
    connect.urlencoded(),
    serveInitPageShortcut
];

//SERVICE REQUEST
exports.serviceRequest = [
    checkContentType(["application/json"]),
    defaultHeaders.setServiceHeader,
    httpAdapter
];

//VALIDATOR REQUEST
exports.validatorRequest = [
    checkContentType(["application/json"]),
    defaultHeaders.setValidatorHeader,
    httpAdapter
];

//STATIC REQUEST
var staticRequestMiddleware = [
    staticFileHandler
];

function staticRequest() {
    var bundler;

    if (env.isDevelopment()) {

        staticRequestMiddleware.unshift(logger);

        if (config.use.bundle) {
            bundler = new Bundler();
            staticRequestMiddleware.unshift(bundler.getDevMiddleware());
        }

    }

    return staticRequestMiddleware;
}

exports.staticRequest = staticRequest();

//UNHANDLED REQUEST
exports.unhandledRequest = [
    notFoundAsset,
    serveInitPage
];

//ON REQUEST ERROR
/**
 * Handler for errors within middleware-pipeline
 * ends the request and returns error-message depending on mode
 * @param err
 * @param req
 * @param res
 */
exports.requestError = function (err, req, res) {

    if (err) {

        if (env.isDevelopment()) {
            console.log(err.stack);
            res.end(err.toString(), "utf-8");
            return;
        }

        res.statusCode = 500;
        res.end("(alamid) Internal Server Error.");
    }
};<|endoftext|>


<commit_before>var ChildEntityCache = require('./ChildEntityCache');

class NetworkEntities {

  constructor() {
    this.entities = {};
    this.childCache = new ChildEntityCache();
  }

  registerLocalEntity(networkId, entity) {
    this.entities[networkId] = entity;
  }

  createRemoteEntity(entityData) {
    NAF.log.write('Creating remote entity', entityData);

    var entity = document.createElement('a-entity');
    entity.setAttribute('id', 'naf-' + entityData.networkId);

    var template = entityData.template;
    var components = NAF.schemas.getComponents(template);
    this.initPosition(entity, entityData.components);
    this.initRotation(entity, entityData.components);
    this.addNetworkComponent(entity, entityData, components);
    this.entities[entityData.networkId] = entity;

    return entity;
  }

  initPosition(entity, componentData) {
    var hasPosition = componentData.hasOwnProperty('position');
    if (hasPosition) {
      var position = componentData.position;
      entity.setAttribute('position', position);
    }
  }

  initRotation(entity, componentData) {
    var hasRotation = componentData.hasOwnProperty('rotation');
    if (hasRotation) {
      var rotation = componentData.rotation;
      entity.setAttribute('rotation', rotation);
    }
  }

  addNetworkComponent(entity, entityData, components) {
    var networkData = {
      template: entityData.template,
      showTemplate: entityData.showTemplate,
      owner: entityData.owner,
      networkId: entityData.networkId,
      components: components
    };
    entity.setAttribute('networked-remote', networkData);
    entity.firstUpdateData = entityData;
  }

  updateEntity(client, dataType, entityData) {
    var isCompressed = entityData[0] == 1;
    var networkId = isCompressed ? entityData[1] : entityData.networkId;

    if (this.hasEntity(networkId)) {
      this.entities[networkId].emit('networkUpdate', {entityData: entityData}, false);
    } else if (!isCompressed) {
      this.receiveFirstUpdateFromEntity(entityData);
    }
  }

  receiveFirstUpdateFromEntity(entityData) {
    var parent = entityData.parent;
    var networkId = entityData.networkId;

    var parentNotCreatedYet = parent && !this.hasEntity(parent);
    if (parentNotCreatedYet) {
      this.childCache.addChild(parent, entityData);
    } else {
      var remoteEntity = this.createRemoteEntity(entityData);
      this.createAndAppendChildren(networkId, remoteEntity);
      this.addEntity(remoteEntity, parent);
    }
  }

  createAndAppendChildren(networkId, parentEntity) {
    var children = this.childCache.getChildren(networkId);
    for (var i = 0; i < children.length; i++) {
      var childEntity = this.createRemoteEntity(children[i]);
      parentEntity.appendChild(childEntity);
    }
  }

  addEntity(entity, parentId) {
    if (this.hasEntity(parentId)) {
      this.addEntityToParent(entity, parentId);
    } else {
      this.addEntityToScene(entity);
    }
  }

  addEntityToScene(entity) {
    var scene = document.querySelector('a-scene');
    scene.appendChild(entity);
  }

  addEntityToParent(entity, parentId) {
    var parentEl = document.getElementById('naf-' + parentId);
    parentEl.appendChild(entity);
  }

  completeSync() {
    for (var id in this.entities) {
      if (this.entities.hasOwnProperty(id)) {
        this.entities[id].emit('syncAll', null, false);
      }
    }
  }

  removeRemoteEntity(toClient, dataType, data) {
    var id = data.networkId;
    return this.removeEntity(id);
  }

  removeEntitiesFromUser(user) {
    var entityList = [];
    for (var id in this.entities) {
      var entityOwner = NAF.utils.getNetworkOwner(this.entities[id]);
      if (entityOwner == user) {
        var entity = this.removeEntity(id);
        entityList.push(entity);
      }
    }
    return entityList;
  }

  removeEntity(id) {
    if (this.hasEntity(id)) {
      var entity = this.entities[id];
      delete this.entities[id];
      entity.parentNode.removeChild(entity);
      return entity;
    } else {
      return null;
    }
  }

  getEntity(id) {
    if (this.entities.hasOwnProperty(id)) {
      return this.entities[id];
    }
    return null;
  }

  hasEntity(id) {
    return this.entities.hasOwnProperty(id);
  }
}

module.exports = NetworkEntities;<commit_msg>make remote template instantiations monkey-patch the root element<commit_after>var ChildEntityCache = require('./ChildEntityCache');

class NetworkEntities {

  constructor() {
    this.entities = {};
    this.childCache = new ChildEntityCache();
  }

  registerLocalEntity(networkId, entity) {
    this.entities[networkId] = entity;
  }

  createRemoteEntity(entityData) {
    NAF.log.write('Creating remote entity', entityData);

    var entity = document.createElement('a-entity');
    entity.setAttribute('id', 'naf-' + entityData.networkId);

    var template = entityData.template;
    var components = NAF.schemas.getComponents(template);
    this.initPosition(entity, entityData.components);
    this.initRotation(entity, entityData.components);
    this.addNetworkComponent(entity, entityData, components);
    this.entities[entityData.networkId] = entity;

    if (template) {
      entity.addEventListener('loaded', function () {

      var templateChild = entity.firstChild;
      templateChild.addEventListener('templaterendered', function () {
        var cloned = templateChild.firstChild;
	// mirror the attributes
        Array.prototype.slice.call(cloned.attributes).forEach(function (attr) {
          entity.setAttribute(attr.nodeName, attr.nodeValue);
        });
        // take the children
        for (var child = cloned.firstChild; child; child = cloned.firstChild) {
          cloned.removeChild(child);
          entity.appendChild(child);
        }

        cloned.pause();
        templateChild.pause();
        setTimeout(function() {
          try { templateChild.removeChild(cloned); } catch (e) {}
          try { entity.removeChild(templateChild); } catch (e) {}
	  // delete?
        });
      });

      });
    }

    return entity;
  }

  initPosition(entity, componentData) {
    var hasPosition = componentData.hasOwnProperty('position');
    if (hasPosition) {
      var position = componentData.position;
      entity.setAttribute('position', position);
    }
  }

  initRotation(entity, componentData) {
    var hasRotation = componentData.hasOwnProperty('rotation');
    if (hasRotation) {
      var rotation = componentData.rotation;
      entity.setAttribute('rotation', rotation);
    }
  }

  addNetworkComponent(entity, entityData, components) {
    var networkData = {
      template: entityData.template,
      showTemplate: entityData.showTemplate,
      //showLocalTemplate: entityData.showTemplate,
      //showRemoteTemplate: entityData.showTemplate,
      owner: entityData.owner,
      networkId: entityData.networkId,
      components: components
    };
    entity.setAttribute('networked-remote', networkData);
    //entity.setAttribute('networked-share', networkData);
    entity.firstUpdateData = entityData;
  }

  updateEntity(client, dataType, entityData) {
    var isCompressed = entityData[0] == 1;
    var networkId = isCompressed ? entityData[1] : entityData.networkId;

    if (this.hasEntity(networkId)) {
      this.entities[networkId].emit('networkUpdate', {entityData: entityData}, false);
    } else if (!isCompressed) {
      this.receiveFirstUpdateFromEntity(entityData);
    }
  }

  receiveFirstUpdateFromEntity(entityData) {
    var parent = entityData.parent;
    var networkId = entityData.networkId;

    var parentNotCreatedYet = parent && !this.hasEntity(parent);
    if (parentNotCreatedYet) {
      this.childCache.addChild(parent, entityData);
    } else {
      var remoteEntity = this.createRemoteEntity(entityData);
      this.createAndAppendChildren(networkId, remoteEntity);
      this.addEntity(remoteEntity, parent);
    }
  }

  createAndAppendChildren(networkId, parentEntity) {
    var children = this.childCache.getChildren(networkId);
    for (var i = 0; i < children.length; i++) {
      var childEntity = this.createRemoteEntity(children[i]);
      parentEntity.appendChild(childEntity);
    }
  }

  addEntity(entity, parentId) {
    if (this.hasEntity(parentId)) {
      this.addEntityToParent(entity, parentId);
    } else {
      this.addEntityToScene(entity);
    }
  }

  addEntityToScene(entity) {
    var scene = document.querySelector('a-scene');
    scene.appendChild(entity);
  }

  addEntityToParent(entity, parentId) {
    var parentEl = document.getElementById('naf-' + parentId);
    parentEl.appendChild(entity);
  }

  completeSync() {
    for (var id in this.entities) {
      if (this.entities.hasOwnProperty(id)) {
        this.entities[id].emit('syncAll', null, false);
      }
    }
  }

  removeRemoteEntity(toClient, dataType, data) {
    var id = data.networkId;
    return this.removeEntity(id);
  }

  removeEntitiesFromUser(user) {
    var entityList = [];
    for (var id in this.entities) {
      var entityOwner = NAF.utils.getNetworkOwner(this.entities[id]);
      if (entityOwner == user) {
        var entity = this.removeEntity(id);
        entityList.push(entity);
      }
    }
    return entityList;
  }

  removeEntity(id) {
    if (this.hasEntity(id)) {
      var entity = this.entities[id];
      delete this.entities[id];
      entity.parentNode.removeChild(entity);
      return entity;
    } else {
      return null;
    }
  }

  getEntity(id) {
    if (this.entities.hasOwnProperty(id)) {
      return this.entities[id];
    }
    return null;
  }

  hasEntity(id) {
    return this.entities.hasOwnProperty(id);
  }
}

module.exports = NetworkEntities;
<|endoftext|>