<commit_before>var webdriver = require('selenium-webdriver');

/* globals browser */

/**
 * Represents a library of canned expected conditions that are useful for
 * protractor, especially when dealing with non-angular apps.
 *
 * Each condition returns a function that evaluates to a promise. You may mix
 * multiple conditions using `and`, `or`, and/or `not`. You may also
 * mix these conditions with any other conditions that you write.
 *
 * See https://selenium.googlecode.com/git/docs/api/java/org/openqa ...
 *     /selenium/support/ui/ExpectedConditions.html
 *
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * var button = $('#xyz');
 * var isClickable = EC.elementToBeClickable(button);
 *
 * browser.get(URL);
 * browser.wait(isClickable, 5000); //wait for an element to become clickable
 * button.click();
 *
 * // You can define your own expected condition, which is a function that
 * // takes no parameter and evaluates to a promise of a boolean.
 * var urlChanged = function() {
 *   return browser.getCurrentUrl().then(function(url) {
 *     return url === 'http://www.angularjs.org';
 *   });
 * };
 *
 * // You can customize the conditions with EC.and, EC.or, and EC.not.
 * // Here's a condition to wait for url to change, $('abc') element to contain
 * // text 'bar', and button becomes clickable.
 * var condition = EC.and(urlChanged, EC.textToBePresentInElement($('abc'), 'bar'), isClickable);
 * browser.get(URL);
 * browser.wait(condition, 5000); //wait for condition to be true.
 * button.click();
 *
 * @constructor
 */
var ExpectedConditions = function() {};

/**
 * Negates the result of a promise.
 *
 * @param {!function} expectedCondition
 *
 * @return {!function} An expected condition that returns the negated value.
 */
ExpectedConditions.prototype.not = function(expectedCondition) {
  return function() {
    return expectedCondition.call().then(function(bool) {
      return !bool;
    });
  };
};

/**
 * Helper function that is equivalent to the logical_and if defaultRet==true,
 * or logical_or if defaultRet==false
 *
 * @private
 * @param {boolean} defaultRet
 * @param {Array.<Function>} fns An array of expected conditions to chain.
 *
 * @return {!function} An expected condition that returns a promise which
 *     evaluates to the result of the logical chain.
 */
ExpectedConditions.prototype.logicalChain_ = function(defaultRet, fns) {
  var self = this;
  return function() {
    if (fns.length === 0) {
      return defaultRet;
    }
    var fn = fns[0];
    return fn().then(function(bool) {
      if (bool === defaultRet) {
        return self.logicalChain_(defaultRet, fns.slice(1))();
      } else {
        return !defaultRet;
      }
    });
  };
};

/**
 * Chain a number of expected conditions using logical_and, short circuiting
 * at the first expected condition that evaluates to false.
 *
 * @param {Array.<Function>} fns An array of expected conditions to 'and' together.
 *
 * @return {!function} An expected condition that returns a promise which
 *     evaluates to the result of the logical and.
 */
ExpectedConditions.prototype.and = function() {
  var args = Array.prototype.slice.call(arguments);
  return this.logicalChain_(true, args);
};

/**
 * Chain a number of expected conditions using logical_or, short circuiting
 * at the first expected condition that evaluates to true.
 *
 * @param {Array.<Function>} fns An array of expected conditions to 'or' together.
 *
 * @return {!function} An expected condition that returns a promise which
 *     evaluates to the result of the logical or.
 */
ExpectedConditions.prototype.or = function() {
  var args = Array.prototype.slice.call(arguments);
  return this.logicalChain_(false, args);
};

/**
 * Expect an alert to be present.
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether an alert is present.
 */
ExpectedConditions.prototype.alertIsPresent = function() {
  return function() {
    return browser.switchTo().alert().then(function() {
      return true;
    }, function(err) {
      if (err.code == webdriver.error.ErrorCode.NO_SUCH_ALERT) {
        return false;
      } else {
        throw err;
      }
    });
  };
};

/**
 * An Expectation for checking an element is visible and enabled such that you
 * can click it.
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is clickable.
 */
ExpectedConditions.prototype.elementToBeClickable = function(elementFinder) {
  return this.and(
      this.visibilityOf(elementFinder),
      elementFinder.isEnabled.bind(elementFinder));
};

/**
 * An expectation for checking if the given text is present in the
 * element. Returns false if the elementFinder does not find an element.
 *
 * @param {!ElementFinder} elementFinder The element to check
 * @param {!string} text The text to verify against
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the text is present in the element.
 */
ExpectedConditions.prototype.textToBePresentInElement = function(elementFinder, text) {
  var hasText = function() {
    return elementFinder.getText().then(function(actualText) {
      return actualText.indexOf(text) > -1;
    });
  };
  return this.and(this.presenceOf(elementFinder), hasText);
};

/**
 * An expectation for checking if the given text is present in the element’s
 * value. Returns false if the elementFinder does not find an element.
 *
 * @param {!ElementFinder} elementFinder The element to check
 * @param {!string} text The text to verify against
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the text is present in the element's value.
 */
ExpectedConditions.prototype.textToBePresentInElementValue = function(elementFinder, text) {
  var hasText = function() {
    return elementFinder.getAttribute('value').then(function(actualText) {
      return actualText.indexOf(text) > -1;
    });
  };
  return this.and(this.presenceOf(elementFinder), hasText);
};

/**
 * An expectation for checking that the title contains a case-sensitive
 * substring.
 *
 * @param {!string} title The fragment of title expected
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the title contains the string.
 */
ExpectedConditions.prototype.titleContains = function(title) {
  return function() {
    return browser.getTitle().then(function(actualTitle) {
      return actualTitle.indexOf(title) > -1;
    });
  };
};

/**
 * An expectation for checking the title of a page.
 *
 * @param {!string} title The expected title, which must be an exact match.
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the title equals the string.
 */
ExpectedConditions.prototype.titleIs = function(title) {
  return function() {
    return browser.getTitle().then(function(actualTitle) {
      return actualTitle === title;
    });
  };
};

/**
 * An expectation for checking that an element is present on the DOM
 * of a page. This does not necessarily mean that the element is visible.
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is present.
 */
ExpectedConditions.prototype.presenceOf = function(elementFinder) {
  return elementFinder.isPresent.bind(elementFinder);
};

/**
 * An expectation for checking that an element is not attached to the DOM
 * of a page.
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is stale.
 */
ExpectedConditions.prototype.stalenessOf = function(elementFinder) {
  return this.not(this.presenceOf(elementFinder));
};

/**
 * An expectation for checking that an element is present on the DOM of a
 * page and visible. Visibility means that the element is not only displayed
 * but also has a height and width that is greater than 0.
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is visible.
 */
ExpectedConditions.prototype.visibilityOf = function(elementFinder) {
  return this.and(
    this.presenceOf(elementFinder),
    elementFinder.isDisplayed.bind(elementFinder));
};

/**
 * An expectation for checking that an element is either invisible or not
 * present on the DOM.
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is invisible.
 */
ExpectedConditions.prototype.invisibilityOf = function(elementFinder) {
  return this.not(this.visibilityOf(elementFinder));
};

/**
 * An expectation for checking the selection is selected.
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is selected.
 */
ExpectedConditions.prototype.elementToBeSelected = function(elementFinder) {
  return this.and(
    this.presenceOf(elementFinder),
    elementFinder.isSelected.bind(elementFinder));
};

module.exports = ExpectedConditions;

<commit_msg>docs(expectedConditions): Add docs for individual expected conditions<commit_after>var webdriver = require('selenium-webdriver');

/* globals browser */

/**
 * Represents a library of canned expected conditions that are useful for
 * protractor, especially when dealing with non-angular apps.
 *
 * Each condition returns a function that evaluates to a promise. You may mix
 * multiple conditions using `and`, `or`, and/or `not`. You may also
 * mix these conditions with any other conditions that you write.
 *
 * See https://selenium.googlecode.com/git/docs/api/java/org/openqa ...
 *     /selenium/support/ui/ExpectedConditions.html
 *
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * var button = $('#xyz');
 * var isClickable = EC.elementToBeClickable(button);
 *
 * browser.get(URL);
 * browser.wait(isClickable, 5000); //wait for an element to become clickable
 * button.click();
 *
 * // You can define your own expected condition, which is a function that
 * // takes no parameter and evaluates to a promise of a boolean.
 * var urlChanged = function() {
 *   return browser.getCurrentUrl().then(function(url) {
 *     return url === 'http://www.angularjs.org';
 *   });
 * };
 *
 * // You can customize the conditions with EC.and, EC.or, and EC.not.
 * // Here's a condition to wait for url to change, $('abc') element to contain
 * // text 'bar', and button becomes clickable.
 * var condition = EC.and(urlChanged, EC.textToBePresentInElement($('abc'), 'bar'), isClickable);
 * browser.get(URL);
 * browser.wait(condition, 5000); //wait for condition to be true.
 * button.click();
 *
 * @constructor
 */
var ExpectedConditions = function() {};

/**
 * Negates the result of a promise.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * var titleIsNotFoo = EC.not(EC.titleIs('Foo'));
 * // Waits for title to become something besides 'foo'.
 * browser.wait(titleIsNotFoo, 5000);
 *
 * @param {!function} expectedCondition
 *
 * @return {!function} An expected condition that returns the negated value.
 */
ExpectedConditions.prototype.not = function(expectedCondition) {
  return function() {
    return expectedCondition.call().then(function(bool) {
      return !bool;
    });
  };
};

/**
 * Helper function that is equivalent to the logical_and if defaultRet==true,
 * or logical_or if defaultRet==false
 *
 * @private
 * @param {boolean} defaultRet
 * @param {Array.<Function>} fns An array of expected conditions to chain.
 *
 * @return {!function} An expected condition that returns a promise which
 *     evaluates to the result of the logical chain.
 */
ExpectedConditions.prototype.logicalChain_ = function(defaultRet, fns) {
  var self = this;
  return function() {
    if (fns.length === 0) {
      return defaultRet;
    }
    var fn = fns[0];
    return fn().then(function(bool) {
      if (bool === defaultRet) {
        return self.logicalChain_(defaultRet, fns.slice(1))();
      } else {
        return !defaultRet;
      }
    });
  };
};

