<commit_before>// ==UserScript==
// @name        Alt+Num Extended Char Entry
// @namespace   https://stackapps.org/
// @description hold Alt while pressing numbers to make extended characters
// @match       *://*/*
// @version	    1.1
// @grant       none
// @downloadURL https://github.com/calraith/gm_scripts/raw/master/Alt+Num_Extended_Char_Entry.user.js
// @run-at      document-end
// ==/UserScript==

if (self != top) return;

// holds a list of number keys pressed while alt is held down
var combo = [],
	clicked; // Chrome failsafe

addEventListener('keyup', safeSimulateNumPad);
addEventListener('load', iFramesToo);

function iFramesToo() {
	var iframes = document.getElementsByTagName('iframe');
	for (var i=iframes.length; i--;) {
		// try-catch block to avoid cross domain errors halting execution
		try {
			if (iframes[i].contentWindow) {
				iframes[i].contentWindow.addEventListener('keyup', safeSimulateNumPad);
				// Chrome failsafe
				iframes[i].contentWindow.addEventListener('click', function(e) { clicked = e.target; });
			}
		}
		catch (err) {}
	}
}

function safeSimulateNumPad(e) {
	try { simulateNumPad(e); }
	catch(err) { console.log(err.message); }
}

function simulateNumPad(e) {

	var el = getActiveElement() || clicked,
		start = el.selectionStart,
		end = el.selectionEnd,
		symbol;

	if (!el) console.log('unable to determine focus');

	// Chrome doesn't reliably bubble up the .isContentEditable property
	if (!/chrome/i.test(navigator.userAgent) && !/textarea|input/i.test(el.nodeName) &&
		!el.isContentEditable) return;

	if (e.altKey) {

		// if alt key is pressed, prevent browser menubar from appearing
		e.preventDefault();

		// keyCode 48 = 0, 49 = 1, 50 = 2, etc.
		if (e.keyCode >= 48 && e.keyCode <= 57) combo.push(e.keyCode - 48);

	} else if (combo.length) {

		// if key combo doesn't start with a zero, retrieve higher Unicode glyphs
		// alt+0176 = °, whereas alt+234 = Ω
		symbol = String.fromCharCode(
			(combo[0]) ? combo.join('') * 1 + 703 : combo.join('')
		);

		console.log('symbol: ' + symbol);

		// purge key sequence
		combo = [];

		// insert symbol at current caret pos and advance caret
		if (el.setSelectionRange) {

			// textarea or input
			el.value = el.value.substring(0, start) + symbol + el.value.substring(end);
			el.setSelectionRange(++start, start);

		} else {

			// contentEditable node
			var sel = el.ownerDocument.defaultView.getSelection(),
				range;

			// hack for Chrome
			if (!sel.rangeCount)
				sel = clicked.ownerDocument.defaultView.getSelection();

			range = sel.getRangeAt(0);
			range.deleteContents();
			range.insertNode(document.createTextNode(symbol));
			sel.collapseToEnd();
		}
	}
}

// credit: https://stackoverflow.com/a/25420726/1683264
function getActiveElement(document) {

	document = document || window.document;
	var el = document.activeElement;

	// if target is an iframe or is the document body with no slection
	// (defaultView seems to be required for Chrome.)
	if (el.tagName == 'IFRAME' ||
		(el === document.body && !el.ownerDocument.defaultView.getSelection())) {

		// enumerate all iframes and test recursively
		var iframes = document.getElementsByTagName('iframe');
		for (var i = iframes.length; i--;) {

			// try-catch to avoid cross domain errors halting execution
			try {
				if (iframes[i].contentDocument)
					var focused = getActiveElement(iframes[i].contentDocument);

				if (focused) return focused;
			}
			catch (err) {}
		}
	}
	else return el;

	return false;
};<commit_msg>Update Alt+Num_Extended_Char_Entry.user.js<commit_after>// ==UserScript==
// @name        Alt+Num Extended Char Entry
// @namespace   https://stackapps.org/
// @description hold Alt while pressing numbers to make extended characters
// @match       *://*/*
// @version     1.2
// @grant       none
// @downloadURL https://github.com/calraith/gm_scripts/raw/master/Alt+Num_Extended_Char_Entry.user.js
// @run-at      document-end
// ==/UserScript==

// In Windows, you can view your native codepage by opening a cmd or PowerShell console and entering chcp
var codepage=437; // 437 is the en-US codepage

if (self != top) return;

// holds a list of number keys pressed while alt is held down
var combo = [],
	clicked; // Chrome failsafe

addEventListener('keyup', safeSimulateNumPad);
addEventListener('load', iFramesToo);

function iFramesToo() {
	var iframes = document.getElementsByTagName('iframe');
	for (var i=iframes.length; i--;) {
		// try-catch block to avoid cross domain errors halting execution
		try {
			if (iframes[i].contentWindow) {
				iframes[i].contentWindow.addEventListener('keyup', safeSimulateNumPad);
				// Chrome failsafe
				iframes[i].contentWindow.addEventListener('click', function(e) { clicked = e.target; });
			}
		}
		catch (err) {}
	}
}

// import codepage abstractions
// Credit: https://github.com/SheetJS/js-codepage
function init(obj) {
	if (obj.idx >= obj.src.length) return;
	try {
		var src = obj.src[obj.idx++],
			script = document.createElement('script');

		script.contentType = 'application/javascript;charset=utf-8';
		script.onload = function(){ init(obj); };
		script.src = 'https://cdn.rawgit.com/SheetJS/js-codepage/master/' + src;

		document.getElementsByTagName('HEAD')[0].appendChild(script);
		console.log('Alt+Num_Extended_Char_Entry: ' + src + ' ready');
	}
	catch(err) {
		console.log(err.message);
		console.log('Codepage translations unavailable.  Only Unicode key combos will work.');
	}
}
init({src: ["cptable.js","cputils.js"], idx: 0});

function safeSimulateNumPad(e) {
	try { simulateNumPad(e); }
	catch(err) { console.log(err.message); }
}

function simulateNumPad(e) {

	var el = getActiveElement() || clicked,
		start = el.selectionStart,
		end = el.selectionEnd,
		symbol;

	if (!el) console.log('unable to determine focus');

	// Chrome doesn't reliably bubble up the .isContentEditable property
	if (!/chrome/i.test(navigator.userAgent) && !/textarea|input/i.test(el.nodeName) &&
		!el.isContentEditable) return;

	if (e.altKey) {

		// if alt key is pressed, prevent browser menubar from appearing
		e.preventDefault();

		// keyCode 48 = 0, 49 = 1, 50 = 2, etc.
		if (e.keyCode >= 48 && e.keyCode <= 57) combo.push(e.keyCode - 48);

	} else if (combo.length) {

		// if key combo doesn't start with a zero, retrieve codepage table glyph
		// alt+0176 = °, whereas alt+234 = Ω (for codepage 437)
		symbol = (combo[0] && (combo.join('') * 1 <= 255)) ?
			cptable[codepage].dec[combo.join('')] : String.fromCharCode(combo.join(''));

		console.log('symbol: ' + symbol);

		// purge key sequence
		combo = [];

		// insert symbol at current caret pos and advance caret
		if (el.setSelectionRange) {

			// textarea or input
			el.value = el.value.substring(0, start) + symbol + el.value.substring(end);
			el.setSelectionRange(++start, start);

		} else {

			// contentEditable node
			var sel = el.ownerDocument.defaultView.getSelection(),
				range;

			// hack for Chrome
			if (!sel.rangeCount)
				sel = clicked.ownerDocument.defaultView.getSelection();

			range = sel.getRangeAt(0);
			range.deleteContents();
			range.insertNode(document.createTextNode(symbol));
			sel.collapseToEnd();
		}
	}
}

// credit: https://stackoverflow.com/a/25420726/1683264
function getActiveElement(document) {

	document = document || window.document;
	var el = document.activeElement;

	// if target is an iframe or is the document body with no slection
	// (defaultView seems to be required for Chrome.)
	if (el.tagName == 'IFRAME' ||
		(el === document.body && !el.ownerDocument.defaultView.getSelection())) {

		// enumerate all iframes and test recursively
		var iframes = document.getElementsByTagName('iframe');
		for (var i = iframes.length; i--;) {

			// try-catch to avoid cross domain errors halting execution
			try {
				if (iframes[i].contentDocument)
					var focused = getActiveElement(iframes[i].contentDocument);

				if (focused) return focused;
			}
			catch (err) {}
		}
	}
	else return el;

	return false;
};
<|endoftext|>


