<commit_before>// Copyright 2002-2013, University of Colorado

/**
 * A persistent display of a specific Node and its descendants
 *
 * @author Jonathan Olson <olsonsjc@gmail.com>
 */

define( function( require ) {
  'use strict';

  var inherit = require( 'PHET_CORE/inherit' );
  var scenery = require( 'SCENERY/scenery' );
  require( 'SCENERY/util/Trail' );
  require( 'SCENERY/display/DisplayInstance' );
  require( 'SCENERY/display/RenderState' );
  require( 'SCENERY/layers/Renderer' );

  scenery.Display = function Display( rootNode ) {
    this._rootNode = rootNode;
    this._domElement = null; // TODO: potentially allow immediate export of this?
    this._sharedCanvasInstances = {}; // map from Node ID to DisplayInstance, for fast lookup
    this._baseInstance = null; // will be filled with the root DisplayInstance
  };
  var Display = scenery.Display;

  // recursively compute the bitmask intersection (bitwise AND) for a node and all of its children, and store it to that node's _subtreeRendererBitmask
  function recursiveUpdateRendererBitmask( node ) {
    var bitmask = scenery.bitmaskAll;
    bitmask &= node._rendererBitmask;

    // include all children
    var children = node._children;
    var numChildren = children.length;
    for ( var i = 0; i < numChildren; i++ ) {
      bitmask &= recursiveUpdateRendererBitmask( children[i] );
    }

    node._subtreeRendererBitmask = bitmask;
    return bitmask; // return the bitmask so we have direct access at the call site
  }

  // display instance linked list ops
  function connectInstances( a, b ) {
    a.nextPainted = b;
    b.previousPainted = a;
  }

  function createBackbone( display, trail, state ) {
    var blockInstance = new scenery.DisplayInstance( trail );
    blockInstance.state = state;
    blockInstance.renderer = scenery.Renderer.DOM;

    createProxyInstance( display, trail, state, blockInstance );
    return blockInstance;
  }

  function createCanvasCache( display, trail, state ) {
    var blockInstance = new scenery.DisplayInstance( trail );
    blockInstance.state = state;
    blockInstance.renderer = state.getCacheRenderer();

    createProxyInstance( display, trail, state, blockInstance );
    return blockInstance;
  }

  function createSharedCanvasCache( display, trail, state ) {
    var instanceKey = trail.lastNode().getId();
    var sharedInstance = display._sharedCanvasInstances[instanceKey];
    if ( sharedInstance ) {
      // TODO: assert state is the same?
      // TODO: increment reference counting?
      return sharedInstance;
    } else {
      var blockInstance = new scenery.DisplayInstance( new scenery.Trail( trail.lastNode() ) );
      blockInstance.state = state;
      blockInstance.renderer = state.getCacheRenderer();

      createProxyInstance( display, trail, state, blockInstance );
      // TODO: increment reference counting?
      display._sharedCanvasInstances[instanceKey] = blockInstance;
      return blockInstance;
    }
  }

  // For when we have a block/stub instance (for a backbone/cache), and we want an instance for the same trail, but to render itself and its subtree.
  // Basically, this involves another getStateForDescendant (called in createInstance), and for now we set up proxy variables
  function createProxyInstance( display, trail, state, blockInstance ) {
    var instance = createInstance( display, trail, state );
    // TODO: better way of handling this?
    blockInstance.proxyChild = instance;
    instance.proxyParent = blockInstance;

    blockInstance.firstPainted = blockInstance;
    blockInstance.lastPainted = blockInstance;
    return instance; // if we need it
  }

  function createSplitInstance() {
    return new scenery.DisplayInstance( null ); // null trail
  }

  function createInstance( display, trail, ancestorState ) {
    var state = ancestorState.getStateForDescendant( trail );
    if ( state.isBackbone() ) {
      return createBackbone( display, trail, state );
    } else if ( state.isCanvasCache() ) {
      return state.isCacheShared() ? createSharedCanvasCache( display, trail, state ) : createCanvasCache( display, trail, state );
    } else {
      var instance = new scenery.DisplayInstance( trail );
      var node = trail.lastNode();
      instance.state = state;
      instance.renderer = node.isPainted() ? state.getPaintedRenderer() : null;

      var currentPaintedInstance = null;
      if ( instance.isEffectivelyPainted() ) {
        currentPaintedInstance = instance;
        instance.firstPainted = instance;
      }

      var children = trail.lastNode().children;
      var numChildren = children.length;
      for ( var i = 0; i < numChildren; i++ ) {
        var childInstance = createInstance( display, trail.copy().addDescendant( children[i], i ), state );
        instance.appendInstance( childInstance );
        if ( childInstance.firstPainted ) {
          assert && assert( childInstance.lastPainted, 'Any display instance with firstPainted should also have lastPainted' );

          if ( currentPaintedInstance ) {
            connectInstances( currentPaintedInstance, childInstance.firstPainted );
          } else {
            instance.firstPainted = childInstance.firstPainted;
          }
          currentPaintedInstance = childInstance.lastPainted;
        }
      }

      if ( currentPaintedInstance !== null ) {
        instance.lastPainted = currentPaintedInstance;
      }

      if ( state.requestsSplit() ) {
        if ( instance.firstPainted ) {
          var beforeSplit = createSplitInstance();
          var afterSplit = createSplitInstance();
          connectInstances( beforeSplit, instance.firstPainted );
          connectInstances( instance.lastPainted, afterSplit );
          instance.firstPainted = beforeSplit;
          instance.lastPainted = afterSplit;
        } else {
          instance.firstPainted = instance.lastPainted = createSplitInstance();
        }
      }

      return instance;
    }
  }

  inherit( Object, Display, {
    getRootNode: function() {
      return this._rootNode;
    },
    get rootNode() { return this.getRootNode(); },

    // NOTE: to be replaced with a full stitching/update version
    buildTemporaryDisplay: function() {
      // compute updated _subtreeRendererBitmask for every Node // TODO: add and use dirty flag for this, and decide how the flags get set!
      recursiveUpdateRendererBitmask( this._rootNode );

      var baseTrail = new scenery.Trail( this._rootNode );
      var baseState = new scenery.RenderState.TestState( baseTrail, [
        scenery.Renderer.DOM,
        scenery.Renderer.Canvas,
        scenery.Renderer.SVG
      ], false, false );
      this._baseInstance = createBackbone( this, baseTrail, baseState );
    }
  } );

  return Display;
} );
<commit_msg>Initialize with an empty trail<commit_after>// Copyright 2002-2013, University of Colorado

/**
 * A persistent display of a specific Node and its descendants
 *
 * @author Jonathan Olson <olsonsjc@gmail.com>
 */

define( function( require ) {
  'use strict';

  var inherit = require( 'PHET_CORE/inherit' );
  var scenery = require( 'SCENERY/scenery' );
  require( 'SCENERY/util/Trail' );
  require( 'SCENERY/display/DisplayInstance' );
  require( 'SCENERY/display/RenderState' );
  require( 'SCENERY/layers/Renderer' );

  scenery.Display = function Display( rootNode ) {
    this._rootNode = rootNode;
    this._domElement = null; // TODO: potentially allow immediate export of this?
    this._sharedCanvasInstances = {}; // map from Node ID to DisplayInstance, for fast lookup
    this._baseInstance = null; // will be filled with the root DisplayInstance
  };
  var Display = scenery.Display;

  // recursively compute the bitmask intersection (bitwise AND) for a node and all of its children, and store it to that node's _subtreeRendererBitmask
  function recursiveUpdateRendererBitmask( node ) {
    var bitmask = scenery.bitmaskAll;
    bitmask &= node._rendererBitmask;

    // include all children
    var children = node._children;
    var numChildren = children.length;
    for ( var i = 0; i < numChildren; i++ ) {
      bitmask &= recursiveUpdateRendererBitmask( children[i] );
    }

    node._subtreeRendererBitmask = bitmask;
    return bitmask; // return the bitmask so we have direct access at the call site
  }

  // display instance linked list ops
  function connectInstances( a, b ) {
    a.nextPainted = b;
    b.previousPainted = a;
  }

  function createBackbone( display, trail, state ) {
    var blockInstance = new scenery.DisplayInstance( trail );
    blockInstance.state = state;
    blockInstance.renderer = scenery.Renderer.DOM;

    createProxyInstance( display, trail, state, blockInstance );
    return blockInstance;
  }

  function createCanvasCache( display, trail, state ) {
    var blockInstance = new scenery.DisplayInstance( trail );
    blockInstance.state = state;
    blockInstance.renderer = state.getCacheRenderer();

    createProxyInstance( display, trail, state, blockInstance );
    return blockInstance;
  }

  function createSharedCanvasCache( display, trail, state ) {
    var instanceKey = trail.lastNode().getId();
    var sharedInstance = display._sharedCanvasInstances[instanceKey];
    if ( sharedInstance ) {
      // TODO: assert state is the same?
      // TODO: increment reference counting?
      return sharedInstance;
    } else {
      var blockInstance = new scenery.DisplayInstance( new scenery.Trail( trail.lastNode() ) );
      blockInstance.state = state;
      blockInstance.renderer = state.getCacheRenderer();

      createProxyInstance( display, trail, state, blockInstance );
      // TODO: increment reference counting?
      display._sharedCanvasInstances[instanceKey] = blockInstance;
      return blockInstance;
    }
  }

  // For when we have a block/stub instance (for a backbone/cache), and we want an instance for the same trail, but to render itself and its subtree.
  // Basically, this involves another getStateForDescendant (called in createInstance), and for now we set up proxy variables
  function createProxyInstance( display, trail, state, blockInstance ) {
    var instance = createInstance( display, trail, state );
    // TODO: better way of handling this?
    blockInstance.proxyChild = instance;
    instance.proxyParent = blockInstance;

    blockInstance.firstPainted = blockInstance;
    blockInstance.lastPainted = blockInstance;
    return instance; // if we need it
  }

  function createSplitInstance() {
    return new scenery.DisplayInstance( null ); // null trail
  }

  function createInstance( display, trail, ancestorState ) {
    var state = ancestorState.getStateForDescendant( trail );
    if ( state.isBackbone() ) {
      return createBackbone( display, trail, state );
    } else if ( state.isCanvasCache() ) {
      return state.isCacheShared() ? createSharedCanvasCache( display, trail, state ) : createCanvasCache( display, trail, state );
    } else {
      var instance = new scenery.DisplayInstance( trail );
      var node = trail.lastNode();
      instance.state = state;
      instance.renderer = node.isPainted() ? state.getPaintedRenderer() : null;

      var currentPaintedInstance = null;
      if ( instance.isEffectivelyPainted() ) {
        currentPaintedInstance = instance;
        instance.firstPainted = instance;
      }

      var children = trail.lastNode().children;
      var numChildren = children.length;
      for ( var i = 0; i < numChildren; i++ ) {
        var childInstance = createInstance( display, trail.copy().addDescendant( children[i], i ), state );
        instance.appendInstance( childInstance );
        if ( childInstance.firstPainted ) {
          assert && assert( childInstance.lastPainted, 'Any display instance with firstPainted should also have lastPainted' );

          if ( currentPaintedInstance ) {
            connectInstances( currentPaintedInstance, childInstance.firstPainted );
          } else {
            instance.firstPainted = childInstance.firstPainted;
          }
          currentPaintedInstance = childInstance.lastPainted;
        }
      }

      if ( currentPaintedInstance !== null ) {
        instance.lastPainted = currentPaintedInstance;
      }

      if ( state.requestsSplit() ) {
        if ( instance.firstPainted ) {
          var beforeSplit = createSplitInstance();
          var afterSplit = createSplitInstance();
          connectInstances( beforeSplit, instance.firstPainted );
          connectInstances( instance.lastPainted, afterSplit );
          instance.firstPainted = beforeSplit;
          instance.lastPainted = afterSplit;
        } else {
          instance.firstPainted = instance.lastPainted = createSplitInstance();
        }
      }

      return instance;
    }
  }

  inherit( Object, Display, {
    getRootNode: function() {
      return this._rootNode;
    },
    get rootNode() { return this.getRootNode(); },

    // NOTE: to be replaced with a full stitching/update version
    buildTemporaryDisplay: function() {
      // compute updated _subtreeRendererBitmask for every Node // TODO: add and use dirty flag for this, and decide how the flags get set!
      recursiveUpdateRendererBitmask( this._rootNode );

      var baseTrail = new scenery.Trail( this._rootNode );
      var baseState = new scenery.RenderState.TestState( baseTrail, [
        scenery.Renderer.DOM,
        scenery.Renderer.Canvas,
        scenery.Renderer.SVG,
        new scenery.Trail()
      ], false, false );
      this._baseInstance = createBackbone( this, baseTrail, baseState );
    }
  } );

  return Display;
} );
<|endoftext|>


