JavaScript logic - Parsing a textarea - javascript

I need to take a textbox that is full of formatted info about accounts and then sort it somehow. I would like to know if it would be ideal (I'm trying to make this as efficient as possible) to parse the info into a two dimensional array, or if I should make account objects that will hold info in fields.
The program is simply meant to format the data so that it can be printed out without having to copy/paste.
So far I have...
function generateOutputfvoc()
{
var accountLines = document.getElementById('accountLines').value;
var accountLinesTemp = accountLines.split(/[\s]/);
for(var i = 0; i < accountLinesTemp.length; i++)
{
if(accountLinesTemp[i].match(/
Edit (1-18-13): Here is an example input. It is basically text copied from a web CRM tool. Note, this example input is something I typed up randomly.
P8B000001234567 stackoverflow Thing 12522225555 444 Active 2005-02-26 CO1000123456
P8B000001234568 stackoverflow Another Thing 444 Active 2005-02-26 CO1000123456
P8B000001234569 stackoverflow Another Thing 556 Active 2005-02-26 CO1000123456
I would like my program to take the text and simply output the text like this:
P8B000001234567 stackoverflow Thing 12522225555 444 Active 2005-02-26 CO1000123456
P8B000001234568 stackoverflow Another Thing 444 Active 2005-02-26 CO1000123456
P8B000001234569 stackoverflow Another Thing 556 Active 2005-02-26 CO1000123456
Also, I would like to know if I should use jQuery variables. I asked this because I have been looking online a lot and I found examples that use code that looks like this:
$check=fcompcheck();
if($check)
{
$output=document.frm1.type.value+" / ";
$output=$output+"Something - "+document.frm1.disco.value+" / ";
Note the: $output variable. The dollar sign indicates a jQuery variable, right?
Thank you for any help you might be able to offer me.
Update (1-19-13): I've taken a shot at it, but I'm making slow progress. I'm used to programming Java and my JavaScript looks too similar, I can tell I'm makings errors.
I'm taking it one step at a time. Here is the logic I'm using now.
Person pastes text into text box and pushes the generate button
Program takes the contents of the text box and parses it into a large array, removing only whitespace
Program then searches for patterns in the text and begins passing values into variables
I am trying to get the program to simply identify the pattern "Summary section collapse Name" because these four words should always be in this sequence. Once it identifies this it will pass the next two array values into first and last name variables. Here's some of the code:
var contactNameFirst, contactNameLast;
// Parse the input box into an array
var inputArr = document.getElementById('inputBox').value.split(/[\s]/);
for(var i = 0; i < inputArr.length; i++)
{
if(inputArr[i] == "Summary" && inputArr[i - 1] == "section" && inputArr[i - 2] == "Collapse" && inputArr[i + 1] == "Name")
{
if(inputArr[i + 2] != "Details")
{
contactNameFirst = inputArr[i + 2];
}
else
{
contactNameFirst = "";
}
if(inputArr[i + 3] != "Details")
{
contactNameLast = inputArr[i + 3];
}
else
{
contactNameLast = "";
}
}
}
document.getElementById('contactNameOutput').innerHTML = contactNameFirst + " " + contactNameLast;
Also, should I create a new post for this now, or keep editing this one?

Your accountLinesTemp is an Array of String, you could use the Array.sort function to sort your array as expected, and then use Array.join to get the full String if necessary.
See https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort on MDN for more information.

Related

Attempting to make nested questions appear dynamically... C# ASP.Net Database First,

Idea for making elements visible or invisible:
So… how the loop works right now is it for each category, it loops through each question in each category.
The idea is: Each question can be answered yes or no, and then for each question answered yes, there can be up to 5 dates added.
What I want to do:
-If yes, first date appears:
-If the first date is answered, then a second question appears, and so on.
These questions are stored in a sql server like so:
I want only the inner loop to have this ability to be visible or invisible..
My thought is to do a nested loop and check check on each element.
//Psuedo code
//For each first question which has 5 sub questions that are all set to hidden:
var questioncount = (count of the first questions)
for(int i = 0; i<questioncount; i++){
// set first variable to hold the first questions object.
var element(‘#questionElement’ + i);
// set firstElement to selected answer
var isAnsweredYes = firstElement.(‘Yes’);
for int j = 0; i<subQuestionCount; j++)
if (isAnsweredYes == True){
// jQuery selector to get an element
var query = $('#element' + j);
// check if element is Visible
var isVisible = query.is(':visible');
if (isVisible === true) {
// element is Visible
// do nothing
} else {
// element is Hidden
query.show();
}
else
{
//do nothing
}
}
}
Does my logic seem forward? or can anyone advise me in a better way?
I would use a button that says "Add another date", which is displayed under the last date field as soon as at least one is visible. That way you won't have to decide on a certain number (e.g. 5) as the maximum, plus I think it's a rather intuitive way of extending a form.
On each press of the button, create new input controls; be it in javascript or server side, it makes no real difference.

Reordering/move pages using Indesign script

I have a nearly 400 page document that I need to [randomly] reorder the pages. (If you need to know, this is a book of single page stories that need to be randomly distributed. I created a random list of pages to input into the script.)
I've been working with a modified script I found elsewhere on the internet that creates an array and moves the pages around:
var order="...list of new page numbers...";
// Create an array out of the list:
ranges = toSeparate (order);
if (ranges.length != app.activeDocument.pages.length)
{
alert ("Page number mismatch -- "+ranges.length+" given, "+app.activeDocument.pages.length+" in document");
exit(0);
}
// Consistency check:
sorted = ranges.slice().sort(numericSort);
for (a=0; a<sorted.length-1; a++)
{
if (sorted[a] < sorted[a+1]-1 ||
sorted[a] == sorted[a+1])
alert ("Mismatch from "+sorted[a]+" to "+sorted[a+1]);
}
// alert ("New order for "+order+"\nis "+ranges.join(", "));
// Convert from 1..x to 0..x-1:
for (moveThis=0; moveThis<ranges.length; moveThis++)
ranges[moveThis]--;
for (moveThis=0; moveThis<ranges.length; moveThis++)
{
if (moveThis != ranges[moveThis])
{
try{
app.activeDocument.pages[ranges[moveThis]].move (LocationOptions.BEFORE, app.activeDocument.pages[moveThis]);
} catch(_) { alert ("problem with page "+moveThis+"/index "+ranges[moveThis]); }
}
for (updateRest=moveThis+1; updateRest<ranges.length; updateRest++)
if (ranges[updateRest] < ranges[moveThis])
ranges[updateRest]++;
}
function toSeparate (list)
{
s = list.split(",");
for (l=0; l<s.length; l++)
{
try {
if (s[l].indexOf("-") > -1)
{
indexes = s[l].split("-");
from = Number(indexes[0]);
to = Number(indexes[indexes.length-1]);
if (from >= to)
{
alert ("Cannot create a range from "+from+" to "+to+"!");
exit(0);
}
s[l] = from;
while (from < to)
s.splice (++l,0,++from);
}} catch(_){}
}
// s.sort (numericSort);
return s;
}
function numericSort(a,b)
{
return Number(a) - Number(b);
}
This code worked, except that it was consistently rearranging them into the wrong random order, which, at the end of the day, is workable, but it'll just be a bigger pain in the ass to index the stories.
I suspected the problem might be caused by starting at the begginning of the document rather than the end, so I modified the script to start at the end, but then app.activeDocument.pages[ranges[moveThis]] kept coming up as undefined.
So I gave up and tried this:
app.activeDocument.pages[298].move (LocationOptions.BEFORE, app.activeDocument.pages[366]);
app.activeDocument.pages[33].move (LocationOptions.BEFORE, app.activeDocument.pages[365]);
app.activeDocument.pages[292].move (LocationOptions.BEFORE, app.activeDocument.pages[364]);
And so on for every page. (This reminds me of my time in junior high using sendKeys to create programs in Visual Basic. Had I bothered to seriously learn JavaScript instead of creating shitty AOL chatroom scrollers, I probably wouldn't be on here today.)
Nevertheless, I received the following error:
Error Number: 30477
Error String: Invalid value for parameter 'reference' of method 'move'. Expected Page or Spread, but received nothing.
I'm trying to avoid having to manually move the pages, especially considering the amount of time I've already been working on this. Any suggestions on what I need to change? Thank you!
The issue might be that you are using more than one page per spread and then trying to shuffle them across spread. The better way is to use single page per spread.
Here is a small snippet that works on my machine
var doc = app.activeDocument;
doc.documentPreferences.facingPages = false;
for (var i =0; i < 100; i++){
var index = parseInt((Math.random() * doc.spreads.length) % doc.spreads.length + '' , 10);
doc.spreads[index].move();
}
What this does is
Disables the facing pages options and makes one page per spread. A desirable condition as you mentioned that your stories are one page each(I am assuming that your stories will not violate this assumption).
Takes a random spread from the doc and sends it to the end of the spreads in the doc. It does so 100 times.
The result is what you wanted. A script to shuffle the current SPREADS randomly.

JavaScript - if class list contains value from Array

I'm trying to setup a filter on a database application, for lost property for a scout camp. The idea is the following:
The lost property items are logged into the database by reception as either 'Lost', 'Handed In', 'Owner Notified' or 'Returned' (meaning 4 lists generated from a table, with a status flag which is used to filter which list an item appears in).
At the top of each list, I have a form field (text) which I would like to use to filter the list, simply by the reception team member typing in some words that describe the item (eg, Jacket blue)
I've set a common class name to each row in the list table (a different one for each list, so listLost, listFound, listNotified, listReturned)
I've then used some of the database fields to add additional classes to the list (eg, item, colour, first name, surname - these are converted to UCASE to get around the case sensitive nature of JavaScript), so the final class might look like:
class="listLost JACKET BLUE FRED BLOGGS"
The reception team member can then type into the text field, something like 'Jacket Blue' and my JavaScript function is supposed to filter the list as follows:
the input from the text field is split into an array, using SPACE as the separator
it looks for all items in the page with a particular common class name (in this example, it would be listLost)
it then pages through the array comparing the class list for each (in this case, table row) with the array value and it if finds a match, the table row will be displayed, if not, it won't
Here's my JavaScript function:
function filterLostProperty(filterField,filterList)
{
var filterStr = document.getElementById(filterField).value;
var filterVals = filterStr.split(" ");
var filterItems = document.getElementsByClassName(filterList);
var displayCheck = 0
for (x = 0; x < filterItems.length; x++)
{
for (y = 0; y < filterVals.length ; y++)
{
if (filterItems[x].classList.contains(filterVals[y].toUpperCase()))
{
displayCheck++
}
}
if (displayCheck > 0)
{
filterItems[x].style.display = "table-row";
}
else
{
filterItems[x].style.display = "none";
}
}
}
The form field has:
onChange="filterLostProperty('filterLost','listLost')
where filterLost is the ID of the text field from which the search string comes.
PROBLEM: it doesn't really filter in the way it should... some strings just generate everything, some bring up the item you wanted plus 2 you didn't, some don't generate anything at all. And when there is more than one word it goes even more weird.
Does anyone have any suggestions about where I might have gone wrong here? Or is my method here just too overly complicated and I'm missing a simple trick with something?
21.11.2017
So - I edited my function further after having a bit of an idea that I would instead of generating an Array of the filter text (as the array approach was only using the last entered word as the filter text), I would just create a string with AND between each one (using a replace function to replace SPACE with AND Operator), in the hope that it would do a 'If class list contains X and Y and Z then blah blah'...
I tested this with fixed values at first on my test page:
function manualFilter(filterList)
{
var filterItems = document.getElementsByClassName(filterList);
for (x = 0; x < filterItems.length; x++)
{
{
if (filterItems[x].classList.contains("WALLET" && "BLUE"))
{
filterItems[x].style.display = "table-row";
}
else
{
filterItems[x].style.display = "none";
}
}
}
}
My test page is at https://bookings.springbank.org.uk/testFilter.asp and the test filter can be triggered by clicking the 'Manual Filter' button.
Problem is that when I do this, I get the row with WALLET BLUE in as expected (and not the row with WALLET BLACK which is good)... but I also get the row with JACKET BLUE (presumably because it's matched BLUE)... ideally, I don't want this to display.
If this can be made to work (effectively replacing the spaces from the text field entry with an AND operator to be interpreted by the IF statement)... the only other bit I'm not totally clear on (not being particularly proficient in JavaScript) is how I can do this dynamically from the function... presumably it's going to be a case of a certain number of consecutive quotes so that the && is interpreted as and AND operator and not simply as part of a string?

Two different conditions for auto-tabbing text fields

Good morning,
First of all, thanks in advance for any help you might provide
I'll try and explain myself as clearly as possible:
I have a column of some 30ish equal text fields, with an unmodifiable width and height in a form. The users will have two options when inputting text into the text fields:
a) Type word by word
b) Copy from another souce a chunk of text and paste it into the text field.
Now, what I want is to have two different options for the form to auto-tab to the next text field if the first one has been filled.
These are the two options I have tried up to now, which both work when used on their own, but won't work together:
a) Custom Keystroke script for, lets say, Field.0:
if (event.fieldFull) {
this.getField("Field.1").setFocus();
}
b) Custom on-blur script for Field.0:
var temp = new Array();
temp = this.getField("Field.0").value.split(' ');
var rest = "";
ini = temp[0] + ' ';
var charsRead = temp[0].length + 1;
var index = 1;
while ((charsRead + temp[index].length) < 110){
ini = ini + temp[index] + ' ';
index++;
charsRead = charsRead + temp[index].length + 1;
}
for (var i=index ; i < temp.length-1 ; i++){
rest = rest + temp[i] + ' ';
}
this.getField("Field.0").value = ini;
this.getField("Field.1").value = rest;
this.getField("Field.1").setFocus();
As you might probably have noticed, I am no expert (not even close to one...) scripter, so the code might be inefficient or repetitive.
What the script does is: Store the words of the chunk pasted into an array (so as not to split the text in the middle of a word), and copy the first fitting words up to 110 chars (an arbitrary number which sometimes is too little and sometimes too much), and then takes the rest of the words in the array and pastes them into the next field.
When the user tabs out of the Field.0 the focus is set to Field.1. If the text is still too long, when he tabs out of Field.1, the focus is set to Field.2 with the second remainder of the text pasted into it. So, all he has to do is Ctrl+V and TAB, TAB, TAB until all the text has occupied the necessary fields.
Now, for the solution to point a), Scrolling Long Text has to be disabled, but, it is necessary for the script used to solve problem b).
What I am looking for is a way of, independently on how the user has inputted text, to auto-tab WHEN THE FIELD IS FULL. And by full I mean that the text has reached THE END OF THE VISIBLE AREA.
Be it while typing out the text (I suppose it'd has to be with a keystroke script) or when pasting a long phrase (with an on-blur, since keystroke doesn't work here).
Sorry for the long post and thank you once more for the help.
BTW: Using Adobe Acrobat X Pro.
If you have a monospaced font, you can determine how many characters fit in a text field.
Break the pasted text up into chunks of that size, then distribute these chunks over the fields.
So, using the chunk function found here:
//(On paste)
var brokenUpString = pastedString.chunk(maxInputLengthPerField);
for(var i = 0; brokenUpString[i]; i++){
fields[i]value = brokenUpString[i]
}
Now, if you want to move the cursor to the next text field when a user is typing, something like this may work:
//(On key up)
var currentField = 0;
if(fields[currentField].value.length == maxInputLengthPerField){
currentField++;
fields[currentField].setFocus();
}
The problem is that it's "hard" to detect how many characters are entered when a user keeps a button pressed, but you could just take the whole string, break it up, and distribute it over the fields, if that happens.
(chunk() function from the link:)
String.prototype.chunk = function(size) {
return [].concat.apply([],
this.split('').map(function(x,i){ return i%size ? [] : this.slice(i,i+size) }, this)
)
}

Google Docs - spreadsheet loop

This one might be a bit basic and easy to answer, but I've been pulling out my hair for a while now!
I've built the following code - which is semi-pseudo as I can't find the right way to make things work!
var s = "Test";
function onEdit(event)
{
var ss = event.source.getActiveSheet();
var r = event.source.getActiveRange();
if (ss.getName() == s)
{
results = {"Currently On": 0, "Next Up": 0, "On Hold": 0, "Waiting on someone else": 0, "zDone": 0};
last = ss.getMaxRows();
start = ss.getRange("F3:"+last).getValues();
var output = "J11";
for (x=0;x<start.length;x++)
{
results[start[x]]++;
}
for (y=0;y<results.length;y++)
{
row = ss.getRow(output);
row.value = results[y];
output++;
}
}
}
I've got an example of the data in this image
The basic idea is to run through all the possible categories of each task and keep a numeric list on the side of how many of each there are. I'd also like to make it dynamic (so I don't have to hard code in the list of categories) but I'm more interested in just making it work for the moment.
The Google Apps debugger is very frustrating!
Thanks for your help all!
Firstly, this particular use case would be easily achievable with a spreadsheet formula, eg:
=QUERY(A2:F;"select F, count(A) where F != '' group by F label count(A) 'Count'";1)
but there may be a reason why you want to do this with GAS.
So secondly, this is where I think there may be some syntax issues:
last = ss.getMaxRows();
I would just use var last = ss.getLastRow() here.
start = ss.getRange("F3:"+last).getValues();
The range reference would evaluate to something like "F3:100", which is a valid reference in GSheets (don't know about whether GAS can handle it), but nevertheless you really want something like "F3:F100", so I would use var start = ss.getRange("F3:F"+last).getValues();.
results[start[x]]++;
When you create an array from a getValues() call it is a 2D array, so you would need to use results[start[x][0]]++;.
With the next loop and the output variable, I must admit I'm a bit lost with what you're doing there. How did you want your result table laid out?
You have
output = "J11";
And then you do
ss.getRow(output);
output++;
This is invalid.First of all, ss is a Sheet under which there is not getRow method. So, what you should really be doing is something like this
var row = 11 ;
var col = 10 ; //Col J
for (y=0;y<results.length;y++)
{
ss.getRange(row,col,1,1).setValue(results[y]);
row++:
}
Like AdamL, I suggest that this is better handled within the native capability of the spreadsheet. Seems to me that you want a pivot table, which would update dynamically. Alternatively a formula like =countif(F:F,"Currently On" ) would meet your immediate request. =Unique(F:F) will give you the list of categories in an array

Categories

Resources