<commit_before>/**
 * Faster DOM manipulation
 * The most basic operations, but much faster than jquery. (mostly)
 * @author Vadim Kr.
 */

function FasterDom(element) {
    this.type = element[0];
    this.name = element.substr(1, element.length);
    this.element = (this.type === "#") ? document.getElementById(this.name) : Array.prototype.slice.call(document.getElementsByClassName(this.name));
}
FasterDom.prototype = {
    constructor: FasterDom,
    attr: function (name, value) {
        if (typeof value == "undefined") {
            return this.element.getAttribute(name);
        }
        if (!this.checkIf(this.element, "Array")) {
            this.set(this.element, name, value);
        } else {
            var i = this.element.length;
            while (i--) {
                this.set(this.element[i], name, value);
            }
        }
        return this;
    }, set: function (element, name, value) {
        if (this.checkIf(name, "String")) {
            element.setAttribute(name, value);
        } else if (this.checkIf(name, "Object")) {
            for (var property in name) {
                element.setAttribute(property, name[property]);
            }
        }
    },
    html: function (html) {
        if (typeof html == "undefined") {
            return this.element.innerHTML;
        }
        if (!this.checkIf(this.element, "Array")) {
            this.element.innerHTML = html;
        } else {
            var len = this.element.length;
            for (var i = 0; i < len; i++) {
                var el = this.element[i];
                var el2 = this.element[len - 1];
                el.innerHTML = html;
                el2.innerHTML = html;
                len--;
            }
        }
        return this;
    },
    css: function (obj) {
        if (!this.checkIf(this.element, "Array")) {
            if (typeof obj == "undefined") {
                return this.element.style;
            }
            for (var key in obj) {
                this.element.style[key] = obj[key];
            }
        } else {
            var len = this.element.length;
            while (len--) {
                for (var key in obj) {
                    this.element[len].style[key] = obj[key];
                }
            }
        }
        return this;
    },
    hide: function () {
        if (!this.checkIf(this.element, "Array")) {
            this.element.style.display = 'none';
        } else {
            var len = this.element.length;
            while (len--) {
                this.element[len].style.display = 'none';
            }
        }
        return this;
    },
    show: function () {
        if (!this.checkIf(this.element, "Array")) {
            this.element.style.display = 'block';
        } else {
            var len = this.element.length;
            while (len--) {
                this.element[len].style.display = 'block';
            }
        }
        return this;
    }, append: function (doc) {
        if (!this.checkIf(this.element, "Array")) {
            if (this.checkIf(doc, "String"))
                this.element.insertAdjacentHTML('beforeend', doc);
            else
                this.element.appendChild(doc.cloneNode(true));
        } else {
            var len = this.element.length;
            var type = this.checkIf(doc, "String");
            while (len--) {
                if (type) {
                    this.element[len].insertAdjacentHTML('beforeend', doc);
                } else {
                    this.element[len].appendChild(doc.cloneNode(true));
                }
            }
        }

    }, prepend: function (doc) {
        if (!this.checkIf(this.element, "Array")) {
            if (this.checkIf(doc, "String"))
                this.element.insertAdjacentHTML('afterbegin', doc);
            else
                this.element.insertBefore(doc.cloneNode(true), this.element.firstChild);
        } else {
            var len = this.element.length;
            var type = this.checkIf(doc, "String");
            while (len--) {
                if (type) {
                    this.element[len].insertAdjacentHTML('afterbegin', doc);
                } else {
                    this.element[len].insertBefore(doc.cloneNode(true), this.element[len].firstChild);
                }
            }
        }
    }, remove: function () {
        if (!this.checkIf(this.element, "Array")) {
            this.element.parentNode && this.element.parentNode.removeChild(this.element);
        } else {
            var len = this.element.length;
            while (len--) {
                this.element[len].parentNode && this.element[len].parentNode.removeChild(this.element[len]);
            }
        }
    },
    get: function () {
        return this.element;
    },
    checkIf: function (obj, type) {
        return Object.prototype.toString.call(obj) == '[object ' + type + ']';
    }
}<commit_msg>Update fasterDOM.js<commit_after>/**
 * Faster DOM manipulation
 * The most basic operations, but much faster than jquery. (mostly)
 * @author Vadim Kr.
 */

function FasterDom(element) {
    this.type = element[0];
    this.name = element.substr(1, element.length);
    this.element = (this.type === "#") ? document.getElementById(this.name) : Array.prototype.slice.call(document.getElementsByClassName(this.name));
}
FasterDom.prototype = {
    constructor: FasterDom,
    attr: function (name, value) {
        if (this.checkIf(name, 'String') && typeof value === "undefined") {
            return this.element.getAttribute(name);
        }
        if (!this.checkIf(this.element, "Array")) {
            this.set(this.element, name, value);
        } else {
            var i = this.element.length;
            while (i--) {
                this.set(this.element[i], name, value);
            }
        }
        return this;
    }, set: function (element, name, value) {
        if (this.checkIf(name, "String")) {
            element.setAttribute(name, value);
        } else if (this.checkIf(name, "Object")) {
            for (var property in name) {
                element.setAttribute(property, name[property]);
            }
        }
    },
    html: function (html) {
        if (typeof html === "undefined") {
            return this.element.innerHTML;
        }
        if (!this.checkIf(this.element, "Array")) {
            this.element.innerHTML = html;
        } else {
            var len = this.element.length;
            for (var i = 0; i < len; ++i) {
                var el = this.element[i];
                var el2 = this.element[len - 1];
                el.innerHTML = html;
                el2.innerHTML = html;
                len--;
            }
        }
        return this;
    },
    css: function (obj) {
        if (!this.checkIf(this.element, "Array")) {
            if (typeof obj === "undefined") {
                return this.element.style;
            }
            for (var key in obj) {
                this.element.style[key] = obj[key];
            }
        } else {
            var len = this.element.length;
            while (len--) {
                for (var key in obj) {
                    this.element[len].style[key] = obj[key];
                }
            }
        }
        return this;
    },
    hide: function () {
        if (!this.checkIf(this.element, "Array")) {
            this.element.style.display = 'none';
        } else {
            var len = this.element.length;
            while (len--) {
                this.element[len].style.display = 'none';
            }
        }
        return this;
    },
    show: function () {
        if (!this.checkIf(this.element, "Array")) {
            this.element.style.display = 'block';
        } else {
            var len = this.element.length;
            while (len--) {
                this.element[len].style.display = 'block';
            }
        }
        return this;
    }, append: function (doc) {
        if (!this.checkIf(this.element, "Array")) {
            if (this.checkIf(doc, "String"))
                this.element.insertAdjacentHTML('beforeend', doc);
            else
                this.element.appendChild(doc.cloneNode(true));
        } else {
            var len = this.element.length;
            var type = this.checkIf(doc, "String");
            while (len--) {
                if (type) {
                    this.element[len].insertAdjacentHTML('beforeend', doc);
                } else {
                    this.element[len].appendChild(doc.cloneNode(true));
                }
            }
        }

    }, prepend: function (doc) {
        if (!this.checkIf(this.element, "Array")) {
            if (this.checkIf(doc, "String"))
                this.element.insertAdjacentHTML('afterbegin', doc);
            else
                this.element.insertBefore(doc.cloneNode(true), this.element.firstChild);
        } else {
            var len = this.element.length;
            var type = this.checkIf(doc, "String");
            while (len--) {
                if (type) {
                    this.element[len].insertAdjacentHTML('afterbegin', doc);
                } else {
                    this.element[len].insertBefore(doc.cloneNode(true), this.element[len].firstChild);
                }
            }
        }
    }, remove: function () {
        if (!this.checkIf(this.element, "Array")) {
            this.element.parentNode && this.element.parentNode.removeChild(this.element);
        } else {
            var len = this.element.length;
            while (len--) {
                this.element[len].parentNode && this.element[len].parentNode.removeChild(this.element[len]);
            }
        }
    },
    get: function () {
        return this.element;
    },
    checkIf: function (obj, type) {
        return Object.prototype.toString.call(obj) === '[object ' + type + ']';
    }
}
<|endoftext|>


