<commit_before>var PaperScript = new function() {
	//TODO: Make sure there are all the correct copyrights for the inlined
	//parse-js:
	//#include "../../lib/parse-js-min.js"

	// Handle Math Operators

	var operators = {
		'+': 'add',
		'-': 'subtract',
		'*': 'multiply',
		'/': 'divide',
		'%': 'modulo',
		'==': 'equals',
		'!=': 'equals'
	};

	function $operator(left, operator, right) {
		var handler = operators[operator];
		if (left && left[handler]) {
			var res = left[handler](right);
			return operator == '!=' ? !res : res;
		}
		switch (operator) {
		case '+': return left + right;
		case '-': return left - right;
		case '*': return left * right;
		case '/': return left / right;
		case '%': return left % right;
		case '==': return left == right;
		case '!=': return left != right;
		default:
			throw new Error('Implement Operator: ' + operator);
		}
	};

	// Handle Sign Operators

	var signs = {
		'-': 'negate'
	};

	function $sign(operator, value) {
		var handler = signs[operator];
		if (value && value[handler]) {
			return value[handler]();
		}
		switch (operator) {
		case '+': return +value;
		case '-': return -value;
		default:
			throw new Error('Implement Sign Operator: ' + operator);
		}
	}

	// AST Helpers

	function isDynamic(exp) {
		var type = exp[0];
		return type != 'num' && type != 'string';
	}

	function handleOperator(operator, left, right) {
		// Only replace operators with calls to paper.handleOperator if
		// the left hand side is potentially an object.
		if (operators[operator] && isDynamic(left)) {
			// Replace with paper.handleOperator(operator, left, right):
			return ['call', ['name', '$operator'],
					[left, ['string', operator], right]];
		}
	}

	function compile(code) {
		// Use parse-js to translate the code into a AST structure which is then
		// walked and parsed for operators to overload. The resulting AST is
		// translated back to code and evaluated.
		var ast = parse_js.parse(code),
			walker = parse_js.walker(),
			walk = walker.walk;

		ast = walker.with_walkers({
			'binary': function(operator, left, right) {
				// Handle simple mathematical operators here:
				return handleOperator(operator, left = walk(left),
						right = walk(right))
						// Always return something since we're walking left and
						// right for the handleOperator() call already.
						|| [this[0], operator, left, right];
			},

			'assign': function(operator, left, right) {
				// Handle assignments like +=, -=, etc:
				// Check if the assignment operator needs to be handled by paper
				// if so, convert the assignment to a simple = and use result of
				// of handleOperator on the right hand side.
				var res = handleOperator(operator, left = walk(left),
						right = walk(right));
				if (res)
					return [this[0], true, left, res];
				// Always return something for the same reason as in binary
				return [this[0], operator, left, right];
			},

			'unary-prefix': function(operator, exp) {
				if (signs[operator] && isDynamic(exp)) {
					return ['call', ['name', '$sign'],
							[['string', operator], walk(exp)]];
				}
			}
		}, function() {
			return walk(ast);
		});

		return parse_js.stringify(ast, true);
	}

	function run(code) {
		// Use paper.extend() to create a paper scope within which the code is
		// evaluated.
		with (paper.extend()) {
			var tool = /onMouse(?:Up|Down|Move|Drag)/.test(code) && new Tool();
			var res = eval(compile(code));
			if (tool) {
				Base.each(['onEditOptions', 'onOptions', 'onSelect',
					'onDeselect', 'onReselect', 'onMouseDown', 'onMouseUp',
					'onMouseDrag', 'onMouseMove'], function(key) {
					try {
						tool[key] = eval(key);
					} catch (e) {
					}
				});
			}
			return res;
		}
	}

//#ifdef BROWSER
	// Code borrowed from Coffee Script:
	function load(url) {
		var xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
		xhr.open('GET', url, true);
		if ('overrideMimeType' in xhr) {
			xhr.overrideMimeType('text/plain');
		}
		xhr.onreadystatechange = function() {
			if (xhr.readyState === 4) {
				return run(xhr.responseText);
			}
		};
		return xhr.send(null);
	}

	function runScripts() {
		var scripts = document.getElementsByTagName('script');
		for (var i = 0, l = scripts.length; i < l; i++) {
			var script = scripts[i];
			if (script.type === 'text/paperscript') {
				// If a canvas id is provided, create a document for it now, so
				// the active document is defined.
				var canvas = script.getAttribute('canvas');
				if (canvas && (canvas = document.getElementById(canvas))) {
					new Document(canvas);
				}
				if (script.src) {
					load(script.src);
				} else {
					run(script.innerHTML);
				}
			}
		}
		return null;
	}

	if (window.addEventListener) {
		addEventListener('load', runScripts, false);
	} else {
		attachEvent('onload', runScripts);
	}
//#endif // BROWSER

	return {
		compile: compile,
		run: run
	};
};
<commit_msg>Fix comments.<commit_after>var PaperScript = new function() {
	//TODO: Make sure there are all the correct copyrights for the inlined
	//parse-js:
	//#include "../../lib/parse-js-min.js"

	// Handle Math Operators

	var operators = {
		'+': 'add',
		'-': 'subtract',
		'*': 'multiply',
		'/': 'divide',
		'%': 'modulo',
		'==': 'equals',
		'!=': 'equals'
	};

	function $operator(left, operator, right) {
		var handler = operators[operator];
		if (left && left[handler]) {
			var res = left[handler](right);
			return operator == '!=' ? !res : res;
		}
		switch (operator) {
		case '+': return left + right;
		case '-': return left - right;
		case '*': return left * right;
		case '/': return left / right;
		case '%': return left % right;
		case '==': return left == right;
		case '!=': return left != right;
		default:
			throw new Error('Implement Operator: ' + operator);
		}
	};

	// Handle Sign Operators

	var signs = {
		'-': 'negate'
	};

	function $sign(operator, value) {
		var handler = signs[operator];
		if (value && value[handler]) {
			return value[handler]();
		}
		switch (operator) {
		case '+': return +value;
		case '-': return -value;
		default:
			throw new Error('Implement Sign Operator: ' + operator);
		}
	}

	// AST Helpers

	function isDynamic(exp) {
		var type = exp[0];
		return type != 'num' && type != 'string';
	}

	function handleOperator(operator, left, right) {
		// Only replace operators with calls to $operator if the left hand side
		// is potentially an object.
		if (operators[operator] && isDynamic(left)) {
			// Replace with call to $operator(left, operator, right):
			return ['call', ['name', '$operator'],
					[left, ['string', operator], right]];
		}
	}

	function compile(code) {
		// Use parse-js to translate the code into a AST structure which is then
		// walked and parsed for operators to overload. The resulting AST is
		// translated back to code and evaluated.
		var ast = parse_js.parse(code),
			walker = parse_js.walker(),
			walk = walker.walk;

		ast = walker.with_walkers({
			'binary': function(operator, left, right) {
				// Handle simple mathematical operators here:
				return handleOperator(operator, left = walk(left),
						right = walk(right))
						// Always return something since we're walking left and
						// right for the handleOperator() call already.
						|| [this[0], operator, left, right];
			},

			'assign': function(operator, left, right) {
				// Handle assignments like +=, -=, etc:
				// Check if the assignment operator needs to be handled by paper
				// if so, convert the assignment to a simple = and use result of
				// of handleOperator on the right hand side.
				var res = handleOperator(operator, left = walk(left),
						right = walk(right));
				if (res)
					return [this[0], true, left, res];
				// Always return something for the same reason as in binary
				return [this[0], operator, left, right];
			},

			'unary-prefix': function(operator, exp) {
				if (signs[operator] && isDynamic(exp)) {
					return ['call', ['name', '$sign'],
							[['string', operator], walk(exp)]];
				}
			}
		}, function() {
			return walk(ast);
		});

		return parse_js.stringify(ast, true);
	}

	function run(code) {
		// Use paper.extend() to create a paper scope within which the code is
		// evaluated.
		with (paper.extend()) {
			var tool = /onMouse(?:Up|Down|Move|Drag)/.test(code) && new Tool();
			var res = eval(compile(code));
			if (tool) {
				Base.each(['onEditOptions', 'onOptions', 'onSelect',
					'onDeselect', 'onReselect', 'onMouseDown', 'onMouseUp',
					'onMouseDrag', 'onMouseMove'], function(key) {
					try {
						tool[key] = eval(key);
					} catch (e) {
					}
				});
			}
			return res;
		}
	}

//#ifdef BROWSER
	// Code borrowed from Coffee Script:
	function load(url) {
		var xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
		xhr.open('GET', url, true);
		if ('overrideMimeType' in xhr) {
			xhr.overrideMimeType('text/plain');
		}
		xhr.onreadystatechange = function() {
			if (xhr.readyState === 4) {
				return run(xhr.responseText);
			}
		};
		return xhr.send(null);
	}

	function runScripts() {
		var scripts = document.getElementsByTagName('script');
		for (var i = 0, l = scripts.length; i < l; i++) {
			var script = scripts[i];
			if (script.type === 'text/paperscript') {
				// If a canvas id is provided, create a document for it now, so
				// the active document is defined.
				var canvas = script.getAttribute('canvas');
				if (canvas && (canvas = document.getElementById(canvas))) {
					new Document(canvas);
				}
				if (script.src) {
					load(script.src);
				} else {
					run(script.innerHTML);
				}
			}
		}
		return null;
	}

	if (window.addEventListener) {
		addEventListener('load', runScripts, false);
	} else {
		attachEvent('onload', runScripts);
	}
//#endif // BROWSER

	return {
		compile: compile,
		run: run
	};
};
<|endoftext|>


<commit_before>
const PATH = require("path");
const URL = require("url");
const PINF = require("..");
const SEND = require("send");

// TODO: Allow option to hoist programs sequentially instead of in parallel as is the
//       default when declaring more than one hoise at a time when setting up routes.

exports.hoist = function(programUri, options) {

	options = options || {};

	if (options.verbose) console.log("[pinf-for-nodejs][hoist]", "programUri", programUri);

	function hoist (callback) {

		return PINF.contextForProgram(programUri, {
            verbose: options.verbose || false,
            debug: options.debug || false
        }, function(err, $pinf) {
            if (err) return callback(err);

			var distPath = options.distPath || $pinf.makePath("bundles") || $pinf.makePath("cache", ["bundles", programUri]);

            return $pinf.bundleProgram({
                distPath: distPath
            }, function(err, summary) {
                if (err) return callback(err);

                summary.distPath = distPath;

				return callback(null, summary);
            });
        });
	}

	var responder = function(req, res, next) {
		res.writeHead(503, "Service Temporarily Unavailable", {
			"Content-Type": "text/plain",
			// `Retry-After` can be a relative number of seconds from now, or an RFC 1123 Date.
			"Retry-After": "5"
		});
		return res.end("Service Temporarily Unavailable\n");
	};

	hoist(function(err, summary) {
		if (err) {
			throw err;
		}

		if (options.verbose) console.log("[pinf-for-nodejs][hoist] Mounted", JSON.stringify(summary, null, 4));

		responder = function(req, res, next) {
			if (typeof req.params !== "object" || typeof req.params[0] !== "string") {
				throw new Error("`req.param[0]` must be set to the uri to load.");
			}
			var path = req.params[0];
			if (summary.bundles[req.params[0]]) {
				path = summary.bundles[req.params[0]];
			}

			// HACK: Removing content-length as SEND gets it wrong too!
			// TODO: Find a way to determine content length 100% accurately.
			var _setHeader = res.setHeader;
			res.setHeader = function () {
				_setHeader.apply(res, arguments);
				res.removeHeader("Content-Length");
			}

			return SEND(req, path)
				.root(summary.distPath)
				.on("error", function (err) {
					if (err && err.code !== "ENOENT") return next(err);
					if (/^loader\./.test(req.params[0])) {
						return SEND(req, req.params[0])
							.root(PATH.join(__dirname, "../node_modules/pinf-loader-js"))
							.on("error", next)
							.on('directory', next)
							.pipe(res);
					}
					return next();
				})
				.on('directory', next)
				.pipe(res);
		};
	});

	return function(req, res, next) {
		return responder(req, res, next);
	};
}
<commit_msg>set bundle age to 1 hour<commit_after>
const PATH = require("path");
const URL = require("url");
const PINF = require("..");
const SEND = require("send");