/**
 * Chain a number of expected conditions using logical_and, short circuiting
 * at the first expected condition that evaluates to false.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * var titleContainsFoo = EC.titleContains('Foo');
 * var titleIsNotFooBar = EC.not(EC.titleIs('FooBar'));
 * // Waits for title to contain 'Foo', but is not 'FooBar'
 * browser.wait(EC.and(titleContainsFoo, titleIsNotFooBar), 5000);
 *
 * @param {Array.<Function>} fns An array of expected conditions to 'and' together.
 *
 * @return {!function} An expected condition that returns a promise which
 *     evaluates to the result of the logical and.
 */
ExpectedConditions.prototype.and = function() {
  var args = Array.prototype.slice.call(arguments);
  return this.logicalChain_(true, args);
};

/**
 * Chain a number of expected conditions using logical_or, short circuiting
 * at the first expected condition that evaluates to true.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * var titleContainsFoo = EC.titleContains('Foo');
 * var titleContainsBar = EC.titleContains('Bar');
 * // Waits for title to contain either 'Foo' or 'Bar'
 * browser.wait(EC.or(titleContainsFoo, titleContainsBar), 5000);
 *
 * @param {Array.<Function>} fns An array of expected conditions to 'or' together.
 *
 * @return {!function} An expected condition that returns a promise which
 *     evaluates to the result of the logical or.
 */
ExpectedConditions.prototype.or = function() {
  var args = Array.prototype.slice.call(arguments);
  return this.logicalChain_(false, args);
};

/**
 * Expect an alert to be present.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for an alert pops up.
 * browser.wait(EC.alertIsPresent(), 5000);
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether an alert is present.
 */
ExpectedConditions.prototype.alertIsPresent = function() {
  return function() {
    return browser.switchTo().alert().then(function() {
      return true;
    }, function(err) {
      if (err.code == webdriver.error.ErrorCode.NO_SUCH_ALERT) {
        return false;
      } else {
        throw err;
      }
    });
  };
};

/**
 * An Expectation for checking an element is visible and enabled such that you
 * can click it.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the element with id 'abc' to be clickable.
 * browser.wait(EC.elementToBeClickable($('#abc')), 5000);
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is clickable.
 */
ExpectedConditions.prototype.elementToBeClickable = function(elementFinder) {
  return this.and(
      this.visibilityOf(elementFinder),
      elementFinder.isEnabled.bind(elementFinder));
};

/**
 * An expectation for checking if the given text is present in the
 * element. Returns false if the elementFinder does not find an element.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the element with id 'abc' to contain the text 'foo'.
 * browser.wait(EC.textToBePresentInElement($('#abc'), 'foo'), 5000);
 *
 * @param {!ElementFinder} elementFinder The element to check
 * @param {!string} text The text to verify against
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the text is present in the element.
 */
ExpectedConditions.prototype.textToBePresentInElement = function(elementFinder, text) {
  var hasText = function() {
    return elementFinder.getText().then(function(actualText) {
      return actualText.indexOf(text) > -1;
    });
  };
  return this.and(this.presenceOf(elementFinder), hasText);
};

/**
 * An expectation for checking if the given text is present in the element’s
 * value. Returns false if the elementFinder does not find an element.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the element with id 'myInput' to contain the input 'foo'.
 * browser.wait(EC.textToBePresentInElementValue($('#myInput'), 'foo'), 5000);
 *
 * @param {!ElementFinder} elementFinder The element to check
 * @param {!string} text The text to verify against
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the text is present in the element's value.
 */
ExpectedConditions.prototype.textToBePresentInElementValue = function(elementFinder, text) {
  var hasText = function() {
    return elementFinder.getAttribute('value').then(function(actualText) {
      return actualText.indexOf(text) > -1;
    });
  };
  return this.and(this.presenceOf(elementFinder), hasText);
};

/**
 * An expectation for checking that the title contains a case-sensitive
 * substring.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the title to contain 'foo'.
 * browser.wait(EC.titleContains('foo'), 5000);
 *
 * @param {!string} title The fragment of title expected
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the title contains the string.
 */
ExpectedConditions.prototype.titleContains = function(title) {
  return function() {
    return browser.getTitle().then(function(actualTitle) {
      return actualTitle.indexOf(title) > -1;
    });
  };
};

/**
 * An expectation for checking the title of a page.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the title to be 'foo'.
 * browser.wait(EC.titleIs('foo'), 5000);
 *
 * @param {!string} title The expected title, which must be an exact match.
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the title equals the string.
 */
ExpectedConditions.prototype.titleIs = function(title) {
  return function() {
    return browser.getTitle().then(function(actualTitle) {
      return actualTitle === title;
    });
  };
};

/**
 * An expectation for checking that an element is present on the DOM
 * of a page. This does not necessarily mean that the element is visible.
 * This is the opposite of 'stalenessOf'.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the element with id 'abc' to be present on the dom.
 * browser.wait(EC.presenceOf($('#abc')), 5000);
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is present.
 */
ExpectedConditions.prototype.presenceOf = function(elementFinder) {
  return elementFinder.isPresent.bind(elementFinder);
};

/**
 * An expectation for checking that an element is not attached to the DOM
 * of a page. This is the opposite of 'presenceOf'.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the element with id 'abc' to be no longer present on the dom.
 * browser.wait(EC.stalenessOf($('#abc')), 5000);
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is stale.
 */
ExpectedConditions.prototype.stalenessOf = function(elementFinder) {
  return this.not(this.presenceOf(elementFinder));
};

/**
 * An expectation for checking that an element is present on the DOM of a
 * page and visible. Visibility means that the element is not only displayed
 * but also has a height and width that is greater than 0. This is the opposite
 * of 'invisibilityOf'.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the element with id 'abc' to be visible on the dom.
 * browser.wait(EC.visibilityOf($('#abc')), 5000);
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is visible.
 */
ExpectedConditions.prototype.visibilityOf = function(elementFinder) {
  return this.and(
    this.presenceOf(elementFinder),
    elementFinder.isDisplayed.bind(elementFinder));
};

/**
 * An expectation for checking that an element is either invisible or not
 * present on the DOM. This is the opposite of 'visibilityOf'.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the element with id 'abc' to be no longer visible on the dom.
 * browser.wait(EC.invisibilityOf($('#abc')), 5000);
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is invisible.
 */
ExpectedConditions.prototype.invisibilityOf = function(elementFinder) {
  return this.not(this.visibilityOf(elementFinder));
};

/**
 * An expectation for checking the selection is selected.
 *
 * @example
 * var EC = protractor.ExpectedConditions;
 * // Waits for the element with id 'myCheckbox' to be selected.
 * browser.wait(EC.elementToBeSelected($('#myCheckbox')), 5000);
 *
 * @param {!ElementFinder} elementFinder The element to check
 *
 * @return {!function} An expected condition that returns a promise
 *     representing whether the element is selected.
 */
ExpectedConditions.prototype.elementToBeSelected = function(elementFinder) {
  return this.and(
    this.presenceOf(elementFinder),
    elementFinder.isSelected.bind(elementFinder));
};

module.exports = ExpectedConditions;

<|endoftext|>


<commit_before>'use strict';

// MODULES //

var resolve = require( 'path' ).resolve;
var rule = require( 'unified-lint-rule' );
var visit = require( 'unist-util-visit' );
var Engine = require( 'eslint' ).CLIEngine;
var cwd = require( '@stdlib/utils/cwd' );
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
var startsWith = require( '@stdlib/string/starts-with' );
var endsWith = require( '@stdlib/string/ends-with' );
var trim = require( '@stdlib/string/trim' );

// VARIABLES //

var COMMENT_START = '<!--';
var COMMENT_END = '-->';
var ESLINT_PREFIX = 'eslint';

// FUNCTIONS //

/**
* Converts an HTML comment containing ESLint configuration to a JavaScript comment.
*
* @private
* @param {string} html - text content of an HTML AST node
* @returns {(string|null)} null or a JavaScript comment
*/
function transformHTML( html ) {
	if (
		!startsWith( html, COMMENT_START ) ||
		!endsWith( html, COMMENT_END )
	) {
		return null;
	}
	html = html.slice( COMMENT_START.length, html.length-COMMENT_END.length );
	html = trim( html );
	if ( !startsWith( html, ESLINT_PREFIX) ) {
		return null;
	}
	return '/* ' + html + ' */';
} // end FUNCTION transformHTML()

// MAIN //

/**
* Lints Markdown code blocks using ESLint.
*
* @param {Object} tree - abstract syntax tree (AST)
* @param {Object} file - file being lint
* @param {Object} options - options
* @param {string} [options.config] - path to an ESLint configuration file
* @param {string} [options.ignorePath] - path to an ESLint ignore file
*
* @example
* var remark = require( 'remark' );
* var linter = remark().use( lint ).processSync;
*
* var vfile = linter( '``` javascript\nvar beep = \'boop\';\n'```' );
*/
function lint( tree, file, options ) {
	var opts;
	var cli;

	opts = {};
	if ( hasOwnProp( options, 'config' ) ) {
		opts.configFile = resolve( cwd(), options.config );
	}
	if ( hasOwnProp( options, 'ignorePath' ) ) {
		opts.ignorePath = resolve( cwd(), options.ignorePath );
	}
	cli = new Engine( opts );
	visit( tree, 'code', onNode );

	/**
	* Callback invoked upon encountering a code block.
	*
	* @private
	* @param {Object} node - AST node
	* @param {number} idx - position of node in parent
	* @param {Object} parent - parent AST node
	* @returns {void}
	*/
	function onNode( node, idx, parent ) {
		var comments;
		var comment;
		var report;
		var result;
		var offset;
		var prev;
		var code;
		var msg;
		var str;
		var i;
		var j;

		if ( node.lang === 'javascript' || node.lang === 'js' ) {
			// Look for HTML comments immediately preceding a code block which may contain ESLint configuration...
			idx -= 1;
			prev = parent.children[ idx ];
			comments = [];
			while ( prev && prev.type === 'html' ) {
				comment = transformHTML( prev.value );
				if ( !comment ) {
					break;
				}
				if ( comment === '/* eslint-skip */' ) {
					return;
				}
				comments.unshift( comment );
				idx -= 1;
				prev = parent.children[ idx ];
			}
			offset = comments.length;
			comments.push( node.value );
			code = comments.join( '\n' );

			// Lint the code block...
			report = cli.executeOnText( code );
			for ( i = 0; i < report.results.length; i++ ) {
				result = report.results[ i ];
				result.filePath = file.path || result.filePath;
				for ( j = 0; j < result.messages.length; j++ ) {
					msg = result.messages[ j ];
					str = '';
					str += (msg.line-offset) + ':' + msg.column;
					str += '   ';
					if ( msg.severity === 2 ) {
						str += 'error';
					} else {
						str += 'warning';
					}
					str += '   ';
					str += msg.message;
					str += '   ';
					str += msg.ruleId;
					file.message( str, node );
				}
			}
		}
	} // end FUNCTION onNode()
} // end FUNCTION lint()