<commit_before>var Backbone = require('backbone');
var UserModel = require('../../../../../../javascripts/cartodb3/data/user-model');
var SourceLayerAnalysisView = require('../../../../../../javascripts/cartodb3/editor/layers/analysis-views/source-layer-analysis-view');
var AnalysisDefinitionNodesCollection = require('../../../../../../javascripts/cartodb3/data/analysis-definition-nodes-collection');
var ConfigModel = require('../../../../../../javascripts/cartodb3/data/config-model');
var TableModel = require('../../../../../../javascripts/cartodb3/data/table-model');
var _ = require('underscore');

describe('editor/layers/analysis-views/source-layer-analysis-view', function () {
  beforeEach(function () {
    this.configModel = new ConfigModel({
      base_url: '/u/pepe'
    });

    this.userModel = new UserModel({
      username: 'chacho'
    }, {
      configModel: this.configModel
    });

    this.analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection([{
      id: 'a0',
      type: 'source',
      table_name: 'foo_bar',
      params: {
        query: 'SELECT * FROM foo_bar'
      }
    }], {
      configModel: this.configModel,
      userModel: this.userModel
    });
    this.sourceAnalysisDefinitionNodeModel = this.analysisDefinitionNodesCollection.get('a0');
    this.layerDefinitionModel = new Backbone.Model({user_name: 'somebody'});
    this.layerDefinitionModel.getQualifiedTableName = function () {};

    this.view = new SourceLayerAnalysisView({
      model: this.sourceAnalysisDefinitionNodeModel,
      analysisNode: this.sourceAnalysisDefinitionNodeModel,
      layerDefinitionModel: this.layerDefinitionModel
    });
  });

  describe('.render', function () {
    it('should render correctly', function () {
      this.view.render();

      expect(this.view.$el.text()).toContain('a0');
      expect(this.view.$el.text()).toContain('foo_bar');
      expect(_.size(this.view._subviews)).toBe(1); // [tooltip]
    });

    describe('when layer is sync', function () {
      var syncView;

      beforeEach(function () {
        var table = new TableModel({
          id: 'harrr',
          name: 'another_table',
          synchronization: {
            id: 'test'
          }
        }, {
          parse: true,
          configModel: this.configModel
        });

        spyOn(this.sourceAnalysisDefinitionNodeModel, 'getTableModel').and.returnValue(table);

        syncView = new SourceLayerAnalysisView({
          model: this.sourceAnalysisDefinitionNodeModel,
          analysisNode: this.sourceAnalysisDefinitionNodeModel,
          layerDefinitionModel: this.layerDefinitionModel
        });

        syncView.render();
      });

      it('should render correctly', function () {
        expect(syncView.$el.html()).toContain('CDB-IconFont CDB-IconFont-wifi');
        expect(_.size(syncView._subviews)).toBe(2); // [tooltip, sync tooltip]
      });
    });

    describe('when custom query is applied', function () {
      beforeEach(function () {
        spyOn(this.view._analysisNode, 'isCustomQueryApplied').and.returnValue(true);
        this.view.render();
      });

      it('should render correctly', function () {
        expect(this.view.$el.html()).toContain('js-sql');
        expect(this.view.$('.js-sql').html()).toContain('SQL');
        expect(_.size(this.view._subviews)).toBe(2); // [tooltip, customQuery tooltip]
      });
    });
  });

  describe('._initBinds', function () {
    it('should call _toggleHover on _stateModel change highlighted', function () {
      spyOn(this.view, '_toggleHover');
      this.view._initBinds();
      this.view._stateModel.trigger('change:highlighted');

      expect(this.view._toggleHover).toHaveBeenCalled();
    });

    it('should call render on _tableNodeModel change synchronization', function () {
      spyOn(this.view, 'render');
      this.view._initBinds();
      this.view._tableNodeModel.trigger('change:synchronization');

      expect(this.view.render).toHaveBeenCalled();
    });
  });

  describe('._onMouseEnter', function () {
    it('should set _stateModel highlighted to true', function () {
      expect(this.view._stateModel.get('highlighted')).toBe(false);

      this.view._onMouseEnter();

      expect(this.view._stateModel.get('highlighted')).toBe(true);
    });
  });

  describe('._onMouseLeave', function () {
    it('should set _stateModel highlighted to false', function () {
      this.view._stateModel.set('highlighted', true, { silent: true });
      expect(this.view._stateModel.get('highlighted')).toBe(true);

      this.view._onMouseLeave();

      expect(this.view._stateModel.get('highlighted')).toBe(false);
    });
  });

  it('should have no leaks', function () {
    expect(this.view).toHaveNoLeaks();
  });

  afterEach(function () {
    this.view.clean();
  });
});
<commit_msg>wayfinding: layer list specs<commit_after>var Backbone = require('backbone');
var UserModel = require('../../../../../../javascripts/cartodb3/data/user-model');
var SourceLayerAnalysisView = require('../../../../../../javascripts/cartodb3/editor/layers/analysis-views/source-layer-analysis-view');
var AnalysisDefinitionNodesCollection = require('../../../../../../javascripts/cartodb3/data/analysis-definition-nodes-collection');
var ConfigModel = require('../../../../../../javascripts/cartodb3/data/config-model');
var TableModel = require('../../../../../../javascripts/cartodb3/data/table-model');
var nodeIds = require('../../../../../../javascripts/cartodb3/value-objects/analysis-node-ids');
var layerColors = require('../../../../../../javascripts/cartodb3/data/layer-colors');
var _ = require('underscore');

describe('editor/layers/analysis-views/source-layer-analysis-view', function () {
  beforeEach(function () {
    this.configModel = new ConfigModel({
      base_url: '/u/pepe'
    });

    this.userModel = new UserModel({
      username: 'chacho'
    }, {
      configModel: this.configModel
    });

    this.analysisDefinitionNodesCollection = new AnalysisDefinitionNodesCollection([{
      id: 'a0',
      type: 'source',
      table_name: 'foo_bar',
      params: {
        query: 'SELECT * FROM foo_bar'
      }
    }], {
      configModel: this.configModel,
      userModel: this.userModel
    });
    this.sourceAnalysisDefinitionNodeModel = this.analysisDefinitionNodesCollection.get('a0');
    this.layerDefinitionModel = new Backbone.Model({user_name: 'somebody'});
    this.layerDefinitionModel.getQualifiedTableName = function () {};

    this.view = new SourceLayerAnalysisView({
      model: this.sourceAnalysisDefinitionNodeModel,
      analysisNode: this.sourceAnalysisDefinitionNodeModel,
      layerDefinitionModel: this.layerDefinitionModel
    });
  });

  describe('.render', function () {
    it('should render correctly', function () {
      this.view.render();

      expect(this.view.$el.text()).toContain('a0');
      expect(this.view.$el.text()).toContain('foo_bar');
      expect(_.size(this.view._subviews)).toBe(1); // [tooltip]
    });

    describe('when layer is sync', function () {
      var syncView;

      beforeEach(function () {
        var table = new TableModel({
          id: 'harrr',
          name: 'another_table',
          synchronization: {
            id: 'test'
          }
        }, {
          parse: true,
          configModel: this.configModel
        });

        spyOn(this.sourceAnalysisDefinitionNodeModel, 'getTableModel').and.returnValue(table);

        syncView = new SourceLayerAnalysisView({
          model: this.sourceAnalysisDefinitionNodeModel,
          analysisNode: this.sourceAnalysisDefinitionNodeModel,
          layerDefinitionModel: this.layerDefinitionModel
        });

        syncView.render();
      });

      it('should render correctly', function () {
        expect(syncView.$el.html()).toContain('CDB-IconFont CDB-IconFont-wifi');
        expect(_.size(syncView._subviews)).toBe(2); // [tooltip, sync tooltip]
      });
    });

    describe('when custom query is applied', function () {
      beforeEach(function () {
        spyOn(this.view._analysisNode, 'isCustomQueryApplied').and.returnValue(true);
        this.view.render();
      });

      it('should render correctly', function () {
        expect(this.view.$el.html()).toContain('js-sql');
        expect(this.view.$('.js-sql').html()).toContain('SQL');
        expect(_.size(this.view._subviews)).toBe(2); // [tooltip, customQuery tooltip]
      });
    });
  });

  describe('._initBinds', function () {
    it('should call _toggleHover on _stateModel change highlighted', function () {
      spyOn(this.view, '_toggleHover');
      this.view._initBinds();
      this.view._stateModel.trigger('change:highlighted');

      expect(this.view._toggleHover).toHaveBeenCalled();
    });

    it('should call render on _tableNodeModel change synchronization', function () {
      spyOn(this.view, 'render');
      this.view._initBinds();
      this.view._tableNodeModel.trigger('change:synchronization');

      expect(this.view.render).toHaveBeenCalled();
    });
  });

  describe('._onMouseEnter', function () {
    it('should set _stateModel highlighted to true', function () {
      expect(this.view._stateModel.get('highlighted')).toBe(false);

      this.view._onMouseEnter();

      expect(this.view._stateModel.get('highlighted')).toBe(true);
    });
  });

  describe('._onMouseLeave', function () {
    it('should set _stateModel highlighted to false', function () {
      this.view._stateModel.set('highlighted', true, { silent: true });
      expect(this.view._stateModel.get('highlighted')).toBe(true);

      this.view._onMouseLeave();

      expect(this.view._stateModel.get('highlighted')).toBe(false);
    });
  });

  describe('._bgColor', function () {
    var letter = 'A';

    it('should call .getColorForLetter with the correct letter', function () {
      nodeIds.letter = function () {
        return letter;
      };
      spyOn(layerColors, 'getColorForLetter');

      this.view._bgColor();
      expect(layerColors.getColorForLetter).toHaveBeenCalledWith(letter);
    });
  });

  it('should have no leaks', function () {
    expect(this.view).toHaveNoLeaks();
  });

  afterEach(function () {
    this.view.clean();
  });
});
<|endoftext|>