// TODO: Allow option to hoist programs sequentially instead of in parallel as is the
//       default when declaring more than one hoise at a time when setting up routes.

exports.hoist = function(programUri, options) {

	options = options || {};

	if (options.verbose) console.log("[pinf-for-nodejs][hoist]", "programUri", programUri);

	function hoist (callback) {

		return PINF.contextForProgram(programUri, {
            verbose: options.verbose || false,
            debug: options.debug || false
        }, function(err, $pinf) {
            if (err) return callback(err);

			var distPath = options.distPath || $pinf.makePath("bundles") || $pinf.makePath("cache", ["bundles", programUri]);

            return $pinf.bundleProgram({
                distPath: distPath
            }, function(err, summary) {
                if (err) return callback(err);

                summary.distPath = distPath;

				return callback(null, summary);
            });
        });
	}

	var responder = function(req, res, next) {
		res.writeHead(503, "Service Temporarily Unavailable", {
			"Content-Type": "text/plain",
			// `Retry-After` can be a relative number of seconds from now, or an RFC 1123 Date.
			"Retry-After": "5"
		});
		return res.end("Service Temporarily Unavailable\n");
	};

	hoist(function(err, summary) {
		if (err) {
			throw err;
		}

		if (options.verbose) console.log("[pinf-for-nodejs][hoist] Mounted", JSON.stringify(summary, null, 4));

		responder = function(req, res, next) {
			if (typeof req.params !== "object" || typeof req.params[0] !== "string") {
				throw new Error("`req.param[0]` must be set to the uri to load.");
			}
			var path = req.params[0];
			if (summary.bundles[req.params[0]]) {
				path = summary.bundles[req.params[0]];
			}

			// HACK: Removing content-length as SEND gets it wrong too!
			// TODO: Find a way to determine content length 100% accurately.
			var _setHeader = res.setHeader;
			res.setHeader = function () {
				_setHeader.apply(res, arguments);
				res.removeHeader("Content-Length");
			}

			return SEND(req, path)
				.root(summary.distPath)
				.on("error", function (err) {
					if (err && err.code !== "ENOENT") return next(err);
					if (/^loader\./.test(req.params[0])) {
						return SEND(req, req.params[0])
							.root(PATH.join(__dirname, "../node_modules/pinf-loader-js"))
							.on("error", next)
							.on('directory', next)
							.pipe(res);
					}
					return next();
				})
				.maxage(60 * 60 * 1000)	// 1 hour
				.on('directory', next)
				.pipe(res);
		};
	});

	return function(req, res, next) {
		return responder(req, res, next);
	};
}
<|endoftext|>


<commit_before>/*
Gradebook from Names and Scores
I worked on this challenge [by myself, with:]
This challenge took me [#] hours.
You will work with the following two variables.  The first, students, holds the names of four students.
The second, scores, holds groups of test scores.  The relative positions of elements within the two
variables match (i.e., 'Joseph' is the first element in students; his scores are the first value in scores.).
Do not alter the students and scores code.
*/

var students = ["Joseph", "Susan", "William", "Elizabeth"]

var scores = [ [80, 70, 70, 100],
               [85, 80, 90, 90],
               [75, 70, 80, 75],
               [100, 90, 95, 85] ]

var gradebook = {}

for (var i = 0; i < students.length; i++){
  gradebook[students[i]] = {}
}

for (var i = 0; i < scores.length; i++){
  gradebook[students[i]]['testScores'] = scores[i]
}

gradebook['addScore'] = function(name, score){
  gradebook[name].testScores.push(score);
}

gradebook.getAverage = function(){}

average = function(numArray){
 var sum = 0;
  for(var element = 0; element < numArray.length; element++)
    {
      sum += numArray[element];
    }
  return sum/numArray.length;
}

gradebook.getAverage = function(name){
  return average(gradebook[name].testScores)

}

console.log(gradebook)

// __________________________________________
// Write your code below.

// __________________________________________
// Refactored Solution

// __________________________________________
// Reflect

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (gradebook instanceof Object),
  "The value of gradebook should be an Object.\n",
  "1. "
)

assert(
  (gradebook["Elizabeth"] instanceof Object),
  "gradebook's Elizabeth property should be an object.",
  "2. "
)

assert(
  (gradebook.William.testScores === scores[2]),
  "William's testScores should equal the third element in scores.",
  "3. "
)

assert(
  (gradebook.addScore instanceof Function),
  "The value of gradebook's addScore property should be a Function.",
  "4. "
)

gradebook.addScore("Susan", 80)

assert(
  (gradebook.Susan.testScores.length === 5
   && gradebook.Susan.testScores[4] === 80),
  "Susan's testScores should have a new score of 80 added to the end.",
  "5. "
)

assert(
  (gradebook.getAverage instanceof Function),
  "The value of gradebook's getAverage property should be a Function.",
  "6. "
)

assert(
  (average instanceof Function),
  "The value of average should be a Function.\n",
  "7. "
)
assert(
  average([1, 2, 3]) === 2,
  "average should return the average of the elements in the array argument.\n",
  "8. "
)

assert(
  (gradebook.getAverage("Joseph") === 80),
  "gradebook's getAverage should return 80 if passed 'Joseph'.",
  "9. "
)<commit_msg>Refactor and add reflection<commit_after>/*
Gradebook from Names and Scores
I worked on this challenge [by myself, with:]
This challenge took me [#] hours.
You will work with the following two variables.  The first, students, holds the names of four students.
The second, scores, holds groups of test scores.  The relative positions of elements within the two
variables match (i.e., 'Joseph' is the first element in students; his scores are the first value in scores.).
Do not alter the students and scores code.
*/

var students = ["Joseph", "Susan", "William", "Elizabeth"]

var scores = [ [80, 70, 70, 100],
               [85, 80, 90, 90],
               [75, 70, 80, 75],
               [100, 90, 95, 85] ]

// __________________________________________
// Write your code below.

// //Release 1 Create a gradebook
// var gradebook = {}

// //Release 2 Add Students to gradebook
// for (var i = 0; i < students.length; i++){
//   gradebook[students[i]] = {}
// }

// //Release 3 Add Test Scores
// for (var i = 0; i < scores.length; i++){
//   gradebook[students[i]]['testScores'] = scores[i]
// }

// //Release 4 Add New Scores
// gradebook['addScore'] = function(name, score){
//   gradebook[name].testScores.push(score);
// }

// //Release 5: Create a Function to Calculate Averages
// gradebook.getAverage = function(){}

// //Release 6: Create a Function to Average Grades
// average = function(numArray){
//  var sum = 0;
//   for(var element = 0; element < numArray.length; element++)
//     {
//       sum += numArray[element];
//     }
//   return sum/numArray.length;
// }

// //Release 7: Modify getAverage Function
// gradebook.getAverage = function(name){
//   return average(gradebook[name].testScores)

// }

// console.log(gradebook)

// __________________________________________
// Refactored Solution
//Release 1 Create a gradebook
var gradebook = {}

//Release 2 Add Students to gradebook
for (i in students){
  gradebook[students[i]] = {}
}

//Release 3 Add Test Scores
for (i in students){
  gradebook[students[i]]['testScores'] = scores[i]
}

//Release 4 Add New Scores
gradebook['addScore'] = function(name, score){
  gradebook[name].testScores.push(score);
}

//Release 5: Create a Function to Calculate Averages
gradebook.getAverage = function(){}

//Release 6: Create a Function to Average Grades
average = function(numArray){
  return  numArray.reduce(function(a,b) {return a+b;})/numArray.length
}

//Release 7: Modify getAverage Function
gradebook.getAverage = function(name){
  return average(gradebook[name].testScores)
}

console.log(gradebook)

// __________________________________________
// Reflect

// What did you learn about adding functions to objects?

  // I learned that functions are added the same way as any other property.

// How did you iterate over nested arrays in JavaScript?

  // Used for loops.  Set a counter and I used the counter as the index number then to access the arrays of students.

// Were there any new methods you were able to incorporate? If so, what were they and how did they work?

  // The reduce method.  Allows you to take an array of numbers and will reduce it down to a single value.  In this case I was able to add each number in the array and it returned a single value of the sum.  Then I was able to divide that by the length of the array to get the average.

// __________________________________________
// Test Code:  Do not alter code below this line.

function assert(test, message, test_number) {
  if (!test) {
    console.log(test_number + "false");
    throw "ERROR: " + message;
  }
  console.log(test_number + "true");
  return true;
}

assert(
  (gradebook instanceof Object),
  "The value of gradebook should be an Object.\n",
  "1. "
)

assert(
  (gradebook["Elizabeth"] instanceof Object),
  "gradebook's Elizabeth property should be an object.",
  "2. "
)

assert(
  (gradebook.William.testScores === scores[2]),
  "William's testScores should equal the third element in scores.",
  "3. "
)

assert(
  (gradebook.addScore instanceof Function),
  "The value of gradebook's addScore property should be a Function.",
  "4. "
)

gradebook.addScore("Susan", 80)

assert(
  (gradebook.Susan.testScores.length === 5
   && gradebook.Susan.testScores[4] === 80),
  "Susan's testScores should have a new score of 80 added to the end.",
  "5. "
)

assert(
  (gradebook.getAverage instanceof Function),
  "The value of gradebook's getAverage property should be a Function.",
  "6. "
)

assert(
  (average instanceof Function),
  "The value of average should be a Function.\n",
  "7. "
)
assert(
  average([1, 2, 3]) === 2,
  "average should return the average of the elements in the array argument.\n",
  "8. "
)

assert(
  (gradebook.getAverage("Joseph") === 80),
  "gradebook's getAverage should return 80 if passed 'Joseph'.",
  "9. "
)<|endoftext|>


<commit_before>import Utils from '../../../utils/utils';

export default function () {
  const swiper = this;
  const { activeIndex, loopedSlides = 0, params } = swiper;
  const breakpoints = params.breakpoints;
  if (!breakpoints || (breakpoints && Object.keys(breakpoints).length === 0)) return;
  // Set breakpoint for window width and update parameters
  const breakpoint = swiper.getBreakpoint(breakpoints);
  if (breakpoint && swiper.currentBreakpoint !== breakpoint) {
    const breakPointsParams = breakpoint in breakpoints ? breakpoints[breakpoint] : swiper.originalParams;
    const needsReLoop = params.loop && (breakPointsParams.slidesPerView !== params.slidesPerView);

    Utils.extend(swiper.params, breakPointsParams);

    Utils.extend(swiper, {
      allowTouchMove: swiper.params.allowTouchMove,
      allowSlideNext: swiper.params.allowSlideNext,
      allowSlidePrev: swiper.params.allowSlidePrev,
    });

    swiper.currentBreakpoint = breakpoint;

    if (needsReLoop) {
      swiper.loopDestroy();
      swiper.loopCreate();
      swiper.updateSlides();
      swiper.slideTo((activeIndex - loopedSlides) + swiper.loopedSlides, 0, false);
    }
    swiper.emit('breakpoint', breakPointsParams);
  }
}
<commit_msg>fixed breakpoint with loop getting wrong realIndex when on init<commit_after>import Utils from '../../../utils/utils';

export default function () {
  const swiper = this;
  const {
    activeIndex, initialized, loopedSlides = 0, params,
  } = swiper;
  const breakpoints = params.breakpoints;
  if (!breakpoints || (breakpoints && Object.keys(breakpoints).length === 0)) return;
  // Set breakpoint for window width and update parameters
  const breakpoint = swiper.getBreakpoint(breakpoints);
  if (breakpoint && swiper.currentBreakpoint !== breakpoint) {
    const breakPointsParams = breakpoint in breakpoints ? breakpoints[breakpoint] : swiper.originalParams;
    const needsReLoop = params.loop && (breakPointsParams.slidesPerView !== params.slidesPerView);

    Utils.extend(swiper.params, breakPointsParams);

    Utils.extend(swiper, {
      allowTouchMove: swiper.params.allowTouchMove,
      allowSlideNext: swiper.params.allowSlideNext,
      allowSlidePrev: swiper.params.allowSlidePrev,
    });

    swiper.currentBreakpoint = breakpoint;

    if (needsReLoop && initialized) {
      swiper.loopDestroy();
      swiper.loopCreate();
      swiper.updateSlides();
      swiper.slideTo((activeIndex - loopedSlides) + swiper.loopedSlides, 0, false);
    }
    swiper.emit('breakpoint', breakPointsParams);
  }
}
<|endoftext|>


<commit_before>"use strict";

$("showCommands").onclick = function(event) {
  var node, root = DomUtils.UI.root;
  event && event.preventDefault();
  Vomnibar.input && Vomnibar.input.blur();
  if (root && root.querySelector('.HelpCommandName')) {
    node = root.getElementById("HelpDialog");
    DomUtils.UI.addElement(node);
    node.click();
    return;
  }
  MainPort.sendMessage({
    handler: "initHelp",
    unbound: true,
    names: true,
    returned: true,
    title: "Command Listing"
  }, function(response) {
    var node, root = DomUtils.UI.root;
    if (root && (node = root.getElementById("HClose"))) {
      node.onclick();
    }
    MainPort.Listener(response);
    node = DomUtils.UI.root.getElementById("HelpDialog");
    node.onclick = function(event) {
      var target = event.target, str;
      if (target.classList.contains("HelpCommandName")) {
        str = target.innerText.slice(1, -1);
        MainPort.port.postMessage({
          handler: "copyToClipboard",
          data: str
        });
        VHUD.showCopied(str);
      }
    };
  });
};

var formatDate = function(time) {
  return new Date(time - new Date().getTimezoneOffset() * 1000 * 60
    ).toJSON().substring(0, 19).replace('T', ' ');
};

$("exportButton").onclick = function(event) {
  var exported_object, exported_data, file_name, force2, d, nodeA;
  exported_object = Object.create(null);
  exported_object.name = "Vimium++";
  exported_object.time = 0;
  (function() {
    var storage = localStorage, i, len, key, mark_head, all = bgSettings.defaults
      , strArr = bgSettings.NonJSON, arr1;
    mark_head = BG.Marks.getMarkKey("");
    for (i = 0, len = storage.length; i < len; i++) {
      key = storage.key(i);
      if (key === "name" || key === "time" || key.startsWith(mark_head)) {
        continue;
      }
      if ((key in strArr) && storage.getItem(key).indexOf("\n") > 0) {
        exported_object[key] = storage.getItem(key).split("\n");
        exported_object[key].push("");
      } else {
        exported_object[key] = (key in all) ? bgSettings.get(key) : storage.getItem(key);
      }
    }
  })();
  delete exported_object.findModeRawQueryList;
  delete exported_object.newTabUrl_f;
  d = new Date();
  exported_object.time = d.getTime();
  exported_data = JSON.stringify(exported_object, null, '\t');
  exported_object = null;
  force2 = function(i) { return ((i <= 9) ? '0'  : '') + i; }
  file_name = 'vimium++_';
  if (event && (event.ctrlKey || event.metaKey || event.shiftKey)) {
    file_name += "settings";
  } else {
    file_name += formatDate(d).replace(/[\-:]/g, "").replace(" ", "_");
  }
  file_name += '.json';

  nodeA = document.createElement("a");
  nodeA.download = file_name;
  nodeA.href = URL.createObjectURL(new Blob([exported_data]));
  nodeA.click();
  URL.revokeObjectURL(nodeA.href);
  console.log("EXPORT settings to", file_name, "at", formatDate(d));
};

var importSettings = function(time, event) {
  var new_data, fileReader = event.target;
  try {
    new_data = JSON.parse(fileReader.result);
    time = new_data.time < 0 ? time : (new_data.time || 0);
  } catch (e) {}
  if (!new_data || new_data.name !== "Vimium++" || (time < 10000 && time > 0)) {
    VHUD.showForDuration("No settings data found!", 2000);
    return;
  } else if (!confirm(
    "You are loading a settings copy exported" + (time ? " at:\n        "
    + formatDate(time) : " before.")
    + "\n\nAre you sure you want to continue?"
  )) {
    VHUD.showForDuration("You cancelled importing.", 1000);
    return;
  }

  var storage = localStorage, i, key, new_value, func, all = bgSettings.defaults
    , strArr = bgSettings.NonJSON;
  func = function(val) {
    return typeof val !== "string" || val.length <= 72 ? val
      : val.substring(0, 68).trimRight() + " ...";
  };
  console.log("IMPORT settings at", formatDate(new Date(time)));
  Object.setPrototypeOf(new_data, null);
  delete new_data.name;
  delete new_data.time;
  delete new_data.findModeRawQuery;
  storage.removeItem("findModeRawQuery");
  for (i = storage.length; 0 <= --i; ) {
    key = storage.key(i);
    if (!(key in new_data)) {
      new_data[key] = null;
    }
  }
  delete new_data.findModeRawQueryList;
  delete new_data.newTabUrl_f;
  Option.all.forEach(function(item) {
    var key = item.field, new_value = new_data[key];
    delete new_data[key];
    if (new_value == null) {
      // NOTE: we assume all nullable settings have the same default value: null
      new_value = all[key];
    } else if (new_value.join && (key in strArr)) {
      new_value = new_value.join("\n").trim();
    }
    if (!item.areEqual(bgSettings.get(key), new_value)) {
      console.log("import", key, func(new_value));
      bgSettings.set(key, new_value);
      if (key in bgSettings.bufferToLoad) {
        Option.syncToFrontend.push(key);
      }
    }
    item.fetch();
  });
  for (key in new_data) {
    new_value = new_data[key];
    if (new_value == null) {
      if (key in all) {
        new_value = all[key];
        if (bgSettings.get(key) !== new_value) {
          bgSettings.set(key, new_value);
          console.log("reset", key, func(new_value));
          continue;
        }
        new_value = bgSettings.get(key);
      } else {
        new_value = storage.getItem(key);
      }
      storage.removeItem(key);
      console.log("remove", key, ":=", func(new_value));
      continue;
    }
    if (new_value.join && (key in strArr)) {
      new_value = new_value.join("\n").trim();
    }
    if (key in all) {
      if (bgSettings.get(key) !== new_value) {
        bgSettings.set(key, new_value);
        console.log("update", key, func(new_value));
      }
    } else {
      storage.setItem(key, new_value);
      console.log("save", key, func(new_value));
    }
  }
  $("saveOptions").onclick(false);
  VHUD.showForDuration("Import settings data: OK!", 1000);
};

$("settingsFile").onchange = function() {
  var file = this.files[0], reader;
  this.value = "";
  if (!file) { return; }
  reader = new FileReader();
  reader.onload = importSettings.bind(null, file.lastModified);
  reader.readAsText(file);
};
$("settingsFile").onclick = function() {};

if (window._delayed) {
  $(window._delayed).onclick();
  delete window._delayed;
}
<commit_msg>it's needed to log the event of finishing import<commit_after>"use strict";

$("showCommands").onclick = function(event) {
  var node, root = DomUtils.UI.root;
  event && event.preventDefault();
  Vomnibar.input && Vomnibar.input.blur();
  if (root && root.querySelector('.HelpCommandName')) {
    node = root.getElementById("HelpDialog");
    DomUtils.UI.addElement(node);
    node.click();
    return;
  }
  MainPort.sendMessage({
    handler: "initHelp",
    unbound: true,
    names: true,
    returned: true,
    title: "Command Listing"
  }, function(response) {
    var node, root = DomUtils.UI.root;
    if (root && (node = root.getElementById("HClose"))) {
      node.onclick();
    }
    MainPort.Listener(response);
    node = DomUtils.UI.root.getElementById("HelpDialog");
    node.onclick = function(event) {
      var target = event.target, str;
      if (target.classList.contains("HelpCommandName")) {
        str = target.innerText.slice(1, -1);
        MainPort.port.postMessage({
          handler: "copyToClipboard",
          data: str
        });
        VHUD.showCopied(str);
      }
    };
  });
};

var formatDate = function(time) {
  return new Date(time - new Date().getTimezoneOffset() * 1000 * 60
    ).toJSON().substring(0, 19).replace('T', ' ');
};

$("exportButton").onclick = function(event) {
  var exported_object, exported_data, file_name, force2, d, nodeA;
  exported_object = Object.create(null);
  exported_object.name = "Vimium++";
  exported_object.time = 0;
  (function() {
    var storage = localStorage, i, len, key, mark_head, all = bgSettings.defaults
      , strArr = bgSettings.NonJSON, arr1;
    mark_head = BG.Marks.getMarkKey("");
    for (i = 0, len = storage.length; i < len; i++) {
      key = storage.key(i);
      if (key === "name" || key === "time" || key.startsWith(mark_head)) {
        continue;
      }
      if ((key in strArr) && storage.getItem(key).indexOf("\n") > 0) {
        exported_object[key] = storage.getItem(key).split("\n");
        exported_object[key].push("");
      } else {
        exported_object[key] = (key in all) ? bgSettings.get(key) : storage.getItem(key);
      }
    }
  })();
  delete exported_object.findModeRawQueryList;
  delete exported_object.newTabUrl_f;
  d = new Date();
  exported_object.time = d.getTime();
  exported_data = JSON.stringify(exported_object, null, '\t');
  exported_object = null;
  force2 = function(i) { return ((i <= 9) ? '0'  : '') + i; }
  file_name = 'vimium++_';
  if (event && (event.ctrlKey || event.metaKey || event.shiftKey)) {
    file_name += "settings";
  } else {
    file_name += formatDate(d).replace(/[\-:]/g, "").replace(" ", "_");
  }
  file_name += '.json';

  nodeA = document.createElement("a");
  nodeA.download = file_name;
  nodeA.href = URL.createObjectURL(new Blob([exported_data]));
  nodeA.click();
  URL.revokeObjectURL(nodeA.href);
  console.log("EXPORT settings to", file_name, "at", formatDate(d));
};

var importSettings = function(time, event) {
  var new_data, fileReader = event.target;
  try {
    new_data = JSON.parse(fileReader.result);
    time = new_data.time < 0 ? time : (new_data.time || 0);
  } catch (e) {}
  if (!new_data || new_data.name !== "Vimium++" || (time < 10000 && time > 0)) {
    VHUD.showForDuration("No settings data found!", 2000);
    return;
  } else if (!confirm(
    "You are loading a settings copy exported" + (time ? " at:\n        "
    + formatDate(time) : " before.")
    + "\n\nAre you sure you want to continue?"
  )) {
    VHUD.showForDuration("You cancelled importing.", 1000);
    return;
  }

  var storage = localStorage, i, key, new_value, func, all = bgSettings.defaults
    , strArr = bgSettings.NonJSON;
  func = function(val) {
    return typeof val !== "string" || val.length <= 72 ? val
      : val.substring(0, 68).trimRight() + " ...";
  };
  console.log("IMPORT settings at", formatDate(new Date(time)));
  Object.setPrototypeOf(new_data, null);
  delete new_data.name;
  delete new_data.time;
  delete new_data.findModeRawQuery;
  storage.removeItem("findModeRawQuery");
  for (i = storage.length; 0 <= --i; ) {
    key = storage.key(i);
    if (!(key in new_data)) {
      new_data[key] = null;
    }
  }
  delete new_data.findModeRawQueryList;
  delete new_data.newTabUrl_f;
  Option.all.forEach(function(item) {
    var key = item.field, new_value = new_data[key];
    delete new_data[key];
    if (new_value == null) {
      // NOTE: we assume all nullable settings have the same default value: null
      new_value = all[key];
    } else if (new_value.join && (key in strArr)) {
      new_value = new_value.join("\n").trim();
    }
    if (!item.areEqual(bgSettings.get(key), new_value)) {
      console.log("import", key, func(new_value));
      bgSettings.set(key, new_value);
      if (key in bgSettings.bufferToLoad) {
        Option.syncToFrontend.push(key);
      }
    }
    item.fetch();
  });
  for (key in new_data) {
    new_value = new_data[key];
    if (new_value == null) {
      if (key in all) {
        new_value = all[key];
        if (bgSettings.get(key) !== new_value) {
          bgSettings.set(key, new_value);
          console.log("reset", key, func(new_value));
          continue;
        }
        new_value = bgSettings.get(key);
      } else {
        new_value = storage.getItem(key);
      }
      storage.removeItem(key);
      console.log("remove", key, ":=", func(new_value));
      continue;
    }
    if (new_value.join && (key in strArr)) {
      new_value = new_value.join("\n").trim();
    }
    if (key in all) {
      if (bgSettings.get(key) !== new_value) {
        bgSettings.set(key, new_value);
        console.log("update", key, func(new_value));
      }
    } else {
      storage.setItem(key, new_value);
      console.log("save", key, func(new_value));
    }
  }
  $("saveOptions").onclick(false);
  VHUD.showForDuration("Import settings data: OK!", 1000);
  console.log("IMPORT settings: finished");
};