// EXPORTS //

module.exports = rule( 'remark-lint:eslint', lint );
<commit_msg>Add missing space<commit_after>'use strict';

// MODULES //

var resolve = require( 'path' ).resolve;
var rule = require( 'unified-lint-rule' );
var visit = require( 'unist-util-visit' );
var Engine = require( 'eslint' ).CLIEngine;
var cwd = require( '@stdlib/utils/cwd' );
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
var startsWith = require( '@stdlib/string/starts-with' );
var endsWith = require( '@stdlib/string/ends-with' );
var trim = require( '@stdlib/string/trim' );

// VARIABLES //

var COMMENT_START = '<!--';
var COMMENT_END = '-->';
var ESLINT_PREFIX = 'eslint';

// FUNCTIONS //

/**
* Converts an HTML comment containing ESLint configuration to a JavaScript comment.
*
* @private
* @param {string} html - text content of an HTML AST node
* @returns {(string|null)} null or a JavaScript comment
*/
function transformHTML( html ) {
	if (
		!startsWith( html, COMMENT_START ) ||
		!endsWith( html, COMMENT_END )
	) {
		return null;
	}
	html = html.slice( COMMENT_START.length, html.length-COMMENT_END.length );
	html = trim( html );
	if ( !startsWith( html, ESLINT_PREFIX ) ) {
		return null;
	}
	return '/* ' + html + ' */';
} // end FUNCTION transformHTML()

// MAIN //

/**
* Lints Markdown code blocks using ESLint.
*
* @param {Object} tree - abstract syntax tree (AST)
* @param {Object} file - file being lint
* @param {Object} options - options
* @param {string} [options.config] - path to an ESLint configuration file
* @param {string} [options.ignorePath] - path to an ESLint ignore file
*
* @example
* var remark = require( 'remark' );
* var linter = remark().use( lint ).processSync;
*
* var vfile = linter( '``` javascript\nvar beep = \'boop\';\n'```' );
*/
function lint( tree, file, options ) {
	var opts;
	var cli;

	opts = {};
	if ( hasOwnProp( options, 'config' ) ) {
		opts.configFile = resolve( cwd(), options.config );
	}
	if ( hasOwnProp( options, 'ignorePath' ) ) {
		opts.ignorePath = resolve( cwd(), options.ignorePath );
	}
	cli = new Engine( opts );
	visit( tree, 'code', onNode );

	/**
	* Callback invoked upon encountering a code block.
	*
	* @private
	* @param {Object} node - AST node
	* @param {number} idx - position of node in parent
	* @param {Object} parent - parent AST node
	* @returns {void}
	*/
	function onNode( node, idx, parent ) {
		var comments;
		var comment;
		var report;
		var result;
		var offset;
		var prev;
		var code;
		var msg;
		var str;
		var i;
		var j;

		if ( node.lang === 'javascript' || node.lang === 'js' ) {
			// Look for HTML comments immediately preceding a code block which may contain ESLint configuration...
			idx -= 1;
			prev = parent.children[ idx ];
			comments = [];
			while ( prev && prev.type === 'html' ) {
				comment = transformHTML( prev.value );
				if ( !comment ) {
					break;
				}
				if ( comment === '/* eslint-skip */' ) {
					return;
				}
				comments.unshift( comment );
				idx -= 1;
				prev = parent.children[ idx ];
			}
			offset = comments.length;
			comments.push( node.value );
			code = comments.join( '\n' );

			// Lint the code block...
			report = cli.executeOnText( code );
			for ( i = 0; i < report.results.length; i++ ) {
				result = report.results[ i ];
				result.filePath = file.path || result.filePath;
				for ( j = 0; j < result.messages.length; j++ ) {
					msg = result.messages[ j ];
					str = '';
					str += (msg.line-offset) + ':' + msg.column;
					str += '   ';
					if ( msg.severity === 2 ) {
						str += 'error';
					} else {
						str += 'warning';
					}
					str += '   ';
					str += msg.message;
					str += '   ';
					str += msg.ruleId;
					file.message( str, node );
				}
			}
		}
	} // end FUNCTION onNode()
} // end FUNCTION lint()

// EXPORTS //

module.exports = rule( 'remark-lint:eslint', lint );
<|endoftext|>


<commit_before>/**
 * bootbox.js [v4.x/master branch]
 *
 * http://bootboxjs.com/license.txt
 */