<commit_before>

var gameSimon = {
    buttons: [],
    sequence: [],
    index: 0,
    time:0,
    status: 0, //0: Splash, 1: Machine, 2: User, 3: End, 4: Pause

    setup: function(gameBackground, gameFront, movementImage) {
        gameSimon.time = new Date().getTime();
        gameSimon.status = 0;
        gameSimon.foregroundImage = $("#simonForeground")[0];
        gameSimon.buttons = [];

        var button;
        button = new Item(1010, 50, 1130, 170, 0, 0, document.getElementById("buttonYellow"), document.getElementById("buttonYellowBig"), 'audio/note1.ogg');
        gameCommon.items.push(button);
        gameSimon.buttons.push(button);

        button = new Item(150, 50, 270, 170, 0, 0, document.getElementById("buttonGreen"), document.getElementById("buttonGreenBig"), 'audio/note2.ogg');
        gameCommon.items.push(button);
        gameSimon.buttons.push(button);

        button = new Item(1010, 500, 1130, 720, 0, 0, document.getElementById("buttonBlue"), document.getElementById("buttonBlueBig"), 'audio/note3.ogg');
        gameCommon.items.push(button);
        gameSimon.buttons.push(button);

        button = new Item(150, 500, 270, 720, 0, 0, document.getElementById("buttonRed"), document.getElementById("buttonRedBig"), 'audio/note4.ogg');
        gameCommon.items.push(button);
        gameSimon.buttons.push(button);

        gameSimon.sequence = [];
        gameSimon.index = 0;

        gameCommon.drawText('READY');
    },

    activateButton: function(button){
        console.log("Activate: " + gameSimon.status);
        if (gameSimon.status == 1 || gameSimon.status == 2){
            button.x1 = button.x1 - 40;
            button.x2 = button.x2 + 40;
            button.y1 = button.y1 - 40;
            button.y2 = button.y2 + 40;
            button.refreshScaled();
            button.setActive(true);
        }
    },

    deactivateButton: function(button){
        console.log("Dectivate: " + gameSimon.status);
        if (gameSimon.status == 1 || gameSimon.status == 2){
            button.x1 = button.x1 + 40;
            button.x2 = button.x2 - 40;
            button.y1 = button.y1 + 40;
            button.y2 = button.y2 - 40;
            button.refreshScaled();
            button.setActive(false);
        }
    },

    onUserMove: function(){
        if (gameSimon.status == 2) {
            var anyActive = gameSimon.buttons[0].active ||
                            gameSimon.buttons[1].active ||
                            gameSimon.buttons[2].active ||
                            gameSimon.buttons[3].active;
            for (i = 0; i < gameCommon.items.length; i++) {
                var button = gameCommon.items[i];
                var active = gameCommon.checkActiveItem(button);
                if (active){
                    //Should have been a while inactive
                    if (new Date().getTime() - button.inactiveTime > 500) {
                        if (!anyActive){
                            gameSimon.activateButton(button);
                            if (gameSimon.sequence[gameSimon.index] == button){
                                gameCommon.playSound(button.sound);
                                gameSimon.index++;
                                if (gameSimon.index == gameSimon.sequence.length){
                                    gameSimon.endUserTurn();
                                }
                            } else {
                                gameSimon.endGame();
                            }
                        }
                    }
                } else {
                    if (button.active){
                        //Should have been a while active
                        if (new Date().getTime() - button.activeTime > 500) {
                            gameSimon.deactivateButton(button);
                        }
                    }
                }
            }
        }
    },

    endUserTurn: function(){
        gameSimon.status = 1;
        gameSimon.index = 0;
        gameCommon.drawText("COMPUTER");
        window.setTimeout(gameSimon.computerTurn, 3000);
        for (i = 0; i < gameSimon.buttons.length; i++) {
            var button = gameSimon.buttons[i];
            if (button.active){
                window.setTimeout(function(){gameSimon.deactivateButton(button);}, 200);
            }
        }
    },

    computerTurn: function(){
        gameCommon.clearText();
        var num = Math.floor((Math.random() * 4));
        var button = gameSimon.buttons[num];
        gameSimon.sequence.push(button);
        gameSimon.playSequence(0);
    },

    startUser: function(){
        gameSimon.status = 4;
        gameCommon.drawText("YOU");
        window.setTimeout(function(){gameCommon.clearText(); gameSimon.status = 2;}, 1000);
        gameSimon.index = 0;
    },

    endGame: function(){
        gameSimon.status = 3;
        gameCommon.playSound('audio/wrong.ogg');
        gameCommon.drawText('YOU LOSE!');
        window.setTimeout(function(){gameCommon.startGame(gameMenu)}, 2000);
    },

    playSequence: function(index){
        if (index == gameSimon.sequence.length){
            window.setTimeout(function(){gameSimon.startUser();}, 1000);
        } else {
            var button = gameSimon.sequence[index];
            gameCommon.playSound(button.sound);
            gameSimon.activateButton(button);
            window.setTimeout(function(){gameSimon.deactivateButton(button)}, 500);

            var time = 1000 - (gameSimon.sequence.length * 50);
            if (time < 600) {
                time = 600;
            }

            console.log(time);

            window.setTimeout(function(){gameSimon.playSequence(index+1)}, time);
        }
    },

    splash: function(){
        var now = new Date().getTime();
        if (now - gameSimon.time > 2000){
            gameSimon.status = 1;
            gameCommon.clearText();
            gameCommon.drawText("COMPUTER");
            window.setTimeout(gameSimon.computerTurn, 2000);
        }
    },

    gameLoop: function(delta){
        //Splash
        if (gameSimon.status == 0) {
            gameSimon.splash();
        }
    }
}
<commit_msg>Fix bugs on simon buttons<commit_after>