$("settingsFile").onchange = function() {
  var file = this.files[0], reader;
  this.value = "";
  if (!file) { return; }
  reader = new FileReader();
  reader.onload = importSettings.bind(null, file.lastModified);
  reader.readAsText(file);
};
$("settingsFile").onclick = function() {};

if (window._delayed) {
  $(window._delayed).onclick();
  delete window._delayed;
}
<|endoftext|>


<commit_before>const Constants = require('../util/Constants');
const util = require('util');

/**
 * Data structure that makes it easy to interact with a permission bitfield. All {@link GuildMember}s have a set of
 * permissions in their guild, and each channel in the guild may also have {@link PermissionOverwrites} for the member
 * that override their default permissions.
 */
class Permissions {
  /**
   * @param {GuildMember} [member] Member the permissions are for **(deprecated)**
   * @param {number|PermissionResolvable[]} permissions Permissions or bitfield to read from
   */
  constructor(member, permissions) {
    permissions = typeof member === 'object' && !(member instanceof Array) ? permissions : member;

    /**
     * Member the permissions are for
     * @type {GuildMember}
     * @deprecated
     */
    this._member = typeof member === 'object' ? member : null;

    /**
     * Bitfield of the packed permissions
     * @type {number}
     */
    this.bitfield = typeof permissions === 'number' ? permissions : this.constructor.resolve(permissions);
  }

  get member() {
    return this._member;
  }

  set member(value) {
    this._member = value;
  }

  /**
   * Bitfield of the packed permissions
   * @type {number}
   * @see {@link Permissions#bitfield}
   * @deprecated
   * @readonly
   */
  get raw() {
    return this.bitfield;
  }

  set raw(raw) {
    this.bitfield = raw;
  }

  /**
   * Checks whether the bitfield has a permission, or multiple permissions.
   * @param {PermissionResolvable|PermissionResolvable[]} permission Permission(s) to check for
   * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
   * @returns {boolean}
   */
  has(permission, checkAdmin = true) {
    if (permission instanceof Array) return permission.every(p => this.has(p, checkAdmin));
    permission = this.constructor.resolve(permission);
    if (checkAdmin && (this.bitfield & this.constructor.FLAGS.ADMINISTRATOR) > 0) return true;
    return (this.bitfield & permission) === permission;
  }

  /**
   * Gets all given permissions that are missing from the bitfield.
   * @param {PermissionResolvable[]} permissions Permissions to check for
   * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
   * @returns {PermissionResolvable[]}
   */
  missing(permissions, checkAdmin = true) {
    return permissions.filter(p => !this.has(p, checkAdmin));
  }

  /**
   * Adds permissions to this one, creating a new instance to represent the new bitfield.
   * @param {...PermissionResolvable} permissions Permissions to add
   * @returns {Permissions}
   */
  add(...permissions) {
    let total = 0;
    for (let p = 0; p < permissions.length; p++) {
      const perm = this.constructor.resolve(permissions[p]);
      if ((this.bitfield & perm) !== perm) total |= perm;
    }
    return new this.constructor(this.member, this.bitfield | total);
  }

  /**
   * Removes permissions to this one, creating a new instance to represent the new bitfield.
   * @param {...PermissionResolvable} permissions Permissions to remove
   * @returns {Permissions}
   */
  remove(...permissions) {
    let total = 0;
    for (let p = 0; p < permissions.length; p++) {
      const perm = this.constructor.resolve(permissions[p]);
      if ((this.bitfield & perm) === perm) total |= perm;
    }
    return new this.constructor(this.member, this.bitfield & ~total);
  }

  /**
   * Gets an object mapping permission name (like `READ_MESSAGES`) to a {@link boolean} indicating whether the
   * permission is available.
   * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
   * @returns {Object}
   */
  serialize(checkAdmin = true) {
    const serialized = {};
    for (const perm in this.constructor.FLAGS) serialized[perm] = this.has(perm, checkAdmin);
    return serialized;
  }

  /**
   * Checks whether the user has a certain permission, e.g. `READ_MESSAGES`.
   * @param {PermissionResolvable} permission The permission to check for
   * @param {boolean} [explicit=false] Whether to require the user to explicitly have the exact permission
   * @returns {boolean}
   * @see {@link Permissions#has}
   * @deprecated
   */
  hasPermission(permission, explicit = false) {
    return this.has(permission, !explicit);
  }

  /**
   * Checks whether the user has all specified permissions.
   * @param {PermissionResolvable[]} permissions The permissions to check for
   * @param {boolean} [explicit=false] Whether to require the user to explicitly have the exact permissions
   * @returns {boolean}
   * @see {@link Permissions#has}
   * @deprecated
   */
  hasPermissions(permissions, explicit = false) {
    return this.has(permissions, !explicit);
  }

  /**
   * Checks whether the user has all specified permissions, and lists any missing permissions.
   * @param {PermissionResolvable[]} permissions The permissions to check for
   * @param {boolean} [explicit=false] Whether to require the user to explicitly have the exact permissions
   * @returns {PermissionResolvable[]}
   * @see {@link Permissions#missing}
   * @deprecated
   */
  missingPermissions(permissions, explicit = false) {
    return this.missing(permissions, !explicit);
  }

  /**
   * Data that can be resolved to give a permission number. This can be:
   * - A string (see {@link Permissions.flags})
   * - A permission number
   * @typedef {string|number} PermissionResolvable
   */

  /**
   * Resolves permissions to their numeric form.
   * @param {PermissionResolvable|PermissionResolvable[]} permission - Permission(s) to resolve
   * @returns {number}
   */
  static resolve(permission) {
    if (permission instanceof Array) return permission.map(p => this.resolve(p)).reduce((prev, p) => prev | p, 0);
    if (typeof permission === 'string') permission = this.FLAGS[permission];
    if (typeof permission !== 'number' || permission < 1) throw new RangeError(Constants.Errors.NOT_A_PERMISSION);
    return permission;
  }
}

/**
 * Numeric permission flags. All available properties:
 * - `ADMINISTRATOR` (implicitly has *all* permissions, and bypasses all channel overwrites)
 * - `CREATE_INSTANT_INVITE` (create invitations to the guild)
 * - `KICK_MEMBERS`
 * - `BAN_MEMBERS`
 * - `MANAGE_CHANNELS` (edit and reorder channels)
 * - `MANAGE_GUILD` (edit the guild information, region, etc.)
 * - `ADD_REACTIONS` (add new reactions to messages)
 * - `VIEW_AUDIT_LOG`
 * - `READ_MESSAGES`
 * - `SEND_MESSAGES`
 * - `SEND_TTS_MESSAGES`
 * - `MANAGE_MESSAGES` (delete messages and reactions)
 * - `EMBED_LINKS` (links posted will have a preview embedded)
 * - `ATTACH_FILES`
 * - `READ_MESSAGE_HISTORY` (view messages that were posted prior to opening Discord)
 * - `MENTION_EVERYONE`
 * - `USE_EXTERNAL_EMOJIS` (use emojis from different guilds)
 * - `EXTERNAL_EMOJIS` **(deprecated)**
 * - `CONNECT` (connect to a voice channel)
 * - `SPEAK` (speak in a voice channel)
 * - `MUTE_MEMBERS` (mute members across all voice channels)
 * - `DEAFEN_MEMBERS` (deafen members across all voice channels)
 * - `MOVE_MEMBERS` (move members between voice channels)
 * - `USE_VAD` (use voice activity detection)
 * - `CHANGE_NICKNAME`
 * - `MANAGE_NICKNAMES` (change other members' nicknames)
 * - `MANAGE_ROLES`
 * - `MANAGE_ROLES_OR_PERMISSIONS` **(deprecated)**
 * - `MANAGE_WEBHOOKS`
 * - `MANAGE_EMOJIS`
 * @type {Object}
 * @see {@link https://discordapp.com/developers/docs/topics/permissions}
 */
Permissions.FLAGS = {
  CREATE_INSTANT_INVITE: 1 << 0,
  KICK_MEMBERS: 1 << 1,
  BAN_MEMBERS: 1 << 2,
  ADMINISTRATOR: 1 << 3,
  MANAGE_CHANNELS: 1 << 4,
  MANAGE_GUILD: 1 << 5,
  ADD_REACTIONS: 1 << 6,
  VIEW_AUDIT_LOG: 1 << 7,

  READ_MESSAGES: 1 << 10,
  SEND_MESSAGES: 1 << 11,
  SEND_TTS_MESSAGES: 1 << 12,
  MANAGE_MESSAGES: 1 << 13,
  EMBED_LINKS: 1 << 14,
  ATTACH_FILES: 1 << 15,
  READ_MESSAGE_HISTORY: 1 << 16,
  MENTION_EVERYONE: 1 << 17,
  EXTERNAL_EMOJIS: 1 << 18,
  USE_EXTERNAL_EMOJIS: 1 << 18,

  CONNECT: 1 << 20,
  SPEAK: 1 << 21,
  MUTE_MEMBERS: 1 << 22,
  DEAFEN_MEMBERS: 1 << 23,
  MOVE_MEMBERS: 1 << 24,
  USE_VAD: 1 << 25,

  CHANGE_NICKNAME: 1 << 26,
  MANAGE_NICKNAMES: 1 << 27,
  MANAGE_ROLES: 1 << 28,
  MANAGE_ROLES_OR_PERMISSIONS: 1 << 28,
  MANAGE_WEBHOOKS: 1 << 29,
  MANAGE_EMOJIS: 1 << 30,
};

/**
 * Bitfield representing every permission combined
 * @type {number}
 */
Permissions.ALL = Object.keys(Permissions.FLAGS).reduce((all, p) => all | Permissions.FLAGS[p], 0);

/**
 * Bitfield representing the default permissions for users
 * @type {number}
 */
Permissions.DEFAULT = 104324097;

/**
 * @class EvaluatedPermissions
 * @classdesc The final evaluated permissions for a member in a channel
 * @see {@link Permissions}
 * @deprecated
 */

Permissions.prototype.hasPermission = util.deprecate(Permissions.prototype.hasPermission,
  'EvaluatedPermissions#hasPermission is deprecated, use Permissions#has instead');
Permissions.prototype.hasPermissions = util.deprecate(Permissions.prototype.hasPermissions,
  'EvaluatedPermissions#hasPermissions is deprecated, use Permissions#has instead');
Permissions.prototype.missingPermissions = util.deprecate(Permissions.prototype.missingPermissions,
  'EvaluatedPermissions#missingPermissions is deprecated, use Permissions#missing instead');
Object.defineProperty(Permissions.prototype, 'member', {
  get: util
        .deprecate(Object.getOwnPropertyDescriptor(Permissions.prototype, 'member').get,
        'EvaluatedPermissions#member is deprecated'),
});