// @see https://github.com/makeusabrew/bootbox/issues/71
window.bootbox = window.bootbox || (function(document, $, undefined) {
  "use strict";

  // the base DOM structure needed to create a modal
  var templates = {
    dialog:
      "
" +
        "
" +
          "
" +
            "

" +
          "
" +
        "
" +
      "
",
    header:
      "
" +
        "

" +
      "
",
    footer:
      "

",
    closeButton:
      "<button type='button' class='bootbox-close-button close'>×</button>",
    form:
      "<form class='bootbox-form'></form>",
    inputs: {
      text:
        "<input class='bootbox-input input-block-level' autocomplete=off type=text />"
    }
  };

  // cache a reference to the jQueryfied body element
  var appendTo = $("body");

  var defaults = {
    // default language
    locale: "en",
    // show backdrop or not
    backdrop: true,
    // animate the modal in/out
    animate: true,
    // additional class string applied to the top level dialog
    className: null,
    // show the modal header or not
    header: false,
    // whether or not to include a close button, if a header is present
    closeButton: true,
    // show the dialog immediately by default
    show: true
  };

  // our public object; augmented after our private API
  var exports = {};

  /**
   * @private
   */
  function _t(key) {
    return locales[defaults.locale][key] || locales.en[key];
  }

  function processCallback(e, dialog, callback) {
    e.preventDefault();

    // by default we assume a callback will get rid of the dialog,
    // although it is given the opportunity to override this

    // so, if the callback can be invoked and it *explicitly returns false*
    // then we'll set a flag to keep the dialog active...
    var preserveDialog = $.isFunction(callback) && callback(e) === false;

    // ... otherwise we'll bin it
    if (!preserveDialog) {
      dialog.modal("hide");
    }
  }

  function getKeyLength(obj) {
    // @TODO defer to Object.keys(x).length if available?
    var k, t = 0;
    for (k in obj) {
      t ++;
    }
    return t;
  }

  function sanitize(options) {
    var buttons;
    var total;
    var keyIndex;

    if (typeof options !== "object") {
      throw new Error("Please supply an object of options");
    }

    if (!options.message) {
      throw new Error("Please specify a message");
    }

    // make sure any supplied options take precedence over defaults
    options = $.extend({}, defaults, options);

    if (!options.buttons) {
      options.buttons = {};
    }

    // we only support Bootstrap's "static" and false backdrop args
    // supporting true would mean you could dismiss the dialog without
    // explicitly interacting with it
    options.backdrop = options.backdrop ? "static" : false;

    buttons = options.buttons;

    total = getKeyLength(buttons);

    keyIndex = 0;

    $.each(buttons, function(key, button) {
      keyIndex ++;

      button = buttons[key];

      if (!button.label) {
        throw new Error("button with key " + key + " requires a label");
      }

      if (!button.className) {
        if (total <= 2 && keyIndex === total) {
          // always add a primary to the main option in a two-button dialog
          button.className = "btn-primary";
        } else {
          button.className = "btn-default";
        }
      }
    });

    return options;
  }

  function mapArguments(args, properties) {
    var argn = args.length;
    var options = {};

    if (argn < 1 || argn > 2) {
      throw new Error("Invalid argument length");
    }

    if (argn === 2 || typeof args[0] === "string") {
      options[properties[0]] = args[0];
      options[properties[1]] = args[1];
    } else {
      options = args[0];
    }

    return options;
  }

  function processOptions(options) {
    // any post-processing of standard options here. for now this
    // is limited to simply choosing whether to show a header or
    // not based on whether the user supplied a title
    options.header = !!options.title;
    return options;
  }

  function mergeArguments(defaults, args, properties) {
    return processOptions(
      $.extend(true, {}, defaults, mapArguments(args, properties))
    );
  }

  function createLabels() {
    var buttons = {};

    for (var i = 0, j = arguments.length; i < j; i++) {
      var argument = arguments[i];
      var key = argument.toLowerCase();
      var value = argument.toUpperCase();

      buttons[key] = {
        label: _t(value)
      };
    }

    return buttons;
  }

  function createButtons() {
    return {
      buttons: createLabels.apply(null, arguments)
    };
  }

  exports.alert = function() {
    var options;

    options = mergeArguments(createButtons("ok"), arguments, ["message", "callback"]);

    if (options.callback && !$.isFunction(options.callback)) {
      throw new Error("alert requires callback property to be a function when provided");
    }

    /**
     * overrides
     */
    options.buttons.ok.callback = options.onEscape = function() {
      if ($.isFunction(options.callback)) {
        return options.callback();
      }
      return true;
    };

    return exports.dialog(options);
  };

  exports.confirm = function() {
    var options;

    options = mergeArguments(createButtons("cancel", "confirm"), arguments, ["message", "callback"]);

    /**
     * overrides; undo anything the user tried to set they shouldn't have
     */
    options.buttons.cancel.callback = options.onEscape = function() {
      return options.callback(false);
    };

    options.buttons.confirm.callback = function() {
      return options.callback(true);
    };

    // confirm specific validation
    if (!$.isFunction(options.callback)) {
      throw new Error("confirm requires a callback");
    }

    return exports.dialog(options);
  };

  exports.prompt = function() {
    var options;
    var defaults;
    var dialog;
    var form;
    var input;
    var shouldShow;

    // we have to create our form first otherwise
    // its value is undefined when gearing up our options
    // @TODO this could be solved by allowing message to
    // be a function instead...
    form = $(templates.form);

    defaults = {
      buttons: createLabels("cancel", "confirm"),
      value: ""
    };

    options = mergeArguments(defaults, arguments, ["title", "callback"]);

    // capture the user's show value; we always set this to false before
    // spawning the dialog to give us a chance to attach some handlers to
    // it, but we need to make sure we respect a preference not to show it
    shouldShow = (options.show === undefined) ? true : options.show;

    /**
     * overrides; undo anything the user tried to set they shouldn't have
     */
    options.message = form;

    options.buttons.cancel.callback = options.onEscape = function() {
      return options.callback(null);
    };

    options.buttons.confirm.callback = function() {
      return options.callback(input.val());
    };

    options.show = false;

    // prompt specific validation
    if (!options.title) {
      throw new Error("prompt requires a title");
    }

    if (!$.isFunction(options.callback)) {
      throw new Error("prompt requires a callback");
    }

    // create the input
    input = $(templates.inputs.text);
    input.val(options.value);

    // now place it in our form
    form.append(input);

    form.on("submit", function(e) {
      e.preventDefault();
      // @TODO can we actually click *the* button object instead?
      // e.g. buttons.confirm.click() or similar
      dialog.find(".btn-primary").click();
    });

    dialog = exports.dialog(options);

    // clear the existing handler focusing the submit button...
    dialog.off("shown.bs.modal");

    // ...and replace it with one focusing our input, if possible
    dialog.on("shown.bs.modal", function() {
      input.focus();
    });

    if (shouldShow === true) {
      dialog.modal("show");
    }

    return dialog;
  };

  exports.dialog = function(options) {
    options = sanitize(options);

    var dialog = $(templates.dialog);
    var body = dialog.find(".modal-body");
    var buttons = options.buttons;
    var buttonStr = "";
    var callbacks = {
      onEscape: options.onEscape
    };

    $.each(buttons, function(key, button) {

      // @TODO I don't like this string appending to itself; bit dirty. Needs reworking
      // can we just build up button elements instead? slower but neater. Then button
      // can just become a template too
      buttonStr += "<button data-bb-handler='" + key + "' type='button' class='btn " + button.className + "'>" + button.label + "</button>";
      callbacks[key] = button.callback;
    })

    body.find(".bootbox-body").html(options.message);

    if (options.animate === true) {
      dialog.addClass("fade");
    }

    if (options.className) {
      dialog.addClass(options.className);
    }

    if (options.header) {
      body.before(templates.header);
    }

    if (options.closeButton) {
      var closeButton = $(templates.closeButton);

      if (options.header) {
        dialog.find(".modal-header").prepend(closeButton);
      } else {
        closeButton.css("margin-top", "-10px").prependTo(body);
      }
    }

    if (options.header && options.title) {
      dialog.find(".modal-title").html(options.title);
    }

    if (buttonStr.length) {
      body.after(templates.footer);
      dialog.find(".modal-footer").html(buttonStr);
    }

    /**
     * Bootstrap event listeners; used handle extra
     * setup & teardown required after the underlying
     * modal has performed certain actions
     */

    dialog.on("hidden.bs.modal", function(e) {
      // ensure we don't accidentally intercept hidden events triggered
      // by children of the current dialog. We shouldn't anymore now BS
      // namespaces its events; but still worth doing
      if (e.target === this) {
        dialog.remove();
      }
    });

    /*
    dialog.on("show.bs.modal", function() {
      // sadly this doesn't work; show is called *just* before
      // the backdrop is added so we'd need a setTimeout hack or
      // otherwise... leaving in as would be nice
      if (options.backdrop) {
        dialog.next(".modal-backdrop").addClass("bootbox-backdrop");
      }
    });
    */

    dialog.on("shown.bs.modal", function() {
      dialog.find(".btn-primary:first").focus();
    });

    /**
     * Bootbox event listeners; experimental and may not last
     * just an attempt to decouple some behaviours from their
     * respective triggers
     */

    dialog.on("escape.close.bb", function(e) {
      if (callbacks.onEscape) {
        processCallback(e, dialog, callbacks.onEscape);
      }
    });

    /**
     * Standard jQuery event listeners; used to handle user
     * interaction with our dialog
     */

    dialog.on("click", ".modal-footer button", function(e) {
      var callbackKey = $(this).data("bb-handler");

      processCallback(e, dialog, callbacks[callbackKey]);

    });

    dialog.on("click", ".bootbox-close-button", function(e) {
      // onEscape might be falsy but that's fine; the fact is
      // if the user has managed to click the close button we
      // have to close the dialog, callback or not
      processCallback(e, dialog, callbacks.onEscape);
    });

    dialog.on("keyup", function(e) {
      if (e.which === 27) {
        dialog.trigger("escape.close.bb");
      }
    });

    // the remainder of this method simply deals with adding our
    // dialogent to the DOM, augmenting it with Bootstrap's modal
    // functionality and then giving the resulting object back
    // to our caller

    appendTo.append(dialog);

    dialog.modal({
      backdrop: options.backdrop,
      keyboard: false,
      show: false
    });

    if (options.show) {
      dialog.modal("show");
    }

    // @TODO should we return the raw element here or should
    // we wrap it in an object on which we can expose some neater
    // methods, e.g. var d = bootbox.alert(); d.hide(); instead
    // of d.modal("hide");

   /*
    function BBDialog(elem) {
      this.elem = elem;
    }

    BBDialog.prototype = {
      hide: function() {
        return this.elem.modal("hide");
      },
      show: function() {
        return this.elem.modal("show");
      }
    };
    */

    return dialog;

  };

  exports.setDefaults = function(values) {
    $.extend(defaults, values);
  };

  exports.hideAll = function() {
    $(".bootbox").modal("hide");
  };

  /**
   * standard locales. Please add more according to ISO 639-1 standard. Multiple language variants are
   * unlikely to be required. If this gets too large it can be split out into separate JS files.
   */
  var locales = {
    br : {
      OK      : "OK",
      CANCEL  : "Cancelar",
      CONFIRM : "Sim"
    },
    da : {
      OK      : "OK",
      CANCEL  : "Annuller",
      CONFIRM : "Accepter"
    },
    de : {
      OK      : "OK",
      CANCEL  : "Abbrechen",
      CONFIRM : "Akzeptieren"
    },
    en : {
      OK      : "OK",
      CANCEL  : "Cancel",
      CONFIRM : "OK"
    },
    es : {
      OK      : "OK",
      CANCEL  : "Cancelar",
      CONFIRM : "Aceptar"
    },
    fi : {
      OK      : "OK",
      CANCEL  : "Peruuta",
      CONFIRM : "OK"
    },
    fr : {
      OK      : "OK",
      CANCEL  : "Annuler",
      CONFIRM : "D'accord"
    },
    it : {
      OK      : "OK",
      CANCEL  : "Annulla",
      CONFIRM : "Conferma"
    },
    nl : {
      OK      : "OK",
      CANCEL  : "Annuleren",
      CONFIRM : "Accepteren"
    },
    pl : {
      OK      : "OK",
      CANCEL  : "Anuluj",
      CONFIRM : "Potwierdź"
    },
    ru : {
      OK      : "OK",
      CANCEL  : "Отмена",
      CONFIRM : "Применить"
    },
    zh_CN : {
      OK      : "OK",
      CANCEL  : "取消",
      CONFIRM : "确认"
    },
    zh_TW : {
      OK      : "OK",
      CANCEL  : "取消",
      CONFIRM : "確認"
    }
  };

  return exports;

}(document, window.jQuery));
<commit_msg>provide wrapped each method with numerical index<commit_after>/**
 * bootbox.js [v4.x/master branch]
 *
 * http://bootboxjs.com/license.txt
 */
