Hopefully you all don't get pissed at me for such a seemingly simple question..
Basically, I have a PDF form that I'm scripting with javascript.
I have a bunch of check boxes that I would like to set required and/or not required based on other inputs and I'm trying to repeat code as little as possible, especially since there's a ton of inputs.
Right now, the best way I can accomplish what I'm attempting is by setting a function for each instance of inputs as follows:
function setWalkwayNotRequired() {
this.getField("sidewalkAsphalt").required = false;
this.getField("sidewalkConcrete").required = false;
this.getField("sidewalkPavers").required = false;
this.getField("sidewalkCondition").required = false;
}
I would then call this function based on the input of a certain checkbox:
if (this.getField("sidewalkNone").value == "Yes") {
setSidewalkNotRequired();
}
Then all of the above-mentioned fields would be set to not required.
I feel like there should be a way to create a single "setRequired" or "setNotRequired" function to take a parameter of the field in question.
In my mind that would look something like this:
function setRequired(a, b, c, d) {
this.getField(a).required = true;
this.getField(b).required = true;
this.getField(c).required = true;
this.getField(d).required = true;
}
I would then call on that function for all instances, for example, walkways (like that above) or driveways, etc. like so:
if (this.getField("sidewalkNone").value == "Off") {
setRequired('"sidewalkAsphalt"', '"sidewalkConcrete"', '"sidewalkPavers"', '"sidewalkCondition"');
}
Again, in my mind what would then be output based on the above code once the function is called is something like:
if (this.getField("sidewalkNone").value == "Off") {
this.getField("sidewalkAsphalt").required = true;
this.getField("sidewalkConcrete").required = true;
this.getField("sidewalkPavers").required = true;
this.getField("sidewalkCondition").required = true;
}
Doing it the way I did in the first code block would require me to create separate functions for each set of checkboxes, creating a lot of code in an already huge file. The second way would allow me to use 1 function over and over throwing the field names as parameters depending on where I'm at in the PDF.
I'm also not very clear on if it's even legal to declare the parameters as I did with the '"..."' quotes; I did that because I need the double quotes inside the this.getField().
Again, I'm sorry if this is novice, I've just been trying to play with the code for a while now and can't get it to work.
Any input would be amazing.
You could just pass in an Array of field names:
function setRequired( fieldNames, isRequired = true ) {
for( var i = 0; i < fieldNames.length; i++ ) {
var fieldName = fieldNames[i];
this.getField( fieldName ).required = isRequired;
}
}
Usage:
if( this.getField("sidewalkNone").value == "Off" ) {
setRequired( [ "sidewalkAsphalt", "sidewalkConcrete", "sidewalkPavers", "sidewalkCondition" ] );
}
If you use hierarchical naming with dot notation, you can set properties on the parent to affect all children. For example, if you name the fields "sidewalk.Asphalt", "sidewalk.Concrete", and "sidewalk.Pavers"...
this.getField("sidewalk").required = true;
... will set all the children to be required.
Related
In a form (named createform) many inputs are created dynamically by clicking on add button (from 0 to any number for each kind of input).
The problem I'm having is the validation of the inputs that were created dynamically, because there is a complex logic behind it.
THE SCENARIO
I can have several different inputs:
brand
model
country
region
The first of them is called brand1, model1, country1 and region1, then adding others they will be called for instance brand2... brand50
In the starting scenario there will be only brand1 and model1. The country and region inputs are added only by clicking on a button.
THE VALIDATION CONDITION
I have to submit the form only in two cases:
If there is at least one brand + one model where both of them are not empty (any brand and any model, so it can also be brand5 and model12)
If there is at least one brand + country + region not empty (all of them not empty, same logic than before)
I made the following validation function which works good if I assume that I just have the first brand,model,country and region (so brand1,model1,country1 and region1).
THE CODE
function validateForm() {
var brand = document.forms["createform"]["brand1"].value;
var model = document.forms["createform"]["model1"].value;
if (document.forms["createform"]["country1"] === undefined) {
var country = "";
} else {
var country = document.forms["createform"]["country1"].value;
}
if (document.forms["createform"]["country1"] === undefined) {
var region = "";
} else {
var region = document.forms["createform"]["region1"].value;
}
if ((brand != "") && (model != "")) {
alert("Send");
return true;
} else if ((brand != "") && (country != "") && (region != "")) {
alert("Send");
return true;
} else {
alert("Impossible to send");
return false;
}
}
For better reading of the code I added return true even if it is not necessary.
The main problem is that it is impossible to know how many inputs there will be of every different kind. I was thinking about trying by checking if the inputs are starting with brand,model,country or region but I don't know how to cross my controls in my validation function with all the possible results.
Do you guys have any idea of how to solve this?
What you need is a way to access all your brand and model elements by the start of their name.
var elements = document.querySelectorAll("form[id='createform']>input[id^='brand']");
This will give you an array (instead of your single valued variable) which you can loop through looking for your values.
The nifty querySelectorAll accepts selectors which can narrow your search to all matching elements. In the example, it gets all input elements within a form named "createform" which start with (^=) "brand".
var brandelements = document.querySelectorAll("#createform select[name^='brand'] option:checked:not([value=''])");
This is the best way to get all the values of a select (you can easily change with a normal input) that are not empty.
I am trying to use a custom function developed in Google Script to validate a value in the spreadsheet.
However I get a response: There is a problem "Enter a value that satisfies the formula: =validateContent()"
The function itself has not been called at all.
Am I pushing Google Spreadsheet validation too far here with custom function?
I was expecting my function to return true or false, is that how it is suppose to work?
function validateContent() {
var val = SpreadsheetApp.getActiveSpreadsheet().getActiveCell().getValue();
if (val == value) return true;
return false;
}
First, to validate the current cell input it is useful to follow the pattern suggested by google:
=ISODD(C8)
In your case:
=validateContent(C8)
The validation generator is smart enough to translate the cell reference correctly to all other cells! I.e if this validation is applied to C8:C100 the validation of cell C42 will read =ISODD(C42).
Still, I have found that custom functions seem not to work in validation! See the following example:
In this screenshot the cell G2 uses a custom validation function (=ssvDataVerify(G2)), which evaluates to TRUE but is shown as invalid (red corner)! As a proof, the data value of cell I2 is =ssvDataVerify(G2). Now the validation if I2 is =I2, which now is shown as correctly validated!
I conclude that currently custom functions are not implemented to work with validation.
Currently, functions cannot be used in validations, but there is a workaround:
Use your custom function in some cell, let's say B2: =validateContent(A2).
Add a validation to cell A2 with the criteria Custom Formula is -> =B2.
I also believe that custom functions don't work for data validation.
I created a function to check a string value , against a list of RegExp and it didn't worked:
function vaidate(){
var range = SpreadsheetApp.getActive().getRange('A1');
var validation = SpreadsheetApp.newDataValidation().requireFormulaSatisfied('=checkValid(A1)').build();
range.setDataValidation(validation);
}
function checkValid(text){
var regexs = [/\|{2,}/g,/\.{2,}/g,];
var valid = true;
for(var i=0;i<regexs.length;i++){
if(testString(text,regexs[i])){
valid = false;
break;
}
}
return valid;
}
function testString(str, regex){
try{
var localRegex = regex;
return localRegex.test(str);
}catch(e) {
return false;
}
}
Here you go :)
The idea is to build the validation rule once the cell is edited
function onEdit(e){
const isValid = validateValue(e.value);
const rule = SpreadsheetApp
.newDataValidation("Yep")
// You can use any function but i believe you only need to use "EQ" with boolean
.requireFormulaSatisfied('=EQ("'+isValid+'","TRUE")')
// Your help message
.setHelpText('Please Enter "123" :P')
// Building the rule
.build();
e.range.setDataValidation(rule);
}
function validateValue(value){
// do what ever you want ;)
return value === "123";
}
I'm attempting to write a function which will scan a range of elements which contains "*-chars" as a class. Once I've found the elements I want to take that particular class (eg max-chars) and extract the part of the class before the -. I can't use a simple split as elements could contain other classes which contain a - or even -chars.
So far I've managed the following:
var getLimitType = function (el) {
var output = el.find('*[class*="-chars"]').filter(function () {
return this.className.match(/(?:^|\s)-chars/);
});
var limitType = output.val().split("-").shift();
var getVal = el.find('input').attr('maxlength');
return limitType+'_'+getVal;
};
Obviously this doesn't work as limitType is trying to perform a split on a jQuery object instead of a string, however I can't figure out what to put in the blank line, I need something which will take all the classes from that object, work out which one I am looking for and returning only that one as a text string.
Never quite found a desirable answer, however I managed to solve my issue with this work-around:
var getLimitType = function (element) {
var ml = element.find('input').attr('maxlength');
if (element.hasClass('exact-chars')) {
return 'exact_'+ml;
} else if (element.hasClass('min-chars')) {
return 'min_'+ml;
} else if (element.hasClass('max-chars')) {
return 'max_'+ml;
} else {
return 0;
}
};
I am building a recurring events module to drop into a form, this module has several fields.
I have named and ID'd each of this module using array notation. EG:
id='recurring_event_options[yearly][by_date_day_number]'
In my JS I need to target all fields with the matching id recurring_event_options
I have some JS working nicely that enables (non disabled) fields as needed, but before i run this i need to disable all the fields in this module.
I have been using somthing similar to this to disable the fields:
function disableForm(theform) {
if (document.all || document.getElementById) {
for (i = 0; i < theform.length; i++) {
var formElement = theform.elements[i];
if (true) {
formElement.disabled = true;
}
}
}
}
As you can see, that going to hit every field in the form - thats not what i want - only to disable the fields that belong to the recurring_event_options parent ID.
I have a feeling I probably cant use [] notation in IDs, so suggestions welcome!
First of all i think it is not a good idea to use [].
You can use a hyphen - or underscore _ to separate the values:
id='recurring_event_options-yearly-by_date_day_number'
Now you can disable:
function disableForm(theform) {
for (i = 0; i < theform.length; i++) {
var formElement = theform.elements[i];
if (formElement.id.indexOf("recurring_event_options") !== -1) {
formElement.disabled = true;
}
}
}
This should work. but in my opinion it will be much better if you use a class instead:
<input type="text" class="recurring_event_options prop2 prop3" />
because the class attribute is designed to support multiple values, separated by a space
This is probably easy for someone.
I am returning a list of campaignIDs (12,45,66) via JSON to a javascript variable
var campaignList = res.DATA.CAMPAIGNS
Now, given a specified campaignID passed in the URL
var campaignId ='<cfoutput>#url.campaignID#</cfoutput>'
I want to check if the returned list contains this campaignID
Any help much appreciated.
Plenty of ways to do it, but I like nice data structures, so ...
Split the list on comma, then loop over list, looking for value:
function campaignExists(campaignList,campaignId) {
aCampaignList = campaignList.split(',');
for (i=0;i<aCampaignList.length;i++) {
if (aCampaignList[i]==campaignId)
return true;
}
return false;
}
Since Array.indexOf sadly isn't cross browser, you're looking at something like:
// assume there is no match
var match_found = false;
// iterate over the campaign list looking for a match,
// set "match_found" to true if we find one
for (var i = 0; i < campaignList.length; i += 1) {
if (parseInt(campaignList[i]) === parseInt(campaignId)) {
match_found = true;
break;
}
}
If you need to do this repeatedly, wrap it in a function
Here's a bit of a "out of the box" solution. You could create a struct for your property id's that you pass into the json searilizer have the key and the value the same. Then you can test the struct for hasOwnProperty. For example:
var campaignIDs = {12 : 12, 45 : 45, 66 : 66};
campaignIDs.hasOwnProperty("12"); //true
campaignIDs.hasOwnProperty("32"); //false
This way if the list is pretty long you wont have to loop through all of the potential properties to find a match. Here's a fiddle to see it in action:
http://jsfiddle.net/bittersweetryan/NeLfk/
I don't like Billy's answer to this, variables within the function have been declared in the global scope and it is somewhat over complicated. If you have a list of ids as a string in your js just search for the id you have from user input.
var patt = new RegExp("(^|,)" + campaignId + "(,|$)");
var foundCampaign = campaignList.search(patt) != -1;