<commit_before>angular.module('delayer')
.factory('delayer',[
  '$timeout',
  '$q',
  function($timeout, $q){

  var Delayer = function(fns, options){
    if(!fns || fns.length<1 || typeof fns[0]!== 'function')
      throw "needs an array of at least one function";

    if(!options)
      options = {};

    this.fns = fns;
    this.delay = typeof options.delay !== 'undefined' ? options.delay : 2000;
    this.block = typeof options.block !== 'undefined' ? options.block : this.fns.length > 1 ? false : true;
    this.current = 0;
    this.hits = 0;
  };

  Delayer.prototype.toggle = function(params){
    var self = this;

    // We modulo the current index to allow looping
    this.current = this.current%this.fns.length;

    // this is just to help the user know which function is beeing called
    this.currentFn = this.fns[this.current].name;

    this.result = $q.defer();

    // if mutliple functions (toggle with 2 or more positions)
    // we wait for the position to be considered "stable" before calling the
    // associated function
    if(!this.block){

      // if there is a timeout function running, we cancel it
      if(this.timeout && this.timeout.$$state.status === 0)
        $timeout.cancel(this.timeout);

      // but we don't call the function if the "stablized" function is the same
      // as the one we started at
      if((this.hits > 0) && (this.hits%this.fns.length === this.current) && (this.fns.length > 1)){
        this.hits = 0;
      }
      else{
        (function(current){
          self.timeout = $timeout(function(){
            self.hits = 0;
            // we resolve the result once the delay is passed
            self.result.resolve(self.fns[current](params));
          },self.delay);
        })(this.current);
        this.hits++;
      }
      this.current++;
    }

    // if there is only one function (ie: refresh button)
    // we execute immediatly then block further calls until the delay is over
    else{
      // if there is a timeout function running, we don't do anything
      if(!(this.timeout && this.timeout.$$state.status === 0)){
        this.result.resolve(this.fns[this.current](params));
        this.timeout = $timeout(this.delay);
      }
    }

    return this.result.promise;
  };

  return Delayer;

}]);
<commit_msg>fix module dependency +  hits counter update even on block<commit_after>angular.module('delayer',[])
.factory('delayer',[
  '$timeout',
  '$q',
  function($timeout, $q){

  var Delayer = function(fns, options){
    if(!fns || fns.length<1 || typeof fns[0]!== 'function')
      throw "needs an array of at least one function";

    if(!options)
      options = {};

    this.fns = fns;
    this.delay = typeof options.delay !== 'undefined' ? options.delay : 2000;
    this.block = typeof options.block !== 'undefined' ? options.block : this.fns.length > 1 ? false : true;
    this.current = 0;
    this.hits = 0;
  };

  Delayer.prototype.toggle = function(params){
    var self = this;

    // We modulo the current index to allow looping
    this.current = this.current%this.fns.length;

    // this is just to help the user know which function is beeing called
    this.currentFn = this.fns[this.current].name;

    this.result = $q.defer();

    // if mutliple functions (toggle with 2 or more positions)
    // we wait for the position to be considered "stable" before calling the
    // associated function
    if(!this.block){

      // if there is a timeout function running, we cancel it
      if(this.timeout && this.timeout.$$state.status === 0)
        $timeout.cancel(this.timeout);

      // but we don't call the function if the "stablized" function is the same
      // as the one we started at
      if((this.hits > 0) && (this.hits%this.fns.length === this.current) && (this.fns.length > 1)){
        this.hits = 0;
      }
      else{
        (function(current){
          self.timeout = $timeout(function(){
            self.hits = 0;
            // we resolve the result once the delay is passed
            self.result.resolve(self.fns[current](params));
          },self.delay);
        })(this.current);
        this.hits++;
      }
      this.current++;
    }

    // if there is only one function (ie: refresh button)
    // we execute immediatly then block further calls until the delay is over
    else{
      // if there is a timeout function running, we don't do anything
      if(!(this.timeout && this.timeout.$$state.status === 0)){
        this.hits = 0;
        this.result.resolve(this.fns[this.current](params));
        this.timeout = $timeout(this.delay);
      }
      else
        this.hits++;
    }

    return this.result.promise;
  };

  return Delayer;

}]);
<|endoftext|>


<commit_before>/**********************************************************************
 *
 *   Customize the values given below to suit your needs.
 *   You can make additional copies of this file with
 *   different customizated settings if you need to load
 *   jsMath with different parameters.
 *
 *   Load this page via:
 *
 *   <SCRIPT SRC="path-to-jsMath/easy/load.js"></SCRIPT>
 *
 *   (If you are including this file into your page via Server-Side
 *   Includes, you should remove line above.)
 *
 *   You can make copies of this file with different settings
 *   if you need to have several different configurations.
 *
 **********************************************************************/

if (!window.jsMath) {window.jsMath = {}}

jsMath.Easy = {
  //
  //  The URL of the root jsMath directory on your server
  //  (it must be in the same domain as the HTML page).
  //  It should include "http://yoursite.com/", or should
  //  be relative to the root of your server.  It is possible
  //  to be a relative URL, but it will be relative to the
  //  HTML page loading this file.
  //
  //  If you leave this blank, jsMath will try to look it up from
  //  the URL where it loaded this file, but that may not work.
  //
  root: "",

  //
  //  The default scaling factor for mathematics compared to the
  //  surrounding text.
  //
  scale: 120,

  //
  //  1 means use the autoload plug-in to decide if jsMath should be loaded
  //  0 means always load jsMath
  //
  autoload: 0,

  //
  //  Setting any of these will cause the tex2math plugin to be used
  //  to add the <DIV> and <SPAN> tags that jsMath needs.  See the
  //  documentation for the tex2math plugin for more information.
  //
  processSlashParens: 1,       // process \(...\) in text?
  processSlashBrackets: 1,     // process \[...\] in text?
  processDoubleDollars: 1,     // process $$...$$ in text?
  processSingleDollars: 1,     // process $...$ in text?
  processLaTeXenvironments: 1, // process \begin{xxx}...\end{xxx} outside math mode?
  fixEscapedDollars: 1,        // convert \$ to $ outside of math mode?
  doubleDollarsAreInLine: 0,   // make $$...$$ be in-line math?
  allowDisableTag: 1,          // allow ID="tex2math_off" to disable tex2math?
  //
  //  If you want to use your own custom delimiters for math instead
  //  of the usual ones, then uncomment the following four lines and
  //  insert your own delimiters within the quotes.  You may want to
  //  turn off processing of the dollars and other delimiters above
  //  as well, though you can use them in combination with the
  //  custom delimiters if you wish.  See the tex2math documentation
  //  for more details.
  //
  //customDelimiters: [
  //  '[math]','[/math]',        // to begin and end in-line math
  //  '[display]','[/display]'   // to begin and end display math
  //],

  //
  //  Show TeX source when mathematics is double-clicked?
  //
  allowDoubleClicks: 1,

  //
  //  Show jsMath font warning messages?  (Disabling this prevents yours
  //  users from finding out that they can have a better experience on your
  //  site by installing some fonts, so don't disable this).
  //
  showFontWarnings: 0,

  //
  //  Use "Process" or "ProcessBeforeShowing".  See the jsMath
  //  author's documentation for the difference between these
  //  two routines.
  //
  method: "Process",

  //
  //  List of plug-ins and extensions that you want to be
  //  loaded automatically.  E.g.
  //      ["plugins/mimeTeX.js","extensions/AMSsymbols.js"]
  //
  loadFiles: ["extensions/AMSsymbols.js","extensions/AMSmath.js"],

  //
  //  List of fonts to load automatically.  E.g.
  //      ["cmmib10"]
  //
  loadFonts: [],

  //
  //  Allow jsMath to enter global mode?
  //  (Uses frames, so may not always work with complex web sites)
  //
  allowGlobal: 1,

  //
  //  Disable image fonts?  (In case you don't load them on your server.)
  //
  noImageFonts: 0

};

/****************************************************************/
/****************************************************************/
//
//            DO NOT MAKE CHANGES BELOW THIS
//
/****************************************************************/
/****************************************************************/

if (jsMath.Easy.root == "") {
  jsMath.Easy.root = document.getElementsByTagName("script");
  jsMath.Easy.root = jsMath.Easy.root[jsMath.Easy.root.length-1].src
  if (jsMath.Easy.root.match(/\/easy\/[^\/]*$/)) {
    jsMath.Easy.root = jsMath.Easy.root.replace(/\/easy\/[^\/]*$/,"");
  } else {
    jsMath.Easy.root = jsMath.Easy.root.replace(/\/(jsMath\/(easy\/)?)?[^\/]*$/,"/jsMath");
  }
}
jsMath.Easy.root = jsMath.Easy.root.replace(/\/$/,""); // trim trailing "/" if any

document.write('<SCRIPT SRC="'+jsMath.Easy.root+'/jsMath-easy-load.js"><'+'/SCRIPT>');

<commit_msg>Specified Root path.<commit_after>/**********************************************************************
 *
 *   Customize the values given below to suit your needs.
 *   You can make additional copies of this file with
 *   different customizated settings if you need to load
 *   jsMath with different parameters.
 *
 *   Load this page via:
 *
 *   <SCRIPT SRC="path-to-jsMath/easy/load.js"></SCRIPT>
 *
 *   (If you are including this file into your page via Server-Side
 *   Includes, you should remove line above.)
 *
 *   You can make copies of this file with different settings
 *   if you need to have several different configurations.
 *
 **********************************************************************/

if (!window.jsMath) {window.jsMath = {}}

jsMath.Easy = {
  //
  //  The URL of the root jsMath directory on your server
  //  (it must be in the same domain as the HTML page).
  //  It should include "http://yoursite.com/", or should
  //  be relative to the root of your server.  It is possible
  //  to be a relative URL, but it will be relative to the
  //  HTML page loading this file.
  //
  //  If you leave this blank, jsMath will try to look it up from
  //  the URL where it loaded this file, but that may not work.
  //
  root: "/jsMath",

  //
  //  The default scaling factor for mathematics compared to the
  //  surrounding text.
  //
  scale: 120,

  //
  //  1 means use the autoload plug-in to decide if jsMath should be loaded
  //  0 means always load jsMath
  //
  autoload: 0,

  //
  //  Setting any of these will cause the tex2math plugin to be used
  //  to add the <DIV> and <SPAN> tags that jsMath needs.  See the
  //  documentation for the tex2math plugin for more information.
  //
  processSlashParens: 1,       // process \(...\) in text?
  processSlashBrackets: 1,     // process \[...\] in text?
  processDoubleDollars: 1,     // process $$...$$ in text?
  processSingleDollars: 1,     // process $...$ in text?
  processLaTeXenvironments: 1, // process \begin{xxx}...\end{xxx} outside math mode?
  fixEscapedDollars: 1,        // convert \$ to $ outside of math mode?
  doubleDollarsAreInLine: 0,   // make $$...$$ be in-line math?
  allowDisableTag: 1,          // allow ID="tex2math_off" to disable tex2math?
  //
  //  If you want to use your own custom delimiters for math instead
  //  of the usual ones, then uncomment the following four lines and
  //  insert your own delimiters within the quotes.  You may want to
  //  turn off processing of the dollars and other delimiters above
  //  as well, though you can use them in combination with the
  //  custom delimiters if you wish.  See the tex2math documentation
  //  for more details.
  //
  //customDelimiters: [
  //  '[math]','[/math]',        // to begin and end in-line math
  //  '[display]','[/display]'   // to begin and end display math
  //],

  //
  //  Show TeX source when mathematics is double-clicked?
  //
  allowDoubleClicks: 1,

  //
  //  Show jsMath font warning messages?  (Disabling this prevents yours
  //  users from finding out that they can have a better experience on your
  //  site by installing some fonts, so don't disable this).
  //
  showFontWarnings: 0,

  //
  //  Use "Process" or "ProcessBeforeShowing".  See the jsMath
  //  author's documentation for the difference between these
  //  two routines.
  //
  method: "Process",

  //
  //  List of plug-ins and extensions that you want to be
  //  loaded automatically.  E.g.
  //      ["plugins/mimeTeX.js","extensions/AMSsymbols.js"]
  //
  loadFiles: ["extensions/AMSsymbols.js","extensions/AMSmath.js"],

  //
  //  List of fonts to load automatically.  E.g.
  //      ["cmmib10"]
  //
  loadFonts: [],

  //
  //  Allow jsMath to enter global mode?
  //  (Uses frames, so may not always work with complex web sites)
  //
  allowGlobal: 1,

  //
  //  Disable image fonts?  (In case you don't load them on your server.)
  //
  noImageFonts: 0

};