var gameSimon = {
    buttons: [],
    sequence: [],
    index: 0,
    time:0,
    status: 0, //0: Splash, 1: Machine, 2: User, 3: End, 4: Pause

    setup: function(gameBackground, gameFront, movementImage) {
        gameSimon.time = new Date().getTime();
        gameSimon.status = 0;
        gameSimon.foregroundImage = $("#simonForeground")[0];
        gameSimon.buttons = [];

        var button;
        button = new Item(1010, 50, 1130, 170, 0, 0, document.getElementById("buttonYellow"), document.getElementById("buttonYellowBig"), 'audio/note1.ogg');
        gameCommon.items.push(button);
        gameSimon.buttons.push(button);

        button = new Item(150, 50, 270, 170, 0, 0, document.getElementById("buttonGreen"), document.getElementById("buttonGreenBig"), 'audio/note2.ogg');
        gameCommon.items.push(button);
        gameSimon.buttons.push(button);

        button = new Item(1010, 500, 1130, 720, 0, 0, document.getElementById("buttonBlue"), document.getElementById("buttonBlueBig"), 'audio/note3.ogg');
        gameCommon.items.push(button);
        gameSimon.buttons.push(button);

        button = new Item(150, 500, 270, 720, 0, 0, document.getElementById("buttonRed"), document.getElementById("buttonRedBig"), 'audio/note4.ogg');
        gameCommon.items.push(button);
        gameSimon.buttons.push(button);

        gameSimon.sequence = [];
        gameSimon.index = 0;

        gameCommon.drawText('READY');
    },

    activateButton: function(button){
        if (!button.active){
            button.x1 = button.x1 - 40;
            button.x2 = button.x2 + 40;
            button.y1 = button.y1 - 40;
            button.y2 = button.y2 + 40;
            button.refreshScaled();
            button.setActive(true);
            gameCommon.clearFrontContext();
            window.setTimeout(function(){gameSimon.deactivateButton(button)}, 500);
        }
    },

    deactivateButton: function(button){
        if (button.active){ //Prevent double deactivation
            button.setActive(false);
            button.x1 = button.x1 + 40;
            button.x2 = button.x2 - 40;
            button.y1 = button.y1 + 40;
            button.y2 = button.y2 - 40;
            button.refreshScaled();

            gameCommon.clearFrontContext();
        }
    },

    onUserMove: function(){
        if (gameSimon.status == 2) {
            var anyActive = gameSimon.buttons[0].active ||
                            gameSimon.buttons[1].active ||
                            gameSimon.buttons[2].active ||
                            gameSimon.buttons[3].active;
            for (i = 0; i < gameCommon.items.length; i++) {
                var button = gameCommon.items[i];
                var active = gameCommon.checkActiveItem(button);
                if (active){
                    //Should have been a while inactive
                    if ((!anyActive) && (new Date().getTime() - button.inactiveTime > 500)) {
                        gameSimon.activateButton(button);
                        if (gameSimon.sequence[gameSimon.index] == button){
                            gameCommon.playSound(button.sound);
                            gameSimon.index++;
                            if (gameSimon.index == gameSimon.sequence.length){
                                gameSimon.endUserTurn();
                            }
                        } else {
                            gameSimon.endGame();
                        }
                    }
                }
            }
        }
    },

    endUserTurn: function(){
        gameSimon.status = 1;
        gameSimon.index = 0;
        gameCommon.drawText("COMPUTER");
        window.setTimeout(gameSimon.computerTurn, 3000);
    },

    computerTurn: function(){
        gameCommon.clearText();
        var num = Math.floor((Math.random() * 4));
        var button = gameSimon.buttons[num];
        gameSimon.sequence.push(button);
        gameSimon.playSequence(0);
    },

    startUser: function(){
        gameSimon.status = 4;
        gameCommon.drawText("YOU");
        window.setTimeout(function(){gameCommon.clearText(); gameSimon.status = 2;}, 1000);
        gameSimon.index = 0;
    },

    endGame: function(){
        gameSimon.status = 3;
        gameCommon.playSound('audio/wrong.ogg');
        gameCommon.drawText('YOU LOSE!');
        window.setTimeout(function(){gameCommon.startGame(gameMenu)}, 2000);
    },

    playSequence: function(index){
        if (index == gameSimon.sequence.length){
            window.setTimeout(function(){gameSimon.startUser();}, 1000);
        } else {
            var button = gameSimon.sequence[index];
            gameCommon.playSound(button.sound);
            gameSimon.activateButton(button);

            var time = 1000 - (gameSimon.sequence.length * 50);
            if (time < 600) {
                time = 600;
            }
            window.setTimeout(function(){gameSimon.playSequence(index+1)}, time);
        }
    },

    splash: function(){
        var now = new Date().getTime();
        if (now - gameSimon.time > 2000){
            gameSimon.status = 1;
            gameCommon.clearText();
            gameCommon.drawText("COMPUTER");
            window.setTimeout(gameSimon.computerTurn, 2000);
        }
    },

    gameLoop: function(delta){
        //Splash
        if (gameSimon.status == 0) {
            gameSimon.splash();
        }
    }
}
<|endoftext|>


<commit_before>/**
 * @file Tfoot component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

// Components
import Tf from '../_Tf';

// Statics
import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';
import Direction from '../_statics/Direction';

// Vendors
import classNames from 'classnames';
import Util from '../_vendors/Util';
import TC from '../_vendors/TableCalculation';
import ScrollBar from '../_vendors/ScrollBar';

class Tfoot extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    getColumnsSpan = () => {
        const {columns, data, onRequestColumnsSpan} = this.props;
        return onRequestColumnsSpan ?
            onRequestColumnsSpan(TableFragment.FOOT, columns, data)
            :
            TC.getColumnsSpan(TableFragment.FOOT, columns, data);
    };

    getStyle = (column, colIndex) => {
        const {columns, columnKeyField, columnsWidth, defaultColumnWidth, hasVerticalScroll} = this.props;
        return {
            ...column.footStyle,
            ...TC.getStickyColumnStyle(column?.fixed, colIndex, columns,
                columnKeyField, columnsWidth, defaultColumnWidth, hasVerticalScroll)
        };
    };

    handleClick = e => {
        const {data, disabled, onFootClick} = this.props;
        !disabled && onFootClick && onFootClick(data, e);
    };

    render() {

        const {
                className, data, disabled, ignoreColumnSpan, scrollEl, hasVerticalScroll, hasFixedRightColumn,
                onCellClick
            } = this.props,
            columnsSpan = this.getColumnsSpan(),
            verticalScrollBarSize = ScrollBar.getSize(Direction.VERTICAL);

        return (

                    {
                        columnsSpan && columnsSpan.map(({column, span}, colIndex) =>
                            <Tf key={colIndex}
                                className={classNames(column.footClassName, {
                                    'fixed-left': column.fixed === HorizontalAlign.LEFT,
                                    'last-fixed-left': column.fixed === HorizontalAlign.LEFT
                                        && columnsSpan?.[colIndex + 1]?.column?.fixed !== HorizontalAlign.LEFT,
                                    'fixed-right': column.fixed === HorizontalAlign.RIGHT,
                                    'first-fixed-right': column.fixed === HorizontalAlign.RIGHT
                                        && columnsSpan?.[colIndex - 1]?.column?.fixed !== HorizontalAlign.RIGHT
                                })}
                                style={this.getStyle(column, colIndex)}
                                colIndex={colIndex}
                                data={data}
                                title={column.footTitle}
                                renderer={column.footRenderer}
                                align={column.footAlign || column.align}
                                span={ignoreColumnSpan ? null : span}
                                noWrap={TC.handleNoWrap(column.footNoWrap, column.noWrap, {
                                    data,
                                    rowIndex: 0,
                                    colIndex: colIndex,
                                    tableData: data
                                })}
                                disabled={disabled}
                                scrollEl={scrollEl}
                                onCellClick={onCellClick}/>
                        )
                    }

                    {
                        hasVerticalScroll && columnsSpan && verticalScrollBarSize > 0 ?
                            <td className={classNames('scroll-bar-tf', {
                                'fixed-right': hasFixedRightColumn
                            })}
                                style={{
                                    width: verticalScrollBarSize,
                                    ...(hasFixedRightColumn ? {
                                        position: 'sticky',
                                        right: 0
                                    } : null)
                                }}>

                            :
                            null
                    }

        );

    }
}

Tfoot.propTypes = {

    className: PropTypes.string,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * unique keyof column.
         */
        key: PropTypes.string,

        /**
         * fixed position of column ( 'left' / 'right' ).
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column.
         */
        width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * minimum width of column.
         */
        minWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * align of current column.
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * no wrap of current column.
         */
        noWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * The title in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headTitle: PropTypes.any,

        /**
         * column span of table header.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table header.
         */
        headNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell.
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * The title in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyTitle: PropTypes.any,

        /**
         * column span of table body.
         *  (1) function callback:
         *      function (rowData, colIndex, rowIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table body.
         */
        bodyNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * The title in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footTitle: PropTypes.any,

        /**
         * column span of table foot.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table foot.
         */
        footNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,
    columnKeyField: PropTypes.string,
    columnsWidth: PropTypes.object,
    data: PropTypes.array,
    disabled: PropTypes.bool,
    ignoreColumnSpan: PropTypes.bool,

    /**
     * scroll
     */
    scrollEl: PropTypes.object,
    hasVerticalScroll: PropTypes.bool,

    /**
     * fixed
     */
    hasFixedRightColumn: PropTypes.bool,

    /**
     * column resizable
     */
    defaultColumnWidth: PropTypes.number,

    onFootClick: PropTypes.func,
    onCellClick: PropTypes.func,
    onRequestColumnsSpan: PropTypes.func

};

