<commit_before>/*global describe, it, beforeEach */
'use strict';
require('chai').config.truncateThreshold = 0;
const joi = require('joi');
const expect = require('chai').expect;
const Service = require('@arangodb/foxx/service');
const createRouter = require('@arangodb/foxx/router');

describe('Foxx Swagger', function () {
  let service;
  beforeEach(function () {
    service = createService();
  });

  it('adds all the basic metadata', function () {
    service.buildRoutes();
    expect(service.docs).to.eql({
      swagger: '2.0',
      basePath: `/_db/_system${service.mount}`,
      paths: {},
      info: {
        title: service.manifest.name,
        description: service.manifest.description,
        version: service.manifest.version,
        license: {
          name: service.manifest.license
        }
      }
    });
  });

  describe('Route Info', function () {
    it('formats path param names', function () {
      service.router.get('/:x', noop());
      service.buildRoutes();
      expect(service.docs.paths).to.have.a.property('/{x}')
      .with.a.property('get');
    });

    it('disambiguates duplicate path param names', function () {
      const child = createRouter();
      child.get('/:x', noop());
      service.router.use('/:x', child);
      service.buildRoutes();
      expect(service.docs.paths).to.have.a.property('/{x}/{x2}')
      .with.a.property('get');
    });

    it('supports multiple methods on the same path', function () {
      service.router.get('/a', noop()).description('x');
      service.router.post('/a', noop()).description('y');
      service.buildRoutes();
      expect(service.docs.paths).to.have.a.property('/a')
      .with.a.deep.property('get.description', 'x');
      expect(service.docs.paths).to.have.a.property('/a')
      .with.a.deep.property('post.description', 'y');
    });

    describe('"deprecated"', function () {
      it('is omitted by default', function () {
        service.router.get('/hello', noop());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.not.a.deep.property('get.deprecated');
      });

      it('is set to true if the route is marked deprecated', function () {
        service.router.get('/hello', noop()).deprecated();
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.deprecated')
        .that.is.equal(true);
      });

      it('is set to true if a parent is marked deprecated', function () {
        const child = createRouter();
        child.get('/hello', noop()).deprecated(false);
        service.router.use(child).deprecated();
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.deprecated')
        .that.is.equal(true);
      });

      it('is omitted if the route is marked un-deprecated', function () {
        service.router.get('/hello', noop()).deprecated(false);
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.not.a.deep.property('get.deprecated');
      });
    });

    ['description', 'summary'].forEach(function (field) {
      describe(`"${field}"`, function () {
        it('is omitted by default', function () {
          service.router.get('/hello', noop());
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.not.a.deep.property(`get.${field}`);
        });

        it(`is set to the ${field} if provided`, function () {
          const str = 'Hello World!';
          service.router.get('/hello', noop())[field](str);
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.a.deep.property(`get.${field}`)
          .that.is.equal(str);
        });

        it(`is omitted if the ${field} is empty`, function () {
          service.router.get('/hello', noop())[field]('');
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.not.a.deep.property(`get.${field}`);
        });
      });
    });

    describe('"consumes"', function () {
      ['patch', 'post', 'put'].forEach(function (method) {
        it(`defaults to JSON for ${method.toUpperCase()}`, function () {
          service.router[method]('/hello', noop());
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.a.deep.property(`${method}.consumes`)
          .that.is.eql(['application/json']);
        });
      });

      ['get', 'head', 'delete'].forEach(function (method) {
        it(`is omitted for ${method.toUpperCase()}`, function () {
          service.router[method]('/hello', noop());
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.not.a.deep.property(`${method}.consumes`);
        });
      });

      it('is set to the body mime type', function () {
        service.router.post('/hello', noop()).body(['text/plain']);
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('post.consumes')
        .that.is.eql(['text/plain']);
      });

      ['get', 'head', 'delete'].forEach(function (method) {
        it(`is set for ${method.toUpperCase()} if explicitly defined`, function () {
          service.router[method]('/hello', noop()).body(['text/plain']);
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.a.deep.property(`${method}.consumes`)
          .that.is.eql(['text/plain']);
        });
      });

      ['patch', 'post', 'put'].forEach(function (method) {
        it(`is empty for ${method.toUpperCase()} if explicitly set to null`, function () {
          service.router[method]('/hello', noop()).body(null);
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.a.deep.property(`${method}.consumes`)
          .that.is.eql([]);
        });
      });
    });

    describe('"produces"', function () {
      it('defaults to JSON', function () {
        service.router.get('/hello', noop());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.produces')
        .that.is.eql(['application/json']);
      });

      it('includes explicit response types', function () {
        service.router.get('/hello', noop()).response(['text/plain']);
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.produces')
        .that.is.eql(['text/plain', 'application/json']);
      });

      it('includes non-200 response types', function () {
        service.router.get('/hello', noop())
        .response(['text/plain'])
        .response(499, ['text/html']);
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.produces')
        .that.is.eql(['text/plain', 'text/html', 'application/json']);
      });
    });

    describe('"responses"', function () {
      it('provides a default response', function () {
        service.router.get('/hello', noop());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses.default')
        .that.has.a.property('description', 'Unexpected error.');
      });

      it('does not provide any other default responses', function () {
        service.router.get('/hello', noop());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses')
        .that.has.all.keys('default');
      });

      it('includes explicit responses', function () {
        service.router.get('/hello', noop())
        .response(200, 'Some response')
        .response(400, 'Some error');
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses.200')
        .that.has.a.property('description', 'Some response');
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses.400')
        .that.has.a.property('description', 'Some error');
      });

      it('includes explicit schemas', function () {
        service.router.get('/hello', noop())
        .response(200, joi.object());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses.200')
        .that.has.a.property('schema')
        .that.is.eql({
          type: 'object',
          properties: {},
          additionalProperties: false
        });
      });
    });

    describe('"parameters"', function () {
      describe('in:body', function () {
        it('TODO');
      });

      describe('in:path', function () {
        it('TODO');
      });

      describe('in:query', function () {
        it('TODO');
      });

      describe('in:header', function () {
        it('TODO');
      });
    });
  });
});

function createService() {
  return new Service({
    path: '/tmp/$dummy$',
    mount: '/__dummy__',
    manifest: {
      name: 'DUMMY APP',
      version: '1.0.0',
      license: 'The Unlicense',
      description: 'Dummy app for Foxx.',
      main: '$dummy$',
      engines: {
        arangodb: '^3.0.0'
      }
    },
    options: {}
  });
}

function noop() {
  return noop;
}
<commit_msg>Fix shell-foxx-swager-spec.js<commit_after>/*global describe, it, beforeEach */
'use strict';
require('chai').config.truncateThreshold = 0;
const joi = require('joi');
const expect = require('chai').expect;
const Service = require('@arangodb/foxx/service');
const createRouter = require('@arangodb/foxx/router');

describe('Foxx Swagger', function () {
  let service;
  beforeEach(function () {
    service = createService();
  });

  it('adds all the basic metadata', function () {
    service.buildRoutes();
    expect(service.docs).to.eql({
      swagger: '2.0',
      basePath: `/_db/_system${service.mount}`,
      paths: {},
      info: {
        title: service.manifest.name,
        description: service.manifest.description,
        version: service.manifest.version,
        license: {
          name: service.manifest.license
        }
      }
    });
  });

  describe('Route Info', function () {
    it('formats path param names', function () {
      service.router.get('/:x', noop());
      service.buildRoutes();
      expect(service.docs.paths).to.have.a.property('/{x}')
      .with.a.property('get');
    });

    it('disambiguates duplicate path param names', function () {
      const child = createRouter();
      child.get('/:x', noop());
      service.router.use('/:x', child);
      service.buildRoutes();
      expect(service.docs.paths).to.have.a.property('/{x}/{x2}')
      .with.a.property('get');
    });

    it('supports multiple methods on the same path', function () {
      service.router.get('/a', noop()).description('x');
      service.router.post('/a', noop()).description('y');
      service.buildRoutes();
      expect(service.docs.paths).to.have.a.property('/a')
      .with.a.deep.property('get.description', 'x');
      expect(service.docs.paths).to.have.a.property('/a')
      .with.a.deep.property('post.description', 'y');
    });

    describe('"deprecated"', function () {
      it('is omitted by default', function () {
        service.router.get('/hello', noop());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.not.a.deep.property('get.deprecated');
      });

      it('is set to true if the route is marked deprecated', function () {
        service.router.get('/hello', noop()).deprecated();
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.deprecated')
        .that.is.equal(true);
      });

      it('is set to true if a parent is marked deprecated', function () {
        const child = createRouter();
        child.get('/hello', noop()).deprecated(false);
        service.router.use(child).deprecated();
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.deprecated')
        .that.is.equal(true);
      });

      it('is omitted if the route is marked un-deprecated', function () {
        service.router.get('/hello', noop()).deprecated(false);
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.not.a.deep.property('get.deprecated');
      });
    });

    ['description', 'summary'].forEach(function (field) {
      describe(`"${field}"`, function () {
        it('is omitted by default', function () {
          service.router.get('/hello', noop());
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.not.a.deep.property(`get.${field}`);
        });

        it(`is set to the ${field} if provided`, function () {
          const str = 'Hello World!';
          service.router.get('/hello', noop())[field](str);
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.a.deep.property(`get.${field}`)
          .that.is.equal(str);
        });

        it(`is omitted if the ${field} is empty`, function () {
          service.router.get('/hello', noop())[field]('');
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.not.a.deep.property(`get.${field}`);
        });
      });
    });

    describe('"consumes"', function () {
      ['patch', 'post', 'put'].forEach(function (method) {
        it(`is omitted for ${method.toUpperCase()} by default`, function () {
          service.router[method]('/hello', noop());
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.not.a.deep.property(`${method}.consumes`);
        });
      });

      ['get', 'head', 'delete'].forEach(function (method) {
        it(`is empty for ${method.toUpperCase()} by default`, function () {
          service.router[method]('/hello', noop());
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.a.deep.property(`${method}.consumes`)
          .that.is.eql([]);
        });
      });

      it('is set to the body mime type', function () {
        service.router.post('/hello', noop()).body(['text/plain']);
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('post.consumes')
        .that.is.eql(['text/plain']);
      });

      ['get', 'head', 'delete'].forEach(function (method) {
        it(`is set for ${method.toUpperCase()} if explicitly defined`, function () {
          service.router[method]('/hello', noop()).body(['text/plain']);
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.a.deep.property(`${method}.consumes`)
          .that.is.eql(['text/plain']);
        });
      });

      ['patch', 'post', 'put'].forEach(function (method) {
        it(`is empty for ${method.toUpperCase()} if explicitly set to null`, function () {
          service.router[method]('/hello', noop()).body(null);
          service.buildRoutes();
          expect(service.docs.paths).to.have.a.property('/hello')
          .with.a.deep.property(`${method}.consumes`)
          .that.is.eql([]);
        });
      });
    });

    describe('"produces"', function () {
      it('defaults to JSON', function () {
        service.router.get('/hello', noop());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.produces')
        .that.is.eql(['application/json']);
      });

      it('includes explicit response types', function () {
        service.router.get('/hello', noop()).response(['text/plain']);
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.produces')
        .that.is.eql(['text/plain', 'application/json']);
      });

      it('includes non-200 response types', function () {
        service.router.get('/hello', noop())
        .response(['text/plain'])
        .response(499, ['text/html']);
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.produces')
        .that.is.eql(['text/plain', 'text/html', 'application/json']);
      });
    });

    describe('"responses"', function () {
      it('provides a default response', function () {
        service.router.get('/hello', noop());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses.default')
        .that.has.a.property('description', 'Unexpected error.');
      });

      it('does not provide any other default responses', function () {
        service.router.get('/hello', noop());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses')
        .that.has.all.keys('default');
      });

      it('includes explicit responses', function () {
        service.router.get('/hello', noop())
        .response(200, 'Some response')
        .response(400, 'Some error');
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses.200')
        .that.has.a.property('description', 'Some response');
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses.400')
        .that.has.a.property('description', 'Some error');
      });

      it('includes explicit schemas', function () {
        service.router.get('/hello', noop())
        .response(200, joi.object());
        service.buildRoutes();
        expect(service.docs.paths).to.have.a.property('/hello')
        .with.a.deep.property('get.responses.200')
        .that.has.a.property('schema')
        .that.is.eql({
          type: 'object',
          properties: {},
          additionalProperties: false
        });
      });
    });

    describe('"parameters"', function () {
      describe('in:body', function () {
        it('TODO');
      });

      describe('in:path', function () {
        it('TODO');
      });

      describe('in:query', function () {
        it('TODO');
      });

      describe('in:header', function () {
        it('TODO');
      });
    });
  });
});