module.exports = Permissions;
<commit_msg>relink Permissions.FLAGS (#1510)<commit_after>const Constants = require('../util/Constants');
const util = require('util');

/**
 * Data structure that makes it easy to interact with a permission bitfield. All {@link GuildMember}s have a set of
 * permissions in their guild, and each channel in the guild may also have {@link PermissionOverwrites} for the member
 * that override their default permissions.
 */
class Permissions {
  /**
   * @param {GuildMember} [member] Member the permissions are for **(deprecated)**
   * @param {number|PermissionResolvable[]} permissions Permissions or bitfield to read from
   */
  constructor(member, permissions) {
    permissions = typeof member === 'object' && !(member instanceof Array) ? permissions : member;

    /**
     * Member the permissions are for
     * @type {GuildMember}
     * @deprecated
     */
    this._member = typeof member === 'object' ? member : null;

    /**
     * Bitfield of the packed permissions
     * @type {number}
     */
    this.bitfield = typeof permissions === 'number' ? permissions : this.constructor.resolve(permissions);
  }

  get member() {
    return this._member;
  }

  set member(value) {
    this._member = value;
  }

  /**
   * Bitfield of the packed permissions
   * @type {number}
   * @see {@link Permissions#bitfield}
   * @deprecated
   * @readonly
   */
  get raw() {
    return this.bitfield;
  }

  set raw(raw) {
    this.bitfield = raw;
  }

  /**
   * Checks whether the bitfield has a permission, or multiple permissions.
   * @param {PermissionResolvable|PermissionResolvable[]} permission Permission(s) to check for
   * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
   * @returns {boolean}
   */
  has(permission, checkAdmin = true) {
    if (permission instanceof Array) return permission.every(p => this.has(p, checkAdmin));
    permission = this.constructor.resolve(permission);
    if (checkAdmin && (this.bitfield & this.constructor.FLAGS.ADMINISTRATOR) > 0) return true;
    return (this.bitfield & permission) === permission;
  }

  /**
   * Gets all given permissions that are missing from the bitfield.
   * @param {PermissionResolvable[]} permissions Permissions to check for
   * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
   * @returns {PermissionResolvable[]}
   */
  missing(permissions, checkAdmin = true) {
    return permissions.filter(p => !this.has(p, checkAdmin));
  }

  /**
   * Adds permissions to this one, creating a new instance to represent the new bitfield.
   * @param {...PermissionResolvable} permissions Permissions to add
   * @returns {Permissions}
   */
  add(...permissions) {
    let total = 0;
    for (let p = 0; p < permissions.length; p++) {
      const perm = this.constructor.resolve(permissions[p]);
      if ((this.bitfield & perm) !== perm) total |= perm;
    }
    return new this.constructor(this.member, this.bitfield | total);
  }

  /**
   * Removes permissions to this one, creating a new instance to represent the new bitfield.
   * @param {...PermissionResolvable} permissions Permissions to remove
   * @returns {Permissions}
   */
  remove(...permissions) {
    let total = 0;
    for (let p = 0; p < permissions.length; p++) {
      const perm = this.constructor.resolve(permissions[p]);
      if ((this.bitfield & perm) === perm) total |= perm;
    }
    return new this.constructor(this.member, this.bitfield & ~total);
  }

  /**
   * Gets an object mapping permission name (like `READ_MESSAGES`) to a {@link boolean} indicating whether the
   * permission is available.
   * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
   * @returns {Object}
   */
  serialize(checkAdmin = true) {
    const serialized = {};
    for (const perm in this.constructor.FLAGS) serialized[perm] = this.has(perm, checkAdmin);
    return serialized;
  }

  /**
   * Checks whether the user has a certain permission, e.g. `READ_MESSAGES`.
   * @param {PermissionResolvable} permission The permission to check for
   * @param {boolean} [explicit=false] Whether to require the user to explicitly have the exact permission
   * @returns {boolean}
   * @see {@link Permissions#has}
   * @deprecated
   */
  hasPermission(permission, explicit = false) {
    return this.has(permission, !explicit);
  }

  /**
   * Checks whether the user has all specified permissions.
   * @param {PermissionResolvable[]} permissions The permissions to check for
   * @param {boolean} [explicit=false] Whether to require the user to explicitly have the exact permissions
   * @returns {boolean}
   * @see {@link Permissions#has}
   * @deprecated
   */
  hasPermissions(permissions, explicit = false) {
    return this.has(permissions, !explicit);
  }

  /**
   * Checks whether the user has all specified permissions, and lists any missing permissions.
   * @param {PermissionResolvable[]} permissions The permissions to check for
   * @param {boolean} [explicit=false] Whether to require the user to explicitly have the exact permissions
   * @returns {PermissionResolvable[]}
   * @see {@link Permissions#missing}
   * @deprecated
   */
  missingPermissions(permissions, explicit = false) {
    return this.missing(permissions, !explicit);
  }

  /**
   * Data that can be resolved to give a permission number. This can be:
   * - A string (see {@link Permissions.FLAGS})
   * - A permission number
   * @typedef {string|number} PermissionResolvable
   */

  /**
   * Resolves permissions to their numeric form.
   * @param {PermissionResolvable|PermissionResolvable[]} permission - Permission(s) to resolve
   * @returns {number}
   */
  static resolve(permission) {
    if (permission instanceof Array) return permission.map(p => this.resolve(p)).reduce((prev, p) => prev | p, 0);
    if (typeof permission === 'string') permission = this.FLAGS[permission];
    if (typeof permission !== 'number' || permission < 1) throw new RangeError(Constants.Errors.NOT_A_PERMISSION);
    return permission;
  }
}

/**
 * Numeric permission flags. All available properties:
 * - `ADMINISTRATOR` (implicitly has *all* permissions, and bypasses all channel overwrites)
 * - `CREATE_INSTANT_INVITE` (create invitations to the guild)
 * - `KICK_MEMBERS`
 * - `BAN_MEMBERS`
 * - `MANAGE_CHANNELS` (edit and reorder channels)
 * - `MANAGE_GUILD` (edit the guild information, region, etc.)
 * - `ADD_REACTIONS` (add new reactions to messages)
 * - `VIEW_AUDIT_LOG`
 * - `READ_MESSAGES`
 * - `SEND_MESSAGES`
 * - `SEND_TTS_MESSAGES`
 * - `MANAGE_MESSAGES` (delete messages and reactions)
 * - `EMBED_LINKS` (links posted will have a preview embedded)
 * - `ATTACH_FILES`
 * - `READ_MESSAGE_HISTORY` (view messages that were posted prior to opening Discord)
 * - `MENTION_EVERYONE`
 * - `USE_EXTERNAL_EMOJIS` (use emojis from different guilds)
 * - `EXTERNAL_EMOJIS` **(deprecated)**
 * - `CONNECT` (connect to a voice channel)
 * - `SPEAK` (speak in a voice channel)
 * - `MUTE_MEMBERS` (mute members across all voice channels)
 * - `DEAFEN_MEMBERS` (deafen members across all voice channels)
 * - `MOVE_MEMBERS` (move members between voice channels)
 * - `USE_VAD` (use voice activity detection)
 * - `CHANGE_NICKNAME`
 * - `MANAGE_NICKNAMES` (change other members' nicknames)
 * - `MANAGE_ROLES`
 * - `MANAGE_ROLES_OR_PERMISSIONS` **(deprecated)**
 * - `MANAGE_WEBHOOKS`
 * - `MANAGE_EMOJIS`
 * @type {Object}
 * @see {@link https://discordapp.com/developers/docs/topics/permissions}
 */
Permissions.FLAGS = {
  CREATE_INSTANT_INVITE: 1 << 0,
  KICK_MEMBERS: 1 << 1,
  BAN_MEMBERS: 1 << 2,
  ADMINISTRATOR: 1 << 3,
  MANAGE_CHANNELS: 1 << 4,
  MANAGE_GUILD: 1 << 5,
  ADD_REACTIONS: 1 << 6,
  VIEW_AUDIT_LOG: 1 << 7,

  READ_MESSAGES: 1 << 10,
  SEND_MESSAGES: 1 << 11,
  SEND_TTS_MESSAGES: 1 << 12,
  MANAGE_MESSAGES: 1 << 13,
  EMBED_LINKS: 1 << 14,
  ATTACH_FILES: 1 << 15,
  READ_MESSAGE_HISTORY: 1 << 16,
  MENTION_EVERYONE: 1 << 17,
  EXTERNAL_EMOJIS: 1 << 18,
  USE_EXTERNAL_EMOJIS: 1 << 18,

  CONNECT: 1 << 20,
  SPEAK: 1 << 21,
  MUTE_MEMBERS: 1 << 22,
  DEAFEN_MEMBERS: 1 << 23,
  MOVE_MEMBERS: 1 << 24,
  USE_VAD: 1 << 25,

  CHANGE_NICKNAME: 1 << 26,
  MANAGE_NICKNAMES: 1 << 27,
  MANAGE_ROLES: 1 << 28,
  MANAGE_ROLES_OR_PERMISSIONS: 1 << 28,
  MANAGE_WEBHOOKS: 1 << 29,
  MANAGE_EMOJIS: 1 << 30,
};

/**
 * Bitfield representing every permission combined
 * @type {number}
 */
Permissions.ALL = Object.keys(Permissions.FLAGS).reduce((all, p) => all | Permissions.FLAGS[p], 0);

/**
 * Bitfield representing the default permissions for users
 * @type {number}
 */
Permissions.DEFAULT = 104324097;

/**
 * @class EvaluatedPermissions
 * @classdesc The final evaluated permissions for a member in a channel
 * @see {@link Permissions}
 * @deprecated
 */

Permissions.prototype.hasPermission = util.deprecate(Permissions.prototype.hasPermission,
  'EvaluatedPermissions#hasPermission is deprecated, use Permissions#has instead');
Permissions.prototype.hasPermissions = util.deprecate(Permissions.prototype.hasPermissions,
  'EvaluatedPermissions#hasPermissions is deprecated, use Permissions#has instead');
Permissions.prototype.missingPermissions = util.deprecate(Permissions.prototype.missingPermissions,
  'EvaluatedPermissions#missingPermissions is deprecated, use Permissions#missing instead');
Object.defineProperty(Permissions.prototype, 'member', {
  get: util
        .deprecate(Object.getOwnPropertyDescriptor(Permissions.prototype, 'member').get,
        'EvaluatedPermissions#member is deprecated'),
});

module.exports = Permissions;
<|endoftext|>


<commit_before>import { useEffect, useState, useDebugValue, useRef } from 'react';
import TrackPlayer from './trackPlayer';
import TrackPlayerEvents from './eventTypes';

/**
 * @description
 *   Get current playback state and subsequent updates
 */
const usePlaybackState = () => {
    const [state, setState] = useState(TrackPlayer.STATE_NONE)

    useEffect(() => {
        async function setPlayerState() {
            const playerState = await TrackPlayer.getState()
            setState(playerState)
        }

        setPlayerState()

        const sub = TrackPlayer.addEventListener(TrackPlayerEvents.PLAYBACK_STATE, data => {
            setState(data.state)
        })

        return () => {
            sub.remove()
        }
    }, [])

    return state
}

/**
 * @description
 *   Attaches a handler to the given TrackPlayer events and performs cleanup on unmount
 * @param {Array<string>} events - TrackPlayer events to subscribe to
 * @param {(payload: any) => void} handler - callback invoked when the event fires
 */
const useTrackPlayerEvents = (events, handler) => {
    const savedHandler = useRef();

    useEffect(() => {
        savedHandler.current = handler;
    }, [handler]);

    useEffect(
        () => {
            if (__DEV__) {
                const allowedTypes = Object.values(TrackPlayerEvents);
                const invalidTypes = events.filter(type => !allowedTypes.includes(type));
                if (invalidTypes.length) {
                    console.warn(
                        'One or more of the events provided to useTrackPlayerEvents is ' +
                        `not a valid TrackPlayer event: ${invalidTypes.join('\', \'')}. ` +
                        'A list of available events can be found at ' +
                        'https://react-native-kit.github.io/react-native-track-player/documentation/#events'
                    )
                }
            }

            const subs = events.map(event =>
                TrackPlayer.addEventListener(event,
                    (payload) => savedHandler.current({ ...payload, type: event })
                )
            );

            return () => {
                subs.forEach(sub => sub.remove());
            }
        },
        events
    );
}

const useInterval = (callback, delay) => {
    const savedCallback = useRef();

    useEffect(() => {
        savedCallback.current = callback;
    })

    useEffect(() => {
        if (!delay) return;
        const id = setInterval(savedCallback.current, delay);
        return () => clearInterval(id);
    }, [delay]);
}

const useWhenPlaybackStateChanges = callback => {
    useTrackPlayerEvents(
        [TrackPlayerEvents.PLAYBACK_STATE],
        ({ state }) => {
            callback(state);
        }
    );
    useEffect(() => {
        let didCancel = false;
        const fetchPlaybackState = async () => {
            const playbackState = await TrackPlayer.getState();
            if (!didCancel) {
                callback(playbackState);
            }
        }
        fetchPlaybackState();
        return () => { didCancel = true };
    }, []);
}

const usePlaybackStateIs = (...states) => {
    const [is, setIs] = useState();
    useWhenPlaybackStateChanges(state => {
        setIs(states.includes(state));
    });

    return is;
}

/**
 * @description
 *   Poll for track progress for the given interval (in miliseconds)
 * @param {number} interval - ms interval
 * @param {Array<TrackPlayerState> | null} pollTrackPlayerStates - TrackPlayer states on which the track progress should be polled. If null is provided, the track progress will be polled every `interval` seconds.
 * @returns {[
 *   {
 *      progress: number,
 *      bufferedPosition: number,
 *      duration: number
 *   },
 *   (interval: number) => void
 * ]}
 */
const useTrackPlayerProgress = (
    interval = 1000,
    pollTrackPlayerStates = [
        TrackPlayer.STATE_PLAYING,
        TrackPlayer.STATE_BUFFERING,
    ]
) => {
    const initialState = {
        position: 0,
        bufferedPosition: 0,
        duration: 0,
    };

    const [state, setState] = useState(initialState);

    const getProgress = async () => {
        const [position, bufferedPosition, duration] = await Promise.all([
            TrackPlayer.getPosition(),
            TrackPlayer.getBufferedPosition(),
            TrackPlayer.getDuration(),
        ]);
        setState({ position, bufferedPosition, duration });
    };

    let needsPoll = true;
    if (pollTrackPlayerStates) {
        needsPoll = usePlaybackStateIs(...pollTrackPlayerStates);
    }

    useInterval(getProgress, needsPoll ? interval : null);
    return state;
};

// Exports
module.exports.usePlaybackState = usePlaybackState
module.exports.useTrackPlayerEvents = useTrackPlayerEvents
module.exports.useInterval = useInterval
module.exports.useWhenPlaybackStateChanges = useWhenPlaybackStateChanges
module.exports.usePlaybackStateIs = usePlaybackStateIs
module.exports.useTrackPlayerProgress = useTrackPlayerProgress
<commit_msg>[js] Fix(progress): progress reflects previous track (#1073)<commit_after>import { useEffect, useState, useDebugValue, useRef } from 'react';
import TrackPlayer from './trackPlayer';
import TrackPlayerEvents from './eventTypes';

/**
 * @description
 *   Get current playback state and subsequent updates
 */
const usePlaybackState = () => {
    const [state, setState] = useState(TrackPlayer.STATE_NONE)

    useEffect(() => {
        async function setPlayerState() {
            const playerState = await TrackPlayer.getState()
            setState(playerState)
        }

        setPlayerState()

        const sub = TrackPlayer.addEventListener(TrackPlayerEvents.PLAYBACK_STATE, data => {
            setState(data.state)
        })

        return () => {
            sub.remove()
        }
    }, [])

    return state
}

/**
 * @description
 *   Attaches a handler to the given TrackPlayer events and performs cleanup on unmount
 * @param {Array<string>} events - TrackPlayer events to subscribe to
 * @param {(payload: any) => void} handler - callback invoked when the event fires
 */
const useTrackPlayerEvents = (events, handler) => {
    const savedHandler = useRef();

    useEffect(() => {
        savedHandler.current = handler;
    }, [handler]);

    useEffect(
        () => {
            if (__DEV__) {
                const allowedTypes = Object.values(TrackPlayerEvents);
                const invalidTypes = events.filter(type => !allowedTypes.includes(type));
                if (invalidTypes.length) {
                    console.warn(
                        'One or more of the events provided to useTrackPlayerEvents is ' +
                        `not a valid TrackPlayer event: ${invalidTypes.join('\', \'')}. ` +
                        'A list of available events can be found at ' +
                        'https://react-native-kit.github.io/react-native-track-player/documentation/#events'
                    )
                }
            }

            const subs = events.map(event =>
                TrackPlayer.addEventListener(event,
                    (payload) => savedHandler.current({ ...payload, type: event })
                )
            );

            return () => {
                subs.forEach(sub => sub.remove());
            }
        },
        events
    );
}

const useInterval = (callback, delay) => {
    const savedCallback = useRef();

    useEffect(() => {
        savedCallback.current = callback;
    })

    useEffect(() => {
        if (!delay) return;
        savedCallback.current();
        const id = setInterval(savedCallback.current, delay);
        return () => clearInterval(id);
    }, [delay]);
}

const useWhenPlaybackStateChanges = callback => {
    useTrackPlayerEvents(
        [TrackPlayerEvents.PLAYBACK_STATE],
        ({ state }) => {
            callback(state);
        }
    );
    useEffect(() => {
        let didCancel = false;
        const fetchPlaybackState = async () => {
            const playbackState = await TrackPlayer.getState();
            if (!didCancel) {
                callback(playbackState);
            }
        }
        fetchPlaybackState();
        return () => { didCancel = true };
    }, []);
}

const usePlaybackStateIs = (...states) => {
    const [is, setIs] = useState();
    useWhenPlaybackStateChanges(state => {
        setIs(states.includes(state));
    });

    return is;
}

/**
 * @description
 *   Poll for track progress for the given interval (in miliseconds)
 * @param {number} interval - ms interval
 * @param {Array<TrackPlayerState> | null} pollTrackPlayerStates - TrackPlayer states on which the track progress should be polled. If null is provided, the track progress will be polled every `interval` seconds.
 * @returns {[
 *   {
 *      progress: number,
 *      bufferedPosition: number,
 *      duration: number
 *   },
 *   (interval: number) => void
 * ]}
 */
const useTrackPlayerProgress = (
    interval = 1000,
    pollTrackPlayerStates = [
        TrackPlayer.STATE_PLAYING,
        TrackPlayer.STATE_BUFFERING,
    ]
) => {
    const initialState = {
        position: 0,
        bufferedPosition: 0,
        duration: 0,
    };

    const [state, setState] = useState(initialState);

    const getProgress = async () => {
        const [position, bufferedPosition, duration] = await Promise.all([
            TrackPlayer.getPosition(),
            TrackPlayer.getBufferedPosition(),
            TrackPlayer.getDuration(),
        ]);
        setState({ position, bufferedPosition, duration });
    };

    let needsPoll = true;
    if (pollTrackPlayerStates) {
        needsPoll = usePlaybackStateIs(...pollTrackPlayerStates);
    }

    useInterval(getProgress, needsPoll ? interval : null);
    return state;
};

// Exports
module.exports.usePlaybackState = usePlaybackState
module.exports.useTrackPlayerEvents = useTrackPlayerEvents
module.exports.useInterval = useInterval
module.exports.useWhenPlaybackStateChanges = useWhenPlaybackStateChanges
module.exports.usePlaybackStateIs = usePlaybackStateIs
module.exports.useTrackPlayerProgress = useTrackPlayerProgress
<|endoftext|>


<commit_before>var switcher = {};

switcher.vars = {
	_enemyArr: [],
	_enemyElemCache: null,
	_enemiesEnabled: false
};

// Вызывается во всех методах
switcher.vars._enemyObserver = function(thatObj) {

	var
		vars 	= switcher.vars;
		obj 	= vars._enemyArr,
		i 		= vars._enemyArr.length,
		cache	= vars._enemyElemCache;

	// Если есть кеш преыдущего объекта
	if(vars._enemyElemCache) {

		vars._enemyElemCache.clearCache(); // очищаем кеш повторного нажатия, в предыдущем объекте из массива

		// Если это повторное нажатие, выходим
		if(Object.getPrototypeOf(vars._enemyElemCache) === thatObj) {
			return true;
		}

	}

	// Обходим все объекты в массиве enemies
	while(i--) {

		// Если есть кеш
		if(vars._enemyElemCache) {

			// Если это тот элемент на котором кликнули
			if(Object.getPrototypeOf(obj[i]) === thatObj) {

				// Если не первый раз запускается, то выключаем элемент который ранее был включен
				vars._enemyElemCache.turnOff();
				vars._enemyElemCache = obj[i]; // кешируем текущий

				//break;
			}

		} else {

			vars._enemyElemCache = obj[i]; // кешируем текущий

		}

	}

};

// Добавляет объекты в массив
switcher.enemies = function() {
	var
		args 	= arguments,
		i 		= args.length,
		vars 	= switcher.vars,
		arr		= vars._enemyArr;

	// Активизируем метод _enemyObserver
	if(i > 0) {
		vars._enemiesEnabled = true;
	}

	// Добавляем элементы
	while(i--) {
		if(typeof args[i] === "object") {
			arr.push(args[i]);
		}
	}

};

friends = function() {

};

switcher.items = function (userConfig) {

	// =============================== Vars
	var
		R = {},
		_cacheElement, // Для выключения элемента, который ранее был включен
		_lock = false, // Включается методом .stop(). Если true, перестает реагировать на события, пока не будет вызван метод .next()

		// enemies
		_SwVars = switcher.vars,
		_enemyObserver = _SwVars._enemyObserver;	// Наблюдатель

		// Конфиг
		R._cfg = {
			eventMethod: "click",
			backClickTurnOff: false
		};

		// Блоки
		R._blocks = {
			arr: null,
			turnOn: function() { this.style.display = "block"; },
			turnOff: function() { this.style.display = "none"; }
		};

		// Табы, для переключения блоков
		R._tabs = {
			parentElem: null,
			arr: null,
			turnOn: function() {},
			turnOff: function() {}
		};

	// end vars

	// =============================== Methods

	// Обработчик событий, который вызывает методы turnOn
	R._listener = function () {

		// Если есть родительский элемент, то вешаем один обработчик
		if(R._tabs.parentElem) {
			R._tabs.parentElem.addEventListener(R._cfg.eventMethod, function(e) {

				// Блокировщик событий .stop() / .next()
				if(!_lock) {
					R.turnOn(e.target);
				}

			});
		} else {
			// Вешаем обработчики на все элементы, если нет родительского id
			// Реализация отложена
			console.log('not found parentElem');
		}
	};

	// Возвращает id из quey строки. #abc li a => abc.
	R._getId = function (str) {
		return document.getElementById(str.match(/#([\w\d_-]+)/i)[1]);
	};

	// =============================== Public Methods

	// Очищает кеш повторного нажатия, нужен для enemies
	R.clearCache = function() {
		_cacheElement = null;
	};

	// Перестает реагировать на события, например пока анимация не завершится
	R.stop = function () {
		_lock = true;
	};

	// Возобновляет реагирование на события
	R.next = function () {
		_lock = false;
	};

	// Добавляет блоки
	R.addBlocks = function (QSA, turnOn, turnOff) {

		R._blocks.arr 		= 	document.querySelectorAll(QSA);

		if(typeof turnOn === "function") {
			R._blocks.turnOn	= 	turnOn;
		}

		if(typeof turnOff === "function") {
			R._blocks.turnOff	= 	turnOff;
		}

	};

	// Добавляет табы-переключатели
	R.addTabs = function (QSA, turnOn, turnOff) {

		R._tabs.arr 		= 	document.querySelectorAll(QSA);
		R._tabs.parentElem	=	R._getId(QSA);

		if(typeof turnOn === "function") {
			R._tabs.turnOn		=	turnOn;
		}

		if(typeof turnOff === "function") {
			R._tabs.turnOff		=	turnOff;
		}

		R._listener(); // обработчик событий
	};

	// Выключает предыдущий элемент
	R.turnOff = function() {

		var
			i 		= R._tabs.arr.length,
			tabs 	= R._tabs,
			blocks	= R._blocks;

		// Если первый запуск, отключаем все элементы
		if(typeof _cacheElement !== "number") {

			while(i--) {

				blocks.turnOff.call(blocks.arr[i]);

				if(tabs.turnOff) {
					tabs.turnOff.call(tabs.arr[i]);
				}

			}

		} else { // Все последующие запуски, после очистки

			// Выключаем предыдущие элементы, блоки и табы
			blocks.turnOff.call(blocks.arr[_cacheElement]);

			if(tabs.turnOff) {
				tabs.turnOff.call(tabs.arr[_cacheElement]);
			}

		}

	}

	// Сначала все выключает, а потом включает конкретный блок и таб, по индексу или по e.target
	R.turnOn = function(ObjOrNum) {

		var
			check, // функция проверки меняет условия в зависимости от параметров.  Цифра/Объект
			arrLn	= R._tabs.arr.length,
			i		= arrLn,
			tabs 	= R._tabs,
			blocks	= R._blocks,
			cfg		= R._cfg;

		// формирование функции + дополнительная проверка на допустимый лимит в цифрах
		switch(typeof ObjOrNum) {
			case "object":

				check = function(i) {
					if(ObjOrNum === tabs.arr[i]) return true; else return false;
				};

			break;
			case "number":

				// Проверка допустимого лимита
				if(ObjOrNum > (arrLn-1) || ObjOrNum < 0) {
					return false;
				}

				check = function(i) {
					if(ObjOrNum === i) return true; else return false;
				};

			break;
			default:
				return false;
			break;
		}

		// Включает конкретный блок и таб
		while(i--) {
			if(check(i)) {

				// Если повторный клик по тому же элементу
				if(_cacheElement === i) {

					// Если true, тогда при повторном нажатии на таб, применяется метод turnOff
					if(cfg.backClickTurnOff) {

						R.turnOff();
						_cacheElement = null;

					} else return true;

				} else {

					// Выключает ранее включенный элемент
					R.turnOff();

					// Если наблюдатель активирован (вызван метод enemies с аргументами - объектами), то запускаем
					if(_SwVars._enemiesEnabled) {
						_enemyObserver(this);
					}

					// Включение блоков
					blocks.turnOn.call(blocks.arr[i]);

					// и табов
					if(tabs.turnOn) {
						tabs.turnOn.call(tabs.arr[i]);
					}

					// Кешируем элемент который собираемся включить, чтобы потом его же и отключить
					_cacheElement = i;

					// Выходим, т.к. нашли то что искали
					break;
				}

			}

		}

	}

	// =============================== init

	// Установка конфига, если есть
	if(typeof userConfig === "object") {

		for(var k in userConfig) {

			// Если в новом конфиге есть такие же свойства как и в локальном, то принимаем новые значения
			if(R._cfg.hasOwnProperty(k)) {
				R._cfg[k] = userConfig[k];
			}

		}

	}

	// Новый экземпляр
	return Object.create(R);
};
<commit_msg>add friends method<commit_after>var switcher = {};

switcher.vars = {
	_enemyArr: [],
	_enemyElemCache: null,
	_enemiesEnabled: false,

	_friendsArgsArr: []
};

// Вызывается во всех методах
switcher.vars._enemyObserver = function(thatObj) {

	// thatObj - Объект элемент по которому кликнули

	var
		vars 				= switcher.vars,
		obj 				= vars._enemyArr,
		i 					= vars._enemyArr.length,
		cache				= vars._enemyElemCache;

	// Если есть кеш предыдущего объекта
	if(vars._enemyElemCache) {

		// Очищаем кеш повторного нажатия, в предыдущем объекте из массива
		vars._enemyElemCache.clearCache();

		// Проверяем дружественные объекты, если есть выходим и не даем их отключить
		if(vars.checkFriends(thatObj, vars._enemyElemCache)) {
			return true;
		}

		// Если это повторное нажатие, выходим
		if(Object.getPrototypeOf(vars._enemyElemCache) === thatObj) {
			return true;
		}

	}

	// Обходим все объекты в массиве enemies
	while(i--) {

		// Если есть кеш
		if(vars._enemyElemCache) {

			// Если это тот элемент на котором кликнули
			if(Object.getPrototypeOf(obj[i]) === thatObj) {

				// Если не первый раз запускается, то выключаем элемент который ранее был включен
				vars._enemyElemCache.turnOff();
				vars._enemyElemCache = obj[i]; // кешируем текущий

				if(vars._friendsArgsArr.length > 0) {

					// Отключение активных объектов из addFriends
					vars._turnOffAllFriends();

				}

				//break;
			}

		} else {

			vars._enemyElemCache = obj[i]; // кешируем текущий

		}

	}

};

// Добавляет объекты в массив
switcher.addEnemies = function() {

	var
		args 	= arguments,
		i 		= args.length,
		vars 	= switcher.vars;

	// Активизируем метод _enemyObserver
	if(i > 0) {
		vars._enemiesEnabled = true;
	}

	// Добавляем элементы
	while(i--) {
		if(typeof args[i] === "object") {
			vars._enemyArr.push(args[i]);
		}
	}

};

// Добавляет группы-объектов которые не будут выключены после addEnemies
switcher.addFriends = function() {

	var
		args 	= arguments,
		i 		= args.length,
		e		= 0,
		k		= 0;

		switcher.vars._friendsArgsArr = args;

	// По аргументам
	while(i--) {
		if(Array.isArray(args[i])) {
			//vars._friendsArr.push(args[i]);
			e = args[i].length;

			// По массиву в одном из аргументов
			while(e--) {

				k = args[i].length;

				// По тому же массиву, добавляя соседние объекты, при этом исключив себя
				while(k--) {

					// Если находим себя, то пропускаем
					if(args[i][e] !== args[i][k]) {

						// Добавляем дружественные объекты в массив
						args[i][e]._friendsObjArr.push(args[i][k]);

					}

				}

			}

		}
	}

};

// Отключает все дружественные элементы. Т.к. кеш тут не срабатывает из-за кол-ва активных
switcher.vars._turnOffAllFriends = function() {

	var
		vars 	= switcher.vars,
		arr 	= vars._friendsArgsArr,
		i		= arr.length;

	// По аргументам
	while(i--) {
		if(Array.isArray(arr[i])) {

			e = arr[i].length;

			// По массиву в одном из аргументов
			while(e--) {

				k = arr[i].length;

				// По тому же массиву
				while(k--) {

					// Если находим себя, то пропускаем
					if(arr[i][e] !== arr[i][k]) {

						// Отключаем
						arr[i][e].clearCache();
						arr[i][e].turnOff();

					}

				}

			}

		}
	}

};

// Проверяет дружественные объекты. Метод не дает отключить дружественные объекты, если они включаются друг с другом. Но отключаются при активации других из enemies
switcher.vars.checkFriends = function(clickObj, cacheObj) {

	var
		arr 	= clickObj._friendsObjArr,
		i 		= clickObj._friendsObjArr.length;

	// Элементы объекта по которому кликнули сравниваются с предыдущем объектом из кеша
	while(i--) {
		if(arr[i] === cacheObj) {
			return true;
		}
	}

	return false;
};

// Основной метод
switcher.items = function (userConfig) {

	// =============================== Vars
	var
		R = {},
		_cacheElement, // Для выключения элемента, который ранее был включен
		_lock = false, // Включается методом .stop(). Если true, перестает реагировать на события, пока не будет вызван метод .next()

		// enemies
		_SwVars = switcher.vars,
		_enemyObserver = _SwVars._enemyObserver;	// Метод наблюдателя.

		// friends
		R._friendsObjArr = []; // массив с дружественными объектами

		// Конфиг
		R._cfg = {
			eventMethod: "click",
			backClickTurnOff: false
		};

		// Блоки
		R._blocks = {
			arr: null,
			turnOn: function() { this.style.display = "block"; },
			turnOff: function() { this.style.display = "none"; }
		};

		// Табы, для переключения блоков
		R._tabs = {
			parentElem: null,
			arr: null,
			turnOn: function() {},
			turnOff: function() {}
		};

	// end vars

	// =============================== Methods

	// Обработчик событий, который вызывает методы turnOn
	R._listener = function () {

		// Если есть родительский элемент, то вешаем один обработчик
		if(R._tabs.parentElem) {
			R._tabs.parentElem.addEventListener(R._cfg.eventMethod, function(e) {

				// Блокировщик событий .stop() / .next()
				if(!_lock) {
					R.turnOn(e.target);
				}

			});
		} else {
			// Вешаем обработчики на все элементы, если нет родительского id
			// Реализация отложена
			console.log('not found parentElem');
		}
	};

	// Возвращает id из query строки. #abc li a => abc.
	R._getId = function (str) {
		return document.getElementById(str.match(/#([\w\d_-]+)/i)[1]);
	};

	// =============================== Public Methods

	// Очищает кеш повторного нажатия, нужен для enemies
	R.clearCache = function() {
		_cacheElement = null;
	};

	// Перестает реагировать на события, например пока анимация не завершится
	R.stop = function () {
		_lock = true;
	};

	// Возобновляет реагирование на события
	R.next = function () {
		_lock = false;
	};

	// Добавляет блоки
	R.addBlocks = function (QSA, turnOn, turnOff) {

		R._blocks.arr 	= 	document.querySelectorAll(QSA);

		if(typeof turnOn === "function") {
			R._blocks.turnOn	= 	turnOn;
		}

		if(typeof turnOff === "function") {
			R._blocks.turnOff	= 	turnOff;
		}

	};

	// Добавляет табы-переключатели
	R.addTabs = function (QSA, turnOn, turnOff) {

		R._tabs.arr 		= 	document.querySelectorAll(QSA);
		R._tabs.parentElem	=	R._getId(QSA);

		if(typeof turnOn === "function") {
			R._tabs.turnOn		=	turnOn;
		}

		if(typeof turnOff === "function") {
			R._tabs.turnOff		=	turnOff;
		}

		R._listener(); // обработчик событий
	};

	// Выключает предыдущий элемент
	R.turnOff = function() {

		var
			i 		= R._tabs.arr.length,
			tabs 	= R._tabs,
			blocks	= R._blocks;

		// Если первый запуск, отключаем все элементы
		if(typeof _cacheElement !== "number") {

			while(i--) {

				blocks.turnOff.call(blocks.arr[i]);

				if(tabs.turnOff) {
					tabs.turnOff.call(tabs.arr[i]);
				}

			}

		} else { // Все последующие запуски, после очистки

			// Выключаем предыдущие элементы, блоки и табы
			blocks.turnOff.call(blocks.arr[_cacheElement]);

			if(tabs.turnOff) {
				tabs.turnOff.call(tabs.arr[_cacheElement]);
			}

		}

	}

	// Сначала все выключает, а потом включает конкретный блок и таб, по индексу или по e.target
	R.turnOn = function(ObjOrNum) {

		var
			check, // функция проверки меняет условия в зависимости от параметров.  Цифра/Объект
			arrLn	= R._tabs.arr.length,
			i		= arrLn,
			tabs 	= R._tabs,
			blocks	= R._blocks,
			cfg		= R._cfg;

		// формирование функции + дополнительная проверка на допустимый лимит в цифрах
		switch(typeof ObjOrNum) {
			case "object":

				check = function(i) {
					if(ObjOrNum === tabs.arr[i]) return true; else return false;
				};

			break;
			case "number":

				// Проверка допустимого лимита
				if(ObjOrNum > (arrLn-1) || ObjOrNum < 0) {
					return false;
				}

				check = function(i) {
					if(ObjOrNum === i) return true; else return false;
				};

			break;
			default:
				return false;
			break;
		}

		// Включает конкретный блок и таб
		while(i--) {
			if(check(i)) {

				// Если повторный клик по тому же элементу
				if(_cacheElement === i) {

					// Если true, тогда при повторном нажатии на таб, применяется метод turnOff
					if(cfg.backClickTurnOff) {

						R.turnOff();
						_cacheElement = null;

					} else return true;

				} else {

					// Выключает ранее включенный элемент
					R.turnOff();

					// Если наблюдатель активирован (вызван метод enemies с аргументами - объектами), то запускаем
					if(_SwVars._enemiesEnabled) {
						_enemyObserver(this);
					}

					// Включение блоков
					blocks.turnOn.call(blocks.arr[i]);

					// и табов
					if(tabs.turnOn) {
						tabs.turnOn.call(tabs.arr[i]);
					}

					// Кешируем элемент который собираемся включить, чтобы потом его же и отключить
					_cacheElement = i;

					// Выходим, т.к. нашли то что искали
					break;
				}

			}

		}

	}

	// =============================== init

	// Установка конфига, если есть
	if(typeof userConfig === "object") {

		for(var k in userConfig) {

			// Если в новом конфиге есть такие же свойства как и в локальном, то принимаем новые значения
			if(R._cfg.hasOwnProperty(k)) {
				R._cfg[k] = userConfig[k];
			}

		}

	}

	// Новый экземпляр
	return Object.create(R);
};
<|endoftext|>


<commit_before>'use strict';

const debug = require('debug')('xsd2jsonschema:BaseConversionVisitor');

const Visitor = require('./visitor');
const XsdElements = require('./../xmlschema/xsdElements');
const State = require('./../parsingState').State;

/**
 * Class representing a visitor.  Vistors are utilized by {@link DepthFirstTraversal} to process each node within an XML
 * Schema file.  This base implmention simply calls the processor member's process() method to facilitate conversion
 * from XMLSchema to JSON Schema.  It also adds error handling.
 */

 class BaseConversionVisitor extends Visitor {

	/**
	 * Constructs an instance of BaseConversionVisiter.
	 * @constructor
	 * @param {Processor} processor - {@link ConverterDraft04} or a subclass of {@link Processor}
	 */
	constructor(processor) {
		super(processor);
	}

	/**
	 * Utilizes {@link module:ParsingState|ParsingState} to push the current elment name (or state) to a stack.  When convertion begins for a given element this method is called.  When conversion ends for the same element the {@link BaseConversionVisitor#exitState|exitState()} method is called.   The stack of element names (or states) represents current depth of the conversion process within {@link XsdFile|xsd}.
	 *
	 * @param {Node} node - The current element in xsd being converted.
	 * @param {JsonSchemaFile} jsonSchema - The JSON Schema representing the current XML Schema file {@link XsdFile|xsd} being converted.
	 * @param {XsdFile} xsd - The XML schema file currently being converted.
	 */
	enterState(node, jsonSchema, xsd) {
		var state = new State({
			node: node
		});
		this.processor.parsingState.enterState(state);
	}

	/**
	 * Utilizes {@link module:ParsingState|ParsingState} to pop and element (or state) from a stack of element nodes.  The stack
	 * of element names (or states) represents current depth of the conversion process within {@link XsdFile|xsd}.
	 *
	 * @param {Node} node - The current element in xsd being converted.
	 * @param {JsonSchemaFile} jsonSchema - The JSON Schema representing the current XML Schema file {@link XsdFile|xsd} being converted.
	 * @param {XsdFile} xsd - The XML schema file currently being converted.
	 */
	exitState(node, jsonSchema, xsd) {
		var state = this.processor.parsingState.exitState();
		if (state.workingJsonSchema !== undefined) {
			this.processor.workingJsonSchema = state.workingJsonSchema;
		}
		/**
		 * <simpleType> tags that take advantage of <restriction> tags are converted to JsonSchema utilizing allOf.  It is
		 * possible a <simpleType> doesn't contain anything meaningful other than the restriction.  In this case the conversion
		 * will end with an empty JsonSchema in the simpleType's allOf array.  To correct this empty JsonSchema's are removed
		 * from a sympleType's allOf array.  Example:
		 * <xs:simpleType name='SomeSimpleType'>
		 * 		<xs:annotation>
		 * 			<xs:documentation xml:lang='en'>Blah Blah Blah</xs:documentation>
		 * 		</xs:annotation>
		 * 		<xs:restriction base='SomeBaseType'/>
		 * </xs:simpleType>
		 */
		if (state.name === XsdElements.SIMPLE_TYPE && this.processor.workingJsonSchema !== undefined) {
			this.processor.workingJsonSchema.removeEmptySchemas();
		}
	}

	/**
	 * This method is called before conversion of {@link XsdFile|xsd} is started.  Subclasss can override this method to implement class
	 * specific pre-processing behavior.  The default implementation logs a message and returns true to allow conversion to start.
	 *
	 * @param {JsonSchemaFile} jsonSchema - The JSON Schema file that will represent converted XML Schema file {@link XsdFile|xsd}.
	 * @param {XsdFile} xsd - The XML schema file about to be processed.
	 *
	 * @returns {Boolean} - True.  Subclasses can return false to cancel traversal of {@link XsdFile|xsd}
	 */
	onBegin(jsonSchema, xsd) {
		debug('\n\n****************************************************************************************************');
		debug('Converting ' + xsd.filename);
		debug('****************************************************************************************************\n');
		return true;
	}

	/**
	 * This method is called after conversion of {@link XsdFile|xsd} has completed.  Subclasss can override this method to implement
	 * class specific post-processing behavior.  The default implementation calls {@link ConverterDraft04#processSpecialCases|ConverterDraft04.processSpecialCases()}.
	 *
	 * @param {JsonSchemaFile} jsonSchema - The resulting JSON Schema file from the conversion.
	 * @param {XsdFile} xsd - The XML Schema file {@link XsdFile|xsd} that was just converted.
	 *
	 * @returns {Boolean} - Returns true if the xml schema file needs to be reprocessed due to forward references or otherwise.
	 */
	onEnd(jsonSchema, xsd) {
		this.processor.processSpecialCases();
		return this.processor.anotherPassNeeded
	}

}

module.exports = BaseConversionVisitor;<commit_msg>Mintor jsdoc updates<commit_after>'use strict';

const debug = require('debug')('xsd2jsonschema:BaseConversionVisitor');

const Visitor = require('./visitor');
const XsdElements = require('./../xmlschema/xsdElements');
const State = require('./../parsingState').State;

/**
 * Class representing a visitor.  Vistors are utilized by {@link DepthFirstTraversal} to process each node within an XML
 * Schema file.  This base implmention simply calls the processor member's process() method to facilitate conversion
 * from XMLSchema to JSON Schema.  It also adds error handling.
 */

 class BaseConversionVisitor extends Visitor {

	/**
	 * Constructs an instance of BaseConversionVisiter.
	 * @constructor
	 * @param {Processor} processor - {@link ConverterDraft04} or a subclass of {@link Processor}
	 */
	constructor(processor) {
		super(processor);
	}

	/**
	 * Utilizes {@link module:ParsingState|ParsingState} to push the current elment name (or state) to a stack.  When convertion begins for a given element this method is called.  When conversion ends for the same element the {@link BaseConversionVisitor#exitState|exitState()} method is called.   The stack of element names (or states) represents current depth of the conversion process within {@link XsdFile|xsd}.
	 *
	 * @param {Node} node - The current element in xsd being converted.
	 * @param {JsonSchemaFile} jsonSchema - The JSON Schema representing the current XML Schema file {@link XsdFile|xsd} being converted.
	 * @param {XsdFile} xsd - The XML schema file currently being converted.
	 *
	 * @return {undefined}
	 */
	enterState(node, jsonSchema, xsd) {
		var state = new State({
			node: node
		});
		this.processor.parsingState.enterState(state);
	}

	/**
	 * Utilizes {@link module:ParsingState|ParsingState} to pop and element (or state) from a stack of element nodes.  The stack
	 * of element names (or states) represents current depth of the conversion process within {@link XsdFile|xsd}.
	 *
	 * @param {Node} node - The current element in xsd being converted.
	 * @param {JsonSchemaFile} jsonSchema - The JSON Schema representing the current XML Schema file {@link XsdFile|xsd} being converted.
	 * @param {XsdFile} xsd - The XML schema file currently being converted.
	 *
	 * @return {undefined}
	 */
	exitState(node, jsonSchema, xsd) {
		var state = this.processor.parsingState.exitState();
		if (state.workingJsonSchema !== undefined) {
			this.processor.workingJsonSchema = state.workingJsonSchema;
		}
		/**
		 * <simpleType> tags that take advantage of <restriction> tags are converted to JsonSchema utilizing allOf.  It is
		 * possible a <simpleType> doesn't contain anything meaningful other than the restriction.  In this case the conversion
		 * will end with an empty JsonSchema in the simpleType's allOf array.  To correct this empty JsonSchema's are removed
		 * from a sympleType's allOf array.  Example:
		 * <xs:simpleType name='SomeSimpleType'>
		 * 		<xs:annotation>
		 * 			<xs:documentation xml:lang='en'>Blah Blah Blah</xs:documentation>
		 * 		</xs:annotation>
		 * 		<xs:restriction base='SomeBaseType'/>
		 * </xs:simpleType>
		 */
		if (state.name === XsdElements.SIMPLE_TYPE && this.processor.workingJsonSchema !== undefined) {
			this.processor.workingJsonSchema.removeEmptySchemas();
		}
	}

	/**
	 * This method is called before conversion of {@link XsdFile|xsd} is started.  Subclasss can override this method to implement class
	 * specific pre-processing behavior.  The default implementation logs a message and returns true to allow conversion to start.
	 *
	 * @param {JsonSchemaFile} jsonSchema - The JSON Schema file that will represent converted XML Schema file {@link XsdFile|xsd}.
	 * @param {XsdFile} xsd - The XML schema file about to be processed.
	 *
	 * @returns {Boolean} - True.  Subclasses can return false to cancel traversal of {@link XsdFile|xsd}
	 */
	onBegin(jsonSchema, xsd) {
		debug('\n\n****************************************************************************************************');
		debug('Converting ' + xsd.filename);
		debug('****************************************************************************************************\n');
		return true;
	}

	/**
	 * This method is called after conversion of {@link XsdFile|xsd} has completed.  Subclasss can override this method to implement
	 * class specific post-processing behavior.  The default implementation calls {@link ConverterDraft04#processSpecialCases|ConverterDraft04.processSpecialCases()}.
	 *
	 * @param {JsonSchemaFile} jsonSchema - The resulting JSON Schema file from the conversion.
	 * @param {XsdFile} xsd - The XML Schema file {@link XsdFile|xsd} that was just converted.
	 *
	 * @returns {Boolean} - Returns true if the xml schema file needs to be reprocessed due to forward references or otherwise.
	 */
	onEnd(jsonSchema, xsd) {
		this.processor.processSpecialCases();
		return this.processor.anotherPassNeeded
	}

}

module.exports = BaseConversionVisitor;<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'

import styles from './style.css'

/*
 * Adapt flex-box based grid for the layout. It is much easier to work with
 * than bootstrap3/patternfly grids.
 */
const Grid = ({ className = '', children, style, ...props }) => {
  const cn = `${styles['grid-container']} ${className}`
  return
{children}

}
Grid.propTypes = {
  children: PropTypes.node.isRequired,
  className: PropTypes.string,
  style: PropTypes.object,
}

const Row = ({ className = '', children, style, id }) => {
  const cn = `${styles['grid-row']} ${className}`
  return
{children}

}
Row.propTypes = {
  children: PropTypes.node.isRequired,
  id: PropTypes.string,
  className: PropTypes.string,
  style: PropTypes.object,
}

const Col = ({ className = '', cols = -1, style, children, content = 'expand', ...props }) => {
  const cn = `${styles['grid-column']} ${className}`
  const widthPercent = cols * 100 / 12
  const col = cols <= 0 ? {} : {
    flex: `0 0 ${widthPercent}%`,
    maxWidth: `${widthPercent}%`,
  }
  return (

      {children}

  )
}
Col.propTypes = {
  children: PropTypes.node,
  className: PropTypes.string,
  cols: PropTypes.number,
  style: PropTypes.object,
  content: PropTypes.oneOf(['expand', 'auto']),
}

export {
  Grid,
  Row,
  Col,
}
<commit_msg>Add `offset` to Col to allow layout positioning<commit_after>import React from 'react'
import PropTypes from 'prop-types'

import styles from './style.css'

/*
 * Adapt flex-box based grid for the layout. It is much easier to work with
 * than bootstrap3/patternfly grids.
 */
const Grid = ({ children, id, className = '', style }) => {
  const cn = `${styles['grid-container']} ${className}`
  return
{children}

}
Grid.propTypes = {
  children: PropTypes.node.isRequired,
  id: PropTypes.string,
  className: PropTypes.string,
  style: PropTypes.object,
}

const Row = ({ children, id, className = '', style }) => {
  const cn = `${styles['grid-row']} ${className}`
  return
{children}

}
Row.propTypes = {
  children: PropTypes.node.isRequired,
  id: PropTypes.string,
  className: PropTypes.string,
  style: PropTypes.object,
}

const Col = ({ children, id, className = '', style, cols = -1, offset = -1, content = 'expand', ...props }) => {
  const cn = `${styles['grid-column']} ${className}`

  if (cols === -1 && offset > 0) {
    cols = 12 - offset
  }
  const widthPercent = cols * 100 / 12
  const colStyle = cols <= 0 ? {} : {
    flex: `0 0 ${widthPercent}%`,
    maxWidth: `${widthPercent}%`,
  }
  const offsetStyle = offset < 1 ? {} : {
    marginLeft: `${offset * 100 / 12}%`,
  }

  return (

      {children}

  )
}
Col.propTypes = {
  children: PropTypes.node.isRequired,
  id: PropTypes.string,
  className: PropTypes.string,
  style: PropTypes.object,
  cols: function (props, propName, componentName) {
    if (props.cols && (props.cols < 1 || props.cols > 12)) {
      return new Error(`Prop 'cols' of component '${componentName}' is not in valid range of 1 .. 12 `)
    }
  },
  offset: function (props, propName, componentName) {
    if (props.offset !== undefined) {
      const maxOffset = props.cols ? 12 - props.cols : 11
      if (props.offset < 1 || props.offset > maxOffset) {
        return new Error(`Prop 'offset' of component '${componentName}' is not in valid range of 1 .. ${maxOffset}`)
      }
    }
  },
  content: PropTypes.oneOf(['expand', 'auto']),
}

export {
  Grid,
  Row,
  Col,
}
<|endoftext|>