/****************************************************************/
/****************************************************************/
//
//            DO NOT MAKE CHANGES BELOW THIS
//
/****************************************************************/
/****************************************************************/

if (jsMath.Easy.root == "") {
  jsMath.Easy.root = document.getElementsByTagName("script");
  jsMath.Easy.root = jsMath.Easy.root[jsMath.Easy.root.length-1].src
  if (jsMath.Easy.root.match(/\/easy\/[^\/]*$/)) {
    jsMath.Easy.root = jsMath.Easy.root.replace(/\/easy\/[^\/]*$/,"");
  } else {
    jsMath.Easy.root = jsMath.Easy.root.replace(/\/(jsMath\/(easy\/)?)?[^\/]*$/,"/jsMath");
  }
}
jsMath.Easy.root = jsMath.Easy.root.replace(/\/$/,""); // trim trailing "/" if any

document.write('<SCRIPT SRC="'+jsMath.Easy.root+'/jsMath-easy-load.js"><'+'/SCRIPT>');

<|endoftext|>


<commit_before>/**
 * Copyright (C) 2016 Joshua Auerbach
 *
 * 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.
 */

function preProcessSQL(sql) {
		var url = "http://localhost:9879"; /* TODO: how to parameterize this */
		var request = new XMLHttpRequest();
		request.open("POST", url, false);
		request.setRequestHeader("Content-Type", "text/plain");
		request.send(sql);
//		console.log("Returning encoded form:");
//		console.log(request.responseText);
		return request.responseText;
}

function preMain(input) {
		if (input.source == "sql") {
			input.query = preProcessSQL(input.query);
			input.sourcesexp = true;
		}
//		console.log("Input to main:");
//		console.log(input);
		return main(input);
}
<commit_msg>Allow flip between local remote server.  Improved error report.<commit_after>/**
 * Copyright (C) 2016 Joshua Auerbach
 *
 * 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.
 */

function preProcessSQL(sql, useLocal) {
		var url = useLocal ? "http://localhost:9879" : "http://35.164.159.76:9879";
//	console.log("URL: " + url);
//	console.log("local flag: " + useLocal);
		var request = new XMLHttpRequest();
		request.open("POST", url, false);
		request.setRequestHeader("Content-Type", "text/plain");
		request.send(sql);
//	console.log("Returning encoded form:");
//	console.log(request.responseText);
		return request.responseText;
}

function preMain(input, useLocal) {
		if (input.source == "sql") {
			try {
				input.query = preProcessSQL(input.query, useLocal);
			} catch (e) {
				return { "result": e.message};
			}
			input.sourcesexp = true;
		}
//		console.log("Input to main:");
//		console.log(input);
		return main(input);
}
<|endoftext|>


<commit_before>DEBUG = true;

FOAModel({
  name: 'Account',

  properties: [
    { name: 'id'      },
    { name: 'status'  },
    { name: 'balance', defaultValue: 0 }
  ],

  methods: [
    {
      model_: "Method",
      name: "setStatus",
      code: function (status) {
        this.status = status;
      },
      args: [
        { model_: 'Arg', type: 'boolean' }
      ]
    },
    {
      model_: "Method",
      name: "deposit",
      code: function (amount) {
        this.balance += amount;

        return this.balance;
      },
      args: [
        { type: 'number' }
      ],
      returnType: 'number',
    },
    {
      model_: "Method",
      name: "withdraw",
      code: function (amount) {
        this.balance -= amount;

        return this.bal;
      },
      args: [
        { type: 'number' }
      ],
      returnType: 'number'
    }
  ]

});

var a = Account.create();

// Both Pass
a.setStatus(true);
a.deposit(100);

// Both Fail
a.deposit('gold coins');
a.withdraw(50);

<commit_msg>Removed Method model declarations from TypeCheck.js<commit_after>DEBUG = true;

FOAModel({
  name: 'Account',

  properties: [
    { name: 'id'      },
    { name: 'status'  },
    { name: 'balance', defaultValue: 0 }
  ],

  methods: [
    {
      name: "setStatus",
      code: function (status) {
        this.status = status;
      },
      args: [
        { model_: 'Arg', type: 'boolean' }
      ]
    },
    {
      name: "deposit",
      code: function (amount) {
        this.balance += amount;

        return this.balance;
      },
      args: [
        { type: 'number' }
      ],
      returnType: 'number',
    },
    {
      name: "withdraw",
      code: function (amount) {
        this.balance -= amount;

        return this.bal;
      },
      args: [
        { type: 'number' }
      ],
      returnType: 'number'
    }
  ]

});

var a = Account.create();

// Both Pass
a.setStatus(true);
a.deposit(100);

// Both Fail
a.deposit('gold coins');
a.withdraw(50);
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'
import { reduxForm } from 'redux-form';
import MetadataEvaluator from './metadata/evaluator/MetadataEvaluator';
import ModelParser from './metadata/model/ModelParser';
// import UIManager from './UIManager';

class AutoFormInternal extends Component {
    static propTypes = {
        uiType: PropTypes.string,
        fields: PropTypes.object.isRequired,
        handleSubmit: PropTypes.func.isRequired,
        resetForm: PropTypes.func.isRequired,
        submitting: PropTypes.bool.isRequired,
        pristine: PropTypes.bool.isRequired,
        componentFactory: PropTypes.object,
        entity: PropTypes.object.isRequired,
        layout: PropTypes.object,
        buttonBar: PropTypes.func.isRequired,
        fieldLayout: PropTypes.string
    };

    //TODO JS: make this work
    getFactory() {
        const { uiType, componentFactory } = this.props;

        // if (!uiType) {
        //     return componentFactory;
        // }
        //
        // return UIManager.getFactoryPerType(uiType);
        return componentFactory;
    }

    buildGroupComponent = () => {
        //Fields: this is not the fields passed from AutoForm. This is generated by ReduxForm.
        //This object has a property for each field. Each property contains all redux props for the given field
        let { fields, fieldMetadata, layout, values } = this.props;

        let modelProcessed = ModelParser.process(values, fieldMetadata);
        let fieldMetadataEvaluated = MetadataEvaluator.evaluate(fieldMetadata, modelProcessed, '', fields);
        let componentFactory = this.getFactory();

        return componentFactory.buildGroupComponent({
            component: layout.component,
            layout: layout,
            fields: fieldMetadataEvaluated,
            componentFactory: componentFactory
        });
    };

	getSubErrors = (fields) => {
		let arr = fields.map(field => {
			let result = null;

			for (let key in field) {
				if (field.hasOwnProperty(key)) {
					if (field[key].error) {
						result = {...result, ...{[field[key].name]: field[key].error}};
					}
				}
			}

			return result;
		});

		return arr.filter(field => {
			return (field !== null)? true : false;
		});
	};

	getErrors = (fields) => {
		let arr = [];

		for (let key in fields) {
			if (fields.hasOwnProperty(key)) {
				if (Array.isArray(fields[key])) {
					let subArr = this.getSubErrors(fields[key]);

					//Merge both arrays into one to get the values up to date
					arr = [...arr, ...subArr];
				}
				else if (fields[key].error) {
					arr.push({[fields[key].name]: fields[key].error});
				}
			}
		}

		return arr;
	};

	getButtonBar = () => {
		//Because redux-form always force a re-render with different kinds of events,
		//we got the errors up to date in fields object
		let { buttonBar, submitting, pristine, fields } = this.props;
		let errors = this.getErrors(fields);

		console.info("This is the array => " + JSON.stringify(errors, null, 2));

		let buttonBarProps = {
			submitting: submitting,
			pristine: pristine,
			errors: errors
		};

		return React.createElement(buttonBar, buttonBarProps);
	};

    render() {
        let groupComponent = this.buildGroupComponent();
        let componentFactory = this.getFactory();
	    let buttonBar = this.getButtonBar();
        let Root = componentFactory.getRoot();

        return (
            <Root {...this.props}>
                { groupComponent }
                { buttonBar }
            </Root>
        )
    }
}

export default reduxForm()(AutoFormInternal);<commit_msg>#83 delete logs<commit_after>import React, { Component, PropTypes } from 'react'
import { reduxForm } from 'redux-form';
import MetadataEvaluator from './metadata/evaluator/MetadataEvaluator';
import ModelParser from './metadata/model/ModelParser';
// import UIManager from './UIManager';

class AutoFormInternal extends Component {
    static propTypes = {
        uiType: PropTypes.string,
        fields: PropTypes.object.isRequired,
        handleSubmit: PropTypes.func.isRequired,
        resetForm: PropTypes.func.isRequired,
        submitting: PropTypes.bool.isRequired,
        pristine: PropTypes.bool.isRequired,
        componentFactory: PropTypes.object,
        entity: PropTypes.object.isRequired,
        layout: PropTypes.object,
        buttonBar: PropTypes.func.isRequired,
        fieldLayout: PropTypes.string
    };

    //TODO JS: make this work
    getFactory() {
        const { uiType, componentFactory } = this.props;

        // if (!uiType) {
        //     return componentFactory;
        // }
        //
        // return UIManager.getFactoryPerType(uiType);
        return componentFactory;
    }

    buildGroupComponent = () => {
        //Fields: this is not the fields passed from AutoForm. This is generated by ReduxForm.
        //This object has a property for each field. Each property contains all redux props for the given field
        let { fields, fieldMetadata, layout, values } = this.props;

        let modelProcessed = ModelParser.process(values, fieldMetadata);
        let fieldMetadataEvaluated = MetadataEvaluator.evaluate(fieldMetadata, modelProcessed, '', fields);
        let componentFactory = this.getFactory();

        return componentFactory.buildGroupComponent({
            component: layout.component,
            layout: layout,
            fields: fieldMetadataEvaluated,
            componentFactory: componentFactory
        });
    };

	getSubErrors = (fields) => {
		let arr = fields.map(field => {
			let result = null;

			for (let key in field) {
				if (field.hasOwnProperty(key)) {
					if (field[key].error) {
						result = {...result, ...{[field[key].name]: field[key].error}};
					}
				}
			}

			return result;
		});

		return arr.filter(field => {
			return (field !== null)? true : false;
		});
	};