<commit_before>//= require "codemirror"
//= require "mobileCodeMirror"
//= require "library"
//= require "unsaved"
var focusPanel = 'javascript';
var editors = {};
// var row = {};
var sql = new Array();

window.editors = editors;

editors.html = CodeMirror.fromTextArea(document.getElementById('html'), {
  parserfile: [],
  tabMode: 'shift',
  mode: 'text/html',
  onChange: changecontrol,
  theme: "eclipse",
  indentUnit: 4,
  lineNumbers: true
});

editors.javascript = CodeMirror.fromTextArea(document.getElementById('javascript'), {
  mode: 'css',
  tabMode: 'shift',
  onChange: changecontrol,
  theme: "eclipse",
  matchBrackets: true,
  indentUnit: 4,
  lineNumbers: true
});

setupEditor('javascript');
setupEditor('html');

var editorsReady = setInterval(function () {
  if (editors.html.ready && editors.javascript.ready) {

    editors.html.setCursor(7, 8);

    clearInterval(editorsReady);
    editors.ready = true;
    if (typeof editors.onReady == 'function') editors.onReady();

    var scrollers = {
      html: $(editors.html.getScrollerElement()),
      javascript: $(editors.javascript.getScrollerElement())
    };

    $document.bind('sizeeditors', function () {
      var top = 0, //$el.offset().top,
          height = $('#bin').height();
      scrollers.html.height(height - top);
      scrollers.javascript.height(height - top - $error.filter(':visible').height());
      editors.javascript.refresh();
      editors.html.refresh();
    });

    $(window).resize(function () {
      setTimeout(function () {
        $document.trigger('sizeeditors');
      }, 100);
    });

    $document.trigger('sizeeditors');
    $document.trigger('jsbinReady');
  }
}, 100);

// $('#javascript').replaceWith('

');
// $('#javascript').css({ height: '100%', width: '100%' });
// $('#html').replaceWith('

');
// $('#html').css({ height: '100%', width: '100%' });
//
// editors.javascript = ace.edit("javascript");
// editors.html = ace.edit("html");
//
// var JavaScriptMode = require("ace/mode/javascript").Mode,
//     HTMLMode = require("ace/mode/html").Mode;
//
// setupAce(editors, 'javascript');
// setupAce(editors, 'html');
//
// function setupAce(editor, type) {
//   var session = editors[type].getSession(),
//       renderer = editors[type].renderer;
//   if (type == 'javascript') {
//     session.setMode(new JavaScriptMode());
//   } else {
//     session.setMode(new HTMLMode());
//   }
//
//   editors[type].setHighlightActiveLine(false);
//   session.setUseWrapMode(true);
//   session.setUseSoftTabs(true);
//   session.setWrapLimitRange(null, null);
//
//   renderer.setShowPrintMargin(false);
//   renderer.setShowGutter(false);
//   renderer.setHScrollBarAlwaysVisible(false);
// }

function focused(editor, event) {
  focusPanel = editor.id;
  snapshot(focusPanel);
  console.log(focusPanel);
}

function getFocusedPanel() {
  return focusPanel;
}

function setupEditor(panel) {
  var e = editors[panel],
      focusedPanel = sessionStorage.getItem('panel');

  // overhang from CodeMirror1
  e.setCode = function (str) {
    e.setValue(str);
  };

  e.getCode = function () {
    return e.getValue();
  };

  e.currentLine = function () {
    var pos = e.getCursor();
    return pos.line;
  };

  e.setOption('onChange', changecontrol);
  e.setOption('onKeyEvent', keycontrol);
  e.setOption('onFocus', focused);

  e.id = panel;

  e.win = e.getWrapperElement();
  e.scroller = $(e.getScrollerElement());

  $(e.win).click(function () {
    e.focus();
  });

  var $label = $('.code.' + panel + ' > .label');
  if (document.body.className.indexOf('ie6') === -1) {
    e.scroller.scroll(function (event) {
      if (this.scrollTop > 10) {
        $label.stop().animate({ opacity: 0 }, 50, function () {
          $(this).hide();
        });
      } else {
        $label.show().stop().animate({ opacity: 1 }, 250);
      }
    });
  }

  populateEditor(panel);
  e.ready = true;

  if (focusedPanel == panel || focusedPanel == null && panel == 'javascript') {
    // e.selectLines(e.nthLine(sessionStorage.getItem('line')), sessionStorage.getItem('character'));
    e.focus();
    e.setCursor({ line: (sessionStorage.getItem('line') || 0) * 1, ch: (sessionStorage.getItem('character') || 0) * 1 });
  }
}

function populateEditor(panel) {
  // populate - should eventually use: session, saved data, local storage
  var data = sessionStorage.getItem(panel), // session code
      saved = localStorage.getItem('saved-' + panel), // user template
      sessionURL = sessionStorage.getItem('url'),
      changed = false;

  if (data == template[panel]) { // restored from original saved
    editors[panel].setCode(data);
  } else if (data && sessionURL == template.url) { // try to restore the session first - only if it matches this url
    editors[panel].setCode(data);
    // tell the document that it's currently being edited, but check that it doesn't match the saved template
    // because sessionStorage gets set on a reload
    changed = data != saved;
  } else if (saved !== null && !/edit/.test(window.location) && !window.location.search) { // then their saved preference
    editors[panel].setCode(saved);
  } else { // otherwise fall back on the JS Bin default
    editors[panel].setCode(template[panel]);
  }

  if (changed) {
    $(document).trigger('codeChange', [ /* revert triggered */ false, /* don't use fade */ true ]);
  }
}

// work out the browser platform
var ua = navigator.userAgent;
if (/macintosh|mac os x/.test(ua)) {
  $.browser.platform = 'mac';
} else if (/windows|win32/.test(ua)) {
  $.browser.platform = 'win';
} else if (/linux/.test(ua)) {
  $.browser.platform = 'linux';
} else {
  $.browser.platform = '';
}

//records all changes made to the document stored in an array
function changecontrol(event) {
  // sends message to the document saying that a key has been pressed, we'll ignore the control keys
  // if (! ({ 16:1, 17:1, 18:1, 20:1, 27:1, 37:1, 38:1, 39:1, 40:1, 91:1, 93:1 })[event.which] ) {
    $(document).trigger('codeChange');
    // if(sql.length > 20){
    //   saveSnaps();
    // }

    snapshot();
  // }

  return true;
}

function roughSizeOfObject(object) {

    var objectList = [];
    var stack = [object];
    var bytes = 0;

    while ( stack.length ) {
        var value = stack.pop();

        if ( typeof value === 'boolean' ) {
            bytes += 4;
        }
        else if ( typeof value === 'string' ) {
            bytes += value.length * 2;
        }
        else if ( typeof value === 'number' ) {
            bytes += 8;
        }
        else if
        (
            typeof value === 'object' && objectList.indexOf(value) === -1
        )
        {
            objectList.push( value );
            for (var i in value) {
                try {
                    if (i == 'Blob') bytes += value[i].size || 0;
                    stack.push(value[i]);
                    stack.push(i);
                } catch(e) {}
            }
        }
    }
    return bytes;
  }

function snapshot(extra){
    var html = editors['html'];
    var css = editors['javascript'];
    var time = new Date();
    var row = {};
    row.clock = time.getTime();
    row.html = html.getValue();
    row.css= css.getValue();
    row.special = extra;
    sql.push(row);
    // console.log('SQL Size: '+roughSizeOfObject(sql));
    // console.log('SQL Length: '+sql.length);
    // console.log(sql);

}

//= require "keycontrol"

<commit_msg>diable statechange log<commit_after>//= require "codemirror"
//= require "mobileCodeMirror"
//= require "library"
//= require "unsaved"
var focusPanel = 'javascript';
var editors = {};
// var row = {};
var sql = new Array();

window.editors = editors;

editors.html = CodeMirror.fromTextArea(document.getElementById('html'), {
  parserfile: [],
  tabMode: 'shift',
  mode: 'text/html',
  onChange: changecontrol,
  theme: "eclipse",
  indentUnit: 4,
  lineNumbers: true
});

editors.javascript = CodeMirror.fromTextArea(document.getElementById('javascript'), {
  mode: 'css',
  tabMode: 'shift',
  onChange: changecontrol,
  theme: "eclipse",
  matchBrackets: true,
  indentUnit: 4,
  lineNumbers: true
});

setupEditor('javascript');
setupEditor('html');

var editorsReady = setInterval(function () {
  if (editors.html.ready && editors.javascript.ready) {

    editors.html.setCursor(7, 8);

    clearInterval(editorsReady);
    editors.ready = true;
    if (typeof editors.onReady == 'function') editors.onReady();

    var scrollers = {
      html: $(editors.html.getScrollerElement()),
      javascript: $(editors.javascript.getScrollerElement())
    };

    $document.bind('sizeeditors', function () {
      var top = 0, //$el.offset().top,
          height = $('#bin').height();
      scrollers.html.height(height - top);
      scrollers.javascript.height(height - top - $error.filter(':visible').height());
      editors.javascript.refresh();
      editors.html.refresh();
    });

    $(window).resize(function () {
      setTimeout(function () {
        $document.trigger('sizeeditors');
      }, 100);
    });

    $document.trigger('sizeeditors');
    $document.trigger('jsbinReady');
  }
}, 100);

// $('#javascript').replaceWith('

');
// $('#javascript').css({ height: '100%', width: '100%' });
// $('#html').replaceWith('

');
// $('#html').css({ height: '100%', width: '100%' });
//
// editors.javascript = ace.edit("javascript");
// editors.html = ace.edit("html");
//
// var JavaScriptMode = require("ace/mode/javascript").Mode,
//     HTMLMode = require("ace/mode/html").Mode;
//
// setupAce(editors, 'javascript');
// setupAce(editors, 'html');
//
// function setupAce(editor, type) {
//   var session = editors[type].getSession(),
//       renderer = editors[type].renderer;
//   if (type == 'javascript') {
//     session.setMode(new JavaScriptMode());
//   } else {
//     session.setMode(new HTMLMode());
//   }
//
//   editors[type].setHighlightActiveLine(false);
//   session.setUseWrapMode(true);
//   session.setUseSoftTabs(true);
//   session.setWrapLimitRange(null, null);
//
//   renderer.setShowPrintMargin(false);
//   renderer.setShowGutter(false);
//   renderer.setHScrollBarAlwaysVisible(false);
// }

