Prevent user from entering numbers but keep the alphabetical characters they have already entered - regex

I'm trying to stop user from entering numbers in an input form but keep alphabetical characters. At the moment,as soon as the user enters a number, my code erases everything entered before, e.g. "Ann3" turns to an "".
I don't know how to keep "Ann" when the user accidentally hits "3". This is what I've got so far:
updateName(event) {
var value = event.target.value;
var model = this.state;
if (!value.match("^[a-zA-Z]*$")) {
value = "";
};
this.setState({ [event.target.name]: value })
I wonder if I could use concatenation here, I'm sorry, I'm new to ReactJS and programming in general and don't know where to start.

Rather than setting value to the empty string, you could use .replace to replace all non-alphabetical characters with the empty string (thereby keeping alphabetical characters and their relative positions):
updateName(event) {
const { value, name } = event.target;
this.setState({ [name]: value.replace(/[^a-z]/gi, '') });
}

i did a code sample with react bootstrap but i'm sure it will work for you:
let { FormGroup,ControlLabel,FormControl } = ReactBootstrap;
class Example extends React.Component {
constructor(props, context) {
super(props, context);
this.handleChange = this.handleChange.bind(this);
this.state = {
value: ''
};
}
getValidationState() {
const length = this.state.value.length;
if (length > 3) return 'success';
else if (length > 2) return 'warning';
else if (length > 0) return 'error';
return null;
}
handleChange(e) {
this.setState({value : e.target.value.replace(/[^a-z]/gi, '')})
}
render() {
return (
<form>
<FormGroup
controlId="formBasicText"
validationState={this.getValidationState()}
>
<ControlLabel>keep alphabetical characters</ControlLabel>
<FormControl
type="text"
value={this.state.value}
placeholder="Enter text"
onChange={this.handleChange}
/>
<FormControl.Feedback />
</FormGroup>
</form>
);
}
}
ReactDOM.render(
<Example />,
document.getElementById('app')
);
https://codepen.io/ene_salinas/pen/zmMyOb?editors=0010
Happy coding!

Related

Is it possible convert text to regex?

As example i have this text
1.2345
12.345
So my input form must following the format above. Is it possible to populate regex dynamically. as example we will use format number 1
User input 12.345 so it will return false, but when user input 5.5555 it will return true, but when user input 1.23 it will return true and the number will become 1.2300
In javascript, i'm doing this
var inputVal = $(this).val();
if (inputVal == "") return;
if (inputVal.indexOf('.') !== -1) {
var inputValSplitdot = inputVal.split(".");
var inputFormatSplitDot = inputFormat.split(".");
if (inputValSplitdot[1].length < inputFormatSplitDot[1].length) {
var compareResult = inputFormatSplitDot[1].length - inputValSplitdot[1].length
var zeroItem = "0".repeat(compareResult);
$(this).val(inputVal + zeroItem);
}
} else {
$(this).val(inputVal + ".").change();
}
How can i achive in flutter/dart ? thanks in advance
This problem can be solved elegantly in Flutter.
First, use RegEx in InputFormatter to make sure users can only enter digits (0-9) and decimal points (.) but not any other characters
inputFormatters: [
// Make sure user can only enter numbers and decimal points
FilteringTextInputFormatter.allow(RegExp(r'[0-9\.]')),
],
Secondly, limit the total input length to 6, so users cannot enter more than that:
maxLength: 6
(Once this is done, Flutter automatically adds a counter, if you don't want the counter, it can be disabled easily by setting counterText: ''.)
Lastly, monitor the input with a TextEditingController, and check if the value entered is valid and within range:
bool isValid(String input) {
if (input.isEmpty) return true; // initial empty string is okay
final number = double.tryParse(input); // try to parse the string
if (number == null) return false; // parse failed: invalid format
if (number >= 100) return false; // range failed: larger than 99.999
return true;
}
Full source code:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("TextField Demo")),
body: Center(
child: SizedBox(
width: 200,
child: VerifiedTextField(),
),
),
);
}
}
class VerifiedTextField extends StatefulWidget {
#override
_VerifiedTextFieldState createState() => _VerifiedTextFieldState();
}
class _VerifiedTextFieldState extends State<VerifiedTextField> {
final _controller = TextEditingController();
bool _valid = true;
#override
void initState() {
_controller.addListener(() {
final valid = isValid(_controller.text);
setState(() => _valid = valid);
});
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return TextField(
controller: _controller,
inputFormatters: [
// Make sure user can only enter numbers and decimal points
FilteringTextInputFormatter.allow(RegExp(r'[0-9\.]')),
],
maxLength: 6,
decoration: InputDecoration(
errorText: _valid ? null : "Incorrect Format",
// counterText: '', // apply this code, if you don't want a counter
),
);
}
bool isValid(String input) {
if (input.isEmpty) return true; // initial empty string is okay
final number = double.tryParse(input); // try to parse the string
if (number == null) return false; // parse failed: invalid format
if (number >= 100) return false; // range failed: larger than 99.999
return true;
}
}
And of course, if you prefer to do it the way you had in JS, you can modify the isValid function accordingly.
If you are working with string then this might be helpful.
There are two ways to construct a regular expression in JavaScript .
Using a regular expression literal, which consists of a pattern enclosed between slashes, as follows.
const reg = /ab+/;
Calling the constructor function of the RegExp object, as follows.
const reg = new RegExp('ab+', flag);
You can try something like this:
First, check if the number provided accomplished the regex expression
bool isMatch(String value) {
var hasMatch = !RegExp("^\d\.\d+").hasMatch(value);
if (hasMatch && value.length < 6) newText(value);
return hasMatch;
}
Secondly, modify the number length if necessary
void newText(String value) {
for (var i = value.length; i < 6; i++) {
value += '0';
}
}
This is how I do it in javascript
// returns true if pattern matches text
function checkPattern(pattern, input) {
return (input.match(pattern)) ? true : false
}
// regex pattern
let pattern = /[0-9]{1}[.][0-9]{4}/g
let pattern2 = /[0-9]{2}[.][0-9]{3}/g
let input = ["1.2345", "12.345", "5.5555", "1.23"]
for (let i in input) {
console.log(`checking first pattern on input: ${input[i]} ${checkPattern(pattern, input[i])}`)
console.log(`checking second pattern on input: ${input[i]} ${checkPattern(pattern2, input[i])}`)
}
the output is
checking first pattern on input: 1.2345 true
checking second pattern on input: 1.2345 false
checking first pattern on input: 12.345 false
checking second pattern on input: 12.345 true
checking first pattern on input: 5.5555 true
checking second pattern on input: 5.5555 false
checking first pattern on input: 1.23 false
checking second pattern on input: 1.23 false