Tfoot.defaultProps = {

    columnKeyField: 'key',
    disabled: false,
    ignoreColumnSpan: false,

    /**
     * scroll
     */
    hasVerticalScroll: false,

    /**
     * fixed
     */
    hasFixedRightColumn: false,

    /**
     * column resizable
     */
    defaultColumnWidth: 100

};

export default Tfoot;
<commit_msg>update Tfoot<commit_after>/**
 * @file Tfoot component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';

// Components
import Tf from '../_Tf';

// Statics
import TableFragment from '../_statics/TableFragment';
import HorizontalAlign from '../_statics/HorizontalAlign';
import SelectMode from '../_statics/SelectMode';
import SelectAllMode from '../_statics/SelectAllMode';
import SortingType from '../_statics/SortingType';
import Direction from '../_statics/Direction';

// Vendors
import classNames from 'classnames';
import Util from '../_vendors/Util';
import TC from '../_vendors/TableCalculation';
import ScrollBar from '../_vendors/ScrollBar';

class Tfoot extends Component {

    static Align = HorizontalAlign;
    static SelectMode = SelectMode;
    static SelectAllMode = SelectAllMode;
    static SortingType = SortingType;

    constructor(props, ...restArgs) {
        super(props, ...restArgs);
    }

    getColumnsSpan = () => {
        const {columns, data, onRequestColumnsSpan} = this.props;
        return onRequestColumnsSpan ?
            onRequestColumnsSpan(TableFragment.FOOT, columns, data)
            :
            TC.getColumnsSpan(TableFragment.FOOT, columns, data);
    };

    getStyle = (column, colIndex) => {
        const {columns, columnKeyField, columnsWidth, defaultColumnWidth, hasVerticalScroll} = this.props;
        return {
            ...column.footStyle,
            ...TC.getStickyColumnStyle(column?.fixed, colIndex, columns,
                columnKeyField, columnsWidth, defaultColumnWidth, hasVerticalScroll)
        };
    };

    handleClick = e => {
        const {data, disabled, onFootClick} = this.props;
        !disabled && onFootClick && onFootClick(data, e);
    };

    render() {

        const {
                className, data, disabled, ignoreColumnSpan, scrollEl, hasVerticalScroll, hasFixedRightColumn,
                onCellClick
            } = this.props,
            columnsSpan = this.getColumnsSpan(),
            verticalScrollBarSize = ScrollBar.getSize(Direction.VERTICAL);

        return (

                    {
                        columnsSpan && columnsSpan.map(({column, span}, colIndex) =>
                            <Tf key={colIndex}
                                className={classNames(column.footClassName, {
                                    'fixed-left': column.fixed === HorizontalAlign.LEFT,
                                    'last-fixed-left': column.fixed === HorizontalAlign.LEFT
                                        && columnsSpan?.[colIndex + 1]?.column?.fixed !== HorizontalAlign.LEFT,
                                    'fixed-right': column.fixed === HorizontalAlign.RIGHT,
                                    'first-fixed-right': column.fixed === HorizontalAlign.RIGHT
                                        && columnsSpan?.[colIndex - 1]?.column?.fixed !== HorizontalAlign.RIGHT
                                })}
                                style={this.getStyle(column, colIndex)}
                                colIndex={colIndex}
                                data={data}
                                title={column.footTitle}
                                renderer={column.footRenderer}
                                align={column.footAlign || column.align}
                                span={ignoreColumnSpan ? null : span}
                                noWrap={TC.handleNoWrap(column.footNoWrap, column.noWrap, {
                                    data,
                                    rowIndex: 0,
                                    colIndex: colIndex,
                                    tableData: data
                                })}
                                disabled={disabled}
                                scrollEl={scrollEl}
                                onCellClick={onCellClick}/>
                        )
                    }

                    {
                        hasVerticalScroll && columnsSpan && verticalScrollBarSize > 0 ?
                            <td className={classNames('scroll-bar-tf', {
                                'fixed-right': hasFixedRightColumn
                            })}
                                style={{
                                    width: verticalScrollBarSize,
                                    ...(hasFixedRightColumn ? {
                                        position: 'sticky',
                                        right: 0
                                    } : null)
                                }}>

                            :
                            null
                    }

        );

    }
}

Tfoot.propTypes = {

    className: PropTypes.string,

    /**
     * Children passed into table header.
     */
    columns: PropTypes.arrayOf(PropTypes.shape({

        /**
         * unique keyof column.
         */
        key: PropTypes.string,

        /**
         * fixed position of column ( 'left' / 'right' ).
         */
        fixed: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * width of column.
         */
        width: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.func]),

        /**
         * minimum width of column.
         */
        minWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),

        /**
         * align of current column.
         */
        align: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * no wrap of current column.
         */
        noWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of header.
         */
        headClassName: PropTypes.string,

        /**
         * Override the styles of header.
         */
        headStyle: PropTypes.object,

        /**
         * align of table header cell
         */
        headAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headRenderer: PropTypes.any,

        /**
         * The title in table head.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        headTitle: PropTypes.any,

        /**
         * column span of table header.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        headSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table header.
         */
        headNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of td.
         */
        bodyClassName: PropTypes.string,

        /**
         * Override the styles of td.
         */
        bodyStyle: PropTypes.object,

        /**
         * align of table body cell.
         */
        bodyAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyRenderer: PropTypes.any,

        /**
         * The title in table body.
         *  (1) callback:
         *      function (rowData, rowIndex, colIndex, parentData, tableData, collapsed, depth, path) {
         *          return rowData.id;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        bodyTitle: PropTypes.any,

        /**
         * column span of table body.
         *  (1) function callback:
         *      function (rowData, colIndex, rowIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        bodySpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table body.
         */
        bodyNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * The class name of footer.
         */
        footClassName: PropTypes.string,

        /**
         * Override the styles of footer.
         */
        footStyle: PropTypes.object,

        /**
         * align of table footer cell
         */
        footAlign: PropTypes.oneOf(Util.enumerateValue(HorizontalAlign)),

        /**
         * The render content in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footRenderer: PropTypes.any,

        /**
         * The title in table foot.
         *  (1) callback:
         *      function (tableData, colIndex) {
         *          return colIndex;
         *      }
         *
         *  (2) others:
         *      render whatever you pass
         */
        footTitle: PropTypes.any,

        /**
         * column span of table foot.
         *  (1) function callback:
         *      function (tableData, colIndex) {
         *          return null;
         *      }
         *
         *  (2) number:
         *      render whatever you pass
         */
        footSpan: PropTypes.oneOfType([PropTypes.number, PropTypes.func]),

        /**
         * no wrap of table foot.
         */
        footNoWrap: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),

        /**
         * If true,this column can be sorted.
         */
        sortable: PropTypes.bool,

        /**
         * Sorting property.
         */
        sortingProp: PropTypes.string,

        defaultSortingType: PropTypes.oneOf(Util.enumerateValue(SortingType))

    })).isRequired,
    columnKeyField: PropTypes.string,
    columnsWidth: PropTypes.object,
    data: PropTypes.array,
    disabled: PropTypes.bool,
    ignoreColumnSpan: PropTypes.bool,

    /**
     * scroll
     */
    scrollEl: PropTypes.object,
    hasVerticalScroll: PropTypes.bool,

    /**
     * fixed
     */
    hasFixedRightColumn: PropTypes.bool,

    /**
     * column resizable
     */
    defaultColumnWidth: PropTypes.number,

    onFootClick: PropTypes.func,
    onCellClick: PropTypes.func,
    onRequestColumnsSpan: PropTypes.func

};

Tfoot.defaultProps = {

    columnKeyField: 'key',
    disabled: false,
    ignoreColumnSpan: false,

    /**
     * scroll
     */
    hasVerticalScroll: false,

    /**
     * fixed
     */
    hasFixedRightColumn: false,

    /**
     * column resizable
     */
    defaultColumnWidth: 100

};

export default Tfoot;
<|endoftext|>


<commit_before>logPath = ""
<commit_msg>Updated config file<commit_after>config = {};
config.logPath = "";

config.exposeEvents = {
	"InitGame": true,
	"InitRound": true,
	"InitAuth": true,
	"ShutdownGame": true,
	"ClientConnect": true,
	"ClientDisconnect": true,
	"ClientUserinfo": true,
	"ClientSpawn": true,
	"ClientBegin": true,
	"say": true,
	"sayteam": true,
	"Kill": true,
	"SurvivorWinner": true
}

<|endoftext|>