function focused(editor, event) {
  focusPanel = editor.id;
  snapshot(focusPanel);

}

function getFocusedPanel() {
  return focusPanel;
}

function setupEditor(panel) {
  var e = editors[panel],
      focusedPanel = sessionStorage.getItem('panel');

  // overhang from CodeMirror1
  e.setCode = function (str) {
    e.setValue(str);
  };

  e.getCode = function () {
    return e.getValue();
  };

  e.currentLine = function () {
    var pos = e.getCursor();
    return pos.line;
  };

  e.setOption('onChange', changecontrol);
  e.setOption('onKeyEvent', keycontrol);
  e.setOption('onFocus', focused);

  e.id = panel;

  e.win = e.getWrapperElement();
  e.scroller = $(e.getScrollerElement());

  $(e.win).click(function () {
    e.focus();
  });

  var $label = $('.code.' + panel + ' > .label');
  if (document.body.className.indexOf('ie6') === -1) {
    e.scroller.scroll(function (event) {
      if (this.scrollTop > 10) {
        $label.stop().animate({ opacity: 0 }, 50, function () {
          $(this).hide();
        });
      } else {
        $label.show().stop().animate({ opacity: 1 }, 250);
      }
    });
  }

  populateEditor(panel);
  e.ready = true;

  if (focusedPanel == panel || focusedPanel == null && panel == 'javascript') {
    // e.selectLines(e.nthLine(sessionStorage.getItem('line')), sessionStorage.getItem('character'));
    e.focus();
    e.setCursor({ line: (sessionStorage.getItem('line') || 0) * 1, ch: (sessionStorage.getItem('character') || 0) * 1 });
  }
}

function populateEditor(panel) {
  // populate - should eventually use: session, saved data, local storage
  var data = sessionStorage.getItem(panel), // session code
      saved = localStorage.getItem('saved-' + panel), // user template
      sessionURL = sessionStorage.getItem('url'),
      changed = false;

  if (data == template[panel]) { // restored from original saved
    editors[panel].setCode(data);
  } else if (data && sessionURL == template.url) { // try to restore the session first - only if it matches this url
    editors[panel].setCode(data);
    // tell the document that it's currently being edited, but check that it doesn't match the saved template
    // because sessionStorage gets set on a reload
    changed = data != saved;
  } else if (saved !== null && !/edit/.test(window.location) && !window.location.search) { // then their saved preference
    editors[panel].setCode(saved);
  } else { // otherwise fall back on the JS Bin default
    editors[panel].setCode(template[panel]);
  }

  if (changed) {
    $(document).trigger('codeChange', [ /* revert triggered */ false, /* don't use fade */ true ]);
  }
}

// work out the browser platform
var ua = navigator.userAgent;
if (/macintosh|mac os x/.test(ua)) {
  $.browser.platform = 'mac';
} else if (/windows|win32/.test(ua)) {
  $.browser.platform = 'win';
} else if (/linux/.test(ua)) {
  $.browser.platform = 'linux';
} else {
  $.browser.platform = '';
}

//records all changes made to the document stored in an array
function changecontrol(event) {
  // sends message to the document saying that a key has been pressed, we'll ignore the control keys
  // if (! ({ 16:1, 17:1, 18:1, 20:1, 27:1, 37:1, 38:1, 39:1, 40:1, 91:1, 93:1 })[event.which] ) {
    $(document).trigger('codeChange');
    // if(sql.length > 20){
    //   saveSnaps();
    // }

    snapshot();
  // }

  return true;
}

function roughSizeOfObject(object) {

    var objectList = [];
    var stack = [object];
    var bytes = 0;

    while ( stack.length ) {
        var value = stack.pop();

        if ( typeof value === 'boolean' ) {
            bytes += 4;
        }
        else if ( typeof value === 'string' ) {
            bytes += value.length * 2;
        }
        else if ( typeof value === 'number' ) {
            bytes += 8;
        }
        else if
        (
            typeof value === 'object' && objectList.indexOf(value) === -1
        )
        {
            objectList.push( value );
            for (var i in value) {
                try {
                    if (i == 'Blob') bytes += value[i].size || 0;
                    stack.push(value[i]);
                    stack.push(i);
                } catch(e) {}
            }
        }
    }
    return bytes;
  }

function snapshot(extra){
    var html = editors['html'];
    var css = editors['javascript'];
    var time = new Date();
    var row = {};
    row.clock = time.getTime();
    row.html = html.getValue();
    row.css= css.getValue();
    row.special = extra;
    sql.push(row);
    // console.log('SQL Size: '+roughSizeOfObject(sql));
    // console.log('SQL Length: '+sql.length);
    // console.log(sql);

}

//= require "keycontrol"

<|endoftext|>


<commit_before>jQuery(function ($) {
    'use strict';

    function applyColorBox() {
        var images = $('.single-post .storycontent a, .single-post .thumbnail a').has('img')
            .concat($('.format-image .thumbnail a, .format-image h1 a'));

        if (images.length === 0) {
            return;
        }
        if ($(document).width() >= 768) {
            images.colorbox({
                rel: 'gal',
                maxWidth: "100%",
                maxHeight: "100%",
                fixed: true,
                scrolling: false
            });
            return;
        }
        var colorBoxEnabled = $(images[0]).hasClass("cboxElement");
        if (colorBoxEnabled && $(document).width() < 768) {
            $.colorbox.close();

            $('.cboxElement')
                .removeData("colorbox")
                .removeClass("cboxElement");
        }
    }

    applyColorBox();
    $(window).resize(applyColorBox);
    $(document.body).bind("post-load", applyColorBox);
});
<commit_msg>Corrected logic as .concat does not work<commit_after>jQuery(function ($) {
    'use strict';

    function applyColorBox() {
        var images = $('.single-post .storycontent a, .single-post .thumbnail a').has('img');
        var images2 = $('.format-image .thumbnail a, .format-image h1 a');

        if (images.length === 0 && images2.length === 0) {
            return;
        }
        if ($(document).width() >= 768) {
            images.colorbox({
                rel: 'gal',
                maxWidth: "100%",
                maxHeight: "100%",
                fixed: true,
                scrolling: false
            });
            images2.colorbox({
                rel: 'gal',
                maxWidth: "100%",
                maxHeight: "100%",
                fixed: true,
                scrolling: false
            });
            return;
        }
        var colorBoxEnabled = $(images[0]).hasClass("cboxElement") || $(images2[0]).hasClass("cboxElement");
        if (colorBoxEnabled && $(document).width() < 768) {
            $.colorbox.close();

            $('.cboxElement')
                .removeData("colorbox")
                .removeClass("cboxElement");
        }
    }

    applyColorBox();
    $(window).resize(applyColorBox);
    $(document.body).bind("post-load", applyColorBox);
});
<|endoftext|>


<commit_before>/**
 * @copyright   2010-2015, The Titon Project
 * @license     http://opensource.org/licenses/BSD-3-Clause
 * @link        http://titon.io
 */