	getErrors = (fields) => {
		let arr = [];

		for (let key in fields) {
			if (fields.hasOwnProperty(key)) {
				if (Array.isArray(fields[key])) {
					let subArr = this.getSubErrors(fields[key]);

					//Merge both arrays into one to get the values up to date
					arr = [...arr, ...subArr];
				}
				else if (fields[key].error) {
					arr.push({[fields[key].name]: fields[key].error});
				}
			}
		}

		return arr;
	};

	getButtonBar = () => {
		//Because redux-form always force a re-render with different kinds of events,
		//we got the errors up to date in fields object
		let { buttonBar, submitting, pristine, fields } = this.props;
		let errors = this.getErrors(fields);

		let buttonBarProps = {
			submitting: submitting,
			pristine: pristine,
			errors: errors
		};

		return React.createElement(buttonBar, buttonBarProps);
	};

    render() {
        let groupComponent = this.buildGroupComponent();
        let componentFactory = this.getFactory();
	    let buttonBar = this.getButtonBar();
        let Root = componentFactory.getRoot();

        return (
            <Root {...this.props}>
                { groupComponent }
                { buttonBar }
            </Root>
        )
    }
}

export default reduxForm()(AutoFormInternal);<|endoftext|>


<commit_before>this.cutie = this.cutie || {};
this.cutie.Behavior = this.cutie.Behavior || {};

(function(module){
    /**
     * Gives an object the ability to follow another object or the mouse.
     *  Testing
     *
     * @memberof cutie.Behavior
     * @constructor
     * @param {Object} [props] The properties being passed in.
     * @param {Boolean} [props.targetObj=false] This is the object that is going to be followed.
     *      If no object is passed in, it will follow the mouse.
     * @param {Number} [props.speed=100] This is an integer value giving the speed in px/s
     * @param {Number} [props.distance=0] This is the follow distance in px.
     * @param {Boolean} [props.setCenter=true] This is signifies if the object doing the following should rotate around its center
     * @param {Number} [props.angleOffset=90] This is the following orientation where 90 is straight up,
     *     the zero point is the cartesian positive x axis and degrees rotate counter-clockwise up from this x axis.
     * @param {Number} [props.followCord] The position of the center of the joystick.
     * @param {Number} [props.followCord.x] The x-coordinate on the image to be pursued (using local image coordinates).
     * @param {Number} [props.followCord.y] The y-coordinate on the image to be pursued (using local image coordinates).
     */

     //NEED TO ALLOW USERS TO ADD X Y COORDINATES TO GO TO A SPOT ON THE TARGET OBJECT

    var Follow = function(props) {
    	// ================================================
        // VARIABLE DECLARATIONS
        // ================================================

        var props = props || {};
        if (!props.followCord) props.followCord = {};

        var _targetCoord = {};

        var _setCenter = ('setCenter' in props)?props.setCenter:true;
        var _targetObj = ('targetObj' in props)?props.targetObj:false;
        var _speed = ('speed' in props)?props.speed:100;
        var _followDistance = ('distance' in props)?props.distance:0;
        var _angOffset = ('angleOffset' in props)?props.angleOffset:90;

        // ================================================
        // PUBLIC METHODS
        // ================================================
        this.init = function(obj) {
        	//If the mouse is the object
            setCoords();
            if(_setCenter) {
                obj.regX = obj.image.width/2;
                obj.regY = obj.image.height/2;
            }
        };

        this.tick = function(obj, e) {
            var dist = _speed*e.delta/1000;
            setCoords();
            var xDist = _targetCoord.x - obj.x;
            var yDist = _targetCoord.y - obj.y;

            var distanceFrom = Math.sqrt(xDist*xDist + yDist*yDist);
            //Will keep correct orientation even if within the distance
            var theta = Math.atan2(yDist,xDist);
            obj.rotation = (theta * 180 / Math.PI) + _angOffset;
            if(distanceFrom > _followDistance && dist < distanceFrom) {
            	obj.x += dist*Math.cos(theta);
            	obj.y += dist*Math.sin(theta);
            }

        };

        // ================================================
        // PRIVATE METHODS
        // ================================================

        function setCoords(){
            if(!_targetObj) {
                var stage = cutie.getStage();
                _targetCoord.x = stage.mouseX;
                _targetCoord.y = stage.mouseY;
            }
            else{
                //Need to decide how this is handled, becuase in DPad it centers
                _targetCoord.x = _targetObj.x;
                _targetCoord.y = _targetObj.y;
            }
        }

    }

    module.Follow = Follow;
})(this.cutie.Behavior);
<commit_msg>undid jsdoc test<commit_after>this.cutie = this.cutie || {};
this.cutie.Behavior = this.cutie.Behavior || {};

(function(module){
    /**
     * Gives an object the ability to follow another object or the mouse.
     *
     * @memberof cutie.Behavior
     * @constructor
     * @param {Object} [props] The properties being passed in.
     * @param {Boolean} [props.targetObj=false] This is the object that is going to be followed.
     *      If no object is passed in, it will follow the mouse.
     * @param {Number} [props.speed=100] This is an integer value giving the speed in px/s
     * @param {Number} [props.distance=0] This is the follow distance in px.
     * @param {Boolean} [props.setCenter=true] This is signifies if the object doing the following should rotate around its center
     * @param {Number} [props.angleOffset=90] This is the following orientation where 90 is straight up,
     *     the zero point is the cartesian positive x axis and degrees rotate counter-clockwise up from this x axis.
     * @param {Number} [props.followCord] The position of the center of the joystick.
     * @param {Number} [props.followCord.x] The x-coordinate on the image to be pursued (using local image coordinates).
     * @param {Number} [props.followCord.y] The y-coordinate on the image to be pursued (using local image coordinates).
     */

     //NEED TO ALLOW USERS TO ADD X Y COORDINATES TO GO TO A SPOT ON THE TARGET OBJECT

    var Follow = function(props) {
    	// ================================================
        // VARIABLE DECLARATIONS
        // ================================================

        var props = props || {};
        if (!props.followCord) props.followCord = {};

        var _targetCoord = {};

        var _setCenter = ('setCenter' in props)?props.setCenter:true;
        var _targetObj = ('targetObj' in props)?props.targetObj:false;
        var _speed = ('speed' in props)?props.speed:100;
        var _followDistance = ('distance' in props)?props.distance:0;
        var _angOffset = ('angleOffset' in props)?props.angleOffset:90;

        // ================================================
        // PUBLIC METHODS
        // ================================================
        this.init = function(obj) {
        	//If the mouse is the object
            setCoords();
            if(_setCenter) {
                obj.regX = obj.image.width/2;
                obj.regY = obj.image.height/2;
            }
        };

        this.tick = function(obj, e) {
            var dist = _speed*e.delta/1000;
            setCoords();
            var xDist = _targetCoord.x - obj.x;
            var yDist = _targetCoord.y - obj.y;

            var distanceFrom = Math.sqrt(xDist*xDist + yDist*yDist);
            //Will keep correct orientation even if within the distance
            var theta = Math.atan2(yDist,xDist);
            obj.rotation = (theta * 180 / Math.PI) + _angOffset;
            if(distanceFrom > _followDistance && dist < distanceFrom) {
            	obj.x += dist*Math.cos(theta);
            	obj.y += dist*Math.sin(theta);
            }

        };

        // ================================================
        // PRIVATE METHODS
        // ================================================

        function setCoords(){
            if(!_targetObj) {
                var stage = cutie.getStage();
                _targetCoord.x = stage.mouseX;
                _targetCoord.y = stage.mouseY;
            }
            else{
                //Need to decide how this is handled, becuase in DPad it centers
                _targetCoord.x = _targetObj.x;
                _targetCoord.y = _targetObj.y;
            }
        }

    }

    module.Follow = Follow;
})(this.cutie.Behavior);
<|endoftext|>


<commit_before>{
    "init":function() {
        this.ciphertext = String.fromCharCode(0x1d,0x49,0x50,0x87,0xa7,0x68,0xf5,0xac
        ,0xa6,0x63,0x4b,0x90,0xb0,0xfa,0x02,0xe9
        ,0x2f,0x12,0xc4,0x0f,0x5f,0x3f,0x07,0xc7
        ,0x04,0x72,0x76,0x64,0x0d,0x37,0xfa,0x20
        ,0x3e,0xae,0x18,0x39,0xc7,0x83,0x1d,0x11
        ,0xd4,0x87,0xa9,0x18,0x5e,0x72,0x3f,0x98
        ,0xa7,0x59,0x26,0xd6,0x21,0x45,0x10,0x7d
        ,0xeb,0xb3,0x46,0x2f,0x54,0x43,0x09,0xbf
        ,0x03,0x68,0x63,0xe3,0xd7,0x2c,0xf6,0x9d
        ,0x40,0xe2,0x65,0x76,0x3b,0xd6,0x6c,0x38);
        this.iv = String.fromCharCode(0x09,0xf0,0x04,0x15,0xc7,0xc3,0x6d,0x8e);
        this.count = 0;
        this.results = [];
    },

    "step":function() {
        var current_key = this.generateRandKey();
        var this_result=des(current_key,this.ciphertext,0,1,this.iv,1);
        this_result = this_result.substring(0, this_result.length - 16);
        this.results.push(this.convertToHex(current_key) + ',' + this.convertToHex(this_result));
        this.count++;
    },

    "convertToHex":function(text) {
        var hext = "";
        for(var i = 0; i < text.length; i++) {
            charHex = text.charCodeAt(i).toString(16);
            while(charHex.length < 2) {
                charHex = '0' + charHex;
            }
            hext += charHex;
        }
        return hext;
    },

    "generateRandKey":function() {
        var key = "";
        for(var i = 0; i < 8; i++) {
            key += String.fromCharCode(Math.floor(Math.random() * 256));
        }
        return key;
    },

    "is_done":function() {
        if (this.count >= 32768) {
            return true;
        }
        return false;
    },

    "finish":function() {
        return this.results.join('\n');
    },

    "save":function() {
        return {count:this.count, results:this.results};
    },

    "resume":function(dict) {
        this.count = dict.count;
        this.results = dict.results;
    }
}
<commit_msg>made work faster<commit_after>{
    "init":function() {
        this.ciphertext = String.fromCharCode(0x1d,0x49,0x50,0x87,0xa7,0x68,0xf5,0xac
        ,0xa6,0x63,0x4b,0x90,0xb0,0xfa,0x02,0xe9
        ,0x2f,0x12,0xc4,0x0f,0x5f,0x3f,0x07,0xc7
        ,0x04,0x72,0x76,0x64,0x0d,0x37,0xfa,0x20
        ,0x3e,0xae,0x18,0x39,0xc7,0x83,0x1d,0x11
        ,0xd4,0x87,0xa9,0x18,0x5e,0x72,0x3f,0x98
        ,0xa7,0x59,0x26,0xd6,0x21,0x45,0x10,0x7d
        ,0xeb,0xb3,0x46,0x2f,0x54,0x43,0x09,0xbf
        ,0x03,0x68,0x63,0xe3,0xd7,0x2c,0xf6,0x9d
        ,0x40,0xe2,0x65,0x76,0x3b,0xd6,0x6c,0x38);
        this.iv = String.fromCharCode(0x09,0xf0,0x04,0x15,0xc7,0xc3,0x6d,0x8e);
        this.count = 0;
        this.result = "0";
    },

    "step":function() {
        var current_key = this.generateRandKey();
        var result=des(current_key,this.ciphertext,0,1,this.iv,1);
        //remove 8 bytes of "chaff"
        result = result.substring(0, result.length - 16);
        //fast fail on non-printable characters
        if(this.is_printable(result)) {
            this.result = "1," + this.convertToHex(current_key) + "," + result;
        }
        this.count++;
    },

    "is_printable":function(result) {
        for (var i = 0; i < result.length; i++) {
            var char_code = result.charCodeAt(i);
            if(char_code < 32 || char_code >= 127) {
                return false;
            }
        }
        return true;
    },

    "convertToHex":function(text) {
        var hext = "";
        for(var i = 0; i < text.length; i++) {
            charHex = text.charCodeAt(i).toString(16);
            while(charHex.length < 2) {
                charHex = '0' + charHex;
            }
            hext += charHex;
        }
        return hext;
    },

    "generateRandKey":function() {
        var key = "";
        for(var i = 0; i < 8; i++) {
            key += String.fromCharCode(Math.floor(Math.random() * 256));
        }
        return key;
    },

    "is_done":function() {
        if (this.count >= 5000 || this.result != "0") {
            return true;
        }
        return false;
    },

    "finish":function() {
        return this.result;
    },

    "save":function() {
        return {count:this.count, result:this.result};
    },

    "resume":function(dict) {
        this.count = dict.count;
        this.result = dict.result;
    }
}
<|endoftext|>


