Pevent CSS content property to be removed - javascript

I have a form where I check the password strength of a user. It works correctly and shows the text according to the validation. But when a user makes a mistake and uses backspace to re-enter his password, the text from data-text isn't show anymore because the content property from the CSS is being removed (I guess because of the backspace). I couldn't find a solution to prevent it from being removed.
// Password field
self.addEventListener("keyup", () => {
let val = self.value;
testPasswordStrength(val);
});
// check password strength
const testPasswordStrength = (value) => {
const strengthText = document.getElementsByClassName('js-password-strength')[0];
const strongRegex = new RegExp(
'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[=/\()%ยง!##$%^&*])(?=.{8,})'
),
mediumRegex = new RegExp(
'^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})'
);
if (value) {
if (strongRegex.test(value)) {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textStrong);
return "strong";
} else if (mediumRegex.test(value)) {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textGood);
return "medium";
} else {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textDefault);
return "weak";
}
} else {
strengthText.classList.add("d-none");
}
};
content: attr(data-validation-text);
<div class="js-password-strength" data-validation-text data-text-default="Password must be 8+ characters" data-text-good="Good password" data-text-strong="Great password">
</div>

Is this work for you
// Password field
const passwordField = document.getElementsByClassName('js-password-strength')[0];
passwordField.addEventListener("keyup", () => {
let val = passwordField.textContent;
testPasswordStrength(val);
});
// check password strength
const testPasswordStrength = (value) => {
;
const strongRegex = new RegExp(
'^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[=/\()%ยง!##$%^&*])(?=.{8,})'
),
mediumRegex = new RegExp(
'^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})'
);
if (value) {
if (strongRegex.test(value)) {
passwordField.setAttribute('data-validation-text', passwordField.dataset.textStrong);
return "strong";
} else if (mediumRegex.test(value)) {
passwordField.setAttribute('data-validation-text', passwordField.dataset.textGood);
return "medium";
} else {
passwordField.setAttribute('data-validation-text', passwordField.dataset.textDefault);
return "weak";
}
} else {
passwordField.classList.add("d-none");
}
};
.js-password-strength{
border:1px solid #000;
}
.js-password-strength:after{
content: attr(data-validation-text);
font-size:12px;
color:#666;
}
<html>
<head>
</head>
<body>
<div class="js-password-strength"
data-validation-text
data-text-default="Password must be 8+ characters"
data-text-good="Good password"
data-text-strong="Great password" contenteditable=true>
</div>
</body>
<html>

#AndrewL64 I found the issue strengthText.classList.add("d-none"); It makes it display none. So it removes the content property. So if the value is set. It should have display: block
if (value) {
strengthText.classList.remove("d-none");
strengthText.classList.add("d-block");
if (strongRegex.test(value)) {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textStrong);
return "strong";
} else if (mediumRegex.test(value)) {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textGood);
return "medium";
} else {
strengthText.setAttribute('data-validation-text', strengthText.dataset.textDefault);
return "weak";
}
} else {
strengthText.classList.remove("d-block");
strengthText.classList.add("d-none");
}

Related

Liveserach passing values ​from other object fields iterates

I put a snippet to make the idea better.
Type any character in the Find field, in the console you will see the log of the dataAdd object, if now we change the value of the select Department and type any character again, the log becomes double, with the value of Department previous and current one, and if you repeat this, each time you add the value in the log.
I need the passed value to send it on the server side to filter the search by department but this way it can't work.
Can you help me, I'm going crazy
const $ = id => document.getElementById(id);
let ajaxInProgress = false;
const ajaxGet = async (elab, q, dataAdd) => {
if (ajaxInProgress) return;
ajaxInProgress = true;
let url;
if (dataAdd != null) {
url = "/utility/cerca/getLiveSearch/" + elab + "/" + q + "/" + btoa(JSON.stringify(dataAdd));
} else {
url = "/utility/cerca/getLiveSearch/" + elab + "/" + q;
}
let response = await fetch(url),
data = await response.text();
if (response.ok) {
ajaxInProgress = false;
return data;
} else if (response.status === 404) {
ajaxInProgress = false;
return false;
} else {
ajaxInProgress = false;
return "Error: " + response.status;
}
};
const liveSearch = (id, elCont, elab, dataAdd) => {
const el = document.querySelector("input" + id);
// If I can't find the execution block element
if (!el) return !1;
el.classList.add("liveSearch");
el.parentElement.classList.add("position-relative");
el.setAttribute("autocomplete", "off");
// If the item doesn't already exist, I create it
if (!$(elCont)) {
// Appendo elemento al campo input
let lsContainer = document.createElement("div");
lsContainer.id = elCont;
lsContainer.classList.add("liveSearchContent", "shadow", "bg-white", "border", "border-2", "rounded-2", "position-absolute", "overflow-auto", "mt-1", "d-none");
el.after(lsContainer);
}
// To KeyUp
el.addEventListener("keyup", ls => {
// I get the typed value
let q = el.value,
innerResult = document.querySelector("#" + elCont);
if (q != "") {
// Log data send from input field
console.log(dataAdd);
ajaxGet(elab, q, dataAdd).then(html => {
// Resize liveSearch
resizeLiveSearch();
// I hang the results
innerResult.innerHTML = html + ' - ' + q;
// Hide/Show liveSearch
ls.target.value.length < 1 ? innerResult.classList.add("d-none") : innerResult.classList.remove("d-none");
});
} else {
// Hide/Show liveSearch
ls.target.value.length < 1 ? innerResult.classList.add("d-none") : innerResult.classList.remove("d-none");
}
});
el.addEventListener("focus", el => {
el.target.closest("div").querySelector(".liveSearchContent").classList.remove("d-none");
});
// When I resize the window, I resize the livesearch
window.onresize = resizeLiveSearch;
document.addEventListener("click", e => {
let box = document.querySelector(".liveSearchContent");
if (box) {
if (box.contains(e.target) || !e.target.classList.contains("liveSearch")) {
handleBlur();
} else {
return false;
}
}
});
};
let resizeLiveSearch = () => {
document.querySelectorAll(".liveSearch").forEach(e => {
e.closest("div").querySelector(".liveSearchContent").style.width = e.offsetWidth + "px";
});
};
let handleBlur = () => {
document.querySelectorAll(".liveSearchContent").forEach(el => {
el.classList.add("d-none");
});
};
// -- Piece of code that interacts with liveSearch
document.addEventListener("DOMContentLoaded", () => {
let idReparto = $("id_reparto"),
idEvento = $("id_evento"),
evento = $("evento"),
reparto = idReparto.value;
idReparto.addEventListener("change", el => {
console.clear();
idEvento.value = evento.value = "";
reparto = el.target.value;
liveSearch("#evento", "searchEventoRicerca", "evento_reparto", { reparto: reparto });
});
liveSearch("#evento", "searchEventoRicerca", "evento_reparto", { reparto: $("id_reparto").value });
$("searchEventoRicerca").addEventListener("click", el => {
let elt = el.target,
evento2 = "";
if (elt.matches(".srel")) {
evento2 = elt.getAttribute("id");
el.preventDefault();
elt.blur();
evento.value = elt.text;
idEvento.value = evento2;
pdvEvento.value = idPdv.value = "";
// Mostro pdv_evento e occulto pdv
pdvEvento.parentElement.classList.remove("d-none");
console.log(evento2);
}
});
});
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"/>
<form class="mb-5 mt-2 mx-2">
<div class="row g-3">
<input type="hidden" id="id_evento" name="id_evento" value="">
<div class="col-md-3">
<label for="id_reparto" class="form-label">Department</label>
<select class="form-select" id="id_reparto" name="id_reparto" title="id_reparto">
<option value="1">Dep 1</option>
<option value="3">Dep 3</option>
<option value="2" selected="selected">Dep 2</option>
</select>
</div>
<div class="col-md-6">
<label for="evento" class="form-label">Find</label>
<input type="text" class="form-control liveSearch" placeholder="Type any character" id="evento" name="evento" value="" autocomplete="off">
<div id="searchEventoRicerca" class="liveSearchContent shadow bg-white border border-2 rounded-2 position-absolute overflow-auto mt-1 d-none"></div>
</div>
</div>
</form>

How can I use this in a loop?

I'm doing this for a class assignment and I know there has to be a better way of writing it. Maybe some kind of loop that gets the inputs and labels? I'm repeating a lot here and it seems better to minify this if possible.
function checkEmptyFields() {
if(formName.value === "") {
formLabels[0].classList.add("has-errors");
formLabels[0].innerHTML = "Name is required *";
formName.style.borderBottomColor = "red";
} else {
formLabels[0].classList.remove("has-errors");
formLabels[0].innerHTML = "Name";
formName.style.borderBottomColor = "green";
}
if(formEmail.value === "") {
formLabels[1].classList.add("has-errors");
formLabels[1].innerHTML = "Email is required *";
formEmail.style.borderBottomColor = "red";
} else {
formLabels[1].classList.remove("has-errors");
formLabels[1].innerHTML = "Email";
formEmail.style.borderBottomColor = "green";
}
if(formNumber.value === "") {
formLabels[2].classList.add("has-errors");
formLabels[2].innerHTML = "Phone is required *";
formNumber.style.borderBottomColor = "red";
} else {
formLabels[2].classList.remove("has-errors");
formLabels[2].innerHTML = "Phone";
formNumber.style.borderBottomColor = "green";
}
if(formMessage.value === "") {
formLabels[3].classList.add("has-errors");
formLabels[3].innerHTML = "message is required *";
formMessage.style.borderBottomColor = "red";
} else {
formLabels[3].classList.remove("has-errors");
formLabels[3].innerHTML = "Email";
formMessage.style.borderBottomColor = "green";
}
}
You can try like this:
fields = [{
'name': formName,
'index': 0,
'css-error': "has-errors",
'innerHtml': "Name",
'innerHtml-error': "Name is required *",
'borderBottomColor ': "green", //Or you can hardcode it in the loop itself.
'borderBottomColor-error': "red"
},
....
]
for(var i=0; i < fields.length; i++) {
var field = fields[i];
if(field.name.value == "") {
formLabels[field.index].classList.add(field.css);
formLabels[field.index].innerHTML = field.innerHtml-error;
field.name.style.borderBottomColor = field.borderBottomColor-error ;
} else {
formLabels[field.index].classList.remove(field.css);
formLabels[field.index].innerHTML = field.innerHtml;
field.name.style.borderBottomColor = field.borderBottomColor ;
}
}
You can create arrays for both the controls and the control names, and process them together with the formLabels array that you already have, in a for-loop that goes from 0 to length (not inclusive), like this:
function checkEmptyFields() {
var controls = [formName, formEmail, formNumber, formMessage];
var controlNames = ["Name", "Email", "Phone", "Message"];
for (var i = 0; i < controls.length; i++) {
if(controls[i].value === "") {
formLabels[i].classList.add("has-errors");
formLabels[i].innerHTML = controlNames[i] + " is required *";
controls[i].style.borderBottomColor = "red";
} else {
formLabels[i].classList.remove("has-errors");
formLabels[i].innerHTML = controlNames[i];
controls[i].style.borderBottomColor = "green";
}
}
}
You can write an additional function to check one field:
function checkEmptyField(field, ind, msg, errmsg) {
if(field.value === "") {
formLabels[ind].classList.add("has-errors");
formLabels[ind].innerHTML = errmsg;
field.style.borderBottomColor = "red";
} else {
formLabels[ind].classList.remove("has-errors");
formLabels[ind].innerHTML = msg;
field.style.borderBottomColor = "green";
}
}
Then you can call it
function checkEmptyFields() {
checkEmptyField(formName,0,"Name","Name is required *");
...
If you know about and understand for loops you can simply loop over 2 arrays of data like this:
function checkEmptyFields() {
formArray = [formName, formEmail, formNumber, formMessage];
labelArray = ["Name", "Email", "Phone", "Message"];
for (let i = 0; i < formArray.length; i++) {
if(formArray[i].value === "") {
formLabels[i].classList.add("has-errors");
formLabels[i].innerHTML = labelArray[i] + " is required *";
formArray[i].style.borderBottomColor = "red";
} else {
formLabels[i].classList.remove("has-errors");
formLabels[i].innerHTML = labelArray[i];
formArray[i].style.borderBottomColor = "green";
}
}
}
if not then you can read about them here:
https://www.w3schools.com/js/js_loop_for.asp
Anytime you have roughly the same code in more than one place, you should stop and rethink your approach as you are doing here.
If you give each of the HTML elements that need to be validated a common class, you can then create a node list (collection/array) that contains them. Then you can loop over that collection and perform the same test (written only once) on each item and act accordingly.
Also, I'm not quite sure what you are doing with .innerHTML, but don't use that when the text you are working with doesn't have any HTML in it. .innerHTML has security and performance implications. Instead, use .textContent when there is no HTML.
// Get all the form fields that need validation into an Array
let fields = Array.prototype.slice.call(document.querySelectorAll(".validationNeeded"));
// Set up form submit event handler
document.querySelector("form").addEventListener("submit", checkEmptyFields);
function checkEmptyFields(event) {
let validCount = fields.length; // Holds the number of valid fields
// Loop over the array
fields.forEach(function(field){
if(field.value === ""){
field.previousElementSibling.classList.add("has-errors-label"); // style the label
field.classList.add("has-errors-field"); // style the field
field.classList.remove("valid-field"); // style the field
validCount--; // Decrease the count of valid fields
} else {
field.previousElementSibling.classList.remove("has-errors-label"); // style the label
field.classList.remove("has-errors-field"); // style the field
field.classList.add("valid-field"); // style the field
}
});
// Check to see if the form should be submitted
if(validCount !== fields.length){
event.preventDefault(); // Cancel the form's submission
}
}
.row {margin-bottom:5px; }
.has-errors-label { color:red; }
.has-errors-field { outline:1px solid red; }
.valid-field { outline:1px solid green; }
<form action="#" method="get">
<div class="row">
<label for="userName">Name: </label>
<input class="validationNeeded" name="userName" id="userName">
</div>
<div class="row">
<label for="email">Email: </label>
<input class="validationNeeded" name="email" id="email">
</div>
<div class="row">
<label for="phone">Phone: </label>
<input class="validationNeeded" name="phone" id="phone">
</div>
<button>Submit</button>
</form>

Validation with jquery and datalist

I have an similar problem like this post: Validation with datalist
However the answer of FelDev is in JavaScript I need it in jquery .
I am new to jquery therefore it would be of great help if some can help.
In the following the answer of FelDev:
let btn = document.getElementById("btnSend");
let form = document.getElementById("zeForm");
let input = document.getElementById("zeInput");
let msg = document.getElementById("msg");
let allowedValues = ["atown", "btown", "ctown"]; // same values as the options in your datalist
btn.onclick = function() {
let allGood = false;
allowedValues.forEach(function(elm) {
if(elm === input.value) {
allGood = true;
return;
}
})
if(allGood) {
msg.innerHTML = "Success!!";
msg.style.color = "green";
//form.submit();
} else {
msg.innerHTML = "This value is not accepted";
msg.style.color = "red";
}
msg.style.display = "inline";
}
#msg {
display: none;
}
#btnSend {
display: block;
margin-top:1rem;
}
<form id="zeForm">
<input id="zeInput" type="text" list="typ" name="name" placeholder="gtown" >
<datalist id="typ">
<!-- notice the absence of a <select> here... -->
<option value="atown">atown</option>
<option value="btown">btown</option>
<option value="ctown">ctown</option>
</datalist>
</input>
<p id="msg"></p>
<button id="btnSend" type="button">send</button>
</form>
So do you need a translation?
So the jquery of this js is :
let btn = $("#btnSend");
let form = $("#zeForm");
let input = $("#zeInput");
let msg = $("#msg");
let allowedValues = ["atown", "btown", "ctown"]; // same values as the options in your datalist
btn.on('click' , function() {
let allGood = false;
allowedValues.each(function(index, element) {
if (element === input.value) {
allGood = true;
return;
}
})
if (allGood) {
msg.text("Success!!");
msg.attr('style',"color:green");
//form.submit();
} else {
msg.text("This value is not accepted";
msg.attr('style',"color:red");
}
msg.attr('style',"display:inline");
});

Preventing HTML and Script injections in Javascript

Assume I have a page with an input box. The user types something into the input box and hits a button. The button triggers a function that picks up the value typed into the text box and outputs it onto the page beneath the text box for whatever reason.
Now this has been disturbingly difficult to find a definitive answer on or I wouldn't be asking but how would you go about outputting this string:
<script>alert("hello")</script> <h1> Hello World </h1>
So that neither the script is executed nor the HTML element is displayed?
What I'm really asking here is if there is a standard method of avoiding both HTML and Script injection in Javascript. Everyone seems to have a different way of doing it (I'm using jQuery so I know I can simply output the string to the text element rather than the html element for instance, that's not the point though).
You can encode the < and > to their HTML equivelant.
html = html.replace(/</g, "<").replace(/>/g, ">");
How to display HTML tags as plain text
myDiv.textContent = arbitraryHtmlString
as #Dan pointed out, do not use innerHTML, even in nodes you don't append to the document because deffered callbacks and scripts are always executed. You can check this https://gomakethings.com/preventing-cross-site-scripting-attacks-when-using-innerhtml-in-vanilla-javascript/ for more info.
A one-liner:
var encodedMsg = $('<div />').text(message).html();
See it work:
https://jsfiddle.net/TimothyKanski/wnt8o12j/
I use this function htmlentities($string):
$msg = "<script>alert("hello")</script> <h1> Hello World </h1>"
$msg = htmlentities($msg);
echo $msg;
From here
var string="<script>...</script>";
string=encodeURIComponent(string); // %3Cscript%3E...%3C/script%3
My solution using typescript + decorators + regex
const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
function filter(target) {
return class extends target {
constructor(...args) {
super(...args);
}
setState(opts) {
const state = {
username: this.filter(opts.username),
password: this.filter(opts.password),
};
super.setState(state);
}
filter(value) {
const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");
}
};
}
let Form = class Form {
constructor() {
this.state = {
username: "",
password: "",
};
}
setState(opts) {
this.state = {
...this.state,
...opts,
};
}
getState() {
return this.state;
}
};
Form = __decorate([
filter,
__metadata("design:paramtypes", [])
], Form);
function getElement(key) {
return document.getElementById(key);
}
const button = getElement("btn");
const username = getElement("username");
const password = getElement("password");
const usernameOutput = getElement("username-output");
const passwordOutput = getElement("password-output");
function handleClick() {
const form = new Form();
form.setState({ username: username.value, password: password.value });
usernameOutput.innerHTML = `Username: ${form.getState().username}`;
passwordOutput.innerHTML = `Password: ${form.getState().password}`;
}
button.onclick = handleClick;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
:root {
--bg: #1d1907;
--foreground: #e3e0cd;
--primary: #cfb53b;
--black: #333;
--white: #fafafa;
}
#keyframes borderColor {
from {
border-bottom: 1px solid var(--foreground);
}
to {
border-bottom: 1px solid var(--primary);
}
}
* {
outline: none;
border: none;
}
body {
padding: 0.5rem;
font-family: "Fira Code";
background-color: var(--bg);
color: var(--foreground);
}
input {
border-bottom: 1px solid var(--foreground);
background-color: var(--black);
color: var(--foreground);
padding: 0.5rem;
}
input:focus {
animation-name: borderColor;
animation-duration: 3s;
animation-fill-mode: forwards;
}
button {
padding: 0.5rem;
border-radius: 3px;
border: 1px solid var(--primary);
background-color: var(--primary);
color: var(--white);
}
button:hover,
button:active {
background-color: var(--white);
color: var(--primary);
}
.form {
margin-bottom: 2rem;
}
</style>
<title>Decorator</title>
</head>
<body>
<h1>Prevent Injection</h1>
<div class="form">
<div class="form-group">
<label for="username">Username</label>
<input type="text" id="username" placeholder="Type your username" />
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" id="password" placeholder="Type your password" />
</div>
<div class="form-group">
<button id="btn">Enviar</button>
</div>
</div>
<div class="form-result">
<p id="username-output">Username:</p>
<p id="password-output">Password:</p>
</div>
<script src="/dist/pratica1.js"></script>
</body>
</html>
Typescript Code bellow:
type State = {
username: string;
password: string;
};
function filter<T extends new (...args: any[]) => any>(target: T): T {
return class extends target {
constructor(...args: any[]) {
super(...args);
}
setState(opts: State) {
const state = {
username: this.filter(opts.username),
password: this.filter(opts.password),
};
super.setState(state);
}
filter(value: string) {
const removeTag = new RegExp("(<[a-zA-Z0-9]+>)|(</[a-zA-Z0-9]+>)", "g");
return value.replace(removeTag, "");
}
};
}
#filter
class Form {
private state: State;
constructor() {
this.state = {
username: "",
password: "",
};
}
setState(opts: State) {
this.state = {
...this.state,
...opts,
};
}
getState() {
return this.state;
}
}
function getElement(key: string): HTMLElement | null {
return document.getElementById(key);
}
const button = getElement("btn") as HTMLButtonElement;
const username = getElement("username") as HTMLInputElement;
const password = getElement("password") as HTMLInputElement;
const usernameOutput = getElement("username-output") as HTMLParagraphElement;
const passwordOutput = getElement("password-output") as HTMLParagraphElement;
function handleClick() {
const form = new Form();
form.setState({ username: username.value, password: password.value });
usernameOutput.innerHTML = `Username: ${form.getState().username}`;
passwordOutput.innerHTML = `Password: ${form.getState().password}`;
}
button.onclick = handleClick;
Try this method to convert a 'string that could potentially contain html code' to 'text format':
$msg = "<div></div>";
$safe_msg = htmlspecialchars($msg, ENT_QUOTES);
echo $safe_msg;
Hope this helps!
Use this,
function restrict(elem){
var tf = _(elem);
var rx = new RegExp;
if(elem == "email"){
rx = /[ '"]/gi;
}else if(elem == "search" || elem == "comment"){
rx = /[^a-z 0-9.,?]/gi;
}else{
rx = /[^a-z0-9]/gi;
}
tf.value = tf.value.replace(rx , "" );
}
On the backend, for java , Try using StringUtils class or a custom script.
public static String HTMLEncode(String aTagFragment) {
final StringBuffer result = new StringBuffer();
final StringCharacterIterator iterator = new
StringCharacterIterator(aTagFragment);
char character = iterator.current();
while (character != StringCharacterIterator.DONE )
{
if (character == '<')
result.append("<");
else if (character == '>')
result.append(">");
else if (character == '\"')
result.append(""");
else if (character == '\'')
result.append("'");
else if (character == '\\')
result.append("\");
else if (character == '&')
result.append("&");
else {
//the char is not a special one
//add it to the result as is
result.append(character);
}
character = iterator.next();
}
return result.toString();
}

Javascript function not being called from onclick

This has me pulling my hair out. Button on site has onclick=method() and it's not calling the method. The method is supposed to grab all the checkboxes, check their checked state and fill the chk[] array with true/false. The WebMethod then takes that array, breaks it down into three smaller arrays and runs checks on the combinations. So far as I can tell, the button never calls the method to begin with.
aspx page:
<fieldset id="Fieldset">
<button onclick="SendForm();">Send</button>
<button onclick="CancelForm();">Cancel</button>
</fieldset>
</form>
<asp:ScriptManager ID="ScriptManager1" EnablePageMethods="true" EnablePartialRendering="true" runat="server" />
<script type="text/javascript">
function SendForm() {
var email = $get("txtEmail").value;
var elLength = form1.elements.length;
var chk = new [42];
for (i = 0; i < elLength; i++) {
var count = 0;
var type = form1.elements[i].type;
if (type == "checkbox") {
if (form1.elements[i].checked) {
chk[count] = true;
}
else {
chk[count] = false;
}
count++;
}
else {
}
}
PageMethods.SendForm(email, chk, OnSucceeded, OnFailed);
}
</script>
codebehind method it's calling:
[WebMethod]
public static void SendForm(string email, bool[] chk)
{
bool[] desc = new bool[14];
bool[] loc = new bool[14];
bool[] other = new bool[14];
for (int i = 0; i < 14; i++)
{
int count = i * 3;
desc[i] = chk[count];
loc[i] = chk[count + 1];
other[i] = chk[count + 2];
}
if (string.IsNullOrEmpty(email))
{
throw new Exception("You must supply an email address.");
}
else
{
if (IsValidEmailAddress(email))
{
for (int i = 0; i < 14; i++)
{
if (desc[i])
{
if ((loc[i]) && (other[i]))
{
throw new Exception("Invalid, two parameters selected");
}
else if (loc[i])
{
// do stuff
}
else if (other[i])
{
// do stuff
}
else
{
throw new Exception("Invalid, every exemption must have at least one reason selected");
}
}
else
{
throw new Exception("No exemptions have been selected");
}
}
}
else
{
throw new Exception("You must supply a valid email address.");
}
}
}
EDIT!!:
Running the page with the following script instead of the previous script works like a charm. No clue why the previous didn't work.
<script type="text/javascript">
function SendForm() {
var email = $get("txtEmail").value;
var elLength = form1.elements.length;
for (i=0;i< elLength;i++) {
var type = form1.elements[i].type;
if (type == "checkbox" && form1.elements[i].checked) {
alert("true!");
}
else {
alert("false!");
}
}
PageMethods.SendForm(email, chk, OnSucceeded, OnFailed);
}
</script>
Instead of calling your function like
<button onclick="SendForm();">Send</button>
try calling it like this
<button onclick="javascript:return SendForm();">Send</button>
Running the page with the following script instead of the previous script works like a charm. No clue why the previous didn't work.
<script type="text/javascript">
function SendForm() {
var email = $get("txtEmail").value;
var elLength = form1.elements.length;
for (i=0;i< elLength;i++) {
var type = form1.elements[i].type;
if (type == "checkbox" && form1.elements[i].checked) {
alert("true!");
}
else {
alert("false!");
}
}
PageMethods.SendForm(email, chk, OnSucceeded, OnFailed);
}
</script>

Categories