define([
    'jquery'
], function($) {

/**
 * An event that allows the clicking of the document to trigger a callback.
 * However, will only trigger if the element clicked is not in the exclude list or a child of.
 * Useful for closing drop downs and menus.
 *
 * Based on and credited to http://benalman.com/news/2010/03/jquery-special-events/
 *
 * @returns {Object}
 */
$.event.special.clickout = (function() {
    var elements = [];

    $(document).on('click.toolkit.out', function(e) {
        if (!elements.length) {
            return;
        }

        var trigger = true,
            collection = $(document),
            target = $(e.target);

        $.each(elements, function(i, item) {
            var self = $(item);

            // Test that the delegated selector class matches
            if ($.type(item) === 'string') {
                trigger = (!target.is(item) && !self.has(e.target).length);

            // Else test if the element matches
            } else {
                trigger = (!self.is(e.target) && !self.has(e.target).length);
            }

            if (trigger) {
                collection = collection.add(self);
            } else {
                return false;
            }
        });

        if (trigger) {
            collection.trigger('clickout', [e.target]);
        }
    });

    return {
        add: function(handler) {
            var context = this;

            if (this === document) {
                context = handler.selector;
            }

            if ($.inArray(context, elements) === -1) {
                elements.push(context);
            }
        },
        remove: function(handler) {
            var context = this;

            if (this === document) {
                context = handler.selector;
            }

            elements = $.grep(elements, function(item) {
                return (item !== context);
            });
        }
    };
})();

});<commit_msg>Fix clickout events not firing on touch devices [#77]<commit_after>/**
 * @copyright   2010-2015, The Titon Project
 * @license     http://opensource.org/licenses/BSD-3-Clause
 * @link        http://titon.io
 */

define([
    'jquery',
    '../flags/touch'
], function($, isTouch) {

/**
 * An event that allows the clicking of the document to trigger a callback.
 * However, will only trigger if the element clicked is not in the exclude list or a child of.
 * Useful for closing drop downs and menus.
 *
 * Based on and credited to http://benalman.com/news/2010/03/jquery-special-events/
 *
 * @returns {Object}
 */
$.event.special.clickout = (function() {
    var elements = [];

    $(document).on(isTouch ? 'touchend' : 'click', function(e) {
        if (!elements.length) {
            return;
        }

        var trigger = true,
            collection = $(document),
            target = $(e.target);

        $.each(elements, function(i, item) {
            var self = $(item);

            // Test that the delegated selector class matches
            if ($.type(item) === 'string') {
                trigger = (!target.is(item) && !self.has(e.target).length);

            // Else test if the element matches
            } else {
                trigger = (!self.is(e.target) && !self.has(e.target).length);
            }

            if (trigger) {
                collection = collection.add(self);
            } else {
                return false;
            }
        });

        if (trigger) {
            collection.trigger('clickout', [e.target]);
        }
    });

    return {
        add: function(handler) {
            var context = this;

            if (this === document) {
                context = handler.selector;
            }

            if ($.inArray(context, elements) === -1) {
                elements.push(context);
            }
        },
        remove: function(handler) {
            var context = this;

            if (this === document) {
                context = handler.selector;
            }

            elements = $.grep(elements, function(item) {
                return (item !== context);
            });
        }
    };
})();

});<|endoftext|>


<commit_before>// Copyright 2013-2015, University of Colorado Boulder

/**
 * Grunt configuration file for PhET projects.
 * Tasks share information via global.phet, see individual tasks for details.
 *
 * @author Chris Malley (PixelZoom, Inc.)
 * @author Jon Olson
 * @author Sam Reid
 * @author John Blanco
 */

// use process.env
/* jslint node: true */

// built-in node APIs
var assert = require( 'assert' );
var fs = require( 'fs' );

// 3rd-party packages
var _ = require( '../../../sherpa/lib/lodash-2.4.1.min' ); // eslint-disable-line require-statement-match

// PhET custom grunt tasks
var afterRequirejsBuild = require( '../../../chipper/js/grunt/afterRequirejsBuild' );
var checkoutShas = require( '../../../chipper/js/grunt/checkoutShas' );
var commitsSince = require( '../../../chipper/js/grunt/commitsSince' );
var createSim = require( '../../../chipper/js/grunt/createSim' );
var deployProduction = require( '../../../chipper/js/grunt/deployProduction' );
var deployDev = require( '../../../chipper/js/grunt/deployDev' );
var deployUtil = require( '../../../chipper/js/grunt/deployUtil' );
var generateDevelopmentHTML = require( '../../../chipper/js/grunt/generateDevelopmentHTML' );
var generateREADME = require( '../../../chipper/js/grunt/generateREADME' );
var generateThumbnails = require( '../../../chipper/js/grunt/generateThumbnails' );
var reportMedia = require( '../../../chipper/js/grunt/reportMedia' );
var reportThirdParty = require( '../../../chipper/js/grunt/reportThirdParty' );
var getBuildConfig = require( '../../../chipper/js/grunt/getBuildConfig' );
var getGruntConfig = require( '../../../chipper/js/grunt/getGruntConfig' );
var updateCopyrightDates = require( '../../../chipper/js/grunt/updateCopyrightDates' );
var toPhETiOSite = require( '../../../chipper/js/grunt/toPhETiOSite' );
var updatePhETiOSite = require( '../../../chipper/js/grunt/updatePhETiOSite' );
var phetIO = require( '../../../chipper/js/grunt/phetIO' );

module.exports = function( grunt ) {
  'use strict';

  // For eslint
  require( 'load-grunt-tasks' )( grunt );

  //---------------------------------------------------------------------------------------------------------------
  // Configuration

  var buildConfig = getBuildConfig( grunt );

  // Initialize and document all globals
  assert( !global.phet, 'global.phet already exists' );
  global.phet = {

    chipper: {

      // the grunt instance, for situations where we can't pass it as a function argument
      grunt: grunt,

      // for code that runs in both requirejs and build modes, and therefore doesn't have access to grunt.file
      fs: fs,

      // polyfill to work around the cache buster arg in the *-config.js file that all sims have.
      getCacheBusterArgs: function() { return ''; },

      // media plugins populate this with license.json entries, see getLicenseEntry.js for format of entries
      licenseEntries: {},

      // use by media plugins, which don't have access to buildConfig
      brand: buildConfig.brand,

      // populated by mipmap.js
      mipmapsToBuild: [],

      // populated by string.js
      strings: {}
    }
  };

  // Initialize grunt
  grunt.initConfig( getGruntConfig( grunt, buildConfig.name, buildConfig.phetLibs ) );

  //---------------------------------------------------------------------------------------------------------------
  // Primary tasks
  //---------------------------------------------------------------------------------------------------------------

  // Default task ('grunt')

  grunt.registerTask( 'default', 'Builds the English HTML', [ 'build' ] );

  // Add the linting step as an pre-build step.  Can be skipped with --lint=false
  var optionalTasks = [];
  if ( grunt.option( 'lint' ) === false ) {

    // do nothing
  }
  else {
    optionalTasks.push( 'lint-all' );
  }

  var additionalTasks = [
    'clean',
    'requirejs:build',
    'after-requirejs-build'
  ];

  grunt.registerTask( 'build',
    'Builds the simulation:\n' +
    'with no options, builds HTML for English only\n' +
    '--locales=* : all locales in strings/ directory\n' +
    '--locales=fr : French\n' +
    '--locales=ar,fr,es : Arabic, French and Spanish (comma separated locales)\n' +
    '--localesRepo=$repo : all locales in another repository\'s strings/ directory, ignored if --locales is present\n' +
    '--brand=$brand : build a specific brand. Choices are phet, phet-io, adapted-from-phet (default)\n' +
    '--lint=false : skip the lint sub-task\n' +
    '--mangle=false : skip the mangling portion of UglifyJS2, and beautify the output\n' +
    '--uglify=false : skip the UglifyJS2 step altogether\n' +
    '--chromeWebStore : Output additional files that can be deployed to the Chrome Web Store',
    optionalTasks.concat( additionalTasks )
  );

  grunt.registerTask( 'build-for-server', 'meant for use by build-server only',
    [ 'build', 'generate-thumbnails' ]
  );

  // Grunt task that determines created and last modified dates from git, and
  // updates copyright statements accordingly, see #403
  grunt.registerTask( 'update-copyright-dates', 'Update the copyright dates in JS source files based on Github dates',
    function() {
      updateCopyrightDates( grunt, buildConfig );
    } );

  grunt.registerTask( 'deploy-production',
    'Invoke deployDev and then deploy a simulation to the production server.\n' +
    'Should be run AFTER grunt build since it uses the shas from dependencies.json in the build directory.\n' +
    'Deploys to figaro by default, but simian can be used for testing by setting:\n' +
    '"productionServerName": "simian.colorado.edu" and "productionServerURL": "https://phet-dev.colorado.edu" in build-local.json\n' +
    '--noDev : if true, deploy to production only, not spot as well. Useful for testing\n' +
    '--email : optionally enter an email to be notified if the build fails or succeeds (overrides buildServerNotifyEmail in build-locale.json)\n' +
    '--locales=* : all locales that have been published so far. NOTE: for sims published after 11/9/15, this is the ' +
    'default option, otherwise it must be explicitly passed to republish all translations.\n' +
    '--locales=fr : French\n' +
    '--locales=ar,fr,es : Arabic, French and Spanish (comma separated locales)',
    function() {
      // before invoking the build-server, do a dev deploy, including committing and pushing to github
      var done = grunt.task.current.async();
      if ( grunt.option( 'noDev' ) ) {
        deployProduction( grunt, done );
      }
      else {
        deployDev( grunt, function() {
          deployProduction( grunt, done );
        } );
      }
    }
  );

  grunt.registerTask( 'deploy-dev',
    'Deploy a dev version to spot, or optionally to the server in your preferences file\n' +
    '--mkdir : set to true to create the sim dir and .htaccess file before copying the version directory\n' +
    '--test : set to true to disable commit and push, and SCP to a test directory on spot',
    function() {
      deployDev( grunt );
    }
  );

  grunt.registerTask( 'deploy-rc',
    'Deploy a rc version to spot using the build server.\n' +
    'Behaves identically to grunt deploy-dev, except the sim is rebuilt and deployed from the build-server instead of locally.\n' +
    'This is useful to ensure that the rc version is built in the same environment as our production deploys',
    function() {
      grunt.option( 'noDev', true );
      grunt.option( 'option', 'rc' );

      var done = grunt.task.current.async();

      deployUtil.commitAndPushDependenciesJSON( grunt, function() {
        deployProduction( grunt, done );
      } );
    }
  );

  grunt.registerTask( 'lint', 'lint js files that are specific to this repository', [ 'eslint:repoFiles' ] );

  grunt.registerTask( 'lint-all', 'lint all js files that are required to build this repository', [ 'eslint:allFiles' ] );

  grunt.registerTask( 'clean',
    'Erases the build/ directory and all its contents, and recreates the build/ directory',
    function() {
      if ( grunt.file.exists( 'build' ) ) {
        grunt.file.delete( 'build' );
      }
      grunt.file.mkdir( 'build' );
    } );

  grunt.registerTask( 'after-requirejs-build',
    '(internal use only) Do things after the requirejs:build task',
    function() {
      afterRequirejsBuild( grunt, buildConfig );
    } );

  //---------------------------------------------------------------------------------------------------------------
  // Utility tasks
  //---------------------------------------------------------------------------------------------------------------

  grunt.registerTask( 'checkout-shas',
    'Check out shas for a project, as specified in dependencies.json',
    function() {
      checkoutShas( grunt, buildConfig.name, false /* toMaster */ );
    } );

  grunt.registerTask( 'checkout-master',
    'Check out master branch for all dependencies, as specified in dependencies.json',
    function() {
      checkoutShas( grunt, buildConfig.name, true /* toMaster */ );
    } );

  grunt.registerTask( 'create-sim',
    'Creates a sim based on the simula-rasa template.\n' +
    '--name="string" : the repository name\n' +
    '--author="string" : the author name\n' +
    '--title="string" : (optional) the simulation title\n' +
    '--clean=true : (optional) deletes the repository directory if it exists',
    function() {
      createSim( grunt );
    } );

  // See reportMedia.js
  grunt.registerTask( 'report-media',
    '(project-wide) Report on license.json files throughout all working copies. ' +
    'Reports any media (such as images or audio) files that have any of the following problems:\n' +
    '(1) incompatible-license (resource license not approved)\n' +
    '(2) not-annotated (license.json missing or entry missing from license.json)\n' +
    '(3) missing-file (entry in the license.json but not on the file system)',
    function() {
      reportMedia( grunt );
    } );

  // see reportThirdParty.js
  grunt.registerTask( 'report-third-party',
    'This task is used to create a report of third-party resources (code, ' +
    'images, audio, etc) used in a set of PhET simulations by reading the ' +
    'license information in built HTML files.\n' +
    '--input (required argument) the path to the directory containing HTML ' +
    'files which will be reported on.\n' +
    '--output (required argument) the path to a file where the report should be ' +
    'written. The file is in markdown syntax and the *.md suffix is ' +
    'recommended. This will silently overwrite an existing file, if there is ' +
    'one.\n' +
    '--active-runnables (optional, default to false) If true, ' +
    'the task iterates over the active-runnables and copies each ' +
    'built HTML file into the directory specified with --input before ' +
    'running the report. If any HTML files are missing, the report will fail. ' +
    'Before using this flag, the developer should run `grunt-all.sh` to make ' +
    'sure all of the HTML files are up-to-date. The directory is neither ' +
    'automatically created nor automatically cleaned, this is the ' +
    'responsibility of the developer. (Note that if you fail to manually ' +
    'clean the directory, you may end up with stale HTML files).',
    function() {
      reportThirdParty( grunt );
    } );

  grunt.registerTask( 'published-README',
    'Generates README.md file for a published simulation.',
    function() {
      assert( buildConfig.simTitleStringKey, 'missing buildConfig.simTitleStringKey' );
      generateREADME( grunt, buildConfig.name, buildConfig.phetLibs, buildConfig.simTitleStringKey, true /* published */ );
    } );

  grunt.registerTask( 'unpublished-README',
    'Generates README.md file for an unpublished simulation.',
    function() {
      assert( buildConfig.simTitleStringKey, 'missing buildConfig.simTitleStringKey' );
      generateREADME( grunt, buildConfig.name, buildConfig.phetLibs, buildConfig.simTitleStringKey, false /* published */ );
    } );

  grunt.registerTask( 'generate-thumbnails', 'Generate 128x84 and 600x394 thumbnails to be used on the website.',
    function() {
      var finished = _.after( 2, grunt.task.current.async() );
      generateThumbnails( grunt, buildConfig.name, 128, 84, finished );
      generateThumbnails( grunt, buildConfig.name, 600, 394, finished );
    } );

  grunt.registerTask( 'generate-development-html',
    'Generates top-level SIM_en.html file based on the preloads in package.json.',
    function() {
      generateDevelopmentHTML( grunt, buildConfig );
    } );

  grunt.registerTask( 'commits-since',
    'Shows commits since a specified date. Use --date=\<date\> to specify the date.',
    function() {
      commitsSince( grunt, buildConfig );
    } );

  grunt.registerTask( 'update-phet-io-site',
    'Copy the phet-io-site docs and materials from phet-io/phet-io-site to phet-io-site',
    function() {
      updatePhETiOSite( grunt, buildConfig );
    } );

  grunt.registerTask( 'phet-io',
    'Full PhET-iO build including phet version, phet-io version and accompanying material',
    function() {
      phetIO( grunt, buildConfig );
    } );

  /*
   * Load tasks from grunt plugins that have been installed locally using npm.
   * Put these in package.json and run 'npm install' before running grunt.
   */
  grunt.loadNpmTasks( 'grunt-requirejs' );
};
<commit_msg>Removed unused reference<commit_after>// Copyright 2013-2015, University of Colorado Boulder

/**
 * Grunt configuration file for PhET projects.
 * Tasks share information via global.phet, see individual tasks for details.
 *
 * @author Chris Malley (PixelZoom, Inc.)
 * @author Jon Olson
 * @author Sam Reid
 * @author John Blanco
 */

// use process.env
/* jslint node: true */

// built-in node APIs
var assert = require( 'assert' );
var fs = require( 'fs' );

// 3rd-party packages
var _ = require( '../../../sherpa/lib/lodash-2.4.1.min' ); // eslint-disable-line require-statement-match

// PhET custom grunt tasks
var afterRequirejsBuild = require( '../../../chipper/js/grunt/afterRequirejsBuild' );
var checkoutShas = require( '../../../chipper/js/grunt/checkoutShas' );
var commitsSince = require( '../../../chipper/js/grunt/commitsSince' );
var createSim = require( '../../../chipper/js/grunt/createSim' );
var deployProduction = require( '../../../chipper/js/grunt/deployProduction' );
var deployDev = require( '../../../chipper/js/grunt/deployDev' );
var deployUtil = require( '../../../chipper/js/grunt/deployUtil' );
var generateDevelopmentHTML = require( '../../../chipper/js/grunt/generateDevelopmentHTML' );
var generateREADME = require( '../../../chipper/js/grunt/generateREADME' );
var generateThumbnails = require( '../../../chipper/js/grunt/generateThumbnails' );
var reportMedia = require( '../../../chipper/js/grunt/reportMedia' );
var reportThirdParty = require( '../../../chipper/js/grunt/reportThirdParty' );
var getBuildConfig = require( '../../../chipper/js/grunt/getBuildConfig' );
var getGruntConfig = require( '../../../chipper/js/grunt/getGruntConfig' );
var updateCopyrightDates = require( '../../../chipper/js/grunt/updateCopyrightDates' );
var updatePhETiOSite = require( '../../../chipper/js/grunt/updatePhETiOSite' );
var phetIO = require( '../../../chipper/js/grunt/phetIO' );

module.exports = function( grunt ) {
  'use strict';

  // For eslint
  require( 'load-grunt-tasks' )( grunt );

  //---------------------------------------------------------------------------------------------------------------
  // Configuration

  var buildConfig = getBuildConfig( grunt );

  // Initialize and document all globals
  assert( !global.phet, 'global.phet already exists' );
  global.phet = {

    chipper: {

      // the grunt instance, for situations where we can't pass it as a function argument
      grunt: grunt,

      // for code that runs in both requirejs and build modes, and therefore doesn't have access to grunt.file
      fs: fs,

      // polyfill to work around the cache buster arg in the *-config.js file that all sims have.
      getCacheBusterArgs: function() { return ''; },

      // media plugins populate this with license.json entries, see getLicenseEntry.js for format of entries
      licenseEntries: {},

      // use by media plugins, which don't have access to buildConfig
      brand: buildConfig.brand,

      // populated by mipmap.js
      mipmapsToBuild: [],

      // populated by string.js
      strings: {}
    }
  };

  // Initialize grunt
  grunt.initConfig( getGruntConfig( grunt, buildConfig.name, buildConfig.phetLibs ) );

  //---------------------------------------------------------------------------------------------------------------
  // Primary tasks
  //---------------------------------------------------------------------------------------------------------------

  // Default task ('grunt')

  grunt.registerTask( 'default', 'Builds the English HTML', [ 'build' ] );

  // Add the linting step as an pre-build step.  Can be skipped with --lint=false
  var optionalTasks = [];
  if ( grunt.option( 'lint' ) === false ) {

    // do nothing
  }
  else {
    optionalTasks.push( 'lint-all' );
  }

  var additionalTasks = [
    'clean',
    'requirejs:build',
    'after-requirejs-build'
  ];

  grunt.registerTask( 'build',
    'Builds the simulation:\n' +
    'with no options, builds HTML for English only\n' +
    '--locales=* : all locales in strings/ directory\n' +
    '--locales=fr : French\n' +
    '--locales=ar,fr,es : Arabic, French and Spanish (comma separated locales)\n' +
    '--localesRepo=$repo : all locales in another repository\'s strings/ directory, ignored if --locales is present\n' +
    '--brand=$brand : build a specific brand. Choices are phet, phet-io, adapted-from-phet (default)\n' +
    '--lint=false : skip the lint sub-task\n' +
    '--mangle=false : skip the mangling portion of UglifyJS2, and beautify the output\n' +
    '--uglify=false : skip the UglifyJS2 step altogether\n' +
    '--chromeWebStore : Output additional files that can be deployed to the Chrome Web Store',
    optionalTasks.concat( additionalTasks )
  );

  grunt.registerTask( 'build-for-server', 'meant for use by build-server only',
    [ 'build', 'generate-thumbnails' ]
  );

  // Grunt task that determines created and last modified dates from git, and
  // updates copyright statements accordingly, see #403
  grunt.registerTask( 'update-copyright-dates', 'Update the copyright dates in JS source files based on Github dates',
    function() {
      updateCopyrightDates( grunt, buildConfig );
    } );

  grunt.registerTask( 'deploy-production',
    'Invoke deployDev and then deploy a simulation to the production server.\n' +
    'Should be run AFTER grunt build since it uses the shas from dependencies.json in the build directory.\n' +
    'Deploys to figaro by default, but simian can be used for testing by setting:\n' +
    '"productionServerName": "simian.colorado.edu" and "productionServerURL": "https://phet-dev.colorado.edu" in build-local.json\n' +
    '--noDev : if true, deploy to production only, not spot as well. Useful for testing\n' +
    '--email : optionally enter an email to be notified if the build fails or succeeds (overrides buildServerNotifyEmail in build-locale.json)\n' +
    '--locales=* : all locales that have been published so far. NOTE: for sims published after 11/9/15, this is the ' +
    'default option, otherwise it must be explicitly passed to republish all translations.\n' +
    '--locales=fr : French\n' +
    '--locales=ar,fr,es : Arabic, French and Spanish (comma separated locales)',
    function() {
      // before invoking the build-server, do a dev deploy, including committing and pushing to github
      var done = grunt.task.current.async();
      if ( grunt.option( 'noDev' ) ) {
        deployProduction( grunt, done );
      }
      else {
        deployDev( grunt, function() {
          deployProduction( grunt, done );
        } );
      }
    }
  );

  grunt.registerTask( 'deploy-dev',
    'Deploy a dev version to spot, or optionally to the server in your preferences file\n' +
    '--mkdir : set to true to create the sim dir and .htaccess file before copying the version directory\n' +
    '--test : set to true to disable commit and push, and SCP to a test directory on spot',
    function() {
      deployDev( grunt );
    }
  );

  grunt.registerTask( 'deploy-rc',
    'Deploy a rc version to spot using the build server.\n' +
    'Behaves identically to grunt deploy-dev, except the sim is rebuilt and deployed from the build-server instead of locally.\n' +
    'This is useful to ensure that the rc version is built in the same environment as our production deploys',
    function() {
      grunt.option( 'noDev', true );
      grunt.option( 'option', 'rc' );

      var done = grunt.task.current.async();

      deployUtil.commitAndPushDependenciesJSON( grunt, function() {
        deployProduction( grunt, done );
      } );
    }
  );

  grunt.registerTask( 'lint', 'lint js files that are specific to this repository', [ 'eslint:repoFiles' ] );

  grunt.registerTask( 'lint-all', 'lint all js files that are required to build this repository', [ 'eslint:allFiles' ] );

  grunt.registerTask( 'clean',
    'Erases the build/ directory and all its contents, and recreates the build/ directory',
    function() {
      if ( grunt.file.exists( 'build' ) ) {
        grunt.file.delete( 'build' );
      }
      grunt.file.mkdir( 'build' );
    } );

  grunt.registerTask( 'after-requirejs-build',
    '(internal use only) Do things after the requirejs:build task',
    function() {
      afterRequirejsBuild( grunt, buildConfig );
    } );

  //---------------------------------------------------------------------------------------------------------------
  // Utility tasks
  //---------------------------------------------------------------------------------------------------------------

  grunt.registerTask( 'checkout-shas',
    'Check out shas for a project, as specified in dependencies.json',
    function() {
      checkoutShas( grunt, buildConfig.name, false /* toMaster */ );
    } );

  grunt.registerTask( 'checkout-master',
    'Check out master branch for all dependencies, as specified in dependencies.json',
    function() {
      checkoutShas( grunt, buildConfig.name, true /* toMaster */ );
    } );

  grunt.registerTask( 'create-sim',
    'Creates a sim based on the simula-rasa template.\n' +
    '--name="string" : the repository name\n' +
    '--author="string" : the author name\n' +
    '--title="string" : (optional) the simulation title\n' +
    '--clean=true : (optional) deletes the repository directory if it exists',
    function() {
      createSim( grunt );
    } );

  // See reportMedia.js
  grunt.registerTask( 'report-media',
    '(project-wide) Report on license.json files throughout all working copies. ' +
    'Reports any media (such as images or audio) files that have any of the following problems:\n' +
    '(1) incompatible-license (resource license not approved)\n' +
    '(2) not-annotated (license.json missing or entry missing from license.json)\n' +
    '(3) missing-file (entry in the license.json but not on the file system)',
    function() {
      reportMedia( grunt );
    } );

  // see reportThirdParty.js
  grunt.registerTask( 'report-third-party',
    'This task is used to create a report of third-party resources (code, ' +
    'images, audio, etc) used in a set of PhET simulations by reading the ' +
    'license information in built HTML files.\n' +
    '--input (required argument) the path to the directory containing HTML ' +
    'files which will be reported on.\n' +
    '--output (required argument) the path to a file where the report should be ' +
    'written. The file is in markdown syntax and the *.md suffix is ' +
    'recommended. This will silently overwrite an existing file, if there is ' +
    'one.\n' +
    '--active-runnables (optional, default to false) If true, ' +
    'the task iterates over the active-runnables and copies each ' +
    'built HTML file into the directory specified with --input before ' +
    'running the report. If any HTML files are missing, the report will fail. ' +
    'Before using this flag, the developer should run `grunt-all.sh` to make ' +
    'sure all of the HTML files are up-to-date. The directory is neither ' +
    'automatically created nor automatically cleaned, this is the ' +
    'responsibility of the developer. (Note that if you fail to manually ' +
    'clean the directory, you may end up with stale HTML files).',
    function() {
      reportThirdParty( grunt );
    } );

  grunt.registerTask( 'published-README',
    'Generates README.md file for a published simulation.',
    function() {
      assert( buildConfig.simTitleStringKey, 'missing buildConfig.simTitleStringKey' );
      generateREADME( grunt, buildConfig.name, buildConfig.phetLibs, buildConfig.simTitleStringKey, true /* published */ );
    } );

  grunt.registerTask( 'unpublished-README',
    'Generates README.md file for an unpublished simulation.',
    function() {
      assert( buildConfig.simTitleStringKey, 'missing buildConfig.simTitleStringKey' );
      generateREADME( grunt, buildConfig.name, buildConfig.phetLibs, buildConfig.simTitleStringKey, false /* published */ );
    } );

  grunt.registerTask( 'generate-thumbnails', 'Generate 128x84 and 600x394 thumbnails to be used on the website.',
    function() {
      var finished = _.after( 2, grunt.task.current.async() );
      generateThumbnails( grunt, buildConfig.name, 128, 84, finished );
      generateThumbnails( grunt, buildConfig.name, 600, 394, finished );
    } );

  grunt.registerTask( 'generate-development-html',
    'Generates top-level SIM_en.html file based on the preloads in package.json.',
    function() {
      generateDevelopmentHTML( grunt, buildConfig );
    } );

  grunt.registerTask( 'commits-since',
    'Shows commits since a specified date. Use --date=\<date\> to specify the date.',
    function() {
      commitsSince( grunt, buildConfig );
    } );

  grunt.registerTask( 'update-phet-io-site',
    'Copy the phet-io-site docs and materials from phet-io/phet-io-site to phet-io-site',
    function() {
      updatePhETiOSite( grunt, buildConfig );
    } );

  grunt.registerTask( 'phet-io',
    'Full PhET-iO build including phet version, phet-io version and accompanying material',
    function() {
      phetIO( grunt, buildConfig );
    } );

  /*
   * Load tasks from grunt plugins that have been installed locally using npm.
   * Put these in package.json and run 'npm install' before running grunt.
   */
  grunt.loadNpmTasks( 'grunt-requirejs' );
};
<|endoftext|>


<commit_before>// Copyright 2002-2014, University of Colorado Boulder

/**
 * General constants for Fraction Matcher.  While constants, they are extended by MixedNumberConstants, so they should be instantiated
 * like instance objects.  See https://github.com/phetsims/fraction-matcher/issues/43
 *
 * @author Andrey Zelenkov (Mlearner)
 */
define( function( require ) {
  'use strict';

  // modules
  var FILL_TYPE = require( 'FRACTION_MATCHER/model/FillType' );
  var Fraction = require( 'PHETCOMMON/model/Fraction' );

  //colors
  var COLORS = {
    LIGHT_GREEN: 'rgb(140,198,63)',
    LIGHT_BLUE: '#6acef5',//to match the PhET Logo
    LIGHT_RED: 'rgb(233,69,69)',
    LIGHT_PINK: 'rgb(255,175,175)',
    ORANGE: 'rgb(255,200,0)',
    YELLOW: '#f2e916',//to match the PhET Logo
    GREEN: 'rgb(0,255,0)',
    PINK: 'rgb(255,0,255)'
  };
  COLORS.CIRCLE_COLOR = COLORS.LIGHT_GREEN;
  COLORS.HORIZONTAL_SLICE_COLOR = COLORS.LIGHT_RED;
  COLORS.VERTICAL_SLICE_COLOR = COLORS.LIGHT_BLUE;
  COLORS.NUMBER_LINE = COLORS.LIGHT_GREEN;

  //list of all possible shapes
  var SHAPES = [ 'PIES', 'HORIZONTAL_BARS', 'VERTICAL_BARS', 'PLUSES', 'GRID', 'PYRAMID', 'POLYGON', 'TETRIS', 'FLOWER', 'LETTER_L_SHAPES', 'INTERLEAVED_L_SHAPES', 'RING_OF_HEXAGONS', 'NINJA_STAR' ];

  function Constants() {
    // color constants
    this.COLORS = COLORS;

    // shapes type constants
    this.SHAPES = SHAPES;

    this.LEVEL_DESCRIPTION = [
    /**
     * Level 1
     * No mixed numbers
     * Only “exact” matches will be present. So for instance if there is a 3/6  and a pie with 6 divisions and 3 shaded slices, there will not be a ½  present .  In other words, the numerical representation on this level will exactly match the virtual manipulative.
     * Only numbers/representations ≦ 1 possible on this level
     * “Easy” shapes on this level (not some of the more abstract representations)
     */
      {
        fractions: [
          new Fraction( 1, 2 ),
          new Fraction( 1, 3 ),
          new Fraction( 2, 3 ),
          new Fraction( 1, 4 ),
          new Fraction( 3, 4 ),
          new Fraction( 1, 1 )
        ],
        numericScaleFactors: [ 1 ],
        fillType: [ FILL_TYPE.SEQUENTIAL ],
        shapes: SHAPES.slice( 0, 3 )
      },
    /**
     * Level 2
     * Reduced fractions possible on this level. So, for instance 3/6 and ½  could both be present.  Or a virtual representation of 3/6 could have the numerical of ½ be its only possible match
     * Still only numbers/representations ≦ 1 possible
     * More shapes can be introduced
     */
      {
        fractions: [
          new Fraction( 1, 2 ),
          new Fraction( 1, 3 ),
          new Fraction( 2, 3 ),
          new Fraction( 2, 4 ),
          new Fraction( 3, 4 ),
          new Fraction( 2, 6 ),
          new Fraction( 3, 6 )
        ],
        numericScaleFactors: [ 1 ],
        fillType: [ FILL_TYPE.SEQUENTIAL ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 3:
     * Reduced fractions possible on this level. So, for instance 3/6 and ½  could both be present.  Or a virtual representation of 3/6 could have the numerical of ½ be its only possible match
     * Still only numbers/representations ≦ 1 possible
     * More shapes can be introduced
     */
      {
        fractions: [
          new Fraction( 3, 2 ),
          new Fraction( 4, 3 ),
          new Fraction( 5, 4 ),
          new Fraction( 6, 4 ),
          new Fraction( 7, 4 ),
          new Fraction( 4, 5 ),
          new Fraction( 2, 6 ),
          new Fraction( 3, 6 ),
          new Fraction( 4, 6 ),
          new Fraction( 5, 6 ),
          new Fraction( 7, 6 ),
          new Fraction( 3, 8 ),
          new Fraction( 4, 8 ),
          new Fraction( 5, 8 ),
          new Fraction( 6, 8 ),
          new Fraction( 7, 8 )
        ],
        numericScaleFactors: [ 1 ],
        fillType: [ FILL_TYPE.SEQUENTIAL ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 4:
     * All representations possible as well as complicated mixed/improper numbers
     */
      {
        fractions: [
          new Fraction( 13, 7 ),
          new Fraction( 13, 7 ),
          new Fraction( 6, 3 ),
          new Fraction( 9, 5 ),
          new Fraction( 9, 7 ),
          new Fraction( 9, 8 ),
          new Fraction( 14, 8 ),
          new Fraction( 2, 9 ),
          new Fraction( 3, 9 ),
          new Fraction( 4, 9 ),
          new Fraction( 6, 9 ),
          new Fraction( 8, 9 )
        ],
        numericScaleFactors: [ 1, 2 ],
        fillType: [ FILL_TYPE.SEQUENTIAL ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 5:
     * All representations possible as well as complicated mixed/improper numbers.  Same fractions as level 4 but different representations.
     */
      {
        fractions: [
          new Fraction( 13, 7 ),
          new Fraction( 13, 7 ),
          new Fraction( 6, 3 ),
          new Fraction( 9, 5 ),
          new Fraction( 9, 7 ),
          new Fraction( 9, 8 ),
          new Fraction( 14, 8 ),
          new Fraction( 2, 9 ),
          new Fraction( 3, 9 ),
          new Fraction( 4, 9 ),
          new Fraction( 6, 9 ),
          new Fraction( 8, 9 )
        ],
        numericScaleFactors: [ 1, 2, 3 ],
        fillType: [ FILL_TYPE.SEQUENTIAL, FILL_TYPE.MIXED ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 6:
     * All representations possible as well as complicated mixed/improper numbers
     */
      {
        fractions: [
          new Fraction( 6, 5 ),
          new Fraction( 7, 5 ),
          new Fraction( 8, 5 ),
          new Fraction( 9, 5 ),
          new Fraction( 7, 6 ),
          new Fraction( 8, 6 ),
          new Fraction( 9, 6 ),
          new Fraction( 9, 7 ),
          new Fraction( 10, 7 ),
          new Fraction( 13, 7 ),
          new Fraction( 9, 8 ),
          new Fraction( 10, 8 ),
          new Fraction( 11, 8 ),
          new Fraction( 14, 8 ),
          new Fraction( 4, 9 ),
          new Fraction( 6, 9 ),
          new Fraction( 8, 9 ),
          new Fraction( 10, 9 ),
          new Fraction( 11, 9 )
        ],
        numericScaleFactors: [ 1, 4, 5 ],
        fillType: [ FILL_TYPE.SEQUENTIAL, FILL_TYPE.RANDOM ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 7:
     * All representations possible as well as complicated mixed/improper numbers
     */
      {
        fractions: [
          new Fraction( 3, 2 ),
          new Fraction( 4, 3 ),
          new Fraction( 5, 3 ),
          new Fraction( 5, 4 ),
          new Fraction( 7, 4 ),
          new Fraction( 6, 5 ),
          new Fraction( 7, 5 ),
          new Fraction( 8, 5 ),
          new Fraction( 9, 5 ),
          new Fraction( 7, 6 ),
          new Fraction( 11, 6 )
        ],
        numericScaleFactors: [ 1, 6, 7 ],
        fillType: [ FILL_TYPE.SEQUENTIAL, FILL_TYPE.RANDOM ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 8:
     * All representations possible as well as complicated mixed/improper numbers
     */
      {
        fractions: [
          new Fraction( 8, 7 ),
          new Fraction( 9, 7 ),
          new Fraction( 10, 7 ),
          new Fraction( 11, 7 ),
          new Fraction( 12, 7 ),
          new Fraction( 13, 7 ),
          new Fraction( 9, 8 ),
          new Fraction( 10, 8 ),
          new Fraction( 11, 8 ),
          new Fraction( 12, 8 ),
          new Fraction( 13, 8 ),
          new Fraction( 14, 8 ),
          new Fraction( 15, 8 ),
          new Fraction( 10, 9 ),
          new Fraction( 11, 9 ),
          new Fraction( 12, 9 ),
          new Fraction( 13, 9 ),
          new Fraction( 14, 9 ),
          new Fraction( 15, 9 ),
          new Fraction( 16, 9 ),
          new Fraction( 17, 9 )
        ],
        numericScaleFactors: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
        fillType: [ FILL_TYPE.SEQUENTIAL, FILL_TYPE.RANDOM ],
        shapes: SHAPES.slice( 0 )
      }
    ];
  }

  return Constants;
} );<commit_msg>Fixed require var names, see https://github.com/phetsims/chipper/issues/195<commit_after>// Copyright 2002-2014, University of Colorado Boulder

/**
 * General constants for Fraction Matcher.  While constants, they are extended by MixedNumberConstants, so they should be instantiated
 * like instance objects.  See https://github.com/phetsims/fraction-matcher/issues/43
 *
 * @author Andrey Zelenkov (Mlearner)
 */
define( function( require ) {
  'use strict';

  // modules
  var FillType = require( 'FRACTION_MATCHER/model/FillType' );
  var Fraction = require( 'PHETCOMMON/model/Fraction' );

  //colors
  var COLORS = {
    LIGHT_GREEN: 'rgb(140,198,63)',
    LIGHT_BLUE: '#6acef5',//to match the PhET Logo
    LIGHT_RED: 'rgb(233,69,69)',
    LIGHT_PINK: 'rgb(255,175,175)',
    ORANGE: 'rgb(255,200,0)',
    YELLOW: '#f2e916',//to match the PhET Logo
    GREEN: 'rgb(0,255,0)',
    PINK: 'rgb(255,0,255)'
  };
  COLORS.CIRCLE_COLOR = COLORS.LIGHT_GREEN;
  COLORS.HORIZONTAL_SLICE_COLOR = COLORS.LIGHT_RED;
  COLORS.VERTICAL_SLICE_COLOR = COLORS.LIGHT_BLUE;
  COLORS.NUMBER_LINE = COLORS.LIGHT_GREEN;

  //list of all possible shapes
  var SHAPES = [ 'PIES', 'HORIZONTAL_BARS', 'VERTICAL_BARS', 'PLUSES', 'GRID', 'PYRAMID', 'POLYGON', 'TETRIS', 'FLOWER', 'LETTER_L_SHAPES', 'INTERLEAVED_L_SHAPES', 'RING_OF_HEXAGONS', 'NINJA_STAR' ];

  function Constants() {
    // color constants
    this.COLORS = COLORS;

    // shapes type constants
    this.SHAPES = SHAPES;

    this.LEVEL_DESCRIPTION = [
    /**
     * Level 1
     * No mixed numbers
     * Only “exact” matches will be present. So for instance if there is a 3/6  and a pie with 6 divisions and 3 shaded slices, there will not be a ½  present .  In other words, the numerical representation on this level will exactly match the virtual manipulative.
     * Only numbers/representations ≦ 1 possible on this level
     * “Easy” shapes on this level (not some of the more abstract representations)
     */
      {
        fractions: [
          new Fraction( 1, 2 ),
          new Fraction( 1, 3 ),
          new Fraction( 2, 3 ),
          new Fraction( 1, 4 ),
          new Fraction( 3, 4 ),
          new Fraction( 1, 1 )
        ],
        numericScaleFactors: [ 1 ],
        fillType: [ FillType.SEQUENTIAL ],
        shapes: SHAPES.slice( 0, 3 )
      },
    /**
     * Level 2
     * Reduced fractions possible on this level. So, for instance 3/6 and ½  could both be present.  Or a virtual representation of 3/6 could have the numerical of ½ be its only possible match
     * Still only numbers/representations ≦ 1 possible
     * More shapes can be introduced
     */
      {
        fractions: [
          new Fraction( 1, 2 ),
          new Fraction( 1, 3 ),
          new Fraction( 2, 3 ),
          new Fraction( 2, 4 ),
          new Fraction( 3, 4 ),
          new Fraction( 2, 6 ),
          new Fraction( 3, 6 )
        ],
        numericScaleFactors: [ 1 ],
        fillType: [ FillType.SEQUENTIAL ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 3:
     * Reduced fractions possible on this level. So, for instance 3/6 and ½  could both be present.  Or a virtual representation of 3/6 could have the numerical of ½ be its only possible match
     * Still only numbers/representations ≦ 1 possible
     * More shapes can be introduced
     */
      {
        fractions: [
          new Fraction( 3, 2 ),
          new Fraction( 4, 3 ),
          new Fraction( 5, 4 ),
          new Fraction( 6, 4 ),
          new Fraction( 7, 4 ),
          new Fraction( 4, 5 ),
          new Fraction( 2, 6 ),
          new Fraction( 3, 6 ),
          new Fraction( 4, 6 ),
          new Fraction( 5, 6 ),
          new Fraction( 7, 6 ),
          new Fraction( 3, 8 ),
          new Fraction( 4, 8 ),
          new Fraction( 5, 8 ),
          new Fraction( 6, 8 ),
          new Fraction( 7, 8 )
        ],
        numericScaleFactors: [ 1 ],
        fillType: [ FillType.SEQUENTIAL ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 4:
     * All representations possible as well as complicated mixed/improper numbers
     */
      {
        fractions: [
          new Fraction( 13, 7 ),
          new Fraction( 13, 7 ),
          new Fraction( 6, 3 ),
          new Fraction( 9, 5 ),
          new Fraction( 9, 7 ),
          new Fraction( 9, 8 ),
          new Fraction( 14, 8 ),
          new Fraction( 2, 9 ),
          new Fraction( 3, 9 ),
          new Fraction( 4, 9 ),
          new Fraction( 6, 9 ),
          new Fraction( 8, 9 )
        ],
        numericScaleFactors: [ 1, 2 ],
        fillType: [ FillType.SEQUENTIAL ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 5:
     * All representations possible as well as complicated mixed/improper numbers.  Same fractions as level 4 but different representations.
     */
      {
        fractions: [
          new Fraction( 13, 7 ),
          new Fraction( 13, 7 ),
          new Fraction( 6, 3 ),
          new Fraction( 9, 5 ),
          new Fraction( 9, 7 ),
          new Fraction( 9, 8 ),
          new Fraction( 14, 8 ),
          new Fraction( 2, 9 ),
          new Fraction( 3, 9 ),
          new Fraction( 4, 9 ),
          new Fraction( 6, 9 ),
          new Fraction( 8, 9 )
        ],
        numericScaleFactors: [ 1, 2, 3 ],
        fillType: [ FillType.SEQUENTIAL, FillType.MIXED ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 6:
     * All representations possible as well as complicated mixed/improper numbers
     */
      {
        fractions: [
          new Fraction( 6, 5 ),
          new Fraction( 7, 5 ),
          new Fraction( 8, 5 ),
          new Fraction( 9, 5 ),
          new Fraction( 7, 6 ),
          new Fraction( 8, 6 ),
          new Fraction( 9, 6 ),
          new Fraction( 9, 7 ),
          new Fraction( 10, 7 ),
          new Fraction( 13, 7 ),
          new Fraction( 9, 8 ),
          new Fraction( 10, 8 ),
          new Fraction( 11, 8 ),
          new Fraction( 14, 8 ),
          new Fraction( 4, 9 ),
          new Fraction( 6, 9 ),
          new Fraction( 8, 9 ),
          new Fraction( 10, 9 ),
          new Fraction( 11, 9 )
        ],
        numericScaleFactors: [ 1, 4, 5 ],
        fillType: [ FillType.SEQUENTIAL, FillType.RANDOM ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 7:
     * All representations possible as well as complicated mixed/improper numbers
     */
      {
        fractions: [
          new Fraction( 3, 2 ),
          new Fraction( 4, 3 ),
          new Fraction( 5, 3 ),
          new Fraction( 5, 4 ),
          new Fraction( 7, 4 ),
          new Fraction( 6, 5 ),
          new Fraction( 7, 5 ),
          new Fraction( 8, 5 ),
          new Fraction( 9, 5 ),
          new Fraction( 7, 6 ),
          new Fraction( 11, 6 )
        ],
        numericScaleFactors: [ 1, 6, 7 ],
        fillType: [ FillType.SEQUENTIAL, FillType.RANDOM ],
        shapes: SHAPES.slice( 0 )
      },
    /**
     * Level 8:
     * All representations possible as well as complicated mixed/improper numbers
     */
      {
        fractions: [
          new Fraction( 8, 7 ),
          new Fraction( 9, 7 ),
          new Fraction( 10, 7 ),
          new Fraction( 11, 7 ),
          new Fraction( 12, 7 ),
          new Fraction( 13, 7 ),
          new Fraction( 9, 8 ),
          new Fraction( 10, 8 ),
          new Fraction( 11, 8 ),
          new Fraction( 12, 8 ),
          new Fraction( 13, 8 ),
          new Fraction( 14, 8 ),
          new Fraction( 15, 8 ),
          new Fraction( 10, 9 ),
          new Fraction( 11, 9 ),
          new Fraction( 12, 9 ),
          new Fraction( 13, 9 ),
          new Fraction( 14, 9 ),
          new Fraction( 15, 9 ),
          new Fraction( 16, 9 ),
          new Fraction( 17, 9 )
        ],
        numericScaleFactors: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
        fillType: [ FillType.SEQUENTIAL, FillType.RANDOM ],
        shapes: SHAPES.slice( 0 )
      }
    ];
  }

  return Constants;
} );<|endoftext|>


<commit_before>/**
 * install : Object -> Function
 * @description
 * Constructs the install function for the SW
 *
 * @param {object} opts
 * @param {string} opts.name      REQUIRED: The name of the app
 * @param {number} opts.version   The version number of the cache
 * @param {array}  opts.items     The urls to cache
 */
const install = (opts = {}) => {
  let { name, version, items } = opts;
  if (!name) {
    throw TypeError('Missing required parameter: name');
  }
  items = (!items) ? ['/'] : items;
  version = (version !== 0 && !version) ? 0 : version;

  const cacheName = `${name}-v${version}`;

  console.log(cacheName);

  return (event) => {
    console.log(`Installing SW: ${cacheName}`);
    event.waitUntil(
      caches.open(cacheName).then(cache => cache.addAll(items))
    );
  };
};

export default install;

<commit_msg>configures an indexedDB database on install<commit_after>import localforage from 'localforage';

/**
 * install : Object -> Function
 * @description
 * Constructs the install function for the SW
 *
 * @param {object} opts
 * @param {string} opts.name      REQUIRED: The name of the app
 * @param {number} opts.version   The version number of the cache
 * @param {array}  opts.items     The urls to cache
 */
const install = (opts = {}) => {
  let { name, version, items } = opts;
  if (!name) {
    throw TypeError('Missing required parameter: name');
  }
  items = (!items) ? ['/'] : items;
  version = (version !== 0 && !version) ? 0 : version;

  const cacheName = `${name}-v${version}`;

  return (event) => {
    console.log(`Installing SW: ${cacheName}`);
    // config is a synchronous event
    localforage.config({name, version, driver: localforage.INDEXEDDB});
    event.waitUntil(
      caches.open(cacheName).then(cache => cache.addAll(items))
    );
  };
};

export default install;

<|endoftext|>


<commit_before>"use strict";

/*global module, require*/

var matchNone = /(?!)/,
    matchEmpty = /$^/;

/*
 Helper functions for producing valid button specifications. We pass these to the menu object, which display them for us.

 The reason for these functions is to provide defaults for the optional arguments, and to check the types of things supplied by the user.
 */
module.exports = function(defaultCollection) {
    var checkState = function(o, props) {
	props.forEach(function(p) {
	    if (o[p] === undefined) {
		throw new Error("Missing property " + p + " had " + Object.keys(o));
	    }

	    if (typeof(o[p]) !== 'boolean') {
		throw new Error("Property " + p + " should be a boolean, was: " + o[p]);
	    }
	});
    };

    /*
     states should be an object.

     We are checking for 3 properties: onlineOffline, readWriteSync and embeddedStandalone. Each of these represents a dimension of the state-space of the menu. If any are missing, the button will be displayed regardless of the state of the dimension.

     Each of these should be a subobject containing true/false sub-properties detailing which states the button should display in.
     */
    var checkStates = function(states) {
	if (!states.onlineOffline) {
	    states.onlineOffline = {
		online: true,
		offline: true
	    };
	} else {
	    checkState(states.onlineOffline, ['online', 'offline']);
	}

	if (!states.readWriteSync) {
	    states.readWriteSync = {
		untitled: true,
		read: true,
		write: true,
		sync: true
	    };
	} else {
	    checkState(states.readWriteSync, ['read', 'write', 'sync']);
	}

	if (!states.embeddedStandalone) {
	    states.embeddedStandalone = {
		embedded: true,
		standalone: true
	    };
	} else {
	    checkState(states.embeddedStandalone, ['embedded', 'standalone']);
	}
    };

    /*
     Produces a search object to be passed to the button. When this button is clicked, it will produce a search box.

     Takes an options object with the following properties:

     collection is optional, and should be a string. This is the Mongo collection which this search will look in. If not specified, we'll use the default collection instead.

     excludeTerms is optional, and should be a regex. If this is specified, any search terms the user types which match that regex will not trigger a search

     includeSearchTerm is optional, and should be a boolean. If this is specified, the search term will always be included in the results, even if it wasn't found in the search. In this case, it will get a different CSS class (.search-result-fabricated) added to it.
     */
    var checkSearch = function(options) {
	if (!options.collection) {
	    options.collection = defaultCollection;
	} else if (typeof(options.collection) !== "string") {
	    throw new Error("If collection is specified, it should be a string, was: " + options.collection);
	}

	if (!options.excludeTerms) {
	    options.excludeTerms = matchNone;

	} else if (!options.excludeTerms.test) {
	    throw new Error("If excludeTerms is specified, it should be a regex, was: " + options.excludeTerms);
	}

	if (!options.includeSearchTerm) {
	    options.includeSearchTerm = false;

	} else if (typeof(options.includeSearchTerm) !== "boolean") {
	    throw new Error("If includeSearchTerm is specified, it should be a boolean, was: " + options.includeSearchTerm);
	}
    },

	disabledToggle = function(button) {
	    button
		.select(".confirmation")
		.text("X")
		.style("opacity", 1)
		.style("color", "darkred");
	},

	enabledToggle = function(button) {
	    button
		.classed("active", true)
		.select(".confirmation")
	    // The standard green looks bad against the darker background.
		.style("color", "lime")
		.style("opacity", 1);
	},

	wrapHooks = function(options, toggleF) {
	    if (options.hooks) {
		var wrapped = options.hooks;

		options.hooks = function(button) {
		    wrapped(button);
		    toggleF(button);
		};

	    } else {
		options.hooks = toggleF;
	    }
	};

    var m =  {
	matchEmpty: matchEmpty,

	/*
	 text is required, and should be a string. It's the text which will be displayed on the button.

	 f is required, and should be a function. If search is specified, then f will be called once a search result is clicked and will get the text of the search result as an argument. Otherwise, it will be called with no arguments as soon as the button is clicked.

	 options is reqyured, and may contain the following optional properties, plus those listed in the checkStates function above:

	 options.search is optional, and should be created using the search() function above. If it is present, then the button will pop up a search box when it is clicked.

	 options.hooks is optional, and should be a function which takes a d3 selection. The d3 selection will be the button. Hooks can be used to modify the button. If not specified, it will default to a noop function.

	 options.element is optional, and should be the name of an html element to use. If not specified, it will default to a div.

	 options.confirm is option, and should be either true of false. It causes a tick to appear and then fade whenever the button is clicked. It will default to 'true'.
	 */
	button: function(text, f, options) {
	    if (!typeof(text) === 'string') {
		throw new Error("Text should be a string, was: " + text);
	    }

	    if (!typeof(f) === 'function') {
		throw new Error('f should be a function, was: ' + f);
	    }

	    checkStates(options);

	    if (options.search) {
		checkSearch(options.search);
	    }

	    if (options.hooks === undefined) {
		options.hooks = function() {
		    // no-op
		};

	    } else if (typeof(options.hooks) !== 'function') {
		throw new Error("If hooks is specified, it must be a function, was: " + options.hooks);
	    }

	    if (options.element === undefined) {
		options.element = "div";

	    } else if (typeof(options.element) !== 'string') {
		throw new Error("If element is specified, it must be a string, was: " + options.element);
	    }

	    if (options.confirmation === undefined) {
		options.confirmation = true;

	    } else if (typeof(options.confirm) !== 'boolean') {
		throw new Error("If confirm is specified, it must be true or false, was: " + options.confirm);
	    }

	    return {
		text: text,
		f: f,
		onlineOffline: options.onlineOffline,
		readWriteSync: options.readWriteSync,
		embeddedStandalone: options.embeddedStandalone,
		search: options.search,
		hooks: options.hooks,
		element: options.element,
		confirm: options.confirm
	    };
	},

	/*
	 Returns two buttons with the same name which work together as a toggle.
	 */
	toggle: function(text, enableF, disabledOptions, disableF, enabledOptions) {
	    wrapHooks(disabledOptions, disabledToggle);
	    wrapHooks(enabledOptions, enabledToggle);

	    disabledOptions.confirm = false;
	    enabledOptions.confirm = false;

	    return [
		m.button(
		    text,
		    enableF,
		    disabledOptions
		),
		m.button(
		    text,
		    disableF,
		    enabledOptions
		)
	    ];
	}
    };

    return m;
};
<commit_msg>Fixed confirm.<commit_after>"use strict";

/*global module, require*/

var matchNone = /(?!)/,
    matchEmpty = /$^/;

/*
 Helper functions for producing valid button specifications. We pass these to the menu object, which display them for us.

 The reason for these functions is to provide defaults for the optional arguments, and to check the types of things supplied by the user.
 */
module.exports = function(defaultCollection) {
    var checkState = function(o, props) {
	props.forEach(function(p) {
	    if (o[p] === undefined) {
		throw new Error("Missing property " + p + " had " + Object.keys(o));
	    }

	    if (typeof(o[p]) !== 'boolean') {
		throw new Error("Property " + p + " should be a boolean, was: " + o[p]);
	    }
	});
    };

    /*
     states should be an object.

     We are checking for 3 properties: onlineOffline, readWriteSync and embeddedStandalone. Each of these represents a dimension of the state-space of the menu. If any are missing, the button will be displayed regardless of the state of the dimension.

     Each of these should be a subobject containing true/false sub-properties detailing which states the button should display in.
     */
    var checkStates = function(states) {
	if (!states.onlineOffline) {
	    states.onlineOffline = {
		online: true,
		offline: true
	    };
	} else {
	    checkState(states.onlineOffline, ['online', 'offline']);
	}

	if (!states.readWriteSync) {
	    states.readWriteSync = {
		untitled: true,
		read: true,
		write: true,
		sync: true
	    };
	} else {
	    checkState(states.readWriteSync, ['read', 'write', 'sync']);
	}

	if (!states.embeddedStandalone) {
	    states.embeddedStandalone = {
		embedded: true,
		standalone: true
	    };
	} else {
	    checkState(states.embeddedStandalone, ['embedded', 'standalone']);
	}
    };

    /*
     Produces a search object to be passed to the button. When this button is clicked, it will produce a search box.

     Takes an options object with the following properties:

     collection is optional, and should be a string. This is the Mongo collection which this search will look in. If not specified, we'll use the default collection instead.

     excludeTerms is optional, and should be a regex. If this is specified, any search terms the user types which match that regex will not trigger a search

     includeSearchTerm is optional, and should be a boolean. If this is specified, the search term will always be included in the results, even if it wasn't found in the search. In this case, it will get a different CSS class (.search-result-fabricated) added to it.
     */
    var checkSearch = function(options) {
	if (!options.collection) {
	    options.collection = defaultCollection;
	} else if (typeof(options.collection) !== "string") {
	    throw new Error("If collection is specified, it should be a string, was: " + options.collection);
	}

	if (!options.excludeTerms) {
	    options.excludeTerms = matchNone;

	} else if (!options.excludeTerms.test) {
	    throw new Error("If excludeTerms is specified, it should be a regex, was: " + options.excludeTerms);
	}

	if (!options.includeSearchTerm) {
	    options.includeSearchTerm = false;

	} else if (typeof(options.includeSearchTerm) !== "boolean") {
	    throw new Error("If includeSearchTerm is specified, it should be a boolean, was: " + options.includeSearchTerm);
	}
    },

	disabledToggle = function(button) {
	    button
		.select(".confirmation")
		.text("X")
		.style("opacity", 1)
		.style("color", "darkred");
	},

	enabledToggle = function(button) {
	    button
		.classed("active", true)
		.select(".confirmation")
	    // The standard green looks bad against the darker background.
		.style("color", "lime")
		.style("opacity", 1);
	},

	wrapHooks = function(options, toggleF) {
	    if (options.hooks) {
		var wrapped = options.hooks;

		options.hooks = function(button) {
		    wrapped(button);
		    toggleF(button);
		};

	    } else {
		options.hooks = toggleF;
	    }
	};

    var m =  {
	matchEmpty: matchEmpty,

	/*
	 text is required, and should be a string. It's the text which will be displayed on the button.

	 f is required, and should be a function. If search is specified, then f will be called once a search result is clicked and will get the text of the search result as an argument. Otherwise, it will be called with no arguments as soon as the button is clicked.

	 options is reqyured, and may contain the following optional properties, plus those listed in the checkStates function above:

	 options.search is optional, and should be created using the search() function above. If it is present, then the button will pop up a search box when it is clicked.

	 options.hooks is optional, and should be a function which takes a d3 selection. The d3 selection will be the button. Hooks can be used to modify the button. If not specified, it will default to a noop function.

	 options.element is optional, and should be the name of an html element to use. If not specified, it will default to a div.

	 options.confirm is option, and should be either true of false. It causes a tick to appear and then fade whenever the button is clicked. It will default to 'true'.
	 */
	button: function(text, f, options) {
	    if (!typeof(text) === 'string') {
		throw new Error("Text should be a string, was: " + text);
	    }

	    if (!typeof(f) === 'function') {
		throw new Error('f should be a function, was: ' + f);
	    }

	    checkStates(options);

	    if (options.search) {
		checkSearch(options.search);
	    }

	    if (options.hooks === undefined) {
		options.hooks = function() {
		    // no-op
		};

	    } else if (typeof(options.hooks) !== 'function') {
		throw new Error("If hooks is specified, it must be a function, was: " + options.hooks);
	    }

	    if (options.element === undefined) {
		options.element = "div";

	    } else if (typeof(options.element) !== 'string') {
		throw new Error("If element is specified, it must be a string, was: " + options.element);
	    }

	    if (options.confirm === undefined) {
		options.confirm = true;

	    } else if (typeof(options.confirm) !== 'boolean') {
		throw new Error("If confirm is specified, it must be true or false, was: " + options.confirm);
	    }

	    return {
		text: text,
		f: f,
		onlineOffline: options.onlineOffline,
		readWriteSync: options.readWriteSync,
		embeddedStandalone: options.embeddedStandalone,
		search: options.search,
		hooks: options.hooks,
		element: options.element,
		confirm: options.confirm
	    };
	},

	/*
	 Returns two buttons with the same name which work together as a toggle.
	 */
	toggle: function(text, enableF, disabledOptions, disableF, enabledOptions) {
	    wrapHooks(disabledOptions, disabledToggle);
	    wrapHooks(enabledOptions, enabledToggle);

	    disabledOptions.confirm = false;
	    enabledOptions.confirm = false;

	    return [
		m.button(
		    text,
		    enableF,
		    disabledOptions
		),
		m.button(
		    text,
		    disableF,
		    enabledOptions
		)
	    ];
	}
    };

    return m;
};
<|endoftext|>