<commit_before>import React, {Component} from 'react';
import classnames from 'classnames';
import {MDCDrawer} from '@material/drawer';
import {MDCRipple} from '@material/ripple';
import {imagePath} from './constants';

const SCREEN_WIDTH_BREAKPOINT = 1160;
const DISMISSIBLE_DRAWER_CLASS = 'mdc-drawer--dismissible';
const MODAL_DRAWER_CLASS = 'mdc-drawer--modal';

class ComponentSidebar extends Component {
  state = {
    variant: DISMISSIBLE_DRAWER_CLASS,
  };

  drawer = null;
  ripples = [];
  debounceTimeout = 0;

  initRipple = ele => ele && this.ripples.push(new MDCRipple(ele));
  handleDrawerOpen_ = () => this.handleDrawerOpen();
  handleDrawerClose_ = () => this.handleDrawerClose();

  initDrawer = ele => {
    if(!ele) return;
    this.drawerEl = ele;

    if(document.body.offsetWidth > SCREEN_WIDTH_BREAKPOINT) {

      this.setState({variant: DISMISSIBLE_DRAWER_CLASS});
    } else {
      this.setState({variant: MODAL_DRAWER_CLASS});
    }
    this.drawer = new MDCDrawer(this.drawerEl);
  };

  componentDidMount() {
    this.drawerEl.addEventListener('MDCDrawer:opened', this.handleDrawerOpen_);
    this.drawerEl.addEventListener('MDCDrawer:closed', this.handleDrawerClose_);
    window.addEventListener('resize', this.debounceResizeMethod_);
  }

  componentWillUnmount() {
    if (this.drawerEl) {
      this.drawerEl.removeEventListener('MDCDrawer:opened',
          this.handleDrawerOpen_);
      this.drawerEl.removeEventListener('MDCDrawer:closed',
          this.handleDrawerClose_);
    }
    if (this.drawer) {
      this.drawer.destroy();
    }
    window.removeEventListener('resize', this.debounceResizeMethod_);
    this.ripples.forEach(ripple => ripple.destroy());
  }

  componentWillReceiveProps(nextProps) {
    if(this.drawer) {
      if (this.props.isDrawerOpen !== nextProps.isDrawerOpen) {
        this.drawer.open = !this.drawer.open;
      }
    }
  }

  computeDrawerWidth() {
    return this.drawerEl.getBoundingClientRect().width;
  }

  handleDrawerOpen() {
    if (!this.props.handleOpen) return;
    this.props.handleOpen(this.computeDrawerWidth());
  }

  handleDrawerClose() {
    if (!this.props.handleClose) return;
    this.props.handleClose(this.computeDrawerWidth());
  }

  renderSidebarLink(link, index) {
    const {match, history, location} = this.props;
    const path = link.url === '/' ? link.url : match.url + link.url;
    const classes = classnames('mdc-list-item', {
          'mdc-list-item--activated': this.state.activeItemIndex === index || path === location.pathname,
        });
    return (
       this.handleListItemClick_(history, path, e)}
        onKeyDown={(e) => this.handleListItemKeyDown_(history, path, e)}
        key={index}
        role='listitem'
        className={classes}
        ref={this.initRipple}
        >
        {link.content}

    );
  }

  renderScrim() {
    return (

    );
  }

  render() {
    if (this.state.variant === MODAL_DRAWER_CLASS) {
      return (

          {this.renderDrawer()}
          {this.renderScrim()}

      );
    } else {
      return this.renderDrawer();
    }
  }

  renderDrawer() {
    const links = [{
      content: 'Home',
      url: '/',
    }, {
      content: 'Button',
      url: '/button',
    }, {
      content: 'Card',
      url: '/card',
    }, {
      content: 'Checkbox',
      url: '/checkbox',
    }, {
      content: 'Chips',
      url: '/chips',
    }, {
      content: 'Dialog',
      url: '/dialog',
    }, {
      content: 'Drawer',
      url: '/drawer',
    }, {
      content: 'Elevation',
      url: '/elevation',
    }, {
      content: 'FAB',
      url: '/fab',
    }, {
      content: 'Icon Button',
      url: '/icon-button',
    }, {
      content: 'Image List',
      url: '/image-list',
    }, {
      content: 'Layout Grid',
      url: '/layout-grid',
    }, {
      content: 'Linear Progress Indicator',
      url: '/linear-progress-indicator',
    }, {
      content: 'List',
      url: '/list',
    }, {
      content: 'Menu',
      url: '/menu',
    }, {
      content: 'Radio Button',
      url: '/radio',
    }, {
      content: 'Ripple',
      url: '/ripple',
    }, {
      content: 'Select',
      url: '/select',
    }, {
      content: 'Shape',
      url: '/shape',
    }, {
      content: 'Slider',
      url: '/slider',
    }, {
      content: 'Snackbar',
      url: '/snackbar',
    }, {
      content: 'Switch',
      url: '/switch',
    }, {
      content: 'Tab Bar',
      url: '/tabs',
    }, {
      content: 'Text Field',
      url: '/text-field',
    }, {
      content: 'Theme',
      url: '/theme',
    }, {
      content: 'Top App Bar',
      url: '/top-app-bar',
    }, {
      content: 'Typography',
      url: '/typography',
    }];

    const classes = `mdc-drawer ${this.state.variant} demo-drawer mdc-top-app-bar--fixed-adjust`;
    const imageSource = `${imagePath}/ic_material_design_24px.svg`;

    return (

            {links.map((link, index) => this.renderSidebarLink(link, index))}

    );
  }

  handleResize_() {
    if (document.body.offsetWidth <= SCREEN_WIDTH_BREAKPOINT &&
        this.state.variant === DISMISSIBLE_DRAWER_CLASS) {
      if (this.drawer.open) {
        this.drawer.open = false;
      }
      setTimeout(() => {
        this.drawer.destroy();
        this.setState({variant: MODAL_DRAWER_CLASS});
        this.drawer = new MDCDrawer(this.drawerEl);
      }, 225)

    } else if(document.body.offsetWidth > SCREEN_WIDTH_BREAKPOINT &&
        this.state.variant === MODAL_DRAWER_CLASS) {
      if (this.drawer.open) {
        this.drawer.open = false;
      }
      setTimeout(() => {
        this.drawer.destroy();
        this.setState({variant: DISMISSIBLE_DRAWER_CLASS});
        this.drawer = new MDCDrawer(this.drawerEl);
      }, 225)
    }
  }

  debounceResizeMethod_ = () => {
    clearTimeout(this.debounceTimeout);
    this.debounceTimeout = setTimeout(() =>
        this.handleResize_(), 50)
  };

  handleListItemKeyDown_ = (history, path, e) => {
    if (e.keyCode === /** ENTER */ 13 || e.keyCode === /** SPACE */ 32) {
      this.handleListItemClick_(history, path, e);
    }
  };

  handleListItemClick_ = (history, path, e) => {
    // Early return if the user clicks the link for the current route.
    if (this.props.location.pathname === path) return;
    history.push(path);
    e.preventDefault();
    this.setState({activeItemIndex: e.target.getAttribute('key')});

    if (this.state.variant === MODAL_DRAWER_CLASS && this.drawer.open) {
      this.drawer.open = false;
    }
  };
}