<commit_before>define( [
    'osg/Utils',
    'osg/Notify',
    'osg/StateAttribute',
    'osg/Map'
], function ( MACROUTILS, Notify, StateAttribute, Map ) {
    'use strict';

    /**
     * Program encapsulate an vertex and fragment shader
     * @class Program
     */
    var Program = function ( vShader, fShader ) {
        StateAttribute.call( this );

        this._program = null;

        // used to know if it's a default program
        // a default program does nothing but avoid to do some
        // useless logic
        // if we vertex or fragment shader are set it's not a default
        // program anymore
        this._nullProgram = true;

        this._vertex = undefined;
        this._fragment = undefined;

        this._uniformsCache = undefined;
        this._attributesCache = undefined;

        if ( vShader )
            this.setVertexShader( vShader );

        if ( fShader )
            this.setFragmentShader( fShader );
    };

    /** @lends Program.prototype */
    Program.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {

        attributeType: 'Program',

        cloneType: function () {
            return new Program();
        },

        setVertexShader: function ( vs ) {
            this._vertex = vs;
            this._nullProgram = false;
        },

        setFragmentShader: function ( fs ) {
            this._fragment = fs;
            this._nullProgram = false;
        },

        getVertexShader: function () {
            return this._vertex;
        },
        getFragmentShader: function () {
            return this._fragment;
        },

        getProgram: function () {
            return this._program;
        },

        apply: function ( state ) {

            if ( this._nullProgram ) return;

            var gl = state.getGraphicContext();

            if ( !this._program || this.isDirty() ) {

                var compileClean;

                if ( !this._vertex.shader ) {
                    compileClean = this._vertex.compile( gl );
                }

                if ( !this._fragment.shader ) {
                    compileClean = this._fragment.compile( gl );
                }

                if ( compileClean ) {

                    this._program = gl.createProgram();

                    gl.attachShader( this._program, this._vertex.shader );
                    gl.attachShader( this._program, this._fragment.shader );
                    MACROUTILS.timeStamp( 'osgjs.metrics:linkShader' );
                    gl.linkProgram( this._program );

                    if ( !gl.getProgramParameter( this._program, gl.LINK_STATUS ) && !gl.isContextLost() ) {
                        var errLink = gl.getProgramInfoLog( this._program );

                        Notify.error( errLink );
                        Notify.log( 'can\'t link program\n' + 'vertex shader:\n' + this._vertex.text + '\n fragment shader:\n' + this._fragment.text, true, false );
                        // rawgl trick is for webgl inspector
                        var debugShader = ( gl.rawgl !== undefined ? gl.rawgl : gl );
                        if ( debugShader !== undefined && debugShader.getExtension !== undefined ) debugShader.getExtension( 'WEBGL_debug_shaders' );
                        if ( debugShader && errLink === 'Failed to create D3D shaders.\n' ) {

                            Notify.error( debugShader.getTranslatedShaderSource( this._vertex.shader ), true, false );
                            Notify.error( debugShader.getTranslatedShaderSource( this._fragment.shader ), true, false );
                        }

                        compileClean = false;
                    }
                    // TODO: better usage of validate.
                    // as it's intended at shader program usage
                    // validating against current gl state
                    // Not for compilation stage
                    // gl.validateProgram( this._program );

                }

                if ( !compileClean ) {
                    // Any error, Any
                    // Pink must die.
                    if ( !Program.prototype._failSafeCache ) {

                        var program = gl.createProgram();
                        this._vertex.failSafe( gl );
                        this._fragment.failSafe( gl );

                        gl.attachShader( program, this._vertex.shader );
                        gl.attachShader( program, this._fragment.shader );
                        gl.linkProgram( program );
                        gl.validateProgram( program );

                        // cache to compile and allocate only once
                        // not polluting the inspector
                        Program.prototype._failSafeCache = program;
                    }
                    Notify.warn( 'FailSafe shader Activated ' );
                    this._program = this._failSafeCache;
                }

                this._uniformsCache = new Map();
                this._attributesCache = new Map();

                this.cacheUniformList( gl, this._vertex.text );
                this.cacheUniformList( gl, this._fragment.text );

                this.cacheAttributeList( gl, this._vertex.text );

                this.setDirty( false );
            }

            state.applyProgram( this._program );
        },

        cacheUniformList: function ( gl, str ) {
            var r = str.match( /uniform\s+\w+\s+\w+/g );
            var map = this._uniformsCache;
            if ( r !== null ) {
                for ( var i = 0, l = r.length; i < l; i++ ) {
                    var uniform = r[ i ].match( /uniform\s+\w+\s+(\w+)/ )[ 1 ];
                    var location = gl.getUniformLocation( this._program, uniform );
                    if ( location !== undefined && location !== null ) {
                        if ( map[ uniform ] === undefined ) {
                            map[ uniform ] = location;
                            this._uniformsCache.dirty();
                        }
                    }
                }
            }
        },

        cacheAttributeList: function ( gl, str ) {
            var r = str.match( /attribute\s+\w+\s+\w+/g );
            var map = this._attributesCache;
            if ( r !== null ) {
                for ( var i = 0, l = r.length; i < l; i++ ) {
                    var attr = r[ i ].match( /attribute\s+\w+\s+(\w+)/ )[ 1 ];
                    var location = gl.getAttribLocation( this._program, attr );
                    if ( location !== -1 && location !== undefined ) {
                        if ( map[ attr ] === undefined ) {
                            map[ attr ] = location;
                            this._attributesCache.dirty();
                        }
                    }
                }
            }
        }
    } ), 'osg', 'Program' );

    return Program;
} );
<commit_msg>Fixes debug shader extension missing initializer<commit_after>define( [
    'osg/Utils',
    'osg/Notify',
    'osg/StateAttribute',
    'osg/Map'
], function ( MACROUTILS, Notify, StateAttribute, Map ) {
    'use strict';

    /**
     * Program encapsulate an vertex and fragment shader
     * @class Program
     */
    var Program = function ( vShader, fShader ) {
        StateAttribute.call( this );

        this._program = null;

        // used to know if it's a default program
        // a default program does nothing but avoid to do some
        // useless logic
        // if we vertex or fragment shader are set it's not a default
        // program anymore
        this._nullProgram = true;

        this._vertex = undefined;
        this._fragment = undefined;

        this._uniformsCache = undefined;
        this._attributesCache = undefined;

        if ( vShader )
            this.setVertexShader( vShader );

        if ( fShader )
            this.setFragmentShader( fShader );
    };

    /** @lends Program.prototype */
    Program.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {

        attributeType: 'Program',

        cloneType: function () {
            return new Program();
        },

        setVertexShader: function ( vs ) {
            this._vertex = vs;
            this._nullProgram = false;
        },

        setFragmentShader: function ( fs ) {
            this._fragment = fs;
            this._nullProgram = false;
        },

        getVertexShader: function () {
            return this._vertex;
        },
        getFragmentShader: function () {
            return this._fragment;
        },

        getProgram: function () {
            return this._program;
        },

        apply: function ( state ) {

            if ( this._nullProgram ) return;

            var gl = state.getGraphicContext();

            if ( !this._program || this.isDirty() ) {

                var compileClean;

                if ( !this._vertex.shader ) {
                    compileClean = this._vertex.compile( gl );
                }

                if ( !this._fragment.shader ) {
                    compileClean = this._fragment.compile( gl );
                }

                if ( compileClean ) {

                    this._program = gl.createProgram();

                    gl.attachShader( this._program, this._vertex.shader );
                    gl.attachShader( this._program, this._fragment.shader );
                    MACROUTILS.timeStamp( 'osgjs.metrics:linkShader' );
                    gl.linkProgram( this._program );

                    if ( !gl.getProgramParameter( this._program, gl.LINK_STATUS ) && !gl.isContextLost() ) {
                        var errLink = gl.getProgramInfoLog( this._program );

                        Notify.error( errLink );
                        Notify.log( 'can\'t link program\n' + 'vertex shader:\n' + this._vertex.text + '\n fragment shader:\n' + this._fragment.text, true, false );
                        // rawgl trick is for webgl inspector
                        var debugShader = ( gl.rawgl !== undefined ? gl.rawgl : gl );
                        if ( debugShader !== undefined && debugShader.getExtension !== undefined ) debugShader = debugShader.getExtension( 'WEBGL_debug_shaders' );
                        if ( debugShader && errLink === 'Failed to create D3D shaders.\n' ) {

                            Notify.error( debugShader.getTranslatedShaderSource( this._vertex.shader ), true, false );
                            Notify.error( debugShader.getTranslatedShaderSource( this._fragment.shader ), true, false );
                        }

                        compileClean = false;
                    }
                    // TODO: better usage of validate.
                    // as it's intended at shader program usage
                    // validating against current gl state
                    // Not for compilation stage
                    // gl.validateProgram( this._program );

                }

                if ( !compileClean ) {
                    // Any error, Any
                    // Pink must die.
                    if ( !Program.prototype._failSafeCache ) {

                        var program = gl.createProgram();
                        this._vertex.failSafe( gl );
                        this._fragment.failSafe( gl );

                        gl.attachShader( program, this._vertex.shader );
                        gl.attachShader( program, this._fragment.shader );
                        gl.linkProgram( program );
                        gl.validateProgram( program );

                        // cache to compile and allocate only once
                        // not polluting the inspector
                        Program.prototype._failSafeCache = program;
                    }
                    Notify.warn( 'FailSafe shader Activated ' );
                    this._program = this._failSafeCache;
                }

                this._uniformsCache = new Map();
                this._attributesCache = new Map();

                this.cacheUniformList( gl, this._vertex.text );
                this.cacheUniformList( gl, this._fragment.text );

                this.cacheAttributeList( gl, this._vertex.text );

                this.setDirty( false );
            }

            state.applyProgram( this._program );
        },

        cacheUniformList: function ( gl, str ) {
            var r = str.match( /uniform\s+\w+\s+\w+/g );
            var map = this._uniformsCache;
            if ( r !== null ) {
                for ( var i = 0, l = r.length; i < l; i++ ) {
                    var uniform = r[ i ].match( /uniform\s+\w+\s+(\w+)/ )[ 1 ];
                    var location = gl.getUniformLocation( this._program, uniform );
                    if ( location !== undefined && location !== null ) {
                        if ( map[ uniform ] === undefined ) {
                            map[ uniform ] = location;
                            this._uniformsCache.dirty();
                        }
                    }
                }
            }
        },

        cacheAttributeList: function ( gl, str ) {
            var r = str.match( /attribute\s+\w+\s+\w+/g );
            var map = this._attributesCache;
            if ( r !== null ) {
                for ( var i = 0, l = r.length; i < l; i++ ) {
                    var attr = r[ i ].match( /attribute\s+\w+\s+(\w+)/ )[ 1 ];
                    var location = gl.getAttribLocation( this._program, attr );
                    if ( location !== -1 && location !== undefined ) {
                        if ( map[ attr ] === undefined ) {
                            map[ attr ] = location;
                            this._attributesCache.dirty();
                        }
                    }
                }
            }
        }
    } ), 'osg', 'Program' );

    return Program;
} );
<|endoftext|>