Angular 5 form custom validation is not working properly

I am working on Angular 5 and I have a form with a field username. I want to integrate a custom validation for minimum character length and avoid blank space.
<input type="text" class="form-control " id="account-details-username" placeholder="" formControlName="username" >
<div *ngIf="form.get('accountDetails.username').touched && form.get('accountDetails.username').invalid" class="alert alert-danger">
<div *ngIf="form.get('accountDetails.username').errors.required">Username is required.</div>
<div *ngIf="form.get('accountDetails.username').errors.minimumSix">Username must contain at least 6 characters</div>
<div *ngIf="form.get('accountDetails.username').errors.blankSpace">Username does not contain blank space.</div>
</div>
I tried to create a custom method for that. But invoking the first condition only.
test(control: any) {
console.log(control.value);
let minimumSix = new RegExp("^[a-zA-Z0-9!##$%^&*]{6,}");
if (!minimumSix.test(control.value)) {
return { 'minimumSix': true };
}
if(control.value.match("^\\s+$")) {
console.log("blank");
return { 'blankSpace': true };
}
return null;
}
Not checking the blank space validation.
I'd suggest the following solution, when it comes to blanks.
const blankSpace = /^\S*$/;
if (!blankSpace.test(control.value)) {
console.log("blank");
return { 'blankSpace': true };
}
So your full method should look like this:
test(control: any) {
const minimumSix = new RegExp("^[a-zA-Z0-9!##$%^&*]{6,}");
const blankSpace = /^\S*$/;
if (!minimumSix.test(control.value)) {
return { 'minimumSix': true };
}
if (!blankSpace.test(control.value)) {
console.log("blank");
return { 'blankSpace': true };
}
return null;
}