function createService() {
  return new Service({
    path: '/tmp/$dummy$',
    mount: '/__dummy__',
    manifest: {
      name: 'DUMMY APP',
      version: '1.0.0',
      license: 'The Unlicense',
      description: 'Dummy app for Foxx.',
      main: '$dummy$',
      engines: {
        arangodb: '^3.0.0'
      }
    },
    options: {}
  });
}

function noop() {
  return noop;
}
<|endoftext|>


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

/**
 * Model for a toggle button that sticks when pushed down ("toggles") and pops up when
 * pushed a second time ("untoggles").
 *
 * @author Sam Reid
 * @author John Blanco
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var ButtonModel = require( 'SUN/experimental/buttons/ButtonModel' );

  /**
   *
   * @param valueA {Object} one value for the toggle
   * @param valueB {Object} other value for the toggle
   * @param valueProperty {Property<Object>} axon property that can be either valueA or valueB.  Would have preferred to call this `property` but it would clash with the property function name.
   * @constructor
   */
  function StickyToggleButtonModel( valueA, valueB, valueProperty ) {
    var thisModel = this;

    this.valueA = valueA;
    this.valueB = valueB;
    this.valueProperty = valueProperty;

    ButtonModel.call( this );

    // When the user releases the toggle button, it should only fire a
    // toggle event if it is not during the same action in which they
    // pressed the button.  Track the state to see if they have already
    // pushed the button.
    // Note: Does this need to be reset when the simulation does "reset
    // all"?  I (sreid) can't find any negative consequences in the user
    // interface of not resetting it, but maybe I missed something. Or maybe
    // it would be safe to reset it anyway.
    this.addProperty( 'readyToToggleUp', false );

    // If the button is untoggled and the user presses it, show it pressed and
    // toggle the state right away.  When the button is released, untoggle the
    // state (unless it was part of the same action that toggled the button
    // down in the first place).
    this.property( 'down' ).link( function( down ) {
      if ( thisModel.enabled && thisModel.over ) {
        if ( down && valueProperty.value === valueA ) {
          thisModel.toggle();
          thisModel.readyToToggleUp = false;
        }
        if ( !down && valueProperty.value === valueB ) {
          if ( thisModel.readyToToggleUp ) {
            thisModel.toggle();
          }
          else {
            thisModel.readyToToggleUp = true;
          }
        }
      }

      //Handle the case where the pointer moved out then up over a toggle button, so it will respond to the next press
      if ( !down && !thisModel.over ) {
        thisModel.readyToToggleUp = true;
      }
    } );

    //Make the button ready to toggle when enabled
    this.property( 'enabled' ).onValue( true, function() {
      thisModel.readyToToggleUp = true;
    } );
  }

  return inherit( ButtonModel, StickyToggleButtonModel, {
    toggle: function() {
      assert && assert( this.valueProperty.value === this.valueA || this.valueProperty.value === this.valueB );
      if ( this.valueProperty.value === this.valueA ) {
        this.valueProperty.value = this.valueB;
      }
      else {
        this.valueProperty.value = this.valueA;
      }
    }
  } );
} );<commit_msg>renamed readyToToggleUp=>pressedWhileDown, see #70<commit_after>// Copyright 2002-2014, University of Colorado Boulder

/**
 * Model for a toggle button that sticks when pushed down and pops up when
 * pushed a second time.
 *
 * @author Sam Reid
 * @author John Blanco
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var ButtonModel = require( 'SUN/experimental/buttons/ButtonModel' );

  /**
   *
   * @param valueA {Object} one possible value for the toggle, when the button is in an "up" state
   * @param valueB {Object} other value for the toggle, when the button is in a "down" state
   * @param valueProperty {Property<Object>} axon property that can be either valueA or valueB.  Would have preferred to call this `property` but it would clash with the property function name.
   * @constructor
   */
  function StickyToggleButtonModel( valueA, valueB, valueProperty ) {
    var thisModel = this;

    this.valueA = valueA;
    this.valueB = valueB;
    this.valueProperty = valueProperty;

    ButtonModel.call( this );

    // When the user releases the toggle button, it should only fire an event
    // if it is not during the same action in which they
    // pressed the button.  Track the state to see if they have already
    // pushed the button.
    // Note: Does this need to be reset when the simulation does "reset
    // all"?  I (Sam Reid) can't find any negative consequences in the user
    // interface of not resetting it, but maybe I missed something. Or maybe
    // it would be safe to reset it anyway.
    this.addProperty( 'pressedWhileDown', false );

    // If the button is up and the user presses it, show it pressed and
    // toggle the state right away.  When the button is released, pop up the button
    // (unless it was part of the same action that pressed the button
    // down in the first place).
    this.property( 'down' ).link( function( down ) {
      if ( thisModel.enabled && thisModel.over ) {
        if ( down && valueProperty.value === valueA ) {
          thisModel.toggle();
          thisModel.pressedWhileDown = false;
        }
        if ( !down && valueProperty.value === valueB ) {
          if ( thisModel.pressedWhileDown ) {
            thisModel.toggle();
          }
          else {
            thisModel.pressedWhileDown = true;
          }
        }
      }

      //Handle the case where the pointer moved out then up over a toggle button, so it will respond to the next press
      if ( !down && !thisModel.over ) {
        thisModel.pressedWhileDown = true;
      }
    } );

    //Make the button ready to toggle when enabled
    this.property( 'enabled' ).onValue( true, function() {
      thisModel.pressedWhileDown = true;
    } );
  }

  return inherit( ButtonModel, StickyToggleButtonModel, {
    toggle: function() {
      assert && assert( this.valueProperty.value === this.valueA || this.valueProperty.value === this.valueB );
      if ( this.valueProperty.value === this.valueA ) {
        this.valueProperty.value = this.valueB;
      }
      else {
        this.valueProperty.value = this.valueA;
      }
    }
  } );
} );<|endoftext|>


<commit_before>sb.forms.inlineEditable = {};
sb.include('Element.prototype.isWithin');

/**
@Name: sb.forms.inlineEditable.textarea
@Description: Creates a click to edit text block
@Param: Object
onBeforeEdit function Fires before editing begins,  Can be used to load raw text wihtout HTML from server
onSave function Fires after save, send back to server, stop editing
className string the classname for the widget, defaults to

@Example:
//use this in a doubleclick event for the text you want to make editable
//I assign it to the target so, you don't make extra editors

var target = e.target;

//var document_id = 'something from target';

if(!target.editor){
target.editor = new sb.forms.inlineEditable.textarea({
	onBeforeEdit : function(){

		this.setValue('loading...');
		var editor = this;

		var aj = new sb.ajax({
			url : '/url/rawtext',
			data : {
				doc_id : doc_id
			},
			onResponse : function(raw_desc){
				editor.setValue(raw_desc);
			}
		}).fetch();
	},
	onSave : function(value){
		if(value != 'loading...'){
			var editor = this;
			var aj = new sb.ajax({
				url : '/url/save',
				data : {
					doc_id : doc_id,
					value : value
				},
				onResponse : function(html){
					editor.setHTML(html);
				}
			}).fetch();
		}
	}

});
}

target.editor.edit(target);

.sb_inlineEditable textarea{
	cursor:text;
	display:block;
	width:97%;
	height:100px;
	overflow:auto;
	font-family:tahoma;
	font-size:1.1em;
}

.sb_inlineEditable editbar{
	text-align:right;
}

.sb_inlineEditable button{
	background-color:#d88713;
	color:#7c4e0d;
}

.sb_inlineEditable button:hover{
	background-color:#e2b370;
}

*/
sb.forms.inlineEditable.textarea = function(params){
	sb.objects.infuse(params, this);
	this.className = params.className || 'sb_inlineEditable';
	this.create();

};