// @see https://github.com/makeusabrew/bootbox/issues/71
window.bootbox = window.bootbox || (function(document, $, undefined) {
  "use strict";

  // the base DOM structure needed to create a modal
  var templates = {
    dialog:
      "
" +
        "
" +
          "
" +
            "

" +
          "
" +
        "
" +
      "
",
    header:
      "
" +
        "

" +
      "
",
    footer:
      "

",
    closeButton:
      "<button type='button' class='bootbox-close-button close'>×</button>",
    form:
      "<form class='bootbox-form'></form>",
    inputs: {
      text:
        "<input class='bootbox-input input-block-level' autocomplete=off type=text />"
    }
  };

  // cache a reference to the jQueryfied body element
  var appendTo = $("body");

  var defaults = {
    // default language
    locale: "en",
    // show backdrop or not
    backdrop: true,
    // animate the modal in/out
    animate: true,
    // additional class string applied to the top level dialog
    className: null,
    // show the modal header or not
    header: false,
    // whether or not to include a close button, if a header is present
    closeButton: true,
    // show the dialog immediately by default
    show: true
  };

  // our public object; augmented after our private API
  var exports = {};

  /**
   * @private
   */
  function _t(key) {
    return locales[defaults.locale][key] || locales.en[key];
  }

  function processCallback(e, dialog, callback) {
    e.preventDefault();

    // by default we assume a callback will get rid of the dialog,
    // although it is given the opportunity to override this

    // so, if the callback can be invoked and it *explicitly returns false*
    // then we'll set a flag to keep the dialog active...
    var preserveDialog = $.isFunction(callback) && callback(e) === false;

    // ... otherwise we'll bin it
    if (!preserveDialog) {
      dialog.modal("hide");
    }
  }

  function getKeyLength(obj) {
    // @TODO defer to Object.keys(x).length if available?
    var k, t = 0;
    for (k in obj) {
      t ++;
    }
    return t;
  }

  function each(collection, iterator) {
    var index = 0;
    $.each(collection, function(key, value) {
      iterator(key, value, index++);
    });
  }

  function sanitize(options) {
    var buttons;
    var total;

    if (typeof options !== "object") {
      throw new Error("Please supply an object of options");
    }

    if (!options.message) {
      throw new Error("Please specify a message");
    }

    // make sure any supplied options take precedence over defaults
    options = $.extend({}, defaults, options);

    if (!options.buttons) {
      options.buttons = {};
    }

    // we only support Bootstrap's "static" and false backdrop args
    // supporting true would mean you could dismiss the dialog without
    // explicitly interacting with it
    options.backdrop = options.backdrop ? "static" : false;

    buttons = options.buttons;

    total = getKeyLength(buttons);

    each(buttons, function(key, button, index) {

      if (!button.label) {
        throw new Error("button with key " + key + " requires a label");
      }

      if (!button.className) {
        if (total <= 2 && index === total-1) {
          // always add a primary to the main option in a two-button dialog
          button.className = "btn-primary";
        } else {
          button.className = "btn-default";
        }
      }
    });

    return options;
  }

  function mapArguments(args, properties) {
    var argn = args.length;
    var options = {};

    if (argn < 1 || argn > 2) {
      throw new Error("Invalid argument length");
    }

    if (argn === 2 || typeof args[0] === "string") {
      options[properties[0]] = args[0];
      options[properties[1]] = args[1];
    } else {
      options = args[0];
    }

    return options;
  }

  function processOptions(options) {
    // any post-processing of standard options here. for now this
    // is limited to simply choosing whether to show a header or
    // not based on whether the user supplied a title
    options.header = !!options.title;
    return options;
  }

  function mergeArguments(defaults, args, properties) {
    return processOptions(
      $.extend(true, {}, defaults, mapArguments(args, properties))
    );
  }

  function createLabels() {
    var buttons = {};

    for (var i = 0, j = arguments.length; i < j; i++) {
      var argument = arguments[i];
      var key = argument.toLowerCase();
      var value = argument.toUpperCase();

      buttons[key] = {
        label: _t(value)
      };
    }

    return buttons;
  }

  function createButtons() {
    return {
      buttons: createLabels.apply(null, arguments)
    };
  }

  exports.alert = function() {
    var options;

    options = mergeArguments(createButtons("ok"), arguments, ["message", "callback"]);

    if (options.callback && !$.isFunction(options.callback)) {
      throw new Error("alert requires callback property to be a function when provided");
    }

    /**
     * overrides
     */
    options.buttons.ok.callback = options.onEscape = function() {
      if ($.isFunction(options.callback)) {
        return options.callback();
      }
      return true;
    };

    return exports.dialog(options);
  };

  exports.confirm = function() {
    var options;

    options = mergeArguments(createButtons("cancel", "confirm"), arguments, ["message", "callback"]);

    /**
     * overrides; undo anything the user tried to set they shouldn't have
     */
    options.buttons.cancel.callback = options.onEscape = function() {
      return options.callback(false);
    };

    options.buttons.confirm.callback = function() {
      return options.callback(true);
    };

    // confirm specific validation
    if (!$.isFunction(options.callback)) {
      throw new Error("confirm requires a callback");
    }

    return exports.dialog(options);
  };

  exports.prompt = function() {
    var options;
    var defaults;
    var dialog;
    var form;
    var input;
    var shouldShow;

    // we have to create our form first otherwise
    // its value is undefined when gearing up our options
    // @TODO this could be solved by allowing message to
    // be a function instead...
    form = $(templates.form);

    defaults = {
      buttons: createLabels("cancel", "confirm"),
      value: ""
    };

    options = mergeArguments(defaults, arguments, ["title", "callback"]);

    // capture the user's show value; we always set this to false before
    // spawning the dialog to give us a chance to attach some handlers to
    // it, but we need to make sure we respect a preference not to show it
    shouldShow = (options.show === undefined) ? true : options.show;

    /**
     * overrides; undo anything the user tried to set they shouldn't have
     */
    options.message = form;

    options.buttons.cancel.callback = options.onEscape = function() {
      return options.callback(null);
    };

    options.buttons.confirm.callback = function() {
      return options.callback(input.val());
    };

    options.show = false;

    // prompt specific validation
    if (!options.title) {
      throw new Error("prompt requires a title");
    }

    if (!$.isFunction(options.callback)) {
      throw new Error("prompt requires a callback");
    }

    // create the input
    input = $(templates.inputs.text);
    input.val(options.value);

    // now place it in our form
    form.append(input);

    form.on("submit", function(e) {
      e.preventDefault();
      // @TODO can we actually click *the* button object instead?
      // e.g. buttons.confirm.click() or similar
      dialog.find(".btn-primary").click();
    });

    dialog = exports.dialog(options);

    // clear the existing handler focusing the submit button...
    dialog.off("shown.bs.modal");

    // ...and replace it with one focusing our input, if possible
    dialog.on("shown.bs.modal", function() {
      input.focus();
    });

    if (shouldShow === true) {
      dialog.modal("show");
    }

    return dialog;
  };

  exports.dialog = function(options) {
    options = sanitize(options);

    var dialog = $(templates.dialog);
    var body = dialog.find(".modal-body");
    var buttons = options.buttons;
    var buttonStr = "";
    var callbacks = {
      onEscape: options.onEscape
    };

    each(buttons, function(key, button) {

      // @TODO I don't like this string appending to itself; bit dirty. Needs reworking
      // can we just build up button elements instead? slower but neater. Then button
      // can just become a template too
      buttonStr += "<button data-bb-handler='" + key + "' type='button' class='btn " + button.className + "'>" + button.label + "</button>";
      callbacks[key] = button.callback;
    });

    body.find(".bootbox-body").html(options.message);

    if (options.animate === true) {
      dialog.addClass("fade");
    }

    if (options.className) {
      dialog.addClass(options.className);
    }

    if (options.header) {
      body.before(templates.header);
    }

    if (options.closeButton) {
      var closeButton = $(templates.closeButton);

      if (options.header) {
        dialog.find(".modal-header").prepend(closeButton);
      } else {
        closeButton.css("margin-top", "-10px").prependTo(body);
      }
    }

    if (options.header && options.title) {
      dialog.find(".modal-title").html(options.title);
    }

    if (buttonStr.length) {
      body.after(templates.footer);
      dialog.find(".modal-footer").html(buttonStr);
    }

    /**
     * Bootstrap event listeners; used handle extra
     * setup & teardown required after the underlying
     * modal has performed certain actions
     */

    dialog.on("hidden.bs.modal", function(e) {
      // ensure we don't accidentally intercept hidden events triggered
      // by children of the current dialog. We shouldn't anymore now BS
      // namespaces its events; but still worth doing
      if (e.target === this) {
        dialog.remove();
      }
    });

    /*
    dialog.on("show.bs.modal", function() {
      // sadly this doesn't work; show is called *just* before
      // the backdrop is added so we'd need a setTimeout hack or
      // otherwise... leaving in as would be nice
      if (options.backdrop) {
        dialog.next(".modal-backdrop").addClass("bootbox-backdrop");
      }
    });
    */

    dialog.on("shown.bs.modal", function() {
      dialog.find(".btn-primary:first").focus();
    });

    /**
     * Bootbox event listeners; experimental and may not last
     * just an attempt to decouple some behaviours from their
     * respective triggers
     */

    dialog.on("escape.close.bb", function(e) {
      if (callbacks.onEscape) {
        processCallback(e, dialog, callbacks.onEscape);
      }
    });

    /**
     * Standard jQuery event listeners; used to handle user
     * interaction with our dialog
     */

    dialog.on("click", ".modal-footer button", function(e) {
      var callbackKey = $(this).data("bb-handler");

      processCallback(e, dialog, callbacks[callbackKey]);

    });

    dialog.on("click", ".bootbox-close-button", function(e) {
      // onEscape might be falsy but that's fine; the fact is
      // if the user has managed to click the close button we
      // have to close the dialog, callback or not
      processCallback(e, dialog, callbacks.onEscape);
    });

    dialog.on("keyup", function(e) {
      if (e.which === 27) {
        dialog.trigger("escape.close.bb");
      }
    });

    // the remainder of this method simply deals with adding our
    // dialogent to the DOM, augmenting it with Bootstrap's modal
    // functionality and then giving the resulting object back
    // to our caller

    appendTo.append(dialog);

    dialog.modal({
      backdrop: options.backdrop,
      keyboard: false,
      show: false
    });

    if (options.show) {
      dialog.modal("show");
    }

    // @TODO should we return the raw element here or should
    // we wrap it in an object on which we can expose some neater
    // methods, e.g. var d = bootbox.alert(); d.hide(); instead
    // of d.modal("hide");

   /*
    function BBDialog(elem) {
      this.elem = elem;
    }

    BBDialog.prototype = {
      hide: function() {
        return this.elem.modal("hide");
      },
      show: function() {
        return this.elem.modal("show");
      }
    };
    */

    return dialog;

  };

  exports.setDefaults = function(values) {
    $.extend(defaults, values);
  };

  exports.hideAll = function() {
    $(".bootbox").modal("hide");
  };

  /**
   * standard locales. Please add more according to ISO 639-1 standard. Multiple language variants are
   * unlikely to be required. If this gets too large it can be split out into separate JS files.
   */
  var locales = {
    br : {
      OK      : "OK",
      CANCEL  : "Cancelar",
      CONFIRM : "Sim"
    },
    da : {
      OK      : "OK",
      CANCEL  : "Annuller",
      CONFIRM : "Accepter"
    },
    de : {
      OK      : "OK",
      CANCEL  : "Abbrechen",
      CONFIRM : "Akzeptieren"
    },
    en : {
      OK      : "OK",
      CANCEL  : "Cancel",
      CONFIRM : "OK"
    },
    es : {
      OK      : "OK",
      CANCEL  : "Cancelar",
      CONFIRM : "Aceptar"
    },
    fi : {
      OK      : "OK",
      CANCEL  : "Peruuta",
      CONFIRM : "OK"
    },
    fr : {
      OK      : "OK",
      CANCEL  : "Annuler",
      CONFIRM : "D'accord"
    },
    it : {
      OK      : "OK",
      CANCEL  : "Annulla",
      CONFIRM : "Conferma"
    },
    nl : {
      OK      : "OK",
      CANCEL  : "Annuleren",
      CONFIRM : "Accepteren"
    },
    pl : {
      OK      : "OK",
      CANCEL  : "Anuluj",
      CONFIRM : "Potwierdź"
    },
    ru : {
      OK      : "OK",
      CANCEL  : "Отмена",
      CONFIRM : "Применить"
    },
    zh_CN : {
      OK      : "OK",
      CANCEL  : "取消",
      CONFIRM : "确认"
    },
    zh_TW : {
      OK      : "OK",
      CANCEL  : "取消",
      CONFIRM : "確認"
    }
  };

  return exports;

}(document, window.jQuery));
<|endoftext|>


<commit_before>import React, {Component, Fragment, createRef} from 'react';
import round from 'lodash/round';

import Table from 'src/Table';
import Switcher from 'src/Switcher';
import IconButton from 'src/IconButton';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import CircularLoading from 'src/CircularLoading';
import RaisedButton from 'src/RaisedButton';
import MaterialTextField from 'src/MaterialTextField';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Table.json';

import Util from 'vendors/Util';

import 'scss/containers/app/modules/layout/TableExamples.scss';

const LOADING_SYMBOL = Symbol('LOADING_SYMBOL');

class TableExamples extends Component {