Regex for different classname form input

This is the original code
$('.holder').on('keypress', 'alphabet', function (e) {
if (window.event) code = e.keyCode;
else code = e.which;
var myRegExp = new RegeExp(/[A-Z]/i);
if (myRegExp.test(String.fromCharCode(code))) {
return true;
} else return false;
});
however i want to make this code reusable as classname as parameter, like this one, but its not working :
$('.holder').on('keypress', classname, function (e) {
if (window.event) code = e.keyCode;
else code = e.which;
var pattern;
if (classname == "alphabet") pattern = /[A-Z]/i;
else if (classname == "number") pattern = /[0-9]/;
var myRegExp = new RegeExp(pattern);
if (myRegExp.test(String.fromCharCode(code))) {
return true;
} else return false;
});
see this FIDDLE
This should be your HTML. You should have a name attribute for an input element
<div class="holder">
alphabets only : <input type="text" name="name" class="alphabet" /><br />
numbers only : <input type="text" name="age" class="number" />
</div>
And this is the JavaScript. You need an event on input and not on holder and you don't need to pass classname as a parameter; rather check it with .attr('class')
$('input').on('keypress', function (e) {
if (window.event) code = e.keyCode;
else code = e.which;
var pattern;
if ($(this).attr('class') == "alphabet") pattern = /[A-Z]/i;
else if ($(this).attr('class') == "number") pattern = /[0-9]/;
var myRegExp = new RegExp(pattern);
if (myRegExp.test(String.fromCharCode(code))) {
return true;
} else return false;
});
Demo
on(...) does not define a function. It calls a function. You can't have an undefined variable there. Wrap the whole thing into a function.
Also, the second parameter to on(...) needs to be a selector, but "alphabet" would try to select a tag <alphabet>, which does not exist. The class selector is ".alphabet".
You also misspelled RegExp.
function applyKeypressValidation(selector, classname) {
$('.holder').on('keypress', selector, function (e) {
if (window.event) code = e.keyCode;
else code = e.which;
var pattern;
if (classname == "alphabet") pattern = /[A-Z]/i;
else if (classname == "number") pattern = /[0-9]/;
var myRegExp = new RegExp(pattern);
if (myRegExp.test(String.fromCharCode(code))) {
return true;
} else return false;
});
}
applyKeypressValidation('.alphabet', 'alphabet');
applyKeypressValidation('.number', 'number');

#each iteration number in Ember.js or {{#index}}