sb.forms.inlineEditable.textarea.prototype = {

	/**
	@Name: sb.forms.inlineEditable.onBeforeEdit
	@Description: Fires before editing begins.  Can be used to load raw data with ajax
	to fill the textarea with.  Reference the textarea with this.textarea
	*/
	onBeforeEdit : function(){
		this.setValue(this.node.innerHTML);
	},

	/**
	@Name: sb.forms.inlineEditable.onBeforeEdit
	@Description: Passes the value of the textarea for you to save back with ajax
	@param string save The value of the textarea when save if fired
	*/
	onSave : function(value){},

	/**
	@Name: sb.forms.inlineEditable.onButtonPress
	@Description: Used Internally Fires when a button is pressed other than save or cancel
	@param event e The press event
	*/
	onButtonPress : function(e){},

	/**
	@Name: sb.forms.inlineEditable.edit
	@Description: Put the editor in edit mode
	@param: element el the element to edit
	*/
	edit : function(el){

		this.editor.title = 'shortcuts: esc to cancel, ctrl+s to save';

		this.element = $(el);
		this.editor.replace(this.element);

		if(typeof this.onBeforeEdit == 'function'){
			this.onBeforeEdit.call(this);
		}
	},

	/**
	@Name: sb.forms.inlineEditable.editStop
	@Description: Exit edit mode
	*/
	editStop : function(){
		this.element.replace(this.editor);

		this._origValue = '';
	},

	/**
	@Name: sb.forms.inlineEditable.setValue
	@Description: Sets the value of the textarea, use in onBeforeEdit
	*/
	setValue : function(value){
		this.textarea.value = value;
		this.focus();
	},

	/**
	@Name: sb.forms.inlineEditable.setHTML
	@Description: Sets the html of the element being edited, use in onSave
	*/
	setHTML : function(html){
		this.element.innerHTML = html;
		this.editStop();
	},

	/**
	@Name: sb.forms.inlineEditable.focus
	@Description: Focuses on text area and puts cursor at top left. automatically fires after setValue
	*/
	focus : function(){
		var ta = this.textarea;
		var range;
		if (this.textarea.setSelectionRange) {
			this.textarea.setSelectionRange(0, 0);
		} else if(this.textarea.createTextRange){
			range = this.textarea.createTextRange();
			range.collapse(true);
			range.moveStart("character", 0);
			range.moveEnd("character", 0 - 0);
			range.select();
		}
		this.textarea.focus();

	},

	/**
	@Name: sb.forms.inlineEditable.addButton
	@Description: Adds a button to the editBar
	*/
	addButton : function(str){
		this.editBar.innerHTML = '<button>'+str+'</button>'+this.editBar.innerHTML;

	},

	/**
	@Name: sb.forms.inlineEditable.addButton
	@Description: Determines if field is edited or not
	*/
	isNotEdited : function(){
		return !this._origValue || this._origValue == this.textarea.value;
	},

	/**
	@Name: sb.forms.inlineEditable.editStop
	@Description: Used internally Creates editor
	*/
	create : function(){
		var self = this;
		if(!this.editor){
			this.editor = new sb.element({
				tag : 'div',
				className : self.className
			});

			this.textarea = new sb.element({
				tag : 'textarea',
				value : this.value,
				className : this.className,
				events : {
					keydown : function(e){

						if(!self._origValue){
							self._origValue = self.textarea.value;
						}

						if(e.keyCode == 9 && self.isNotEdited()){
							self.editStop();
						} else if(e.keyCode == 27){
							self.editStop();
						} else if((e.ctrlKey || e.metaKey) && e.keyCode == 83){
							e.stopPropagation();
							e.preventDefault();
							self.onSave.call(self, self.textarea.value);
							self.editStop();
						}
					},
					blur : function(e){
						if(self.isNotEdited()){
							self.editStop();
						}

					}
				}
			});

			this.textarea.appendTo(this.editor);

			this.editBar = new sb.element({
				tag : 'editbar',
				styles : {
					display : 'block'
				},
				innerHTML : '<button>cancel</button><button>save</button>',
				events : {
					mousedown : function(e){
						var target = e.target;
						e.preventDefault();
						e.stopPropagation();
						if(target.nodeName == 'BUTTON'){

							switch(target.innerHTML){
								case 'save':
									self.onSave(self.textarea.value);
									break;

								case 'cancel':
									self.editStop();
									break;

								default:
									self.onButtonPress(e);
							}
						}

						return true;

					}
				}
			});

			this.editBar.appendTo(this.editor);
		}
	}
};<commit_msg>updated docs and added setHTML()<commit_after>sb.forms.inlineEditable = {};
sb.include('Element.prototype.isWithin');

/**
@Name: sb.forms.inlineEditable.textarea
@Description: Creates a click to edit text block
@Param: Object
onBeforeEdit function Fires before editing begins,  Can be used to load raw text wihtout HTML from server
onSave function Fires after save, send back to server, stop editing
className string the classname for the widget, defaults to

@Example:
//use this in a doubleclick event for the text you want to make editable
//I assign it to the target so, you don't make extra editors

var target = e.target;

//var document_id = 'something from target';

if(!target.editor){
target.editor = new sb.forms.inlineEditable.textarea({
	onBeforeEdit : function(){

		this.setValue('loading...');
		var editor = this;

		var aj = new sb.ajax({
			url : '/url/rawtext',
			data : {
				doc_id : doc_id
			},
			onResponse : function(raw_desc){
				editor.setValue(raw_desc);
			}
		}).fetch();
	},
	onSave : function(value){
		if(value != 'loading...'){
			var editor = this;
			var aj = new sb.ajax({
				url : '/url/save',
				data : {
					doc_id : doc_id,
					value : value
				},
				onResponse : function(html){
					editor.setHTML(html);
				}
			}).fetch();
		}
	}

});
}

target.editor.edit(target);

.sb_inlineEditable textarea{
	cursor:text;
	display:block;
	width:97%;
	height:100px;
	overflow:auto;
	font-family:tahoma;
	font-size:1.1em;
}

.sb_inlineEditable editbar{
	text-align:right;
}

.sb_inlineEditable button{
	background-color:#d88713;
	color:#7c4e0d;
}

.sb_inlineEditable button:hover{
	background-color:#e2b370;
}

*/
sb.forms.inlineEditable.textarea = function(params){
	sb.objects.infuse(params, this);
	this.className = params.className || 'sb_inlineEditable';
	this.create();

};

sb.forms.inlineEditable.textarea.prototype = {

	/**
	@Name: sb.forms.inlineEditable.onBeforeEdit
	@Description: Fires before editing begins.  Can be used to load raw data with ajax
	to fill the textarea with.  Reference the textarea with this.textarea
	*/
	onBeforeEdit : function(){
		this.setValue(this.node.innerHTML);
	},

	/**
	@Name: sb.forms.inlineEditable.onBeforeEdit
	@Description: Passes the value of the textarea for you to save back with ajax
	@param string save The value of the textarea when save if fired
	*/
	onSave : function(value){},

	/**
	@Name: sb.forms.inlineEditable.onButtonPress
	@Description: Used Internally Fires when a button is pressed other than save or cancel
	@param event e The press event
	*/
	onButtonPress : function(e){},

	/**
	@Name: sb.forms.inlineEditable.setValue
	@Description: Sets the value of the textarea, use in onBeforeEdit
	*/
	setValue : function(value){
		this.textarea.value = value;
		this.focus();
	},

	/**
	@Name: sb.forms.inlineEditable.setHTML
	@Description: Sets the html of the element being edited, use in onSave
	*/
	setHTML : function(html){
		this.element.innerHTML = html;
		this.editStop();
	},

	/**
	@Name: sb.forms.inlineEditable.edit
	@Description: Put the editor in edit mode
	@param: element el the element to edit
	*/
	edit : function(el){

		this.editor.title = 'shortcuts: esc to cancel, ctrl+s to save';

		this.element = $(el);
		this.editor.replace(this.element);

		if(typeof this.onBeforeEdit == 'function'){
			this.onBeforeEdit.call(this);
		}
	},

	/**
	@Name: sb.forms.inlineEditable.editStop
	@Description: Exit edit mode
	*/
	editStop : function(){
		this.element.replace(this.editor);

		this._origValue = '';
	},

	/**
	@Name: sb.forms.inlineEditable.focus
	@Description: Focuses on text area and puts cursor at top left. automatically fires after setValue
	*/
	focus : function(){
		var ta = this.textarea;
		var range;
		if (this.textarea.setSelectionRange) {
			this.textarea.setSelectionRange(0, 0);
		} else if(this.textarea.createTextRange){
			range = this.textarea.createTextRange();
			range.collapse(true);
			range.moveStart("character", 0);
			range.moveEnd("character", 0 - 0);
			range.select();
		}
		this.textarea.focus();

	},

	/**
	@Name: sb.forms.inlineEditable.addButton
	@Description: Adds a button to the editBar
	*/
	addButton : function(str){
		this.editBar.innerHTML = '<button>'+str+'</button>'+this.editBar.innerHTML;

	},

	/**
	@Name: sb.forms.inlineEditable.addButton
	@Description: Determines if field is edited or not
	*/
	isNotEdited : function(){
		return !this._origValue || this._origValue == this.textarea.value;
	},

	/**
	@Name: sb.forms.inlineEditable.editStop
	@Description: Used internally Creates editor
	*/
	create : function(){
		var self = this;
		if(!this.editor){
			this.editor = new sb.element({
				tag : 'div',
				className : self.className
			});

			this.textarea = new sb.element({
				tag : 'textarea',
				value : this.value,
				className : this.className,
				events : {
					keydown : function(e){

						if(!self._origValue){
							self._origValue = self.textarea.value;
						}

						if(e.keyCode == 9 && self.isNotEdited()){
							self.editStop();
						} else if(e.keyCode == 27){
							self.editStop();
						} else if((e.ctrlKey || e.metaKey) && e.keyCode == 83){
							e.stopPropagation();
							e.preventDefault();
							self.onSave.call(self, self.textarea.value);
							self.editStop();
						}
					},
					blur : function(e){
						if(self.isNotEdited()){
							self.editStop();
						}

					}
				}
			});

			this.textarea.appendTo(this.editor);

			this.editBar = new sb.element({
				tag : 'editbar',
				styles : {
					display : 'block'
				},
				innerHTML : '<button>cancel</button><button>save</button>',
				events : {
					mousedown : function(e){
						var target = e.target;
						e.preventDefault();
						e.stopPropagation();
						if(target.nodeName == 'BUTTON'){

							switch(target.innerHTML){
								case 'save':
									self.onSave(self.textarea.value);
									break;

								case 'cancel':
									self.editStop();
									break;

								default:
									self.onButtonPress(e);
							}
						}

						return true;

					}
				}
			});

			this.editBar.appendTo(this.editor);
		}
	}
};<|endoftext|>


<commit_before>"use strict";
var x = '',
	y = '',
	z = '',
	final_transformation = '',
	scalex = '',
	scaley = '',
	translatex = '',
	translatey = '',
	translatez = '',
	skewY = '',
	skewX = '';
	/*is2dmatrix = false;*/ //transformations
var hor = '',
	ver = '',
	blur = '',
	spread = '',
	inset = '',
	red = "0",
	green = "0",
	blue = "0",
	color = 'rgb(250,48,90)',
	bshadow = '0px 0px black',
	transparency = 1; //box-shadow
var tl = '',
	tr = '',
	bl = '',
	br = '',
	rad = 0; //border-radius
//Text shadow properies
var text_shadow = "",
	text_shadow_x = "",
	text_shadow_y = "",
	text_shadow_blur = "",
	add_text_transform = false;;
//Text shadow color
//Note:We could use the color from the box-shadow but instead we choose to seperate box-shadow color from text-shadow color
var text_shadow_r = 0,
	text_shadow_g = 0,
	text_shadow_b = 0,
	text_shadow_opacity = 0,
	text_shadow_color = "";
var addRadius = false,
	addTransform = false;
var transform_fav = [],
	radius_fav = [],
	box_fav = [],
	text_fav = [];
var transform_col = 0,
	box_col = 0,
	radius_col = 0,
	text_col = 0; //columns in each table