    constructor(props) {

        super(props);

        this.tableRef = createRef();

        this.state = {
            data: this.generateData(),
            loadingData: null,
            sorting: null,
            filter: '',
            footVisible: true
        };

        this.columns = [{
            headRenderer: 'ID',
            bodyRenderer: rowDate => rowDate[LOADING_SYMBOL] ?
                <CircularLoading/> : rowDate.id,
            footRenderer: 'Total',
            sortable: true,
            sortingProp: 'id'
        }, {
            width: 300,
            noWrap: true,
            headRenderer: 'Name',
            bodyRenderer: rowDate => rowDate.firstName && rowDate.lastName ?
                `${rowDate.firstName} ${rowDate.lastName}` : '',
            sortable: true,
            sortingProp: 'firstName'
        }, {
            align: Table.Align.RIGHT,
            noWrap: true,
            headRenderer: 'Age',
            bodyRenderer: rowDate => rowDate.age,
            footRenderer: this.state.data && this.state.data.length > 0 ? () =>
                    <Fragment>

Average

{this.state.data.reduce((a, b) => a + b.age, 0) / this.state.data.length}

                    </Fragment>
                :
                null,
            sortable: true,
            sortingProp: 'age'
        }, {
            headRenderer: 'Other Column',
            headAlign: Table.Align.CENTER,
            children: [{
                width: 300,
                headRenderer: 'Other Column 1',
                bodyRenderer: rowDate => rowDate.other ? `${rowDate.other} 1` : ''
            }, {
                width: 300,
                headRenderer: 'Other Column 2',
                bodyRenderer: rowDate => rowDate.other ? `${rowDate.other} 2` : ''
            }, {
                width: 300,
                headRenderer: 'Other Column 3',
                bodyRenderer: rowDate => rowDate.other ? `${rowDate.other} 3` : ''
            }, {
                width: 300,
                headRenderer: 'Other Column 4',
                bodyRenderer: rowDate => rowDate.other ? `${rowDate.other} 4` : ''
            }]
        }, {
            align: Table.Align.RIGHT,
            noWrap: true,
            headRenderer: 'Deposit',
            bodyRenderer: rowDate => rowDate.deposit ? `$${rowDate.deposit}` : '',
            footRenderer: this.state.data && this.state.data.length > 0 ? () =>
                    <Fragment>

Sum

${this.state.data.reduce((a, b) => round(a + b.deposit, 2), 0)}

                    </Fragment>
                :
                null,
            sortable: true,
            sortingProp: 'deposit'
        }, {
            headRenderer: 'Status',
            bodyRenderer: rowData => rowData[LOADING_SYMBOL] ?
                null
                :
                <Switcher value={!rowData.disabled}
                          size="small"
                          onClick={e => e.stopPropagation()}/>
        }, {
            headRenderer: 'Action',
            bodyRenderer: rowData => rowData[LOADING_SYMBOL] ?
                null
                :
                <IconButton iconCls="fas fa-trash-alt"
                            onClick={() => this.deleteRow(rowData.id)}/>
        }];

        this.pageSizes = [{
            value: 10,
            text: '10 / page'
        }, {
            value: 20,
            text: '20 / page'
        }, {
            value: 30,
            text: '30 / page'
        }, {
            value: 40,
            text: '40 / page'
        }, {
            value: 50,
            text: '50 / page'
        }];

    }

    getFixedColumns = () => {
        return this.columns.map(column => {
            if (['ID', 'Name'].includes(column.headRenderer)) {
                return {
                    fixed: Table.Fixed.LEFT,
                    ...column
                };
            } else if (['Status', 'Action'].includes(column.headRenderer)) {
                return {
                    fixed: Table.Fixed.RIGHT,
                    ...column
                };
            }
            return column;
        });
    };

    generateData = (size = 100, base = '', expanded = true) => {

        let data = [];
        for (let i = 0; i < size; i++) {

            const id = `${base ? `${base}-` : ''}${i}`,
                item = {
                    id,
                    firstName: `firstName${id}`,
                    lastName: `lastName${id}`,
                    age: Math.floor(Math.random() * 100),
                    deposit: round(Math.random() * 1000000, 2),
                    other: 'Other Content'
                };

            if (expanded && id.split('-').pop() === '0') {
                item.children = [{
                    [LOADING_SYMBOL]: true,
                    disabled: true
                }];
            }

            data.push(item);

        }

        return data;

    };

    deleteRow = id => {

        const {data} = this.state,
            newData = data.filter(item => item.id !== id);

        this.setState({
            data: newData
        });

    };

    handleSortChange = sorting => {
        this.setState({
            sorting
        });
        console.log('Sort Change Value: ', sorting);
    };

    handlePaginationChange = ({page, pageSize}) => {
        console.log(`page: ${page}, pageSize: ${pageSize}`);
    };

    handleSelect = (rowData, rowIndex, value) => {
        console.log('Select Value: ', rowData);
    };

    handleDeselect = (rowData, rowIndex, value) => {
        console.log('Deselect Value: ', rowData);
    };

    handleSelectAll = value => {
        console.log('Select All Value: ', value);
    };

    handleSeselectAll = value => {
        console.log('Deselect All Value: ', value);
    };

    handleChange = value => {
        console.log('Changed Value: ', value);
    };

    handleExpand = rowData => {

        console.log('Expand: ', rowData);

        const {data} = this.state;

        if (!rowData || !data || !rowData.children[0][LOADING_SYMBOL]) {
            return;
        }

        setTimeout(() => {

            Util.postOrderTraverse({
                children: data
            }, node => {
                if (node && node.id === rowData.id) {
                    node.children = this.generateData(10, node.id);
                    return false;
                }
            });

            this.setState({
                data
            });

        }, 1000);

    };

    handleCollapse = rowData => {
        console.log('Collapse: ', rowData);
    };

    collapseAllRows = () => {
        this.tableRef && this.tableRef.current && this.tableRef.current.collapseAllRows();
    };

    toggleFoot = () => {
        this.setState({
            footVisible: !this.state.footVisible
        });
    };

    handleFilter = filter => {
        this.setState({
            filter
        });
    };

    filterData = (data = this.state.data) => {

        const {filter} = this.state;

        if (!filter || !data) {
            return data;
        }

        return data.filter(item => item && (
            (item.firstName && item.firstName.toUpperCase().includes(filter.toUpperCase()))
            ||
            (item.lastName && item.lastName.toUpperCase().includes(filter.toUpperCase()))
        ));

    };

    componentDidMount() {
        setTimeout(() => {
            this.setState({
                loadingData: this.generateData()
            });
        }, 3000);
    }

    render() {

        const {data, loadingData, sorting, filter, footVisible} = this.state,
            // filteredData = this.filterData(data),
            filteredLoadingData = this.filterData(loadingData);

        return (

Table

                    Table
                     are used to display data and to organize it.

Examples

                {/*<Widget>*/}

                {/*    <WidgetHeader className="example-header"*/}
                {/*                  title="Normal"/>*/}

                {/*
*/}
                {/*
*/}

                {/*
A simple Table example.
*/}

                {/*            <Table className="example-table"*/}
                {/*                   columns={this.columns}*/}
                {/*                   data={data}*/}
                {/*                   onSortChange={this.handleSortChange}*/}
                {/*                   onPaginationChange={this.handlePaginationChange}*/}
                {/*                   onExpand={this.handleExpand}*/}
                {/*                   onCollapse={this.handleCollapse}*/}
                {/*                   onChange={this.handleChange}*/}
                {/*                   onSelect={this.handleSelect}*/}
                {/*                   onSelectAll={this.handleSelectAll}*/}
                {/*                   onDeselect={this.handleDeselect}*/}
                {/*                   onDeselectAll={this.handleSeselectAll}/>*/}

                {/*
*/}
                {/*
*/}

                {/*</Widget>*/}

                {/*<Widget>*/}

                {/*    <WidgetHeader className="example-header"*/}
                {/*                  title="Fix Head & Foot"/>*/}

                {/*
*/}
                {/*
*/}

                {/*
*/}
                {/*                You can config isHeadFixed to fix the Head, */}
                {/*                and config isFootFixed to fix the Foot.*/}
                {/*
*/}

                {/*            <Table className="example-table"*/}
                {/*                   columns={this.columns}*/}
                {/*                   data={data}*/}
                {/*                   isHeadFixed={true}*/}
                {/*                   isFootFixed={true}*/}
                {/*                   scroll={{*/}
                {/*                       maxHeight: 320*/}
                {/*                   }}*/}
                {/*                   onSortChange={this.handleSortChange}*/}
                {/*                   onPaginationChange={this.handlePaginationChange}*/}
                {/*                   onExpand={this.handleExpand}*/}
                {/*                   onCollapse={this.handleCollapse}*/}
                {/*                   onChange={this.handleChange}*/}
                {/*                   onSelect={this.handleSelect}*/}
                {/*                   onSelectAll={this.handleSelectAll}*/}
                {/*                   onDeselect={this.handleDeselect}*/}
                {/*                   onDeselectAll={this.handleSeselectAll}/>*/}

                {/*
*/}
                {/*
*/}

                {/*</Widget>*/}

                {/*<Widget>*/}

                {/*    <WidgetHeader className="example-header"*/}
                {/*                  title="Fix Columns"/>*/}

                {/*
*/}
                {/*
*/}

                {/*
*/}
                {/*                You can config fixed in columns to fix the column */}
                {/*                Left or Right.*/}
                {/*
*/}

                {/*            <Table className="example-table"*/}
                {/*                   columns={this.getFixedColumns()}*/}
                {/*                   data={data}*/}
                {/*                   scroll={{*/}
                {/*                       width: 1200*/}
                {/*                   }}*/}
                {/*                   onSortChange={this.handleSortChange}*/}
                {/*                   onPaginationChange={this.handlePaginationChange}*/}
                {/*                   onExpand={this.handleExpand}*/}
                {/*                   onCollapse={this.handleCollapse}*/}
                {/*                   onChange={this.handleChange}*/}
                {/*                   onSelect={this.handleSelect}*/}
                {/*                   onSelectAll={this.handleSelectAll}*/}
                {/*                   onDeselect={this.handleDeselect}*/}
                {/*                   onDeselectAll={this.handleSeselectAll}/>*/}

                {/*
*/}
                {/*
*/}

                {/*</Widget>*/}

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Fix Head, Foot and Columns"/>

                                <RaisedButton className="action-button"
                                              value="Collapse All Rows"
                                              onClick={this.collapseAllRows}/>
                                <RaisedButton className="action-button"
                                              value="Toggle Table Foot"
                                              onClick={this.toggleFoot}/>
                                <MaterialTextField className="filter"
                                                   label="Filter"
                                                   value={filter}
                                                   onChange={this.handleFilter}/>

                                {
                                    filteredLoadingData ?
                                        <Table ref={this.tableRef}
                                               className="example-table"
                                               data={filteredLoadingData}
                                               columns={this.getFixedColumns()}
                                               sorting={sorting}
                                               selectMode={Table.SelectMode.MULTI_SELECT}
                                               isHeadFixed={true}
                                               isFootFixed={true}
                                               isFootHidden={!footVisible || !filteredLoadingData || filteredLoadingData.length < 1}
                                               scroll={{
                                                   width: 1200,
                                                   height: filteredLoadingData && filteredLoadingData.length > 0 ? 320 : 0
                                               }}
                                               useFullPagination={true}
                                               paginationTotalRenderer={total =>
                                                   Self Defined Total: {total}}
                                               onSortChange={this.handleSortChange}
                                               onPaginationChange={this.handlePaginationChange}
                                               onExpand={this.handleExpand}
                                               onCollapse={this.handleCollapse}
                                               onChange={this.handleChange}
                                               onSelect={this.handleSelect}
                                               onSelectAll={this.handleSelectAll}
                                               onDeselect={this.handleDeselect}
                                               onDeselectAll={this.handleSeselectAll}/>
                                        :
                                        <CircularLoading className="loading-table-loading"/>
                                }

                </Widget>

                {/*<Widget>*/}

                {/*    <WidgetHeader className="example-header"*/}
                {/*                  title="No Data"/>*/}

                {/*
*/}
                {/*
*/}

                {/*
No Data Table example.
*/}

                {/*
*/}

                {/*
*/}
                {/*
*/}

                {/*</Widget>*/}

                {/*
Properties
*/}

                {/*<PropTypeDescTable data={doc}/>*/}

        );
    }
}

