<commit_before>'use strict';

// MODULES //

var bench = require( '@stdlib/bench' );
var randu = require( '@stdlib/math/base/random/randu' );
var pow = require( '@stdlib/math/base/special/pow' );
var isnan = require( '@stdlib/math/base/utils/is-nan' );
var pkg = require( './../package.json' ).name;
var wasm = require( './../lib/wasm.js' )();

// FUNCTIONS //

/**
* Creates a benchmark function.
*
* @private
* @param {PositiveInteger} len - array length
* @returns {Function} benchmark function
*/
function createBenchmark1( len ) {
	var x;
	var i;

	x = new Float64Array( len );
	for ( i = 0; i < x.length; i++ ) {
		x[ i ] = ( randu()*10000.0 ) - 20000.0;
	}
	return benchmark;

	/**
	* Benchmark function.
	*
	* @private
	* @param {Benchmark} b - benchmark instance
	*/
	function benchmark( b ) {
		var i;
		var j;

		b.tic();
		for ( i = 0; i < b.iterations; i++ ) {
			for ( j = 0; j < len; j++ ) {
				x[ j ] = ( randu()*10000.0 ) - 20000.0;
			}
			if ( isnan( x[ j ] ) ) {
				b.fail( 'should not return NaN' );
			}
		}
		b.toc();
		if ( isnan( x[ j ] ) ) {
			b.fail( 'should not return NaN' );
		}
		b.pass( 'benchmark finished' );
		b.end();
	} // end FUNCTION benchmark()
} // end FUNCTION createBenchmark1()

/**
* Creates a benchmark function.
*
* @private
* @param {PositiveInteger} len - array length
* @returns {Function} benchmark function
*/
function createBenchmark2( len ) {
	var x;
	var i;

	x = new Float64Array( len );
	for ( i = 0; i < x.length; i++ ) {
		x[ i ] = ( randu()*10000.0 ) - 20000.0;
	}
	return benchmark;

	/**
	* Benchmark function.
	*
	* @private
	* @param {Benchmark} b - benchmark instance
	*/
	function benchmark( b ) {
		var nbytes;
		var heap;
		var v;
		var i;
		var j;

		nbytes = x.length * x.BYTES_PER_ELEMENT;
		heap = wasm.malloc( nbytes );
		heap.set( new Uint8Array( x.buffer ) );

		b.tic();
		for ( i = 0; i < b.iterations; i++ ) {
			for ( j = 0; j < len; j++ ) {
				v = ( randu()*10000.0 ) - 20000.0;
				heap.setValue( j * x.BYTES_PER_ELEMENT, v );
			}
			if ( isnan( v ) ) {
				b.fail( 'should not return NaN' );
			}
		}
		b.toc();
		if ( isnan( v ) ) {
			b.fail( 'should not return NaN' );
		}
		b.pass( 'benchmark finished' );

		wasm.free( heap );
		b.end();
	} // end FUNCTION benchmark()
} // end FUNCTION createBenchmark2()

// MAIN //

/**
* Main execution sequence.
*
* @private
*/
function main() {
	var len;
	var min;
	var max;
	var f;
	var i;

	min = 1; // 10^min
	max = 6; // 10^max

	for ( i = min; i <= max; i++ ) {
		len = pow( 10, i );

		f = createBenchmark1( len );
		bench( pkg+'::set-value,main:len='+len, f );

		f = createBenchmark2( len );
		bench( pkg+'::set-value,wasm:len='+len, f );
	}
} // end FUNCTION main()

main();
<commit_msg>Add benchmarks for creating a separate view<commit_after>'use strict';

// MODULES //

var bench = require( '@stdlib/bench' );
var randu = require( '@stdlib/math/base/random/randu' );
var pow = require( '@stdlib/math/base/special/pow' );
var isnan = require( '@stdlib/math/base/utils/is-nan' );
var pkg = require( './../package.json' ).name;
var wasm = require( './../lib/wasm.js' )();

// FUNCTIONS //

/**
* Creates a benchmark function.
*
* @private
* @param {PositiveInteger} len - array length
* @returns {Function} benchmark function
*/
function createBenchmark1( len ) {
	var x;
	var i;

	x = new Float64Array( len );
	for ( i = 0; i < x.length; i++ ) {
		x[ i ] = ( randu()*10000.0 ) - 20000.0;
	}
	return benchmark;

	/**
	* Benchmark function.
	*
	* @private
	* @param {Benchmark} b - benchmark instance
	*/
	function benchmark( b ) {
		var v;
		var i;
		var j;

		b.tic();
		for ( i = 0; i < b.iterations; i++ ) {
			for ( j = 0; j < len; j++ ) {
				v = ( randu()*10000.0 ) - 20000.0;
				x[ j ] = v;
			}
			if ( isnan( v ) ) {
				b.fail( 'should not return NaN' );
			}
		}
		b.toc();
		if ( isnan( v ) ) {
			b.fail( 'should not return NaN' );
		}
		b.pass( 'benchmark finished' );
		b.end();
	} // end FUNCTION benchmark()
} // end FUNCTION createBenchmark1()

/**
* Creates a benchmark function.
*
* @private
* @param {PositiveInteger} len - array length
* @returns {Function} benchmark function
*/
function createBenchmark2( len ) {
	var x;
	var i;

	x = new Float64Array( len );
	for ( i = 0; i < x.length; i++ ) {
		x[ i ] = ( randu()*10000.0 ) - 20000.0;
	}
	return benchmark;

	/**
	* Benchmark function.
	*
	* @private
	* @param {Benchmark} b - benchmark instance
	*/
	function benchmark( b ) {
		var nbytes;
		var heap;
		var v;
		var i;
		var j;

		nbytes = x.length * x.BYTES_PER_ELEMENT;
		heap = wasm.malloc( nbytes );
		heap.set( new Uint8Array( x.buffer ) );

		b.tic();
		for ( i = 0; i < b.iterations; i++ ) {
			for ( j = 0; j < len; j++ ) {
				v = ( randu()*10000.0 ) - 20000.0;
				heap.setValue( j * x.BYTES_PER_ELEMENT, v );
			}
			if ( isnan( v ) ) {
				b.fail( 'should not return NaN' );
			}
		}
		b.toc();
		if ( isnan( v ) ) {
			b.fail( 'should not return NaN' );
		}
		b.pass( 'benchmark finished' );

		wasm.free( heap );
		b.end();
	} // end FUNCTION benchmark()
} // end FUNCTION createBenchmark2()

/**
* Creates a benchmark function.
*
* @private
* @param {PositiveInteger} len - array length
* @returns {Function} benchmark function
*/
function createBenchmark3( len ) {
	var x;
	var i;

	x = new Float64Array( len );
	for ( i = 0; i < x.length; i++ ) {
		x[ i ] = ( randu()*10000.0 ) - 20000.0;
	}
	return benchmark;

	/**
	* Benchmark function.
	*
	* @private
	* @param {Benchmark} b - benchmark instance
	*/
	function benchmark( b ) {
		var nbytes;
		var heap;
		var view;
		var v;
		var i;
		var j;

		nbytes = x.length * x.BYTES_PER_ELEMENT;
		heap = wasm.malloc( nbytes );
		heap.set( new Uint8Array( x.buffer ) );

		view = new Float64Array( heap.buffer, heap.byteOffset, x.length );

		b.tic();
		for ( i = 0; i < b.iterations; i++ ) {
			for ( j = 0; j < len; j++ ) {
				v = ( randu()*10000.0 ) - 20000.0;
				view[ j ] = v;
			}
			if ( isnan( v ) ) {
				b.fail( 'should not return NaN' );
			}
		}
		b.toc();
		if ( isnan( v ) ) {
			b.fail( 'should not return NaN' );
		}
		b.pass( 'benchmark finished' );

		wasm.free( heap );
		b.end();
	} // end FUNCTION benchmark()
} // end FUNCTION createBenchmark3()

// MAIN //

/**
* Main execution sequence.
*
* @private
*/
function main() {
	var len;
	var min;
	var max;
	var f;
	var i;

	min = 1; // 10^min
	max = 6; // 10^max

	for ( i = min; i <= max; i++ ) {
		len = pow( 10, i );

		f = createBenchmark1( len );
		bench( pkg+'::set-value,main:len='+len, f );

		f = createBenchmark2( len );
		bench( pkg+'::set-value,wasm:len='+len, f );

		f = createBenchmark3( len );
		bench( pkg+'::set-value,wasm,view:len='+len, f );
	}
} // end FUNCTION main()

main();
<|endoftext|>


<commit_before>// Handles related-objects functionality: lookup link for raw_id_admin=True
// and Add Another links.

function showRelatedObjectLookupPopup(triggeringLink) {
    var name = triggeringLink.id.replace(/^lookup_/, '');
    // IE doesn't like periods in the window name, so convert temporarily.
    name = name.replace(/\./g, '___');
    var href;
    if (triggeringLink.href.search(/\?/) >= 0) {
        href = triggeringLink.href + '&pop=1';
    } else {
        href = triggeringLink.href + '?pop=1';
    }
    var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
    win.focus();
    return false;
}

function dismissRelatedLookupPopup(win, chosenId) {
    var name = win.name.replace(/___/g, '.');
    var elem = document.getElementById(name);
    if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
        elem.value += ',' + chosenId;
    } else {
        document.getElementById(name).value = chosenId;
    }
    win.close();
}

function showAddAnotherPopup(triggeringLink) {
    var name = triggeringLink.id.replace(/^add_/, '');
    name = name.replace(/\./g, '___');
    href = triggeringLink.href
    if (href.indexOf('?') == -1)
	href += '?_popup=1';
    else
	href += '&_popup=1';
    var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
    win.focus();
    return false;
}

function dismissAddAnotherPopup(win, newId, newRepr) {
    var name = win.name.replace(/___/g, '.');
    var elem = document.getElementById(name);
    if (elem) {
        if (elem.nodeName == 'SELECT') {
            var o = new Option(newRepr, newId);
            elem.options[elem.options.length] = o;
            o.selected = true;
        } else if (elem.nodeName == 'INPUT') {
            elem.value = newId;
        }
    } else {
        var toId = name + "_to";
        elem = document.getElementById(toId);
        var o = new Option(newRepr, newId);
        SelectBox.add_to_cache(toId, o);
        SelectBox.redisplay(toId);
    }
    win.close();
}
<commit_msg>Fixed #4556 -- Stylistic changes to [5500]. Thanks, glin@seznam.cz.<commit_after>// Handles related-objects functionality: lookup link for raw_id_admin=True
// and Add Another links.

function showRelatedObjectLookupPopup(triggeringLink) {
    var name = triggeringLink.id.replace(/^lookup_/, '');
    // IE doesn't like periods in the window name, so convert temporarily.
    name = name.replace(/\./g, '___');
    var href;
    if (triggeringLink.href.search(/\?/) >= 0) {
        href = triggeringLink.href + '&pop=1';
    } else {
        href = triggeringLink.href + '?pop=1';
    }
    var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
    win.focus();
    return false;
}

function dismissRelatedLookupPopup(win, chosenId) {
    var name = win.name.replace(/___/g, '.');
    var elem = document.getElementById(name);
    if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
        elem.value += ',' + chosenId;
    } else {
        document.getElementById(name).value = chosenId;
    }
    win.close();
}

function showAddAnotherPopup(triggeringLink) {
    var name = triggeringLink.id.replace(/^add_/, '');
    name = name.replace(/\./g, '___');
    href = triggeringLink.href
    if (href.indexOf('?') == -1) {
        href += '?_popup=1';
    } else {
        href  += '&_popup=1';
    }
    var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
    win.focus();
    return false;
}

