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

/**
 * RoundButton is the base class for round buttons.
 *
 * @author John Blanco (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 */

import DerivedProperty from '../../../axon/js/DerivedProperty.js';
import Shape from '../../../kite/js/Shape.js';
import merge from '../../../phet-core/js/merge.js';
import Circle from '../../../scenery/js/nodes/Circle.js';
import Node from '../../../scenery/js/nodes/Node.js';
import PaintColorProperty from '../../../scenery/js/util/PaintColorProperty.js';
import RadialGradient from '../../../scenery/js/util/RadialGradient.js';
import sun from '../sun.js';
import ButtonInteractionState from './ButtonInteractionState.js';
import ButtonNode from './ButtonNode.js';

// constants
const HIGHLIGHT_GRADIENT_LENGTH = 5; // In screen coords, which are roughly pixels.

class RoundButton extends ButtonNode {

  /**
   * @param {ButtonModel} buttonModel
   * @param {Property} interactionStateProperty - a Property that is used to drive the visual appearance of the button
   * @param {Object} [options]
   */
  constructor( buttonModel, interactionStateProperty, options ) {

    options = merge( {

      // {Node|null} what appears on the button (icon, label, etc.)
      content: null,

      radius: ( options && options.content ) ? null : 30,
      cursor: 'pointer',

      // If these are not the same, the larger one will be used to calculate the size of the button
      xMargin: 5, // Minimum margin in x direction, i.e. on left and right
      yMargin: 5, // Minimum margin in y direction, i.e. on top and bottom

      fireOnDown: false,

      // pointer area dilation
      touchAreaDilation: 0, // radius dilation for touch area
      mouseAreaDilation: 0, // radius dilation for mouse area

      // pointer area shift
      touchAreaXShift: 0,
      touchAreaYShift: 0,
      mouseAreaXShift: 0,
      mouseAreaYShift: 0,

      stroke: undefined, // undefined by default, which will cause a stroke to be derived from the base color
      lineWidth: 0.5, // Only meaningful if stroke is non-null

      // Class that determines the button's appearance for the values of interactionStateProperty.
      // See RoundButton.ThreeDAppearanceStrategy for an example of the interface required.
      buttonAppearanceStrategy: RoundButton.ThreeDAppearanceStrategy
    }, options );

    if ( !options.content ) {
      assert && assert( typeof options.radius === 'number', `invalid radius: ${options.radius}` );
    }

    if ( options.radius ) {
      assert && assert( options.xMargin < options.radius, 'xMargin cannot be larger than radius' );
      assert && assert( options.yMargin < options.radius, 'yMargin cannot be larger than radius' );
    }

    // Compute the radius of the button. radius will not be falsey if content is also falsey
    const buttonRadius = options.radius ||
                         Math.max( options.content.width + options.xMargin * 2, options.content.height + options.yMargin * 2 ) / 2;

    if ( options.content && options.radius ) {
      const previousContent = options.content;
      const minScale = Math.min(
        ( options.radius - options.xMargin ) * 2 / previousContent.width,
        ( options.radius - options.yMargin ) * 2 / previousContent.height );

      options.content = new Node( {
        children: [ previousContent ],
        scale: minScale
      } );
    }

    // Create the circular part of the button.
    const buttonBackground = new Circle( buttonRadius, {
      lineWidth: options.lineWidth
    } );

    super( buttonModel, buttonBackground, interactionStateProperty, options );

    // Get the actual button radius after calling super, so that buttonAppearanceStrategy has applied the stroke.
    // This accounts for stroke + lineWidth, which is important when setting pointer areas and focus highlight.
    // See https://github.com/phetsims/sun/issues/660
    const buttonBackgroundRadius = buttonBackground.localBounds.width / 2;

    // Set pointer areas.
    this.touchArea = Shape.circle( options.touchAreaXShift, options.touchAreaYShift,
      buttonBackgroundRadius + options.touchAreaDilation );
    this.mouseArea = Shape.circle( options.mouseAreaXShift, options.mouseAreaYShift,
      buttonBackgroundRadius + options.mouseAreaDilation );

    // pdom - focus highlight is circular for round buttons, with a little bit of padding
    // between button shape and inner edge of highlight
    this.focusHighlight = Shape.circle( 0, 0, buttonBackgroundRadius + 5 );
  }
}

/**
 * ThreeDAppearanceStrategy is a value for RoundButton options.buttonAppearanceStrategy. It makes a round button
 * look 3D-ish by using gradients that create the appearance of highlighted and shaded edges. The gradients are
 * set up to make the light source appear to be in the upper left.
 */
class ThreeDAppearanceStrategy {

  /**
   * @param {Node,Paintable} buttonBackground - the Node for the button's background, sans content
   * @param {Property.<ButtonInteractionState>} interactionStateProperty
   * @param {Property.<ColorDef>} baseColorProperty
   * @param {Object} [options]
   */
  constructor( buttonBackground, interactionStateProperty, baseColorProperty, options ) {

    // Dynamic colors
    // TODO https://github.com/phetsims/sun/issues/553 missing "Property" suffix for all PaintColorProperty names
    const baseBrighter8 = new PaintColorProperty( baseColorProperty, { luminanceFactor: 0.8 } );
    const baseBrighter7 = new PaintColorProperty( baseColorProperty, { luminanceFactor: 0.7 } );
    const baseBrighter3 = new PaintColorProperty( baseColorProperty, { luminanceFactor: 0.3 } );
    const baseDarker1 = new PaintColorProperty( baseColorProperty, { luminanceFactor: -0.1 } );
    const baseDarker2 = new PaintColorProperty( baseColorProperty, { luminanceFactor: -0.2 } );
    const baseDarker4 = new PaintColorProperty( baseColorProperty, { luminanceFactor: -0.4 } );
    const baseDarker5 = new PaintColorProperty( baseColorProperty, { luminanceFactor: -0.5 } );
    const baseTransparent = new DerivedProperty( [ baseColorProperty ], color => color.withAlpha( 0 ) );

    // Set up variables needed to create the various gradient fills and otherwise modify the appearance
    const buttonRadius = buttonBackground.width / 2;
    const innerGradientRadius = buttonRadius - HIGHLIGHT_GRADIENT_LENGTH / 2;
    const outerGradientRadius = buttonRadius + HIGHLIGHT_GRADIENT_LENGTH / 2;
    const gradientOffset = HIGHLIGHT_GRADIENT_LENGTH / 2;

    const upFillHighlight = new RadialGradient( gradientOffset, gradientOffset, innerGradientRadius, gradientOffset, gradientOffset, outerGradientRadius )
      .addColorStop( 0, baseColorProperty )
      .addColorStop( 1, baseBrighter7 );

    const upFillShadow = new RadialGradient( -gradientOffset, -gradientOffset, innerGradientRadius, -gradientOffset, -gradientOffset, outerGradientRadius )
      .addColorStop( 0, baseTransparent )
      .addColorStop( 1, baseDarker5 );

    const overFillHighlight = new RadialGradient( gradientOffset, gradientOffset, innerGradientRadius, gradientOffset, gradientOffset, outerGradientRadius )
      .addColorStop( 0, baseBrighter3 )
      .addColorStop( 1, baseBrighter8 );

    const overFillShadow = new RadialGradient( -gradientOffset, -gradientOffset, innerGradientRadius, -gradientOffset, -gradientOffset, outerGradientRadius )
      .addColorStop( 0, baseTransparent )
      .addColorStop( 1, baseDarker5 );

    const pressedFill = new RadialGradient( -gradientOffset, -gradientOffset, 0, 0, 0, outerGradientRadius )
      .addColorStop( 0, baseDarker1 )
      .addColorStop( 0.6, baseDarker2 )
      .addColorStop( 0.8, baseColorProperty )
      .addColorStop( 1, baseBrighter8 );

    // Create and add the overlay that is used to add shading.
    const shadowNode = new Circle( buttonRadius, {
      stroke: ( typeof ( options.stroke ) === 'undefined' ) ? baseDarker4 : options.stroke,
      lineWidth: options.lineWidth,
      pickable: false
    } );
    buttonBackground.addChild( shadowNode );

    // Cache gradients
    buttonBackground.cachedPaints = [ upFillHighlight, overFillHighlight, pressedFill ];
    shadowNode.cachedPaints = [ upFillShadow, overFillShadow ];

    // Change colors to match interactionState
    function interactionStateListener( interactionState ) {

      switch( interactionState ) {

        case ButtonInteractionState.IDLE:
          buttonBackground.fill = upFillHighlight;
          shadowNode.fill = upFillShadow;
          break;

        case ButtonInteractionState.OVER:
          buttonBackground.fill = overFillHighlight;
          shadowNode.fill = overFillShadow;
          break;

        case ButtonInteractionState.PRESSED:
          buttonBackground.fill = pressedFill;
          shadowNode.fill = overFillShadow;
          break;

        default:
          throw new Error( `unsupported interactionState: ${interactionState}` );
      }
    }

    interactionStateProperty.link( interactionStateListener );

    // @public
    this.dispose = () => {
      if ( interactionStateProperty.hasListener( interactionStateListener ) ) {
        interactionStateProperty.unlink( interactionStateListener );
      }

      baseBrighter8.dispose();
      baseBrighter7.dispose();
      baseBrighter3.dispose();
      baseDarker1.dispose();
      baseDarker2.dispose();
      baseDarker4.dispose();
      baseDarker5.dispose();
      baseTransparent.dispose();
    };
  }
}