<commit_before>/* eslint-disable no-unused-vars */
var config = {
  map: {
    '*': {
      'amastyGiftCardMain': 'Amasty_GiftCard/js/main',
    }
  }
};
<commit_msg>#86672 remove since Amasty_GiftCard/js/main no longer exists<commit_after><|endoftext|>


<commit_before>var ForbiddenAction = require('builder/data/backbone/network-interceptors/interceptors/forbidden-403');
var URLFunctions = require('builder/data/backbone/network-interceptors/interceptors/forbidden-403').URLFunctions;

describe('data/backbone/network-interceptors/interceptors/forbidden-403', function () {
  var action;

  beforeEach(function () {
    action = ForbiddenAction();
    spyOn(URLFunctions, 'redirectTo');
    spyOn(URLFunctions, 'getRedirectURL').and.callThrough();
  });

  it('should do nothing if error status is not 403', function () {
    action({ status: 404 });
    expect(URLFunctions.redirectTo).not.toHaveBeenCalled();
  });

  it('should redirect to login if error response contains an unknown error', function () {
    action({
      status: 403,
      responseJSON: {
        error: 'unknown'
      }
    });
    expect(URLFunctions.redirectTo).toHaveBeenCalledWith(window.location.origin + '/login');
  });

  it('should redirect to login if error response contains no error', function () {
    action({
      status: 403,
      responseJSON: {

      }
    });
    expect(URLFunctions.redirectTo).toHaveBeenCalledWith(window.location.origin + '/login');
  });

  it('should redirect to login if error response contains `session_expired`', function () {
    action({
      status: 403,
      responseJSON: {
        error: 'session_expired'
      }
    });
    expect(URLFunctions.redirectTo).toHaveBeenCalledWith(window.location.origin + '/login?error=session_expired');
  });

  it('should redirect to multifactor_authentication if error response contains `mfa_required`', function () {
    action({
      status: 403,
      responseJSON: {
        error: 'mfa_required'
      }
    });
    expect(URLFunctions.redirectTo).toHaveBeenCalledWith(window.location.origin + '/multifactor_authentication');
  });

  it('should redirect to lockout if error response contains `lockout`', function () {
    action({
      status: 403,
      responseJSON: {
        error: 'lockout'
      }
    });
    expect(URLFunctions.redirectTo).toHaveBeenCalledWith(window.location.origin + '/lockout');
  });

  it('should call getRedirectURL with username if provided', function () {
    var action = ForbiddenAction('username');
    action({
      status: 403,
      responseJSON: {
        error: 'session_expired'
      }
    });
    expect(URLFunctions.getRedirectURL).toHaveBeenCalledWith(window.location.origin, '/login?error=session_expired', 'username');
  });

  describe('.getRedirectURL', function () {
    it('should return URL with /login with the current URL if no username is provided', function () {
      expect(URLFunctions.getRedirectURL('http://test.carto.com', '/login?error=session_expired')).toBe('http://test.carto.com/login?error=session_expired');
    });

    it('should return current URL with username replaced if username is provided', function () {
      expect(URLFunctions.getRedirectURL('http://test-user.carto.com', '/login?error=session_expired', 'username')).toBe('http://username.carto.com/login?error=session_expired');
    });
  });
});
<commit_msg>Fix tests<commit_after>var ForbiddenAction = require('builder/data/backbone/network-interceptors/interceptors/forbidden-403');
var URLFunctions = require('builder/data/backbone/network-interceptors/interceptors/forbidden-403').URLFunctions;

describe('data/backbone/network-interceptors/interceptors/forbidden-403', function () {
  var action;

  beforeEach(function () {
    action = ForbiddenAction();
    spyOn(URLFunctions, 'redirectTo');
    spyOn(URLFunctions, 'getRedirectURL').and.callThrough();
  });

  it('should do nothing if error status is not 403', function () {
    action({ status: 404 });
    expect(URLFunctions.redirectTo).not.toHaveBeenCalled();
  });

  it('should redirect to login if error response contains `session_expired`', function () {
    action({
      status: 403,
      responseJSON: {
        error: 'session_expired'
      }
    });
    expect(URLFunctions.redirectTo).toHaveBeenCalledWith(window.location.origin + '/login?error=session_expired');
  });

  it('should redirect to multifactor_authentication if error response contains `mfa_required`', function () {
    action({
      status: 403,
      responseJSON: {
        error: 'mfa_required'
      }
    });
    expect(URLFunctions.redirectTo).toHaveBeenCalledWith(window.location.origin + '/multifactor_authentication');
  });

  it('should redirect to lockout if error response contains `lockout`', function () {
    action({
      status: 403,
      responseJSON: {
        error: 'lockout'
      }
    });
    expect(URLFunctions.redirectTo).toHaveBeenCalledWith(window.location.origin + '/lockout');
  });

  it('should call getRedirectURL with username if provided', function () {
    var action = ForbiddenAction('username');
    action({
      status: 403,
      responseJSON: {
        error: 'session_expired'
      }
    });
    expect(URLFunctions.getRedirectURL).toHaveBeenCalledWith(window.location.origin, '/login?error=session_expired', 'username');
  });

  describe('.getRedirectURL', function () {
    it('should return URL with /login with the current URL if no username is provided', function () {
      expect(URLFunctions.getRedirectURL('http://test.carto.com', '/login?error=session_expired')).toBe('http://test.carto.com/login?error=session_expired');
    });

    it('should return current URL with username replaced if username is provided', function () {
      expect(URLFunctions.getRedirectURL('http://test-user.carto.com', '/login?error=session_expired', 'username')).toBe('http://username.carto.com/login?error=session_expired');
    });
  });
});
<|endoftext|>