function dismissAddAnotherPopup(win, newId, newRepr) {
    var name = win.name.replace(/___/g, '.');
    var elem = document.getElementById(name);
    if (elem) {
        if (elem.nodeName == 'SELECT') {
            var o = new Option(newRepr, newId);
            elem.options[elem.options.length] = o;
            o.selected = true;
        } else if (elem.nodeName == 'INPUT') {
            elem.value = newId;
        }
    } else {
        var toId = name + "_to";
        elem = document.getElementById(toId);
        var o = new Option(newRepr, newId);
        SelectBox.add_to_cache(toId, o);
        SelectBox.redisplay(toId);
    }
    win.close();
}
<|endoftext|>


<commit_before>// Handles related-objects functionality: lookup link for raw_id_admin=True
// and Add Another links.

function showRelatedObjectLookupPopup(triggeringLink) {
    var name = triggeringLink.id.replace(/^lookup_/, '');
    var href;
    if (triggeringLink.href.search(/\?/) >= 0) {
        href = triggeringLink.href + '&pop=1';
    } else {
        href = triggeringLink.href + '?pop=1';
    }
    var win = window.open(href, name, 'height=500,width=740,resizable=yes,scrollbars=yes');
    win.focus();
    return false;
}

function dismissRelatedLookupPopup(win, chosenId) {
    var elem = document.getElementById(win.name);
    if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
        elem.value += ',' + chosenId;
    } else {
        document.getElementById(win.name).value = chosenId;
    }
    win.close();
}

function showAddAnotherPopup(triggeringLink) {
    var name = triggeringLink.id.replace(/^add_/, '');
    name = name.replace(/\./g, '___');
    var win = window.open(triggeringLink.href + '?_popup=1', name, 'height=500,width=800,resizable=yes,scrollbars=yes');
    win.focus();
    return false;
}

function dismissAddAnotherPopup(win, newId, newRepr) {
    var name = win.name.replace(/___/g, '.');
    var elem = document.getElementById(name);
    if (elem) {
        if (elem.nodeName == 'SELECT') {
            var o = new Option(newRepr, newId);
            elem.options[elem.options.length] = o;
            o.selected = true;
        } else if (elem.nodeName == 'INPUT') {
            elem.value = newId;
        }
    } else {
        var toId = name + "_to";
        elem = document.getElementById(toId);
        var o = new Option(newRepr, newId);
        SelectBox.add_to_cache(toId, o);
        SelectBox.redisplay(toId);
    }
    win.close();
}
<commit_msg>Fixed #1635 -- Admin-site related-object popup no longer fails for edit_inline objects in IE/Win. Thanks, Christopher Lenz<commit_after>// Handles related-objects functionality: lookup link for raw_id_admin=True
// and Add Another links.

function showRelatedObjectLookupPopup(triggeringLink) {
    var name = triggeringLink.id.replace(/^lookup_/, '');
    // IE doesn't like periods in the window name, so convert temporarily.
    name = name.replace(/\./g, '___');
    var href;
    if (triggeringLink.href.search(/\?/) >= 0) {
        href = triggeringLink.href + '&pop=1';
    } else {
        href = triggeringLink.href + '?pop=1';
    }
    var win = window.open(href, name, 'height=500,width=740,resizable=yes,scrollbars=yes');
    win.focus();
    return false;
}

function dismissRelatedLookupPopup(win, chosenId) {
    var name = win.name.replace(/___/g, '.');
    var elem = document.getElementById(name);
    if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
        elem.value += ',' + chosenId;
    } else {
        document.getElementById(name).value = chosenId;
    }
    win.close();
}

function showAddAnotherPopup(triggeringLink) {
    var name = triggeringLink.id.replace(/^add_/, '');
    name = name.replace(/\./g, '___');
    var win = window.open(triggeringLink.href + '?_popup=1', name, 'height=500,width=800,resizable=yes,scrollbars=yes');
    win.focus();
    return false;
}

function dismissAddAnotherPopup(win, newId, newRepr) {
    var name = win.name.replace(/___/g, '.');
    var elem = document.getElementById(name);
    if (elem) {
        if (elem.nodeName == 'SELECT') {
            var o = new Option(newRepr, newId);
            elem.options[elem.options.length] = o;
            o.selected = true;
        } else if (elem.nodeName == 'INPUT') {
            elem.value = newId;
        }
    } else {
        var toId = name + "_to";
        elem = document.getElementById(toId);
        var o = new Option(newRepr, newId);
        SelectBox.add_to_cache(toId, o);
        SelectBox.redisplay(toId);
    }
    win.close();
}
<|endoftext|>


<commit_before>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component } from 'react';
import DocsArticle from '../../components/DocsArticle';
import NavAnchor from '../../components/NavAnchor';
import Example from '../Example';
import Notification from 'grommet/components/Notification';

Notification.displayName = 'Notification';

export default class NotificationDoc extends Component {

  render () {
    return (
      <DocsArticle title="Notification" colorIndex="neutral-3">

A box to display Notification messages.

          <Notification status='warning'
            message='Inconsistent configuration detected.' />

Options

closer           {"true|false|{node}"}

Adds a visible control to close the layer.
              If the caller provides a node, it is the caller's
              responsibility to listen to events from the node.

message          {"{string}"}

Message to display in the notification box.

onClose          {"{function ()}"}

Function that will be called when the user clicks on the
              closer control. Clicking the closer control does not automatically
              cause the Layer to be removed. The recipient of this callback can
              still decide whether to continue rendering the Layer or not.

percentComplete  {"{number}"}

Number to measure the progress of an ongoing notification.

size             small|medium|large

Size of the notification box.

state            {"{string}"}

State of the element on the notification message
              (e.g. Active, Running).

status           {"{string}"}

Status of the element on the nofitication message
              (e.g. Ok, Critical).

timestamp        {"{date}"}

Timestamp of the notification message.

Options for <NavAnchor path="/docs/box">Box</NavAnchor> are
          also available for Notification.

Examples

          <Example name="Unknown" code={
            <Notification message='Unknown Message' />
          } />
          <Example name="Warning" code={
            <Notification status='warning'
              message='Inconsistent configuration detected.'
              timestamp={new Date('Mon Jan 25 2016')}
              state='Active'
              closer={true} />
          } />
          <Example name="Critical" code={
            <Notification status='critical'
              message='Temperature threshold exceeded by 10 degrees.'
              timestamp={new Date('Mon Jan 25 2016')}
              state='Active' />
          } />
          <Example name="OK" code={
            <Notification status='ok'
              message='Updated server configuration.'
              timestamp={new Date('Mon Jan 25 2016')}
              state='Completed' />
          } />
          <Example name="Percent Complete" code={
            <Notification status='ok'
              message='Updating server profile.'
              timestamp={new Date('Mon Jan 25 2016')}
              state='Running'
              percentComplete={30} />
          } />

      </DocsArticle>
    );
  }
};
<commit_msg>Added closer example to Notification Doc.<commit_after>// (C) Copyright 2014-2016 Hewlett Packard Enterprise Development LP

import React, { Component } from 'react';
import DocsArticle from '../../components/DocsArticle';
import NavAnchor from '../../components/NavAnchor';
import Example from '../Example';
import Notification from 'grommet/components/Notification';

Notification.displayName = 'Notification';

export default class NotificationDoc extends Component {

  constructor () {
    super();
    this.state = {
      showNotification: true
    };
  }

  render () {

    let closerExample;
    if (this.state.showNotification) {
      closerExample = (
        <Example name="Closer" code={
          <Notification status='critical'
            message='Temperature threshold exceeded by 10 degrees.'
            timestamp={new Date('Mon Jan 25 2016')}
            state='Active' closer={true}
            onClose={() => this.setState({ showNotification: false })} />
        } />
      );
    }
    return (
      <DocsArticle title="Notification" colorIndex="neutral-3">

A box to display Notification messages.

          <Notification status='warning'
            message='Inconsistent configuration detected.' />

Options

closer           {"true|false|{node}"}

Adds a visible control to close the layer.
              If the caller provides a node, it is the caller's
              responsibility to listen to events from the node.

message          {"{string}"}

Message to display in the notification box.

onClose          {"{function ()}"}

Function that will be called when the user clicks on the
              closer control. Clicking the closer control does not automatically
              cause the Notification to be removed.
              The recipient of this callback can
              still decide whether to continue rendering the Notification
              or not.

percentComplete  {"{number}"}

Number to measure the progress of an ongoing notification.

size             small|medium|large

Size of the notification box.

state            {"{string}"}

State of the element on the notification message
              (e.g. Active, Running).

status           {"{string}"}

Status of the element on the nofitication message
              (e.g. Ok, Critical).

timestamp        {"{date}"}

Timestamp of the notification message.

Options for <NavAnchor path="/docs/box">Box</NavAnchor> are
          also available for Notification.

Examples

          <Example name="Unknown" code={
            <Notification message='Unknown Message' />
          } />
          <Example name="Warning" code={
            <Notification status='warning'
              message='Inconsistent configuration detected.'
              timestamp={new Date('Mon Jan 25 2016')}
              state='Active'
              closer={true} />
          } />
          <Example name="Critical" code={
            <Notification status='critical'
              message='Temperature threshold exceeded by 10 degrees.'
              timestamp={new Date('Mon Jan 25 2016')}
              state='Active' />
          } />
          <Example name="OK" code={
            <Notification status='ok'
              message='Updated server configuration.'
              timestamp={new Date('Mon Jan 25 2016')}
              state='Completed' />
          } />
          <Example name="Percent Complete" code={
            <Notification status='ok'
              message='Updating server profile.'
              timestamp={new Date('Mon Jan 25 2016')}
              state='Running'
              percentComplete={30} />
          } />
          {closerExample}

      </DocsArticle>
    );
  }
};
<|endoftext|>


<commit_before>String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.split(search).join(replacement);
};

// Filesystem setup
var url = '';
var files = ["readme.md"];

$(function() {

  // Set the command-line prompt to include the user's IP Address
    $('.prompt').html('user ~' + url + ' $ ');

  // Initialize a new terminal object
  var term = new Terminal('#input-line .cmdline', '#container output');
  term.init();

});
document.getElementById("noJsSupport").style.display = 'none';
var util = util || {};
util.toArray = function(list) {
  return Array.prototype.slice.call(list || [], 0);
};

