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

/**
 * Main ScreenView container for Buttons portion of the UI component demo.
 *
 * @author John Blanco
 */
define( function( require ) {
  'use strict';

  var Color = require( 'SCENERY/util/Color' );
  var inherit = require( 'PHET_CORE/inherit' );
  var OutsideBackgroundNode = require( 'SCENERY_PHET/OutsideBackgroundNode' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var RectangularPushButton = require( 'SUN/experimental/buttons/RectangularPushButton' );
  var BooleanRectangularStickyToggleButton = require( 'SUN/experimental/buttons/BooleanRectangularStickyToggleButton' );
  var RefreshButton = require( 'SUN/experimental/buttons/RefreshButton' );
  var ResetAllButton = require( 'SCENERY_PHET/ResetAllButton' );
  var ResetAllButton2 = require( 'SUN/experimental/buttons/ResetAllButton2' );
  var ReturnToLevelSelectButton = require( 'SUN/experimental/buttons/ReturnToLevelSelectButton' );
  var RoundPushButton = require( 'SUN/experimental/buttons/RoundPushButton' );
  var RoundStickyToggleButton = require( 'SUN/experimental/buttons/RoundStickyToggleButton' );
  var InOutRadioButton = require( 'SUN/experimental/buttons/InOutRadioButton' );
  var ScreenView = require( 'JOIST/ScreenView' );
  var SoundToggleButton2 = require( 'SUN/experimental/buttons/SoundToggleButton2' );
  var Text = require( 'SCENERY/nodes/Text' );
  var TimerToggleButton2 = require( 'SUN/experimental/buttons/TimerToggleButton2' );
  var BooleanRectangularToggleButtonWithContent = require( 'SUN/experimental/buttons/BooleanRectangularToggleButton' );

  // Constants
  var BUTTON_FONT = new PhetFont( { size: 20 } );
  var BUTTON_CAPTION_FONT = new PhetFont( { size: 16 } );

  function ButtonsView() {
    ScreenView.call( this, { renderer: 'svg' } );

    // background
    this.addChild( new OutsideBackgroundNode( this.layoutBounds.centerX, this.layoutBounds.centerY + 20, this.layoutBounds.width * 3, this.layoutBounds.height, this.layoutBounds.height ) );
    // Set up a property for testing button enable/disable.
    var buttonsEnabled = new Property( true );

    // convenience vars for layout
    var rightEdge = this.layoutBounds.width * 0.6;
    var buttonSpacing = 10;

    // Text area for outputting test information
    var outputText = new Text( '(output text)', { font: new PhetFont( 16 ), bottom: this.layoutBounds.height - 5, left: this.layoutBounds.minX + 10  } );
    this.addChild( outputText );

    // add refresh button and caption
    var refreshButton = new RefreshButton(
      {
        listener: function() { outputText.text = 'Refresh pressed'; },
        right: rightEdge,
        top: 10
      } );
    this.addChild( refreshButton );
    var refreshButtonLabel = new Text( 'Refresh Button: ', { font: BUTTON_CAPTION_FONT, right: refreshButton.left - 5, centerY: refreshButton.centerY } );
    this.addChild( refreshButtonLabel );

    // add return to level select button and caption
    var returnToLevelSelectButton = new ReturnToLevelSelectButton(
      {
        listener: function() { outputText.text = 'Return to level select pressed'; },
        centerX: refreshButton.centerX,
        top: refreshButton.bottom + buttonSpacing
      } );
    this.addChild( returnToLevelSelectButton );
    var returnToLevelSelectButtonLabel = new Text( 'Return to Level Selection Button: ', { font: BUTTON_CAPTION_FONT, right: returnToLevelSelectButton.left - 5, centerY: returnToLevelSelectButton.centerY } );
    this.addChild( returnToLevelSelectButtonLabel );

    // add sound toggle button
    var soundEnabled = new Property( true );
    var soundToggleButton = new SoundToggleButton2( soundEnabled, { centerX: refreshButton.centerX, top: returnToLevelSelectButton.bottom + buttonSpacing } );
    this.addChild( soundToggleButton );
    var soundToggleButtonLabel = new Text( 'Sound Toggle Button: ', { font: BUTTON_CAPTION_FONT, right: soundToggleButton.left - 5, centerY: soundToggleButton.centerY } );
    this.addChild( soundToggleButtonLabel );

    // add timer toggle button
    var timerEnabled = new Property( true );
    var timerToggleButton = new TimerToggleButton2( timerEnabled, { centerX: refreshButton.centerX, y: soundToggleButton.bottom + 5 } );
    this.addChild( timerToggleButton );
    var timerToggleButtonLabel = new Text( 'Timer Toggle Button: ', { font: BUTTON_CAPTION_FONT, right: timerToggleButton.left - 5, centerY: timerToggleButton.centerY } );
    this.addChild( timerToggleButtonLabel );

    // Count variables, declared here so that they can be reset.
    var buttonCFireCount = 0;
    var fireOnDownCount = 0;

    // Reset function
    function resetAll() {
      outputText.text = 'Reset All pressed';
      buttonsEnabled.reset();
      soundEnabled.reset();
      timerEnabled.reset();
      buttonCFireCount = 0;
      fireOnDownCount = 0;
      roundToggleButtonProperty.reset();
      rectangularToggleButtonProperty.reset();
    }

    // add reset all button and caption
    var resetAllButton = new ResetAllButton( resetAll, { radius: 22, centerX: refreshButton.centerX, top: timerToggleButton.bottom + buttonSpacing } );
    this.addChild( resetAllButton );
    var resetAllButtonLabel = new Text( 'Reset All Button: ', { font: BUTTON_CAPTION_FONT, right: resetAllButton.left - 5, centerY: resetAllButton.centerY } );
    this.addChild( resetAllButtonLabel );

    // Test button behavior.
    var buttonA = new RectangularPushButton(
      {
        content: new Text( '--- A ---', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Button A pressed'; },
        left: 100,
        top: 300
      } );
    this.addChild( buttonA );

    var buttonB = new RectangularPushButton(
      {
        content: new Text( '--- B ---', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Button B pressed'; },
        left: buttonA.right + 10,
        centerY: buttonA.centerY,
        baseColor: new Color( 250, 0, 0 )
      } );
    this.addChild( buttonB );

    var buttonC = new RectangularPushButton(
      {
        content: new Text( '--- C ---', { font: BUTTON_FONT } ),
        listener: function() {
          outputText.text = 'Button C pressed ' + ( ++buttonCFireCount ) + 'x';
        },
        left: buttonB.right + 10,
        centerY: buttonB.centerY,
        baseColor: new Color( 204, 102, 204 )
      } );
    this.addChild( buttonC );

    var fireOnDownButton = new RectangularPushButton(
      {
        content: new Text( 'Fire on Down Button', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Fire on down button pressed ' + ( ++fireOnDownCount ) + 'x'; },
        left: buttonC.right + 30,
        centerY: buttonC.centerY,
        baseColor: new Color( 255, 255, 61 ),
        fireOnDown: true,
        stroke: 'black'
      } );
    this.addChild( fireOnDownButton );

    var buttonEnableButton = new BooleanRectangularToggleButtonWithContent(
      new Text( 'Disable Buttons', { font: BUTTON_CAPTION_FONT } ),
      new Text( 'Enable Buttons', { font: BUTTON_CAPTION_FONT } ),
      buttonsEnabled,
      { baseColor: new Color( 204, 255, 51 ), left: buttonA.left, top: buttonA.bottom + 30 }
    );
    this.addChild( buttonEnableButton );

    // add alternative reset all button
    var resetAllButton2 = new ResetAllButton2( { listener: resetAll, radius: 22, centerX: buttonC.centerX, centerY: buttonEnableButton.centerY } );
    this.addChild( resetAllButton2 );

    var buttonD = new RoundPushButton(
      {
        content: new Text( '--- D ---', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Button D pressed'; },
        left: resetAllButton2.right + buttonSpacing,
        centerY: resetAllButton2.centerY
      } );
    this.addChild( buttonD );

    var buttonE = new RoundPushButton(
      {
        content: new Text( '--- E ---', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Button E pressed'; },
        baseColor: new Color( 245, 184, 0 ),
        left: buttonD.right + buttonSpacing,
        centerY: buttonD.centerY
      } );
    this.addChild( buttonE );

    var fireButton = new RoundPushButton(
      {
        content: new Text( 'Fire!', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Fire button pressed'; },
        baseColor: new Color( 255, 100, 51 ),
        left: buttonE.right + buttonSpacing,
        centerY: buttonE.centerY,
        stroke: 'black',
        lineWidth: 0.5
      } );
    this.addChild( fireButton );

    var goButton = new RoundPushButton(
      {
        content: new Text( 'Go!', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Go button pressed'; },
        baseColor: new Color( 0, 163, 0 ),
        minXPadding: 10,
        centerX: resetAllButton2.centerX,
        top: buttonE.bottom + 5
      } );
    this.addChild( goButton );

    var helpButtonBaseColor = new Color( 244, 154, 194 );
    var helpButton = new RoundPushButton(
      {
        content: new Text( 'Help', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Help button pressed'; },
        baseColor: new Color( 244, 154, 194 ),
        minXPadding: 10,
        left: goButton.right + 5,
        centerY: goButton.centerY,
        stroke: helpButtonBaseColor.colorUtilsDarker( 0.4 ),
        lineWidth: 0.5
      } );
    this.addChild( helpButton );

    // Demonstrate using arbitrary values for toggle button.  Wrap in extra
    // quotes so it is clear that it is a string in the debugging UI.
    var roundToggleButtonProperty = new Property( '"off"' );
    roundToggleButtonProperty.lazyLink( function( toggleButton ) {
      outputText.text = "Round sticky toggle button state changed to: " + toggleButton;
    } );
    var roundStickyToggleButton = new RoundStickyToggleButton( '"off"', '"on"', roundToggleButtonProperty, {
      baseColor: new Color( 255, 0, 0 ),
      left: helpButton.right + 5,
      centerY: goButton.centerY
    } );
    this.addChild( roundStickyToggleButton );

    var rectangularToggleButtonProperty = new Property( false );
    rectangularToggleButtonProperty.lazyLink( function( toggleButton ) {
      outputText.text = 'Rectangular sticky toggle button state changed to: ' + toggleButton;
    } );
    var booleanRectangularStickyToggleButton = new BooleanRectangularStickyToggleButton( rectangularToggleButtonProperty, {
      baseColor: new Color( 0, 200, 200 ),
      left: roundStickyToggleButton.right + 10,
      centerY: goButton.centerY,
      minWidth: 50,
      minHeight: 35
    } );
    this.addChild( booleanRectangularStickyToggleButton );

    var inOutRadioButton = new InOutRadioButton( new Property( true ), true, new Text( 'In/Out' ) );
    this.addChild( inOutRadioButton );

    var transparentButton = new RectangularPushButton(
      {
        content: new Text( 'Transparent Button', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Transparent button pressed'; },
        left: helpButton.centerX,
        top: roundStickyToggleButton.bottom - 10,
        baseColor: new Color( 255, 255, 0, 0.7 )
      } );
    this.addChild( transparentButton );

    // Hook up button enable property
    buttonsEnabled.link( function( enabled ) {
      buttonA.enabled = enabled;
      buttonB.enabled = enabled;
      buttonC.enabled = enabled;
      buttonD.enabled = enabled;
      buttonE.enabled = enabled;
      fireOnDownButton.enabled = enabled;
      fireButton.enabled = enabled;
      goButton.enabled = enabled;
      helpButton.enabled = enabled;
      refreshButton.enabled = enabled;
      returnToLevelSelectButton.enabled = enabled;
      soundToggleButton.enabled = enabled;
      timerToggleButton.enabled = enabled;
      roundStickyToggleButton.enabled = enabled;
      booleanRectangularStickyToggleButton.enabled = enabled;
    } );

    // TODO: For debug, don't leave this here long term.
    var debugText = new Text( '(debug text)', { font: new PhetFont( 16 ), bottom: outputText.top - 5, left: this.layoutBounds.minX + 10  } );
    this.addChild( debugText );
    window.debugText = debugText;
  }

  return inherit( ScreenView, ButtonsView, {
    step: function( timeElapsed ) {
      // Does nothing for now.
    }
  } );
} );
<commit_msg>Depracated the ResetAll button, see https://github.com/phetsims/sun/issues/94.<commit_after>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Main ScreenView container for Buttons portion of the UI component demo.
 *
 * @author John Blanco
 */
define( function( require ) {
  'use strict';

  var Color = require( 'SCENERY/util/Color' );
  var inherit = require( 'PHET_CORE/inherit' );
  var OutsideBackgroundNode = require( 'SCENERY_PHET/OutsideBackgroundNode' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var RectangularPushButton = require( 'SUN/experimental/buttons/RectangularPushButton' );
  var BooleanRectangularStickyToggleButton = require( 'SUN/experimental/buttons/BooleanRectangularStickyToggleButton' );
  var RefreshButton = require( 'SUN/experimental/buttons/RefreshButton' );
  var ResetAllButtonDeprecated = require( 'SCENERY_PHET/ResetAllButtonDeprecated' );
  var ResetAllButton2 = require( 'SUN/experimental/buttons/ResetAllButton2' );
  var ReturnToLevelSelectButton = require( 'SUN/experimental/buttons/ReturnToLevelSelectButton' );
  var RoundPushButton = require( 'SUN/experimental/buttons/RoundPushButton' );
  var RoundStickyToggleButton = require( 'SUN/experimental/buttons/RoundStickyToggleButton' );
  var InOutRadioButton = require( 'SUN/experimental/buttons/InOutRadioButton' );
  var ScreenView = require( 'JOIST/ScreenView' );
  var SoundToggleButton2 = require( 'SUN/experimental/buttons/SoundToggleButton2' );
  var Text = require( 'SCENERY/nodes/Text' );
  var TimerToggleButton2 = require( 'SUN/experimental/buttons/TimerToggleButton2' );
  var BooleanRectangularToggleButtonWithContent = require( 'SUN/experimental/buttons/BooleanRectangularToggleButton' );

  // Constants
  var BUTTON_FONT = new PhetFont( { size: 20 } );
  var BUTTON_CAPTION_FONT = new PhetFont( { size: 16 } );

  function ButtonsView() {
    ScreenView.call( this, { renderer: 'svg' } );

    // background
    this.addChild( new OutsideBackgroundNode( this.layoutBounds.centerX, this.layoutBounds.centerY + 20, this.layoutBounds.width * 3, this.layoutBounds.height, this.layoutBounds.height ) );
    // Set up a property for testing button enable/disable.
    var buttonsEnabled = new Property( true );

    // convenience vars for layout
    var rightEdge = this.layoutBounds.width * 0.6;
    var buttonSpacing = 10;

    // Text area for outputting test information
    var outputText = new Text( '(output text)', { font: new PhetFont( 16 ), bottom: this.layoutBounds.height - 5, left: this.layoutBounds.minX + 10  } );
    this.addChild( outputText );

    // add refresh button and caption
    var refreshButton = new RefreshButton(
      {
        listener: function() { outputText.text = 'Refresh pressed'; },
        right: rightEdge,
        top: 10
      } );
    this.addChild( refreshButton );
    var refreshButtonLabel = new Text( 'Refresh Button: ', { font: BUTTON_CAPTION_FONT, right: refreshButton.left - 5, centerY: refreshButton.centerY } );
    this.addChild( refreshButtonLabel );

    // add return to level select button and caption
    var returnToLevelSelectButton = new ReturnToLevelSelectButton(
      {
        listener: function() { outputText.text = 'Return to level select pressed'; },
        centerX: refreshButton.centerX,
        top: refreshButton.bottom + buttonSpacing
      } );
    this.addChild( returnToLevelSelectButton );
    var returnToLevelSelectButtonLabel = new Text( 'Return to Level Selection Button: ', { font: BUTTON_CAPTION_FONT, right: returnToLevelSelectButton.left - 5, centerY: returnToLevelSelectButton.centerY } );
    this.addChild( returnToLevelSelectButtonLabel );

    // add sound toggle button
    var soundEnabled = new Property( true );
    var soundToggleButton = new SoundToggleButton2( soundEnabled, { centerX: refreshButton.centerX, top: returnToLevelSelectButton.bottom + buttonSpacing } );
    this.addChild( soundToggleButton );
    var soundToggleButtonLabel = new Text( 'Sound Toggle Button: ', { font: BUTTON_CAPTION_FONT, right: soundToggleButton.left - 5, centerY: soundToggleButton.centerY } );
    this.addChild( soundToggleButtonLabel );

    // add timer toggle button
    var timerEnabled = new Property( true );
    var timerToggleButton = new TimerToggleButton2( timerEnabled, { centerX: refreshButton.centerX, y: soundToggleButton.bottom + 5 } );
    this.addChild( timerToggleButton );
    var timerToggleButtonLabel = new Text( 'Timer Toggle Button: ', { font: BUTTON_CAPTION_FONT, right: timerToggleButton.left - 5, centerY: timerToggleButton.centerY } );
    this.addChild( timerToggleButtonLabel );

    // Count variables, declared here so that they can be reset.
    var buttonCFireCount = 0;
    var fireOnDownCount = 0;

    // Reset function
    function resetAll() {
      outputText.text = 'Reset All pressed';
      buttonsEnabled.reset();
      soundEnabled.reset();
      timerEnabled.reset();
      buttonCFireCount = 0;
      fireOnDownCount = 0;
      roundToggleButtonProperty.reset();
      rectangularToggleButtonProperty.reset();
    }

    // add reset all button and caption
    var resetAllButton = new ResetAllButtonDeprecated( resetAll, { radius: 22, centerX: refreshButton.centerX, top: timerToggleButton.bottom + buttonSpacing } );
    this.addChild( resetAllButton );
    var resetAllButtonLabel = new Text( 'Reset All Button: ', { font: BUTTON_CAPTION_FONT, right: resetAllButton.left - 5, centerY: resetAllButton.centerY } );
    this.addChild( resetAllButtonLabel );

    // Test button behavior.
    var buttonA = new RectangularPushButton(
      {
        content: new Text( '--- A ---', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Button A pressed'; },
        left: 100,
        top: 300
      } );
    this.addChild( buttonA );

    var buttonB = new RectangularPushButton(
      {
        content: new Text( '--- B ---', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Button B pressed'; },
        left: buttonA.right + 10,
        centerY: buttonA.centerY,
        baseColor: new Color( 250, 0, 0 )
      } );
    this.addChild( buttonB );

    var buttonC = new RectangularPushButton(
      {
        content: new Text( '--- C ---', { font: BUTTON_FONT } ),
        listener: function() {
          outputText.text = 'Button C pressed ' + ( ++buttonCFireCount ) + 'x';
        },
        left: buttonB.right + 10,
        centerY: buttonB.centerY,
        baseColor: new Color( 204, 102, 204 )
      } );
    this.addChild( buttonC );

    var fireOnDownButton = new RectangularPushButton(
      {
        content: new Text( 'Fire on Down Button', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Fire on down button pressed ' + ( ++fireOnDownCount ) + 'x'; },
        left: buttonC.right + 30,
        centerY: buttonC.centerY,
        baseColor: new Color( 255, 255, 61 ),
        fireOnDown: true,
        stroke: 'black'
      } );
    this.addChild( fireOnDownButton );

    var buttonEnableButton = new BooleanRectangularToggleButtonWithContent(
      new Text( 'Disable Buttons', { font: BUTTON_CAPTION_FONT } ),
      new Text( 'Enable Buttons', { font: BUTTON_CAPTION_FONT } ),
      buttonsEnabled,
      { baseColor: new Color( 204, 255, 51 ), left: buttonA.left, top: buttonA.bottom + 30 }
    );
    this.addChild( buttonEnableButton );

    // add alternative reset all button
    var resetAllButton2 = new ResetAllButton2( { listener: resetAll, radius: 22, centerX: buttonC.centerX, centerY: buttonEnableButton.centerY } );
    this.addChild( resetAllButton2 );

    var buttonD = new RoundPushButton(
      {
        content: new Text( '--- D ---', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Button D pressed'; },
        left: resetAllButton2.right + buttonSpacing,
        centerY: resetAllButton2.centerY
      } );
    this.addChild( buttonD );

    var buttonE = new RoundPushButton(
      {
        content: new Text( '--- E ---', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Button E pressed'; },
        baseColor: new Color( 245, 184, 0 ),
        left: buttonD.right + buttonSpacing,
        centerY: buttonD.centerY
      } );
    this.addChild( buttonE );

    var fireButton = new RoundPushButton(
      {
        content: new Text( 'Fire!', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Fire button pressed'; },
        baseColor: new Color( 255, 100, 51 ),
        left: buttonE.right + buttonSpacing,
        centerY: buttonE.centerY,
        stroke: 'black',
        lineWidth: 0.5
      } );
    this.addChild( fireButton );

    var goButton = new RoundPushButton(
      {
        content: new Text( 'Go!', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Go button pressed'; },
        baseColor: new Color( 0, 163, 0 ),
        minXPadding: 10,
        centerX: resetAllButton2.centerX,
        top: buttonE.bottom + 5
      } );
    this.addChild( goButton );

    var helpButtonBaseColor = new Color( 244, 154, 194 );
    var helpButton = new RoundPushButton(
      {
        content: new Text( 'Help', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Help button pressed'; },
        baseColor: new Color( 244, 154, 194 ),
        minXPadding: 10,
        left: goButton.right + 5,
        centerY: goButton.centerY,
        stroke: helpButtonBaseColor.colorUtilsDarker( 0.4 ),
        lineWidth: 0.5
      } );
    this.addChild( helpButton );

    // Demonstrate using arbitrary values for toggle button.  Wrap in extra
    // quotes so it is clear that it is a string in the debugging UI.
    var roundToggleButtonProperty = new Property( '"off"' );
    roundToggleButtonProperty.lazyLink( function( toggleButton ) {
      outputText.text = "Round sticky toggle button state changed to: " + toggleButton;
    } );
    var roundStickyToggleButton = new RoundStickyToggleButton( '"off"', '"on"', roundToggleButtonProperty, {
      baseColor: new Color( 255, 0, 0 ),
      left: helpButton.right + 5,
      centerY: goButton.centerY
    } );
    this.addChild( roundStickyToggleButton );

    var rectangularToggleButtonProperty = new Property( false );
    rectangularToggleButtonProperty.lazyLink( function( toggleButton ) {
      outputText.text = 'Rectangular sticky toggle button state changed to: ' + toggleButton;
    } );
    var booleanRectangularStickyToggleButton = new BooleanRectangularStickyToggleButton( rectangularToggleButtonProperty, {
      baseColor: new Color( 0, 200, 200 ),
      left: roundStickyToggleButton.right + 10,
      centerY: goButton.centerY,
      minWidth: 50,
      minHeight: 35
    } );
    this.addChild( booleanRectangularStickyToggleButton );

    var inOutRadioButton = new InOutRadioButton( new Property( true ), true, new Text( 'In/Out' ) );
    this.addChild( inOutRadioButton );

    var transparentButton = new RectangularPushButton(
      {
        content: new Text( 'Transparent Button', { font: BUTTON_FONT } ),
        listener: function() { outputText.text = 'Transparent button pressed'; },
        left: helpButton.centerX,
        top: roundStickyToggleButton.bottom - 10,
        baseColor: new Color( 255, 255, 0, 0.7 )
      } );
    this.addChild( transparentButton );

    // Hook up button enable property
    buttonsEnabled.link( function( enabled ) {
      buttonA.enabled = enabled;
      buttonB.enabled = enabled;
      buttonC.enabled = enabled;
      buttonD.enabled = enabled;
      buttonE.enabled = enabled;
      fireOnDownButton.enabled = enabled;
      fireButton.enabled = enabled;
      goButton.enabled = enabled;
      helpButton.enabled = enabled;
      refreshButton.enabled = enabled;
      returnToLevelSelectButton.enabled = enabled;
      soundToggleButton.enabled = enabled;
      timerToggleButton.enabled = enabled;
      roundStickyToggleButton.enabled = enabled;
      booleanRectangularStickyToggleButton.enabled = enabled;
    } );

    // TODO: For debug, don't leave this here long term.
    var debugText = new Text( '(debug text)', { font: new PhetFont( 16 ), bottom: outputText.top - 5, left: this.layoutBounds.minX + 10  } );
    this.addChild( debugText );
    window.debugText = debugText;
  }

  return inherit( ScreenView, ButtonsView, {
    step: function( timeElapsed ) {
      // Does nothing for now.
    }
  } );
} );
<|endoftext|>


<commit_before>/* eslint-env mocha */
/*global $, sinon, expect */
describe('jsonproxy', function () {
  var loc = window.location,
    origin = loc.origin || loc.protocol + '//' + loc.host,
    proxy = 'https://jsonp.afeld.me/',
    packagePath = loc.pathname.replace(/test.html/, 'package.json'),
    sandbox = sinon.createSandbox(),
    server;

  beforeEach(function () {
    server = sinon.fakeServer.create();
    server.autoRespond = true;
  });

  afterEach(function () {
    sandbox.restore();
    server.restore();
  });

  function sharedTests() {
    it('should do standard ajax for relative domains', function () {
      server.respondWith('GET', packagePath, [
        200,
        { 'Content-Type': 'application/json' },
        '{ "name": "jsonp" }',
      ]);

      return $.jsonp({
        url: packagePath,

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(packagePath);
        },
      }).done(function (data) {
        expect(data.name).to.equal('jsonp');
      });
    });

    it('should do standard ajax for the same domain', function () {
      var url = origin + packagePath;

      server.respondWith('GET', packagePath, [
        200,
        { 'Content-Type': 'application/json' },
        '{ "name": "jsonp" }',
      ]);

      return $.jsonp({
        url: url,

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(url);
        },
      }).done(function (data) {
        expect(data.name).to.equal('jsonp');
      });
    });

    it('should use the proxy for a mismatched protocol', function (done) {
      sandbox.stub($.jsonp, 'getLocation').callsFake(function () {
        return {
          hash: '',
          host: 'foo.com',
          hostname: 'foo.com',
          href: 'https://foo.com/other/path',
          origin: 'https://foo.com',
          pathname: '/other/path',
          port: '',
          protocol: 'https:',
        };
      });

      var url = 'http://foo.com/other/path';

      $.jsonp({
        url: url,

        beforeSend: function (_, settings) {
          expect(settings.url).to.contain(proxy + '?');
          expect(settings.url).to.contain('url=' + encodeURIComponent(url));

          done();
          return false;
        },
      });
    });
  }

  describe('with browser CORS support', function () {
    var origCors;
    before(function () {
      origCors = $.support.cors;
      $.support.cors = true;
    });

    after(function () {
      $.support.cors = origCors;
    });

    sharedTests();

    it('should use the CORS proxy', function (done) {
      var url = 'http://foo.com/bar';

      $.jsonp({
        url: url,

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(proxy + '?url=' + encodeURIComponent(url));

          done();
          return false;
        },
      });
    });

    it('should use CORS proxy even if the URL supports JSONP', function (done) {
      var url = 'http://foo.com/bar';

      $.jsonp({
        url: url,
        jsonpSupport: true,

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(proxy + '?url=' + encodeURIComponent(url));

          done();
          return false;
        },
      });
    });

    // TODO fix
    // it('should handle requests for text to relative path', function (done) {
    //   var url = loc.pathname.replace(/test.html/, 'client/test/data.txt');

    //   $.jsonp({
    //     url: url,
    //     dataType: 'text',

    //     beforeSend: function (_, settings) {
    //       expect(settings.url).to.be(url);
    //     },
    //   }).done(function (text) {
    //     expect(text).to.equal('hello world');
    //     done();
    //   });
    // });

    it('should handle requests for text across domains', function (done) {
      var url = 'http://foo.com/data.txt';

      $.jsonp({
        url: url,
        dataType: 'text',

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(proxy + '?url=' + encodeURIComponent(url));

          done();
          return false;
        },
      });
    });

    it("should handle the 'data' option", function (done) {
      $.jsonp({
        url: 'http://foo.com',
        data: {
          bar: 'baz',
        },

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(
            proxy + '?url=http%3A%2F%2Ffoo.com%2F%3Fbar%3Dbaz'
          );

          done();
          return false;
        },
      });
    });

    describe('when API has corsSupport', function () {
      it('should use the URL directly', function (done) {
        var url = 'http://foo.com/bar';

        $.jsonp({
          url: url,
          corsSupport: true,

          beforeSend: function (_, settings) {
            expect(settings.url).to.be(url);

            done();
            return false;
          },
        });
      });

      it('should favor CORS to JSONP on the URL directly', function (done) {
        var url = 'http://foo.com/bar';

        $.jsonp({
          url: url,
          corsSupport: true,
          jsonpSupport: true,

          beforeSend: function (_, settings) {
            expect(settings.url).to.be(url);

            done();
            return false;
          },
        });
      });

      it("should use the proxy if protocols don't match", function (done) {
        var url = 'http://foo.com/bar';

        sandbox.stub($.jsonp, 'getLocation').callsFake(function () {
          return {
            hash: '',
            host: 'foo.com',
            hostname: 'foo.com',
            href: 'https://foo.com/other/path',
            origin: 'https://foo.com',
            pathname: '/other/path',
            port: '',
            protocol: 'https:',
          };
        });

        $.jsonp({
          url: url,
          corsSupport: true,

          beforeSend: function (_, settings) {
            expect(settings.url).to.be(
              proxy + '?url=' + encodeURIComponent(url)
            );

            done();
            return false;
          },
        });
      });
    });
  });

  describe('without browser CORS support', function () {
    var origCors;
    before(function () {
      origCors = $.support.cors;
      $.support.cors = false;
    });

    after(function () {
      $.support.cors = origCors;
    });

    sharedTests();

    it('should use the JSONP proxy', function (done) {
      var url = 'http://foo.com/bar';

      $.jsonp({
        url: url,

        beforeSend: function (_, settings) {
          expect(settings.url).to.contain(proxy + '?');
          expect(settings.url).to.contain('url=' + encodeURIComponent(url));
          expect(settings.url).to.contain('callback=jQuery');
          // should set default timeout
          expect(settings.timeout).to.be.a('number');

          done();
          return false;
        },
      });
    });

    it('should handle requests for text across domains', function (done) {
      var url = 'http://foo.com/data.txt';

      $.jsonp({
        url: url,
        dataType: 'text',

        beforeSend: function (_, settings) {
          expect(settings.dataType).to.be('jsonp');

          done();
          return false;
        },
      });
    });

    describe('when API has jsonpSupport', function () {
      it('should use the URL directly', function (done) {
        var url = 'http://foo.com/bar';

        $.jsonp({
          url: url,
          jsonpSupport: true,

          beforeSend: function (_, settings) {
            expect(settings.url).to.contain(url + '?callback=jQuery');
            // should set default timeout
            expect(settings.timeout).to.be.a('number');

            done();
            return false;
          },
        });
      });
    });
  });
});
<commit_msg>fix test for fetching plain text<commit_after>/* eslint-env mocha */
/*global $, sinon, expect */
describe('jsonproxy', function () {
  var loc = window.location,
    origin = loc.origin || loc.protocol + '//' + loc.host,
    proxy = 'https://jsonp.afeld.me/',
    packagePath = loc.pathname.replace(/test.html/, 'package.json'),
    sandbox = sinon.createSandbox(),
    server;

  beforeEach(function () {
    server = sinon.fakeServer.create();
    server.autoRespond = true;
  });

  afterEach(function () {
    sandbox.restore();
    server.restore();
  });

  function sharedTests() {
    it('should do standard ajax for relative domains', function () {
      server.respondWith('GET', packagePath, [
        200,
        { 'Content-Type': 'application/json' },
        '{ "name": "jsonp" }',
      ]);

      return $.jsonp({
        url: packagePath,

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(packagePath);
        },
      }).done(function (data) {
        expect(data.name).to.equal('jsonp');
      });
    });

    it('should do standard ajax for the same domain', function () {
      var url = origin + packagePath;

      server.respondWith('GET', packagePath, [
        200,
        { 'Content-Type': 'application/json' },
        '{ "name": "jsonp" }',
      ]);

      return $.jsonp({
        url: url,

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(url);
        },
      }).done(function (data) {
        expect(data.name).to.equal('jsonp');
      });
    });

    it('should use the proxy for a mismatched protocol', function (done) {
      sandbox.stub($.jsonp, 'getLocation').callsFake(function () {
        return {
          hash: '',
          host: 'foo.com',
          hostname: 'foo.com',
          href: 'https://foo.com/other/path',
          origin: 'https://foo.com',
          pathname: '/other/path',
          port: '',
          protocol: 'https:',
        };
      });

      var url = 'http://foo.com/other/path';

      $.jsonp({
        url: url,

        beforeSend: function (_, settings) {
          expect(settings.url).to.contain(proxy + '?');
          expect(settings.url).to.contain('url=' + encodeURIComponent(url));

          done();
          return false;
        },
      });
    });
  }

  describe('with browser CORS support', function () {
    var origCors;
    before(function () {
      origCors = $.support.cors;
      $.support.cors = true;
    });

    after(function () {
      $.support.cors = origCors;
    });

    sharedTests();

    it('should use the CORS proxy', function (done) {
      var url = 'http://foo.com/bar';

      $.jsonp({
        url: url,

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(proxy + '?url=' + encodeURIComponent(url));

          done();
          return false;
        },
      });
    });

    it('should use CORS proxy even if the URL supports JSONP', function (done) {
      var url = 'http://foo.com/bar';

      $.jsonp({
        url: url,
        jsonpSupport: true,

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(proxy + '?url=' + encodeURIComponent(url));

          done();
          return false;
        },
      });
    });

    it('should handle requests for text to relative path', function () {
      const txtFile = 'client/test/data.txt';
      var url = loc.pathname.replace(/test.html/, txtFile);

      server.respondWith('GET', url, [
        200,
        { 'Content-Type': 'text/plain' },
        'hello world',
      ]);

      return $.jsonp({
        url: url,
        dataType: 'text',

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(url);
        },
      }).done(function (text) {
        expect(text).to.equal('hello world');
      });
    });

    it('should handle requests for text across domains', function (done) {
      var url = 'http://foo.com/data.txt';

      $.jsonp({
        url: url,
        dataType: 'text',

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(proxy + '?url=' + encodeURIComponent(url));

          done();
          return false;
        },
      });
    });

    it("should handle the 'data' option", function (done) {
      $.jsonp({
        url: 'http://foo.com',
        data: {
          bar: 'baz',
        },

        beforeSend: function (_, settings) {
          expect(settings.url).to.be(
            proxy + '?url=http%3A%2F%2Ffoo.com%2F%3Fbar%3Dbaz'
          );

          done();
          return false;
        },
      });
    });

    describe('when API has corsSupport', function () {
      it('should use the URL directly', function (done) {
        var url = 'http://foo.com/bar';

        $.jsonp({
          url: url,
          corsSupport: true,

          beforeSend: function (_, settings) {
            expect(settings.url).to.be(url);

            done();
            return false;
          },
        });
      });

      it('should favor CORS to JSONP on the URL directly', function (done) {
        var url = 'http://foo.com/bar';

        $.jsonp({
          url: url,
          corsSupport: true,
          jsonpSupport: true,

          beforeSend: function (_, settings) {
            expect(settings.url).to.be(url);

            done();
            return false;
          },
        });
      });

      it("should use the proxy if protocols don't match", function (done) {
        var url = 'http://foo.com/bar';

        sandbox.stub($.jsonp, 'getLocation').callsFake(function () {
          return {
            hash: '',
            host: 'foo.com',
            hostname: 'foo.com',
            href: 'https://foo.com/other/path',
            origin: 'https://foo.com',
            pathname: '/other/path',
            port: '',
            protocol: 'https:',
          };
        });

        $.jsonp({
          url: url,
          corsSupport: true,

          beforeSend: function (_, settings) {
            expect(settings.url).to.be(
              proxy + '?url=' + encodeURIComponent(url)
            );

            done();
            return false;
          },
        });
      });
    });
  });

  describe('without browser CORS support', function () {
    var origCors;
    before(function () {
      origCors = $.support.cors;
      $.support.cors = false;
    });

    after(function () {
      $.support.cors = origCors;
    });

    sharedTests();

    it('should use the JSONP proxy', function (done) {
      var url = 'http://foo.com/bar';

      $.jsonp({
        url: url,

        beforeSend: function (_, settings) {
          expect(settings.url).to.contain(proxy + '?');
          expect(settings.url).to.contain('url=' + encodeURIComponent(url));
          expect(settings.url).to.contain('callback=jQuery');
          // should set default timeout
          expect(settings.timeout).to.be.a('number');

          done();
          return false;
        },
      });
    });

    it('should handle requests for text across domains', function (done) {
      var url = 'http://foo.com/data.txt';

      $.jsonp({
        url: url,
        dataType: 'text',

        beforeSend: function (_, settings) {
          expect(settings.dataType).to.be('jsonp');

          done();
          return false;
        },
      });
    });

    describe('when API has jsonpSupport', function () {
      it('should use the URL directly', function (done) {
        var url = 'http://foo.com/bar';

        $.jsonp({
          url: url,
          jsonpSupport: true,

          beforeSend: function (_, settings) {
            expect(settings.url).to.contain(url + '?callback=jQuery');
            // should set default timeout
            expect(settings.timeout).to.be.a('number');

            done();
            return false;
          },
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * A stack of overlays that display itself and handle mouse events.
 * TODO(kaznacheev) Consider disbanding this class and moving
 * the functionality to individual objects that display anything or handle
 * mouse events.
 * @constructor
 */
function ImageBuffer() {
  this.overlays_ = [];
}

/**
 * TODO(JSDOC).
 * @param {ImageBuffer.Overlay} overlay  // TODO(JSDOC).
 */
ImageBuffer.prototype.addOverlay = function(overlay) {
  var zIndex = overlay.getZIndex();
  // Store the overlays in the ascending Z-order.
  var i;
  for (i = 0; i != this.overlays_.length; i++) {
    if (zIndex < this.overlays_[i].getZIndex()) break;
  }
  this.overlays_.splice(i, 0, overlay);
};

/**
 * TODO(JSDOC).
 * @param {ImageBuffer.Overlay} overlay  // TODO(JSDOC).
 */
ImageBuffer.prototype.removeOverlay = function(overlay) {
  for (var i = 0; i != this.overlays_.length; i++) {
    if (this.overlays_[i] == overlay) {
      this.overlays_.splice(i, 1);
      return;
    }
  }
  throw new Error('Cannot remove overlay ' + overlay);
};

/**
 * Draws overlays in the ascending Z-order.
 */
ImageBuffer.prototype.draw = function() {
  for (var i = 0; i != this.overlays_.length; i++) {
    this.overlays_[i].draw();
  }
};

/**
 * Searches for a cursor style in the descending Z-order.
 * @param {number} x X coordinate for cursor.
 * @param {number} y Y coordinate for cursor.
 * @param {boolean} mouseDown If mouse button is down.
 * @return {string} A value for style.cursor CSS property.
 */
ImageBuffer.prototype.getCursorStyle = function(x, y, mouseDown) {
  for (var i = this.overlays_.length - 1; i >= 0; i--) {
    var style = this.overlays_[i].getCursorStyle(x, y, mouseDown);
    if (style) return style;
  }
  return 'default';
};

/**
 * Searches for a click handler in the descending Z-order.
 * @param {number} x X coordinate for click event.
 * @param {number} y Y coordinate for click event.
 * @return {boolean} True if handled.
 */
ImageBuffer.prototype.onClick = function(x, y) {
  for (var i = this.overlays_.length - 1; i >= 0; i--) {
    if (this.overlays_[i].onClick(x, y)) return true;
  }
  return false;
};

/**
 * Searches for a drag handler in the descending Z-order.
 * @param {number} x Event X coordinate.
 * @param {number} y Event Y coordinate.
 * @param {boolean} touch True if it's a touch event, false if mouse.
 * @return {function(number,number)} A function to be called on mouse drag.
 */
ImageBuffer.prototype.getDragHandler = function(x, y, touch) {
  for (var i = this.overlays_.length - 1; i >= 0; i--) {
    var handler = this.overlays_[i].getDragHandler(x, y, touch);
    if (handler)
      return handler;
  }
  return null;
};

/**
 * Searches for an action for the double tap enumerating
 * layers in the descending Z-order.
 * @param {number} x X coordinate of the event.
 * @param {number} y Y coordinate of the event.
 * @return {ImageBuffer.DoubleTapAction} Action to perform as result.
 */
ImageBuffer.prototype.getDoubleTapAction = function(x, y) {
  for (var i = this.overlays_.length - 1; i >= 0; i--) {
    var action = this.overlays_[i].getDoubleTapAction(x, y);
    if (action != ImageBuffer.DoubleTapAction.NOTHING)
      return action;
  }
  return ImageBuffer.DoubleTapAction.NOTHING;
};

/**
 * Possible double tap actions.
 * @enum
 */
ImageBuffer.DoubleTapAction = {
  NOTHING: 0,
  COMMIT: 1,
  CANCEL: 2
};

/**
 * ImageBuffer.Overlay is a pluggable extension that modifies the outlook
 * and the behavior of the ImageBuffer instance.
 * @constructor
 * @struct
 */
ImageBuffer.Overlay = function() {};

/**
 * TODO(JSDOC).
 * @return {number}  // TODO(JSDOC).
 */
ImageBuffer.Overlay.prototype.getZIndex = function() { return 0; };

/**
 * TODO(JSDOC).
 */
ImageBuffer.Overlay.prototype.draw = function() {};

/**
 * TODO(JSDOC).
 * @param {number} x X coordinate for cursor.
 * @param {number} y Y coordinate for cursor.
 * @param {boolean} mouseDown If mouse button is down.
 * @return {?string} A value for style.cursor CSS property or null for
 *     default.
 */
ImageBuffer.Overlay.prototype.getCursorStyle = function(x, y, mouseDown) {
  return null;
};

/**
 * TODO(JSDOC).
 * @param {number} x  // TODO(JSDOC).
 * @param {number} y  // TODO(JSDOC).
 * @return {boolean}  // TODO(JSDOC).
 */
ImageBuffer.Overlay.prototype.onClick = function(x, y) {
  return false;
};

/**
 * TODO(JSDOC).
 * @param {number} x Event X coordinate.
 * @param {number} y Event Y coordinate.
 * @param {boolean} touch True if it's a touch event, false if mouse.
 * @return {function(number,number)} A function to be called on mouse drag.
 */
ImageBuffer.Overlay.prototype.getDragHandler = function(x, y, touch) {
  return null;
};

/**
 * TODO(JSDOC).
 * @param {number} x  // TODO(JSDOC).
 * @param {number} y  // TODO(JSDOC).
 * @return {ImageBuffer.DoubleTapAction}  // TODO(JSDOC).
 */
ImageBuffer.Overlay.prototype.getDoubleTapAction = function(x, y) {
  return ImageBuffer.DoubleTapAction.NOTHING;
};
<commit_msg>Add type annotations to gallery/js/image_buffer.js.<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * A stack of overlays that display itself and handle mouse events.
 * TODO(kaznacheev) Consider disbanding this class and moving
 * the functionality to individual objects that display anything or handle
 * mouse events.
 * @constructor
 * @struct
 */
function ImageBuffer() {
  this.overlays_ = [];
}

/**
 * Add an overlay to a buffer.
 * @param {!ImageBuffer.Overlay} overlay An overlay added to a buffer.
 */
ImageBuffer.prototype.addOverlay = function(overlay) {
  var zIndex = overlay.getZIndex();
  // Store the overlays in the ascending Z-order.
  var i;
  for (i = 0; i != this.overlays_.length; i++) {
    if (zIndex < this.overlays_[i].getZIndex()) break;
  }
  this.overlays_.splice(i, 0, overlay);
};

/**
 * Remove an overlay from a buffer.
 * @param {!ImageBuffer.Overlay} overlay An overlay removed from a buffer.
 */
ImageBuffer.prototype.removeOverlay = function(overlay) {
  for (var i = 0; i != this.overlays_.length; i++) {
    if (this.overlays_[i] == overlay) {
      this.overlays_.splice(i, 1);
      return;
    }
  }
  throw new Error('Cannot remove overlay ' + overlay);
};

/**
 * Draws overlays in the ascending Z-order.
 */
ImageBuffer.prototype.draw = function() {
  for (var i = 0; i != this.overlays_.length; i++) {
    this.overlays_[i].draw();
  }
};

/**
 * Searches for a cursor style in the descending Z-order.
 * @param {number} x X coordinate for cursor.
 * @param {number} y Y coordinate for cursor.
 * @param {boolean} mouseDown If mouse button is down.
 * @return {string} A value for style.cursor CSS property.
 */
ImageBuffer.prototype.getCursorStyle = function(x, y, mouseDown) {
  for (var i = this.overlays_.length - 1; i >= 0; i--) {
    var style = this.overlays_[i].getCursorStyle(x, y, mouseDown);
    if (style) return style;
  }
  return 'default';
};

/**
 * Searches for a click handler in the descending Z-order.
 * @param {number} x X coordinate for click event.
 * @param {number} y Y coordinate for click event.
 * @return {boolean} True if handled.
 */
ImageBuffer.prototype.onClick = function(x, y) {
  for (var i = this.overlays_.length - 1; i >= 0; i--) {
    if (this.overlays_[i].onClick(x, y)) return true;
  }
  return false;
};

/**
 * Searches for a drag handler in the descending Z-order.
 * @param {number} x Event X coordinate.
 * @param {number} y Event Y coordinate.
 * @param {boolean} touch True if it's a touch event, false if mouse.
 * @return {?function(number,number)} A function to be called on mouse drag.
 */
ImageBuffer.prototype.getDragHandler = function(x, y, touch) {
  for (var i = this.overlays_.length - 1; i >= 0; i--) {
    var handler = this.overlays_[i].getDragHandler(x, y, touch);
    if (handler)
      return handler;
  }
  return null;
};

/**
 * Searches for an action for the double tap enumerating
 * layers in the descending Z-order.
 * @param {number} x X coordinate of the event.
 * @param {number} y Y coordinate of the event.
 * @return {!ImageBuffer.DoubleTapAction} Action to perform as result.
 */
ImageBuffer.prototype.getDoubleTapAction = function(x, y) {
  for (var i = this.overlays_.length - 1; i >= 0; i--) {
    var action = this.overlays_[i].getDoubleTapAction(x, y);
    if (action != ImageBuffer.DoubleTapAction.NOTHING)
      return action;
  }
  return ImageBuffer.DoubleTapAction.NOTHING;
};

/**
 * Possible double tap actions.
 * @enum {number}
 */
ImageBuffer.DoubleTapAction = {
  NOTHING: 0,
  COMMIT: 1,
  CANCEL: 2
};

/**
 * ImageBuffer.Overlay is a pluggable extension that modifies the outlook
 * and the behavior of the ImageBuffer instance.
 * @constructor
 * @struct
 */
ImageBuffer.Overlay = function() {};

/**
 * Get Z index of this overlay.
 * @return {number} Z index of this overlay.
 */
ImageBuffer.Overlay.prototype.getZIndex = function() { return 0; };

/**
 * Draw an overlay.
 */
ImageBuffer.Overlay.prototype.draw = function() {};

/**
 * Get cursor style.
 * @param {number} x X coordinate for cursor.
 * @param {number} y Y coordinate for cursor.
 * @param {boolean} mouseDown If mouse button is down.
 * @return {?string} A value for style.cursor CSS property or null for
 *     default.
 */
ImageBuffer.Overlay.prototype.getCursorStyle = function(x, y, mouseDown) {
  return null;
};

/**
 * Handle click.
 * @param {number} x X coordinate.
 * @param {number} y Y coordinate.
 * @return {boolean} True if handled.
 */
ImageBuffer.Overlay.prototype.onClick = function(x, y) {
  return false;
};

/**
 * Returns a drag handler.
 * @param {number} x Event X coordinate.
 * @param {number} y Event Y coordinate.
 * @param {boolean} touch True if it's a touch event, false if mouse.
 * @return {?function(number,number)} A function to be called on mouse drag.
 */
ImageBuffer.Overlay.prototype.getDragHandler = function(x, y, touch) {
  return null;
};

/**
 * Returns an action for a double tap.
 * @param {number} x X coordinate.
 * @param {number} y Y coordinate.
 * @return {ImageBuffer.DoubleTapAction} Double tap action.
 */
ImageBuffer.Overlay.prototype.getDoubleTapAction = function(x, y) {
  return ImageBuffer.DoubleTapAction.NOTHING;
};
<|endoftext|>


<commit_before>
function getParameterByName(name) {
    // from: http://stackoverflow.com/a/901144/908430
    name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
    var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'),
        results = regex.exec(location.search);
    return results == null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}

function createHtmlFragment(htmlStr) {
    // from: http://stackoverflow.com/a/814649/908430
    // also, see: http://ejohn.org/blog/dom-documentfragments/
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}

function setResults(htmlStr) {
    var results = document.getElementById('results');
    results.innerHTML = '';

    var fragment = createHtmlFragment(htmlStr);
    results.appendChild(fragment);

    if (htmlStr != '')
        results.style.visibility = 'visible';
    else
        results.style.visibility = 'hidden';
}

function calculateAndDisplayTaxes(income, deductions, exemptions) {
    var resultsHtml = '';

    function w(kind, text, amt) {
        if (kind == 'a')
            resultsHtml += '
' + text + ': ' + amt + '
';
        else if (kind == 'l_start')
            resultsHtml += '

' + text + '
';
        else if (kind == 'b')
            resultsHtml += '
' + text + '
';
        else if (kind == 'l_end')
            resultsHtml += '
' + text + ': ' + amt + '

';
        else if (kind == 't')
            resultsHtml += '
' + text + '
';
        else if (kind == 'x') // html decorators
            resultsHtml += text;
    }

    function do_nothing_w(kind, text, amt) {}

    var my_tax = calc_taxes(taxRates, income, deductions, exemptions, w),
        my_tax_plus = calc_taxes(taxRates, income + 1.0, deductions, exemptions, do_nothing_w);

    var marginal_tax_rate = (my_tax_plus - my_tax) * 100.0;
    w('a', 'Marginal Tax Rate', marginal_tax_rate.toFixed(2) + '%');

    return resultsHtml;
}

function calcAndDisplay(input) {
    setResults(calculateAndDisplayTaxes(input.income, input.deductions, input.exemptions));
}

function constructErrorMessage(input, incomeParam, deductionsParam, exemptionsParam) {
    var errorMessage = '';

    if (!incomeParam)
        errorMessage += 'Income must be specified.
';
    if (incomeParam && input.income == 0)
        errorMessage += 'Income must be greater than zero.
';
    if (incomeParam && (!isValidNumber(incomeParam) || !(input.income >= 0)))
        errorMessage += "Income: '" + incomeParam + "'" + ' is not valid.
';
    if (!deductionsParam)
        errorMessage += 'The total dollar amount of tax deductions must be specified.
';
    if (deductionsParam && (!isValidNumber(deductionsParam) || !(input.deductions >= 0)))
        errorMessage += "Deductions: '" + deductionsParam + "'" + ' is not valid.
';
    if (!exemptionsParam)
        errorMessage += 'The number of personal exemptions must be specified.
';
    if (exemptionsParam && (!isValidNumber(exemptionsParam) || !(input.exemptions >= 0)))
        errorMessage += "Exemptions: '" + exemptionsParam + "'" + ' is not valid.
';

    return errorMessage;
}

function isValidNumber(text) { // from: http://stackoverflow.com/a/21907572/908430
    return /^[0-9,.]*$/.test(text);
}

function removeCommas(text) {
    return text.replace(/,/g, '');
}

function createInputObject(incomeParam, deductionsParam, exemptionsParam) {
    var input = {
        income: parseFloat(removeCommas(incomeParam)),
        deductions: parseFloat(removeCommas(deductionsParam)),
        exemptions: parseFloat(removeCommas(exemptionsParam))
    };

    if (isValidNumber(incomeParam) && input.income > 0 &&
        isValidNumber(deductionsParam) && input.deductions >= 0 &&
        isValidNumber(exemptionsParam) && input.exemptions >= 0)
        return input;
    else
        throw constructErrorMessage(input, incomeParam, deductionsParam, exemptionsParam);
}

function setFormValues(incomeVal, deductionsVal, exemptionsVal) {
    document.getElementById('agi').value = incomeVal;
    document.getElementById('itd').value = deductionsVal;
    document.getElementById('npe').value = exemptionsVal;
}

function getParams() {
    var incomeParam = getParameterByName('income');
    var deductionsParam = getParameterByName('deductions');
    var exemptionsParam = getParameterByName('exemptions');

    if (deductionsParam == '')
        deductionsParam = '0';

    if (exemptionsParam == '')
        exemptionsParam = '1';

    setFormValues(incomeParam, deductionsParam, exemptionsParam);

    return createInputObject(incomeParam, deductionsParam, exemptionsParam);
}

function getFormParams() {
    return {
        income: document.getElementById('agi').value,
        deductions: document.getElementById('itd').value,
        exemptions: document.getElementById('npe').value
    };
}

function createInputObjectFromParams(formParams) {
    return createInputObject(formParams.income, formParams.deductions, formParams.exemptions);
}

function overrideSubmit(onsubmit_function) {
    // from: http://stackoverflow.com/a/1395254
    // also see: http://stackoverflow.com/a/3350260
    function jsSubmit() {
        onsubmit_function();
        return false;
    }
    document.forms['input_form'].onsubmit = jsSubmit;
}

function doesSupportHistoryAPI() {
    // from: http://stackoverflow.com/a/9446306
    return !!(window.history && history.pushState);
}

function encodeQueryData(data) {
    // from: http://stackoverflow.com/a/111545
    var ret = [];
    for (var d in data)
        ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
    return ret.join('&');
}

function dynamicSubmit() {
    var formParams = getFormParams();

    try {
        var input = createInputObjectFromParams(formParams);

        history.pushState(formParams, '', '?' + encodeQueryData(formParams));

        calcAndDisplay(input);
    }
    catch (err_output) {
        history.pushState(formParams, '', '?' + encodeQueryData(formParams));

        setResults(err_output);
    }
}

function main() {
    try {
        var input = getParams();

        calcAndDisplay(input);
    }
    catch (err_output) {
        setResults(err_output);
        var input = null;
    }

    if (doesSupportHistoryAPI()) {
        overrideSubmit(dynamicSubmit);

        window.onpopstate = function(event) {
            var formParams = event.state;

            if (formParams)
                setFormValues(formParams.income, formParams.deductions, formParams.exemptions);

            try {
                var input = formParams ? createInputObjectFromParams(formParams) : getParams();

                calcAndDisplay(input);
            }
            catch (err_output) {
                setResults(err_output);
            }
        };
    }
}

main();
<commit_msg>Auto-populate default income of 50,000<commit_after>
default_income = '50,000';

function getParameterByName(name) {
    // from: http://stackoverflow.com/a/901144/908430
    name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
    var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'),
        results = regex.exec(location.search);
    return results == null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}

function createHtmlFragment(htmlStr) {
    // from: http://stackoverflow.com/a/814649/908430
    // also, see: http://ejohn.org/blog/dom-documentfragments/
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}

function setResults(htmlStr) {
    var results = document.getElementById('results');
    results.innerHTML = '';

    var fragment = createHtmlFragment(htmlStr);
    results.appendChild(fragment);

    if (htmlStr != '')
        results.style.visibility = 'visible';
    else
        results.style.visibility = 'hidden';
}

function calculateAndDisplayTaxes(income, deductions, exemptions) {
    var resultsHtml = '';

    function w(kind, text, amt) {
        if (kind == 'a')
            resultsHtml += '
' + text + ': ' + amt + '
';
        else if (kind == 'l_start')
            resultsHtml += '

' + text + '
';
        else if (kind == 'b')
            resultsHtml += '
' + text + '
';
        else if (kind == 'l_end')
            resultsHtml += '
' + text + ': ' + amt + '

';
        else if (kind == 't')
            resultsHtml += '
' + text + '
';
        else if (kind == 'x') // html decorators
            resultsHtml += text;
    }

    function do_nothing_w(kind, text, amt) {}

    var my_tax = calc_taxes(taxRates, income, deductions, exemptions, w),
        my_tax_plus = calc_taxes(taxRates, income + 1.0, deductions, exemptions, do_nothing_w);

    var marginal_tax_rate = (my_tax_plus - my_tax) * 100.0;
    w('a', 'Marginal Tax Rate', marginal_tax_rate.toFixed(2) + '%');

    return resultsHtml;
}

function calcAndDisplay(input) {
    setResults(calculateAndDisplayTaxes(input.income, input.deductions, input.exemptions));
}

function constructErrorMessage(input, incomeParam, deductionsParam, exemptionsParam) {
    var errorMessage = '';

    if (!incomeParam)
        errorMessage += 'Income must be specified.
';
    if (incomeParam && input.income == 0)
        errorMessage += 'Income must be greater than zero.
';
    if (incomeParam && (!isValidNumber(incomeParam) || !(input.income >= 0)))
        errorMessage += "Income: '" + incomeParam + "'" + ' is not valid.
';
    if (!deductionsParam)
        errorMessage += 'The total dollar amount of tax deductions must be specified.
';
    if (deductionsParam && (!isValidNumber(deductionsParam) || !(input.deductions >= 0)))
        errorMessage += "Deductions: '" + deductionsParam + "'" + ' is not valid.
';
    if (!exemptionsParam)
        errorMessage += 'The number of personal exemptions must be specified.
';
    if (exemptionsParam && (!isValidNumber(exemptionsParam) || !(input.exemptions >= 0)))
        errorMessage += "Exemptions: '" + exemptionsParam + "'" + ' is not valid.
';

    return errorMessage;
}

function isValidNumber(text) { // from: http://stackoverflow.com/a/21907572/908430
    return /^[0-9,.]*$/.test(text);
}

function removeCommas(text) {
    return text.replace(/,/g, '');
}

function createInputObject(incomeParam, deductionsParam, exemptionsParam) {
    var input = {
        income: parseFloat(removeCommas(incomeParam)),
        deductions: parseFloat(removeCommas(deductionsParam)),
        exemptions: parseFloat(removeCommas(exemptionsParam))
    };

    if (isValidNumber(incomeParam) && input.income > 0 &&
        isValidNumber(deductionsParam) && input.deductions >= 0 &&
        isValidNumber(exemptionsParam) && input.exemptions >= 0)
        return input;
    else
        throw constructErrorMessage(input, incomeParam, deductionsParam, exemptionsParam);
}

function setFormValues(incomeVal, deductionsVal, exemptionsVal) {
    document.getElementById('agi').value = incomeVal;
    document.getElementById('itd').value = deductionsVal;
    document.getElementById('npe').value = exemptionsVal;
}

function getParams() {
    var incomeParam = getParameterByName('income');
    var deductionsParam = getParameterByName('deductions');
    var exemptionsParam = getParameterByName('exemptions');

    // if there are no parameters, use default income
    if (incomeParam === '' && deductionsParam === '' && exemptionsParam === '')
        incomeParam = default_income;

    if (deductionsParam == '')
        deductionsParam = '0';

    if (exemptionsParam == '')
        exemptionsParam = '1';

    setFormValues(incomeParam, deductionsParam, exemptionsParam);

    return createInputObject(incomeParam, deductionsParam, exemptionsParam);
}

function getFormParams() {
    return {
        income: document.getElementById('agi').value,
        deductions: document.getElementById('itd').value,
        exemptions: document.getElementById('npe').value
    };
}

function createInputObjectFromParams(formParams) {
    return createInputObject(formParams.income, formParams.deductions, formParams.exemptions);
}

function overrideSubmit(onsubmit_function) {
    // from: http://stackoverflow.com/a/1395254
    // also see: http://stackoverflow.com/a/3350260
    function jsSubmit() {
        onsubmit_function();
        return false;
    }
    document.forms['input_form'].onsubmit = jsSubmit;
}

function doesSupportHistoryAPI() {
    // from: http://stackoverflow.com/a/9446306
    return !!(window.history && history.pushState);
}

function encodeQueryData(data) {
    // from: http://stackoverflow.com/a/111545
    var ret = [];
    for (var d in data)
        ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
    return ret.join('&');
}

function dynamicSubmit() {
    var formParams = getFormParams();

    try {
        var input = createInputObjectFromParams(formParams);

        history.pushState(formParams, '', '?' + encodeQueryData(formParams));

        calcAndDisplay(input);
    }
    catch (err_output) {
        history.pushState(formParams, '', '?' + encodeQueryData(formParams));

        setResults(err_output);
    }
}

function main() {
    try {
        calcAndDisplay(getParams());
    }
    catch (err_output) {
        setResults(err_output);
    }

    if (doesSupportHistoryAPI()) {
        overrideSubmit(dynamicSubmit);

        window.onpopstate = function(event) {
            var formParams = event.state;

            if (formParams)
                setFormValues(formParams.income, formParams.deductions, formParams.exemptions);

            try {
                var input = formParams ? createInputObjectFromParams(formParams) : getParams();

                calcAndDisplay(input);
            }
            catch (err_output) {
                setResults(err_output);
            }
        };
    }
}

main();
<|endoftext|>


<commit_before> function showBatchWork(keyword){
    	window.clearInterval(inter);
		$("#main").load("remote/batch.jsp",{"tb":"room","keyword":keyword});
    }
 function doBatchWork(frm){
	 window.clearInterval(inter);
		var data=$(frm).serialize();

		$("#main").load("remote/batch.jsp#"+Math.random(),data);
		return false;
	}

 function viewroom(roomid){
 	window.clearInterval(inter);
		$("#main").load("view.jsp",{"tb":"room","id":roomid},reformatview);
 }
	function add_value(tbname){
		let newValue=prompt(tbname,"");
		if(newValue!=null){
			$.post("callStatic.jsp",{"c":"com.newsclan.crud.Tools","m":"insert",
				"tbname":tbname,
				"newValue":newValue,
					},
			    function(data,status,xhr){
				console.log("new_id:"+data.id);
				let newOption="<option value='"+data.id+"' selected >"+newValue+"</option>";
				$("select[name="+tbname+"_id]").append(newOption);
			    }
			,"json");
		}

	}
	function dbid(evt){
		var data=$(evt.target).parent().parent().attr("id");
		return parseInt(data);
	}
	function view(rowid){
		window.clearTimeout(inter);
		var tbname=$("#tbname").val();
		$("#main").load("view.jsp",{"tb":tbname,"id":rowid},reformatview);

		//window.open("view.jsp?tb="+tbname+"&id="+rowid);
	}
	function edit(rowid){
		window.clearTimeout(inter);
		var tbname=$("#tbname").val();
		$("#main").load("add.jsp",{"tb":tbname,"id":rowid},reformatform);
	}

	function report_row_del(tbname,rowid){
		var ans=confirm('确定删除编号'+rowid);
		if(ans){
			$.post("del.jsp",{"tbname":tbname,"id":rowid},new function(){
				 window.setTimeout("$('#main').load('report.jsp?page=0')",1000);
			});
		}
	}
	function del(rowid){
		var ans=confirm('确定删除编号'+rowid);
		var tbname=$("#tbname").val();
		if(ans){
			$.post("del.jsp",{"tbname":tbname,"id":rowid},new function(){
				 window.setTimeout("mainLoad('"+tbname+"')",1000);
			});
		}
	}

	function addButton(main){
		//$("#main tr :last-child").css("background","#eeeeee");
		var buttons=""+
		""+
		""
								+"";

		buttons+="	";

		$("#main tr").append(buttons);
		$(".glyphicon-eye-open").bind("click",function(evt){
			view(dbid(evt));
		});
		$(".glyphicon-trash").bind("click",function(evt){
			del(dbid(evt));
		});
		$(".glyphicon-edit").bind("click",function(evt){
			edit(dbid(evt));
		});
		$(".glyphicon-refresh").bind("click",function(evt){
			goodsPriceSync(dbid(evt));
		});

	}
	function filteNext(preSelect){
		console.log("pre:",preSelect.name,preSelect.value);
		var tr=$(preSelect).parent().parent();
		var nextSelect=tr.next().children().last().children().last();
		if(nextSelect!=null&&nextSelect.length>0&&nextSelect[0].tagName=="SELECT"){
			var keyword=preSelect.name;
			var keyvalue=preSelect.value;
			console.log("reload:",keyword,keyvalue);
		    loadSelect(nextSelect,"keyword="+keyword+"&keyvalue="+keyvalue);
		}
	}
	function loadSelect(input,append){
		var input_name=input.attr("name");
		var default_value=input.val();
		if(input[0].nodeName=="SPAN")  //view use span for tag, text() for value
			 	default_value=input.text();
		var tbname=input_name.substring(0,input_name.length-3);
		if(input.attr("fr")!=undefined) tbname=input.attr("fr");;
		var td=input.parent();
		td.load("select.jsp?tbname="+tbname+"&input_name="+input_name+"&value="+default_value+"&"+append);

	}
	function loadFile(input){
		var input_name=input.attr("name");
		var default_value=input.val();
		if(input[0].nodeName=="SPAN")  //view use span for tag, text() for value
			 	default_value=input.text();
		var td=input.parent();
		input[0].id=input_name;
		input[0].type="hidden";

		var html=$(td).html()+"";

		$(td).html(html);

	}
	function reformatform(){
		$("input[name$=_file]").each(function(){
			loadFile($(this));
		});
		$("input[name$=_id]").each(function(){
				loadSelect($(this));
		});
		$("input[postLoad=1]").each(function(){
			loadSelect($(this));
		});
		$(".input_date").datepicker();
		$(".input_datetime").datetimepicker(
				{   showSecond: false,
		            timeFormat: 'hh:mm:ss',
		            stepHour: 1,
		            stepMinute: 1,
		            stepSecond: 1
		        });
		if(tableName.endsWith('config')){
			$("textarea").attr("rows",20).attr("cols",80);
		}else{
				$("textarea").ckeditor();
		}
		$("span[class='modifiable']").each(function(){
			var tbname=$(this).attr("tb");
			var fdname=$(this).attr("fd");
			var rid=$(this).attr("rid");

			if(tbname==tableName){
				$(this)[0].title="双击修改";
				if($(this).html()=="")$(this).html("_");
				$(this).dblclick(function(){
					var newValue=prompt("手工修改",$(this).text());
					if(newValue!=null&&newValue!=$(this).text()){
						//alert("update "+tbname+" set "+fdname+"="+newValue+" where id="+rid);

						$.post("callStatic.jsp",{"c":"com.newsclan.crud.Tools","m":"update",
							"tbname":tbname,
							"fdname":fdname,
							"value":newValue,
							"id":rid

								},new function(){
							 window.setTimeout("refresh();",500);
						});

					}
				});
			}else{
				$(this)[0].title="双击选择";
				$(this).dblclick(function(){
					var span=$(this);
					var oldValue=$(this).html();
					var fdname=tbname+"_id";
					//if(fdname.startsWith("t_")) fdname=fdname.substring(2);
					var td=$(this).parent();
					if(fdname=="pcdata_id"){ //适配某易语言系统中文字段名
						fdname="批次uid";
					}
					var selectURL="select.jsp?tbname="+tbname+"&input_name="+fdname+"&value=-1";
					$(this).load("select.jsp",{"tbname":tbname,"input_name":fdname,"value":-1},
						function(text,status,http){
							if(status=="success"){
								var sel=$("select[name="+fdname+"]");
								if(sel.length==0){
									sel=td.find("select");
								}
								var opt=$("option");
								var nowValue=opt.map(function(){if($(this).text()==oldValue) return($(this).val())});
								sel.val(nowValue);
								sel.removeAttr("onchange");
								sel.change(function(){
									var newValue=$(this).val();
									//alert(fdname);
									$.post("callStatic.jsp",{"c":"com.newsclan.crud.Tools","m":"update",
										"tbname":tableName,
										"fdname":fdname,
										"value":newValue,
										"id":rid

											},new function(){
										 window.setTimeout("refresh();",500);
									});
								});
								sel.blur(function(){
									span.html(oldValue);
								});
								sel.focus();
							}
						}

					);
					//	alert("update "+tableName+" set "+tbname+"_id="+oldValue+" where id="+rid);
				});

			}
		});
	}
	function reformatview(){
		$("span[name$=_id]").each(function(){
			loadSelect($(this));
		});
	}

	function loadImport(){
		window.clearInterval(inter);
		$("#main").load("import.jsp?"+Math.random(),{},reformatform);
	}

	function loadReport(){
		window.clearInterval(inter);
		$("#main").load("report_select.jsp?"+Math.random(),{},reformatform);
	}

	function passChange(){
		window.clearInterval(inter);
		$("#main").load("passChange.jsp?"+Math.random());
	}
	function checkIfPasswordIsSame(frm){
		if($("#password").val()!=$("#password2").val()){
			alert("两次密码不一致");
			return false;
		}
		return true;
	}
	function mainLoad(tbname,pageNum,keyword){
		tableName=tbname;
		if (typeof(pageNum)=='undefined') pageNum=thepage;
		if (typeof(keyword)=='undefined'||keyword=="") keyword=searchKeyword;
		thepage=pageNum;
		searchKeyword=keyword;
		window.clearInterval(inter);
		$("#main").load("list.jsp",{"tb":tbname,"pageNum":pageNum,"keyword":keyword},function(text,status,http){

			if(status=="success"){
				addButton($("#main"));
				reformatform();
				$("#tbname").after("");
				$("#addrow").click(function(){
					$("#main").load("add.jsp",{tb:tbname},reformatform);
				});
				if($("#auto")[0].checked){
					autoRefresh();
				}
			}
		});
		lastLoad="mainLoad('"+tbname+"',"+pageNum+",'"+keyword+"');";

	}
	function reportPage(page){
		$('#main').load('report.jsp?page='+page);
		lastLoad="reportPage("+page+");";
	}
	function pageUp(tbname,pageNum){
		mainLoad(tbname,pageNum-1,searchKeyword);
	}
	function pageDown(tbname,pageNum){
		mainLoad(tbname,pageNum+1,searchKeyword);
	}
	function showReport(frm){
		var data=$(frm).serialize();
		$("#main").load("report_select.jsp?"+Math.random(),data,reformatform);
		lastLoad="reportPage(0);";
		return false;
	}

	function submitAdd(tbname){
		var data=$("#addForm").serialize();
		$.post("add.jsp",data,new function(){
			 mainLoad(tbname,0,searchKeyword);
		});
	}
	function submitTable(){
		var data=$("#frmAddTable").serialize();
		var tbname=$("#tb_name").val();

		$.post("addTable.jsp",data,new function(){
			 window.setTimeout("mainLoad('"+tbname+"',0,'"+searchKeyword+"')",1000);
		});
	}
	function addTable(){
		$("#main").empty();
		$("#main").append("<form method=post onSubmit='submitTable()' id='frmAddTable'>

</form>");
		$("#tb_adding").append("
表名<input type=text id=tb_name name=tb_name value='tb_'>	中文<input type=text name=tb_title value='信息'>
");
		$("#tb_adding").append("
列名	类型	中文
");
		$("#frmAddTable").append("<input type=button onclick='submitTable()' value='确定'><input type=reset value='重置'>");
		addColumn();

	}
	function addColumn(){
		var row="
";
		row+="<input name=fd_name type=text>	";
		row+="<input name=fd_type type=text value='varchar(32)'>	";
		row+="<input name=fd_title type=text>	";
		row+="
";
		$("#tb_adding").append(row);
	}
	function search(keyword){
		window.clearTimeout(inter);
		if(lastLoad.indexOf("selectMenu")!=-1){
			selectMenu(menu_id,keyword);
		}else{
			searchKeyword=keyword;
			inter=window.setTimeout("mainLoad(tableName,0,'"+keyword+"');",500);
		}
	}
	function reload(){
		$("#main").empty();
		$("#main").append("");
		window.setTimeout("mainLoad('"+tableName+"',0);",500);
		alert("reload");
	}
	function refresh(){
		eval(lastLoad);
	}
	function autoRefresh(){
		window.clearTimeout(inter);
		inter=window.setTimeout('refresh()',5000);
	}
 	function keyDownSearch(e) {
        // 兼容FF和IE和Opera
        var theEvent = e || window.event;
        var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
        if (code == 13) {
            if(theEvent.target==$("#keyword")[0]){
            		search($("#keyword").val());
            		$("#keyword")[0].select();
            }
            if(theEvent.target.tagName=="INPUT"){
         	   $(theEvent.target).parent().parent().next("tr").find("input").focus();
            }
            return false;
        }
        return true;
    }
 	function selectMenu(id){
 		menu_id=id;
 		if(arguments.length==1){

 			filter=$("#keyword").val();
 	 		lastLoad="selectMenu("+id+",'"+filter+"')";
 	 		$("#main").load("report_select.jsp?id="+id+"&filter="+filter);

 		}else{
 			id=arguments[0];
 			filter=arguments[1];
 			lastLoad="selectMenu("+id+",'"+filter+"')";
 			$("#main").load("report_select.jsp?id="+id+"&filter="+filter);
 		}
	}
        function autoHide(){
                if(fullMenu){
                  $("#menu a").hide();
                  $("#menu a[used=yes]").show();
                }else{
                  $("#menu a").show();
                }
                fullMenu=!fullMenu;
        }
   	document.onkeydown=keyDownSearch;
        var inter=null;
        //var stid=null;
        var tableName="userdata";
        var searchKeyword="";
        var thepage=0;
        var lastLoad="";
        var menu_id=0;
        var fullMenu=true;
	$(document).ready(function(){
	  $("a").click(function(){
	    $(this).attr("used","yes");
	  });
	});

<commit_msg>Update main.js<commit_after> function showBatchWork(keyword){
    	window.clearInterval(inter);
		$("#main").load("remote/batch.jsp",{"tb":"room","keyword":keyword});
    }
 function doBatchWork(frm){
	 window.clearInterval(inter);
		var data=$(frm).serialize();

		$("#main").load("remote/batch.jsp#"+Math.random(),data);
		return false;
	}

 function viewroom(roomid){
 	window.clearInterval(inter);
		$("#main").load("view.jsp",{"tb":"room","id":roomid},reformatview);
 }
	function add_value(tbname){
		let newValue=prompt(tbname,"");
		if(newValue!=null){
			$.post("callStatic.jsp",{"c":"com.newsclan.crud.Tools","m":"insert",
				"tbname":tbname,
				"newValue":newValue,
					},
			    function(data,status,xhr){
				console.log("new_id:"+data.id);
				let newOption="<option value='"+data.id+"' selected >"+newValue+"</option>";
				$("select[name="+tbname+"_id]").append(newOption);
			    }
			,"json");
		}

	}
	function dbid(evt){
		var data=$(evt.target).parent().parent().attr("id");
		return parseInt(data);
	}
	function view(rowid){
		window.clearTimeout(inter);
		var tbname=$("#tbname").val();
		$("#main").load("view.jsp",{"tb":tbname,"id":rowid},reformatview);

		//window.open("view.jsp?tb="+tbname+"&id="+rowid);
	}
	function edit(rowid){
		window.clearTimeout(inter);
		var tbname=$("#tbname").val();
		$("#main").load("add.jsp",{"tb":tbname,"id":rowid},reformatform);
	}

	function report_row_del(tbname,rowid){
		var ans=confirm('确定删除编号'+rowid);
		if(ans){
			$.post("del.jsp",{"tbname":tbname,"id":rowid},new function(){
				 window.setTimeout("$('#main').load('report.jsp?page=0')",1000);
			});
		}
	}
	function del(rowid){
		var ans=confirm('确定删除编号'+rowid);
		var tbname=$("#tbname").val();
		if(ans){
			$.post("del.jsp",{"tbname":tbname,"id":rowid},new function(){
				 window.setTimeout("mainLoad('"+tbname+"')",1000);
			});
		}
	}

	function addButton(main){
		//$("#main tr :last-child").css("background","#eeeeee");
		var buttons=""+
		""+
		""
								+"";

		buttons+="	";

		$("#main tr").append(buttons);
		$(".glyphicon-eye-open").bind("click",function(evt){
			view(dbid(evt));
		});
		$(".glyphicon-trash").bind("click",function(evt){
			del(dbid(evt));
		});
		$(".glyphicon-edit").bind("click",function(evt){
			edit(dbid(evt));
		});
		$(".glyphicon-refresh").bind("click",function(evt){
			goodsPriceSync(dbid(evt));
		});

	}
	function filteNext(preSelect){
		console.log("pre:",preSelect.name,preSelect.value);
		var tr=$(preSelect).parent().parent();
		var nextSelect=tr.next().children().last().children().last();
		if(nextSelect!=null&&nextSelect.length>0&&nextSelect[0].tagName=="SELECT"){
			var keyword=preSelect.name;
			var keyvalue=preSelect.value;
			console.log("reload:",keyword,keyvalue);
		    loadSelect(nextSelect,"keyword="+keyword+"&keyvalue="+keyvalue);
		}
	}
	function loadSelect(input,append){
		var input_name=input.attr("name");
		var default_value=input.val();
		if(input[0].nodeName=="SPAN")  //view use span for tag, text() for value
			 	default_value=input.text();
		var tbname=input_name.substring(0,input_name.length-3);
		if(input.attr("fr")!=undefined) tbname=input.attr("fr");;
		var td=input.parent();
		td.load("select.jsp?tbname="+tbname+"&input_name="+input_name+"&value="+default_value+"&"+append);

	}
	function loadFile(input){
		var input_name=input.attr("name");
		var default_value=input.val();
		if(input[0].nodeName=="SPAN")  //view use span for tag, text() for value
			 	default_value=input.text();
		var td=input.parent();
		input[0].id=input_name;
		input[0].type="hidden";

		var html=$(td).html()+"";

		$(td).html(html);

	}
	function reformatform(){
		$("input[name$=_file]").each(function(){
			loadFile($(this));
		});
		$("input[name$=_id]").each(function(){
				loadSelect($(this));
		});
		$("input[postLoad=1]").each(function(){
			loadSelect($(this));
		});
		$(".input_date").datepicker();
		$(".input_datetime").datetimepicker(
				{   showSecond: false,
		            timeFormat: 'hh:mm:ss',
		            stepHour: 1,
		            stepMinute: 1,
		            stepSecond: 1
		        });
		if(tableName.endsWith('config')){
			$("textarea").attr("rows",20).attr("cols",80);
		}else{
				$("textarea").ckeditor();
		}
		$("span[class='modifiable']").each(function(){
			var tbname=$(this).attr("tb");
			var fdname=$(this).attr("fd");
			var rid=$(this).attr("rid");

			if(tbname==tableName){
				$(this)[0].title="双击修改";
				if($(this).html()=="")$(this).html("_");
				$(this).dblclick(function(){
					var newValue=prompt("手工修改",$(this).text());
					if(newValue!=null&&newValue!=$(this).text()){
						//alert("update "+tbname+" set "+fdname+"="+newValue+" where id="+rid);

						$.post("callStatic.jsp",{"c":"com.newsclan.crud.Tools","m":"update",
							"tbname":tbname,
							"fdname":fdname,
							"value":newValue,
							"id":rid

								},new function(){
							 window.setTimeout("refresh();",500);
						});

					}
				});
			}else{
				$(this)[0].title="双击选择";
				$(this).dblclick(function(){
					var span=$(this);
					var oldValue=$(this).html();
					var fdname=tbname+"_id";
					//if(fdname.startsWith("t_")) fdname=fdname.substring(2);
					var td=$(this).parent();
					if(fdname=="pcdata_id"){ //适配某易语言系统中文字段名
						fdname="批次uid";
					}
					var selectURL="select.jsp?tbname="+tbname+"&input_name="+fdname+"&value=-1";
					$(this).load("select.jsp",{"tbname":tbname,"input_name":fdname,"value":-1},
						function(text,status,http){
							if(status=="success"){
								var sel=$("select[name="+fdname+"]");
								if(sel.length==0){
									sel=td.find("select");
								}
								var opt=$("option");
								var nowValue=opt.map(function(){if($(this).text()==oldValue) return($(this).val())});
								sel.val(nowValue);
								sel.removeAttr("onchange");
								sel.change(function(){
									var newValue=$(this).val();
									//alert(fdname);
									$.post("callStatic.jsp",{"c":"com.newsclan.crud.Tools","m":"update",
										"tbname":tableName,
										"fdname":fdname,
										"value":newValue,
										"id":rid

											},new function(){
										 window.setTimeout("refresh();",500);
									});
								});
								sel.blur(function(){
									span.html(oldValue);
								});
								sel.focus();
							}
						}

					);
					//	alert("update "+tableName+" set "+tbname+"_id="+oldValue+" where id="+rid);
				});

			}
		});
	}
	function reformatview(){
		$("span[name$=_id]").each(function(){
			loadSelect($(this));
		});
	}

	function loadImport(){
		window.clearInterval(inter);
		$("#main").load("import.jsp?"+Math.random(),{},reformatform);
	}

	function loadReport(){
		window.clearInterval(inter);
		$("#main").load("report_select.jsp?"+Math.random(),{},reformatform);
	}

	function passChange(){
		window.clearInterval(inter);
		$("#main").load("passChange.jsp?"+Math.random());
	}
	function checkIfPasswordIsSame(frm){
		if($("#password").val()!=$("#password2").val()){
			alert("两次密码不一致");
			return false;
		}
		return true;
	}
	function mainLoad(tbname,pageNum,keyword){
		tableName=tbname;
		if (typeof(pageNum)=='undefined') pageNum=thepage;
		if (typeof(keyword)=='undefined'||keyword=="") keyword=searchKeyword;
		thepage=pageNum;
		searchKeyword=keyword;
		window.clearInterval(inter);
		$("#main").load("list.jsp",{"tb":tbname,"pageNum":pageNum,"keyword":keyword},function(text,status,http){

			if(status=="success"){
				addButton($("#main"));
				reformatform();
				$("#tbname").after("");
				$("#addrow").click(function(){
					$("#main").load("add.jsp",{tb:tbname},reformatform);
				});
				if($("#auto")[0].checked){
					autoRefresh();
				}
			}
		});
		lastLoad="mainLoad('"+tbname+"',"+pageNum+",'"+keyword+"');";

	}
	function reportPage(page){
		$('#main').load('report.jsp?page='+page);
		lastLoad="reportPage("+page+");";
	}
	function pageUp(tbname,pageNum){
		mainLoad(tbname,pageNum-1,searchKeyword);
	}
	function pageDown(tbname,pageNum){
		mainLoad(tbname,pageNum+1,searchKeyword);
	}
	function showReport(frm){
		var data=$(frm).serialize();
		$("#main").load("report_select.jsp?"+Math.random(),data,reformatform);
		lastLoad="reportPage(0);";
		return false;
	}

	function submitAdd(tbname){
		var data=$("#addForm").serialize();
		$.post("add.jsp",data,new function(){
			 mainLoad(tbname,0,searchKeyword);
		});
	}
	function submitTable(){
		var data=$("#frmAddTable").serialize();
		var tbname=$("#tb_name").val();

		$.post("addTable.jsp",data,new function(){
			 window.setTimeout("mainLoad('"+tbname+"',0,'"+searchKeyword+"')",1000);
		});
	}
	function addTable(){
		$("#main").empty();
		$("#main").append("<form method=post onSubmit='submitTable()' id='frmAddTable'>

</form>");
		$("#tb_adding").append("
表名<input type=text id=tb_name name=tb_name value='tb_'>	中文<input type=text name=tb_title value='信息'>
");
		$("#tb_adding").append("
列名	类型	中文
");
		$("#frmAddTable").append("<input type=button onclick='submitTable()' value='确定'><input type=reset value='重置'>");
		addColumn();

	}
	function addColumn(){
		var row="
";
		row+="<input name=fd_name type=text>	";
		row+="<input name=fd_type type=text value='varchar(32)'>	";
		row+="<input name=fd_title type=text>	";
		row+="
";
		$("#tb_adding").append(row);
	}
	function search(keyword){
		window.clearTimeout(inter);
		if(lastLoad.indexOf("selectMenu")!=-1){
			selectMenu(menu_id,keyword);
		}else{
			searchKeyword=keyword;
			inter=window.setTimeout("mainLoad(tableName,0,'"+keyword+"');",500);
		}
	}
	function reload(){
		$("#main").empty();
		$("#main").append("");
		window.setTimeout("mainLoad('"+tableName+"',0);",500);
		alert("reload");
	}
	function refresh(){
		eval(lastLoad);
	}
	function autoRefresh(){
		window.clearTimeout(inter);
		inter=window.setTimeout('refresh()',5000);
	}
 	function keyDownSearch(e) {
        // 兼容FF和IE和Opera
        var theEvent = e || window.event;
        var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
        if (code == 13) {
            if(theEvent.target==$("#keyword")[0]){
            		search($("#keyword").val());
            		$("#keyword")[0].select();
            }
            if(theEvent.target.tagName=="INPUT"){
         	   $(theEvent.target).parent().parent().next("tr").find("input").focus();
            }
            return false;
        }
        return true;
    }
 	function selectMenu(id){
 		menu_id=id;
 		if(arguments.length==1){

 			filter=$("#keyword").val();
 	 		lastLoad="selectMenu("+id+",'"+filter+"')";
 	 		$("#main").load("report_select.jsp?id="+id+"&filter="+filter);

 		}else{
 			id=arguments[0];
 			filter=arguments[1];
 			lastLoad="selectMenu("+id+",'"+filter+"')";
 			$("#main").load("report_select.jsp?id="+id+"&filter="+filter);
 		}
	}
        function autoHide(){
                if(fullMenu){
                  $("#menu a").hide();
                  $("#menu a[used=yes]").show();
                }else{
                  $("#menu a").show();
                }
                fullMenu=!fullMenu;
        }
   	document.onkeydown=keyDownSearch;
        var inter=null;
        //var stid=null;
        var tableName="userdata";
        var searchKeyword="";
        var thepage=0;
        var lastLoad="";
        var menu_id=0;
        var fullMenu=true;
	$(document).ready(function(){
	  $("a").click(function(){
	    $(this).attr("used","yes");
	    $(this).css("font-weight","bold");
	  });
	});

<|endoftext|>


<commit_before>myApp.directive('stonegraph', function() {
	return {
		restrict: 'E',
		scope : {
			stones: '=',
			active: '='
		},
		replace: true,
		templateUrl : 'js/directives/stoneGraph.html',
		link : function (scope, element, attrs) {
			scope.init = initGraph(scope.active, scope.stones);
		}
	};
});

function initGraph(coreElement, stones) {

	console.log("init Graph");
	console.log(coreElement);
	console.log(stones);
	var dataset = {
        nodes: [
                { name: "Adam" },
                { name: "Bob" },
                { name: "Carrie" },
        ],
        edges: [
                { source: 0, target: 1 },
                { source: 0, target: 2 },
		]
	};

	var w = 700;
	var h = 800;
	var colors = d3.scale.category10();

	var zoom = d3.behavior.zoom()
		.scaleExtent([1, 10])
		.on("zoom", zoomed);

	var drag = d3.behavior.drag()
		.origin(function(d) {return d; })
		.on("dragstart", dragstarted)
		.on("drag", dragged)
		.on("dragend", dragended);

	var svg = d3.select(".graph")
		.append("svg")
		.attr("width", w)
		.attr("height", h)

	//background rectangle for detecting zooming and dragging of the whole graph
	var rect = svg.append("rect")
    	.attr("width", w)
    	.attr("height", h)
    	.style("fill", "none")
    	.style("pointer-events", "all")
    	.call(zoom);

	// container layer for nodes and edges
	var container = svg
		.append("g")
		.attr('width', w)
		.attr('height', h);

	var force = d3.layout.force()
		.nodes(dataset.nodes)
		.links(dataset.edges)
		.size([w, h])
		.linkDistance([400])
		.charge([-1000])
		.start();

	var edges = container.selectAll("line")
		.data(dataset.edges)
		.enter()
		.append("line")
		.style("stroke", "#ccc")
		.style("stroke-width", 1);

	var nodes = container.selectAll("rect")
		.data(dataset.nodes)
		.enter()
		.append("rect")
		.attr("width", 100)
		.attr("height", 100)
		.style("fill", function(d, i) {
			return colors(i);
		})
		.each(function(obj) {
			console.log(obj);
		})
		.call(force.drag);

	force.on("tick", function() {

		edges.attr("x1", function(d) { return d.source.x; })
			.attr("y1", function(d) { return d.source.y; })
			.attr("x2", function(d) { return d.target.x; })
			.attr("y2", function(d) { return d.target.y; });

		nodes.attr("x", function(d) { return d.x; })
			.attr("y", function(d) { return d.y; });
	});

	// force.on("start", function() {
	// 	edges.attr("x1", function(d) { return d.source.x; })
	// 		.attr("y1", function(d) { return d.source.y; })
	// 		.attr("x2", function(d) { return d.target.x; })
	// 		.attr("y2", function(d) { return d.target.y; });

	// 	nodes.attr("x", function(d) { return d.x; })
	// 		.attr("y", function(d) { return d.y; });
	// })

	function zoomed() {
	  container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
	}

	function dragstarted(d) {
	  d3.event.sourceEvent.stopPropagation();
	  d3.select(this).classed("dragging", true);
	}

	function dragged(d) {
	  d3.select(this).attr("x", d.x = d3.event.x).attr("y", d.y = d3.event.y);

	}

	function dragended(d) {
	  d3.select(this).classed("dragging", false);
	}
}<commit_msg>add controls to the graph to expand it<commit_after>var dataset = {
        nodes: [
                { name: "Adam" },
                { name: "Bob" },
                { name: "Carrie" },
        ],
        edges: [
                { source: 0, target: 1 },
                { source: 0, target: 2 },
		]
	};

myApp.directive('stonegraph', function() {
	return {
		restrict: 'E',
		scope : {
			stones: '=',
			active: '='
		},
		replace: true,
		templateUrl : 'js/directives/stoneGraph.html',
		link : function (scope, element, attrs) {
			scope.init = initGraph(scope.active, scope.stones);
		}
	};
});

function initGraph() {

	console.log("init Graph");
	//console.log(coreElement);
	//console.log(stones);

	var w = 700;
	var h = 800;
	var colors = d3.scale.category10();

	var zoom = d3.behavior.zoom()
		.scaleExtent([1, 10])
		.on("zoom", zoomed);

	var drag = d3.behavior.drag()
		.origin(function(d) {return d; })
		.on("dragstart", dragstarted)
		.on("drag", dragged)
		.on("dragend", dragended);

	var svg = d3.select(".graph")
		.append("svg")
		.attr("width", w)
		.attr("height", h)

	//background rectangle for detecting zooming and dragging of the whole graph
	var rect = svg.append("rect")
    	.attr("width", w)
    	.attr("height", h)
    	.style("fill", "none")
    	.style("pointer-events", "all")
    	.call(zoom);

	// container layer for nodes and edges
	var container = svg
		.append("g")
		.attr('width', w)
		.attr('height', h);

	var force = d3.layout.force()
		.nodes(dataset.nodes)
		.links(dataset.edges)
		.size([w, h])
		.linkDistance([400])
		.charge([-1000])
		.start();

	var edges = container.selectAll("line")
		.data(dataset.edges)
		.enter()
		.append("line")
		.style("stroke", "#ccc")
		.style("stroke-width", 1);

	var nodeGroups = container.selectAll("g")
		.data(dataset.nodes)
		.enter()
		.append('g')
		.call(force.drag);

	nodeGroups.each(function(d, i) {
		d3.select(this).append("rect")
	 		.attr("width", 100)
	 		.attr("height", 100)
	 		.style("fill", function(d, i) {
	 			return colors(i);
	 		})
	 	});

	//triangle up
	nodeGroups.each(function(d, i) {
		createExpansionButton(this, "0,0, 50,-50, 100,0");
	});

	//triangle left
	nodeGroups.each(function(d, i) {
		createExpansionButton(this, "0,0, -50,50, 0,100");
	});

	//triangle down
	nodeGroups.each(function(d, i) {
		createExpansionButton(this, "0,100, 50,150, 100,100");
	});

	//triangle right
	nodeGroups.each(function(d, i) {
		createExpansionButton(this, "100,0, 150,50, 100,100");
	});

	var nodes = {};
	// var nodes = nodeGroups.selectAll()
	// 	.data(dataset.nodes)
	// 	.enter()
	// 	.append("rect")
	// 		.attr("width", 100)
	// 		.attr("height", 100)
	// 		.style("fill", function(d, i) {
	// 			return colors(i);
	// 		})
	// 	.call(force.drag);

	// var triangleUps = nodeGroups.selectAll("polygon")
	// 	.data(dataset.nodes)
	// 	.enter()
	// 	.append("polygon")
	// 	 	.style("stroke", "black")
	// 	 	.style("fill", "none")
	// 	 	.attr("points", function(d) {
	// 	 	 	console.log("polygon:");
	// 	 	 	console.log(d);
	// 	 	 	return d.px + "," + d.py + "," + d.px + 50 + "," + d.py + 50 + "," + d.px + 100 + "," + d.py;
	// 	 	});

	force.on("tick", function() {

		edges.attr("x1", function(d) { return d.source.x; })
			.attr("y1", function(d) { return d.source.y; })
			.attr("x2", function(d) { return d.target.x; })
			.attr("y2", function(d) { return d.target.y; });

		nodeGroups.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
	});

	// force.on("start", function() {
	// 	edges.attr("x1", function(d) { return d.source.x; })
	// 		.attr("y1", function(d) { return d.source.y; })
	// 		.attr("x2", function(d) { return d.target.x; })
	// 		.attr("y2", function(d) { return d.target.y; });

	// 	nodes.attr("x", function(d) { return d.x; })
	// 		.attr("y", function(d) { return d.y; });
	// })

	function zoomed() {
	  container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
	}

	function dragstarted(d) {
	  d3.event.sourceEvent.stopPropagation();
	  d3.select(this).classed("dragging", true);
	}

	function dragged(d) {
	  d3.select(this).attr("x", d.x = d3.event.x).attr("y", d.y = d3.event.y);

	}

	function dragended(d) {
	  d3.select(this).classed("dragging", false);
	}

	function expand(d) {
		//dataset.nodes.push({ name: "David" });
		//dataset.edges.push({source: 2, target: 3});
		initGraph();
	}

	function triangleMouseDown(d) {
		d3.select(this)
			.style('fill', 'black');
	}

	function triangleMouseUp(d) {
		d3.select(this)
			.style('fill', 'none');
	}

	function createExpansionButton(element, figure) {
		d3.select(element)
			.append("polygon")
	 	 		.style("stroke", "black")
	 	 		.style("fill", "none")
	 	 		.attr("points", function(d) {
	 	 	 		return figure;
	 	 		})
	 	 	.style("pointer-events", "all")
	 	 	.on("click", expand)
	 	 	.on("mousedown", triangleMouseDown)
	 	 	.on("mouseup", triangleMouseUp);
	}
}<|endoftext|>


<commit_before>(function (Shreds) { 'use strict';
  var name = 'subscription';
  var spinner = null;

  Shreds.components.push(name);
  Shreds[name] = {
    startSpinner: function (el) {
      spinner = Ladda.create(el);
      spinner.start();
    },
    stopSpinner: function () { spinner.stop(); },
    init: function () { setupFileUpload(); }
  };

  function setupFileUpload() {
    var spinner = Ladda.create($('.fileinput-button')[0]);

    $('#fileupload').fileupload({
      dataType: 'json'
    }).on('fileuploadstart', function () {
      spinner.start();
    }).on('fileuploaddone', function (e, data) {
      var result = data.result;
      if (result && result.error) {
        Shreds.notification.error(result.error);
        spinner.stop();
      } else if (result && result.watch) { Shreds.watch.add(result.watch); }
    }).on('fileuploadfail', function () {
      Shreds.notification.error('Can\'t upload file.');
      spinner.stop();
    }).on('spinnerstop', function () { spinner.stop(); });
  }
})(window.Shreds);

<commit_msg>Relayout fileupload source<commit_after>(function (Shreds) { 'use strict';
  var name = 'subscription';
  var spinner = null;

  Shreds.components.push(name);
  Shreds[name] = {
    startSpinner: function (el) {
      spinner = Ladda.create(el);
      spinner.start();
    },
    stopSpinner: function () { spinner.stop(); },
    init: function () { setupFileUpload(); }
  };

  function setupFileUpload() {
    var spinner = Ladda.create($('.fileinput-button')[0]);

    $('#fileupload').fileupload({ dataType: 'json' })
      .on('fileuploadstart', function () { spinner.start(); })
      .on('fileuploaddone', function (e, data) {
        var result = data.result;
        if (result && result.error) {
          Shreds.notification.error(result.error);
          spinner.stop();
        } else if (result && result.watch) { Shreds.watch.add(result.watch); }
      })
      .on('fileuploadfail', function () {
        Shreds.notification.error('Can\'t upload file.');
        spinner.stop();
      })
      .on('spinnerstop', function () { spinner.stop(); });
  }
})(window.Shreds);

<|endoftext|>