// @public
RoundButton.ThreeDAppearanceStrategy = ThreeDAppearanceStrategy;

sun.register( 'RoundButton', RoundButton );
export default RoundButton;<commit_msg>update copyright dates from daily grunt work<commit_after>// Copyright 2014-2021, University of Colorado Boulder

/**
 * RoundButton is the base class for round buttons.
 *
 * @author John Blanco (PhET Interactive Simulations)
 * @author Sam Reid (PhET Interactive Simulations)
 */

import DerivedProperty from '../../../axon/js/DerivedProperty.js';
import Shape from '../../../kite/js/Shape.js';
import merge from '../../../phet-core/js/merge.js';
import Circle from '../../../scenery/js/nodes/Circle.js';
import Node from '../../../scenery/js/nodes/Node.js';
import PaintColorProperty from '../../../scenery/js/util/PaintColorProperty.js';
import RadialGradient from '../../../scenery/js/util/RadialGradient.js';
import sun from '../sun.js';
import ButtonInteractionState from './ButtonInteractionState.js';
import ButtonNode from './ButtonNode.js';

// constants
const HIGHLIGHT_GRADIENT_LENGTH = 5; // In screen coords, which are roughly pixels.

class RoundButton extends ButtonNode {

  /**
   * @param {ButtonModel} buttonModel
   * @param {Property} interactionStateProperty - a Property that is used to drive the visual appearance of the button
   * @param {Object} [options]
   */
  constructor( buttonModel, interactionStateProperty, options ) {

    options = merge( {

      // {Node|null} what appears on the button (icon, label, etc.)
      content: null,

      radius: ( options && options.content ) ? null : 30,
      cursor: 'pointer',

      // If these are not the same, the larger one will be used to calculate the size of the button
      xMargin: 5, // Minimum margin in x direction, i.e. on left and right
      yMargin: 5, // Minimum margin in y direction, i.e. on top and bottom

      fireOnDown: false,

      // pointer area dilation
      touchAreaDilation: 0, // radius dilation for touch area
      mouseAreaDilation: 0, // radius dilation for mouse area

      // pointer area shift
      touchAreaXShift: 0,
      touchAreaYShift: 0,
      mouseAreaXShift: 0,
      mouseAreaYShift: 0,

      stroke: undefined, // undefined by default, which will cause a stroke to be derived from the base color
      lineWidth: 0.5, // Only meaningful if stroke is non-null

      // Class that determines the button's appearance for the values of interactionStateProperty.
      // See RoundButton.ThreeDAppearanceStrategy for an example of the interface required.
      buttonAppearanceStrategy: RoundButton.ThreeDAppearanceStrategy
    }, options );

    if ( !options.content ) {
      assert && assert( typeof options.radius === 'number', `invalid radius: ${options.radius}` );
    }

    if ( options.radius ) {
      assert && assert( options.xMargin < options.radius, 'xMargin cannot be larger than radius' );
      assert && assert( options.yMargin < options.radius, 'yMargin cannot be larger than radius' );
    }

    // Compute the radius of the button. radius will not be falsey if content is also falsey
    const buttonRadius = options.radius ||
                         Math.max( options.content.width + options.xMargin * 2, options.content.height + options.yMargin * 2 ) / 2;

    if ( options.content && options.radius ) {
      const previousContent = options.content;
      const minScale = Math.min(
        ( options.radius - options.xMargin ) * 2 / previousContent.width,
        ( options.radius - options.yMargin ) * 2 / previousContent.height );

      options.content = new Node( {
        children: [ previousContent ],
        scale: minScale
      } );
    }

    // Create the circular part of the button.
    const buttonBackground = new Circle( buttonRadius, {
      lineWidth: options.lineWidth
    } );

    super( buttonModel, buttonBackground, interactionStateProperty, options );

    // Get the actual button radius after calling super, so that buttonAppearanceStrategy has applied the stroke.
    // This accounts for stroke + lineWidth, which is important when setting pointer areas and focus highlight.
    // See https://github.com/phetsims/sun/issues/660
    const buttonBackgroundRadius = buttonBackground.localBounds.width / 2;

    // Set pointer areas.
    this.touchArea = Shape.circle( options.touchAreaXShift, options.touchAreaYShift,
      buttonBackgroundRadius + options.touchAreaDilation );
    this.mouseArea = Shape.circle( options.mouseAreaXShift, options.mouseAreaYShift,
      buttonBackgroundRadius + options.mouseAreaDilation );

    // pdom - focus highlight is circular for round buttons, with a little bit of padding
    // between button shape and inner edge of highlight
    this.focusHighlight = Shape.circle( 0, 0, buttonBackgroundRadius + 5 );
  }
}

/**
 * ThreeDAppearanceStrategy is a value for RoundButton options.buttonAppearanceStrategy. It makes a round button
 * look 3D-ish by using gradients that create the appearance of highlighted and shaded edges. The gradients are
 * set up to make the light source appear to be in the upper left.
 */
class ThreeDAppearanceStrategy {

  /**
   * @param {Node,Paintable} buttonBackground - the Node for the button's background, sans content
   * @param {Property.<ButtonInteractionState>} interactionStateProperty
   * @param {Property.<ColorDef>} baseColorProperty
   * @param {Object} [options]
   */
  constructor( buttonBackground, interactionStateProperty, baseColorProperty, options ) {

    // Dynamic colors
    // TODO https://github.com/phetsims/sun/issues/553 missing "Property" suffix for all PaintColorProperty names
    const baseBrighter8 = new PaintColorProperty( baseColorProperty, { luminanceFactor: 0.8 } );
    const baseBrighter7 = new PaintColorProperty( baseColorProperty, { luminanceFactor: 0.7 } );
    const baseBrighter3 = new PaintColorProperty( baseColorProperty, { luminanceFactor: 0.3 } );
    const baseDarker1 = new PaintColorProperty( baseColorProperty, { luminanceFactor: -0.1 } );
    const baseDarker2 = new PaintColorProperty( baseColorProperty, { luminanceFactor: -0.2 } );
    const baseDarker4 = new PaintColorProperty( baseColorProperty, { luminanceFactor: -0.4 } );
    const baseDarker5 = new PaintColorProperty( baseColorProperty, { luminanceFactor: -0.5 } );
    const baseTransparent = new DerivedProperty( [ baseColorProperty ], color => color.withAlpha( 0 ) );

    // Set up variables needed to create the various gradient fills and otherwise modify the appearance
    const buttonRadius = buttonBackground.width / 2;
    const innerGradientRadius = buttonRadius - HIGHLIGHT_GRADIENT_LENGTH / 2;
    const outerGradientRadius = buttonRadius + HIGHLIGHT_GRADIENT_LENGTH / 2;
    const gradientOffset = HIGHLIGHT_GRADIENT_LENGTH / 2;

    const upFillHighlight = new RadialGradient( gradientOffset, gradientOffset, innerGradientRadius, gradientOffset, gradientOffset, outerGradientRadius )
      .addColorStop( 0, baseColorProperty )
      .addColorStop( 1, baseBrighter7 );

    const upFillShadow = new RadialGradient( -gradientOffset, -gradientOffset, innerGradientRadius, -gradientOffset, -gradientOffset, outerGradientRadius )
      .addColorStop( 0, baseTransparent )
      .addColorStop( 1, baseDarker5 );

    const overFillHighlight = new RadialGradient( gradientOffset, gradientOffset, innerGradientRadius, gradientOffset, gradientOffset, outerGradientRadius )
      .addColorStop( 0, baseBrighter3 )
      .addColorStop( 1, baseBrighter8 );

    const overFillShadow = new RadialGradient( -gradientOffset, -gradientOffset, innerGradientRadius, -gradientOffset, -gradientOffset, outerGradientRadius )
      .addColorStop( 0, baseTransparent )
      .addColorStop( 1, baseDarker5 );

    const pressedFill = new RadialGradient( -gradientOffset, -gradientOffset, 0, 0, 0, outerGradientRadius )
      .addColorStop( 0, baseDarker1 )
      .addColorStop( 0.6, baseDarker2 )
      .addColorStop( 0.8, baseColorProperty )
      .addColorStop( 1, baseBrighter8 );

    // Create and add the overlay that is used to add shading.
    const shadowNode = new Circle( buttonRadius, {
      stroke: ( typeof ( options.stroke ) === 'undefined' ) ? baseDarker4 : options.stroke,
      lineWidth: options.lineWidth,
      pickable: false
    } );
    buttonBackground.addChild( shadowNode );

    // Cache gradients
    buttonBackground.cachedPaints = [ upFillHighlight, overFillHighlight, pressedFill ];
    shadowNode.cachedPaints = [ upFillShadow, overFillShadow ];

    // Change colors to match interactionState
    function interactionStateListener( interactionState ) {

      switch( interactionState ) {

        case ButtonInteractionState.IDLE:
          buttonBackground.fill = upFillHighlight;
          shadowNode.fill = upFillShadow;
          break;

        case ButtonInteractionState.OVER:
          buttonBackground.fill = overFillHighlight;
          shadowNode.fill = overFillShadow;
          break;

        case ButtonInteractionState.PRESSED:
          buttonBackground.fill = pressedFill;
          shadowNode.fill = overFillShadow;
          break;

        default:
          throw new Error( `unsupported interactionState: ${interactionState}` );
      }
    }

    interactionStateProperty.link( interactionStateListener );

    // @public
    this.dispose = () => {
      if ( interactionStateProperty.hasListener( interactionStateListener ) ) {
        interactionStateProperty.unlink( interactionStateListener );
      }

      baseBrighter8.dispose();
      baseBrighter7.dispose();
      baseBrighter3.dispose();
      baseDarker1.dispose();
      baseDarker2.dispose();
      baseDarker4.dispose();
      baseDarker5.dispose();
      baseTransparent.dispose();
    };
  }
}