var line = [false, false, false, false] //this array is used to create a new row in each favourite table after adding 3 cells in each row
function isBlack(color) {
	return ["#00", "#000000", "rgba(0,0,0,1)", "rgb(0,0,0)", "black"].indexOf(color) != -1;
}
function saving(type) {
	var file, blob;
	var i = 0;
	var transform_max = transform_fav.length,
		box_max = box_fav.length,
		radius_max = radius_fav.length,
		text_max = text_fav.length;
	switch (type) {
		case 'f':
			file = "/***\n";
			for (; i < transfom_max; i++) {
				fav += "-webkit-transform:" + transform_fav[i] + ";\n"
				fav += "-moz-transform:" + transform_fav[i] + ";\n"
				fav += "-ms-transform:" + transform_fav[i] + ";\n"
				fav += "transform:" + transform_fav[i] + ";\n"
			}
			for (; i < box_max; i++) {
				fav += "-webkit-box-shadow:" + box_fav[i] + ";\n";
				fav += "-moz-box-shadow:" + box_fav[i] + ";\n";
				fav += "-ms-box-shadow:" + box_fav[i] + ";\n";
				fav += "box-shadow:" + box_fav[i] + ";\n";
			}
			for (; i < radius_max; i++)
				fav += "border-radius:" + radius_fav[i] + ";\n";
			for (; i < text_max; i++)
				fav += "text-shadow:" + text_fav[i] + ";\n";
			file += "***/\n";
			break;
		default:
			file = "div{\n";
			file += "-webkit-transform:" + final_transformation + ";\n";
			file += "-moz-transform:" + final_transformation + ";\n";
			file += "-ms-transform:" + final_transformation + ";\n";
			file += "transform:" + final_transformation + ";\n";
			if (bshadow != "none") {
				file += "-webkit-box-shadow:" + bshadow + ";\n";
				file += "-moz-box-shadow:" + bshadow + ";\n";
				file += "-ms-box-shadow:" + bshadow + ";\n";
				file += "box-shadow:" + bshadow + ";\n";
			}
			if (addRadius)
				file += "border-radius:" + rad + ";\n";
			if (add_text_transform)
				file += "text-shadow:" + text_shadow + ";\n";
			file += "}";
			break;
	} //switch
	blob = new Blob([file], {
		type: "text/plain;charset=utf-8"
	});
	saveAs(blob, type == 'f' ? 'favourites.css' : 'transformations.css');
}
function fav(type) {
	switch (type) {
		case "text-shadow":
			if (text_shadow != "none" && text_fav.indexOf(text_shadow) == -1) {
				text_fav.push(text_shadow);
				if (!line[3]) {
					$("#table_text tbody").append("
");
					line[3] = true;
				}
				if (text_col == 4) {
					text_col = 0;
					$("#table_text").append("

");
				}
				$("#table_text tbody tr:last").append("" + text_shadow + "	");
				text_col++;
				$("#text_total").text("(" + text_fav.length + ")");
			}
		case "radius":
			if (rad !== 0 && radius_fav.indexOf(rad) == -1) {
				radius_fav.push(rad);
				if (!line[2]) {
					$("#table_rad tbody").append("
");
					line[2] = true;
				}
				if (radius_col == 3) {
					radius_col = 0;
					$("#table_rad").append("

");
				}
				$("#table_rad tbody tr:last").append("" + rad + "	");
				radius_col++;
				$("#radius_total").text("(" + radius_fav.length + ")");
			}
			break;
		case "transform":
			if (transform_fav.indexOf(final_transformation) == -1 && final_transformation !== "rotate(0)") {
				//mind the gap after rotate(0)
				transform_fav.push(final_transformation);
				if (!line[0]) {
					$("#table_tran tbody").append("
");
					line[0] = true;
				}
				$("#table_tran tbody tr:last").append("" + final_transformation + "	");
				transform_col++;
				if (transform_col == 3) {
					transform_col = 0;
					$("#table_tran").append("

");
				}
				$("#totaltran").text("(" + transform_fav.length + ")");
			}
			break;
		default:
			if (box_fav.indexOf(bshadow) == -1) {
				box_fav.push(bshadow);
				if (!line[1]) {
					$("#table_box tbody").append("
");
					line[1] = true;
				}
				$("#table_box tbody tr:last").append("" + bshadow + "	");
				box_col++;
				if (box_col == 3) {
					box_col = 0;
					$("#table_box").append("

");
				}
				$("#box_total").text("(" + box_fav.length + ")");
			} //if indexOf()==-1
			break;
	} //switch
} //fav
function log(o) {
	console.log(o);
}
function removefav() {
	bootbox.confirm("Are you sure you want to delete your favourites?", function(answer) {
		//bootbox.confirm() requires a callback function as the second parameter
		if (answer) {
			line[0] = line[1] = line[2] = line[3] = false;
			box_fav.length = radius_fav.length = transform_fav.length = text_fav.length = 0; //empty all the lists
			$("#box_total,#totaltran,#radius_total").text("(0)");
		}
	});
}
function update() {
	function val(o) {
		return $(o).val();
	}
	function float(o) {
		return parseFloat(val(o));
	}
	function int(o) {
		return parseInt(val(o));
	}
	x = int("#rotatexd");
	y = int("#rotatey");
	z = int("#rotatez");
	scalex = float("#scalex");
	scaley = float("#scaley");
	translatex = int("#tranx");
	translatey = int("#trany");
	translatez = int("#tranz");
	skewY = int("#skewy");
	skewX = int("#skewx");
	tl = val("#tl");
	tr = val("#tr");
	bl = val("#bl");
	br = val("#br");
	hor = val("#hor_axis");
	ver = val("#ver_axis");
	blur = val('#blur');
	spread = val("#spread");
	transparency = float("#trans");
	inset = int("#in");
	/*colors*/
	red = int("#red");
	green = int("#green");
	blue = int("#blue");
	//Text shadow values
	text_shadow_x = int("#text_shadow_x");
	text_shadow_y = int("#text_shadow_y");
	text_shadow_blur = float("#text_shadow_blur");
	text_shadow_r = int("#text_shadow_red");
	text_shadow_g = int("#text_shadow_green");
	text_shadow_b = int("#text_shadow_blue");
	text_shadow_opacity = float("#text_shadow_opacity");
	add_text_transform = text_shadow_x + text_shadow_y + text_shadow_blur != 0;
} //update
$(document).ready(function() {
	$("#controllers h1").click(function() {
		$(this).next('.slider_container').toggle(800);
	});
	//var rotate = (axis,deg)=> "rotate"+axis+"("+deg+"deg)";
	$(".ultra_app").on("input change touchmove", function() {
		update();
		final_transformation = "";
		if (x)
			final_transformation += "rotateX(" + x + "deg)";
		if (y)
			final_transformation += " rotateY(" + y + "deg)";
		if (z)
			final_transformation += " rotateZ(" + z + "deg)";
		if (scalex !== 1 || scaley !== 1)
			final_transformation += " scale(" + scalex + "," + scaley + ")";
		if (translatex !== 0 || translatey !== 0 || translatez !== 0) {
			if (translatex !== 0 && translatey == 0 && translatez == 0)
				final_transformation += " translateX(" + translatex + "px)";
			else if (translatey !== 0 && translatex == 0 && translatez == 0)
				final_transformation += " translateY(" + translatey + "px)";
			else if (translatez !== 0 && translatex == 0 && translatey == 0)
				final_transformation += " translateZ(" + translatez + "px)";
			else if (translatex == 0)
				final_transformation += " translateY(" + translatey + "px) translateZ(" + translatez + "px)";
			else if (translatez == 0)
				final_transformation += " translateX(" + translatex + "px) translateY(" + translatey + "px)";
			else if (translatey == 0)
				final_transformation += " translateX(" + translatex + "px) translateZ(" + translatez + "px)";
			else
				final_transformation += " translateX(" + translatex + "px) translateY(" + translatey + "px) translateZ(" + translatez + "px)";
		}
		//if scalex != 1 || scaley != 1
		//If the skew's sliders have been changed e.g, moved from 0 to 1 or from 0 to 100 add skew property
		if (skewX || skewY)
			final_transformation += " skew(" + skewX + "deg," + skewY + "deg)";
		if (hor+ver == 0 && blur == 0 && spread == 0){
    		bshadow="none";//If we haven't touched any box_shadow slider then there is no box-shadow so set it to none
    		$("#boxshadowcode").hide();
   		}
		else {
			$("#boxshadowcode").show();
			bshadow = hor + "px " + ver + "px " + blur + "px " + spread + "px";
		}
		color = transparency == 1 ? " rgb(" + red + "," + green + "," + blue + ")" : " rgba(" + red + "," + green + "," + blue + "," + transparency + ")";
		if (inset) bshadow = "inset " + bshadow;
		if (bshadow != 'none')
			bshadow += color;
		if (tl + tr + bl + br == 0)
			rad = 0;
		else {
			addRadius = true;
			rad = tl + "px " + tr + "px " + br + "px " + bl + "px";
		}
		if (text_shadow_x + text_shadow_y + text_shadow_blur == 0)
			text_shadow = "none";
		else {
			text_shadow = text_shadow_x + "px " + text_shadow_y + "px ";
			if (text_shadow_blur != 0)
				text_shadow += text_shadow_blur + "px ";
			text_shadow_color = text_shadow_opacity != 1 ? "rgba(" + text_shadow_r + "," + text_shadow_g + "," + text_shadow_b + "," + text_shadow_opacity + ")" : "rgb(" + text_shadow_r + "," + text_shadow_g + "," + text_shadow_b + ")";
			text_shadow += text_shadow_color;
		}
		$('#totransform').css({
			"transform": final_transformation,
			"box-shadow": bshadow,
			"border-radius": rad
		});
		$("#text_shadow_demo").css("text-shadow", text_shadow);
		$('.transform').text(final_transformation);
		$('.box').text(bshadow);
		$('.borderRadius').text(rad);
		$(".text_shadow_code_output").text(text_shadow);
	});
	$("#restart").click(function() {
		final_transformation = bshadow = text_shadow = "none";
		rad = 0;
		$("#boxshadowcode").hide();
		$('.ultra_app:not(#trans,.scale,#text_shadow_opacity)').val(0);
		$('.scale,#trans').val(1);
		$('#totransform').css({
			"transform": "none",
			"box-shadow": "none",
			"border-radius": "0"
		});
		$("#text_shadow_demo").css("text-shadow", "none");
		$('.transform,.box,.text_shadow_code_output,.borderRadius').text("none");
	});
	$("#table_tran").on("click", 'td', function() {
		var f = $(this).html();
		$("#totransform").css("transform", f);
	});
});
$(document).on('click', '.modal-backdrop', function(event) {
	bootbox.hideAll();
});
<commit_msg>bug fixes<commit_after>"use strict";
var x = '',
	y = '',
	z = '',
	final_transformation = '',
	scalex = '',
	scaley = '',
	translatex = '',
	translatey = '',
	translatez = '',
	skewY = '',
	skewX = '';
	/*is2dmatrix = false;*/ //transformations
var hor = '',
	ver = '',
	blur = '',
	spread = '',
	inset = '',
	red = "0",
	green = "0",
	blue = "0",
	color = 'rgb(250,48,90)',
	bshadow = '0px 0px black',
	transparency = 1; //box-shadow
var tl = '',
	tr = '',
	bl = '',
	br = '',
	rad = 0; //border-radius
//Text shadow properies
var text_shadow = "",
	text_shadow_x = "",
	text_shadow_y = "",
	text_shadow_blur = "",
	add_text_transform = false;;
//Text shadow color
//Note:We could use the color from the box-shadow but instead we choose to seperate box-shadow color from text-shadow color
var text_shadow_r = 0,
	text_shadow_g = 0,
	text_shadow_b = 0,
	text_shadow_opacity = 0,
	text_shadow_color = "";
var addRadius = false,
	addTransform = false;
var transform_fav = [],
	radius_fav = [],
	box_fav = [],
	text_fav = [];
var transform_col = 0,
	box_col = 0,
	radius_col = 0,
	text_col = 0; //columns in each table
var line = [false, false, false, false] //this array is used to create a new row in each favourite table after adding 3 cells in each row
function isBlack(color) {
	return ["#00", "#000000", "rgba(0,0,0,1)", "rgb(0,0,0)", "black"].indexOf(color) != -1;
}
function saving(type) {
	var file, blob;
	var i = 0;
	var transform_max = transform_fav.length,
		box_max = box_fav.length,
		radius_max = radius_fav.length,
		text_max = text_fav.length;
	switch (type) {
		case 'f':
			file = "/***\n";
			for (; i < transfom_max; i++) {
				fav += "-webkit-transform:" + transform_fav[i] + ";\n"
				fav += "-moz-transform:" + transform_fav[i] + ";\n"
				fav += "-ms-transform:" + transform_fav[i] + ";\n"
				fav += "transform:" + transform_fav[i] + ";\n"
			}
			for (; i < box_max; i++) {
				fav += "-webkit-box-shadow:" + box_fav[i] + ";\n";
				fav += "-moz-box-shadow:" + box_fav[i] + ";\n";
				fav += "-ms-box-shadow:" + box_fav[i] + ";\n";
				fav += "box-shadow:" + box_fav[i] + ";\n";
			}
			for (; i < radius_max; i++)
				fav += "border-radius:" + radius_fav[i] + ";\n";
			for (; i < text_max; i++)
				fav += "text-shadow:" + text_fav[i] + ";\n";
			file += "***/\n";
			break;
		default:
			file = "div{\n";
			file += "-webkit-transform:" + final_transformation + ";\n";
			file += "-moz-transform:" + final_transformation + ";\n";
			file += "-ms-transform:" + final_transformation + ";\n";
			file += "transform:" + final_transformation + ";\n";
			if (bshadow != "none") {
				file += "-webkit-box-shadow:" + bshadow + ";\n";
				file += "-moz-box-shadow:" + bshadow + ";\n";
				file += "-ms-box-shadow:" + bshadow + ";\n";
				file += "box-shadow:" + bshadow + ";\n";
			}
			if (addRadius)
				file += "border-radius:" + rad + ";\n";
			if (add_text_transform)
				file += "text-shadow:" + text_shadow + ";\n";
			file += "}";
			break;
	} //switch
	blob = new Blob([file], {
		type: "text/plain;charset=utf-8"
	});
	saveAs(blob, type == 'f' ? 'favourites.css' : 'transformations.css');
}
function fav(type) {
	switch (type) {
		case "text-shadow":
			if (text_shadow != "none" && text_fav.indexOf(text_shadow) == -1) {
				text_fav.push(text_shadow);
				if (!line[3]) {
					$("#table_text tbody").append("
");
					line[3] = true;
				}
				if (text_col == 4) {
					text_col = 0;
					$("#table_text").append("

");
				}
				$("#table_text tbody tr:last").append("" + text_shadow + "	");
				text_col++;
				$("#text_total").text("(" + text_fav.length + ")");
			}
		case "radius":
			if (rad !== 0 && radius_fav.indexOf(rad) == -1) {
				radius_fav.push(rad);
				if (!line[2]) {
					$("#table_rad tbody").append("
");
					line[2] = true;
				}
				if (radius_col == 3) {
					radius_col = 0;
					$("#table_rad").append("

");
				}
				$("#table_rad tbody tr:last").append("" + rad + "	");
				radius_col++;
				$("#radius_total").text("(" + radius_fav.length + ")");
			}
			break;
		case "transform":
			if (transform_fav.indexOf(final_transformation) == -1 && final_transformation !== "rotate(0)") {
				//mind the gap after rotate(0)
				transform_fav.push(final_transformation);
				if (!line[0]) {
					$("#table_tran tbody").append("
");
					line[0] = true;
				}
				$("#table_tran tbody tr:last").append("" + final_transformation + "	");
				transform_col++;
				if (transform_col == 3) {
					transform_col = 0;
					$("#table_tran").append("

");
				}
				$("#totaltran").text("(" + transform_fav.length + ")");
			}
			break;
		default:
			if (box_fav.indexOf(bshadow) == -1) {
				box_fav.push(bshadow);
				if (!line[1]) {
					$("#table_box tbody").append("
");
					line[1] = true;
				}
				$("#table_box tbody tr:last").append("" + bshadow + "	");
				box_col++;
				if (box_col == 3) {
					box_col = 0;
					$("#table_box").append("

");
				}
				$("#box_total").text("(" + box_fav.length + ")");
			} //if indexOf()==-1
			break;
	} //switch
} //fav
function log(o) {
	console.log(o);
}
function removefav() {
	bootbox.confirm("Are you sure you want to delete your favourites?", function(answer) {
		//bootbox.confirm() requires a callback function as the second parameter
		if (answer) {
			line[0] = line[1] = line[2] = line[3] = false;
			box_fav.length = radius_fav.length = transform_fav.length = text_fav.length = 0; //empty all the lists
			$("#box_total,#totaltran,#radius_total").text("(0)");
		}
	});
}
function update() {
	function val(o) {
		return $(o).val();
	}
	function float(o) {
		return parseFloat(val(o));
	}
	function int(o) {
		return parseInt(val(o));
	}
	x = int("#rotatexd");
	y = int("#rotatey");
	z = int("#rotatez");
	scalex = float("#scalex");
	scaley = float("#scaley");
	translatex = int("#tranx");
	translatey = int("#trany");
	translatez = int("#tranz");
	skewY = int("#skewy");
	skewX = int("#skewx");
	tl = val("#tl");
	tr = val("#tr");
	bl = val("#bl");
	br = val("#br");
	hor = val("#hor_axis");
	ver = val("#ver_axis");
	blur = val('#blur');
	spread = val("#spread");
	transparency = float("#trans");
	inset = int("#in");
	/*colors*/
	red = int("#red");
	green = int("#green");
	blue = int("#blue");
	//Text shadow values
	text_shadow_x = int("#text_shadow_x");
	text_shadow_y = int("#text_shadow_y");
	text_shadow_blur = float("#text_shadow_blur");
	text_shadow_r = int("#text_shadow_red");
	text_shadow_g = int("#text_shadow_green");
	text_shadow_b = int("#text_shadow_blue");
	text_shadow_opacity = float("#text_shadow_opacity");
	add_text_transform = text_shadow_x + text_shadow_y + text_shadow_blur != 0;
} //update
$(document).ready(function() {
	$("#controllers h1").click(function() {
		$(this).next('.slider_container').toggle(800);
	});
	//var rotate = (axis,deg)=> "rotate"+axis+"("+deg+"deg)";
	$(".ultra_app").on("input change touchmove", function() {
		update();
		final_transformation = "";
		if (x)
			final_transformation += "rotateX(" + x + "deg)";
		if (y)
			final_transformation += " rotateY(" + y + "deg)";
		if (z)
			final_transformation += " rotateZ(" + z + "deg)";
		if (scalex !== 1 || scaley !== 1)
			final_transformation += " scale(" + scalex + "," + scaley + ")";
		if (translatex !== 0 || translatey !== 0 || translatez !== 0) {
			if (translatex !== 0 && translatey == 0 && translatez == 0)
				final_transformation += " translateX(" + translatex + "px)";
			else if (translatey !== 0 && translatex == 0 && translatez == 0)
				final_transformation += " translateY(" + translatey + "px)";
			else if (translatez !== 0 && translatex == 0 && translatey == 0)
				final_transformation += " translateZ(" + translatez + "px)";
			else if (translatex == 0)
				final_transformation += " translateY(" + translatey + "px) translateZ(" + translatez + "px)";
			else if (translatez == 0)
				final_transformation += " translateX(" + translatex + "px) translateY(" + translatey + "px)";
			else if (translatey == 0)
				final_transformation += " translateX(" + translatex + "px) translateZ(" + translatez + "px)";
			else
				final_transformation += " translateX(" + translatex + "px) translateY(" + translatey + "px) translateZ(" + translatez + "px)";
		}
		//if scalex != 1 || scaley != 1
		//If the skew's sliders have been changed e.g, moved from 0 to 1 or from 0 to 100 add skew property
		if (skewX || skewY)
			final_transformation += " skew(" + skewX + "deg," + skewY + "deg)";
		if (hor+ver == 0 && blur == 0 && spread == 0){
    		bshadow="none";//If we haven't touched any box_shadow slider then there is no box-shadow so set it to none
    		$("#boxshadowcode").hide();
   		}
		else {
			$("#boxshadowcode").show();
			bshadow = hor + "px " + ver + "px " + blur + "px " + spread + "px";
		}
		color = transparency == 1 ? " rgb(" + red + "," + green + "," + blue + ")" : " rgba(" + red + "," + green + "," + blue + "," + transparency + ")";
		if (inset) bshadow = "inset " + bshadow;
		if (bshadow != 'none')
			bshadow += color;
		if (tl + tr + bl + br == 0)
			rad = 0;
		else {
			addRadius = true;
			rad = tl + "px " + tr + "px " + br + "px " + bl + "px";
		}
		if (text_shadow_x + text_shadow_y + text_shadow_blur == 0)
			text_shadow = "none";
		else {
			text_shadow = text_shadow_x + "px " + text_shadow_y + "px ";
			if (text_shadow_blur)
				text_shadow += text_shadow_blur + "px ";
			text_shadow_color = text_shadow_opacity != 1 ? "rgba(" + text_shadow_r + "," + text_shadow_g + "," + text_shadow_b + "," + text_shadow_opacity + ")" : "rgb(" + text_shadow_r + "," + text_shadow_g + "," + text_shadow_b + ")";
			text_shadow += text_shadow_color;
		}
		$('#totransform').css({
			"transform": final_transformation,
			"box-shadow": bshadow,
			"border-radius": rad
		});
		$("#text_shadow_demo").css("text-shadow", text_shadow);
		$('.transform').text(final_transformation==''?'none':final_transformation);
		$('.box').text(bshadow);
		$('.borderRadius').text(rad);
		$(".text_shadow_code_output").text(text_shadow);
	});
	$("#restart").click(function() {
		final_transformation = bshadow = text_shadow = "none";
		rad = 0;
		$("#boxshadowcode").hide();
		$('.ultra_app:not(#trans,.scale,#text_shadow_opacity)').val(0);
		$('.scale,#trans').val(1);
		$('#totransform').css({
			"transform": "none",
			"box-shadow": "none",
			"border-radius": "0"
		});
		$("#text_shadow_demo").css("text-shadow", "none");
		$('.transform,.box,.text_shadow_code_output,.borderRadius').text("none");
	});
	$("#table_tran").on("click", 'td', function() {
		var f = $(this).html();
		$("#totransform").css("transform", f);
	});
});
$(document).on('click', '.modal-backdrop', function(event) {
	bootbox.hideAll();
});
<|endoftext|>


<commit_before>/* eslint-disable no-underscore-dangle */

import warning from 'warning';

// People might bundle this classname generator twice.
// We need to use a global.
global.__MUI_GENERATOR_COUNTER__ = 0;

// Returns a function which generates unique class names based on counters.
// When new generator function is created, rule counter is reset.
// We need to reset the rule counter for SSR for each request.
//
// It's inspired by
// https://github.com/cssinjs/jss/blob/4e6a05dd3f7b6572fdd3ab216861d9e446c20331/src/utils/createGenerateClassName.js
export default function createGenerateClassName(options = {}) {
  const { dangerouslyUseGlobalCSS = false, productionPrefix = 'jss' } = options;
  const escapeRegex = /([[\].#*$><+~=|^:(),"'`\s])/g;
  let ruleCounter = 0;

  // - HMR can lead to many class name generators being instantiated,
  // so the warning is only triggered in production.
  // - We expect a class name generator to be instantiated per new request on the server,
  // so the warning is only triggered client side.
  // - You can get away with having multiple class name generators
  // by modifying the `productionPrefix`.
  if (
    process.env.NODE_ENV === 'production' &&
    typeof window !== 'undefined' &&
    productionPrefix === 'jss'
  ) {
    global.__MUI_GENERATOR_COUNTER__ += 1;

    if (global.__MUI_GENERATOR_COUNTER__ > 2) {
      // eslint-disable-next-line no-console
      console.error(
        [
          'Material-UI: we have detected more than needed creation of the class name generator.',
          'You should only use one class name generator on the client side.',
          'If you do otherwise, you take the risk to have conflicting class names in production.',
        ].join('\n'),
      );
    }
  }

  return (rule, styleSheet) => {
    ruleCounter += 1;
    warning(
      ruleCounter < 1e10,
      [
        'Material-UI: you might have a memory leak.',
        'The ruleCounter is not supposed to grow that much.',
      ].join(''),
    );

    // Code branch the whole block at the expense of more code.
    if (dangerouslyUseGlobalCSS) {
      if (styleSheet && styleSheet.options.classNamePrefix) {
        let prefix = styleSheet.options.classNamePrefix;
        // Sanitize the string as will be used to prefix the generated class name.
        prefix = prefix.replace(escapeRegex, '-');

        if (prefix.match(/^Mui/)) {
          return `${prefix}-${rule.key}`;
        }

        if (process.env.NODE_ENV !== 'production') {
          return `${prefix}-${rule.key}-${ruleCounter}`;
        }
      }

      if (process.env.NODE_ENV === 'production') {
        return `${productionPrefix}${ruleCounter}`;
      }

      return `${rule.key}-${ruleCounter}`;
    }

    if (process.env.NODE_ENV === 'production') {
      return `${productionPrefix}${ruleCounter}`;
    }

    if (styleSheet && styleSheet.options.classNamePrefix) {
      let prefix = styleSheet.options.classNamePrefix;
      // Sanitize the string as will be used to prefix the generated class name.
      prefix = prefix.replace(escapeRegex, '-');

      return `${prefix}-${rule.key}-${ruleCounter}`;
    }

    return `${rule.key}-${ruleCounter}`;
  };
}
<commit_msg>[core] Better warnings for class names duplicates (#11788)<commit_after>/* eslint-disable no-underscore-dangle */

import warning from 'warning';

// People might bundle this classname generator twice.
// We need to use a global.
global.__MUI_GENERATOR_COUNTER__ = 0;

// Returns a function which generates unique class names based on counters.
// When new generator function is created, rule counter is reset.
// We need to reset the rule counter for SSR for each request.
//
// It's inspired by
// https://github.com/cssinjs/jss/blob/4e6a05dd3f7b6572fdd3ab216861d9e446c20331/src/utils/createGenerateClassName.js
export default function createGenerateClassName(options = {}) {
  const { dangerouslyUseGlobalCSS = false, productionPrefix = 'jss' } = options;
  const escapeRegex = /([[\].#*$><+~=|^:(),"'`\s])/g;
  let ruleCounter = 0;

  // - HMR can lead to many class name generators being instantiated,
  // so the warning is only triggered in production.
  // - We expect a class name generator to be instantiated per new request on the server,
  // so the warning is only triggered client side.
  if (process.env.NODE_ENV === 'production' && typeof window !== 'undefined') {
    global.__MUI_GENERATOR_COUNTER__ += 1;

    if (global.__MUI_GENERATOR_COUNTER__ > 2) {
      // eslint-disable-next-line no-console
      console.error(
        [
          'Material-UI: we have detected more than needed creation of the class name generator.',
          'You should only use one class name generator on the client side.',
          'If you do otherwise, you take the risk to have conflicting class names in production.',
        ].join('\n'),
      );
    }
  }

  return (rule, styleSheet) => {
    ruleCounter += 1;
    warning(
      ruleCounter < 1e10,
      [
        'Material-UI: you might have a memory leak.',
        'The ruleCounter is not supposed to grow that much.',
      ].join(''),
    );

    // Code branch the whole block at the expense of more code.
    if (dangerouslyUseGlobalCSS) {
      if (styleSheet && styleSheet.options.classNamePrefix) {
        let prefix = styleSheet.options.classNamePrefix;
        // Sanitize the string as will be used to prefix the generated class name.
        prefix = prefix.replace(escapeRegex, '-');

        if (prefix.match(/^Mui/)) {
          return `${prefix}-${rule.key}`;
        }

        if (process.env.NODE_ENV !== 'production') {
          return `${prefix}-${rule.key}-${ruleCounter}`;
        }
      }

      if (process.env.NODE_ENV === 'production') {
        return `${productionPrefix}${ruleCounter}`;
      }

      return `${rule.key}-${ruleCounter}`;
    }

    if (process.env.NODE_ENV === 'production') {
      return `${productionPrefix}${ruleCounter}`;
    }

    if (styleSheet && styleSheet.options.classNamePrefix) {
      let prefix = styleSheet.options.classNamePrefix;
      // Sanitize the string as will be used to prefix the generated class name.
      prefix = prefix.replace(escapeRegex, '-');

      return `${prefix}-${rule.key}-${ruleCounter}`;
    }

    return `${rule.key}-${ruleCounter}`;
  };
}
<|endoftext|>


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

goog.provide('jsprettify.prettifyStr');

goog.require('goog.array');
goog.require('jsprettify.entities');

/**
 * Prettifies strings by replacing ASCII shorthand with proper typographical
 * symbols.
 * @param {string} text Text to prettify.
 * @return {string} Prettified text.
 */
jsprettify.prettifyStr = function(text) {
  var e = jsprettify.entities;
  // We replace single-quoted expressions by looking for pairs with the
  // shortest distance between them: we grab an open quote, any intervening
  // text, and a close quote.
  var pattern = new RegExp("(^|[\\s\"])'([\\s\\S]*?)'($|[\\s\".,;:?!])", 'g');
  var replace = '$1' + e.lsquo + '$2' + e.rsquo + '$3';
  // We run the regexp until the string stops changing to handle nested quotes
  // and adjacent quotes.
  var old;
  do {
    old = text;
    text = text.replace(pattern, replace);
  } while (old != text);
  /**
   * This array holds entries consisting of patterns and replacements in the
   * order that they are to be applied. We need to preserve order, since e.g.
   * if -- were replaced before ---, disaster would ensue.
   * @type {Array.<{pattern: string, replace: string}>}
   */
  var subs = [
    {pattern: '\\.\\.\\.',         replace: e.hellip},
    {pattern: "'",                 replace: e.rsquo},
    {pattern: '"($|[\\s.,;:?!])',  replace: e.rdquo + '$1'},
    {pattern: '(^|[\\s-])"',       replace: '$1' + e.ldquo},
    {pattern: '---',               replace: e.emdash},
    {pattern: '--',                replace: e.endash}
  ];
  goog.array.forEach(subs, function(sub) {
    var pattern = new RegExp(sub.pattern, 'g');
    text = text.replace(pattern, sub.replace);
  });
  return text;
};

window['prettifyStr'] = jsprettify.prettifyStr;
<commit_msg>Match hyphens as things that can occur before or after single quotes.<commit_after>// Copyright 2010 Steven Dee. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

goog.provide('jsprettify.prettifyStr');

goog.require('goog.array');
goog.require('jsprettify.entities');

/**
 * Prettifies strings by replacing ASCII shorthand with proper typographical
 * symbols.
 * @param {string} text Text to prettify.
 * @return {string} Prettified text.
 */
jsprettify.prettifyStr = function(text) {
  var e = jsprettify.entities;
  // We replace single-quoted expressions by looking for pairs with the
  // shortest distance between them: we grab an open quote, any intervening
  // text, and a close quote.
  var pattern = new RegExp("(^|[\\s\"-])'([\\s\\S]*?)'($|[\\s\".,;:?!-])", 'g');
  var replace = '$1' + e.lsquo + '$2' + e.rsquo + '$3';
  // We run the regexp until the string stops changing to handle nested quotes
  // and adjacent quotes.
  var old;
  do {
    old = text;
    text = text.replace(pattern, replace);
  } while (old != text);
  /**
   * This array holds entries consisting of patterns and replacements in the
   * order that they are to be applied. We need to preserve order, since e.g.
   * if -- were replaced before ---, disaster would ensue.
   * @type {Array.<{pattern: string, replace: string}>}
   */
  var subs = [
    {pattern: '\\.\\.\\.',         replace: e.hellip},
    {pattern: "'",                 replace: e.rsquo},
    {pattern: '"($|[\\s.,;:?!])',  replace: e.rdquo + '$1'},
    {pattern: '(^|[\\s-])"',       replace: '$1' + e.ldquo},
    {pattern: '---',               replace: e.emdash},
    {pattern: '--',                replace: e.endash}
  ];
  goog.array.forEach(subs, function(sub) {
    var pattern = new RegExp(sub.pattern, 'g');
    text = text.replace(pattern, sub.replace);
  });
  return text;
};

window['prettifyStr'] = jsprettify.prettifyStr;
<|endoftext|>


<commit_before>// @flow

import styles from './AppRoute.css';
import React, { PureComponent, type Element } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { dispatched } from '@webkom/react-prepare';
import Helmet from 'react-helmet';
import Raven from 'raven-js';
import {
  loginAutomaticallyIfPossible,
  logout,
  login
} from 'app/actions/UserActions';
import {
  fetchNotificationData,
  markAllNotifications,
  markNotification
} from 'app/actions/NotificationsFeedActions';
import { fetchNotificationFeed } from 'app/actions/FeedActions';
import { fetchMeta } from 'app/actions/MetaActions';
import { selectFeedActivitesByFeedId } from 'app/reducers/feeds';
import { toggleSearch } from 'app/actions/SearchActions';
import Header from 'app/components/Header';
import Footer from 'app/components/Footer';
import NotificationContainer from 'app/components/NotificationContainer';
import { selectIsLoggedIn, selectCurrentUser } from 'app/reducers/auth';
import cx from 'classnames';
import HTTPError from '../errors/HTTPError';
import { setStatusCode } from 'app/actions/RoutingActions';

type Props = {
  statusCode: number,
  location: any,
  children: Element<*>,
  currentUser: /*TODO: User*/ Object,
  setStatusCode: (code: ?number) => void,
  loggedIn: boolean
};

class AppChildren extends PureComponent<Props> {
  render() {
    return (

        <NotificationContainer />
        {this.props.statusCode ? (
          <HTTPError
            statusCode={this.props.statusCode}
            setStatusCode={this.props.setStatusCode}
            location={this.props.location}
          />
        ) : (
          React.cloneElement(this.props.children, {
            currentUser: this.props.currentUser,
            loggedIn: this.props.loggedIn
          })
        )}

    );
  }
}

// TODO: Type it
type AppProps = any;

class App extends PureComponent<AppProps> {
  componentWillReceiveProps(nextProps: Props) {
    Raven.setUserContext(nextProps.currentUser);
  }

  render() {
    return (

        <Helmet defaultTitle="Abakus.no" titleTemplate="%s | Abakus.no" />

        <Header
          searchOpen={this.props.searchOpen}
          toggleSearch={this.props.toggleSearch}
          currentUser={this.props.currentUser}
          loggedIn={this.props.loggedIn}
          logout={this.props.logout}
          login={this.props.login}
          notificationsData={this.props.notificationsData}
          fetchNotifications={this.props.fetchNotificationFeed}
          notifications={this.props.notifications}
          markNotification={this.props.markNotification}
          markAllNotifications={this.props.markAllNotifications}
          fetchNotificationData={this.props.fetchNotificationData}
        />

        <AppChildren
          currentUser={this.props.currentUser}
          loggedIn={this.props.loggedIn}
          statusCode={this.props.statusCode}
          setStatusCode={this.props.setStatusCode}
          location={this.props.location}
        >
          {this.props.children}
        </AppChildren>

    );
  }
}

function mapStateToProps(state) {
  return {
    searchOpen: state.search.open,
    currentUser: selectCurrentUser(state),
    loggedIn: selectIsLoggedIn(state),
    notificationsData: state.notificationsFeed,
    notifications: selectFeedActivitesByFeedId(state, {
      feedId: 'notifications'
    }),
    statusCode: state.routing.statusCode
  };
}

function fetchInitialOnServer(props, dispatch) {
  return dispatch(loginAutomaticallyIfPossible()).then(() =>
    dispatch(fetchMeta())
  );
}

const mapDispatchToProps = {
  toggleSearch,
  logout,
  login,
  fetchNotificationFeed,
  markNotification,
  markAllNotifications,
  fetchNotificationData,
  setStatusCode
};

export default compose(
  dispatched(fetchInitialOnServer, {
    componentDidMount: false,
    componentWillReceiveProps: false
  }),
  dispatched((props, dispatch) => dispatch(fetchNotificationData())),
  connect(mapStateToProps, mapDispatchToProps)
)(App);
<commit_msg>Add a red development header to prevent us from making mistakes in prod<commit_after>// @flow

import styles from './AppRoute.css';
import React, { PureComponent, type Element } from 'react';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { dispatched } from '@webkom/react-prepare';
import Helmet from 'react-helmet';
import Raven from 'raven-js';
import {
  loginAutomaticallyIfPossible,
  logout,
  login
} from 'app/actions/UserActions';
import {
  fetchNotificationData,
  markAllNotifications,
  markNotification
} from 'app/actions/NotificationsFeedActions';
import { fetchNotificationFeed } from 'app/actions/FeedActions';
import { fetchMeta } from 'app/actions/MetaActions';
import { selectFeedActivitesByFeedId } from 'app/reducers/feeds';
import { toggleSearch } from 'app/actions/SearchActions';
import Header from 'app/components/Header';
import Footer from 'app/components/Footer';
import NotificationContainer from 'app/components/NotificationContainer';
import { selectIsLoggedIn, selectCurrentUser } from 'app/reducers/auth';
import cx from 'classnames';
import HTTPError from '../errors/HTTPError';
import { setStatusCode } from 'app/actions/RoutingActions';
import config from 'app/config';

type Props = {
  statusCode: number,
  location: any,
  children: Element<*>,
  currentUser: /*TODO: User*/ Object,
  setStatusCode: (code: ?number) => void,
  loggedIn: boolean
};

class AppChildren extends PureComponent<Props> {
  render() {
    return (

        <NotificationContainer />
        {this.props.statusCode ? (
          <HTTPError
            statusCode={this.props.statusCode}
            setStatusCode={this.props.setStatusCode}
            location={this.props.location}
          />
        ) : (
          React.cloneElement(this.props.children, {
            currentUser: this.props.currentUser,
            loggedIn: this.props.loggedIn
          })
        )}

    );
  }
}

// TODO: Type it
type AppProps = any;

class App extends PureComponent<AppProps> {
  componentWillReceiveProps(nextProps: Props) {
    Raven.setUserContext(nextProps.currentUser);
  }

  render() {
    return (

        <Helmet defaultTitle="Abakus.no" titleTemplate="%s | Abakus.no" />

        {config.environment !== 'production' && (

            This is a development version of lego-webapp.

        )}

        <Header
          searchOpen={this.props.searchOpen}
          toggleSearch={this.props.toggleSearch}
          currentUser={this.props.currentUser}
          loggedIn={this.props.loggedIn}
          logout={this.props.logout}
          login={this.props.login}
          notificationsData={this.props.notificationsData}
          fetchNotifications={this.props.fetchNotificationFeed}
          notifications={this.props.notifications}
          markNotification={this.props.markNotification}
          markAllNotifications={this.props.markAllNotifications}
          fetchNotificationData={this.props.fetchNotificationData}
        />

        <AppChildren
          currentUser={this.props.currentUser}
          loggedIn={this.props.loggedIn}
          statusCode={this.props.statusCode}
          setStatusCode={this.props.setStatusCode}
          location={this.props.location}
        >
          {this.props.children}
        </AppChildren>

    );
  }
}

function mapStateToProps(state) {
  return {
    searchOpen: state.search.open,
    currentUser: selectCurrentUser(state),
    loggedIn: selectIsLoggedIn(state),
    notificationsData: state.notificationsFeed,
    notifications: selectFeedActivitesByFeedId(state, {
      feedId: 'notifications'
    }),
    statusCode: state.routing.statusCode
  };
}

function fetchInitialOnServer(props, dispatch) {
  return dispatch(loginAutomaticallyIfPossible()).then(() =>
    dispatch(fetchMeta())
  );
}

const mapDispatchToProps = {
  toggleSearch,
  logout,
  login,
  fetchNotificationFeed,
  markNotification,
  markAllNotifications,
  fetchNotificationData,
  setStatusCode
};

export default compose(
  dispatched(fetchInitialOnServer, {
    componentDidMount: false,
    componentWillReceiveProps: false
  }),
  dispatched((props, dispatch) => dispatch(fetchNotificationData())),
  connect(mapStateToProps, mapDispatchToProps)
)(App);
<|endoftext|>


<commit_before>import plugin_data from 'plugin_data';

export default {
  launchIntent: plugin_data.appCapabilities.launch_intent,
};
<commit_msg>Make capability reading robust for tests.<commit_after>import plugin_data from 'plugin_data';

const appCapabilities = plugin_data.appCapabilities || {};

export default {
  launchIntent: appCapabilities.launch_intent,
};
<|endoftext|>


<commit_before>/*

Copyright 2014 - 2016 Roland Bouman (roland.bouman@gmail.com)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/
/**
*   Pivot table tab
*/
var XavierPivotTableTab;
(XavierPivotTableTab = function(conf){
  conf = conf || {};
  conf.showHorizontalHierarchyHeaders = Boolean(conf.showHorizontalHierarchyHeaders);
  conf.showVerticalHierarchyHeaders = Boolean(conf.showVerticalHierarchyHeaders);
  this.classes = ["pivot-table"];
  arguments.callee._super.apply(this, [conf]);
}).prototype = {
  text: gMsg("Pivot Table"),
  initToolbar: function(dom){
    var conf = this.conf;
    var toolbar = this.toolbar = new Toolbar({
      container: dom
    });
    toolbar.addButton([
      {"class": "show-column-hierarchy-headers",
        tooltip: gMsg("Show column hierarchy headers"),
        toggleGroup: "show-column-hierarchy-headers",
        depressed: conf.showHorizontalHierarchyHeaders
      },
      {"class": "show-row-hierarchy-headers",
        tooltip: gMsg("Show row hierarchy headers"),
        toggleGroup: "show-row-hierarchy-headers",
        depressed: conf.showVerticalHierarchyHeaders
      }
    ]);
    toolbar.listen({
      scope: this,
      buttonPressed: function(toolbar, event, button){
        var conf = button.conf;
        var className = conf["class"];
        switch (className) {
          default:
            throw "Not implemented";
        }
      },
      afterToggleGroupStateChanged: function(toolbar, event, data){
        var depressedButton = toolbar.getDepressedButtonInToggleGroup(data.group);
        switch (data.group) {
          case "show-column-hierarchy-headers":
            this.visualizer.showHorizontalHierarchyHeaders(depressedButton ? true : false);
            break;
          case "show-row-hierarchy-headers":
            this.visualizer.showVerticalHierarchyHeaders(depressedButton ? true : false);
            break;
        }
      }
    });
  },
  createQueryDesigner: function(dom){
    var intrinsicProperties = ["PARENT_UNIQUE_NAME"];
    var queryDesigner = this.queryDesigner = new QueryDesigner({
      container: cEl("DIV", {}, null, dom),
      dnd: this.getDnd(),
      xmla: this.getXmla(),
      xmlaTreeView: this.getXmlaTreeView(),
      axes: [
        {
          id: Xmla.Dataset.AXIS_COLUMNS,
          label: gMsg("Columns"),
          tooltip: gMsg("Items on this axis are used to generate columns for the pivot table"),
          hint: gMsg("Drag any levels, members or measures unto the columns axis to create columns in the pivot table."),
          "class": "columns",
          //isDistinct: true,
          isDistinct: false,
          mandatory: true,
          intrinsicProperties: intrinsicProperties,
          userSortBreaksHierarchy: false
        },
        {
          id: Xmla.Dataset.AXIS_ROWS,
          label: gMsg("Rows"),
          tooltip: gMsg("Items on this axis are used to generate rows for the pivot table"),
          hint: gMsg("Optionally, drag any levels, members or measures unto the row axis to create rows in the pivot table."),
          "class": "rows",
          //isDistinct: true,
          isDistinct: false,
          intrinsicProperties: intrinsicProperties,
          userSortBreaksHierarchy: false
        },
        {
          id: Xmla.Dataset.AXIS_SLICER
        }
      ]
    });
    return queryDesigner;
  },
  showHorizontalHierarchyHeaders: function(setting){
    var toolbar = this.toolbar;
    if (iDef(setting)) {
      toolbar.getButtonWithClass("show-column-hierarchy-headers").setDepressed(setting);
      this.visualizer.showHorizontalHierarchyHeaders(setting)
    }
    else {
      return toolbar.getDepressedButtonInToggleGroup("show-column-hierarchy-headers") ? true : false;
    }
  },
  showVerticalHierarchyHeaders: function(setting){
    var toolbar = this.toolbar;
    if (iDef(setting)) {
      toolbar.getButtonWithClass("show-row-hierarchy-headers").setDepressed(setting);
      this.visualizer.showVerticalHierarchyHeaders(setting);
    }
    else {
      return toolbar.getDepressedButtonInToggleGroup("show-row-hierarchy-headers") ? true : false;
    }
  },
  initPivotTable: function(dom){
    var pivotTable = this.visualizer = new PivotTable({
      showHorizontalHierarchyHeaders: this.showHorizontalHierarchyHeaders(),
      showVerticalHierarchyHeaders: this.showVerticalHierarchyHeaders()
    });
    dom.appendChild(pivotTable.getDom());
    pivotTable.listen({
      scope: this,
      collapse: function(pivotTable, event, data){
        this.collapseMember(data);
      },
      expand: function(pivotTable, event, data){
        this.expandMember(data);
      }
    });
    return pivotTable;
  },
  drillMember: function (drillEventData, drillDirection){
    var queryDesigner = this.getQueryDesigner();
    var xmla = this.getXmla();
    var axisId = queryDesigner.getAxisId(drillEventData.axis);
    var axis = queryDesigner.getAxis(axisId);
    if (!axis) {
      throw "Invalid axis " + drillEventData.axis;
    }
    //first, fetch the metadata for this member
    var datasource = this.getDatasource();
    var catalogName = this.getCatalog().CATALOG_NAME;
    var cubeName = this.getCube().CUBE_NAME;
    var properties = {
      DataSourceInfo: datasource.DataSourceInfo,
      Catalog: catalogName
    };
    var restrictions = {
      CATALOG_NAME: catalogName,
      CUBE_NAME: cubeName,
      MEMBER_UNIQUE_NAME: drillEventData.member
    };
    var drillAction = function(xmla, options, rowset){
      busy(false);
      var rows = rowset.fetchAllAsObject();
      if (rows.length !== 1) {
        throw "Expected exactly 1 result row, not " + rows.length;
      }
      var metadata = rows[0];
      var hierarchy = metadata.HIERARCHY_UNIQUE_NAME;
      var setDefs = axis.getSetDefs(hierarchy);
      if (!setDefs) {
        throw "Cant find set definitions for " + setDefs;
      }
      switch (drillDirection) {
        case "up":
          //TODO: find descendants with a proper metadata query.
          var descendants;
          try {
            descendants = axis.getMemberDescendants(metadata, "member");
          }
          catch (e) {
            if (e === "Member not found") {
              if (metadata.LEVEL_NUMBER === 0) {
                descendants = [];
              }
              else {
                descendants = axis.getMemberDescendants(metadata, "member-drilldown");
              }
              var member = axis.getMember(metadata, "member-drilldown");
              if (!member) {
                throw "Member not found";
              }
              descendants.push(member.setDef);
            }
          }
          var removed = axis.removeMember(descendants);
          if (!removed) {
            //apparently this member was not expanded from within the pivot table.
            //manually remove all child expressions of this member.
            debugger;
          }
          break;
        case "down":
          axis.addMember(setDefs.length, "member-drilldown", metadata);
          break;
        default:
          throw "Unknown drill direction " + drillDirection;
      }
    };

    xmla.discoverMDMembers({
      url: datasource.URL,
      properties: properties,
      restrictions: restrictions,
      success: drillAction,
      error: function(xmla, options, exception){
        busy(false);
        throw exception;
      }
    });
  },
  collapseMember: function(data){
    this.drillMember(data, "up");
  },
  expandMember: function(data) {
    this.drillMember(data, "down");
  },
  createDom: function(){
    var me = this;

    var dom = cEl("DIV", {
      id: this.getId()
    });
    this.initToolbar(dom);
    this.initQueryDesigner(dom);
    this.visualizer = this.initPivotTable(dom);
    return dom;
  }
};
XavierPivotTableTab.newInstance = function(conf){
  return new XavierPivotTableTab(conf);
}
adopt(XavierPivotTableTab, XavierTab);
<commit_msg>Set busy when discovering drill down member. Should solve: https://github.com/rpbouman/xavier/issues/25<commit_after>/*

Copyright 2014 - 2016 Roland Bouman (roland.bouman@gmail.com)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/
/**
*   Pivot table tab
*/
var XavierPivotTableTab;
(XavierPivotTableTab = function(conf){
  conf = conf || {};
  conf.showHorizontalHierarchyHeaders = Boolean(conf.showHorizontalHierarchyHeaders);
  conf.showVerticalHierarchyHeaders = Boolean(conf.showVerticalHierarchyHeaders);
  this.classes = ["pivot-table"];
  arguments.callee._super.apply(this, [conf]);
}).prototype = {
  text: gMsg("Pivot Table"),
  initToolbar: function(dom){
    var conf = this.conf;
    var toolbar = this.toolbar = new Toolbar({
      container: dom
    });
    toolbar.addButton([
      {"class": "show-column-hierarchy-headers",
        tooltip: gMsg("Show column hierarchy headers"),
        toggleGroup: "show-column-hierarchy-headers",
        depressed: conf.showHorizontalHierarchyHeaders
      },
      {"class": "show-row-hierarchy-headers",
        tooltip: gMsg("Show row hierarchy headers"),
        toggleGroup: "show-row-hierarchy-headers",
        depressed: conf.showVerticalHierarchyHeaders
      }
    ]);
    toolbar.listen({
      scope: this,
      buttonPressed: function(toolbar, event, button){
        var conf = button.conf;
        var className = conf["class"];
        switch (className) {
          default:
            throw "Not implemented";
        }
      },
      afterToggleGroupStateChanged: function(toolbar, event, data){
        var depressedButton = toolbar.getDepressedButtonInToggleGroup(data.group);
        switch (data.group) {
          case "show-column-hierarchy-headers":
            this.visualizer.showHorizontalHierarchyHeaders(depressedButton ? true : false);
            break;
          case "show-row-hierarchy-headers":
            this.visualizer.showVerticalHierarchyHeaders(depressedButton ? true : false);
            break;
        }
      }
    });
  },
  createQueryDesigner: function(dom){
    var intrinsicProperties = ["PARENT_UNIQUE_NAME"];
    var queryDesigner = this.queryDesigner = new QueryDesigner({
      container: cEl("DIV", {}, null, dom),
      dnd: this.getDnd(),
      xmla: this.getXmla(),
      xmlaTreeView: this.getXmlaTreeView(),
      axes: [
        {
          id: Xmla.Dataset.AXIS_COLUMNS,
          label: gMsg("Columns"),
          tooltip: gMsg("Items on this axis are used to generate columns for the pivot table"),
          hint: gMsg("Drag any levels, members or measures unto the columns axis to create columns in the pivot table."),
          "class": "columns",
          //isDistinct: true,
          isDistinct: false,
          mandatory: true,
          intrinsicProperties: intrinsicProperties,
          userSortBreaksHierarchy: false
        },
        {
          id: Xmla.Dataset.AXIS_ROWS,
          label: gMsg("Rows"),
          tooltip: gMsg("Items on this axis are used to generate rows for the pivot table"),
          hint: gMsg("Optionally, drag any levels, members or measures unto the row axis to create rows in the pivot table."),
          "class": "rows",
          //isDistinct: true,
          isDistinct: false,
          intrinsicProperties: intrinsicProperties,
          userSortBreaksHierarchy: false
        },
        {
          id: Xmla.Dataset.AXIS_SLICER
        }
      ]
    });
    return queryDesigner;
  },
  showHorizontalHierarchyHeaders: function(setting){
    var toolbar = this.toolbar;
    if (iDef(setting)) {
      toolbar.getButtonWithClass("show-column-hierarchy-headers").setDepressed(setting);
      this.visualizer.showHorizontalHierarchyHeaders(setting)
    }
    else {
      return toolbar.getDepressedButtonInToggleGroup("show-column-hierarchy-headers") ? true : false;
    }
  },
  showVerticalHierarchyHeaders: function(setting){
    var toolbar = this.toolbar;
    if (iDef(setting)) {
      toolbar.getButtonWithClass("show-row-hierarchy-headers").setDepressed(setting);
      this.visualizer.showVerticalHierarchyHeaders(setting);
    }
    else {
      return toolbar.getDepressedButtonInToggleGroup("show-row-hierarchy-headers") ? true : false;
    }
  },
  initPivotTable: function(dom){
    var pivotTable = this.visualizer = new PivotTable({
      showHorizontalHierarchyHeaders: this.showHorizontalHierarchyHeaders(),
      showVerticalHierarchyHeaders: this.showVerticalHierarchyHeaders()
    });
    dom.appendChild(pivotTable.getDom());
    pivotTable.listen({
      scope: this,
      collapse: function(pivotTable, event, data){
        this.collapseMember(data);
      },
      expand: function(pivotTable, event, data){
        this.expandMember(data);
      }
    });
    return pivotTable;
  },
  drillMember: function (drillEventData, drillDirection){
    var queryDesigner = this.getQueryDesigner();
    var xmla = this.getXmla();
    var axisId = queryDesigner.getAxisId(drillEventData.axis);
    var axis = queryDesigner.getAxis(axisId);
    if (!axis) {
      throw "Invalid axis " + drillEventData.axis;
    }
    //first, fetch the metadata for this member
    var datasource = this.getDatasource();
    var catalogName = this.getCatalog().CATALOG_NAME;
    var cubeName = this.getCube().CUBE_NAME;
    var properties = {
      DataSourceInfo: datasource.DataSourceInfo,
      Catalog: catalogName
    };
    var restrictions = {
      CATALOG_NAME: catalogName,
      CUBE_NAME: cubeName,
      MEMBER_UNIQUE_NAME: drillEventData.member
    };
    var drillAction = function(xmla, options, rowset){
      busy(false);
      var rows = rowset.fetchAllAsObject();
      if (rows.length !== 1) {
        throw "Expected exactly 1 result row, not " + rows.length;
      }
      var metadata = rows[0];
      var hierarchy = metadata.HIERARCHY_UNIQUE_NAME;
      var setDefs = axis.getSetDefs(hierarchy);
      if (!setDefs) {
        throw "Cant find set definitions for " + setDefs;
      }
      switch (drillDirection) {
        case "up":
          //TODO: find descendants with a proper metadata query.
          var descendants;
          try {
            descendants = axis.getMemberDescendants(metadata, "member");
          }
          catch (e) {
            if (e === "Member not found") {
              if (metadata.LEVEL_NUMBER === 0) {
                descendants = [];
              }
              else {
                descendants = axis.getMemberDescendants(metadata, "member-drilldown");
              }
              var member = axis.getMember(metadata, "member-drilldown");
              if (!member) {
                throw "Member not found";
              }
              descendants.push(member.setDef);
            }
          }
          var removed = axis.removeMember(descendants);
          if (!removed) {
            //apparently this member was not expanded from within the pivot table.
            //manually remove all child expressions of this member.
            debugger;
          }
          break;
        case "down":
          axis.addMember(setDefs.length, "member-drilldown", metadata);
          break;
        default:
          throw "Unknown drill direction " + drillDirection;
      }
    };
    busy(true);
    xmla.discoverMDMembers({
      url: datasource.URL,
      properties: properties,
      restrictions: restrictions,
      success: drillAction,
      error: function(xmla, options, exception){
        busy(false);
        throw exception;
      }
    });
  },
  collapseMember: function(data){
    this.drillMember(data, "up");
  },
  expandMember: function(data) {
    this.drillMember(data, "down");
  },
  createDom: function(){
    var me = this;

    var dom = cEl("DIV", {
      id: this.getId()
    });
    this.initToolbar(dom);
    this.initQueryDesigner(dom);
    this.visualizer = this.initPivotTable(dom);
    return dom;
  }
};
XavierPivotTableTab.newInstance = function(conf){
  return new XavierPivotTableTab(conf);
}
adopt(XavierPivotTableTab, XavierTab);
<|endoftext|>