export default TableExamples;
<commit_msg>update TableExamples<commit_after>import React, {Component, Fragment, createRef} from 'react';
import round from 'lodash/round';

import Table from 'src/Table';
import Switcher from 'src/Switcher';
import IconButton from 'src/IconButton';
import Widget from 'src/Widget';
import WidgetHeader from 'src/WidgetHeader';
import CircularLoading from 'src/CircularLoading';
import RaisedButton from 'src/RaisedButton';
import MaterialTextField from 'src/MaterialTextField';

import PropTypeDescTable from 'components/PropTypeDescTable';
import doc from 'assets/propTypes/Table.json';

import Util from 'vendors/Util';

import 'scss/containers/app/modules/layout/TableExamples.scss';

const LOADING_SYMBOL = Symbol('LOADING_SYMBOL');

class TableExamples extends Component {

    constructor(props) {

        super(props);

        this.tableRef = createRef();

        this.state = {
            data: this.generateData(),
            loadingData: null,
            sorting: null,
            filter: '',
            footVisible: true
        };

        this.columns = [{
            headRenderer: 'ID',
            bodyRenderer: rowDate => rowDate[LOADING_SYMBOL] ?
                <CircularLoading/> : rowDate.id,
            footRenderer: 'Total',
            sortable: true,
            sortingProp: 'id'
        }, {
            width: 300,
            noWrap: true,
            headRenderer: 'Name',
            bodyRenderer: rowDate => rowDate.firstName && rowDate.lastName ?
                `${rowDate.firstName} ${rowDate.lastName}` : '',
            sortable: true,
            sortingProp: 'firstName'
        }, {
            align: Table.Align.RIGHT,
            noWrap: true,
            headRenderer: 'Age',
            bodyRenderer: rowDate => rowDate.age,
            footRenderer: this.state.data && this.state.data.length > 0 ? () =>
                    <Fragment>

Average

{this.state.data.reduce((a, b) => a + b.age, 0) / this.state.data.length}

                    </Fragment>
                :
                null,
            sortable: true,
            sortingProp: 'age'
        }, {
            headRenderer: 'Other Column',
            headAlign: Table.Align.CENTER,
            children: [{
                width: 300,
                headRenderer: 'Other Column 1',
                bodyRenderer: rowDate => rowDate.other ? `${rowDate.other} 1` : ''
            }, {
                width: 300,
                headRenderer: 'Other Column 2',
                bodyRenderer: rowDate => rowDate.other ? `${rowDate.other} 2` : ''
            }, {
                width: 300,
                headRenderer: 'Other Column 3',
                bodyRenderer: rowDate => rowDate.other ? `${rowDate.other} 3` : ''
            }, {
                width: 300,
                headRenderer: 'Other Column 4',
                bodyRenderer: rowDate => rowDate.other ? `${rowDate.other} 4` : ''
            }]
        }, {
            align: Table.Align.RIGHT,
            noWrap: true,
            headRenderer: 'Deposit',
            bodyRenderer: rowDate => rowDate.deposit ? `$${rowDate.deposit}` : '',
            footRenderer: this.state.data && this.state.data.length > 0 ? () =>
                    <Fragment>

Sum

${this.state.data.reduce((a, b) => round(a + b.deposit, 2), 0)}

                    </Fragment>
                :
                null,
            sortable: true,
            sortingProp: 'deposit'
        }, {
            headRenderer: 'Status',
            bodyRenderer: rowData => rowData[LOADING_SYMBOL] ?
                null
                :
                <Switcher value={!rowData.disabled}
                          size="small"
                          onClick={e => e.stopPropagation()}/>
        }, {
            headRenderer: 'Action',
            bodyRenderer: rowData => rowData[LOADING_SYMBOL] ?
                null
                :
                <IconButton iconCls="fas fa-trash-alt"
                            onClick={() => this.deleteRow(rowData.id)}/>
        }];

        this.pageSizes = [{
            value: 10,
            text: '10 / page'
        }, {
            value: 20,
            text: '20 / page'
        }, {
            value: 30,
            text: '30 / page'
        }, {
            value: 40,
            text: '40 / page'
        }, {
            value: 50,
            text: '50 / page'
        }];

    }

    getFixedColumns = () => {
        return this.columns.map(column => {
            if (['ID', 'Name'].includes(column.headRenderer)) {
                return {
                    fixed: Table.Fixed.LEFT,
                    ...column
                };
            } else if (['Status', 'Action'].includes(column.headRenderer)) {
                return {
                    fixed: Table.Fixed.RIGHT,
                    ...column
                };
            }
            return column;
        });
    };

    generateData = (size = 100, base = '', expanded = true) => {

        let data = [];
        for (let i = 0; i < size; i++) {

            const id = `${base ? `${base}-` : ''}${i}`,
                item = {
                    id,
                    firstName: `firstName${id}`,
                    lastName: `lastName${id}`,
                    age: Math.floor(Math.random() * 100),
                    deposit: round(Math.random() * 1000000, 2),
                    other: 'Other Content'
                };

            if (expanded && id.split('-').pop() === '0') {
                item.children = [{
                    [LOADING_SYMBOL]: true,
                    disabled: true
                }];
            }

            data.push(item);

        }

        return data;

    };

    deleteRow = id => {

        const {data} = this.state,
            newData = data.filter(item => item.id !== id);

        this.setState({
            data: newData
        });

    };

    handleSortChange = sorting => {
        this.setState({
            sorting
        });
        console.log('Sort Change Value: ', sorting);
    };

    handlePaginationChange = ({page, pageSize}) => {
        console.log(`page: ${page}, pageSize: ${pageSize}`);
    };

    handleSelect = (rowData, rowIndex, value) => {
        console.log('Select Value: ', rowData);
    };

    handleDeselect = (rowData, rowIndex, value) => {
        console.log('Deselect Value: ', rowData);
    };

    handleSelectAll = value => {
        console.log('Select All Value: ', value);
    };

    handleSeselectAll = value => {
        console.log('Deselect All Value: ', value);
    };

    handleChange = value => {
        console.log('Changed Value: ', value);
    };

    handleExpand = rowData => {

        console.log('Expand: ', rowData);

        const {data} = this.state;

        if (!rowData || !data || !rowData.children[0][LOADING_SYMBOL]) {
            return;
        }

        setTimeout(() => {

            Util.postOrderTraverse({
                children: data
            }, node => {
                if (node && node.id === rowData.id) {
                    node.children = this.generateData(10, node.id);
                    return false;
                }
            });

            this.setState({
                data
            });

        }, 1000);

    };

    handleCollapse = rowData => {
        console.log('Collapse: ', rowData);
    };

    collapseAllRows = () => {
        this.tableRef && this.tableRef.current && this.tableRef.current.collapseAllRows();
    };

    toggleFoot = () => {
        this.setState({
            footVisible: !this.state.footVisible
        });
    };

    handleFilter = filter => {
        this.setState({
            filter
        });
    };

    filterData = (data = this.state.data) => {

        const {filter} = this.state;

        if (!filter || !data) {
            return data;
        }

        return data.filter(item => item && (
            (item.firstName && item.firstName.toUpperCase().includes(filter.toUpperCase()))
            ||
            (item.lastName && item.lastName.toUpperCase().includes(filter.toUpperCase()))
        ));

    };

    componentDidMount() {
        setTimeout(() => {
            this.setState({
                loadingData: this.generateData()
            });
        }, 3000);
    }

