Automatic generation of multiple other info fields. For Version 6. Change log: 23-06-06 V1.5 Bugfix: Downloaded order was stripping leading digits from normal prompt input. File changed OrderScript.pl patch. 18-07-05 Altered sequence of patching to prevent temporary V7 error if Preview Pane on. 11-11-03 Added note to this readme re 6.1.3 changes. No code changes. 11-06-03 V1.4 Added maxlength capability and inline style. 07-02-03 V1.4 Added autocomplete="off" to input fields as IE was not firing onchange event on autocompleted entries. 26-12-02 V1.2 Tidied and commented setotherinfo JavaScript. 24-12-02 V1.1 Minor correction in OrderScript.pl patches to suppress field list appearing twice on Order Reports. If you've installed V1.0 then restore OrderScript.pl from your backup and re-apply only the OrderScript.pl patches as below. V1.0. -- 22/12/02 -- First Release. This code works only on Actinic V6 pages using the Quantity on Product Page (with or without the single Add to Cart button). You can still use other types of pages but should not use multiple prompts there. You don't need to change any templates as the extra code is generated automatically whenever you set the Other info prompt to something like Prompt1|Prompt2|Prompt3, etc. If you don't have a "|" character in your prompt, then the original single line prompt is created. Also you can have fields that are optional so the customer can leave them empty without error. Whenever you have a colon ":" character within any of these sub-prompt names, then these fields are optional and will not cause an error if the customer leaves them empty. You can control whether the prompt and input appear on the same or successive lines. If your prompt ends with a space then the input field will follow it on that row. No space and the input field will be on the next row. You can control the width of the input field by starting your prompt with a number. This will be removed from display and and used instead as the field width. E.g. Other Info Prompt:- Name|E-mail|Phone: Optional|Fax: Optional|Postcode or:- 30Name |40E-mail |25Phone: Optional |25Fax: Optional |12Postcode If you use a number of the form nn.nn then the integer part is the field width and the fractional part defines the maximum length of the input. E.g. Other Info Prompt:- Name|4.3Age (Name, standard width; Age, 4 wide but only 3 chars can be input) You can include style code for a field by enclosing it in { and }. Don't include the style="...." - just the .... bit without any quotes. E.g. Other Info Prompt:- 20.16{text-align:center}First Name |20.16{text-align:center; color:green}Second Name (First Name, 20 wide - only 16 chars allowed - centered text, Second name same but text in greenand optional) Note: Don't set any text to red as it will be invisible if the field has an error as this is the error background colour. These patches need a JavaScript 1.2 capable browser, so should work on most modern browsers. ########################################################################################### Patching instructions:- ########################################################################################### Put the following code into actiniccore.js (make a backup first) at the bottom after all existing code. Our patches are the bits inside the long lines of ####'s. You don't need the ####... lines. ########################################################################################### // (V11) Multiple other info prompt support - V1.5 var formno; var fieldno; var docform; function locatefield(fname){ formno = ''; fieldno = ''; // (V11) look through all forms 'till one containing field "fname" var tf = -1; var te = 0; var df = document.forms; var i = df.length - 1; for ( var j = 0; j <= i; j++ ) { var k = df[j].length - 1; for ( var l = 0; l <= k; l++ ) { if ( df[j].elements[l].name == (fname) ) { tf = j; te = l; } } } if ( tf < 0 ) { alert('Cannot find product form ' + fname); return false; } else { formno = tf; fieldno = te; docform = df[tf]; return true; } } function stripspecial( prodref ){ // find the form with the order field. if (locatefield(prodref)) { docform.elements[fieldno].value = docform.elements[fieldno].value.replace(/[¬\¦]/g, " "); } } function concat( prodref ){ // find the form with the order field. if (locatefield('O_' + prodref)) { var items = docform.elements[fieldno].value.split(' ¦ '); // fetch names docform.elements[fieldno].value = ''; for (var i = 0; i < items.length; i++) // add in all sub fields { var names = items[i].split('¬'); if ( i > 0) docform.elements[fieldno].value += ' ¦ '; docform.elements[fieldno].value += names[0] + '¬' + docform.elements[fieldno + i + 1].value.replace(/[¬\¦]/g, " "); } } } function setotherinfo(pre, name, size, max) { // alert('Pre ' + pre + ' Name ' + name + ' Size ' + size + ' Max ' + max); var prodref = name.substr(8); // the product reference part start var prodref = prodref.slice(0, -1); // lose the > char var p1 = prodref.indexOf('"'); // end of the text var prodvalue = prodref.substr(p1 + 1); // any additional value text prodref = prodref.substring(0, p1); // the actual prodref // see if simple form if (pre.indexOf('|') == -1 ) { // alert('Simple ' + name + ' Prodref-' + prodref + '-Value-' + prodvalue + '-'); document.write(pre + ''); } else { // now have a complex selection var p1 = pre.indexOf('
'); var before = pre.substring(0, p1 + 4); // before the prompt. var rest = pre.substr(p1 + 4); // whats after the
p1 = rest.indexOf('
'); // final
var prompt = rest.substring(0, p1); // the prompt text. var after = rest.substr(p1 + 4); // after the prompt (we don't need this data). // alert('Complex-' + name + '- Prodref-' + prodref + '- Value-' + prodvalue + '-'); if ( prodvalue == '') // we're not bouncing back with an error { var items = prompt.split('|'); // create default list from prompt text var S = ' value="' for (var I = 0; I < items.length - 1; I++) S += items[I] + '¬ ¦ '; S += items[items.length - 1] + '¬'; } else { p1 = prodvalue.indexOf(' VALUE="'); // we've had an error bounce var S = prodvalue.slice((p1 + 8), -1); // so extract the old data var items = S.split(' ¦ '); // the items and their data S = prodvalue.slice(p1, -1); // the value="..." substring } // alert(''); // alert('Prodvalue-' + prodvalue + '- Items-' + items); document.write(''); // the standard prompt but hidden // make a table for a nice layout document.write(''); // now see how many sub fields there are for (var I = 0; I < items.length; I++) { if ( prodvalue == '') { // simple empty list var itemname = items[I]; var itemvalue = ''; // test for additional style code var itemstyle = ''; var itemtest = itemname.match(/(.*)\{(.*)\}(.*)/); // see if there's a {...} if ( itemtest != null ) { itemname = itemtest[1] + itemtest[3]; itemstyle = 'style="' + itemtest[2] + '" '; } } else { var itembits = items[I].split('¬'); // returned list with values itemname = itembits[0]; itemvalue = ' value="' + itembits[1] + '"'; // test for additional style code var itemstyle = ''; var itemtest = itemname.match(/(.*)\{(.*)\}(.*)/); // see if there's a {...} if ( itemtest != null ) { itemname = itemtest[1] + itemtest[3]; itemstyle = itemtest[2]; } if ( (itemname.indexOf(':') == -1) && (itembits[1] == '') ) { if ( itemstyle != '' ) itemstyle += ';'; itemstyle += 'background-color: #ff0000'; } if ( itemstyle != '' ) itemstyle = 'style="' + itemstyle + '" '; } var fieldsize = size; var maxlength = ''; var sizelook = itemname.match(/^(\d+)\.?(\d*)/); // look for prefix nn or nn.nn if ( sizelook != null) { itemname = itemname.replace(/^\d+\.?\d*/, ''); // strip out any size / max prefix fieldsize = sizelook[1]; if ( sizelook[2] != '' ) maxlength = ' maxlength="' + sizelook[2] + '"'; } var spacer1 = ''); } document.write('
'; var spacer2 = '
'; if ( itemname.search(/ $/) > -1 ) { spacer1 = '
'; spacer2 = ''; } if ( itemname.indexOf(':') > -1 ) { document.write(spacer1 + '' + itemname + ''); } else { document.write(spacer1 + '' + itemname + ''); } document.write(spacer2 + '
'); } } // end of multiple other info prompt support ########################################################################################### In Actinic / Design / Text / HTML find the line (it's Phase: -1 ID 2161) %s If you're using 6.1.3 or later this line is %s In Either case replace it with the following line ########################################################################################## Patches are needed to ActinicOrder.pm (make a backup copy). Use a text editor not a word processor. The modified subroutines are listed in full below just replace them. When replacing entire subroutines, replace everything from e.g sub InfoLineHTML down to the code immediately above the comment block of the next sub ....... statement. ########################################################################################### sub InfoLineHTML { my ($sPrompt, $sInfo, $sTemplate) = @_; # # Create variables for substitution # my %hVariables; if ( $sPrompt =~ /\|/ ) {$sPrompt = '';} # Norman - remove prompt if multiple $hVariables{$::VARPREFIX . 'PROMPTLABEL'} = $sPrompt; $hVariables{$::VARPREFIX . 'PROMPTVALUE'} = $sInfo; my ($Status, $Message, $sLine) = ACTINIC::TemplateString($sTemplate, \%hVariables); # make the substitutions if ($Status != $::SUCCESS) { return ($Message); } return($sLine); } ########################################################################################### sub InfoHTMLGenerate { my $sProdref = shift; # the reference of the product my $nIndex = shift; # index of the field my $sValue = shift; # the initial value of the info (as standard string) my $bStatic = shift; # static or editable HTML? my $bHighLight = shift; my $sInfoPrompt = shift; my $sHTML; # the HTML code of the related edit box # # The default processing doesn't depend on the product reference # If you want product specific prodessing the edit the line # below as appropriate # if ( (defined $sInfoPrompt) && ($sValue == '') ) # allow for product on confirmation page { $sValue = $sInfoPrompt; $sValue =~ s/\|/¬ ¦ /g; # convert to empty strings $sValue .= '¬'; } if ($bStatic) { if ($sValue =~ / \¦ /) # norman patching { my @aValues = split / \¦ /, $sValue; $sHTML = ''; for (my $nI = 0; $nI < @aValues ; $nI++) { my @aPairs = split /¬/, $aValues[$nI]; my $sText = $aPairs[0]; $sText =~ s/^\d+\.?\d*//; # remove size & maxlength info $sText =~ s/\{.*\}//; # remove additional style info my $sSpacer1 = ''; } $sHTML .= '
'; my $sSpacer2 = '
'; if ( $sText =~ / $/ ) { $sSpacer1 = '
'; $sSpacer2 = ''; } $sHTML .= $sSpacer1 . '' . $sText . ''; $sHTML .= $sSpacer2 . $aPairs[1] . '
'; } else { $sHTML = ' ' . $sValue; } } else { my $sStyle; if (defined $bHighLight && $bHighLight == $::TRUE) { $sStyle = "background-color: $::g_sErrorColor"; # Norman removed style="...." tag } if ($sValue =~ m/ \¦ /) # norman patching { my @aValues = split / \¦ /, $sValue; # change HIDDEN to TEXT for diagnostics $sHTML = ""; my $nJ = @aValues; for (my $nI = 0; $nI < $nJ ; $nI++) { my @aPairs = split /¬/, $aValues[$nI]; my $sSize = '35'; my $sText = $aPairs[0]; $sText =~ s/\{(.*)\}//; # remove additional style info my $sThisStyle = $1; # save the embedded style my $sSpacer1 = '"; } $sHTML .= '
'; my $sSpacer2 = '
'; if ( $sText =~ / $/ ) { $sSpacer1 = '
'; $sSpacer2 = ''; } $sText =~ s/^(\d+)\.?(\d*)//; if ( $1 ) { $sSize = $1; } my $sMaxLength = ''; if ( $2 ) { $sMaxLength = 'maxlength="' . $2 . '"'; } if ($sText =~ /:/) { $sHTML .= $sSpacer1 . $sText; } else { $sHTML .= "$sSpacer1$sText"; if ( length $aPairs[1] == 0 ) { if ( $sThisStyle ) { $sThisStyle .= ';' } $sThisStyle .= $sStyle; } } if ( $sThisStyle ) { $sThisStyle = "style=\"$sThisStyle\""; } $sHTML .= $sSpacer2 . "
'; } else { $sHTML = ""; } } return $sHTML; } ########################################################################################### sub InfoValidate { my $sProdref = shift; # the reference of the product my $sInfo = shift; # the value of the field my $sPrompt = shift; my $sMessage; # # The default processing doesn't depend on the product reference # If you want product specific prodessing the edit the line # below as appropriate # if ($sInfo =~ / \¦ /) # norman patching { my @aValues = split / \¦ /, $sInfo; for (my $nI = 0; $nI < @aValues ; $nI++) { my @aPairs = split /¬/, $aValues[$nI]; $aPairs[0] =~ s/\{.*\}//; # remove additional style info if ((length($aPairs[1]) == 0) && ($aPairs[0] !~ /:/)) { my $sFieldName = $aPairs[0]; $sFieldName =~ s/^\d+\.?\d*//; # remove size count $sMessage .= "$sFieldName is required." . "

\n"; } } } if (length $sInfo == 0) # if there is no info, reprompt { $sMessage .= ACTINIC::GetPhrase(-1, 55, "$sPrompt") . "

\n"; } if (length $sInfo > 1000) { $sMessage .= ACTINIC::GetPhrase(-1, 56, "$sPrompt") . "

\n"; } return (length $sMessage == 0 ? $::SUCCESS : $::BADDATA, $sMessage); } ########################################################################################### Finally patches are needed to OrderScript.pl (make a backup copy). Use a text editor not a word preocessor. ########################################################################################### Locate the line (there will only be 1 instance):- $objOrderBlob->AddString($CurrentItem{"INFO"}); REPLACE that line with:- my $sPromptFudge = $CurrentItem{"INFO"}; # Norman fixing prompt for readibility if ( $sPromptFudge =~ /¬/ ) # if multi prompt (V1.5) { $sPromptFudge =~ s/\{.*?\}//g; # strip style info $sPromptFudge =~ s/(^| \¦ )\d+\.?\d*/$1/g; # strip field size and maxlength info $sPromptFudge =~ s/¬/ /g; # Spaces instead of ¬¦ $sPromptFudge =~ s/ \¦ /\r\n/g; # new line for each item } $objOrderBlob->AddString($sPromptFudge); # the info prompt Locate the line (there will only be 1 instance):- $objOrderBlob->AddString($$pProduct{"OTHER_INFO_PROMPT"}); REPLACE that line with:- my $sPromptName = $$pProduct{'OTHER_INFO_PROMPT'}; # Norman fixing prompt for readibility if ( $sPromptName =~ /\|/) # Hide the prompt title if complex one { $sPromptName = ''; } $objOrderBlob->AddString($sPromptName); # the info prompt Locate the pair of lines (there will only be 1 instance):- MailOrderLine( "", $$pProduct{'OTHER_INFO_PROMPT'} . "\r\n " . $CurrentItem{'INFO'}, REPLACE both those lines with:- my $sPromptName = $$pProduct{'OTHER_INFO_PROMPT'} . "\r\n "; # Norman fixing prompt for readibility if ( $sPromptName =~ /\|/) # Hide the prompt title if complex one { $sPromptName = ''; } my $sPromptFudge = $CurrentItem{"INFO"}; # The Prompt / Data pairs if ( $sPromptFudge =~ /¬/ ) # if multi prompt (V1.5) { $sPromptFudge =~ s/\{.*?\}//g; # strip style info $sPromptFudge =~ s/(^| \¦ )\d+\.?\d*/$1/g; # strip field size and maxlength info $sPromptFudge =~ s/¬/ /g; # Spaces instead of _ $sPromptFudge =~ s/ \¦ /\r\n/g; # new line for each item } MailOrderLine( "", $sPromptName . $sPromptFudge, ########################################################################################### That's all patching finished. Now do a site update. To refresh the modified scripts. Now in your product creation dialogue just set the Other Info Prompt to Prompt1|Prompt2|Prompt3, etc and the required code will be generated automatically. The "|" char is the one on the bottom left of most keyboards (not the one on some keybords top left). Remember to only use these type of prompts on pages with "Quantity on Product Page" set. They won't work properly on other type of pages. They work fine with / without the Single Add to Cart Button option. If you don't have a "|" character in your prompt, then the original single line prompt is created. Also you can have fields that are optional so the customer can leave them empty without error. Whenever you have a colon character within any of these sub-prompt names, then these fields are optional and will not cause an error if the customer leaves them empty. You can control whether the prompt and input appear on the same or successive lines. If your prompt ends with a space then the input field will follow it on that row. No space and the input field will be on the next row. Finally you can control the width of the input field by starting your prompt with a number. This will be removed from display and and used instead as the field width. E.g. Other Info Prompt:- Name|E-mail|Phone: Optional|Fax: Optional|Postcode or:- 20Name |40E-mail |25Phone: Optional |25Fax: Optional |12Postcode If you use a number of the form nn.nn then the integer part is the field width and the fractional part defines the maximum length of the input. E.g. Other Info Prompt:- Name|4.3Age (Name, standard width; Age, 4 wide but only 3 chars can be input) You can include style code for a field by enclosing it in { and }. E.g. Other Info Prompt:- 20.16{text-align:center}First Name |20.16{text-align:center; color:green}Second Name (First Name, 20 wide - only 16 chars allowed - centered text, Second name same but text in green) Note: Don't set any text to red as it will be invisible if the field has an error as this is the error background colour. These patches need a JavaScript 1.2 capable browser, so should work on most modern browsers. Bugs / Quirks. Only works on pages with "Quantity on Product Page" set. The patches make use internally of the "¬" and "¦" characters (top left ones on most keyboards) and will strip such characters from the user input (and replace them with spaces). This shouldn't affect anyone as these are very unusual characters. You can have a maximum of 1000 characters of input (that's user input text + the other info names). In practice you'll be limited by how many field names you can fit into the 256 character limit of the Other Info Prompt. TOUBLESHOOTING If your site fails you probably have patched one of the Perl scripts wrong. Go to C:\ProgramFiles\Actinic Ecommerce v6\Original and copy the files ActinicOrder.pm into your Site1 folder. Now try a site update. If the site now works you have located the mispatched script. Try making an order (use a normal product). Site should be OK. Try checking out. If you still have problems then you have also mispatched OrderScript.pl so copy it from C:\Program Files\Actinic Ecommerce v6\Original into your Site folder. Re-do the patches (one file at a time) ActinicOrder.pm first. Upload and see if the site works (use a normal product). If it's OK re-patch OrderScript.pl and retest (use a normal product and then a multi-other info one). UNINSTALLING THIS PATCH - START If you want to completely remove this patch just restore ActinicOrder.pm and OrderScript.pl and In Actinic / Design / Text / HTML find the line (it's Phase: -1 ID 2161) and restore it to:- Pre V6.1.3 %s If you're using 6.1.3 or later this line is %s Edit actiniccore.js and remove the chunk of code starting // Multiple other info prompt support - updated 11-06-03 var formno; var fieldno; var docform; . . . . // end of multiple other info prompt support UNINSTALLING THIS PATCH - END