Skip to content

Commit

Permalink
Merge pull request #33 from kristerkari/bugfix/change-type
Browse files Browse the repository at this point in the history
Handle input type change after page load, fixes #30
  • Loading branch information
Krister Kari committed Jun 22, 2015
2 parents 05b12c6 + 445b802 commit 2c550df
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@
element.setAttribute("data-placeholder-maxlength", element.maxLength);
}

function getTypeAttr(element) {
return element.getAttribute("data-placeholder-type");
}

function setTypeAttr(element, type) {
element.setAttribute("data-placeholder-type", type);
}
Expand Down Expand Up @@ -109,6 +113,7 @@
getMaxLengthAttr: getMaxLengthAttr,
getElementValueAttr: getElementValueAttr,
getValueAttr: getValueAttr,
getTypeAttr: getTypeAttr,
setElementValueAttr: setElementValueAttr,
setValueAttr: setValueAttr,
setActiveAttr: setActiveAttr,
Expand Down
32 changes: 32 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

function setupElement(element, placeholderValue) {
data.setValueAttr(element, placeholderValue);
data.setTypeAttr(element, utils.getElementType(element));
data.setElementValueAttr(element, element.value);
data.setEventsAttr(element);
elems.createPasswordCloneIfNeeded(element);
Expand Down Expand Up @@ -85,7 +86,36 @@
return element.value !== "" || element === support.safeActiveElement();
}

function isClone(element) {
return data.hasCloneAttrSetToTrue(element) && elems.getPasswordOriginal(element) != null;
}

function hasChangedType(element) {
var el = isClone(element) ? elems.getPasswordOriginal(element) : element;
return utils.getElementType(el) !== data.getTypeAttr(element);
}

function handleTypeChange(element) {

if (!hasChangedType(element)) {
return;
}

if (isClone(element)) {
var type = data.getTypeAttr(element);
element = elems.getPasswordOriginal(element);
element.setAttribute("type", type);
}

cleanupElement(element);
}

function checkForPlaceholder(element) {

if (!element) {
return;
}

var placeholder = utils.getPlaceholderValue(element);
var clone;

Expand All @@ -100,6 +130,8 @@
return;
}

handleTypeChange(element);

if (needsSetup(element)) {
setupElement(element, placeholder);
} else {
Expand Down
1 change: 0 additions & 1 deletion src/polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
} else {
element.type = "text";
}
data.setTypeAttr(element, "password");
}

element.value = val;
Expand Down
199 changes: 199 additions & 0 deletions test/unit/change-type.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
describe("changing element type", function() {
"use strict";

beforeEach(helpers.initialSetup);

if (helpers.canActuallyChangeType) {

describe("when input type can be changed", function() {

beforeEach(function() {
helpers.spyOnCanChangeToTypeAndReturn(true);
helpers.spyOnNativeSupportAndReturn(false);
});

describe("when a password input with placeholder exists on the page", function() {
var element;

beforeEach(function(done) {
element = helpers.createInputElement(true, "password");
setTimeout(done, helpers.loopDurationForTests);
placekeeper.priv.__init();
});

afterEach(function() {
element.parentNode.removeChild(element);
});

describe("and when its type is changed to text with a data attribute", function() {

beforeEach(function(done) {
element.setAttribute("data-placeholder-type", "text");
setTimeout(done, helpers.loopDurationForTests);
});

it("should have one input on the page", function() {
expect(document.getElementsByTagName("input").length).toEqual(1);
});

it("should have element type set to text", function() {
expect(element.type).toEqual("text");
});

});

});

describe("when a text input with placeholder exists on the page", function() {
var element;

beforeEach(function(done) {
element = helpers.createInputElement(true);
setTimeout(done, helpers.loopDurationForTests);
placekeeper.priv.__init();
});

afterEach(function() {
element.parentNode.removeChild(element);
});

describe("and when its type is changed to password", function() {

beforeEach(function(done) {
element.type = "password";
setTimeout(done, helpers.loopDurationForTests);
});

it("should have one input on the page", function() {
expect(document.getElementsByTagName("input").length).toEqual(1);
});

it("should have element type set to text (so that placeholder is visible)", function() {
expect(element.type).toEqual("text");
});

/* This test is failing
TODO: find out why
describe("and when the element is focused", function() {
beforeEach(function(done) {
helpers.retryFocus(element, function() {
setTimeout(done, helpers.loopDurationForTests);
});
});
it("should have element type set to password", function() {
expect(element.type).toEqual("password");
});
});
*/

});

});

});

describe("when input type can not be changed", function() {

beforeEach(function() {
helpers.spyOnCanChangeToTypeAndReturn(false);
helpers.spyOnNativeSupportAndReturn(false);
});

describe("when a password input with placeholder exists on the page", function() {
var element;

beforeEach(function(done) {
element = helpers.createInputElement(true, "password");
setTimeout(function() {
element = document.getElementById("elem");
done();
}, helpers.loopDurationForTests);
placekeeper.priv.__init();
});

afterEach(function() {
element.parentNode.removeChild(element);
});

describe("and when its type is changed to text with a data attribute", function() {

beforeEach(function(done) {
element.setAttribute("data-placeholder-type", "text");
setTimeout(function() {
element = document.getElementById("elem");
done();
}, helpers.loopDurationForTests);
});

it("should have one input on the page", function() {
expect(document.getElementsByTagName("input").length).toEqual(1);
});

it("should have element type set to text", function() {
expect(element.type).toEqual("text");
});

});

});

describe("when a text input with placeholder exists on the page", function() {
var element;

beforeEach(function(done) {
element = helpers.createInputElement(true);
placekeeper.priv.__init();
setTimeout(done, helpers.loopDurationForTests);
});

afterEach(function() {
element.parentNode.removeChild(element);
});

describe("and when its type is changed to password", function() {

beforeEach(function(done) {
element.type = "password";
setTimeout(function() {
element = document.getElementById("elem");
done();
}, helpers.loopDurationForTests);
});

it("should have two inputs on the page", function() {
expect(document.getElementsByTagName("input").length).toEqual(2);
});

it("should have element type set to text", function() {
expect(element.type).toEqual("text");
});

describe("and when the element is focused", function() {

beforeEach(function(done) {
helpers.retryFocus(element, function() {
setTimeout(function() {
element = document.getElementById("elem");
done();
}, helpers.loopDurationForTests);
});
});

it("should have element type set to password", function() {
expect(element.type).toEqual("password");
});

});

});

});

});

}

});

0 comments on commit 2c550df

Please sign in to comment.