export default ComponentSidebar;
<commit_msg>fix: Avoid pile-up of drawer instantiations (#196)<commit_after>import React, {Component} from 'react';
import classnames from 'classnames';
import {MDCDrawer} from '@material/drawer';
import {MDCRipple} from '@material/ripple';
import {imagePath} from './constants';

const SCREEN_WIDTH_BREAKPOINT = 1160;
const DISMISSIBLE_DRAWER_CLASS = 'mdc-drawer--dismissible';
const MODAL_DRAWER_CLASS = 'mdc-drawer--modal';

class ComponentSidebar extends Component {
  state = {
    variant: document.body.offsetWidth > SCREEN_WIDTH_BREAKPOINT ? DISMISSIBLE_DRAWER_CLASS : MODAL_DRAWER_CLASS,
  };

  drawer = null;
  ripples = [];
  debounceTimeout = 0;

  initRipple = ele => ele && this.ripples.push(new MDCRipple(ele));
  handleDrawerOpen_ = () => this.handleDrawerOpen();
  handleDrawerClose_ = () => this.handleDrawerClose();

  initDrawer = ele => {
    if (!ele) {
      return;
    }
    this.drawerEl = ele;

    if (this.drawer) {
      this.drawer.destroy();
    }
    this.drawer = new MDCDrawer(this.drawerEl);
  };

  componentDidMount() {
    this.drawerEl.addEventListener('MDCDrawer:opened', this.handleDrawerOpen_);
    this.drawerEl.addEventListener('MDCDrawer:closed', this.handleDrawerClose_);
    window.addEventListener('resize', this.debounceResizeMethod_);
  }

  componentWillUnmount() {
    if (this.drawerEl) {
      this.drawerEl.removeEventListener('MDCDrawer:opened',
          this.handleDrawerOpen_);
      this.drawerEl.removeEventListener('MDCDrawer:closed',
          this.handleDrawerClose_);
    }
    if (this.drawer) {
      this.drawer.destroy();
    }
    window.removeEventListener('resize', this.debounceResizeMethod_);
    this.ripples.forEach(ripple => ripple.destroy());
  }

  componentWillReceiveProps(nextProps) {
    if(this.drawer) {
      if (this.props.isDrawerOpen !== nextProps.isDrawerOpen) {
        this.drawer.open = !this.drawer.open;
      }
    }
  }

  computeDrawerWidth() {
    return this.drawerEl.getBoundingClientRect().width;
  }

  handleDrawerOpen() {
    if (!this.props.handleOpen) return;
    this.props.handleOpen(this.computeDrawerWidth());
  }

  handleDrawerClose() {
    if (!this.props.handleClose) return;
    this.props.handleClose(this.computeDrawerWidth());
  }

  renderSidebarLink(link, index) {
    const {match, history, location} = this.props;
    const path = link.url === '/' ? link.url : match.url + link.url;
    const classes = classnames('mdc-list-item', {
          'mdc-list-item--activated': this.state.activeItemIndex === index || path === location.pathname,
        });
    return (
       this.handleListItemClick_(history, path, e)}
        onKeyDown={(e) => this.handleListItemKeyDown_(history, path, e)}
        key={index}
        role='listitem'
        className={classes}
        ref={this.initRipple}
        >
        {link.content}

    );
  }

  renderScrim() {
    return (

    );
  }

  render() {
    if (this.state.variant === MODAL_DRAWER_CLASS) {
      return (

          {this.renderDrawer()}
          {this.renderScrim()}

      );
    } else {
      return this.renderDrawer();
    }
  }

  renderDrawer() {
    const links = [{
      content: 'Home',
      url: '/',
    }, {
      content: 'Button',
      url: '/button',
    }, {
      content: 'Card',
      url: '/card',
    }, {
      content: 'Checkbox',
      url: '/checkbox',
    }, {
      content: 'Chips',
      url: '/chips',
    }, {
      content: 'Dialog',
      url: '/dialog',
    }, {
      content: 'Drawer',
      url: '/drawer',
    }, {
      content: 'Elevation',
      url: '/elevation',
    }, {
      content: 'FAB',
      url: '/fab',
    }, {
      content: 'Icon Button',
      url: '/icon-button',
    }, {
      content: 'Image List',
      url: '/image-list',
    }, {
      content: 'Layout Grid',
      url: '/layout-grid',
    }, {
      content: 'Linear Progress Indicator',
      url: '/linear-progress-indicator',
    }, {
      content: 'List',
      url: '/list',
    }, {
      content: 'Menu',
      url: '/menu',
    }, {
      content: 'Radio Button',
      url: '/radio',
    }, {
      content: 'Ripple',
      url: '/ripple',
    }, {
      content: 'Select',
      url: '/select',
    }, {
      content: 'Shape',
      url: '/shape',
    }, {
      content: 'Slider',
      url: '/slider',
    }, {
      content: 'Snackbar',
      url: '/snackbar',
    }, {
      content: 'Switch',
      url: '/switch',
    }, {
      content: 'Tab Bar',
      url: '/tabs',
    }, {
      content: 'Text Field',
      url: '/text-field',
    }, {
      content: 'Theme',
      url: '/theme',
    }, {
      content: 'Top App Bar',
      url: '/top-app-bar',
    }, {
      content: 'Typography',
      url: '/typography',
    }];

    const classes = `mdc-drawer ${this.state.variant} demo-drawer mdc-top-app-bar--fixed-adjust`;
    const imageSource = `${imagePath}/ic_material_design_24px.svg`;

    return (

            {links.map((link, index) => this.renderSidebarLink(link, index))}

    );
  }

  handleResize_() {
    if (document.body.offsetWidth <= SCREEN_WIDTH_BREAKPOINT &&
        this.state.variant === DISMISSIBLE_DRAWER_CLASS) {
      if (this.drawer.open) {
        this.drawer.open = false;
      }
      setTimeout(() => {
        this.setState({variant: MODAL_DRAWER_CLASS});
      }, 225);
    } else if(document.body.offsetWidth > SCREEN_WIDTH_BREAKPOINT &&
        this.state.variant === MODAL_DRAWER_CLASS) {
      if (this.drawer.open) {
        this.drawer.open = false;
      }
      setTimeout(() => {
        this.setState({variant: DISMISSIBLE_DRAWER_CLASS});
      }, 225);
    }
  }

  debounceResizeMethod_ = () => {
    clearTimeout(this.debounceTimeout);
    this.debounceTimeout = setTimeout(() => this.handleResize_(), 50);
  };

  handleListItemKeyDown_ = (history, path, e) => {
    if (e.keyCode === /** ENTER */ 13 || e.keyCode === /** SPACE */ 32) {
      this.handleListItemClick_(history, path, e);
    }
  };

  handleListItemClick_ = (history, path, e) => {
    // Early return if the user clicks the link for the current route.
    if (this.props.location.pathname === path) return;
    history.push(path);
    e.preventDefault();
    this.setState({activeItemIndex: e.target.getAttribute('key')});

    if (this.state.variant === MODAL_DRAWER_CLASS && this.drawer.open) {
      this.drawer.open = false;
    }
  };
}

export default ComponentSidebar;
<|endoftext|>


<commit_before>var dialogPolyfill = {}

dialogPolyfill.reposition = function(element) {
  var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
  element.style.top = topValue + 'px';
  element.dialogPolyfillInfo.isTopOverridden = true;
}

dialogPolyfill.inNodeList = function(nodeList, node) {
  for (var i = 0; i < nodeList.length; ++i) {
    if (nodeList[i] == node)
      return true;
  }
  return false;
}

dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
  for (var i = 0; i < document.styleSheets.length; ++i) {
    var styleSheet = document.styleSheets[i];
    var cssRules = null;
    // Some browsers throw on cssRules.
    try {
      cssRules = styleSheet.cssRules;
    } catch (e) {}
    if (!cssRules)
      continue;
    for (var j = 0; j < cssRules.length; ++j) {
      var rule = cssRules[j];
      var selectedNodes = document.querySelectorAll(rule.selectorText);
      if (!dialogPolyfill.inNodeList(selectedNodes, element))
        continue;
      var cssTop = rule.style.getPropertyValue('top');
      var cssBottom = rule.style.getPropertyValue('bottom');
      if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
        return true;
    }
  }
  return false;
}

dialogPolyfill.needsCentering = function(dialog) {
  var computedStyle = getComputedStyle(dialog);
  if (computedStyle.position != 'absolute')
    return false;

  // We must determine whether the top/bottom specified value is non-auto.  In
  // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
  // Firefox returns the used value. So we do this crazy thing instead: check
  // the inline style and then go through CSS rules.
  if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
      (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
    return false;
  return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
}

dialogPolyfill.showDialog = function(isModal) {
  if (this.open) {
    throw 'InvalidStateError: showDialog called on open dialog';
  }
  this.open = true;
  this.style.display = 'block';

  if (dialogPolyfill.needsCentering(this))
    dialogPolyfill.reposition(this);
  if (isModal) {
    this.dialogPolyfillInfo.modal = true;
    dialogPolyfill.dm.pushDialog(this);
  }
};

dialogPolyfill.close = function(retval) {
  if (!this.open)
    throw new InvalidStateError;
  this.open = false;
  this.style.display = 'none';

  // This won't match the native <dialog> exactly because if the user sets top
  // on a centered polyfill dialog, that top gets thrown away when the dialog is
  // closed. Not sure it's possible to polyfill this perfectly.
  if (this.dialogPolyfillInfo.isTopOverridden) {
    this.style.top = 'auto';
  }

  if (this.dialogPolyfillInfo.modal) {
    dialogPolyfill.dm.removeDialog(this);
  }

  if (typeof retval != 'undefined')
    return retval;
}

dialogPolyfill.registerDialog = function(element) {
  if (element instanceof HTMLDialogElement) {
    console.error("This browser already supports <dialog>.");
    return;
  }
  element.show = dialogPolyfill.showDialog.bind(element, false);
  element.showModal = dialogPolyfill.showDialog.bind(element, true);
  element.close = dialogPolyfill.close.bind(element);
  element.dialogPolyfillInfo = {};
};

// The overlay is used to simulate how a modal dialog blocks the document. The
// blocking dialog is positioned on top of the overlay, and the rest of the
// dialogs on the pending dialog stack are positioned below it. In the actual
// implementation, the modal dialog stacking is controlled by the top layer,
// where z-index has no effect.
TOP_LAYER_ZINDEX = 100000;
MAX_PENDING_DIALOGS = 100000;

dialogPolyfill.DialogManager = function() {
  this.pendingDialogStack = [];
  this.overlay = document.createElement('div');
  this.overlay.style.width = '100%';
  this.overlay.style.height = '100%';
  this.overlay.style.position = 'fixed';
  this.overlay.style.left = '0px';
  this.overlay.style.top = '0px';
  this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

  this.overlay.addEventListener('click', function(e) {
    var redirectedEvent = document.createEvent('MouseEvents');
    redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
        e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
        e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
    document.body.dispatchEvent(redirectedEvent);
  });
}

dialogPolyfill.dm = new dialogPolyfill.DialogManager();

dialogPolyfill.DialogManager.prototype.blockDocument = function() {
  if (!document.body.contains(this.overlay))
    document.body.appendChild(this.overlay);
}

dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
  document.body.removeChild(this.overlay);
}

dialogPolyfill.DialogManager.prototype.updateStacking = function() {
  if (this.pendingDialogStack.length == 0) {
    this.unblockDocument();
    return;
  }
  this.blockDocument();

  var zIndex = TOP_LAYER_ZINDEX;
  for (var i = 0; i < this.pendingDialogStack.length; i++) {
    if (i == this.pendingDialogStack.length - 1)
      this.overlay.style.zIndex = zIndex++;
    var dialog = this.pendingDialogStack[i];
    dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
    dialog.style.zIndex = zIndex++;
  }

}

dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
  if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
    throw "Too many modal dialogs";
  }

  var backdrop = document.createElement('div');
  backdrop.classList.add('backdrop');
  backdrop.addEventListener('click', function(e) {
    var redirectedEvent = document.createEvent('MouseEvents');
    redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
        e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
        e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
    dialog.dispatchEvent(redirectedEvent);
  });
  dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
  dialog.dialogPolyfillInfo.backdrop = backdrop;
  this.pendingDialogStack.push(dialog);
  this.updateStacking();
}

dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
  var index = this.pendingDialogStack.indexOf(dialog);
  if (index == -1)
    return;
  this.pendingDialogStack.splice(index, 1);
  var backdrop = dialog.dialogPolyfillInfo.backdrop;
  backdrop.parentNode.removeChild(backdrop);
  dialog.dialogPolyfillInfo.backdrop = null;
  this.updateStacking();
}
<commit_msg>Fix breakage from trying to detect native <dialog><commit_after>var dialogPolyfill = {}

dialogPolyfill.reposition = function(element) {
  var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
  element.style.top = topValue + 'px';
  element.dialogPolyfillInfo.isTopOverridden = true;
}

dialogPolyfill.inNodeList = function(nodeList, node) {
  for (var i = 0; i < nodeList.length; ++i) {
    if (nodeList[i] == node)
      return true;
  }
  return false;
}

dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
  for (var i = 0; i < document.styleSheets.length; ++i) {
    var styleSheet = document.styleSheets[i];
    var cssRules = null;
    // Some browsers throw on cssRules.
    try {
      cssRules = styleSheet.cssRules;
    } catch (e) {}
    if (!cssRules)
      continue;
    for (var j = 0; j < cssRules.length; ++j) {
      var rule = cssRules[j];
      var selectedNodes = document.querySelectorAll(rule.selectorText);
      if (!dialogPolyfill.inNodeList(selectedNodes, element))
        continue;
      var cssTop = rule.style.getPropertyValue('top');
      var cssBottom = rule.style.getPropertyValue('bottom');
      if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
        return true;
    }
  }
  return false;
}