var Terminal = Terminal || function(cmdLineContainer, outputContainer) {
  window.URL = window.URL || window.webkitURL;
  window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;

  var cmdLine_ = document.querySelector(cmdLineContainer);
  var output_ = document.querySelector(outputContainer);

  const CMDS_ = [
    'about', 'calc [-n]', 'clear', 'date', 'echo [-neE]', 'git', 'uname', 'whoami', 'license', 'credits'
  ];

  var fs_ = null;
  var cwd_ = null;
  var history_ = [];
  var histpos_ = 0;
  var histtemp_ = 0;

  window.addEventListener('click', function(e) {
    cmdLine_.focus();
  }, false);

  cmdLine_.addEventListener('click', inputTextClick_, false);
  cmdLine_.addEventListener('keydown', historyHandler_, false);
  cmdLine_.addEventListener('keydown', processNewCommand_, false);

  //
  function inputTextClick_(e) {
    this.value = this.value;
  }

  //
  function historyHandler_(e) {
    if (history_.length) {
      if (e.keyCode == 38 || e.keyCode == 40) {
        if (history_[histpos_]) {
          history_[histpos_] = this.value;
        } else {
          histtemp_ = this.value;
        }
      }

      if (e.keyCode == 38) { // up
        histpos_--;
        if (histpos_ < 0) {
          histpos_ = 0;
        }
      } else if (e.keyCode == 40) { // down
        histpos_++;
        if (histpos_ > history_.length) {
          histpos_ = history_.length;
        }
      }

      if (e.keyCode == 38 || e.keyCode == 40) {
        this.value = history_[histpos_] ? history_[histpos_] : histtemp_;
        this.value = this.value; // Sets cursor to end of input.
      }
    }
  }

  //
  function processNewCommand_(e) {

    if (e.keyCode == 9) { // tab
      e.preventDefault();
      // Implement tab suggest.
    } else if (e.keyCode == 13) { // enter
      // Save shell history.
      if (this.value) {
        history_[history_.length] = this.value;
        histpos_ = history_.length;
      }

      // Duplicate current input and append to output section.
      var line = this.parentNode.parentNode.cloneNode(true);
      line.removeAttribute('id')
      line.classList.add('line');
      var input = line.querySelector('input.cmdline');
      input.autofocus = false;
      input.readOnly = true;
      output_.appendChild(line);

      if (this.value && this.value.trim()) {
        var args = this.value.split(' ').filter(function(val, i) {
          return val;
        });
        var cmd = args[0].toLowerCase();
        args = args.splice(1); // Remove cmd from arg list.
      }

      switch (cmd) {
        case 'cat':
          var url = args.join(' ');
          if (!url) {
            output('Usage: ' + cmd + ': Displays file contents.');
            break;
          }
          $.get( url, function(data) {
            var encodedStr = data.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
               return '&#'+i.charCodeAt(0)+';';
            });
            output('
' + encodedStr + '
');
          });
          break;
        case 'clear':
          output_.innerHTML = '';
          this.value = '';
          return;
          output('
' + new Date() + '
');
          break;
        case 'date':
          output( new Date() );
          break;
        case 'echo':
          output( args.join(' ').replaceAll('</', '</').replaceAll('<', '<').replaceAll('/>', '/>').replaceAll('>', '>').replaceAll('\\n', '
') );
          break;
        case 'nano':
          output('');
          break;
        case 'about':
          output('
Torminal

Enter "help" for more information.

(c) 2018 Henry Gruett Under MIT License');
        case 'help':
          output('
' + CMDS_.join('
') + '
');
          break;
        case 'uname':
          output(navigator.appVersion);
          break;
        case 'whoami':
          var findIP = new Promise(r=>{var w=window,a=new (w.RTCPeerConnection||w.mozRTCPeerConnection||w.webkitRTCPeerConnection)({iceServers:[]}),b=()=>{};a.createDataChannel("");a.createOffer(c=>a.setLocalDescription(c,b,b),b);a.onicecandidate=c=>{try{c.candidate.candidate.match(/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g).forEach(r)}catch(e){}}})
          findIP.then(ip => output('' + ip + ''))
          break;
        case 'git':
          output('Usage: ' + cmd + ' [--version] [--help] <command> [<args>]');
          output('git is a popular VCM.  git docs can be found at https://git-scm.com/doc');
          break;
        case 'ls':
          output( files.join(' ') );
          break;
        case 'calc':
          output( math.eval(args.join(' ')) );
          break;
        case 'license':
          var txt = "\
            Torminal is licensed under the MIT License.
\

\
            ----------
\

\
            MIT License
\

\
            Copyright (c) 2018 Henry Gruett (GitHub/@card100)
\

\
            Permission is hereby granted, free of charge, to any person obtaining a copy
\
            of this software and associated documentation files (the \"Software\"), to deal
\
            in the Software without restriction, including without limitation the rights
\
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\
            copies of the Software, and to permit persons to whom the Software is
\
            furnished to do so, subject to the following conditions:
\

\
            The above copyright notice and this permission notice shall be included in all
\
            copies or substantial portions of the Software.
\

\
            THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\
            SOFTWARE.\
              ";
          output(txt);
          break;
        case 'credits':
              output("TORMINAL

Created by:
Henry Gruett card100

Contributors:
Nanomotion, Sheshank Shankar GreenBayRules, Arav Narula, csf30816, Kerr Travers ktrvs
Notes:
torminal was built on top of Andrew M Barfield's HTML5 Web Terminal. It is released under a standard MIT license.
Math handled by math.js.  It is released under a Apache License 2.0 license.  No changes have been made to the API.");
              break;
        default:
          if (cmd) {
            output('' + cmd + ': command not found');
          }
      };

      window.scrollTo(0, getDocHeight_());
      this.value = ''; // Clear/setup line for next input.
    }
  }

  //
  function formatColumns_(entries) {
    var maxName = entries[0].name;
    util.toArray(entries).forEach(function(entry, i) {
      if (entry.name.length > maxName.length) {
        maxName = entry.name;
      }
    });

    var height = entries.length <= 3 ?
        'height: ' + (entries.length * 15) + 'px;' : '';

    // 12px monospace font yields ~7px screen width.
    var colWidth = maxName.length * 7;

    return ['
'];
  }

  //
  function output(html) {
    output_.insertAdjacentHTML('beforeEnd', '
' + html + '
');
    return(0);
  }

  // Cross-browser impl to get document's height.
  function getDocHeight_() {
    var d = document;
    return Math.max(
        Math.max(d.body.scrollHeight, d.documentElement.scrollHeight),
        Math.max(d.body.offsetHeight, d.documentElement.offsetHeight),
        Math.max(d.body.clientHeight, d.documentElement.clientHeight)
    );
  }

  //
  return {
    init: function() {
      output('
Torminal

' + new Date() + '

Enter "help" for more information.

(c) 2017 Henry Gruett Under MIT License. Type \'license\' for more info.');
    },
    output: output
  }
};
<commit_msg>Cookie setup<commit_after>String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.split(search).join(replacement);
};

// Filesystem setup
var url = '';
var files = ["readme.md"];
var fileValues = ["# Hello World!"];
// Cookies might need to be declared ouside of load out function

// Load in:
var files = Cookies.get('fileCookie');
var fileValues = Cookies.get('fileValuesCookie');

// Load out
window.onbeforeunload = cookiesSave(){
    Cookies.set("fileCookie", files);
    Cookies.set("fileValuesCookie", fileValues);
};

$(function() {

  // Set the command-line prompt to include the user's IP Address
    $('.prompt').html('user ~' + url + ' $ ');

  // Initialize a new terminal object
  var term = new Terminal('#input-line .cmdline', '#container output');
  term.init();

});
document.getElementById("noJsSupport").style.display = 'none';
var util = util || {};
util.toArray = function(list) {
  return Array.prototype.slice.call(list || [], 0);
};

var Terminal = Terminal || function(cmdLineContainer, outputContainer) {
  window.URL = window.URL || window.webkitURL;
  window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;

  var cmdLine_ = document.querySelector(cmdLineContainer);
  var output_ = document.querySelector(outputContainer);

  const CMDS_ = [
    'about', 'calc [-n]', 'clear', 'date', 'echo [-neE]', 'git', 'uname', 'whoami', 'license', 'credits'
  ];

  var fs_ = null;
  var cwd_ = null;
  var history_ = [];
  var histpos_ = 0;
  var histtemp_ = 0;

  window.addEventListener('click', function(e) {
    cmdLine_.focus();
  }, false);

  cmdLine_.addEventListener('click', inputTextClick_, false);
  cmdLine_.addEventListener('keydown', historyHandler_, false);
  cmdLine_.addEventListener('keydown', processNewCommand_, false);

  //
  function inputTextClick_(e) {
    this.value = this.value;
  }

  //
  function historyHandler_(e) {
    if (history_.length) {
      if (e.keyCode == 38 || e.keyCode == 40) {
        if (history_[histpos_]) {
          history_[histpos_] = this.value;
        } else {
          histtemp_ = this.value;
        }
      }

      if (e.keyCode == 38) { // up
        histpos_--;
        if (histpos_ < 0) {
          histpos_ = 0;
        }
      } else if (e.keyCode == 40) { // down
        histpos_++;
        if (histpos_ > history_.length) {
          histpos_ = history_.length;
        }
      }

      if (e.keyCode == 38 || e.keyCode == 40) {
        this.value = history_[histpos_] ? history_[histpos_] : histtemp_;
        this.value = this.value; // Sets cursor to end of input.
      }
    }
  }

  //
  function processNewCommand_(e) {

    if (e.keyCode == 9) { // tab
      e.preventDefault();
      // Implement tab suggest.
    } else if (e.keyCode == 13) { // enter
      // Save shell history.
      if (this.value) {
        history_[history_.length] = this.value;
        histpos_ = history_.length;
      }

      // Duplicate current input and append to output section.
      var line = this.parentNode.parentNode.cloneNode(true);
      line.removeAttribute('id')
      line.classList.add('line');
      var input = line.querySelector('input.cmdline');
      input.autofocus = false;
      input.readOnly = true;
      output_.appendChild(line);

      if (this.value && this.value.trim()) {
        var args = this.value.split(' ').filter(function(val, i) {
          return val;
        });
        var cmd = args[0].toLowerCase();
        args = args.splice(1); // Remove cmd from arg list.
      }

      switch (cmd) {
        case 'cat':
          var url = args.join(' ');
          if (!url) {
            output('Usage: ' + cmd + ': Displays file contents.');
            break;
          }
          $.get( url, function(data) {
            var encodedStr = data.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
               return '&#'+i.charCodeAt(0)+';';
            });
            output('
' + encodedStr + '
');
          });
          break;
        case 'clear':
          output_.innerHTML = '';
          this.value = '';
          return;
          output('
' + new Date() + '
');
          break;
        case 'date':
          output( new Date() );
          break;
        case 'echo':
          output( args.join(' ').replaceAll('</', '</').replaceAll('<', '<').replaceAll('/>', '/>').replaceAll('>', '>').replaceAll('\\n', '
') );
          break;
        case 'nano':
          output('');
          break;
        case 'about':
          output('
Torminal

Enter "help" for more information.

(c) 2018 Henry Gruett Under MIT License');
        case 'help':
          output('
' + CMDS_.join('
') + '
');
          break;
        case 'uname':
          output(navigator.appVersion);
          break;
        case 'whoami':
          var findIP = new Promise(r=>{var w=window,a=new (w.RTCPeerConnection||w.mozRTCPeerConnection||w.webkitRTCPeerConnection)({iceServers:[]}),b=()=>{};a.createDataChannel("");a.createOffer(c=>a.setLocalDescription(c,b,b),b);a.onicecandidate=c=>{try{c.candidate.candidate.match(/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g).forEach(r)}catch(e){}}})
          findIP.then(ip => output('' + ip + ''))
          break;
        case 'git':
          output('Usage: ' + cmd + ' [--version] [--help] <command> [<args>]');
          output('git is a popular VCM.  git docs can be found at https://git-scm.com/doc');
          break;
        case 'ls':
          output( files.join(' ') );
          break;
        case 'calc':
          output( math.eval(args.join(' ')) );
          break;
        case 'license':
          var txt = "\
            Torminal is licensed under the MIT License.
\

\
            ----------
\

\
            MIT License
\

\
            Copyright (c) 2018 Henry Gruett (GitHub/@card100)
\

\
            Permission is hereby granted, free of charge, to any person obtaining a copy
\
            of this software and associated documentation files (the \"Software\"), to deal
\
            in the Software without restriction, including without limitation the rights
\
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\
            copies of the Software, and to permit persons to whom the Software is
\
            furnished to do so, subject to the following conditions:
\

\
            The above copyright notice and this permission notice shall be included in all
\
            copies or substantial portions of the Software.
\

\
            THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\
            SOFTWARE.\
              ";
          output(txt);
          break;
        case 'credits':
              output("TORMINAL

Created by:
Henry Gruett card100

Contributors:
Nanomotion, Sheshank Shankar GreenBayRules, Arav Narula, csf30816, Kerr Travers ktrvs
Notes:
torminal was built on top of Andrew M Barfield's HTML5 Web Terminal. It is released under a standard MIT license.
Math handled by math.js.  It is released under a Apache License 2.0 license.  No changes have been made to the API.");
              break;
        default:
          if (cmd) {
            output('' + cmd + ': command not found');
          }
      };

      window.scrollTo(0, getDocHeight_());
      this.value = ''; // Clear/setup line for next input.
    }
  }

  //
  function formatColumns_(entries) {
    var maxName = entries[0].name;
    util.toArray(entries).forEach(function(entry, i) {
      if (entry.name.length > maxName.length) {
        maxName = entry.name;
      }
    });

    var height = entries.length <= 3 ?
        'height: ' + (entries.length * 15) + 'px;' : '';

    // 12px monospace font yields ~7px screen width.
    var colWidth = maxName.length * 7;

    return ['
'];
  }

  //
  function output(html) {
    output_.insertAdjacentHTML('beforeEnd', '
' + html + '
');
    return(0);
  }

  // Cross-browser impl to get document's height.
  function getDocHeight_() {
    var d = document;
    return Math.max(
        Math.max(d.body.scrollHeight, d.documentElement.scrollHeight),
        Math.max(d.body.offsetHeight, d.documentElement.offsetHeight),
        Math.max(d.body.clientHeight, d.documentElement.clientHeight)
    );
  }

  //
  return {
    init: function() {
      output('
Torminal

' + new Date() + '

Enter "help" for more information.

(c) 2017 Henry Gruett Under MIT License. Type \'license\' for more info.');
    },
    output: output
  }
};
<|endoftext|>


<commit_before>Ui.LBox.extend('Ui.Draggable',
{
	/**
	 * Fires when object start to be dragged
	 * @name Ui.Draggable#dragstart
	 * @event
	 * @param {Ui.Draggable} draggable The draggable itself
	 */
	/**
	 * Fires when object stop to be dragged
	 * @name Ui.Draggable#dragend
	 * @event
	 * @param {Ui.Draggable} draggable The draggable itself
	 * @param {string} dropEffect Give the operation done: [none|copy|link|move]
	 */

	icon: undefined,
	downloadUrl: undefined,
	downloadMimetype: undefined,
	downloadFilename: undefined,
	allowedMode: 'copyMove',
	mimetype: undefined,
	data: undefined,
	lastPress: undefined,
	isDown: false,
	isDrag: false,
	timer: undefined,
	dragDelta: undefined,
	clock: undefined,
	screenX: undefined,
	screenY: undefined,
	lock: false,

	/**
	 * @constructs
	 * @class
	 * @extends Ui.LBox
	 */
	constructor: function(config) {
		this.addEvents('dragstart', 'dragend', 'press', 'activate', 'menu');

		this.getDrawing().style.cursor = 'pointer';

		this.setFocusable(true);

		this.connect(this.getDrawing(), 'dragstart', this.onDragStart, true);
		this.connect(this.getDrawing(), 'dragend', this.onDragEnd, true);

		this.connect(this.getDrawing(), 'localdragstart', this.onDragStart, true);
		this.connect(this.getDrawing(), 'localdragend', this.onDragEnd, true);

		this.connect(this.getDrawing(), 'mousedown', this.onMouseDown);
		this.connect(this.getDrawing(), 'fingerdown', this.onFingerDown);

		// handle keyboard
		this.connect(this.getDrawing(), 'keyup', this.onKeyUp);
	},

	setLock: function(lock) {
    	this.lock = lock;
	},

	getLock: function() {
		return this.lock;
	},

	/**
	 * Set the mimetype of the data
	 */
	setMimetype: function(mimetype) {
		if(mimetype === undefined)
			this.mimetype = 'application/era-framework';
		else
			this.mimetype = mimetype;
	},

	getMimetype: function() {
		return this.mimetype;
	},

	/**
	 * Set the data that we drag & drop
	 */
	setData: function(data) {
		this.data = data;
		if(typeof(this.data) === 'object') {
			if(this.mimetype === undefined) {
				if(this.data.classType !== undefined)
					this.mimetype = this.data.classType;
				else
					this.mimetype = 'object';
			}
		}
		// allow native drag & drop
		else
			this.getDrawing().setAttribute('draggable', true);
	},

	/**
	 * Set the allowed operation. Possible values are:
	 * [copy|copyLink|copyMove|link|linkMove|move|all]
	 */
	setAllowedMode: function(allowedMode) {
		this.allowedMode = allowedMode;
	},

	/**
	 * Provide an Ui.Image that will be used when
	 * dragging the element
	 * Supported by: Firefox, Chrome and Safari on Windows
	 */
	setIcon: function(icon) {
		this.icon = icon;
	},

	/**
	 * Provide an URL to download the associated file (if any)
	 * if the element is dropped on the desktop
	 * Supported by: Chrome only
	 */
	setDownloadUrl: function(url, mimetype, filename) {
		// TODO: if url is relative, make it absolute
		var uri = new Core.Uri({ uri: url });
		this.downloadUrl = uri.toString();
		// extract the fileName if not given
		//if(filename === undefined) {
			// TODO
		//}
		// guess the mimetype if not given
		//if(mimetype === undefined) {
			// TODO
		//}
	 	this.downloadMimetype = mimetype;
		this.downloadFilename = filename;
	},

	getDragDelta: function() {
		return this.dragDelta;
	},

	/**#@+
	 * @private
	 */

	onDragStart: function(event) {
		if(this.lock || this.getIsDisabled())
			return;
		if(!this.dragAllowed) {
			this.setTransform(new Ui.Matrix());
			if(this.clock !== undefined) {
				this.clock.stop();
				this.clock = undefined;
			}
			if(this.timer !== undefined) {
				this.timer.abort();
				this.timer = undefined;
			}
			event.stopPropagation();
			event.preventDefault();
			return;
		}

		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
			this.setTransform(new Ui.Matrix());
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}

		this.isDown = false;
		this.isDrag = true;
		this.dragDelta = this.pointFromWindow({ x: event.clientX, y: event.clientY });

		this.disconnect(window, 'mouseup', this.onMouseUp, true);

		event.stopPropagation();
		event.dataTransfer.effectAllowed = this.allowedMode;

		// if the element if downloadable to the destkop,
		// try to provide the link
		if(this.downloadUrl !== undefined) {
			try {
				event.dataTransfer.setData('DownloadURL', this.downloadMimetype+':'+this.downloadFilename+':'+this.downloadUrl);
			} catch(e) {}
		}

		// use Text as data because it is the only thing
		// that works cross browser. Only Firefox support different mimetypes
		//event.dataTransfer.setData('Text', this.mimetype+':'+this.dragDelta.x+':'+this.dragDelta.y+':'+this.data);
		event.dataTransfer.setData(this.mimetype, this.data);

		this.fireEvent('dragstart', this);

		if(this.icon !== undefined) {
			// TODO: improve this
			if(event.dataTransfer.setDragImage !== undefined)
				event.dataTransfer.setDragImage(this.icon.drawing.childNodes[0], 0, 0);
		}
		return false;
	},

	onDragEnd: function(event) {
		this.isDrag = false;
		this.isDown = false;

		event.stopPropagation();
		// dropEffect give the operation done: [none|copy|link|move]
		this.fireEvent('dragend', this, event.dataTransfer.dropEffect);
	},

	onMouseDown: function(event) {
		if(this.lock || this.isDown || (event.button != 0) || this.getIsDisabled())
			return;
		this.isDown = true;
		this.dragAllowed = false;
		this.setTransform(new Ui.Matrix());
		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}
		this.timer = new Core.DelayedTask({ scope: this, delay: 0.5, callback: this.onTimer });

		this.screenX = event.screenX;
		this.screenY = event.screenY;

		this.connect(window, 'mousemove', this.onMouseMove, true);
		this.connect(window, 'mouseup', this.onMouseUp, true);

		event.stopPropagation();
		if((!navigator.supportDrag || (typeof(this.data) === 'object')) && (event.button == 0))
			new Core.DragDataTransfer({ local: (typeof(this.data) === 'object'), draggable: this.getDrawing(), x: event.clientX, y: event.clientY, event: event, mouse: true });
	},

	onMouseMove: function(event) {
		var deltaX = event.screenX - this.screenX;
		var deltaY = event.screenY - this.screenY;
		var delta = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

		event.preventDefault();
		event.stopPropagation();

		// if the user move to much, release the touch event
		if(delta > 10) {
			this.disconnect(window, 'mousemove', this.onMouseMove, true);
			this.disconnect(window, 'mouseup', this.onMouseUp, true);

			this.isDrag = false;
			this.isDown = false;
			this.dragAllowed = false;
			this.setTransform(new Ui.Matrix());
			if(this.clock !== undefined) {
				this.clock.stop();
				this.clock = undefined;
			}
			if(this.timer !== undefined) {
				this.timer.abort();
				this.timer = undefined;
			}

			var mouseDownEvent = document.createEvent('MouseEvents');
			mouseDownEvent.initMouseEvent('mousedown', true, true, window, 1, event.screenX, event.screenY,
				event.clientX, event.clientY,
				event.ctrlKey, event.altKey, event.shiftKey,
				event.metaKey, 0, event.target);
			this.getDrawing().offsetParent.dispatchEvent(mouseDownEvent);
		}
	},

	onMouseUp: function(event) {
		this.disconnect(window, 'mousemove', this.onMouseMove, true);
		this.disconnect(window, 'mouseup', this.onMouseUp, true);

		this.isDown = false;
		this.dragAllowed = false;
		this.setTransform(new Ui.Matrix());
		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}

		if(!this.isDrag) {
			this.isDrag = false;
			var currentTime = (new Date().getTime())/1000;
			if((this.lastPress !== undefined) && ((currentTime - this.lastPress) < 0.5)) {
				this.fireEvent('activate', this);
			}
			else {
				this.fireEvent('press', this);
			}
			this.lastPress = currentTime;
			this.focus();
		}
		this.isDrag = false;
	},

	onFingerDown: function(event) {
		if(this.lock || this.isDown || this.getIsDisabled())
			return;
		this.connect(event.finger, 'fingermove', this.onFingerMove);
		this.connect(event.finger, 'fingerup', this.onFingerUp);
		event.finger.capture(this.getDrawing());

		event.preventDefault();
		event.stopPropagation();

		this.screenX = event.finger.getX();
		this.screenY = event.finger.getY();

		this.isDown = true;
		this.dragAllowed = false;
		this.setTransform(new Ui.Matrix());
		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}
		this.timer = new Core.DelayedTask({ scope: this, delay: 0.5, callback: this.onTimer });
	},

	onFingerMove: function(event) {
		event.preventDefault();
		event.stopPropagation();

		var deltaX = event.finger.getX() - this.screenX;
		var deltaY = event.finger.getY() - this.screenY;
		var delta = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

		// if the user move to much, release the touch event
		if(delta > 20) {
			this.setTransform(new Ui.Matrix());
			if(this.clock !== undefined) {
				this.clock.stop();
				this.clock = undefined;
			}
			if(this.timer !== undefined) {
				this.timer.abort();
				this.timer = undefined;
			}

			this.disconnect(event.finger, 'fingermove', this.onFingerMove);
			this.disconnect(event.finger, 'fingerup', this.onFingerUp);

			if(this.dragAllowed) {
				if(navigator.supportDrag)
					event.finger.release();
				else
					new Core.DragDataTransfer({ draggable: this.getDrawing(), x: event.finger.getX(), y: event.finger.getY(), event: event, finger: event.finger });
			}
			else {
				event.finger.release();
			}
			this.dragAllowed = false;
			this.isDown = false;
		}
	},

	onFingerUp: function(event) {
		event.preventDefault();
		event.stopPropagation();

		this.disconnect(event.finger, 'fingermove', this.onFingerMove);
		this.disconnect(event.finger, 'fingerup', this.onFingerUp);

		this.dragAllowed = false;
		this.isDown = false;
		this.setTransform(new Ui.Matrix());
		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}

		if(!this.isDrag) {
			this.isDrag = false;
			var currentTime = (new Date().getTime())/1000;
			if((this.lastPress !== undefined) && ((currentTime - this.lastPress) < 0.5)) {
				this.fireEvent('activate', this);
			}
			else {
				this.fireEvent('press', this);
			}
			this.lastPress = currentTime;
			this.focus();
		}
		this.isDrag = false;
	},

	onTimer: function() {
		this.timer = undefined;

		this.isDrag = true;
		this.dragAllowed = true;
		this.disconnect(window, 'mousemove', this.onMouseMove, true);

		this.clock = new Anim.Clock({ duration: 'forever' });
		this.connect(this.clock, 'timeupdate', this.onAnim);
		this.clock.begin();
	},

	onKeyUp: function(event) {
		var key = event.which;
		if((key == 13) && !this.getIsDisabled() && !this.lock) {
			event.preventDefault();
			event.stopPropagation();
			this.fireEvent('press', this);
		}
	},

	onAnim: function(clock) {
		var progress = (clock.getGlobalTime() % 0.8) / 0.8;
		var ease = new Anim.ElasticEase({ mode: 'inout' });
		progress = ease.ease(progress);

		var scale = 1 + (progress/12);
		this.setTransform(Ui.Matrix.createScale(scale, scale));
	}
});

<commit_msg>provide the "dragDirection" to allow quick drag and drop without waiting for long press but only in a given orientation [horizontal|vertical]<commit_after>Ui.LBox.extend('Ui.Draggable',
{
	/**
	 * Fires when object start to be dragged
	 * @name Ui.Draggable#dragstart
	 * @event
	 * @param {Ui.Draggable} draggable The draggable itself
	 */
	/**
	 * Fires when object stop to be dragged
	 * @name Ui.Draggable#dragend
	 * @event
	 * @param {Ui.Draggable} draggable The draggable itself
	 * @param {string} dropEffect Give the operation done: [none|copy|link|move]
	 */

	icon: undefined,
	downloadUrl: undefined,
	downloadMimetype: undefined,
	downloadFilename: undefined,
	allowedMode: 'copyMove',
	mimetype: undefined,
	data: undefined,
	lastPress: undefined,
	isDown: false,
	isDrag: false,
	timer: undefined,
	dragDelta: undefined,
	clock: undefined,
	screenX: undefined,
	screenY: undefined,
	lock: false,
	directionDrag: undefined,

	/**
	 * @constructs
	 * @class
	 * @extends Ui.LBox
	 */
	constructor: function(config) {
		this.addEvents('dragstart', 'dragend', 'press', 'activate', 'menu');

		this.getDrawing().style.cursor = 'pointer';

		this.setFocusable(true);

		this.connect(this.getDrawing(), 'dragstart', this.onDragStart, true);
		this.connect(this.getDrawing(), 'dragend', this.onDragEnd, true);

		this.connect(this.getDrawing(), 'localdragstart', this.onDragStart, true);
		this.connect(this.getDrawing(), 'localdragend', this.onDragEnd, true);

		this.connect(this.getDrawing(), 'mousedown', this.onMouseDown);
		this.connect(this.getDrawing(), 'fingerdown', this.onFingerDown);

		// handle keyboard
		this.connect(this.getDrawing(), 'keyup', this.onKeyUp);
	},

	/**
	 * If direction drag is set, allow a drag before the long press
	 * but only in the given direction. Possible values are:
	 * horizontal, vertical
	 */
	setDirectionDrag: function(direction) {
		this.directionDrag = direction;
	},

	setLock: function(lock) {
    	this.lock = lock;
	},

	getLock: function() {
		return this.lock;
	},

	/**
	 * Set the mimetype of the data
	 */
	setMimetype: function(mimetype) {
		if(mimetype === undefined)
			this.mimetype = 'application/era-framework';
		else
			this.mimetype = mimetype;
	},

	getMimetype: function() {
		return this.mimetype;
	},

	/**
	 * Set the data that we drag & drop
	 */
	setData: function(data) {
		this.data = data;
		if(typeof(this.data) === 'object') {
			if(this.mimetype === undefined) {
				if(this.data.classType !== undefined)
					this.mimetype = this.data.classType;
				else
					this.mimetype = 'object';
			}
		}
		// allow native drag & drop
		else
			this.getDrawing().setAttribute('draggable', true);
	},

	/**
	 * Set the allowed operation. Possible values are:
	 * [copy|copyLink|copyMove|link|linkMove|move|all]
	 */
	setAllowedMode: function(allowedMode) {
		this.allowedMode = allowedMode;
	},

	/**
	 * Provide an Ui.Image that will be used when
	 * dragging the element
	 * Supported by: Firefox, Chrome and Safari on Windows
	 */
	setIcon: function(icon) {
		this.icon = icon;
	},

	/**
	 * Provide an URL to download the associated file (if any)
	 * if the element is dropped on the desktop
	 * Supported by: Chrome only
	 */
	setDownloadUrl: function(url, mimetype, filename) {
		// TODO: if url is relative, make it absolute
		var uri = new Core.Uri({ uri: url });
		this.downloadUrl = uri.toString();
		// extract the fileName if not given
		//if(filename === undefined) {
			// TODO
		//}
		// guess the mimetype if not given
		//if(mimetype === undefined) {
			// TODO
		//}
	 	this.downloadMimetype = mimetype;
		this.downloadFilename = filename;
	},

	getDragDelta: function() {
		return this.dragDelta;
	},

	/**#@+
	 * @private
	 */

	onDragStart: function(event) {
		if(this.lock || this.getIsDisabled())
			return;
		if(!this.dragAllowed) {
			this.setTransform(new Ui.Matrix());
			if(this.clock !== undefined) {
				this.clock.stop();
				this.clock = undefined;
			}
			if(this.timer !== undefined) {
				this.timer.abort();
				this.timer = undefined;
			}
			event.stopPropagation();
			event.preventDefault();
			return;
		}

		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
			this.setTransform(new Ui.Matrix());
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}

		this.isDown = false;
		this.isDrag = true;
		this.dragDelta = this.pointFromWindow({ x: event.clientX, y: event.clientY });

		this.disconnect(window, 'mouseup', this.onMouseUp, true);

		event.stopPropagation();
		event.dataTransfer.effectAllowed = this.allowedMode;

		// if the element if downloadable to the destkop,
		// try to provide the link
		if(this.downloadUrl !== undefined) {
			try {
				event.dataTransfer.setData('DownloadURL', this.downloadMimetype+':'+this.downloadFilename+':'+this.downloadUrl);
			} catch(e) {}
		}

		// use Text as data because it is the only thing
		// that works cross browser. Only Firefox support different mimetypes
		//event.dataTransfer.setData('Text', this.mimetype+':'+this.dragDelta.x+':'+this.dragDelta.y+':'+this.data);
		event.dataTransfer.setData(this.mimetype, this.data);

		this.fireEvent('dragstart', this);

		if(this.icon !== undefined) {
			// TODO: improve this
			if(event.dataTransfer.setDragImage !== undefined)
				event.dataTransfer.setDragImage(this.icon.drawing.childNodes[0], 0, 0);
		}
		return false;
	},

	onDragEnd: function(event) {
		this.isDrag = false;
		this.isDown = false;

		event.stopPropagation();
		// dropEffect give the operation done: [none|copy|link|move]
		this.fireEvent('dragend', this, event.dataTransfer.dropEffect);
	},

	onMouseDown: function(event) {
		if(this.lock || this.isDown || (event.button != 0) || this.getIsDisabled())
			return;
		this.isDown = true;
		this.dragAllowed = false;
		this.setTransform(new Ui.Matrix());
		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}
		this.timer = new Core.DelayedTask({ scope: this, delay: 0.5, callback: this.onTimer });

		this.screenX = event.screenX;
		this.screenY = event.screenY;

		this.connect(window, 'mousemove', this.onMouseMove, true);
		this.connect(window, 'mouseup', this.onMouseUp, true);

		event.stopPropagation();
		if((!navigator.supportDrag || (typeof(this.data) === 'object')) && (event.button == 0))
			new Core.DragDataTransfer({ local: (typeof(this.data) === 'object'), draggable: this.getDrawing(), x: event.clientX, y: event.clientY, event: event, mouse: true });
	},

	onMouseMove: function(event) {
		var deltaX = event.screenX - this.screenX;
		var deltaY = event.screenY - this.screenY;
		var delta = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

		event.preventDefault();
		event.stopPropagation();

		// if the user move to much, release the touch event
		if(delta > 10) {
			this.disconnect(window, 'mousemove', this.onMouseMove, true);
			this.disconnect(window, 'mouseup', this.onMouseUp, true);

			this.isDrag = false;
			this.isDown = false;
			this.dragAllowed = false;
			this.setTransform(new Ui.Matrix());
			if(this.clock !== undefined) {
				this.clock.stop();
				this.clock = undefined;
			}
			if(this.timer !== undefined) {
				this.timer.abort();
				this.timer = undefined;
			}

			// allow fast drag when directionDrag is set
			if((this.directionDrag !== undefined) && (((this.directionDrag === 'horizontal') && (Math.abs(deltaX) > Math.abs(deltaY))) ||
			   ((this.directionDrag === 'vertical') && (Math.abs(deltaY) > Math.abs(deltaX))))) {
				this.isDrag = true;
				this.dragAllowed = true;
			}
			else {
				var mouseDownEvent = document.createEvent('MouseEvents');
				mouseDownEvent.initMouseEvent('mousedown', true, true, window, 1, event.screenX, event.screenY,
					event.clientX, event.clientY,
					event.ctrlKey, event.altKey, event.shiftKey,
					event.metaKey, 0, event.target);
				this.getDrawing().offsetParent.dispatchEvent(mouseDownEvent);
			}
		}
	},

	onMouseUp: function(event) {
		this.disconnect(window, 'mousemove', this.onMouseMove, true);
		this.disconnect(window, 'mouseup', this.onMouseUp, true);

		this.isDown = false;
		this.dragAllowed = false;
		this.setTransform(new Ui.Matrix());
		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}

		if(!this.isDrag) {
			this.isDrag = false;
			var currentTime = (new Date().getTime())/1000;
			if((this.lastPress !== undefined) && ((currentTime - this.lastPress) < 0.5)) {
				this.fireEvent('activate', this);
			}
			else {
				this.fireEvent('press', this);
			}
			this.lastPress = currentTime;
			this.focus();
		}
		this.isDrag = false;
	},

	onFingerDown: function(event) {
		if(this.lock || this.isDown || this.getIsDisabled())
			return;
		this.connect(event.finger, 'fingermove', this.onFingerMove);
		this.connect(event.finger, 'fingerup', this.onFingerUp);
		event.finger.capture(this.getDrawing());

		event.preventDefault();
		event.stopPropagation();

		this.screenX = event.finger.getX();
		this.screenY = event.finger.getY();

		this.isDown = true;
		this.dragAllowed = false;
		this.setTransform(new Ui.Matrix());
		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}
		this.timer = new Core.DelayedTask({ scope: this, delay: 0.5, callback: this.onTimer });
	},

	onFingerMove: function(event) {
		var deltaX = event.finger.getX() - this.screenX;
		var deltaY = event.finger.getY() - this.screenY;
		var delta = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

		event.preventDefault();
		event.stopPropagation();

		// if the user move to much, release the touch event
		if(delta > 20) {
			this.setTransform(new Ui.Matrix());
			if(this.clock !== undefined) {
				this.clock.stop();
				this.clock = undefined;
			}
			if(this.timer !== undefined) {
				this.timer.abort();
				this.timer = undefined;
			}

			this.disconnect(event.finger, 'fingermove', this.onFingerMove);
			this.disconnect(event.finger, 'fingerup', this.onFingerUp);

			// allow fast drag when directionDrag is set
			if((this.directionDrag !== undefined) && (((this.directionDrag === 'horizontal') && (Math.abs(deltaX) > Math.abs(deltaY))) ||
			   	((this.directionDrag === 'vertical') && (Math.abs(deltaY) > Math.abs(deltaX))))) {
				this.isDrag = true;
				this.dragAllowed = true;
			}

			if(this.dragAllowed) {
				if(navigator.supportDrag)
					event.finger.release();
				else
					new Core.DragDataTransfer({ draggable: this.getDrawing(), x: event.finger.getX(), y: event.finger.getY(), event: event, finger: event.finger });
			}
			else {
				event.finger.release();
			}
			this.dragAllowed = false;
			this.isDown = false;
		}
	},

	onFingerUp: function(event) {
		event.preventDefault();
		event.stopPropagation();

		this.disconnect(event.finger, 'fingermove', this.onFingerMove);
		this.disconnect(event.finger, 'fingerup', this.onFingerUp);

		this.dragAllowed = false;
		this.isDown = false;
		this.setTransform(new Ui.Matrix());
		if(this.clock !== undefined) {
			this.clock.stop();
			this.clock = undefined;
		}
		if(this.timer !== undefined) {
			this.timer.abort();
			this.timer = undefined;
		}

		if(!this.isDrag) {
			this.isDrag = false;
			var currentTime = (new Date().getTime())/1000;
			if((this.lastPress !== undefined) && ((currentTime - this.lastPress) < 0.5)) {
				this.fireEvent('activate', this);
			}
			else {
				this.fireEvent('press', this);
			}
			this.lastPress = currentTime;
			this.focus();
		}
		this.isDrag = false;
	},

	onTimer: function() {
		this.timer = undefined;

		this.isDrag = true;
		this.dragAllowed = true;
		this.disconnect(window, 'mousemove', this.onMouseMove, true);

		this.clock = new Anim.Clock({ duration: 'forever' });
		this.connect(this.clock, 'timeupdate', this.onAnim);
		this.clock.begin();
	},

	onKeyUp: function(event) {
		var key = event.which;
		if((key == 13) && !this.getIsDisabled() && !this.lock) {
			event.preventDefault();
			event.stopPropagation();
			this.fireEvent('press', this);
		}
	},

	onAnim: function(clock) {
		var progress = (clock.getGlobalTime() % 0.8) / 0.8;
		var ease = new Anim.ElasticEase({ mode: 'inout' });
		progress = ease.ease(progress);

		var scale = 1 + (progress/12);
		this.setTransform(Ui.Matrix.createScale(scale, scale));
	}
});

<|endoftext|>


<commit_before>/**
 * Globale Felder
 */
var infoPanelDistrictName = document.getElementById('extended-tooltip-district-name'),
    infoPanel = document.getElementById('extended-tooltip'),
    extendedTooltipDetailDistrictInfo = document.getElementById('extended-tooltip-detail-district-info');
    lastSelectedConstituencyNumber = null;

/**
 * Globale Variabeln
 */
var lastSelectetDistrictName = '',
    lastSelectetDistrictId = null;

/**
 * Wird aufgerufen wenn der User auf eine Region klickt
 * @param featureData das aktuelle "feature"
 */
function selectDistrict(featureData) {

    var props = featureData.properties;

    // Karte Reference setzten wenn nicht vorhanden
    if(elemSvg === null){
        getSVGMap();
    } // end if

    if(lastSelectetDistrictId !== props.stadtteilnummer){

        if(lastSelectetDistrictId !== null) {
            // Letzer Stadtteil wieder zurück setzen
            elemSvg.getElementById(lastSelectetDistrictId).style.fill = '#fff';
        } // end if

        // Neuer Stadtteil färben
        elemSvg.getElementById(props.stadtteilnummer).style.fill = '#bbe3fa';

        // letzte ausgewählter Stadtteil speichern
        lastSelectetDistrictId = props.stadtteilnummer;

    } // end if

    // In das HTML schreiben
    infoPanelDistrictName.innerHTML = currentConstituencyObject.properties.wahlbezirksname+" (" + props.stadtteilname + ")";

    // Hat sich der Wahlbezirk begeändert?
    if(lastSelectedConstituencyNumber !== currentConstituencyObject.properties.wahlbezirksnummer){

        if(lastSelectedConstituencyNumber !== null) {
            elemSvg.getElementById(lastSelectedConstituencyNumber).style.fill = '#fff';
        } // end if

        lastSelectedConstituencyNumber = currentConstituencyObject.properties.wahlbezirksnummer;
        elemSvg.getElementById(lastSelectedConstituencyNumber).style.fill = '#57bdeb';
    } // end if

    // Info vom aktullen ausgewählen Wahlbezirk weiter an das ExtendedToolTip geben.
    // currentConstituencyObject wird in der Funktion onMouseOverWahlbezirk gefüllt.

    addDetailDistrictInfo(currentConstituencyObject);
    infoPanel.classList.add('isOpen');
} // end function

/**
 * Schließt das Infopanel
 */
function closeInfoPanel() {

    if(lastSelectetDistrictId !== null) {
        // Letzer Stadtteil wieder zurück setzen
        elemSvg.getElementById(lastSelectetDistrictId).style.fill = '#fff';
    } // end if

    lastSelectetDistrictId = null;
    infoPanel.classList.remove('isOpen');
} // end function

/**
 * Fügt die Detalierte Wahlinfo hinzu
 *
 * @param districtInfo {object}
 */
function addDetailDistrictInfo(districtInfo) {

    var template = 'Zweitstimmen (Parteien)' +
        '
' +
        '
' +
        '<colgroup>' +
        '   <col style="width: 100px">' +
        '   <col style="width: 25px">' +
        '   <col style="width: 60px">' +
        '</colgroup>';

    // Verhältnis ermitteln
    for(var index in districtInfo.properties.btw2013.zweitstimme){

        var partyItem = PARTY[(districtInfo.properties.btw2013.zweitstimme[index].partei).toUpperCase()];

        if( typeof partyItem === 'undefined'){
            partyItem = {
                color: '#808080'
            }
        } // end if

        template += '
';
        //template += '

';
        template += ''+districtInfo.properties.btw2013.zweitstimme[index].partei+'	';
        template += ''+((100 * districtInfo.properties.btw2013.zweitstimme[index].stimmen) / districtInfo.sumDistrict).toFixed(1)+'%	';
        template += ''+districtInfo.properties.btw2013.zweitstimme[index].stimmen+' Stimmen	';

        template += '
';

    } // end for

    template += '
';

    extendedTooltipDetailDistrictInfo.innerHTML = template;
} // end function<commit_msg>Erstimme in das ExtendedToolTip hinzugefügt<commit_after>/**
 * Globale Felder
 */
var infoPanelDistrictName = document.getElementById('extended-tooltip-district-name'),
    infoPanel = document.getElementById('extended-tooltip'),
    extendedTooltipDetailDistrictInfo = document.getElementById('extended-tooltip-detail-district-info');
    lastSelectedConstituencyNumber = null;

/**
 * Globale Variabeln
 */
var lastSelectetDistrictName = '',
    lastSelectetDistrictId = null;

/**
 * Wird aufgerufen wenn der User auf eine Region klickt
 * @param featureData das aktuelle "feature"
 */
function selectDistrict(featureData) {

    var props = featureData.properties;

    // Karte Reference setzten wenn nicht vorhanden
    if(elemSvg === null){
        getSVGMap();
    } // end if

    if(lastSelectetDistrictId !== props.stadtteilnummer){

        if(lastSelectetDistrictId !== null) {
            // Letzer Stadtteil wieder zurück setzen
            elemSvg.getElementById(lastSelectetDistrictId).style.fill = '#fff';
        } // end if

        // Neuer Stadtteil färben
        elemSvg.getElementById(props.stadtteilnummer).style.fill = '#bbe3fa';

        // letzte ausgewählter Stadtteil speichern
        lastSelectetDistrictId = props.stadtteilnummer;

    } // end if

    // In das HTML schreiben
    infoPanelDistrictName.innerHTML = currentConstituencyObject.properties.wahlbezirksname+" (" + props.stadtteilname + ")";

    // Hat sich der Wahlbezirk begeändert?
    if(lastSelectedConstituencyNumber !== currentConstituencyObject.properties.wahlbezirksnummer){

        if(lastSelectedConstituencyNumber !== null) {
            elemSvg.getElementById(lastSelectedConstituencyNumber).style.fill = '#fff';
        } // end if

        lastSelectedConstituencyNumber = currentConstituencyObject.properties.wahlbezirksnummer;
        elemSvg.getElementById(lastSelectedConstituencyNumber).style.fill = '#57bdeb';
    } // end if

    // Info vom aktullen ausgewählen Wahlbezirk weiter an das ExtendedToolTip geben.
    // currentConstituencyObject wird in der Funktion onMouseOverWahlbezirk gefüllt.

    addDetailDistrictInfo(currentConstituencyObject);
    infoPanel.classList.add('isOpen');
} // end function

/**
 * Schließt das Infopanel
 */
function closeInfoPanel() {

    if(lastSelectetDistrictId !== null) {
        // Letzer Stadtteil wieder zurück setzen
        elemSvg.getElementById(lastSelectetDistrictId).style.fill = '#fff';
    } // end if

    lastSelectetDistrictId = null;
    infoPanel.classList.remove('isOpen');
} // end function

/**
 * Fügt die Detalierte Wahlinfo hinzu
 *
 * @param districtInfo {object}
 */
function addDetailDistrictInfo(districtInfo) {

    console.log(districtInfo);
    var template = 'Zweitstimmen (Parteien)' +
        '
' +
        '
' +
        '<colgroup>' +
        '   <col style="width: 100px">' +
        '   <col style="width: 25px">' +
        '   <col style="width: 60px">' +
        '</colgroup>';

    // Verhältnis ermitteln
    for(var index in districtInfo.properties.btw2013.zweitstimme){

        var partyItem = PARTY[(districtInfo.properties.btw2013.zweitstimme[index].partei).toUpperCase()];

        if( typeof partyItem === 'undefined'){
            partyItem = {
                color: '#808080'
            }
        } // end if

        template += '
';
        //template += '

';
        template += ''+districtInfo.properties.btw2013.zweitstimme[index].partei+'	';
        template += ''+((100 * districtInfo.properties.btw2013.zweitstimme[index].stimmen) / districtInfo.sumDistrict).toFixed(1)+'%	';
        template += ''+districtInfo.properties.btw2013.zweitstimme[index].stimmen+' Stimmen	';

        template += '
';

    } // end for

    template += '
';
    template += '
';

    template += '
';

    template += 'Erststimmen (Kandidaten)' +
        '
' +
        '
' +
        '<colgroup>' +
        '   <col style="width: 100px">' +
        '   <col style="width: 25px">' +
        '   <col style="width: 60px">' +
        '</colgroup>';

    // Verhältnis ermitteln
    for(var index in districtInfo.properties.btw2013.erststimme){

        var partyItem = PARTY[(districtInfo.properties.btw2013.erststimme[index].partei).toUpperCase()];

        if( typeof partyItem === 'undefined'){
            partyItem = {
                color: '#808080'
            }
        } // end if

        template += '
';
        //template += '

';
        template += ''+districtInfo.properties.btw2013.erststimme[index].name+' ('+districtInfo.properties.btw2013.erststimme[index].partei+')	';
        template += ''+((100 * districtInfo.properties.btw2013.erststimme[index].stimmen) / districtInfo.sumDistrict).toFixed(1)+'%	';
        template += ''+districtInfo.properties.btw2013.erststimme[index].stimmen+' Stimmen	';

        template += '
';

    } // end for

    template += '
';
    template += '
';

    extendedTooltipDetailDistrictInfo.innerHTML = template;
} // end function<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'EnabledAwareDAO',
  extends: 'foam.dao.ProxyDAO',

  documentation: 'DAO that filters out disabled entries',

  methods: [
    {
      name: 'find_',
      code: function(x, obj) {
        return this.delegate.find_(x, obj).then(function(result) {
          return this.filter(x, result);
        }.bind(this));
      },
      javaCode: `
        return filter(x, getDelegate().find_(x, obj));
      `
    },
    {
      name: 'select_',
      code: function(x, sink, skip, limit, order, predicate) {

      },
      javaCode: `
      public Sink select_(X x, Sink sink, long skip, long limit, Comparator order, Pre
      `,
    },
    {
      name: 'enabled',
      code: function(x, obj) {
        if ( obj == null ||
             ( foam.nanos.auth.EnabledAware.isInstance(obj) &&
               ! ((foam.nanos.auth.EnabledAware)obj).isEnabled() ) ) {
          return false;
        }
        return true;
      },
      javaReturns: 'Boolean',
      javaCode: `
        Object result = getDelegate().find_(x, obj);
        if ( result == null ||
             ( result instanceof EnabledAware &&
             ! ((EnabledAware)result).isEnabled() ) ) {
          return false;
        }
        return true;
      `
    }
    {
      name: 'filter',
      code: function(x, obj, enabled) {
        return enabled ? obj : null;
      },
      args: ,
      javaReturns: 'Object',
      javaCode: `
        return enabled ? obj : null;
      `
    }
  ]
});
<commit_msg>Accidentally commited a WIP file<commit_after><|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.crunch',
  name: 'CrunchController',
  documentation: `
    Defines behaviour for invocation of CRUNCH-related views.
  `,

  implements: [
    'foam.mlang.Expressions'
  ],

  imports: [
    'capabilityDAO',
    'capabilityCategoryDAO',
    'crunchService',
    'ctrl',
    'prerequisiteCapabilityJunctionDAO',
    'stack',
    'subject',
    'userCapabilityJunctionDAO'
  ],

  requires: [
    'foam.log.LogLevel',
    'foam.nanos.crunch.AgentCapabilityJunction',
    'foam.nanos.crunch.UserCapabilityJunction',
    'foam.u2.crunch.wizardflow.ConfigureFlowAgent',
    'foam.u2.crunch.wizardflow.CapabilityAdaptAgent',
    'foam.u2.crunch.wizardflow.CheckPendingAgent',
    'foam.u2.crunch.wizardflow.LoadCapabilitiesAgent',
    'foam.u2.crunch.wizardflow.CreateWizardletsAgent',
    'foam.u2.crunch.wizardflow.FilterWizardletsAgent',
    'foam.u2.crunch.wizardflow.RequirementsPreviewAgent',
    'foam.u2.crunch.wizardflow.StepWizardAgent',
    'foam.u2.crunch.wizardflow.PutFinalJunctionsAgent',
    'foam.u2.crunch.wizardflow.TestAgent',
    'foam.u2.crunch.wizardflow.LoadTopConfig',
    'foam.u2.crunch.wizardflow.CapableDefaultConfigAgent',
    'foam.u2.crunch.wizardflow.CapableCreateWizardletsAgent',
    'foam.u2.crunch.wizardflow.MaybeDAOPutAgent',
    'foam.util.async.Sequence',
    'foam.u2.borders.MarginBorder',
    'foam.u2.crunch.CapabilityInterceptView',
    'foam.u2.dialog.Popup'
  ],

  properties: [
    {
      name: 'activeIntercepts',
      class: 'Array',
      documentation: `
        Since permissions may be checked during asynchronous calls,
        it is possible that the same intercept view will be requested
        twice in a short period of time. Keeping a map of active
        intercept views is done to prevent two intercept views being
        open for the same permission (as this would be confusing for
        the user if they happen to choose the "cancel" option).

        This also allows a single intercept view to activate the
        message retry for multiple permissioned calls made
        asynchronously.
      `
    },
    {
      class: 'Map',
      name: 'capabilityCache',
      factory: function() {
        return new Map();
      }
    },
  ],

  methods: [
    function createWizardSequence(capabilityOrId, x) {
      if ( ! x ) x = this.__subContext__;
      return this.Sequence.create(null, x.createSubContext({
        rootCapability: capabilityOrId
      }))
        .add(this.ConfigureFlowAgent)
        .add(this.CapabilityAdaptAgent)
        .add(this.LoadCapabilitiesAgent)
        .add(this.CheckPendingAgent)
        .add(this.CreateWizardletsAgent)
        .add(this.FilterWizardletsAgent)
        .add(this.RequirementsPreviewAgent)
        .add(this.LoadTopConfig)
        .add(this.StepWizardAgent)
        .add(this.PutFinalJunctionsAgent)
        // .add(this.TestAgent)
        ;
    },

    // Excludes UCJ-related logic
    function createCapableWizardSequence(intercept, capable) {
      return this.Sequence.create(null, this.__subContext__.createSubContext({
        intercept: intercept,
        capable: capable
      }))
        .add(this.ConfigureFlowAgent)
        .add(this.CapableDefaultConfigAgent)
        .add(this.CapableCreateWizardletsAgent)
        .add(this.StepWizardAgent)
        .add(this.MaybeDAOPutAgent)
        ;
    },

    function handleIntercept(intercept) {
      var self = this;

      intercept.capabilityOptions.forEach((c) => {
        self.capabilityCache.set(c, false);
      });

      // Allow zero or more promises to block this method
      let p = Promise.resolve();

      // TODO: investigate why this is sometimes inconsistent
      if (
        intercept.capabilityOptions.length == 0 &&
        intercept.capableRequirements.length > 0 &&
        intercept.capableRequirements[0].userCapabilityRequirements.length > 0
      ) {
        intercept.capabilityOptions =
          intercept.capableRequirements[0].userCapabilityRequirements;
      }

      // Intercept view for regular user capability options
      console.log('intercept', intercept)
      if ( intercept.capabilityOptions.length > 1 ) {
        p = p.then(() => {
          return self.maybeLaunchInterceptView(intercept);
        });
      }
      else if ( intercept.capabilityOptions.length > 0 ) {
        p = p.then(() => {
          return self.createWizardSequence(intercept.capabilityOptions[0])
            .execute();
        });
      }

      let isCapable = intercept.capableRequirements.length > 0;

      // Wizard for Capable objects and required user capabilities
      // (note: no intercept view; this case immediately invokes a wizard)
      if ( isCapable ) {
        p = p.then(x => {
          if ( ! x || x.submitted ) {
            return self.launchCapableWizard(intercept);
          }
          return x;
        });
      }

      p = p.then(x => {
        var isCompleted = x.submitted;

        if ( isCapable ) {
          intercept.capableRequirements[0].isWizardCompleted = isCompleted;
          if ( ! isCompleted ) {
            intercept.resolve(intercept.capableRequirements[0]);
            return;
          }
          intercept.returnCapable.isWizardCompleted = isCompleted;
          intercept.resolve(intercept.returnCapable);
          return;
        }
        intercept.resend();
      })

      p.catch(err => {
        intercept.reject(err.data);
      })

      return p;
    },

    function maybeLaunchInterceptView(intercept) {
      // Clear stale intercepts (ones which have been closed already)
      this.activeIntercepts = this.activeIntercepts.filter((ic) => {
        return ( ! ic.aquired ) && ( ! ic.cancelled );
      });
      // Try to find a matching intercept view that's already opened.
      // NP-1426 explains this is greater detail.
      for ( let i = 0 ; i < this.activeIntercepts.length ; i++ ) {
        let activeIntercept = this.activeIntercepts[i];
        let hasAllOptions = true;

        // All options in the active intercept need to satisfy the
        // incoming intercept for this to be a match.
        activeIntercept.capabilityOptions.forEach((capOpt) => {
          if ( ! intercept.capabilityOptions.includes(capOpt) ) {
            hasAllOptions = false;
          }
        });
        if ( hasAllOptions ) {
          return activeIntercept.promise;
        }
      }
      // Register intercept for later occurances of the check above
      this.activeIntercepts.push(intercept);

      // Pop up the popup
      return new Promise((resolve, _) => {
        this.ctrl.add(this.Popup.create({ closeable: false })
            .tag(this.CapabilityInterceptView, {
              data: intercept,
              onClose: (x) => {
                x.closeDialog();
                resolve(x);
              }
            })
        );
      });
    },

    function save(wizardlet) {
      if ( ! wizardlet.isAvailable ) return Promise.resolve();
      var isAssociation = wizardlet.capability.associatedEntity === foam.nanos.crunch.AssociatedEntity.ACTING_USER;
      var associatedEntity = isAssociation ? this.subject.realUser :
      wizardlet.capability.associatedEntity === foam.nanos.crunch.AssociatedEntity.USER ? this.subject.user : this.subject.realUser;

      return this.updateUCJ(wizardlet, associatedEntity).then(() => {
        var ucj = wizardlet.ucj;
        if ( ucj === null ) {
          ucj = isAssociation ?
          this.AgentCapabilityJunction.create({
              sourceId: associatedEntity.id,
              targetId: wizardlet.capability.id,
              effectiveUser: this.subject.user.id
            })
            : this.UserCapabilityJunction.create({
              sourceId: associatedEntity.id,
              targetId: wizardlet.capability.id
            })
        }
        if ( wizardlet.of ) ucj.data = wizardlet.data;
        return this.userCapabilityJunctionDAO.put(ucj);
      });
    },
    async function updateUCJ(wizardlet, associatedEntity) {
      return this.userCapabilityJunctionDAO.find(
        this.AND(
          this.OR(
            this.AND(
              this.NOT(this.INSTANCE_OF(this.AgentCapabilityJunction)),
              this.EQ(this.UserCapabilityJunction.SOURCE_ID, associatedEntity.id)
            ),
            this.AND(
              this.INSTANCE_OF(this.AgentCapabilityJunction),
              this.EQ(this.UserCapabilityJunction.SOURCE_ID, associatedEntity.id),
              this.EQ(this.AgentCapabilityJunction.EFFECTIVE_USER, this.subject.user.id)
            )
          ),
          this.EQ(this.UserCapabilityJunction.TARGET_ID, wizardlet.capability.id)
        )
      ).then(ucj => {
        wizardlet.ucj = ucj;
        return wizardlet;
      });
    },
    function purgeCachedCapabilityDAOs() {
      this.capabilityDAO.cmd_(this, foam.dao.CachingDAO.PURGE);
      this.capabilityDAO.cmd_(this, foam.dao.AbstractDAO.RESET_CMD);
      this.capabilityCategoryDAO.cmd_(this, foam.dao.CachingDAO.PURGE);
      this.capabilityCategoryDAO.cmd_(this, foam.dao.AbstractDAO.RESET_CMD);
      this.userCapabilityJunctionDAO.cmd_(this, foam.dao.CachingDAO.PURGE);
      this.userCapabilityJunctionDAO.cmd_(this, foam.dao.AbstractDAO.RESET_CMD);
    },

    // CRUNCH Lite Methods
    function launchCapableWizard(intercept) {
      var p = Promise.resolve(true);

      intercept.capableRequirements.forEach(capable => {
        var seq = this.createCapableWizardSequence(intercept, capable);
        p = p.then(() => {
          return seq.execute().then(x => {
            return x;
          });
        });
      })

      return p;
    },

    // This function is only called by CapableView
    function getWizardletsFromCapable(capable) {
      return this.Sequence.create(null, this.__subContext__.createSubContext({
        capable: capable
      })).add(this.CapableCreateWizardletsAgent).execute().then(x => x.wizardlets);
    }
  ]
});
<commit_msg>Revert adding granted UCJ capability to wizard<commit_after>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  package: 'foam.u2.crunch',
  name: 'CrunchController',
  documentation: `
    Defines behaviour for invocation of CRUNCH-related views.
  `,

  implements: [
    'foam.mlang.Expressions'
  ],

  imports: [
    'capabilityDAO',
    'capabilityCategoryDAO',
    'crunchService',
    'ctrl',
    'prerequisiteCapabilityJunctionDAO',
    'stack',
    'subject',
    'userCapabilityJunctionDAO'
  ],

  requires: [
    'foam.log.LogLevel',
    'foam.nanos.crunch.AgentCapabilityJunction',
    'foam.nanos.crunch.UserCapabilityJunction',
    'foam.u2.crunch.wizardflow.ConfigureFlowAgent',
    'foam.u2.crunch.wizardflow.CapabilityAdaptAgent',
    'foam.u2.crunch.wizardflow.CheckPendingAgent',
    'foam.u2.crunch.wizardflow.LoadCapabilitiesAgent',
    'foam.u2.crunch.wizardflow.CreateWizardletsAgent',
    'foam.u2.crunch.wizardflow.FilterWizardletsAgent',
    'foam.u2.crunch.wizardflow.RequirementsPreviewAgent',
    'foam.u2.crunch.wizardflow.StepWizardAgent',
    'foam.u2.crunch.wizardflow.PutFinalJunctionsAgent',
    'foam.u2.crunch.wizardflow.TestAgent',
    'foam.u2.crunch.wizardflow.LoadTopConfig',
    'foam.u2.crunch.wizardflow.CapableDefaultConfigAgent',
    'foam.u2.crunch.wizardflow.CapableCreateWizardletsAgent',
    'foam.u2.crunch.wizardflow.MaybeDAOPutAgent',
    'foam.util.async.Sequence',
    'foam.u2.borders.MarginBorder',
    'foam.u2.crunch.CapabilityInterceptView',
    'foam.u2.dialog.Popup'
  ],

  properties: [
    {
      name: 'activeIntercepts',
      class: 'Array',
      documentation: `
        Since permissions may be checked during asynchronous calls,
        it is possible that the same intercept view will be requested
        twice in a short period of time. Keeping a map of active
        intercept views is done to prevent two intercept views being
        open for the same permission (as this would be confusing for
        the user if they happen to choose the "cancel" option).

        This also allows a single intercept view to activate the
        message retry for multiple permissioned calls made
        asynchronously.
      `
    },
    {
      class: 'Map',
      name: 'capabilityCache',
      factory: function() {
        return new Map();
      }
    },
  ],

  methods: [
    function createWizardSequence(capabilityOrId, x) {
      if ( ! x ) x = this.__subContext__;
      return this.Sequence.create(null, x.createSubContext({
        rootCapability: capabilityOrId
      }))
        .add(this.ConfigureFlowAgent)
        .add(this.CapabilityAdaptAgent)
        .add(this.LoadCapabilitiesAgent)
        .add(this.CheckPendingAgent)
        .add(this.CreateWizardletsAgent)
        .add(this.FilterWizardletsAgent)
        .add(this.RequirementsPreviewAgent)
        .add(this.LoadTopConfig)
        .add(this.StepWizardAgent)
        .add(this.PutFinalJunctionsAgent)
        // .add(this.TestAgent)
        ;
    },

    // Excludes UCJ-related logic
    function createCapableWizardSequence(intercept, capable) {
      return this.Sequence.create(null, this.__subContext__.createSubContext({
        intercept: intercept,
        capable: capable
      }))
        .add(this.ConfigureFlowAgent)
        .add(this.CapableDefaultConfigAgent)
        .add(this.CapableCreateWizardletsAgent)
        .add(this.StepWizardAgent)
        .add(this.MaybeDAOPutAgent)
        ;
    },

    function handleIntercept(intercept) {
      var self = this;

      intercept.capabilityOptions.forEach((c) => {
        self.capabilityCache.set(c, false);
      });

      // Allow zero or more promises to block this method
      let p = Promise.resolve();

      // TODO: investigate why this is sometimes inconsistent
      // if (
      //   intercept.capabilityOptions.length == 0 &&
      //   intercept.capableRequirements.length > 0 &&
      //   intercept.capableRequirements[0].userCapabilityRequirements.length > 0
      // ) {
      //   intercept.capabilityOptions =
      //     intercept.capableRequirements[0].userCapabilityRequirements;
      // }

      // Intercept view for regular user capability options
      console.log('intercept', intercept)
      if ( intercept.capabilityOptions.length > 1 ) {
        p = p.then(() => {
          return self.maybeLaunchInterceptView(intercept);
        });
      }
      else if ( intercept.capabilityOptions.length > 0 ) {
        p = p.then(() => {
          return self.createWizardSequence(intercept.capabilityOptions[0])
            .execute();
        });
      }

      let isCapable = intercept.capableRequirements.length > 0;

      // Wizard for Capable objects and required user capabilities
      // (note: no intercept view; this case immediately invokes a wizard)
      if ( isCapable ) {
        p = p.then(x => {
          if ( ! x || x.submitted ) {
            return self.launchCapableWizard(intercept);
          }
          return x;
        });
      }

      p = p.then(x => {
        var isCompleted = x.submitted;

        if ( isCapable ) {
          intercept.capableRequirements[0].isWizardCompleted = isCompleted;
          if ( ! isCompleted ) {
            intercept.resolve(intercept.capableRequirements[0]);
            return;
          }
          intercept.returnCapable.isWizardCompleted = isCompleted;
          intercept.resolve(intercept.returnCapable);
          return;
        }
        intercept.resend();
      })

      p.catch(err => {
        intercept.reject(err.data);
      })

      return p;
    },

    function maybeLaunchInterceptView(intercept) {
      // Clear stale intercepts (ones which have been closed already)
      this.activeIntercepts = this.activeIntercepts.filter((ic) => {
        return ( ! ic.aquired ) && ( ! ic.cancelled );
      });
      // Try to find a matching intercept view that's already opened.
      // NP-1426 explains this is greater detail.
      for ( let i = 0 ; i < this.activeIntercepts.length ; i++ ) {
        let activeIntercept = this.activeIntercepts[i];
        let hasAllOptions = true;

        // All options in the active intercept need to satisfy the
        // incoming intercept for this to be a match.
        activeIntercept.capabilityOptions.forEach((capOpt) => {
          if ( ! intercept.capabilityOptions.includes(capOpt) ) {
            hasAllOptions = false;
          }
        });
        if ( hasAllOptions ) {
          return activeIntercept.promise;
        }
      }
      // Register intercept for later occurances of the check above
      this.activeIntercepts.push(intercept);

      // Pop up the popup
      return new Promise((resolve, _) => {
        this.ctrl.add(this.Popup.create({ closeable: false })
            .tag(this.CapabilityInterceptView, {
              data: intercept,
              onClose: (x) => {
                x.closeDialog();
                resolve(x);
              }
            })
        );
      });
    },

    function save(wizardlet) {
      if ( ! wizardlet.isAvailable ) return Promise.resolve();
      var isAssociation = wizardlet.capability.associatedEntity === foam.nanos.crunch.AssociatedEntity.ACTING_USER;
      var associatedEntity = isAssociation ? this.subject.realUser :
      wizardlet.capability.associatedEntity === foam.nanos.crunch.AssociatedEntity.USER ? this.subject.user : this.subject.realUser;

      return this.updateUCJ(wizardlet, associatedEntity).then(() => {
        var ucj = wizardlet.ucj;
        if ( ucj === null ) {
          ucj = isAssociation ?
          this.AgentCapabilityJunction.create({
              sourceId: associatedEntity.id,
              targetId: wizardlet.capability.id,
              effectiveUser: this.subject.user.id
            })
            : this.UserCapabilityJunction.create({
              sourceId: associatedEntity.id,
              targetId: wizardlet.capability.id
            })
        }
        if ( wizardlet.of ) ucj.data = wizardlet.data;
        return this.userCapabilityJunctionDAO.put(ucj);
      });
    },
    async function updateUCJ(wizardlet, associatedEntity) {
      return this.userCapabilityJunctionDAO.find(
        this.AND(
          this.OR(
            this.AND(
              this.NOT(this.INSTANCE_OF(this.AgentCapabilityJunction)),
              this.EQ(this.UserCapabilityJunction.SOURCE_ID, associatedEntity.id)
            ),
            this.AND(
              this.INSTANCE_OF(this.AgentCapabilityJunction),
              this.EQ(this.UserCapabilityJunction.SOURCE_ID, associatedEntity.id),
              this.EQ(this.AgentCapabilityJunction.EFFECTIVE_USER, this.subject.user.id)
            )
          ),
          this.EQ(this.UserCapabilityJunction.TARGET_ID, wizardlet.capability.id)
        )
      ).then(ucj => {
        wizardlet.ucj = ucj;
        return wizardlet;
      });
    },
    function purgeCachedCapabilityDAOs() {
      this.capabilityDAO.cmd_(this, foam.dao.CachingDAO.PURGE);
      this.capabilityDAO.cmd_(this, foam.dao.AbstractDAO.RESET_CMD);
      this.capabilityCategoryDAO.cmd_(this, foam.dao.CachingDAO.PURGE);
      this.capabilityCategoryDAO.cmd_(this, foam.dao.AbstractDAO.RESET_CMD);
      this.userCapabilityJunctionDAO.cmd_(this, foam.dao.CachingDAO.PURGE);
      this.userCapabilityJunctionDAO.cmd_(this, foam.dao.AbstractDAO.RESET_CMD);
    },

    // CRUNCH Lite Methods
    function launchCapableWizard(intercept) {
      var p = Promise.resolve(true);

      intercept.capableRequirements.forEach(capable => {
        var seq = this.createCapableWizardSequence(intercept, capable);
        p = p.then(() => {
          return seq.execute().then(x => {
            return x;
          });
        });
      })

      return p;
    },

    // This function is only called by CapableView
    function getWizardletsFromCapable(capable) {
      return this.Sequence.create(null, this.__subContext__.createSubContext({
        capable: capable
      })).add(this.CapableCreateWizardletsAgent).execute().then(x => x.wizardlets);
    }
  ]
});
<|endoftext|>