// @public
RoundButton.ThreeDAppearanceStrategy = ThreeDAppearanceStrategy;

sun.register( 'RoundButton', RoundButton );
export default RoundButton;<|endoftext|>


<commit_before>setViewer6Upload=function(upload){
    var header;
    var index;
    var buttonToReplace;
    upload.callOnClick(function(){
        header = upload.header();
        index=0;
    });
    var url = '/rest3d/upload',
        uploadButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .text('Upload')
            .on('click', function (){
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .text('Abort')
                    .on('click', function () {
                        $this.remove();
                        data.abort();
                    });
                data.submit();
                buttonToReplace=$(this);
                //.always(function () {
                //     $this.remove();
                // });
        }),
        // show the name of the file nicely
        formatName = function(data,file){
            var i = file.name.lastIndexOf('/');
            return file.name.substring(i+1);
        },
        convertButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .text('Convert')
            .on('click', function () {
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .text('Convert')
                    .prop('disabled',true)
                // user rest to convert dae into glTF
                var callback = function(data) {
                    $this.prop('disabled',true);
                    if(data.result.output){console.debug(data.result.output);}
                    if(data.result.code){console.debug("Exit code: "+data.result.code);}
                    if (data.error){
                        var span = $('
Error code='+data.error.code+' :: '+data.error.message+'
');
                        data.context.append(span);
                    } else {
                        // ennumerate all resulting files
                        var $conve = upload.header(data.file.name);
                        $.each(data.result.files, function (index, file) {
                            var $download = $("<button>Downl..</button>").on("click",function(){
                                var gitHtml = $('');
                                gitPanel = $('body').append(gitHtml);
                            });
                        console.debug(decodeURIComponent(file.url))
                        var $dialog = $("<button>Launch</button>").on("click",function(){
                            pleaseWait(true);
                            var url = decodeURIComponent(file.url);
                            glTF.load(url, parse_gltf);
                            notif(url);
                            pleaseWait(false);
                        });
                            // function(parent,link,button1,button2,button3){
                            upload.convert($conve,formatName(data,file),$dialog,$("<button>Display</button>"),$download);
                            // var span = '

'+formatName(data,file)+'';
                            // // endsWith
                            // if (file.url.indexOf('.json', file.url.length - '.json'.length) !== -1) {
                            //     var url='/viewer/viewer4.html?file=/rest3d/upload/'+decodeURIComponent(file.name);
                            //     span += ' ->  View '+formatName(data,file)+'';
                            // }
                            // span += '
';
                            // data.context.append($(span));
                        });
                    }
                }

                rest3d.convert(data,callback);
            });

    upload.object.on('fileuploadadd', function (e, data) {
        upload.object=$(this);
        data.context = header;
        $.each(data.files, function (index, file) {
            if (!index) {
                upload.upload(header,file.name,uploadButton.clone(true).data(data));
            }
            else{this.upload(header,file.name);}
        });
    }).on('fileuploadprocessalways', function (e, data) {
            var indexI = data.index,
            file = data.files[indexI],
             node = $(data.context.children('div')[index+1]);
        if (file.preview) {
            node
                .prepend('
')
                .prepend(file.preview);
        }
        if (file.error) {
          GUI.addTooltip({
                    parent: node.find('button'),
                    content: file.error,
                });
        }
        if (indexI + 1 === data.files.length) {
            node.find('button')
                .text('Upload')
                .prop('disabled', !!data.files.error);
        }
        index++;
    }).on('fileuploadprogressall', function (e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        upload.progress.setValue(progress);
    }).on('fileuploaddone', function (e, data) {
        $.each(data.result.files, function (index, file) {
            file.assetName = data.result.files[index].name;
            var $node = convertButton.clone(true).data({file: file, context: data.context})
                .text('Convert')
                .prop('disabled', !/dae$/i.test(file.url));
            buttonToReplace
                .replaceWith($node);
        });
    }).on('fileuploadfail', function (e, data) {
        if (!data.result) {
            $(data.context.children()[0])
                .append('
')
                .append('error communicating with server')
                .find('button').remove();
        } else
        $.each(data.result.files, function (index, file) {
            var error = $('').text(file.error);
            $(data.context.children()[index])
                .append('
')
                .append(error)
                .find('button').remove();
        });
    });
}
<commit_msg>Load GLTF for uppload assets workaround #4<commit_after>setViewer6Upload=function(upload){
    var header;
    var index;
    var buttonToReplace;
    upload.callOnClick(function(){
        header = upload.header();
        index=0;
    });
    var url = '/rest3d/upload',
        uploadButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .text('Upload')
            .on('click', function (){
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .text('Abort')
                    .on('click', function () {
                        $this.remove();
                        data.abort();
                    });
                data.submit();
                buttonToReplace=$(this);
                //.always(function () {
                //     $this.remove();
                // });
        }),
        // show the name of the file nicely
        formatName = function(data,file){
            var i = file.name.lastIndexOf('/');
            return file.name.substring(i+1);
        },
        convertButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .text('Convert')
            .on('click', function () {
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .text('Convert')
                    .prop('disabled',true)
                // user rest to convert dae into glTF
                var callback = function(data) {
                    $this.prop('disabled',true);
                    if(data.result.output){console.debug(data.result.output);}
                    if(data.result.code){console.debug("Exit code: "+data.result.code);}
                    if (data.error){
                        var span = $('
Error code='+data.error.code+' :: '+data.error.message+'
');
                        data.context.append(span);
                    } else {
                        // ennumerate all resulting files
                        var $conve = upload.header(data.file.name);
                        $.each(data.result.files, function (index, file) {
                            var $download = $("<button>Downl..</button>").on("click",function(){
                                var gitHtml = $('');
                                gitPanel = $('body').append(gitHtml);
                            });
                        console.debug(decodeURIComponent(file.url))
                        var $dialog = $("<button>Launch</button>").on("click",function(){
                            var url = decodeURIComponent(file.url);
                            glTF.load(url, parse_gltf);
                            // notif(url);
                        });
                            // function(parent,link,button1,button2,button3){
                            upload.convert($conve,formatName(data,file),$dialog,$("<button>Display</button>"),$download);
                            // var span = '

'+formatName(data,file)+'';
                            // // endsWith
                            // if (file.url.indexOf('.json', file.url.length - '.json'.length) !== -1) {
                            //     var url='/viewer/viewer4.html?file=/rest3d/upload/'+decodeURIComponent(file.name);
                            //     span += ' ->  View '+formatName(data,file)+'';
                            // }
                            // span += '
';
                            // data.context.append($(span));
                        });
                    }
                }

                rest3d.convert(data,callback);
            });

    upload.object.on('fileuploadadd', function (e, data) {
        upload.object=$(this);
        data.context = header;
        $.each(data.files, function (index, file) {
            if (!index) {
                upload.upload(header,file.name,uploadButton.clone(true).data(data));
            }
            else{this.upload(header,file.name);}
        });
    }).on('fileuploadprocessalways', function (e, data) {
            var indexI = data.index,
            file = data.files[indexI],
             node = $(data.context.children('div')[index+1]);
        if (file.preview) {
            node
                .prepend('
')
                .prepend(file.preview);
        }
        if (file.error) {
          GUI.addTooltip({
                    parent: node.find('button'),
                    content: file.error,
                });
        }
        if (indexI + 1 === data.files.length) {
            node.find('button')
                .text('Upload')
                .prop('disabled', !!data.files.error);
        }
        index++;
    }).on('fileuploadprogressall', function (e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        upload.progress.setValue(progress);
    }).on('fileuploaddone', function (e, data) {
        $.each(data.result.files, function (index, file) {
            file.assetName = data.result.files[index].name;
            var $node = convertButton.clone(true).data({file: file, context: data.context})
                .text('Convert')
                .prop('disabled', !/dae$/i.test(file.url));
            buttonToReplace
                .replaceWith($node);
        });
    }).on('fileuploadfail', function (e, data) {
        if (!data.result) {
            $(data.context.children()[0])
                .append('
')
                .append('error communicating with server')
                .find('button').remove();
        } else
        $.each(data.result.files, function (index, file) {
            var error = $('').text(file.error);
            $(data.context.children()[index])
                .append('
')
                .append(error)
                .find('button').remove();
        });
    });
}
<|endoftext|>


<commit_before>setViewer6Upload=function(upload){
    var header;
    var index;
    var buttonToReplace;
    upload.callOnClick(function(){
        header = upload.header();
        index=0;
    });
    var url = '/rest3d/upload',
        uploadButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .text('Upload')
            .on('click', function (){
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .text('Abort')
                    .on('click', function () {
                        $this.remove();
                        data.abort();
                    });
                data.submit();
                buttonToReplace=$(this);
                //.always(function () {
                //     $this.remove();
                // });
        }),
        // show the name of the file nicely
        formatName = function(data,file){
            var i = file.name.lastIndexOf('/');
            return file.name.substring(i+1);
        },
        convertButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .text('Convert')
            .on('click', function () {
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .text('Converting...')
                    .prop('disabled',true)
                // user rest to convert dae into glTF
                var callback = function(data) {
                    $this.prop('disabled',true);
                    if(data.result.output){console.debug(data.result.output);}
                    if(data.result.code){console.debug("Exit code: "+data.result.code);}
                    if (data.error){
                        var span = $('
Error code='+data.error.code+' :: '+data.error.message+'
');
                        data.context.append(span);
                    } else {
                        // ennumerate all resulting files
                        var $conve = upload.header(data.file.name);
                        $.each(data.result.files, function (index, file) {
                            var $dialog = $("<button>Dialog</button>").on("click",function(){
                                var gitHtml = '

';
                                gitPanel = $('body').append(gitHtml);
                                $("#"+file.name).dialog({
                                autoOpen: true,
                                width: 800,
                                height: 600,
                                open: function (ev, ui) {
                                    $('#myIframe').attr('src', decodeURIComponent(file.url));
                                },
                            })
                            })
                            // function(parent,link,button1,button2,button3){
                            upload.convert($conve,formatName(data,file),$dialog,$("<button>Display</button>"),$("<button>Downlo</button>"));
                            // var span = '

'+formatName(data,file)+'';
                            // // endsWith
                            // if (file.url.indexOf('.json', file.url.length - '.json'.length) !== -1) {
                            //     var url='/viewer/viewer4.html?file=/rest3d/upload/'+decodeURIComponent(file.name);
                            //     span += ' ->  View '+formatName(data,file)+'';
                            // }
                            // span += '
';
                            // data.context.append($(span));
                        });
                    }
                }

                rest3d.convert(data,callback);
            });

    upload.object.on('fileuploadadd', function (e, data) {
        upload.object=$(this);
        data.context = header;
        $.each(data.files, function (index, file) {
            if (!index) {
                upload.upload(header,file.name,uploadButton.clone(true).data(data));
            }
            else{this.upload(header,file.name);}
        });
    }).on('fileuploadprocessalways', function (e, data) {
            var indexI = data.index,
            file = data.files[indexI],
             node = $(data.context.children('div')[index+1]);
        if (file.preview) {
            node
                .prepend('
')
                .prepend(file.preview);
        }
        if (file.error) {
          GUI.addTooltip({
                    parent: node.find('button'),
                    content: file.error,
                });
        }
        if (indexI + 1 === data.files.length) {
            node.find('button')
                .text('Upload')
                .prop('disabled', !!data.files.error);
        }
        index++;
    }).on('fileuploadprogressall', function (e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        upload.progress.setValue(progress);
    }).on('fileuploaddone', function (e, data) {
        $.each(data.result.files, function (index, file) {
            file.assetName = data.result.files[index].name;
            var $node = convertButton.clone(true).data({file: file, context: data.context})
                .text('Convert')
                .prop('disabled', !/dae$/i.test(file.url));
            buttonToReplace
                .replaceWith($node);
        });
    }).on('fileuploadfail', function (e, data) {
        if (!data.result) {
            $(data.context.children()[0])
                .append('
')
                .append('error communicating with server')
                .find('button').remove();
        } else
        $.each(data.result.files, function (index, file) {
            var error = $('').text(file.error);
            $(data.context.children()[index])
                .append('
')
                .append(error)
                .find('button').remove();
        });
    });
}
<commit_msg>Convert fix #14<commit_after>setViewer6Upload=function(upload){
    var header;
    var index;
    var buttonToReplace;
    upload.callOnClick(function(){
        header = upload.header();
        index=0;
    });
    var url = '/rest3d/upload',
        uploadButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .text('Upload')
            .on('click', function (){
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .text('Abort')
                    .on('click', function () {
                        $this.remove();
                        data.abort();
                    });
                data.submit();
                buttonToReplace=$(this);
                //.always(function () {
                //     $this.remove();
                // });
        }),
        // show the name of the file nicely
        formatName = function(data,file){
            var i = file.name.lastIndexOf('/');
            return file.name.substring(i+1);
        },
        convertButton = $('<button/>')
            .addClass('btn')
            .prop('disabled', true)
            .text('Convert')
            .on('click', function () {
                var $this = $(this),
                    data = $this.data();
                $this
                    .off('click')
                    .text('Convert')
                    .prop('disabled',true)
                // user rest to convert dae into glTF
                var callback = function(data) {
                    $this.prop('disabled',true);
                    if(data.result.output){console.debug(data.result.output);}
                    if(data.result.code){console.debug("Exit code: "+data.result.code);}
                    if (data.error){
                        var span = $('
Error code='+data.error.code+' :: '+data.error.message+'
');
                        data.context.append(span);
                    } else {
                        // ennumerate all resulting files
                        var $conve = upload.header(data.file.name);
                        $.each(data.result.files, function (index, file) {
                            var $dialog = $("<button>Dialog</button>").on("click",function(){
                                var gitHtml = $('

');
                                gitPanel = $('body').append(gitHtml);
                                gitHtml.dialog({
                                autoOpen: true,
                                width: 800,
                                height: 600,
                                open: function (ev, ui) {
                                    gitHtml.find('iframe').attr('src', decodeURIComponent(file.url));
                                },
                            })
                            })
                            // function(parent,link,button1,button2,button3){
                            upload.convert($conve,formatName(data,file),$dialog,$("<button>Display</button>"),$("<button>Downlo</button>"));
                            // var span = '

'+formatName(data,file)+'';
                            // // endsWith
                            // if (file.url.indexOf('.json', file.url.length - '.json'.length) !== -1) {
                            //     var url='/viewer/viewer4.html?file=/rest3d/upload/'+decodeURIComponent(file.name);
                            //     span += ' ->  View '+formatName(data,file)+'';
                            // }
                            // span += '
';
                            // data.context.append($(span));
                        });
                    }
                }

                rest3d.convert(data,callback);
            });

    upload.object.on('fileuploadadd', function (e, data) {
        upload.object=$(this);
        data.context = header;
        $.each(data.files, function (index, file) {
            if (!index) {
                upload.upload(header,file.name,uploadButton.clone(true).data(data));
            }
            else{this.upload(header,file.name);}
        });
    }).on('fileuploadprocessalways', function (e, data) {
            var indexI = data.index,
            file = data.files[indexI],
             node = $(data.context.children('div')[index+1]);
        if (file.preview) {
            node
                .prepend('
')
                .prepend(file.preview);
        }
        if (file.error) {
          GUI.addTooltip({
                    parent: node.find('button'),
                    content: file.error,
                });
        }
        if (indexI + 1 === data.files.length) {
            node.find('button')
                .text('Upload')
                .prop('disabled', !!data.files.error);
        }
        index++;
    }).on('fileuploadprogressall', function (e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        upload.progress.setValue(progress);
    }).on('fileuploaddone', function (e, data) {
        $.each(data.result.files, function (index, file) {
            file.assetName = data.result.files[index].name;
            var $node = convertButton.clone(true).data({file: file, context: data.context})
                .text('Convert')
                .prop('disabled', !/dae$/i.test(file.url));
            buttonToReplace
                .replaceWith($node);
        });
    }).on('fileuploadfail', function (e, data) {
        if (!data.result) {
            $(data.context.children()[0])
                .append('
')
                .append('error communicating with server')
                .find('button').remove();
        } else
        $.each(data.result.files, function (index, file) {
            var error = $('').text(file.error);
            $(data.context.children()[index])
                .append('
')
                .append(error)
                .find('button').remove();
        });
    });
}
<|endoftext|>


<commit_before>/**
 * This script contains functionality common to all GeoTag-X pages.
 */
$(document).ready(function(){
	// Initialize Bootstrap's opt-in javascript components.
	$("[data-toggle='tooltip']").tooltip();
	$("[data-toggle='popover']").popover();

	// Initialize Smooth scroll.
	$("a").smoothScroll();

    $(function () {

        var filterList = {

            init: function () {

                // MixItUp plugin
                // http://mixitup.io
                $('#portfoliolist-three').mixitup({
                    targetSelector: '.portfolio',
                    filterSelector: '.filter',
                    effects: ['fade'],
                    easing: 'snap',
                    // call the hover effect
                    onMixEnd: filterList.hoverEffect()
                });
            },
            hoverEffect: function () {
                $("[rel='tooltip']").tooltip();
                // Simple parallax effect
                $('#portfoliolist-three .portfolio .portfolio-hover').hover(
        function(){
            $(this).find('.image-caption').slideDown(250); //.fadeIn(250)
        },
        function(){
            $(this).find('.image-caption').slideUp(250); //.fadeOut(205)
        }
    );
            }

        };

        // Run the show!
        filterList.init();
    });
    $('.magnefig').each(function(){
        $(this).magnificPopup({
            type:'image',
            removalDelay: 300,
            mainClass: 'mfp-fade'
        })
    });

    $(".image-caption a").tooltip();

var Script = function () {

//    bxslider

    // $('.bxslider').show();
    // $('.bxslider').bxSlider({
    //     minSlides: 4,
    //     maxSlides: 4,
    //     slideWidth: 276,
    //     slideMargin: 20
    // });

}();

	(function() {

   			$('').appendTo($('body'));

			$(window).scroll(function() {

				if($(this).scrollTop() != 0) {
					$('#back-to-top').fadeIn();
				} else {
					$('#back-to-top').fadeOut();
				}

			});

			$('#back-to-top').click(function() {
				$('body,html').animate({scrollTop:0},600);
			});

	})();
});
<commit_msg>Remove unused code<commit_after>/**
 * This script contains functionality common to all GeoTag-X pages.
 */
$(document).ready(function(){
	// Initialize Bootstrap's opt-in javascript components.
	$("[data-toggle='tooltip']").tooltip();
	$("[data-toggle='popover']").popover();

	// Initialize Smooth scroll.
	$("a").smoothScroll();

    $(function () {

        var filterList = {

            init: function () {

                // MixItUp plugin
                // http://mixitup.io
                $('#portfoliolist-three').mixitup({
                    targetSelector: '.portfolio',
                    filterSelector: '.filter',
                    effects: ['fade'],
                    easing: 'snap',
                    // call the hover effect
                    onMixEnd: filterList.hoverEffect()
                });
            },
            hoverEffect: function () {
                $("[rel='tooltip']").tooltip();
                // Simple parallax effect
                $('#portfoliolist-three .portfolio .portfolio-hover').hover(
        function(){
            $(this).find('.image-caption').slideDown(250); //.fadeIn(250)
        },
        function(){
            $(this).find('.image-caption').slideUp(250); //.fadeOut(205)
        }
    );
            }

        };

        // Run the show!
        filterList.init();
    });

	(function() {

   			$('').appendTo($('body'));

			$(window).scroll(function() {

				if($(this).scrollTop() != 0) {
					$('#back-to-top').fadeIn();
				} else {
					$('#back-to-top').fadeOut();
				}

			});

			$('#back-to-top').click(function() {
				$('body,html').animate({scrollTop:0},600);
			});

	})();
});
<|endoftext|>


<commit_before>var tc = tc || {};
tc.gam = tc.gam || {};
tc.gam.project_widgets = tc.gam.project_widgets || {};

tc.gam.project_widgets.need_form = function(options) {
    tc.util.log('project.need_form');
    var dom = options.dom,
        cached_events = [],
        self = {};

    //Helper function to make the jqDropDown plugin more robust
    //since you can't set multiple classes at a time.
    //  id - the selector for the select element, also used to
    //       identify the generated markup
    //  defaultVal - Used to identify the unselectable default value
    var initDropDown = function(id, defaultVal) {
      //Apply jqDropDown to our select element
      tc.jQ('#' + id).jqDropDown({
        toggleBtnName:'ddSelect',
        optionListName:'ddSelectOptions',
        containerName:'dd-' + id,
        optionChanged: function() {
          //manually trigger the change event on the select element
          //so that Merlin validation will trigger properly
          tc.jQ('#' + id).change();
        }
      }).data('default', defaultVal);

      //Add the default container css class (important, common styles on this guy)
      tc.jQ('.dd-' + id).addClass('ddSelectContainer');

      //There's no default value, something is always selected, so it's always valid
      if (!defaultVal) {
        tc.jQ('.dd-' + id).addClass('ddNoDefault');
        tc.jQ('.dd-' + id + ' .ddSelect').addClass('valid has-been-focused').removeClass('not-valid');
      }
    };

    var disableCustomEventInputs = function(disable, merlin) {
      var inputs = [merlin.current_step.inputs.month,
          merlin.current_step.inputs.day,
          merlin.current_step.inputs.time,
          merlin.current_step.inputs.address];

        tc.jQ.each(inputs, function(i, input) {
          if (input.dom.is('select')) {
            if (disable) {
              input.dom.next('.ddSelectContainer').find('.ddSelect').addClass('disabled');
            } else {
              input.dom.next('.ddSelectContainer').find('.ddSelect').removeClass('disabled');
            }
          }

          if (disable) {
            input.dom.addClass('disabled');
          } else {
            input.dom.removeClass('disabled');
          }
        });
    };

    /**
     * Function: initMerlin
     * Initialize the merlin object for validation of the modal dialog.
     */
    var initMerlin = function(need_id) {
        var merlin;

        //We are using merlin only for the built-in validation in this case.
        merlin =  new tc.merlin(options.app, {
            name:'need_form',
            dom:tc.jQ('.add-need.merlin'),
            next_button:tc.jQ('a.need-submit'),
            first_step:'need_form',
            use_hashchange:false,
            data: {
              type:'volunteer',
              request:null,
              quantity:null,
              description:null,
              date:null,
              time:null,
              duration:null,
              project_id:null,
              address:null
            },
            steps: {
                'need_form': {
                    selector: '.step.add-need-step',
                    next_step:'need-submit',
                    inputs: {
                        'quantity': {
                            selector: '#vol-quantity',
                            validators: ['required', 'numeric'],
                            hint:'Qty'
                        },
                        'request': {
                            selector: '#vol-job',
                            validators: ['required', 'max-100'],
                            hint:'Job Title - DJ, Cashier, etc'
                        },
                        'description': {
                          selector: '#vol-desc',
                          validators: ['required', 'max-200'],
                          hint:'Write a brief description of the volunteer tasks and skills.',
                          counter:{
                            selector:'.charlimit.title',
                            limit:200
                          }
                        },
                        'duration': {
                          selector: '#vol-hours',
                          validators: ['required', 'numeric'],
                          hint:''
                        },
                        'address': {
                          selector: '#vol-street',
                          validators: function(merlinInput, $element, step, onSubmit) {
                            if ($element.is('.disabled')) {
                              return {valid:true};
                            } else {
                              return tc.validate($element, ['required']);
                            }
                          },
                          hint:'Address'
                        },
                        'month': {
                          selector: '#vol-month',
                          validators: function(input, $element, step, submit) {
                            var $ddSelect = $element.next('.ddSelectContainer').find('.ddSelect');

                            if ($element.is('.disabled')) {
                              return {valid:true};
                            } else {
                              if (submit) {
                                $ddSelect.addClass('not-valid has-been-focused has-attempted-submit').removeClass('valid');
                              }

                              if ($element.val() === 'Month') {
                                $ddSelect.addClass('not-valid').removeClass('valid');
                                return {
                                  valid: false,
                                  errors: ['Must select a month.']
                                };
                              } else {
                                $ddSelect.addClass('valid').removeClass('not-valid');
                                return {valid: true};
                              }
                            }
                          },
                          hint:'Month'
                        },
                        'day': {
                          selector: '#vol-day',
                          validators: function(merlinInput, $element, step, onSubmit) {
                            if ($element.is('.disabled')) {
                              return {valid:true};
                            } else {
                              return tc.validate($element, ['required', 'numeric']);
                            }
                          },
                          hint:'Day'
                        },
                        'time': {
                          selector: '#vol-time',
                          validators: function(merlinInput, $element, step, onSubmit) {
                            if ($element.is('.disabled')) {
                              return {valid:true};
                            } else {
                              return tc.validate($element, ['required']);
                            }
                          },
                          hint:'Time'
                        },
                        'event_link': {
                          selector: '#event-list',
                          validators: function(merlinInput, $element, step, onSubmit) {
                            var $ddSelectContainer = $element.next('.ddSelectContainer'),
                                $ddSelect = $ddSelectContainer.find('.ddSelect');

                            $ddSelect.removeClass('valid');

                            if ($ddSelectContainer.hasClass('ddNoDefault')
                              || ($element.val() !== '' && $element.val() !== $element.data('default'))) {
                              $ddSelect.addClass('has-been-focused valid');

                              //disable all of the custom date/place fields
                              disableCustomEventInputs(true, merlinInput);
                              return { valid: true };
                            } else {
                              //enable all of the custom date/place fields
                              disableCustomEventInputs(false, merlinInput);
                              return { valid: '' };
                            }
                          }
                        }
                    },
                    init:function(merlin, dom) {
                      // Set up the fancy jqDropDown for month
                      initDropDown('vol-month', 'Month');
                      initDropDown('event-list', 'Link to an event');

                      if (need_id) {
                        tc.jQ.each(merlin.current_step.inputs, function(key, input) {
                          if (input.default_val) {
                            input.dom.val(input.default_val);
                          }
                        });
                        merlin.validate(true);
                      }
                    },
                    finish:function(merlin, dom) {
                      var d = new Date();
                      var needDate = d.getFullYear()
                              + '-' + (parseInt(merlin.current_step.inputs.month.dom.val(), 10)+1)
                              + '-' + merlin.current_step.inputs.day.dom.val();
                      merlin.options.data = tc.jQ.extend(merlin.options.data,{
                        type:'volunteer',
                        request:merlin.current_step.inputs.request.dom.val(),
                        quantity:merlin.current_step.inputs.quantity.dom.val(),
                        description:merlin.current_step.inputs.description.dom.val(),
                        date:needDate,
                        time:merlin.current_step.inputs.time.dom.val(),
                        duration:merlin.current_step.inputs.duration.dom.val(),
                        project_id:merlin.app.app_page.data.project.project_id,
                        address:merlin.current_step.inputs.address.dom.val(),
                        event_id:merlin.current_step.inputs.event_link.dom.val()
                      });
                    }
                },
                'need-submit':{
                  selector:'.step.submit-need-step',
                  init:function(merlin,dom){
                    var need_data = merlin.options.data;

                    var success = function(data,tx,xhr){
                      if(data == 'False'){
                        return false;
                      }
                      window.location.hash = 'show,needs';
                      window.location.reload();
                    };
                    if (need_id === undefined) {
                      tc.gam.project_data.createNeed(need_data, success);
                    } else {
                      tc.gam.project_data.updateNeed(need_id, need_data, success);
                    }
                  }
                }
            }
        });

        merlin.show_step('need_form');
    };

    var mergeTemplate = function(need_details) {
        var new_details = tc.jQ.extend(true, {
                day: function() { return this.date ? (new Date(this.date).getUTCDate()) : ''; },
                monthOpts: function() {
                  var needDate = this.date ? (new Date(this.date).getUTCMonth()) : '';
                  var months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
                  var options = '';
                  for (var i = 0; i < months.length; i++) {
                    if (i === needDate) {
                      options += '<option value="' + i + '" selected>' + months[i] + '</option>';
                    } else {
                      options += '<option value="' + i + '">' + months[i] + '</option>';
                    }
                  }
                  return options;
                },
                eventOpts: function() {
                  var options = '';

                  for (var i = 0; i < cached_events.length; i++) {
                    if (cached_events[i].id === need_details.event_id) {
                      options += '<option value="'+cached_events[i].id+'" selected>'+cached_events[i].name+'</option>';
                    } else {
                      options += '<option value="'+cached_events[i].id+'">'+cached_events[i].name+'</option>';
                    }
                  }
                  return options;
                }
            }, need_details),
            $html = ich.need_form_tmpl(new_details);

        dom.find('.add-need-step').html($html);
    };

    var initForm = function(need_id, callback) {
      tc.gam.project_data.getEvents(function(events) {
        cached_events = events;

        if (need_id) {
            tc.gam.project_data.getNeedDetails(need_id, function(data){
                mergeTemplate(data);
                if (callback) {
                    callback();
                }
                initMerlin(need_id);
            });
        } else {
            mergeTemplate();
            if (callback) {
                callback();
            }
            initMerlin();
        }
      });
    };

    /**
     * Function: bindEvents
     * Bind events for this widget
     */
    var bindEvents = function() {
        tc.jQ(tc).bind('show-project-widget', function(event, widgetName, id) {
            if (options.name === widgetName) {
                tc.util.log('&&& showing ' + options.name);

                initForm(id, function(){
                    dom.show();
                });

            } else {
                tc.util.log('&&& hiding ' + options.name);
                dom.hide();
            }
        });
    };

    bindEvents();
    return self;
};
<commit_msg>handle validation better<commit_after>var tc = tc || {};
tc.gam = tc.gam || {};
tc.gam.project_widgets = tc.gam.project_widgets || {};

tc.gam.project_widgets.need_form = function(options) {
    tc.util.log('project.need_form');
    var dom = options.dom,
        cached_events = [],
        self = {};

    //Helper function to make the jqDropDown plugin more robust
    //since you can't set multiple classes at a time.
    //  id - the selector for the select element, also used to
    //       identify the generated markup
    //  defaultVal - Used to identify the unselectable default value
    var initDropDown = function(id, defaultVal, onChange) {
      //Apply jqDropDown to our select element
      var $container,
        $input = tc.jQ('#' + id);

      $input.jqDropDown({
        toggleBtnName:'ddSelect',
        optionListName:'ddSelectOptions',
        containerName:'dd-' + id,
        optionChanged: function() {
          if (onChange) {
            onChange($input);
          }

          //manually trigger the change event on the select element
          //so that Merlin validation will trigger properly
          $input.change();
        }
      }).data('default', defaultVal);

      $container = tc.jQ('.dd-' + id);

      //Add the default container css class (important, common styles on this guy)
      $container.addClass('ddSelectContainer');

      //There's no default value, something is always selected, so it's always valid
      if (!defaultVal) {
        $container.addClass('ddNoDefault');
        $container.find('.ddSelect').addClass('valid has-been-focused').removeClass('not-valid');
      }
    };

    var disableCustomEventInputs = function(disable, merlin) {
      var inputs = [merlin.current_step.inputs.month,
          merlin.current_step.inputs.day,
          merlin.current_step.inputs.time,
          merlin.current_step.inputs.address];

        tc.jQ.each(inputs, function(i, input) {
          if (input.dom.is('select')) {
            if (disable) {
              input.dom.next('.ddSelectContainer').find('.ddSelect').addClass('disabled');
            } else {
              input.dom.next('.ddSelectContainer').find('.ddSelect').removeClass('disabled');
            }
          }

          if (disable) {
            input.dom.addClass('disabled');
          } else {
            input.dom.removeClass('disabled');
          }
        });
    };

    var initEventInputs = function(merlin) {
      var $select = merlin.current_step.inputs.event_link.dom;

      if ($select.val() !== '' && $select.val() !== $select.data('default')) {
        //disable all of the custom date/place fields
        disableCustomEventInputs(true, merlin);
      } else {
        //enable all of the custom date/place fields
        disableCustomEventInputs(false, merlin);
      }
    };

    /**
     * Function: initMerlin
     * Initialize the merlin object for validation of the modal dialog.
     */
    var initMerlin = function(need_id) {
        var merlin;

        //We are using merlin only for the built-in validation in this case.
        merlin =  new tc.merlin(options.app, {
            name:'need_form',
            dom:tc.jQ('.add-need.merlin'),
            next_button:tc.jQ('a.need-submit'),
            first_step:'need_form',
            use_hashchange:false,
            data: {
              type:'volunteer',
              request:null,
              quantity:null,
              description:null,
              date:null,
              time:null,
              duration:null,
              project_id:null,
              address:null
            },
            steps: {
                'need_form': {
                    selector: '.step.add-need-step',
                    next_step:'need-submit',
                    inputs: {
                        'quantity': {
                            selector: '#vol-quantity',
                            validators: ['required', 'numeric'],
                            hint:'Qty'
                        },
                        'request': {
                            selector: '#vol-job',
                            validators: ['required', 'max-100'],
                            hint:'Job Title - DJ, Cashier, etc'
                        },
                        'description': {
                          selector: '#vol-desc',
                          validators: ['required', 'max-200'],
                          hint:'Write a brief description of the volunteer tasks and skills.',
                          counter:{
                            selector:'.charlimit.title',
                            limit:200
                          }
                        },
                        'duration': {
                          selector: '#vol-hours',
                          validators: ['required', 'numeric'],
                          hint:''
                        },
                        'address': {
                          selector: '#vol-street',
                          validators: function(merlinInput, $element, step, onSubmit) {
                            if ($element.is('.disabled')) {
                              return {valid:true};
                            } else {
                              return tc.validate($element, ['required']);
                            }
                          },
                          hint:'Address'
                        },
                        'month': {
                          selector: '#vol-month',
                          validators: function(input, $element, step, submit) {
                            var $ddSelect = $element.next('.ddSelectContainer').find('.ddSelect');

                            if ($element.is('.disabled')) {
                              return {valid:true};
                            } else {
                              if (submit) {
                                $ddSelect.addClass('not-valid has-been-focused has-attempted-submit').removeClass('valid');
                              }

                              if ($element.val() === 'Month') {
                                $ddSelect.addClass('not-valid').removeClass('valid');
                                return {
                                  valid: false,
                                  errors: ['Must select a month.']
                                };
                              } else {
                                $ddSelect.addClass('valid').removeClass('not-valid');
                                return {valid: true};
                              }
                            }
                          },
                          hint:'Month'
                        },
                        'day': {
                          selector: '#vol-day',
                          validators: function(merlinInput, $element, step, onSubmit) {
                            if ($element.is('.disabled')) {
                              return {valid:true};
                            } else {
                              return tc.validate($element, ['required', 'numeric']);
                            }
                          },
                          hint:'Day'
                        },
                        'time': {
                          selector: '#vol-time',
                          validators: function(merlinInput, $element, step, onSubmit) {
                            if ($element.is('.disabled')) {
                              return {valid:true};
                            } else {
                              return tc.validate($element, ['required']);
                            }
                          },
                          hint:'Time'
                        },
                        'event_link': {
                          selector: '#event-list',
                          validators: function(merlinInput, $element, step, onSubmit) {
                            var $ddSelectContainer = $element.next('.ddSelectContainer'),
                                $ddSelect = $ddSelectContainer.find('.ddSelect');

                            $ddSelect.removeClass('valid');

                            if ($ddSelectContainer.hasClass('ddNoDefault')
                              || ($element.val() !== '' && $element.val() !== $element.data('default'))) {
                              $ddSelect.addClass('has-been-focused valid');
                            }

                            return { valid: true };
                          }
                        }
                    },
                    init:function(merlin, dom) {
                      // Set up the fancy jqDropDown for month
                      initDropDown('vol-month', 'Month');
                      initDropDown('event-list', 'Link to an event', function($select) {
                        initEventInputs(merlin);
                      });

                      if (need_id) {
                        tc.jQ.each(merlin.current_step.inputs, function(key, input) {
                          if (input.default_val) {
                            input.dom.val(input.default_val);
                          }
                        });

                        initEventInputs(merlin);

                        merlin.validate(true);
                      }
                    },
                    finish:function(merlin, dom) {
                      var d = new Date();
                      var needDate = d.getFullYear()
                              + '-' + (parseInt(merlin.current_step.inputs.month.dom.val(), 10)+1)
                              + '-' + merlin.current_step.inputs.day.dom.val();
                      merlin.options.data = tc.jQ.extend(merlin.options.data,{
                        type:'volunteer',
                        request:merlin.current_step.inputs.request.dom.val(),
                        quantity:merlin.current_step.inputs.quantity.dom.val(),
                        description:merlin.current_step.inputs.description.dom.val(),
                        date:needDate,
                        time:merlin.current_step.inputs.time.dom.val(),
                        duration:merlin.current_step.inputs.duration.dom.val(),
                        project_id:merlin.app.app_page.data.project.project_id,
                        address:merlin.current_step.inputs.address.dom.val(),
                        event_id:merlin.current_step.inputs.event_link.dom.val()
                      });
                    }
                },
                'need-submit':{
                  selector:'.step.submit-need-step',
                  init:function(merlin,dom){
                    var need_data = merlin.options.data;

                    var success = function(data,tx,xhr){
                      if(data == 'False'){
                        return false;
                      }
                      window.location.hash = 'show,needs';
                      window.location.reload();
                    };
                    if (need_id === undefined) {
                      tc.gam.project_data.createNeed(need_data, success);
                    } else {
                      tc.gam.project_data.updateNeed(need_id, need_data, success);
                    }
                  }
                }
            }
        });

        merlin.show_step('need_form');
    };

    var mergeTemplate = function(need_details) {
        var new_details = tc.jQ.extend(true, {
                day: function() { return this.date ? (new Date(this.date).getUTCDate()) : ''; },
                monthOpts: function() {
                  var needDate = this.date ? (new Date(this.date).getUTCMonth()) : '';
                  var months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
                  var options = '';
                  for (var i = 0; i < months.length; i++) {
                    if (i === needDate) {
                      options += '<option value="' + i + '" selected>' + months[i] + '</option>';
                    } else {
                      options += '<option value="' + i + '">' + months[i] + '</option>';
                    }
                  }
                  return options;
                },
                eventOpts: function() {
                  var options = '';

                  for (var i = 0; i < cached_events.length; i++) {
                    if (cached_events[i].id === need_details.event_id) {
                      options += '<option value="'+cached_events[i].id+'" selected>'+cached_events[i].name+'</option>';
                    } else {
                      options += '<option value="'+cached_events[i].id+'">'+cached_events[i].name+'</option>';
                    }
                  }
                  return options;
                }
            }, need_details),
            $html = ich.need_form_tmpl(new_details);

        dom.find('.add-need-step').html($html);
    };

    var initForm = function(need_id, callback) {
      tc.gam.project_data.getEvents(function(events) {
        cached_events = events;

        if (need_id) {
            tc.gam.project_data.getNeedDetails(need_id, function(data){
                mergeTemplate(data);
                if (callback) {
                    callback();
                }
                initMerlin(need_id);
            });
        } else {
            mergeTemplate();
            if (callback) {
                callback();
            }
            initMerlin();
        }
      });
    };

    /**
     * Function: bindEvents
     * Bind events for this widget
     */
    var bindEvents = function() {
        tc.jQ(tc).bind('show-project-widget', function(event, widgetName, id) {
            if (options.name === widgetName) {
                tc.util.log('&&& showing ' + options.name);

                initForm(id, function(){
                    dom.show();
                });

            } else {
                tc.util.log('&&& hiding ' + options.name);
                dom.hide();
            }
        });
    };

    bindEvents();
    return self;
};
<|endoftext|>


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

  angular
    .module('crowdsource.routes', ['ngRoute'])
    .config(config);

  config.$inject = ['$routeProvider'];

  /**
  * @name config
  * @desc Define valid application routes
  */
  function config($routeProvider) {
    $routeProvider.when('/', {
      templateUrl: '/static/templates/intro.html',
    })

    .when('/home', {
      templateUrl: '/static/templates/home.html',
      controller: 'HomeController',
    })

    .when('/ranking', {
      templateUrl: '/static/templates/ranking/requesterrank.html',
      controller: 'RankingController',
    })

    .when('/tasks/workflow', {
      templateUrl: '/static/templates/task/workflow.html',
      controller: 'taskCreateController',
    })

    //We will merge tasklistSearch and tasklist to one component, please keep it separate for now.
    .when('/tasklistSearch', {
    templateUrl: '/static/templates/tasksearches/tasklistSearch.html',
    controller: 'taskSearchGridController',
    })

    .when('/requester', {
      templateUrl: '/static/templates/requester/home.html',
      controller: 'HomeController',
    })

    .when('/tasklist', {
      templateUrl: '/static/templates/task/tasklist.html',
      controller: 'taskController',
    })

    .when('/ImageLabel', {
      templateUrl: '/static/templates/task/ImageLabel.html'
    })

    .when('/register', {
      controller: 'RegisterController',
      controllerAs: 'vm',
      templateUrl: '/static/templates/authentication/register.html'
    })

    .when('/login', {
      controller: 'LoginController',
      controllerAs: 'vm',
      templateUrl: '/static/templates/authentication/login.html'
    })

    .when('/profile', {
      templateUrl: '/static/templates/home.html'
    })

    .when('/terms', {
      templateUrl: '/static/templates/terms.html'
    })

    .when('/contributors', {
      templateUrl: '/static/templates/contributors/home.html'
    })

  /**
   * Location for contributor urls. Include your personal page url here.
   */
    .when('/contributors/rohit', {
      templateUrl: '/static/templates/contributors/rohit.html'
    })

    .when('/contributors/amx', {
      templateUrl: '/static/templates/contributors/amx.html'
    })

    .when('/contributors/aneesha', {
      templateUrl: '/static/templates/contributors/aneesha.html'
    })

    .when('/contributors/ansuman', {
      templateUrl: '/static/templates/contributors/ansuman.html'
    })

    .when('/contributors/anirudh', {
      templateUrl: '/static/templates/contributors/anirudh.html'
    })

  	.when('/contributors/shirish', {
      templateUrl: '/static/templates/contributors/shirish.html'
    })

    .when('/contributors/geza', {
      templateUrl: '/static/templates/contributors/geza.html'
    })

    .when('/contributors/ard', {
      templateUrl: '/static/templates/contributors/ard.html'
    })

    .when('/contributors/narwal', {
      templateUrl: '/static/templates/contributors/narwal.html'
    })

    .when('/contributors/radhika', {
      templateUrl: '/static/templates/contributors/radhika.html'
    })

    .when('/contributors/sangm', {
      templateUrl: '/static/templates/contributors/sangm.html'
    })

    .when('/contributors/sean', {
      templateUrl: '/static/templates/contributors/sean.html'
    })

     .when('/contributors/leek', {
      templateUrl: '/static/templates/contributors/leek.html'
    })

    .when('/contributors/karan', {
      templateUrl: '/static/templates/contributors/karan.html'
    })

    .when('/contributors/vaidehi', {
      templateUrl: '/static/templates/contributors/vaidehi.html'
    })

    .when('/contributors/jason', {
      templateUrl: '/static/templates/contributors/jason.html'
    })

    .when('/contributors/lucamatsumoto', {
      templateUrl: '/static/templates/contributors/lucamatsumoto.html'
    })

    .when('/contributors/arcolife', {
      templateUrl: '/static/templates/contributors/arcolife.html'
    })

    .when('/contributors/AditiNath', {
      templateUrl: '/static/templates/contributors/aditinath.html'
    })

    .when('/contributors/ucerron', {
      templateUrl: '/static/templates/contributors/ucerron.html'
    })

    .when('/contributors/AmitRakesh', {
		templateUrl: '/static/templates/contributors/amitrakesh.html'
    })

    .when('/contributors/Milstein', {
      templateUrl: '/static/templates/contributors/milstein.html'
    })

    .when('/contributors/bmoix', {
      templateUrl: '/static/templates/contributors/bmoix.html'
    })

    .when('/contributors/vineet', {
      templateUrl: '/static/templates/contributors/vineet.html'
    })

    .when('/contributors/damon', {
      templateUrl: '/static/templates/contributors/damon.html'
    })

	.when('/contributors/rcompton', {
      templateUrl: '/static/templates/contributors/rcompton.html'
    })

    .when('/contributors/hiroshi', {
      templateUrl: '/static/templates/contributors/hiroshi.html'
    })

    .when('/contributors/niraj', {
      templateUrl: '/static/templates/contributors/niraj.html'
    })

    .when('/contributors/abhinav', {
      templateUrl: '/static/templates/contributors/abhinav.html'
    })

	.when('/contributors/Pabitra', {
      templateUrl: '/static/templates/contributors/Pabitra.html'
    })

  	.when('/contributors/KajalGupta', {
      templateUrl: '/static/templates/contributors/kajal.html'
    })

    .when('/contributors/pemmasani', {
      templateUrl: '/static/templates/contributors/pemmasani.html'
    })

    .when('/contributors/ramachandracn', {
      templateUrl: '/static/templates/contributors/ramachandracn.html'
    })

    .when('/contributors/saviaga', {
      templateUrl: '/static/templates/contributors/saviaga.html'
    })

    .when('/contributors/pitkofsky', {
      templateUrl: '/static/templates/contributors/pitkofsky.html'
    })

   .when('/contributors/paresh', {
      templateUrl: '/static/templates/contributors/paresh.html'
    })

    .when('/contributors/msb', {
      templateUrl: '/static/templates/contributors/msb.html'
    })

    .when('/contributors/ankita2992', {
      templateUrl: '/static/templates/contributors/ankita.html'
    })

    .when('/contributors/savage', {
      templateUrl: '/static/templates/contributors/savage.html'
    })

    .when('/contributors/mistercruz', {
      templateUrl: '/static/templates/contributors/mistercruz.html'
    })

    .when('/contributors/arshiya', {
      templateUrl: '/static/templates/contributors/arshiya.html'
    })

    .when('/contributors/vivekvinodh', {
      templateUrl: '/static/templates/contributors/vivekvinodh.html'
    })

     .when('/contributors/kevin', {
      templateUrl: '/static/templates/contributors/kevin.html'
     })

     .when('/contributors/vipul', {
      templateUrl: '/static/templates/contributors/vipul.html'
     })

     .when('/contributors/khushali', {
      templateUrl: '/static/templates/contributors/khushali.html'
     })

    .otherwise('/');
  }
})();
<commit_msg>reverting back the workflow routes <commit_after>(function () {
  'use strict';

  angular
    .module('crowdsource.routes', ['ngRoute'])
    .config(config);

  config.$inject = ['$routeProvider'];

  /**
  * @name config
  * @desc Define valid application routes
  */
  function config($routeProvider) {
    $routeProvider.when('/', {
      templateUrl: '/static/templates/intro.html',
    })

    .when('/home', {
      templateUrl: '/static/templates/home.html',
      controller: 'HomeController',
    })

    .when('/ranking', {
      templateUrl: '/static/templates/ranking/requesterrank.html',
      controller: 'RankingController',
    })

    //We will merge tasklistSearch and tasklist to one component, please keep it separate for now.
    .when('/tasklistSearch', {
    templateUrl: '/static/templates/tasksearches/tasklistSearch.html',
    controller: 'taskSearchGridController',
    })

    .when('/requester', {
      templateUrl: '/static/templates/requester/home.html',
      controller: 'HomeController',
    })

    .when('/tasklist', {
      templateUrl: '/static/templates/task/tasklist.html',
      controller: 'taskController',
    })

    .when('/ImageLabel', {
      templateUrl: '/static/templates/task/ImageLabel.html'
    })

    .when('/register', {
      controller: 'RegisterController',
      controllerAs: 'vm',
      templateUrl: '/static/templates/authentication/register.html'
    })

    .when('/login', {
      controller: 'LoginController',
      controllerAs: 'vm',
      templateUrl: '/static/templates/authentication/login.html'
    })

    .when('/profile', {
      templateUrl: '/static/templates/home.html'
    })

    .when('/terms', {
      templateUrl: '/static/templates/terms.html'
    })

    .when('/contributors', {
      templateUrl: '/static/templates/contributors/home.html'
    })

  /**
   * Location for contributor urls. Include your personal page url here.
   */
    .when('/contributors/rohit', {
      templateUrl: '/static/templates/contributors/rohit.html'
    })

    .when('/contributors/amx', {
      templateUrl: '/static/templates/contributors/amx.html'
    })

    .when('/contributors/aneesha', {
      templateUrl: '/static/templates/contributors/aneesha.html'
    })

    .when('/contributors/ansuman', {
      templateUrl: '/static/templates/contributors/ansuman.html'
    })

    .when('/contributors/anirudh', {
      templateUrl: '/static/templates/contributors/anirudh.html'
    })

  	.when('/contributors/shirish', {
      templateUrl: '/static/templates/contributors/shirish.html'
    })

    .when('/contributors/geza', {
      templateUrl: '/static/templates/contributors/geza.html'
    })

    .when('/contributors/ard', {
      templateUrl: '/static/templates/contributors/ard.html'
    })

    .when('/contributors/narwal', {
      templateUrl: '/static/templates/contributors/narwal.html'
    })

    .when('/contributors/radhika', {
      templateUrl: '/static/templates/contributors/radhika.html'
    })

    .when('/contributors/sangm', {
      templateUrl: '/static/templates/contributors/sangm.html'
    })

    .when('/contributors/sean', {
      templateUrl: '/static/templates/contributors/sean.html'
    })

     .when('/contributors/leek', {
      templateUrl: '/static/templates/contributors/leek.html'
    })

    .when('/contributors/karan', {
      templateUrl: '/static/templates/contributors/karan.html'
    })

    .when('/contributors/vaidehi', {
      templateUrl: '/static/templates/contributors/vaidehi.html'
    })

    .when('/contributors/jason', {
      templateUrl: '/static/templates/contributors/jason.html'
    })

    .when('/contributors/lucamatsumoto', {
      templateUrl: '/static/templates/contributors/lucamatsumoto.html'
    })

    .when('/contributors/arcolife', {
      templateUrl: '/static/templates/contributors/arcolife.html'
    })

    .when('/contributors/AditiNath', {
      templateUrl: '/static/templates/contributors/aditinath.html'
    })

    .when('/contributors/ucerron', {
      templateUrl: '/static/templates/contributors/ucerron.html'
    })

    .when('/contributors/AmitRakesh', {
		templateUrl: '/static/templates/contributors/amitrakesh.html'
    })

    .when('/contributors/Milstein', {
      templateUrl: '/static/templates/contributors/milstein.html'
    })

    .when('/contributors/bmoix', {
      templateUrl: '/static/templates/contributors/bmoix.html'
    })

    .when('/contributors/vineet', {
      templateUrl: '/static/templates/contributors/vineet.html'
    })

    .when('/contributors/damon', {
      templateUrl: '/static/templates/contributors/damon.html'
    })

	.when('/contributors/rcompton', {
      templateUrl: '/static/templates/contributors/rcompton.html'
    })

    .when('/contributors/hiroshi', {
      templateUrl: '/static/templates/contributors/hiroshi.html'
    })

    .when('/contributors/niraj', {
      templateUrl: '/static/templates/contributors/niraj.html'
    })

    .when('/contributors/abhinav', {
      templateUrl: '/static/templates/contributors/abhinav.html'
    })

	.when('/contributors/Pabitra', {
      templateUrl: '/static/templates/contributors/Pabitra.html'
    })

  	.when('/contributors/KajalGupta', {
      templateUrl: '/static/templates/contributors/kajal.html'
    })

    .when('/contributors/pemmasani', {
      templateUrl: '/static/templates/contributors/pemmasani.html'
    })

    .when('/contributors/ramachandracn', {
      templateUrl: '/static/templates/contributors/ramachandracn.html'
    })

    .when('/contributors/saviaga', {
      templateUrl: '/static/templates/contributors/saviaga.html'
    })

    .when('/contributors/pitkofsky', {
      templateUrl: '/static/templates/contributors/pitkofsky.html'
    })

   .when('/contributors/paresh', {
      templateUrl: '/static/templates/contributors/paresh.html'
    })

    .when('/contributors/msb', {
      templateUrl: '/static/templates/contributors/msb.html'
    })

    .when('/contributors/ankita2992', {
      templateUrl: '/static/templates/contributors/ankita.html'
    })

    .when('/contributors/savage', {
      templateUrl: '/static/templates/contributors/savage.html'
    })

    .when('/contributors/mistercruz', {
      templateUrl: '/static/templates/contributors/mistercruz.html'
    })

    .when('/contributors/arshiya', {
      templateUrl: '/static/templates/contributors/arshiya.html'
    })

    .when('/contributors/vivekvinodh', {
      templateUrl: '/static/templates/contributors/vivekvinodh.html'
    })

     .when('/contributors/kevin', {
      templateUrl: '/static/templates/contributors/kevin.html'
     })

     .when('/contributors/vipul', {
      templateUrl: '/static/templates/contributors/vipul.html'
     })

     .when('/contributors/khushali', {
      templateUrl: '/static/templates/contributors/khushali.html'
     })

    .otherwise('/');
  }
})();
<|endoftext|>