dialogPolyfill.needsCentering = function(dialog) {
  var computedStyle = getComputedStyle(dialog);
  if (computedStyle.position != 'absolute')
    return false;

  // We must determine whether the top/bottom specified value is non-auto.  In
  // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
  // Firefox returns the used value. So we do this crazy thing instead: check
  // the inline style and then go through CSS rules.
  if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
      (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
    return false;
  return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
}

dialogPolyfill.showDialog = function(isModal) {
  if (this.open) {
    throw 'InvalidStateError: showDialog called on open dialog';
  }
  this.open = true;
  this.style.display = 'block';

  if (dialogPolyfill.needsCentering(this))
    dialogPolyfill.reposition(this);
  if (isModal) {
    this.dialogPolyfillInfo.modal = true;
    dialogPolyfill.dm.pushDialog(this);
  }
};

dialogPolyfill.close = function(retval) {
  if (!this.open)
    throw new InvalidStateError;
  this.open = false;
  this.style.display = 'none';

  // This won't match the native <dialog> exactly because if the user sets top
  // on a centered polyfill dialog, that top gets thrown away when the dialog is
  // closed. Not sure it's possible to polyfill this perfectly.
  if (this.dialogPolyfillInfo.isTopOverridden) {
    this.style.top = 'auto';
  }

  if (this.dialogPolyfillInfo.modal) {
    dialogPolyfill.dm.removeDialog(this);
  }

  if (typeof retval != 'undefined')
    return retval;
}

dialogPolyfill.registerDialog = function(element) {
  if (element.show) {
    console.warn("This browser already supports <dialog>, the polyfill " +
        "may not work correctly.");
  }
  element.show = dialogPolyfill.showDialog.bind(element, false);
  element.showModal = dialogPolyfill.showDialog.bind(element, true);
  element.close = dialogPolyfill.close.bind(element);
  element.dialogPolyfillInfo = {};
};

// The overlay is used to simulate how a modal dialog blocks the document. The
// blocking dialog is positioned on top of the overlay, and the rest of the
// dialogs on the pending dialog stack are positioned below it. In the actual
// implementation, the modal dialog stacking is controlled by the top layer,
// where z-index has no effect.
TOP_LAYER_ZINDEX = 100000;
MAX_PENDING_DIALOGS = 100000;

dialogPolyfill.DialogManager = function() {
  this.pendingDialogStack = [];
  this.overlay = document.createElement('div');
  this.overlay.style.width = '100%';
  this.overlay.style.height = '100%';
  this.overlay.style.position = 'fixed';
  this.overlay.style.left = '0px';
  this.overlay.style.top = '0px';
  this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

  this.overlay.addEventListener('click', function(e) {
    var redirectedEvent = document.createEvent('MouseEvents');
    redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
        e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
        e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
    document.body.dispatchEvent(redirectedEvent);
  });
}

dialogPolyfill.dm = new dialogPolyfill.DialogManager();

dialogPolyfill.DialogManager.prototype.blockDocument = function() {
  if (!document.body.contains(this.overlay))
    document.body.appendChild(this.overlay);
}

dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
  document.body.removeChild(this.overlay);
}

dialogPolyfill.DialogManager.prototype.updateStacking = function() {
  if (this.pendingDialogStack.length == 0) {
    this.unblockDocument();
    return;
  }
  this.blockDocument();

  var zIndex = TOP_LAYER_ZINDEX;
  for (var i = 0; i < this.pendingDialogStack.length; i++) {
    if (i == this.pendingDialogStack.length - 1)
      this.overlay.style.zIndex = zIndex++;
    var dialog = this.pendingDialogStack[i];
    dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
    dialog.style.zIndex = zIndex++;
  }

}

dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
  if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
    throw "Too many modal dialogs";
  }

  var backdrop = document.createElement('div');
  backdrop.classList.add('backdrop');
  backdrop.addEventListener('click', function(e) {
    var redirectedEvent = document.createEvent('MouseEvents');
    redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
        e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
        e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
    dialog.dispatchEvent(redirectedEvent);
  });
  dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
  dialog.dialogPolyfillInfo.backdrop = backdrop;
  this.pendingDialogStack.push(dialog);
  this.updateStacking();
}

dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
  var index = this.pendingDialogStack.indexOf(dialog);
  if (index == -1)
    return;
  this.pendingDialogStack.splice(index, 1);
  var backdrop = dialog.dialogPolyfillInfo.backdrop;
  backdrop.parentNode.removeChild(backdrop);
  dialog.dialogPolyfillInfo.backdrop = null;
  this.updateStacking();
}
<|endoftext|>