According to this question, it was possible to do something like this with Handlebars rc1:
{{#each links}}
<li>{{#index}} - {{url}}</li>
{{/each}}
{{#index}} would basically give you the iteration index, which is really useful when creating tables.
When I try this with Ember.js rc3, I get an unexpected token error. Does this not work anymore? Did it ever work? Is there another way to get the iteration index?
It looks like it was possible. Can't get it to work with HBS RC3. Probably, is deprecated.
Here's a "hand written" HBS helper.
This can help you gettin the index with {{index}} and side by side you can know if the iteration in on first or last object of the Array with {{first}} and {{last}} respectively.
Ember.Handlebars.registerHelper("foreach", function(path, options) {
var ctx;
var helperName = 'foreach';
if (arguments.length === 4) {
Ember.assert("If you pass more than one argument to the foreach helper, it must be in the form #foreach foo in bar", arguments[1] === "in");
var keywordName = arguments[0];
options = arguments[3];
path = arguments[2];
helperName += ' ' + keywordName + ' in ' + path;
if (path === '') {
path = "this";
}
options.hash.keyword = keywordName;
} else if (arguments.length === 1) {
options = path;
path = 'this';
} else {
helperName += ' ' + path;
}
options.hash.dataSourceBinding = path;
// Set up emptyView as a metamorph with no tag
//options.hash.emptyViewClass = Ember._MetamorphView;
// can't rely on this default behavior when use strict
ctx = this || window;
var len = options.contexts[0][path].length;
options.helperName = options.helperName || helperName;
options.contexts[0][path].map(function(item, index) {
item.index = index;
item.first = index === 0;
item.last = index === len - 1;
})
if (options.data.insideGroup && !options.hash.groupedRows && !options.hash.itemViewClass) {
new GroupedEach(ctx, path, options).render();
} else {
return Ember.Handlebars.helpers.collection.call(ctx, Ember.Handlebars.EachView, options);
}
});
and this can be tested like
{{#foreach array}}
{{log index first last}}
{{/foreach}}
i had the same problem recently i finish by writing a bound helper and passing them objects via Binding for example item here is an ember DS.Store object and content is a 'content' of the controller. hope it
Ember.Handlebars.registerBoundHelper 'isPair', (content, options)->
item = options.hash.item
content_name = options.hash.content || 'content'
if #get(content_name).indexOf(item) % 2 == 0 then 'is-pair' else 'is-unpair'
and in you view you call it
{{isPair content itemBinding='order'}}
i don't know if it is what you looking for but it might give you some ideas how to use it in your project.
btw. Ember overwrites #each helper that's why there it no #index i suppose

A CFML variable name cannot end with a "." character error

I get this error when posting a form. The strangest thing, though, is that this error only occurs in Chrome and Safari. FF, IE and Opera all post the form without a problem.
The Stack Trace does not point to a file to where this error occurs. A cfdump of cfcatch gives me some insight as to what the problem is, but I can't find any instance of where the problem actually exists. Here's the partial dump:
Column 1
Detail The variable attributes. ends with a "." character. You must supply an additional structure key or delete the "." character.
KnownColumn -1
KnownLine -1
KnownText "unknown"
Line 1
Message A CFML variable name cannot end with a "." character.
Here's the code handling the posted data. Everything is wrapped inside cftransaction and there's a loop, not sure why it's not being displayed. (thanks Peter Boughton for clearing that up)
<!--- Delete out the old category ties --->
<cfquery name="deleteCategory" datasource="#request.dsnWrite#">
DELETE FROM
ProductListings_categories
WHERE
listingID = <cfqueryparam value="#attributes.listingID#">
</cfquery>
<!--- Loop through the list --->
<cfloop list="#attributes.taginput#" index="idx" delimiters=".">
<!--- check to see if tag exists --->
<cfquery name="checkTag" datasource="#request.dsnWrite#">
SELECT
categoryID
FROM
categories
WHERE
CategoryName = <cfqueryparam value="#idx#" cfsqltype="cf_sql_varchar">
</cfquery>
<!--- If it does not then add the tag --->
<cfif not(checkTag.recordCount)>
<cfquery name="insertTag" datasource="#request.dsnWrite#">
INSERT into Categories
(
categoryname,
dateCreated
)
VALUES
(
<cfqueryparam value="#idx#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#now()#" cfsqltype="cf_sql_timestamp">
)
</cfquery>
<cfquery name="insertTag" datasource="#request.dsnWrite#">
SELECT
LAST_INSERT_ID() as newID
FROM
Categories
</cfquery>
<cfset variables.categoryID = insertTag.newID>
<cfelse>
<cfset variables.categoryID = checkTag.categoryID>
</cfif>
<cftry>
<!--- Tie the tag to the listing --->
<cfquery name="insertCategory" datasource="#request.dsnWrite#">
INSERT into ProductListings_categories
(
listingID,
CategoryID
)
VALUES
(
<cfqueryparam value="#attributes.listingID#" cfsqltype="cf_sql_bigint">,
<cfqueryparam value="#variables.categoryID#" cfsqltype="cf_sql_bigint">
)
</cfquery>
<cfcatch></cfcatch>
</cftry>
</cfloop>
<cflocation url="/sell/add_listing/step/3/listingID/#attributes.listingID#" addtoken="false">
Any insight would be great. Thanks!
Here's the form and the Javascript. I haven't had a chance to rewrite the code by the previous developer (up until this point, it was working, so there was no need to visit the code in the first place), but CFFORM isn't used, nor are other CF form items. Various JS functions are used for AJAX calls and are included as well.
<form action="/sell/add_listing/step/2/listingID/#attributes.listingId#" method="post">
<div id="formFields"><input name="tagInput" id="tagInput" value="#variables.tagInput#" type="hidden"/></div>
<h3>Step 2: <span id="instructions">First, choose a top-level category</span></h3>
<p id="instructions2">This category will show up as the first tag on your listing.</p>
<div id="tagLand">
<div>
1. <select onchange="mainCategorySelector(this.value)">
<cfloop query="getTopCats">
<option value="#getTopCats.categoryName#" <cfif ListFirst(variables.tagInput,".") EQ getTopCats.categoryName>selected="selected"</cfif>>#capFirstTitle(ReplaceNoCase(getTopCats.categoryName, "_"," ", "all"))#</option>
</cfloop>
</select>
</div>
<div id="inputDiv" style="visibility: hidden;">
<div>Add a tag</div>
<div>2.
<input type="text" onkeypress="return disableEnterKey(event)" name="newTag" id="newTag" maxlength="18"/>
<input type="button" value="add" onclick="addTag(document.getElementById('newTag').value)" class="small_button" />
</div>
<div class="error"></div>
</div>
</div>
<img src="/resources/img/layoutV3/button_prev.gif" alt="prev"/>
<input type="image" name="btnSubmit" src="/resources/img/layoutV3/button_next.gif" />
</form>
<script src="/resources/js/listing_2.js" type="text/javascript"></script>
//some variables
var listCount=1;
var tagLimit=14;
var maxSuggestions=100;
var allTags=new Array();
var allTags=new Array();
var allTagPointers=new Array();
var currentTags=0;
// XML document
var xmlDoc;
var req;
//this function will run anything upon page load
function addLoadEvent(func)
{
var oldonload = window.onload;
if (typeof window.onload != 'function')
{
if(func)window.onload = func;
}
else
{
window.onload = function()
{
oldonload();
func();
}
}
}
//let's rebuild the page!
addLoadEvent(rebuildTags());
function rebuildTags()
{
//grab the tag tree left for us by PHP
var passedTags=document.getElementById('tagInput').value;
//only run if we got a value
if(passedTags.replace(/^\s+|\s+$/g, ""))
{
//split the string into an array
passedTags=passedTags.split(".");
//run functions to rebuild the world
mainCategorySelector(passedTags[0]);
for(var i=1;i<passedTags.length;i++)
{
addTag(passedTags[i]);
}
}
}
function addTag(tagName)
{
tagName=trim(tagName);
tagName=tagName.toLowerCase();
if(tagName)
{
//remove underscores from tags, replace with spaces so we can validate
tagName=tagName.replace(/_/g," ");
//clear out error message if it's there
var errorDiv=document.getElementById('errorDiv');
errorDiv.innerHTML="";
//only run if we're not at the limit and tag has not been used already
if(currentTags<=tagLimit && !getArrayIndex(allTags,tagName))
{
//if not alphanumeric, error
var myRegxp = /^[0-9a-zA-Z\s]*$/;
if(myRegxp.test(tagName)==false)
{
var errorDiv=document.getElementById('errorDiv');
errorDiv.innerHTML="You may only use letters and numbers in your tags.";
}
//if it error checks fine, move on
else
{
//let's replace all spaces with underscores for DB storage
//tagName=tagName.replace(/ /g,"_");
//query server and get list of related tags
//random number to kill the cache
var cacheKiller=Math.random();
//get all children tags
xmlDoc=ajaxRequest("/sell/get_categories_xml/tag/"+tagName.replace(/ /g,"_")+"/random/"+cacheKiller);
relatedTags=new Array;
var root=xmlDoc.getElementsByTagName('root')[0];
var tags=root.getElementsByTagName('tag');
//now get all sibling tags
xmlDoc=ajaxRequest("/sell/get_categories_siblings_xml/tag/"+tagName.replace(/ /g,"_")+"/random/"+cacheKiller);
root=xmlDoc.getElementsByTagName('root')[0];
var siblingTags=root.getElementsByTagName('tag');
//first compile child tags into an array
for(var i=0;(i<tags.length && i<maxSuggestions);i++)
{
relatedTags[i]=tags[i].firstChild.nodeValue;
}
//now add sibling tags to the same array
tags=root.getElementsByTagName('tag');
for(i;(i<tags.length && i<maxSuggestions);i++)
{
relatedTags[i]=tags[i].firstChild.nodeValue;
}
var tagLand=document.getElementById('tagLand');
var newNumberDiv=document.createElement('div');
var newDiv=document.createElement('div');
//add to counter and master tag array
listCount++;
allTags[allTags.length]=tagName.replace(/ /g,"_");
allTagPointers[allTagPointers.length]=listCount;
updateForm();
newNumberDiv.setAttribute('id','number_'+listCount);
newNumberDiv.className='listing_number';
newNumberDiv.innerHTML=listCount+".";
newDiv.innerHTML=tagName+' <span onclick="removeTag(\''+listCount+'\');" class="list_dynamic_link">x</span>';
newDiv.className='list_tag';
var newReccomendDiv=makeRelatedDiv(relatedTags);
//let's give IDs to all of the new divs so we can't kill 'em later
newDiv.setAttribute('id','tagDiv'+listCount);
newReccomendDiv.setAttribute('id','reccomendDiv'+listCount);
//add new divs to the master list
tagLand.appendChild(newNumberDiv);
tagLand.appendChild(newDiv);
tagLand.appendChild(newReccomendDiv);
//remove and re-append the input div to keep it at the end
var inputDiv=document.getElementById('inputDiv');
tagLand.removeChild(inputDiv);
tagLand.appendChild(inputDiv);
//make the inputDiv visible if it is not already
inputDiv.style.visibility='visible';
//run the reorderizer
reorderizer();
//clear input field
document.getElementById('newTag').value="";
document.getElementById('newTag').focus();
}
}
}
}
//removes a tag from the list -- called through the "x" link on each tag
function removeTag(tagNumber)
{
//get master div
var tagLand=document.getElementById('tagLand');
//get reference to all three divs that make up a tag listing
var deathRowNumberDiv=document.getElementById('number_'+tagNumber);
var deathRowTagDiv=document.getElementById('tagDiv'+tagNumber);
var deathRowReccomendDiv=document.getElementById('reccomendDiv'+tagNumber);
//any last words, boys?
tagLand.removeChild(deathRowNumberDiv);
tagLand.removeChild(deathRowTagDiv);
tagLand.removeChild(deathRowReccomendDiv);
//find where we are in the master array
var tagIndex=getArrayIndex(allTagPointers,tagNumber);
//splice this tag out of master tag array
allTags.splice(tagIndex,1);
allTagPointers.splice(tagIndex,1);
updateForm();
//alert(allTags.join("."));
//since we just changed the page structure, let's run reorderizer
//run the reorderizer
reorderizer();
//make the inputDiv visible if we're below the tag limit
var inputDiv=document.getElementById('inputDiv');
if(currentTags<=tagLimit)
{
inputDiv.style.visibility='visible';
}
}
//this function displays the formatted div for related tags
function makeRelatedDiv(relatedTags)
{
//let's prepare the recommended tags div
var newReccomendDiv=document.createElement('div');
newReccomendDiv.className='list_suggested_tags';
newReccomendDiv.innerHTML='<span>Add related tags: </span> ';
var numTags=0;
//loop through suggested tag array
for ( keyVar in relatedTags )
{
//add comma if necessary
if(numTags)
{
newReccomendDiv.innerHTML+=", ";
}
newReccomendDiv.innerHTML+='<span onclick="addTag(\''+relatedTags[keyVar]+'\');" class="list_dynamic_link">'+relatedTags[keyVar]+'</span>';
numTags++;
}
return newReccomendDiv;
}
function mainCategorySelector(tag)
{
//only run if we're not the dead selection
if(tag!="- - -")
{
//query server and get list of related tags
//random number to kill the cache
var cacheKiller=Math.random();
xmlDoc=ajaxRequest("/sell/get_categories_xml/tag/"+tag+"/random/"+cacheKiller);
relatedTags=new Array;
var root=xmlDoc.getElementsByTagName('root')[0];
var tags=root.getElementsByTagName('tag');
for(var i=0;(i<tags.length && i<maxSuggestions);i++)
{
relatedTags[i]=tags[i].firstChild.nodeValue;
}
var tagLand=document.getElementById('tagLand');
var newReccomendDiv=makeRelatedDiv(relatedTags);
//replace old reccomend list if it exists
if(document.getElementById('mainCategoryReccomendations'))
{
var mainCategoryReccomendations=document.getElementById('mainCategoryReccomendations');
tagLand.appendChild(newReccomendDiv);
tagLand.insertBefore(newReccomendDiv , mainCategoryReccomendations);
tagLand.removeChild(mainCategoryReccomendations);
}
else
{
tagLand.appendChild(newReccomendDiv);
//add to counter if we added a new tag
listCount++;
}
newReccomendDiv.setAttribute('id' , 'mainCategoryReccomendations');
//alert(allTags.join("."));
//add master tag array
allTags[0]=tag;
allTagPointers[0]=1;
updateForm()
//alert(allTags.join("."));
//remove and re-append the input div to keep it at the end
var inputDiv=document.getElementById('inputDiv');
tagLand.removeChild(inputDiv);
tagLand.appendChild(inputDiv);
//make the inputDiv visible if we're below the tag limit
if(currentTags<=tagLimit)
{
inputDiv.style.visibility='visible';
//focus on the new field
document.getElementById('newTag').focus();
}
//change up the instructions
changeInstructions("Now, add other tags to sort your listing","You can either click the related tags or enter your own")
}
}
//this function changes the content of the instructional div
function changeInstructions(top, bottom)
{
var instructions=document.getElementById('instructions');
var instructions2=document.getElementById('instructions2');
instructions.innerHTML=top;
instructions2.innerHTML=bottom;
}
//this function reassigns all list numbers to their proper value
function reorderizer()
{
/*
Here we run through all number div IDs...
remember, the div ID number may not match the display number, due to
additions/removals. That's why we have a separate variable for displayNumber!
*/
var tagLand=document.getElementById('tagLand');
//another counting var, for the actual display number
var displayNumber=1;
for(var i=1; i <= listCount; i++)
{
if(document.getElementById('number_'+i))
{
var b=document.getElementById('number_'+i);
b.innerHTML=displayNumber+".";
//ony increment displayNumber if we've actually printed a number
displayNumber++;
}
}
//update global tag count to most current and accurate number
currentTags=displayNumber;
//have we hit the tag limit? If so, hidezorz input
if(displayNumber>tagLimit)
{
var inputDiv=document.getElementById('inputDiv');
inputDiv.style.visibility='hidden';
}
else
{
//after looping through dynamic list entries, let's change the submit field's number too
var number_last=document.getElementById('number_last');
if(number_last)
{
number_last.innerHTML=displayNumber+".";
}
}
}
function pausecomp(millis)
{
date = new Date();
var curDate = null;
do { var curDate = new Date(); }
while(curDate-date < millis);
}
function ajaxRequest(requestURL)
{
var req;
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
}
req.open("GET", requestURL, false);
req.send(null);
var xmlDocument = req.responseXML;
return(xmlDocument);
}
function disableEnterKey(e)
{
var key;
if(window.event)
key = window.event.keyCode; //IE
else
key = e.which; //firefox
if(key == 13)
{
addTag(document.getElementById('newTag').value);
return false;
}
else
{
return true;
}
}
function getArrayIndex(arr, val)
{
for (i = 0; i < arr.length; i++)
{
if (arr[i] == val) { return i; }
}
}
function updateForm()
{
//this function updates the hidden field that will actually send the tag data upon form submission
document.getElementById('tagInput').value=allTags.join(".");
}
Problem solved: select list did not have the name attribute defined, and as a result, the attributes variable did have a null field name, causing the error. In my case, the select list is not used in CF, but only in JS. Chrome and Safari will pass a field's value even if the field lacks a name, while IE, FF and Opera do not. Thanks for guiding me in the right direction.
From your description it sounds like that the error is thrown by the form itself in the client, and not the handling code that you've posted above. If you have a cfform/cfgrid on the calling page, you may want to look at the Javascript that's generated by CF and test it against Chrome/Safari.