    render() {

        const {data, loadingData, sorting, filter, footVisible} = this.state,
            // filteredData = this.filterData(data),
            filteredLoadingData = this.filterData(loadingData);

        return (

Table

                    Table
                     are used to display data and to organize it.

Examples

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Normal"/>

A simple Table example.

                            <Table className="example-table"
                                   columns={this.columns}
                                   data={data}
                                   onSortChange={this.handleSortChange}
                                   onPaginationChange={this.handlePaginationChange}
                                   onExpand={this.handleExpand}
                                   onCollapse={this.handleCollapse}
                                   onChange={this.handleChange}
                                   onSelect={this.handleSelect}
                                   onSelectAll={this.handleSelectAll}
                                   onDeselect={this.handleDeselect}
                                   onDeselectAll={this.handleSeselectAll}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Fix Head & Foot"/>

                                You can config isHeadFixed to fix the Head,
                                and config isFootFixed to fix the Foot.

                            <Table className="example-table"
                                   columns={this.columns}
                                   data={data}
                                   isHeadFixed={true}
                                   isFootFixed={true}
                                   scroll={{
                                       maxHeight: 320
                                   }}
                                   onSortChange={this.handleSortChange}
                                   onPaginationChange={this.handlePaginationChange}
                                   onExpand={this.handleExpand}
                                   onCollapse={this.handleCollapse}
                                   onChange={this.handleChange}
                                   onSelect={this.handleSelect}
                                   onSelectAll={this.handleSelectAll}
                                   onDeselect={this.handleDeselect}
                                   onDeselectAll={this.handleSeselectAll}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Fix Columns"/>

                                You can config fixed in columns to fix the column
                                Left or Right.

                            <Table className="example-table"
                                   columns={this.getFixedColumns()}
                                   data={data}
                                   scroll={{
                                       width: 1200
                                   }}
                                   onSortChange={this.handleSortChange}
                                   onPaginationChange={this.handlePaginationChange}
                                   onExpand={this.handleExpand}
                                   onCollapse={this.handleCollapse}
                                   onChange={this.handleChange}
                                   onSelect={this.handleSelect}
                                   onSelectAll={this.handleSelectAll}
                                   onDeselect={this.handleDeselect}
                                   onDeselectAll={this.handleSeselectAll}/>

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="Fix Head, Foot and Columns"/>

                                <RaisedButton className="action-button"
                                              value="Collapse All Rows"
                                              onClick={this.collapseAllRows}/>
                                <RaisedButton className="action-button"
                                              value="Toggle Table Foot"
                                              onClick={this.toggleFoot}/>
                                <MaterialTextField className="filter"
                                                   label="Filter"
                                                   value={filter}
                                                   onChange={this.handleFilter}/>

                                {
                                    filteredLoadingData ?
                                        <Table ref={this.tableRef}
                                               className="example-table"
                                               data={filteredLoadingData}
                                               columns={this.getFixedColumns()}
                                               sorting={sorting}
                                               selectMode={Table.SelectMode.MULTI_SELECT}
                                               isHeadFixed={true}
                                               isFootFixed={true}
                                               isFootHidden={!footVisible || !filteredLoadingData || filteredLoadingData.length < 1}
                                               scroll={{
                                                   width: 1200,
                                                   height: filteredLoadingData && filteredLoadingData.length > 0 ? 320 : 0
                                               }}
                                               useFullPagination={true}
                                               paginationTotalRenderer={total =>
                                                   Self Defined Total: {total}}
                                               onSortChange={this.handleSortChange}
                                               onPaginationChange={this.handlePaginationChange}
                                               onExpand={this.handleExpand}
                                               onCollapse={this.handleCollapse}
                                               onChange={this.handleChange}
                                               onSelect={this.handleSelect}
                                               onSelectAll={this.handleSelectAll}
                                               onDeselect={this.handleDeselect}
                                               onDeselectAll={this.handleSeselectAll}/>
                                        :
                                        <CircularLoading className="loading-table-loading"/>
                                }

                </Widget>

                <Widget>

                    <WidgetHeader className="example-header"
                                  title="No Data"/>

No Data Table example.

                </Widget>

Properties

                <PropTypeDescTable data={doc}/>

        );
    }
}

export default TableExamples;
<|endoftext|>


<commit_before>// A virtual "piece type" that provides a way to manage
// all submitted drafts, both pieces and pages. Supports
// most write operations, passing them through to the
// appropriate manager for the document in question

module.exports = {
  extend: '@apostrophecms/piece-type',
  options: {
    quickCreate: false,
    label: 'Submitted Draft',
    pluralLabel: 'Submitted Drafts',
    canCreate: false,
    canDismissSubmission: true,
    canArchive: false,
    canDiscardDraft: false
  },
  columns: {
    add: {
      title: {
        label: 'Title',
        component: 'AposCellButton'
      },
      type: {
        label: 'Type',
        // TODO need to push the choices somehow
        component: 'AposCellType'
      },
      'draft:submitted.at': {
        label: 'Submitted',
        component: 'AposCellDate'
      },
      'draft:submitted.by': {
        label: 'Proposed By',
        component: 'AposCellBasic'
      }
    },
    remove: [ 'updatedAt', 'visibility' ],
    order: [ 'title', 'type', 'draft:submitted.at', 'draft:submitted.by' ]
  },

  fields: {
    add: {
      _type: {
        label: 'Type',
        type: 'select',
        // Patched later
        choices: []
      }
    }
  },

  filters: {
    add: {
      _type: {
        label: 'Type'
      }
    }
  },

  handlers(self) {
    return {
      'apostrophe:modulesReady': {
        patchTypeField() {
          const typeField = self.schema.find(field => field.name === '_type');
          const managers = Object.values(self.apos.doc.managers);
          typeField.choices = managers.filter(manager => manager.isLocalized() && !manager.options.autopublish).map(manager => ({
            label: manager.options.label || manager.name || manager.__meta.name,
            value: manager.name || manager.__meta.name
          }));
        }
      }
    };
  },

  methods(self) {
    return {
      insert(req, piece, options) {
        throw new Error('Virtual piece type, should never be inserted');
      },
      update(req, piece, options) {
        // Virtual piece type, find the proper manager and use it
        const manager = self.apos.doc.getManager(piece.type);
        return manager.update(req, piece, options);
      },
      publish(req, piece, options) {
        // Virtual piece type, find the proper manager and use it
        const manager = self.apos.doc.getManager(piece.type);
        return manager.publish(req, piece, options);
      },
      delete(req, piece, options) {
        // Virtual piece type, find the proper manager and use it
        const manager = self.apos.doc.getManager(piece.type);
        return manager.delete(req, piece, options);
      },
      revertDraftToPublished(req, piece, options) {
        // Virtual piece type, find the proper manager and use it
        const manager = self.apos.doc.getManager(piece.type);
        return manager.revertDraftToPublished(req, piece, options);
      },
      addToAdminBar() {
        self.apos.adminBar.add(
          `${self.__meta.name}:manager`,
          self.pluralLabel,
          {
            action: 'edit',
            type: self.name
          },
          {
            component: 'AposSubmittedDraftIcon',
            contextUtility: true,
            tooltip: 'Submitted Drafts'
          }
        );
      }
    };
  },
  icons: {
    'tray-full-icon': 'TrayFull'
  },
  extendMethods(self) {
    return {
      find(_super, req, criteria, options) {
        const query = _super(req, criteria, options).type(null).and({
          submitted: {
            $exists: 1
          }
        });
        if (!self.apos.permission.can(req, 'publish', self.name)) {
          query.and({
            'submitted.byId': req.user && req.user._id
          });
        }
        return query;
      }
    };
  },
  queries(self, query) {
    return {
      builders: {
        _type: {
          def: null,
          launder(type) {
            return self.apos.launder.string(type);
          },
          finalize() {
            const state = query.get('_type');
            if (state) {
              query.and({
                type: state
              });
            }
          },
          async choices() {
            const values = await query.toDistinct('type');
            return values.map(name => {
              const manager = self.apos.doc.getManager(name);
              return {
                value: name,
                label: (manager && manager.options.label) || name
              };
            });
          }
        }
      }
    };
  }
};
<commit_msg>swap date cell for relative time cell<commit_after>// A virtual "piece type" that provides a way to manage
// all submitted drafts, both pieces and pages. Supports
// most write operations, passing them through to the
// appropriate manager for the document in question

module.exports = {
  extend: '@apostrophecms/piece-type',
  options: {
    quickCreate: false,
    label: 'Submitted Draft',
    pluralLabel: 'Submitted Drafts',
    canCreate: false,
    canDismissSubmission: true,
    canArchive: false,
    canDiscardDraft: false
  },
  columns: {
    add: {
      title: {
        label: 'Title',
        component: 'AposCellButton'
      },
      type: {
        label: 'Type',
        // TODO need to push the choices somehow
        component: 'AposCellType'
      },
      'draft:submitted.at': {
        label: 'Submitted',
        component: 'AposCellLastEdited'
      },
      'draft:submitted.by': {
        label: 'Proposed By',
        component: 'AposCellBasic'
      }
    },
    remove: [ 'updatedAt', 'visibility' ],
    order: [ 'title', 'type', 'draft:submitted.at', 'draft:submitted.by' ]
  },

  fields: {
    add: {
      _type: {
        label: 'Type',
        type: 'select',
        // Patched later
        choices: []
      }
    }
  },

  filters: {
    add: {
      _type: {
        label: 'Type'
      }
    }
  },

  handlers(self) {
    return {
      'apostrophe:modulesReady': {
        patchTypeField() {
          const typeField = self.schema.find(field => field.name === '_type');
          const managers = Object.values(self.apos.doc.managers);
          typeField.choices = managers.filter(manager => manager.isLocalized() && !manager.options.autopublish).map(manager => ({
            label: manager.options.label || manager.name || manager.__meta.name,
            value: manager.name || manager.__meta.name
          }));
        }
      }
    };
  },

  methods(self) {
    return {
      insert(req, piece, options) {
        throw new Error('Virtual piece type, should never be inserted');
      },
      update(req, piece, options) {
        // Virtual piece type, find the proper manager and use it
        const manager = self.apos.doc.getManager(piece.type);
        return manager.update(req, piece, options);
      },
      publish(req, piece, options) {
        // Virtual piece type, find the proper manager and use it
        const manager = self.apos.doc.getManager(piece.type);
        return manager.publish(req, piece, options);
      },
      delete(req, piece, options) {
        // Virtual piece type, find the proper manager and use it
        const manager = self.apos.doc.getManager(piece.type);
        return manager.delete(req, piece, options);
      },
      revertDraftToPublished(req, piece, options) {
        // Virtual piece type, find the proper manager and use it
        const manager = self.apos.doc.getManager(piece.type);
        return manager.revertDraftToPublished(req, piece, options);
      },
      addToAdminBar() {
        self.apos.adminBar.add(
          `${self.__meta.name}:manager`,
          self.pluralLabel,
          {
            action: 'edit',
            type: self.name
          },
          {
            component: 'AposSubmittedDraftIcon',
            contextUtility: true,
            tooltip: 'Submitted Drafts'
          }
        );
      }
    };
  },
  icons: {
    'tray-full-icon': 'TrayFull'
  },
  extendMethods(self) {
    return {
      find(_super, req, criteria, options) {
        const query = _super(req, criteria, options).type(null).and({
          submitted: {
            $exists: 1
          }
        });
        if (!self.apos.permission.can(req, 'publish', self.name)) {
          query.and({
            'submitted.byId': req.user && req.user._id
          });
        }
        return query;
      }
    };
  },
  queries(self, query) {
    return {
      builders: {
        _type: {
          def: null,
          launder(type) {
            return self.apos.launder.string(type);
          },
          finalize() {
            const state = query.get('_type');
            if (state) {
              query.and({
                type: state
              });
            }
          },
          async choices() {
            const values = await query.toDistinct('type');
            return values.map(name => {
              const manager = self.apos.doc.getManager(name);
              return {
                value: name,
                label: (manager && manager.options.label) || name
              };
            });
          }
        }
      }
    };
  }
};
<|endoftext|>