<commit_before>var dialogPolyfill = (function() {

  var addEventListenerFn = (window.document.addEventListener
      ? function(element, type, fn) { element.addEventListener(type, fn); }
      : function(element, type, fn) { element.attachEvent('on' + type, fn); });
  var removeEventListenerFn = (window.document.removeEventListener
      ? function(element, type, fn) { element.removeEventListener(type, fn); }
      : function(element, type, fn) { element.detachEvent('on' + type, fn); });

  var dialogPolyfill = {};

  dialogPolyfill.reposition = function(element) {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
    element.style.top = topValue + 'px';
    element.dialogPolyfillInfo.isTopOverridden = true;
  };

  dialogPolyfill.inNodeList = function(nodeList, node) {
    for (var i = 0; i < nodeList.length; ++i) {
      if (nodeList[i] == node)
        return true;
    }
    return false;
  };

  dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
    for (var i = 0; i < document.styleSheets.length; ++i) {
      var styleSheet = document.styleSheets[i];
      var cssRules = null;
      // Some browsers throw on cssRules.
      try {
        cssRules = styleSheet.cssRules;
      } catch (e) {}
      if (!cssRules)
        continue;
      for (var j = 0; j < cssRules.length; ++j) {
        var rule = cssRules[j];
        var selectedNodes = null;
        // Ignore errors on invalid selector texts.
        try {
          selectedNodes = document.querySelectorAll(rule.selectorText);
        } catch(e) {}
        if (!selectedNodes || !dialogPolyfill.inNodeList(selectedNodes, element))
          continue;
        var cssTop = rule.style.getPropertyValue('top');
        var cssBottom = rule.style.getPropertyValue('bottom');
        if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
          return true;
      }
    }
    return false;
  };

  dialogPolyfill.needsCentering = function(dialog) {
    var computedStyle = getComputedStyle(dialog);
    if (computedStyle.position != 'absolute')
      return false;

    // We must determine whether the top/bottom specified value is non-auto.  In
    // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
    // Firefox returns the used value. So we do this crazy thing instead: check
    // the inline style and then go through CSS rules.
    if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
        (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
      return false;
    return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
  };

  dialogPolyfill.showDialog = function(isModal) {
    if (this.open) {
      throw 'InvalidStateError: showDialog called on open dialog';
    }
    this.open = true;
    this.setAttribute('open', 'open');

    if (dialogPolyfill.needsCentering(this))
      dialogPolyfill.reposition(this);
    if (isModal) {
      this.dialogPolyfillInfo.modal = true;
      dialogPolyfill.dm.pushDialog(this);
    }
  };

  dialogPolyfill.close = function(retval) {
    if (!this.open)
      throw new InvalidStateError;
    this.open = false;
    this.removeAttribute('open');

    // Leave returnValue untouched in case it was set directly on the element
    if (typeof retval != 'undefined') {
      this.returnValue = retval;
    }

    // This won't match the native <dialog> exactly because if the user sets top
    // on a centered polyfill dialog, that top gets thrown away when the dialog is
    // closed. Not sure it's possible to polyfill this perfectly.
    if (this.dialogPolyfillInfo.isTopOverridden) {
      this.style.top = 'auto';
    }

    if (this.dialogPolyfillInfo.modal) {
      dialogPolyfill.dm.removeDialog(this);
    }

    // Triggering "close" event for any attached listeners on the <dialog>
    var event;
    if (document.createEvent) {
      event = document.createEvent('HTMLEvents');
      event.initEvent('close', true, true);
    } else {
      event = new Event('close');
    }
    this.dispatchEvent(event);

    return this.returnValue;
  };

  dialogPolyfill.registerDialog = function(element) {
    if (element.show) {
      console.warn("This browser already supports <dialog>, the polyfill " +
          "may not work correctly.");
    }
    var forms = element.getElementsByTagName('form');
    var found = -1;
    for (var i = 0; i < forms.length; i++) {
      if (forms[i].getAttribute('method') == 'dialog') { // form.method won't return 'dialog'
        found = i;
        break;
      }
    }
    if (found !== -1) {
      addEventListenerFn(forms[found], 'click', function(event) {
        if (event.target.type == 'submit') {
          element.close(event.target.value);
        }
      });
    }
    element.show = dialogPolyfill.showDialog.bind(element, false);
    element.showModal = dialogPolyfill.showDialog.bind(element, true);
    element.close = dialogPolyfill.close.bind(element);
    element.dialogPolyfillInfo = {};
  };

  // The overlay is used to simulate how a modal dialog blocks the document. The
  // blocking dialog is positioned on top of the overlay, and the rest of the
  // dialogs on the pending dialog stack are positioned below it. In the actual
  // implementation, the modal dialog stacking is controlled by the top layer,
  // where z-index has no effect.
  TOP_LAYER_ZINDEX = 100000;
  MAX_PENDING_DIALOGS = 100000;

  dialogPolyfill.DialogManager = function() {
    this.pendingDialogStack = [];
    this.overlay = document.createElement('div');
    this.overlay.style.width = '100%';
    this.overlay.style.height = '100%';
    this.overlay.style.position = 'fixed';
    this.overlay.style.left = '0px';
    this.overlay.style.top = '0px';
    this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

    addEventListenerFn(this.overlay, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      document.body.dispatchEvent(redirectedEvent);
    });
  };

  dialogPolyfill.dm = new dialogPolyfill.DialogManager();

  dialogPolyfill.DialogManager.prototype.blockDocument = function() {
    if (!document.body.contains(this.overlay))
      document.body.appendChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
    document.body.removeChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.updateStacking = function() {
    if (this.pendingDialogStack.length == 0) {
      this.unblockDocument();
      return;
    }
    this.blockDocument();

    var zIndex = TOP_LAYER_ZINDEX;
    for (var i = 0; i < this.pendingDialogStack.length; i++) {
      if (i == this.pendingDialogStack.length - 1)
        this.overlay.style.zIndex = zIndex++;
      var dialog = this.pendingDialogStack[i];
      dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
      dialog.style.zIndex = zIndex++;
    }
  };

  dialogPolyfill.DialogManager.prototype.cancelDialog = function(event) {
    if (event.keyCode === 27 && this.pendingDialogStack.length > 0) {
      event.preventDefault();
      event.stopPropagation();
      var dialog = this.pendingDialogStack.slice(-1)[0];
      if (dialog) {
        var cancelEvent = document.createEvent('Event');
        cancelEvent.initEvent('cancel', false, true);
        if (dialog.dispatchEvent(cancelEvent)) {
          dialog.close();
        }
      }
    }
  };

  dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
    if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
      throw "Too many modal dialogs";
    }

    var backdrop = document.createElement('div');
    backdrop.classList.add('backdrop');
    addEventListenerFn(backdrop, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      dialog.dispatchEvent(redirectedEvent);
    });
    dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
    dialog.dialogPolyfillInfo.backdrop = backdrop;
    this.pendingDialogStack.push(dialog);
    this.updateStacking();
  };

  dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
    var index = this.pendingDialogStack.indexOf(dialog);
    if (index == -1)
      return;
    this.pendingDialogStack.splice(index, 1);
    var backdrop = dialog.dialogPolyfillInfo.backdrop;
    backdrop.parentNode.removeChild(backdrop);
    dialog.dialogPolyfillInfo.backdrop = null;
    this.updateStacking();
  };

  addEventListenerFn(document, 'keydown', dialogPolyfill.dm.cancelDialog.bind(dialogPolyfill.dm));

  return dialogPolyfill;
})();
<commit_msg>autofocus is now supported<commit_after>var dialogPolyfill = (function() {

  var addEventListenerFn = (window.document.addEventListener
      ? function(element, type, fn) { element.addEventListener(type, fn); }
      : function(element, type, fn) { element.attachEvent('on' + type, fn); });
  var removeEventListenerFn = (window.document.removeEventListener
      ? function(element, type, fn) { element.removeEventListener(type, fn); }
      : function(element, type, fn) { element.detachEvent('on' + type, fn); });

  var dialogPolyfill = {};

  dialogPolyfill.reposition = function(element) {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
    element.style.top = topValue + 'px';
    element.dialogPolyfillInfo.isTopOverridden = true;
  };

  dialogPolyfill.inNodeList = function(nodeList, node) {
    for (var i = 0; i < nodeList.length; ++i) {
      if (nodeList[i] == node)
        return true;
    }
    return false;
  };

  dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
    for (var i = 0; i < document.styleSheets.length; ++i) {
      var styleSheet = document.styleSheets[i];
      var cssRules = null;
      // Some browsers throw on cssRules.
      try {
        cssRules = styleSheet.cssRules;
      } catch (e) {}
      if (!cssRules)
        continue;
      for (var j = 0; j < cssRules.length; ++j) {
        var rule = cssRules[j];
        var selectedNodes = null;
        // Ignore errors on invalid selector texts.
        try {
          selectedNodes = document.querySelectorAll(rule.selectorText);
        } catch(e) {}
        if (!selectedNodes || !dialogPolyfill.inNodeList(selectedNodes, element))
          continue;
        var cssTop = rule.style.getPropertyValue('top');
        var cssBottom = rule.style.getPropertyValue('bottom');
        if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
          return true;
      }
    }
    return false;
  };

  dialogPolyfill.needsCentering = function(dialog) {
    var computedStyle = getComputedStyle(dialog);
    if (computedStyle.position != 'absolute')
      return false;

    // We must determine whether the top/bottom specified value is non-auto.  In
    // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
    // Firefox returns the used value. So we do this crazy thing instead: check
    // the inline style and then go through CSS rules.
    if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
        (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
      return false;
    return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
  };

  dialogPolyfill.showDialog = function(isModal) {
    if (this.open) {
      throw 'InvalidStateError: showDialog called on open dialog';
    }
    this.open = true;
    this.setAttribute('open', 'open');

    // Find element with `autofocus` attribute or first form control
    var first_form_ctrl = null;
    var first_autofocus = null;
    var traverse = function(root) {
      for (var i = 0; i < root.children.length; i++) {
        var elem = root.children[i];
        if (first_form_ctrl === null && (
            elem.nodeName == 'BUTTON' ||
            elem.nodeName == 'INPUT'  ||
            elem.nodeName == 'KEYGEN' ||
            elem.nodeName == 'SELECT' ||
            elem.nodeName == 'TEXTAREA')) {
          first_form_ctrl = elem;
        }
        if (first_autofocus === null &&
            elem.getAttribute('autofocus') === '') {
          first_autofocus = elem;
        }

        if (first_form_ctrl && first_autofocus) {
          break;
        } else {
          traverse(elem);
        }
      }
    };

    traverse(this);

    if (first_autofocus) {
      first_autofocus.focus();
    } else if (first_form_ctrl) {
      first_form_ctrl.focus();
    }

    if (dialogPolyfill.needsCentering(this))
      dialogPolyfill.reposition(this);
    if (isModal) {
      this.dialogPolyfillInfo.modal = true;
      dialogPolyfill.dm.pushDialog(this);
    }
  };

  dialogPolyfill.close = function(retval) {
    if (!this.open)
      throw new InvalidStateError;
    this.open = false;
    this.removeAttribute('open');

    // Leave returnValue untouched in case it was set directly on the element
    if (typeof retval != 'undefined') {
      this.returnValue = retval;
    }

    // This won't match the native <dialog> exactly because if the user sets top
    // on a centered polyfill dialog, that top gets thrown away when the dialog is
    // closed. Not sure it's possible to polyfill this perfectly.
    if (this.dialogPolyfillInfo.isTopOverridden) {
      this.style.top = 'auto';
    }

    if (this.dialogPolyfillInfo.modal) {
      dialogPolyfill.dm.removeDialog(this);
    }

    // Triggering "close" event for any attached listeners on the <dialog>
    var event;
    if (document.createEvent) {
      event = document.createEvent('HTMLEvents');
      event.initEvent('close', true, true);
    } else {
      event = new Event('close');
    }
    this.dispatchEvent(event);

    return this.returnValue;
  };

  dialogPolyfill.registerDialog = function(element) {
    if (element.show) {
      console.warn("This browser already supports <dialog>, the polyfill " +
          "may not work correctly.");
    }
    var forms = element.getElementsByTagName('form');
    var found = -1;
    for (var i = 0; i < forms.length; i++) {
      if (forms[i].getAttribute('method') == 'dialog') { // form.method won't return 'dialog'
        found = i;
        break;
      }
    }
    if (found !== -1) {
      addEventListenerFn(forms[found], 'click', function(event) {
        if (event.target.type == 'submit') {
          element.close(event.target.value);
        }
      });
    }
    element.show = dialogPolyfill.showDialog.bind(element, false);
    element.showModal = dialogPolyfill.showDialog.bind(element, true);
    element.close = dialogPolyfill.close.bind(element);
    element.dialogPolyfillInfo = {};
  };

  // The overlay is used to simulate how a modal dialog blocks the document. The
  // blocking dialog is positioned on top of the overlay, and the rest of the
  // dialogs on the pending dialog stack are positioned below it. In the actual
  // implementation, the modal dialog stacking is controlled by the top layer,
  // where z-index has no effect.
  TOP_LAYER_ZINDEX = 100000;
  MAX_PENDING_DIALOGS = 100000;

  dialogPolyfill.DialogManager = function() {
    this.pendingDialogStack = [];
    this.overlay = document.createElement('div');
    this.overlay.style.width = '100%';
    this.overlay.style.height = '100%';
    this.overlay.style.position = 'fixed';
    this.overlay.style.left = '0px';
    this.overlay.style.top = '0px';
    this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

    addEventListenerFn(this.overlay, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      document.body.dispatchEvent(redirectedEvent);
    });
  };

  dialogPolyfill.dm = new dialogPolyfill.DialogManager();

  dialogPolyfill.DialogManager.prototype.blockDocument = function() {
    if (!document.body.contains(this.overlay))
      document.body.appendChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
    document.body.removeChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.updateStacking = function() {
    if (this.pendingDialogStack.length == 0) {
      this.unblockDocument();
      return;
    }
    this.blockDocument();

    var zIndex = TOP_LAYER_ZINDEX;
    for (var i = 0; i < this.pendingDialogStack.length; i++) {
      if (i == this.pendingDialogStack.length - 1)
        this.overlay.style.zIndex = zIndex++;
      var dialog = this.pendingDialogStack[i];
      dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
      dialog.style.zIndex = zIndex++;
    }
  };

  dialogPolyfill.DialogManager.prototype.cancelDialog = function(event) {
    if (event.keyCode === 27 && this.pendingDialogStack.length > 0) {
      event.preventDefault();
      event.stopPropagation();
      var dialog = this.pendingDialogStack.slice(-1)[0];
      if (dialog) {
        var cancelEvent = document.createEvent('Event');
        cancelEvent.initEvent('cancel', false, true);
        if (dialog.dispatchEvent(cancelEvent)) {
          dialog.close();
        }
      }
    }
  };

  dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
    if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
      throw "Too many modal dialogs";
    }

    var backdrop = document.createElement('div');
    backdrop.classList.add('backdrop');
    addEventListenerFn(backdrop, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      dialog.dispatchEvent(redirectedEvent);
    });
    dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
    dialog.dialogPolyfillInfo.backdrop = backdrop;
    this.pendingDialogStack.push(dialog);
    this.updateStacking();
  };

  dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
    var index = this.pendingDialogStack.indexOf(dialog);
    if (index == -1)
      return;
    this.pendingDialogStack.splice(index, 1);
    var backdrop = dialog.dialogPolyfillInfo.backdrop;
    backdrop.parentNode.removeChild(backdrop);
    dialog.dialogPolyfillInfo.backdrop = null;
    this.updateStacking();
  };

  addEventListenerFn(document, 'keydown', dialogPolyfill.dm.cancelDialog.bind(dialogPolyfill.dm));

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


<commit_before>var dialogPolyfill = {}

dialogPolyfill.reposition = function(element) {
  var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
  element.style.top = topValue + 'px';
  element.dialogPolyfillInfo.isTopOverridden = true;
}

dialogPolyfill.inNodeList = function(nodeList, node) {
  for (var i = 0; i < nodeList.length; ++i) {
    if (nodeList[i] == node)
      return true;
  }
  return false;
}

dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
  for (var i = 0; i < document.styleSheets.length; ++i) {
    var styleSheet = document.styleSheets[i];
    var cssRules = null;
    // Some browsers throw on cssRules.
    try {
      cssRules = styleSheet.cssRules;
    } catch (e) {}
    if (!cssRules)
      continue;
    for (var j = 0; j < cssRules.length; ++j) {
      var rule = cssRules[j];
      var selectedNodes = null;
      // Ignore errors on invalid selector texts.
      try {
        selectedNodes = document.querySelectorAll(rule.selectorText);
      } catch(e) {}
      if (!selectedNodes || !dialogPolyfill.inNodeList(selectedNodes, element))
        continue;
      var cssTop = rule.style.getPropertyValue('top');
      var cssBottom = rule.style.getPropertyValue('bottom');
      if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
        return true;
    }
  }
  return false;
}

