Socket
Socket
Sign inDemoInstall

form-js

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

form-js - npm Package Compare versions

Comparing version 1.11.1 to 2.0.0

2

bower.json
{
"name": "form-js",
"version": "1.11.1",
"version": "2.0.0",
"homepage": "https://github.com/mkay581/form-js",

@@ -5,0 +5,0 @@ "authors": [

/**
* form-js - v1.11.1.
* form-js - v2.0.0.
* https://github.com/mkay581/form-js.git

@@ -4,0 +4,0 @@ * Copyright 2015 Mark Kennedy. Licensed MIT.

/**
* form-js - v1.11.1.
* form-js - v2.0.0.
* https://github.com/mkay581/form-js.git

@@ -4,0 +4,0 @@ * Copyright 2015 Mark Kennedy. Licensed MIT.

/**
* form-js - v1.11.1.
* form-js - v2.0.0.
* https://github.com/mkay581/form-js.git

@@ -4,0 +4,0 @@ * Copyright 2015 Mark Kennedy. Licensed MIT.

/**
* form-js - v1.11.1.
* form-js - v2.0.0.
* https://github.com/mkay581/form-js.git

@@ -4,0 +4,0 @@ * Copyright 2015 Mark Kennedy. Licensed MIT.

{
"name": "form-js",
"version": "1.11.1",
"version": "2.0.0",
"description": "Create better ui form elements. Supports IE9+, all modern browsers, and mobile.",

@@ -5,0 +5,0 @@ "repository": {

@@ -15,3 +15,5 @@ 'use strict';

* @callback Form~onValueChange
* @param {Event} event - The event that fired the change
* @param {string} value - The new value
* @param {HTMLElement} element - The form element
* @param {HTMLElement} uIElement - The ui-version of the form element
*/

@@ -68,4 +70,2 @@

this.options = options;
// okay to cache here because its a "live" html collection -- yay!

@@ -75,2 +75,3 @@ this.formEls = this.options.el.elements;

this._formInstances = [];
this._moduleCount = 0;
Module.prototype.initialize.call(this, this.options);

@@ -80,2 +81,34 @@ },

/**
* Returns a mapping of ids to their associated form option and selector.
*/
_getSelectorMap: function () {
return {
dropdown: {
option: this.options.dropdownClass,
selector: 'select',
tag: 'select'
},
checkbox: {
option: this.options.checkboxClass,
tag: 'input',
types: ['checkbox']
},
input: {
option: this.options.inputFieldClass,
tag: 'input',
types: [
'password', 'email', 'number', 'text', 'date',
'datetime', 'month', 'search', 'range', 'time',
'week', 'tel', 'color', 'datetime-local'
]
},
radio: {
option: this.options.buttonToggleClass,
tag: 'input',
types: ['radio']
}
}
},
/**
* Sets up the form and instantiates all necessary element classes.

@@ -85,7 +118,14 @@ */

var submitButtonEl = this.options.el.getElementsByClassName(this.options.submitButtonClass)[0];
this._setupInstances(this.options.dropdownClass, Dropdown);
this._setupInstances(this.options.checkboxClass, Checkbox);
this._setupInstances(this.options.inputFieldClass, InputField);
this._setupButtonToggleInstances(this.options.buttonToggleClass);
this._setupInstances(this._getInstanceEls('dropdown'), Dropdown);
this._setupInstances(this._getInstanceEls('checkbox'), Checkbox);
this._setupInstances(this._getInstanceEls('input'), InputField);
// group radio button toggles by name before instantiating
var radios = this._getInstanceEls('radio');
_.each(this.mapElementsByAttribute(radios, 'name'), function (els) {
this._setupInstance(els, ButtonToggle, {}, 'inputs');
}, this);
if (submitButtonEl) {

@@ -101,4 +141,34 @@ this.subModules.submitButton = new SubmitButton({

/**
* Instantiates elements.
* @param {string} cssClass - The class that the elements must match to be instantiated
* Gets the matching form elements, based on the supplied type.
* @param {string} type - The type identifier (i.e. "dropdown", "checkbox", "input")
* @returns {Array|HTMLCollection} Returns an array of matching elements
* @private
*/
_getInstanceEls: function (type) {
var formEl = this.options.el,
elements = [],
map = this._getSelectorMap();
map = map[type] || {};
// we are strategically grabbing elements by "tagName" to ensure we have a LIVE HTMLCollection
// instead of an ineffective, non-live NodeList (i.e. querySelector), can we say, "less state management"!
if (map.option) {
elements = formEl.getElementsByClassName(map.option);
} else if (map.types) {
map.types.forEach(function (val) {
(this.mapElementsByAttribute(this.formEls, 'type')[val] || []).forEach(function (el) {
elements.push(el);
});
}, this);
} else if (map.tag) {
elements = formEl.getElementsByTagName(map.tag);
}
return elements;
},
/**
* Creates a single instance of a class for each of the supplied elements.
* @param {HTMLCollection|Array} elements - The set of elements to instance the class on
* @param {Function} View - The class to instantiate

@@ -109,19 +179,8 @@ * @param {Object} [options] - The options to be passed to instantiation

*/
_setupInstances: function (cssClass, View, options, elKey) {
var elements = this.options.el.getElementsByClassName(cssClass),
count = elements.length,
i,
instance,
el;
var finalOptions = {};
_setupInstances: function (elements, View, options, elKey) {
var count = elements.length,
i;
if (count) {
elKey = elKey || 'el';
for (i = 0; i < count; i++) {
el = elements[i];
finalOptions = this._buildOptions(el, options);
finalOptions[elKey] = el; // dont allow custom options to override the el!
instance = this.subModules['fe' + elKey + cssClass + i] = new View(finalOptions);
this._formInstances.push(instance);
this._setupInstance(elements[i], View, options, elKey);
}

@@ -132,23 +191,25 @@ }

/**
* Sets up button toggle instances by on the elements that contain the supplied css class.
* @param {string} cssClass - The css class of all button toggle elements to instantiate
* Creates a single instance of a class using multiple elements.
* @param {Array|HTMLCollection} els - The elements for which to setup an instance
* @param {Function} View - The class to instantiate
* @param {Object} [options] - The options to be passed to instantiation
* @param {string} [elKey] - The key to use as the "el"
* @private
*/
_setupButtonToggleInstances: function (cssClass) {
var toggleNameMap = this.mapElementsByName(this.options.el.getElementsByClassName(cssClass)),
elKey = 'radio',
finalOptions = {};
_.each(toggleNameMap, function (els, name) {
finalOptions = this._buildOptions(els, {});
finalOptions.inputs = els; // dont allow custom options to override the radio inputs
this._formInstances.push(this.subModules['fe' + elKey + cssClass + name] = new ButtonToggle(finalOptions));
}, this);
_setupInstance: function (els, View, options, elKey) {
elKey = elKey || 'el';
var finalOptions = this._buildOptions(els, options);
finalOptions[elKey] = els; // dont allow custom options to override the el!
this._moduleCount++;
var instance = this.subModules['fe' + this._moduleCount] = new View(finalOptions);
this._formInstances.push(instance);
},
/**
* Takes a set of elements and maps them by their name attributes.
* @param {HTMLCollection|Array|NodeList} elements - An array of elements
* @returns {{}} Returns an object with name/elements mapping
* Maps all supplied elements by an attribute.
* @param {Array|HTMLCollection|NodeList} elements
* @param {string} attr - The attribute to map by (the values will be the keys in the map returned)
* @returns {Object} Returns the final object
*/
mapElementsByName: function (elements) {
mapElementsByAttribute: function (elements, attr) {
var map = {},

@@ -161,6 +222,6 @@ count = elements.length,

el = elements[i];
if (map[el.name]) {
map[el.name].push(el);
if (map[el[attr]]) {
map[el[attr]].push(el);
} else {
map[el.name] = [el];
map[el[attr]] = [el];
}

@@ -173,2 +234,12 @@ }

/**
* Takes a set of elements and maps them by their name attributes.
* @param {HTMLCollection|Array|NodeList} elements - An array of elements
* @returns {{}} Returns an object with name/elements mapping
* @deprecated since 2.0.0
*/
mapElementsByName: function (elements) {
return this.mapElementsByAttribute(elements, 'name');
},
/**
* Returns the instance (if there is one) of an element with a specified name attribute

@@ -175,0 +246,0 @@ * @param {string} name - The name attribute of the element whos instance is desired

@@ -89,3 +89,3 @@ "use strict";

QUnit.test('should call initialize method of Module super class when instantiated', function () {
QUnit.test('should call initialize method of Module super class with correct el when instantiated', function () {
QUnit.expect(1);

@@ -96,3 +96,3 @@ var formEl = TestUtils.createHtmlElement('<form></form>');

var formInstance = new Form(formOptions);
QUnit.deepEqual(moduleInitializeStub.args[0][0], formOptions, 'initialized with form options');
QUnit.deepEqual(moduleInitializeStub.args[0][0].el, formEl);
formInstance.destroy();

@@ -102,3 +102,3 @@ moduleInitializeStub.restore();

QUnit.test('Dropdown class should be instantiated with correct select element and get destroyed correctly', function () {
QUnit.test('specifying a css class for dropdown selects in initialize options should instantiate and destroy Dropdown class correctly', function () {
QUnit.expect(3);

@@ -126,4 +126,26 @@ var dropdownClass = 'form-dropdown-select';

QUnit.test('InputField class should be instantiated with correct input element and get destroyed correctly', function () {
QUnit.test('when a select element exists, Dropdown gets instantiated with the select element in its options, and destroys correctly', function () {
QUnit.expect(3);
var formEl = TestUtils.createHtmlElement(' ' +
'<form>' +
'<select name="select" id="age-gate-form-country-label-id">' +
'<option class="form-dropdown-option">North America</option>' +
'</select>' +
'</form>');
var selectEl = formEl.getElementsByTagName('select')[0];
var dropdownInitialize = Sinon.stub(Dropdown.prototype, 'initialize');
var dropdownDestroy = Sinon.stub(Dropdown.prototype, 'destroy');
var formInstance = new Form({el: formEl});
QUnit.equal(dropdownInitialize.callCount, 0, 'Dropdown class was not yet initialized because setup() wasnt triggered yet');
formInstance.setup();
QUnit.deepEqual(dropdownInitialize.args[0][0].el, selectEl, 'after setting up, Dropdown class was instantiated with correct options');
formInstance.destroy();
QUnit.equal(dropdownDestroy.callCount, 1, 'after destroy() is called, Dropdown class instance was destroyed');
dropdownDestroy.restore();
dropdownInitialize.restore();
});
QUnit.test('specifying a css class for input fields in initialize options should instantiate and destroy InputField class correctly', function () {
QUnit.expect(3);
var inputClass = 'text-field';

@@ -148,4 +170,24 @@ var formEl = TestUtils.createHtmlElement(' ' +

QUnit.test('Checkbox class should be instantiated with checkbox elements and get destroyed correctly', function () {
QUnit.test('when an text input element exists, InputField gets instantiated with the input element in its options, and destroys correctly', function () {
QUnit.expect(3);
var formEl = TestUtils.createHtmlElement(' ' +
'<form>' +
'<input type="text" name="test_input_field" value="text1" />' +
'</form>'
);
var inputEl = formEl.getElementsByTagName('input')[0];
var inputFieldInitialize = Sinon.stub(InputField.prototype, 'initialize');
var inputFieldDestroy = Sinon.stub(InputField.prototype, 'destroy');
var formInstance = new Form({el: formEl});
QUnit.equal(inputFieldInitialize.callCount, 0, 'InputField class was not yet initialized because setup() wasnt triggered yet');
formInstance.setup();
QUnit.deepEqual(inputFieldInitialize.args[0][0].el, inputEl, 'after setting up, InputField class was instantiated with correct options');
formInstance.destroy();
QUnit.equal(inputFieldDestroy.callCount, 1, 'after destroy() is called, InputField class instance was destroyed');
inputFieldDestroy.restore();
inputFieldInitialize.restore();
});
QUnit.test('specifying a css class for checkbox inputs in initialize options should instantiate and destroy Checkbox class correctly', function () {
QUnit.expect(3);
var checkboxClass = 'checkbox';

@@ -171,3 +213,24 @@ var formEl = TestUtils.createHtmlElement(' ' +

QUnit.test('ButtonToggle class should be instantiated with radio button elements with the same name attribute and get destroyed correctly', function () {
QUnit.test('when an input checkbox element exists, Checkbox gets instantiated with the checkbox element in its options, and destroys correctly', function () {
QUnit.expect(3);
var formEl = TestUtils.createHtmlElement(' ' +
'<form>' +
'<input type="checkbox" name="test_toggle" value="toggle1" />' +
'<input type="checkbox" name="test_toggle" value="toggle2" />' +
'</form>');
var checkboxEls = formEl.getElementsByTagName('input');
var checkboxInitializeStub = Sinon.stub(Checkbox.prototype, 'initialize');
var checkboxDestroyStub = Sinon.stub(Checkbox.prototype, 'destroy');
var formInstance = new Form({el: formEl});
formInstance.setup();
QUnit.equal(checkboxInitializeStub.args[0][0].el, checkboxEls[0], 'after setting up, first Checkbox class was instantiated with first checkbox element');
QUnit.equal(checkboxInitializeStub.args[1][0].el, checkboxEls[1], 'second Checkbox class was instantiated with second checkbox element');
formInstance.destroy();
QUnit.equal(checkboxDestroyStub.callCount, 2, 'both Checkbox instances were destroyed');
checkboxDestroyStub.restore();
checkboxInitializeStub.restore();
});
QUnit.test('when multiple radio inputs exist with the same supplied css class, with the same name attribute, only one ButtonToggle instance should be created, and destroyed correctly', function () {
QUnit.expect(4);

@@ -195,2 +258,68 @@ var radioClass = 'radio';

QUnit.test('when multiple radio inputs exist with the same name attribute, only one ButtonToggle instance should be created, and destroyed correctly', function () {
QUnit.expect(4);
var formEl = TestUtils.createHtmlElement(' ' +
'<form>' +
'<input type="radio" name="test" value="radioA" />' +
'<input type="radio" name="test" value="radioB" />' +
'</form>');
var radioEls = formEl.getElementsByTagName('input');
var buttonToggleInitializeStub = Sinon.stub(ButtonToggle.prototype, 'initialize');
var buttonToggleDestroyStub = Sinon.stub(ButtonToggle.prototype, 'destroy');
var formInstance = new Form({el: formEl});
formInstance.setup();
QUnit.equal(buttonToggleInitializeStub.args[0][0].inputs[0], radioEls[0], 'after setting up, ButtonToggle class was instantiated with first radio element');
QUnit.equal(buttonToggleInitializeStub.args[0][0].inputs[1], radioEls[1], 'ButtonToggle class was instantiated with second radio element');
QUnit.equal(buttonToggleInitializeStub.callCount, 1, 'ButtonToggle class was only instantiated once');
formInstance.destroy();
QUnit.equal(buttonToggleDestroyStub.callCount, 1, 'ButtonToggle instance was destroyed');
buttonToggleDestroyStub.restore();
buttonToggleInitializeStub.restore();
});
QUnit.test('specifying css class for radio buttons in initialize options should instantiate and destroy ButtonToggle class correctly', function () {
QUnit.expect(3);
var radioClass = 'radio';
var formEl = TestUtils.createHtmlElement(' ' +
'<form>' +
'<input type="radio" name="test" class="' + radioClass + '" value="radioA" />' +
'<input type="radio" name="test2" class="' + radioClass + '" value="radioB" />' +
'</form>');
var radioEls = formEl.getElementsByClassName(radioClass);
var buttonToggleInitializeStub = Sinon.stub(ButtonToggle.prototype, 'initialize');
var buttonToggleDestroyStub = Sinon.stub(ButtonToggle.prototype, 'destroy');
var formInstance = new Form({el: formEl, buttonToggleClass: radioClass});
formInstance.setup();
QUnit.equal(buttonToggleInitializeStub.args[0][0].inputs[0], radioEls[0], 'after setting up, ButtonToggle class was instantiated with first radio element');
QUnit.equal(buttonToggleInitializeStub.args[1][0].inputs[0], radioEls[1], 'ButtonToggle class was instantiated again with second radio element');
formInstance.destroy();
QUnit.equal(buttonToggleDestroyStub.callCount, 2, 'all ButtonToggle instances were destroyed');
buttonToggleDestroyStub.restore();
buttonToggleInitializeStub.restore();
});
QUnit.test('radio buttons without css classes should instantiate and destroy ButtonToggle class correctly', function () {
QUnit.expect(3);
var formEl = TestUtils.createHtmlElement(' ' +
'<form>' +
'<input type="radio" name="test" value="radioA" />' +
'<input type="radio" name="test2" value="radioB" />' +
'</form>');
var radioEls = formEl.getElementsByTagName('input');
var buttonToggleInitializeStub = Sinon.stub(ButtonToggle.prototype, 'initialize');
var buttonToggleDestroyStub = Sinon.stub(ButtonToggle.prototype, 'destroy');
var formInstance = new Form({el: formEl});
formInstance.setup();
QUnit.equal(buttonToggleInitializeStub.args[0][0].inputs[0], radioEls[0], 'after setting up, ButtonToggle class was instantiated with first radio element');
QUnit.equal(buttonToggleInitializeStub.args[1][0].inputs[0], radioEls[1], 'ButtonToggle class was instantiated again with second radio element');
formInstance.destroy();
QUnit.equal(buttonToggleDestroyStub.callCount, 2, 'all ButtonToggle instances were destroyed');
buttonToggleDestroyStub.restore();
buttonToggleInitializeStub.restore();
});
QUnit.test('SubmitButton class should NOT be instantiated if there is no element that matches the passed class', function () {

@@ -229,25 +358,2 @@ QUnit.expect(1);

QUnit.test('multiple ButtonToggle classes should be instantiated with radio button elements with different name attributes and they should be destroyed correctly', function () {
QUnit.expect(3);
var radioClass = 'radio';
var formEl = TestUtils.createHtmlElement(' ' +
'<form>' +
'<input type="radio" name="test" class="' + radioClass + '" value="radioA" />' +
'<input type="radio" name="test2" class="' + radioClass + '" value="radioB" />' +
'</form>');
var radioEls = formEl.getElementsByClassName(radioClass);
var buttonToggleInitializeStub = Sinon.stub(ButtonToggle.prototype, 'initialize');
var buttonToggleDestroyStub = Sinon.stub(ButtonToggle.prototype, 'destroy');
var formInstance = new Form({el: formEl, buttonToggleClass: radioClass});
formInstance.setup();
QUnit.equal(buttonToggleInitializeStub.args[0][0].inputs[0], radioEls[0], 'after setting up, ButtonToggle class was instantiated with first radio element');
QUnit.equal(buttonToggleInitializeStub.args[1][0].inputs[0], radioEls[1], 'ButtonToggle class was instantiated again with second radio element');
formInstance.destroy();
QUnit.equal(buttonToggleDestroyStub.callCount, 2, 'all ButtonToggle instances were destroyed');
buttonToggleDestroyStub.restore();
buttonToggleInitializeStub.restore();
});
QUnit.test('getInstanceByName()', function () {

@@ -254,0 +360,0 @@ QUnit.expect(1);

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc