patternjavascriptMinor
Dual-mode JavaScript textbox watermark
Viewed 0 times
javascriptmodewatermarktextboxdual
Problem
I was just trying to make an alternate Ajax watermark from "insert date" (first mode) to "mm/dd/yyyy" (second mode). After some trial and error, I successfully implemented a solution using JavaScript.
How can I improve this script functionality?
JavaScript:
```
var original = "insert date";
var alternate = "mmddyyyy";
var countalerted = 0;
var txt = "";
var intird = 0;
if (intird == 0) {
intrId = setInterval(function () { alterWaterMarkForDateTBX() }, 1000);
}
function SetIntervalTBX() {
setInterval(function () { alterWaterMarkForDateTBX() }, 1000);
}
function alterWaterMarkForDateTBX() {
var d = new Date();
var t = d.toLocaleTimeString();
if (countalerted < 4) {
if (countalerted % 2 == 0) {
document.forms["form1"].elements["TBXinsertDate"].value = original;
}
else {
document.forms["form1"].elements["TBXinsertDate"].value = alternate;
}
countalerted++;
}
else {
window.status = intrId;
clearInterval(intrId);
// document.forms["form1"].elements["TBXinsertDate"].value = original;
}
}
var wasFocused = false;var wasBlur = false;
function Focus(objname, waterMarkText) {
wasFocused = true;
if (wasBlur == false) {
obj = document.getElementById(objname);
if (obj.value == waterMarkText) {
obj.value = "";
obj.className = "NormalTextBox";
if (obj.value == original || obj.value == alternate || obj.value == "" || obj.value == null) {
obj.style.color = "black";
}
}
}
}
//i added "__/__/____" for the value of the ajax MaskEdit
function Blur(objname, waterMarkText) {
wasBlur = true;
var alternateWM1 = "insert date";
var alternateWM2 = "mm/dd/yyyy";
obj = document.getElementById(objname);
if (obj.value == "" || obj.value == "__/__/____") {
obj.value = waterMarkText;
obj.className = "WaterMarkedTextBox";
}
else {
How can I improve this script functionality?
JavaScript:
```
var original = "insert date";
var alternate = "mmddyyyy";
var countalerted = 0;
var txt = "";
var intird = 0;
if (intird == 0) {
intrId = setInterval(function () { alterWaterMarkForDateTBX() }, 1000);
}
function SetIntervalTBX() {
setInterval(function () { alterWaterMarkForDateTBX() }, 1000);
}
function alterWaterMarkForDateTBX() {
var d = new Date();
var t = d.toLocaleTimeString();
if (countalerted < 4) {
if (countalerted % 2 == 0) {
document.forms["form1"].elements["TBXinsertDate"].value = original;
}
else {
document.forms["form1"].elements["TBXinsertDate"].value = alternate;
}
countalerted++;
}
else {
window.status = intrId;
clearInterval(intrId);
// document.forms["form1"].elements["TBXinsertDate"].value = original;
}
}
var wasFocused = false;var wasBlur = false;
function Focus(objname, waterMarkText) {
wasFocused = true;
if (wasBlur == false) {
obj = document.getElementById(objname);
if (obj.value == waterMarkText) {
obj.value = "";
obj.className = "NormalTextBox";
if (obj.value == original || obj.value == alternate || obj.value == "" || obj.value == null) {
obj.style.color = "black";
}
}
}
}
//i added "__/__/____" for the value of the ajax MaskEdit
function Blur(objname, waterMarkText) {
wasBlur = true;
var alternateWM1 = "insert date";
var alternateWM2 = "mm/dd/yyyy";
obj = document.getElementById(objname);
if (obj.value == "" || obj.value == "__/__/____") {
obj.value = waterMarkText;
obj.className = "WaterMarkedTextBox";
}
else {
Solution
Some notes:
-
Think about reusability. Your code integrates the field names directly into the functions. Same goes for some of your choices of function names (
-
You appear to be mixing ideas. You set a class name sometimes, set the text color other times. I'm not sure if this was intentional but I just changed it all to class names.
-
You had some dead variables. Stuff like this just make it harder to edit in the future. Remove them.
-
You are checking to make sure the field had focus before it blurred (and vice versa). And then Not sure what the purpose of that is.
-
Your focus and blur events pass in the textbox name and the textbox value (as
-
Think about non-intrusive javascript. It is easier to maintain. Notice how I added the blur and focus events to the field through javascript instead of directly in the html.
-
You should try to avoid global objects. Look into putting this entire code block into an object. The problem you will face is what if you have two fields on the same form that need this functionality. The changes I have made below will go a long way in helping but the global interval and global counter will conflict with one another and it will not work.
EDIT:
I was interested in this problem. So I extended my code.
-
I moved the main work into a function object. This can now be called using a constructor which passes in the text box. This also allows for multiple textboxes using this even on the same page.
-
I added an options object to the parameters. This will allow you to change the functionality of the script without changing the actual code. This allows for reusability without needing to modify the code (open-closed principle). This is also a common technique used in many of the JS frameworks (jQuery, mooTools, etc..)
Styles:
Script:
Body:
```
-
Think about reusability. Your code integrates the field names directly into the functions. Same goes for some of your choices of function names (
alterWaterMarkForDateTBX). This makes it difficult to reuse next time you need this function. -
You appear to be mixing ideas. You set a class name sometimes, set the text color other times. I'm not sure if this was intentional but I just changed it all to class names.
-
You had some dead variables. Stuff like this just make it harder to edit in the future. Remove them.
var d = new Date(); var t = d.toLocaleTimeString();-
You are checking to make sure the field had focus before it blurred (and vice versa). And then Not sure what the purpose of that is.
-
Your focus and blur events pass in the textbox name and the textbox value (as
watermarkText. Then you check the value against a couple of other values and if it matches set the textbox back to watermarkText. This will never accomplish anything and is confusing. Just pass in the textbox itself.-
Think about non-intrusive javascript. It is easier to maintain. Notice how I added the blur and focus events to the field through javascript instead of directly in the html.
-
You should try to avoid global objects. Look into putting this entire code block into an object. The problem you will face is what if you have two fields on the same form that need this functionality. The changes I have made below will go a long way in helping but the global interval and global counter will conflict with one another and it will not work.
EDIT:
I was interested in this problem. So I extended my code.
-
I moved the main work into a function object. This can now be called using a constructor which passes in the text box. This also allows for multiple textboxes using this even on the same page.
-
I added an options object to the parameters. This will allow you to change the functionality of the script without changing the actual code. This allows for reusability without needing to modify the code (open-closed principle). This is also a common technique used in many of the JS frameworks (jQuery, mooTools, etc..)
Styles:
.NormalTextBox {
color = "black";
}
.WaterMarkedTextBox {
color = "grey";
}Script:
var MultiWatermark = function (obj, options) {
var defaultOptions = {
// These variables can be changed to alter functionality using the passed in options object
watermarkVals: ["insert date", "mmddyyyy"], // all watermark values.
totalIterations: 2, // how many times to go through watermark Array.
watermarkClassName: "WaterMarkedTextBox",
normalClassName: "NormalTextBox",
changeDelay: 1000, // in milliseconds
extraValsToCheck: ['', null]//
}
//merge options with defaultOptions
for (var property in defaultOptions) {
if (!options.hasOwnProperty(property)) {
options[property] = defaultOptions[property];
}
}
// local variables (do not change)
var textBox = obj;
var iterationCounter = 0;
var itemCounter = 0;
var intrId;
var startWatermark = function () {
itemCounter = 0; iterationCounter = 0; // resets for after blur
intrId = setInterval(function () { alterWaterMark() }, options.changeDelay);
}
var stopWatermark = function () {
clearInterval(intrId);
}
var alterWaterMark = function () {
if (iterationCounter < options.totalIterations) {
textBox.value = options.watermarkVals[itemCounter];
itemCounter += 1;
if (itemCounter == options.watermarkVals.length) {
itemCounter = 0;
iterationCounter += 1;
}
}
else {
stopWatermark();
}
}
var isWatermarkValue = function (val) {
var i = options.watermarkVals.length;
while (i--) {
if (options.watermarkVals[i] === val) {
return true;
}
}
// value is not in watermark array, so check secondary values.
i = options.extraValsToCheck.length;
while (i--) {
if (options.extraValsToCheck[i] === val) {
return true;
}
}
}
var setClass = function () {
textBox.className = isWatermarkValue(textBox.value) ? options.watermarkClassName : options.normalClassName;
}
var focusEvent = function () {
stopWatermark();
if (isWatermarkValue(textBox.value)) {
textBox.value = "";
}
setClass()
}
var blurEvent = function () {
if (isWatermarkValue(textBox.value)) {
startWatermark();
}
setClass();
}
var initWatermark = function () {
setClass();
textBox.onfocus = focusEvent;
textBox.onblur = blurEvent;
startWatermark();
}
initWatermark();
}Body:
```
Code Snippets
.NormalTextBox {
color = "black";
}
.WaterMarkedTextBox {
color = "grey";
}var MultiWatermark = function (obj, options) {
var defaultOptions = {
// These variables can be changed to alter functionality using the passed in options object
watermarkVals: ["insert date", "mmddyyyy"], // all watermark values.
totalIterations: 2, // how many times to go through watermark Array.
watermarkClassName: "WaterMarkedTextBox",
normalClassName: "NormalTextBox",
changeDelay: 1000, // in milliseconds
extraValsToCheck: ['', null]//
}
//merge options with defaultOptions
for (var property in defaultOptions) {
if (!options.hasOwnProperty(property)) {
options[property] = defaultOptions[property];
}
}
// local variables (do not change)
var textBox = obj;
var iterationCounter = 0;
var itemCounter = 0;
var intrId;
var startWatermark = function () {
itemCounter = 0; iterationCounter = 0; // resets for after blur
intrId = setInterval(function () { alterWaterMark() }, options.changeDelay);
}
var stopWatermark = function () {
clearInterval(intrId);
}
var alterWaterMark = function () {
if (iterationCounter < options.totalIterations) {
textBox.value = options.watermarkVals[itemCounter];
itemCounter += 1;
if (itemCounter == options.watermarkVals.length) {
itemCounter = 0;
iterationCounter += 1;
}
}
else {
stopWatermark();
}
}
var isWatermarkValue = function (val) {
var i = options.watermarkVals.length;
while (i--) {
if (options.watermarkVals[i] === val) {
return true;
}
}
// value is not in watermark array, so check secondary values.
i = options.extraValsToCheck.length;
while (i--) {
if (options.extraValsToCheck[i] === val) {
return true;
}
}
}
var setClass = function () {
textBox.className = isWatermarkValue(textBox.value) ? options.watermarkClassName : options.normalClassName;
}
var focusEvent = function () {
stopWatermark();
if (isWatermarkValue(textBox.value)) {
textBox.value = "";
}
setClass()
}
var blurEvent = function () {
if (isWatermarkValue(textBox.value)) {
startWatermark();
}
setClass();
}
var initWatermark = function () {
setClass();
textBox.onfocus = focusEvent;
textBox.onblur = blurEvent;
startWatermark();
}
initWatermark();
}<form id="form1" runat="server">
<input ID="TBXinsertDate" ToolTip="date Box" Width="79px" />
<input ID="Text1" ToolTip="date Box" Width="79px" />
</form>
<script>
var dateOptions = {
// These variables alter functionality, the main script will use the defaults of any options not included here
watermarkVals: ["insert date", "mmddyyyy", "mm/dd/yyyy"], // all watermark values.
totalIterations: 4,
changeDelay: 500, // in milliseconds
extraValsToCheck: ['', null, '__/__/____', 'test']//
}
new MultiWatermark(document.forms["form1"].elements["TBXinsertDate"], dateOptions);
new MultiWatermark(document.forms["form1"].elements["Text1"], dateOptions);
</script>
</body>
</html>Context
StackExchange Code Review Q#16159, answer score: 3
Revisions (0)
No revisions yet.