dialogPolyfill.needsCentering = function(dialog) {
  var computedStyle = getComputedStyle(dialog);
  if (computedStyle.position != 'absolute')
    return false;

  // We must determine whether the top/bottom specified value is non-auto.  In
  // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
  // Firefox returns the used value. So we do this crazy thing instead: check
  // the inline style and then go through CSS rules.
  if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
      (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
    return false;
  return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
}

dialogPolyfill.showDialog = function(isModal) {
  if (this.open) {
    throw 'InvalidStateError: showDialog called on open dialog';
  }
  this.open = true;
  this.setAttribute('open', 'open');

  if (dialogPolyfill.needsCentering(this))
    dialogPolyfill.reposition(this);
  if (isModal) {
    this.dialogPolyfillInfo.modal = true;
    dialogPolyfill.dm.pushDialog(this);
  }
};

dialogPolyfill.close = function(retval) {
  if (!this.open)
    throw new InvalidStateError;
  this.open = false;
  this.removeAttribute('open');

  // Leave returnValue untouched in case it was set directly on the element
  if (typeof retval != 'undefined') {
    this.returnValue = retval;
  }

  // This won't match the native <dialog> exactly because if the user sets top
  // on a centered polyfill dialog, that top gets thrown away when the dialog is
  // closed. Not sure it's possible to polyfill this perfectly.
  if (this.dialogPolyfillInfo.isTopOverridden) {
    this.style.top = 'auto';
  }

  if (this.dialogPolyfillInfo.modal) {
    dialogPolyfill.dm.removeDialog(this);
  }

  // Triggering "close" event for any attached listeners on the <dialog>
  var event;
  if (document.createEvent) {
    event = document.createEvent('HTMLEvents');
    event.initEvent('close', true, true);
  } else {
    event = new Event('close');
  }
  this.dispatchEvent(event);

  return this.returnValue;
}

dialogPolyfill.registerDialog = function(element) {
  if (element.show) {
    console.warn("This browser already supports <dialog>, the polyfill " +
        "may not work correctly.");
  }
  element.show = dialogPolyfill.showDialog.bind(element, false);
  element.showModal = dialogPolyfill.showDialog.bind(element, true);
  element.close = dialogPolyfill.close.bind(element);
  element.dialogPolyfillInfo = {};
};

// The overlay is used to simulate how a modal dialog blocks the document. The
// blocking dialog is positioned on top of the overlay, and the rest of the
// dialogs on the pending dialog stack are positioned below it. In the actual
// implementation, the modal dialog stacking is controlled by the top layer,
// where z-index has no effect.
TOP_LAYER_ZINDEX = 100000;
MAX_PENDING_DIALOGS = 100000;

dialogPolyfill.DialogManager = function() {
  this.pendingDialogStack = [];
  this.overlay = document.createElement('div');
  this.overlay.style.width = '100%';
  this.overlay.style.height = '100%';
  this.overlay.style.position = 'fixed';
  this.overlay.style.left = '0px';
  this.overlay.style.top = '0px';
  this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

  this.overlay.addEventListener('click', function(e) {
    var redirectedEvent = document.createEvent('MouseEvents');
    redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
        e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
        e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
    document.body.dispatchEvent(redirectedEvent);
  });
}

dialogPolyfill.dm = new dialogPolyfill.DialogManager();

dialogPolyfill.DialogManager.prototype.blockDocument = function() {
  if (!document.body.contains(this.overlay))
    document.body.appendChild(this.overlay);
}

dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
  document.body.removeChild(this.overlay);
}

dialogPolyfill.DialogManager.prototype.updateStacking = function() {
  if (this.pendingDialogStack.length == 0) {
    this.unblockDocument();
    return;
  }
  this.blockDocument();

  var zIndex = TOP_LAYER_ZINDEX;
  for (var i = 0; i < this.pendingDialogStack.length; i++) {
    if (i == this.pendingDialogStack.length - 1)
      this.overlay.style.zIndex = zIndex++;
    var dialog = this.pendingDialogStack[i];
    dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
    dialog.style.zIndex = zIndex++;
  }

}

dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
  if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
    throw "Too many modal dialogs";
  }

  var backdrop = document.createElement('div');
  backdrop.classList.add('backdrop');
  backdrop.addEventListener('click', function(e) {
    var redirectedEvent = document.createEvent('MouseEvents');
    redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
        e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
        e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
    dialog.dispatchEvent(redirectedEvent);
  });
  dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
  dialog.dialogPolyfillInfo.backdrop = backdrop;
  this.pendingDialogStack.push(dialog);
  this.updateStacking();
}

dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
  var index = this.pendingDialogStack.indexOf(dialog);
  if (index == -1)
    return;
  this.pendingDialogStack.splice(index, 1);
  var backdrop = dialog.dialogPolyfillInfo.backdrop;
  backdrop.parentNode.removeChild(backdrop);
  dialog.dialogPolyfillInfo.backdrop = null;
  this.updateStacking();
}
<commit_msg>encapsulated whole script and added private methods<commit_after>var dialogPolyfill = (function() {

  var addEventListenerFn = (window.document.addEventListener
      ? function(element, type, fn) { element.addEventListener(type, fn); }
      : function(element, type, fn) { element.attachEvent('on'+type, fn); });
  var removeEventListenerFn = (window.document.removeEventListener
      ? function(element, type, fn) { element.removeEventListener(type, fn); }
      : function(element, type, fn) { element.detachEvent('on'+type, fn); });

  var dialogPolyfill = {};

  dialogPolyfill.reposition = function(element) {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    var topValue = scrollTop + (window.innerHeight - element.offsetHeight) / 2;
    element.style.top = topValue + 'px';
    element.dialogPolyfillInfo.isTopOverridden = true;
  };

  dialogPolyfill.inNodeList = function(nodeList, node) {
    for (var i = 0; i < nodeList.length; ++i) {
      if (nodeList[i] == node)
        return true;
    }
    return false;
  };

  dialogPolyfill.isInlinePositionSetByStylesheet = function(element) {
    for (var i = 0; i < document.styleSheets.length; ++i) {
      var styleSheet = document.styleSheets[i];
      var cssRules = null;
      // Some browsers throw on cssRules.
      try {
        cssRules = styleSheet.cssRules;
      } catch (e) {}
      if (!cssRules)
        continue;
      for (var j = 0; j < cssRules.length; ++j) {
        var rule = cssRules[j];
        var selectedNodes = null;
        // Ignore errors on invalid selector texts.
        try {
          selectedNodes = document.querySelectorAll(rule.selectorText);
        } catch(e) {}
        if (!selectedNodes || !dialogPolyfill.inNodeList(selectedNodes, element))
          continue;
        var cssTop = rule.style.getPropertyValue('top');
        var cssBottom = rule.style.getPropertyValue('bottom');
        if ((cssTop && cssTop != 'auto') || (cssBottom && cssBottom != 'auto'))
          return true;
      }
    }
    return false;
  };

  dialogPolyfill.needsCentering = function(dialog) {
    var computedStyle = getComputedStyle(dialog);
    if (computedStyle.position != 'absolute')
      return false;

    // We must determine whether the top/bottom specified value is non-auto.  In
    // WebKit/Blink, checking computedStyle.top == 'auto' is sufficient, but
    // Firefox returns the used value. So we do this crazy thing instead: check
    // the inline style and then go through CSS rules.
    if ((dialog.style.top != 'auto' && dialog.style.top != '') ||
        (dialog.style.bottom != 'auto' && dialog.style.bottom != ''))
      return false;
    return !dialogPolyfill.isInlinePositionSetByStylesheet(dialog);
  };

  dialogPolyfill.showDialog = function(isModal) {
    if (this.open) {
      throw 'InvalidStateError: showDialog called on open dialog';
    }
    this.open = true;
    this.setAttribute('open', 'open');

    if (dialogPolyfill.needsCentering(this))
      dialogPolyfill.reposition(this);
    if (isModal) {
      this.dialogPolyfillInfo.modal = true;
      dialogPolyfill.dm.pushDialog(this);
    }
  };

  dialogPolyfill.close = function(retval) {
    if (!this.open)
      throw new InvalidStateError;
    this.open = false;
    this.removeAttribute('open');

    // Leave returnValue untouched in case it was set directly on the element
    if (typeof retval != 'undefined') {
      this.returnValue = retval;
    }

    // This won't match the native <dialog> exactly because if the user sets top
    // on a centered polyfill dialog, that top gets thrown away when the dialog is
    // closed. Not sure it's possible to polyfill this perfectly.
    if (this.dialogPolyfillInfo.isTopOverridden) {
      this.style.top = 'auto';
    }

    if (this.dialogPolyfillInfo.modal) {
      dialogPolyfill.dm.removeDialog(this);
    }

    // Triggering "close" event for any attached listeners on the <dialog>
    var event;
    if (document.createEvent) {
      event = document.createEvent('HTMLEvents');
      event.initEvent('close', true, true);
    } else {
      event = new Event('close');
    }
    this.dispatchEvent(event);

    return this.returnValue;
  };

  dialogPolyfill.registerDialog = function(element) {
    if (element.show) {
      console.warn("This browser already supports <dialog>, the polyfill " +
          "may not work correctly.");
    }
    element.show = dialogPolyfill.showDialog.bind(element, false);
    element.showModal = dialogPolyfill.showDialog.bind(element, true);
    element.close = dialogPolyfill.close.bind(element);
    element.dialogPolyfillInfo = {};
  };

  // The overlay is used to simulate how a modal dialog blocks the document. The
  // blocking dialog is positioned on top of the overlay, and the rest of the
  // dialogs on the pending dialog stack are positioned below it. In the actual
  // implementation, the modal dialog stacking is controlled by the top layer,
  // where z-index has no effect.
  TOP_LAYER_ZINDEX = 100000;
  MAX_PENDING_DIALOGS = 100000;

  dialogPolyfill.DialogManager = function() {
    this.pendingDialogStack = [];
    this.overlay = document.createElement('div');
    this.overlay.style.width = '100%';
    this.overlay.style.height = '100%';
    this.overlay.style.position = 'fixed';
    this.overlay.style.left = '0px';
    this.overlay.style.top = '0px';
    this.overlay.style.backgroundColor = 'rgba(0,0,0,0.0)';

    addEventListenerFn(this.overlay, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      document.body.dispatchEvent(redirectedEvent);
    });
  };

  dialogPolyfill.dm = new dialogPolyfill.DialogManager();

  dialogPolyfill.DialogManager.prototype.blockDocument = function() {
    if (!document.body.contains(this.overlay))
      document.body.appendChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.unblockDocument = function() {
    document.body.removeChild(this.overlay);
  };

  dialogPolyfill.DialogManager.prototype.updateStacking = function() {
    if (this.pendingDialogStack.length == 0) {
      this.unblockDocument();
      return;
    }
    this.blockDocument();

    var zIndex = TOP_LAYER_ZINDEX;
    for (var i = 0; i < this.pendingDialogStack.length; i++) {
      if (i == this.pendingDialogStack.length - 1)
        this.overlay.style.zIndex = zIndex++;
      var dialog = this.pendingDialogStack[i];
      dialog.dialogPolyfillInfo.backdrop.style.zIndex = zIndex++;
      dialog.style.zIndex = zIndex++;
    }
  };

  dialogPolyfill.DialogManager.prototype.pushDialog = function(dialog) {
    if (this.pendingDialogStack.length >= MAX_PENDING_DIALOGS) {
      throw "Too many modal dialogs";
    }

    var backdrop = document.createElement('div');
    backdrop.classList.add('backdrop');
    addEventListenerFn(backdrop, 'click', function(e) {
      var redirectedEvent = document.createEvent('MouseEvents');
      redirectedEvent.initMouseEvent(e.type, e.bubbles, e.cancelable, window,
          e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey,
          e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget);
      dialog.dispatchEvent(redirectedEvent);
    });
    dialog.parentNode.insertBefore(backdrop, dialog.nextSibling);
    dialog.dialogPolyfillInfo.backdrop = backdrop;
    this.pendingDialogStack.push(dialog);
    this.updateStacking();
  };

  dialogPolyfill.DialogManager.prototype.removeDialog = function(dialog) {
    var index = this.pendingDialogStack.indexOf(dialog);
    if (index == -1)
      return;
    this.pendingDialogStack.splice(index, 1);
    var backdrop = dialog.dialogPolyfillInfo.backdrop;
    backdrop.parentNode.removeChild(backdrop);
    dialog.dialogPolyfillInfo.backdrop = null;
    this.updateStacking();
  };
  return dialogPolyfill;
})();<|endoftext|>