PHP: How to serve customized content based on hundreds of user options? - javascript

I'm working on a long, long user form which will then lead to a customized display.
The final display has to be curated, paragraph by paragraph, to fit the user's input.
My first attempt was all if statements:
if($input_a && $input_b && $input_c !== $input_d) :
echo result;
if($input_a === 'example') :
return false;
endif;
if($input_b !== 'example') :
echo $input_c * $input_d;
endif;
endif;
This got very messy, especially when I had to pass the results of this logic between JS and PHP.
My next attempt involved building a custom string for each user, based on some of the inputs ('x' means no input):
$code = array('x', 'x', 'x', 'x', 'x', 'x');
if($input_a && $input_b && $input_c !== $input_d) :
$code[0] = 1;
$code[1] = 1;
if($input_a === 'example') :
$code[2] = 1;
else:
$code[2] = 0;
endif;
if($input_b !== 'example') :
$code[3] = 1;
else :
$code[3] = 0
endif;
else :
$code[0] = 0;
$code[1] = 0;
endif;
So, in the above, the string would read something like '01x0'. Now I can assign the user this code, based on their input. Further along in the logic, I can check against this code to decide whether to serve some blocks of content or hide others.
If I want to check for a match on the first and fourth inputs, but don't care about the second and third, I can do this:
// 'x' is a placeholder for code items I don't care about
$result_option = '1xx1';
$pattern = '/[' . $code[0] . 'x][' . $code[1] . 'x][' . $code[2] . 'x]/';
if(preg_match($pattern, $result_option) :
echo $result_option;
endif;
Ok, so this works.
But I feel like I'm reinventing the wheel here and eventually my code string is going to be a hundred characters long.
Are there better ways to serve customized content based on hundreds of user options that doesn't involve a hundred classes of nested if statements?
Edit:
So just to be clearer on what I'm trying to accomplish, let's say fills in the form. They say they own a house and a car and they have a lot of debt.
For that user, I want to show them content about dealing with debt, and that's it.
Another user fills in the form. They say they rent and they lease a car and they have moderate debt.
For that user, I want to show the same debt content, slightly modified because their debt is less extreme. In addition to that, I want to show content on buying a house and the benefits of buying a used car.
Each user has a unique combination of attributes, and for each attribute, custom content is served.

I agree with Kyle - insert into a database and then create a class to handle the data manipulation that queries the new DB record(s).
In a simple example:
User enters all data on a form on a page
User submits form
On the subsequent page, the first thing you do is create a new record (or records) in a MySQL table and get the newly-created ID
for the record(s)
Now you can have a class or set of classes to handle each data point or data set
I'm not super clear on your end objective, but I might use a template page that instantiates the above-referenced class and, for each data point I want to display, I call a function in that object to do the business logic. It's not necessarily a better solution than just using the $_POST data directly, but for me such an approach helps me break down the task logically and in a clean, simplified fashion.
(NOTE: this should solve the nested 'if's but may not shorten your code per-se.)
UPDATE:
I actually do something similar to what you're talking about but with much less custom content and I use a .txt template file and then basically parse it.
The template (which is static):
<p>
Hi {recipientFname},<br>
{senderFname} has nominated you for membership into blah blah. As per your conversation with him, visit the site by following the below URL for your next steps.<br><br>
{choiceLines}
</p>
Then I have a class that does all the muscle work, but the important part is here:
$arr_tpl_vars = array('{salutation}',
'{directMessage}',
'{referralMessage}',
'{senderFname}',
'{parentFname}',
'{parentLname}',
'{memberFname}',
'{memberLname}',
'{recipientFname}'
);
$arr_tpl_data = array($this->recipient_salutation,
$directMessage,
$referralMessage,
$this->sender_fname,
$this->parent_fname,
$this->parent_lname,
$this->memberFname,
$this->memberLname,
$recipFname);
$msg = str_replace($arr_tpl_vars, $arr_tpl_data, $msg_tmpl);
With the above code, I basically load in the template, feed it the array of strings to look for (all the replaceable content is denoted by {string} ) and the function replaces everything.
In your case, I'd define the text to use (ex: $this->recipient) in business logic functions...

Related

Adding breaks in an array

I'm trying to have there be a line break between each item in my array. What my program does is create a new array using a few others which are based on the users answer to a question. I can't seem to figure out how to allow a line break between each item.
It's all done in JavaScript (with the exception of a little CSS but unimportant). I've tried using the < br > tag but it would just print the < br > instead.
I have four relevant arrays.
One for the questions:
var questions = ["Do you like volunteering","Would you be interested in joining the musical/theatre?","Would you..."] //it goes on and on but I'll spare you
Another for all of the possible results:
var clubs=[["All In","Interact Club","Key Club"," Environmental Club"],[" Fall Production"," Spring Musical"], "Student Government"," Tricorn"] //also goes on for a while
An empty array called recClubs which gets filled as they make choices.
And an empty array called choices for the choices themselves.
Then a little later I print the final outcome:
function endQuizDiv(){
//header of screen
document.getElementById("question").innerHTML= "These are the clubs that you might be interested in";
//prints the recommended clubs
document.getElementById("recClubs").innerHTML= recClubs;
}
And here is where recClubs gets its information:
function eliminateClubs(){
for(h=0;h<=personChoices.length;h++){
if (personChoices[h]==1){
recClubs.push(clubs[h]);
}
}
}
When recClubs is given to the user, all of the clubs are in one block of text and separated by commas. I want them to be separated by a line break. Any help is appreciated.
You could use join for array recClubs.push(clubs[h].join(', <br/>')); Actually you are adding array to innerHtml but it might be formatted string instead with <br/> tags
But data strucure should be :
var clubs=[["All In","Interact Club","Key Club"," Environmental Club"],[" Fall Production"," Spring Musical"], ["Student Government"],[" Tricorn"]].
or without changing data structure
function eliminateClubs(){
for(h=0;h<=personChoices.length;h++){
if (personChoices[h]==1){
var addedValue = Array.isArray(clubs[h]) ? clubs[h].join(', <br/>') :clubs[h] + '<br/>';
recClubs.push(addedValue);
}
}

If username is invalid, hide links

This is my first time doing much with anything but perl and vb so please bear with me.
I am able to compare two fields which need to match, and if they don't, then I need to hide HTML links completely. How would this be written?
This grabs the first userid
($("#trid").val());
($("#pxuserid").text());
var test = $("#pxuserid").text().indexOf("-");
var username = $("#pxuserid").text().substring(test + 1);
(username);
This grabs the second userid and changes it from all uppercase to lowercase.
($("[name=vsvadm]").val());
var str = $("[name=vsvadm]").text("checked", true).val().toLowerCase();
(str);
These are what I need to show/hide
<div class="pxcontent" id="sarea">
<div class="pxvtab" id="pxform">
<div class="pxvtablinks">
Directories
Accounting
Advanced
Security
I'm trying to get the script to say "If userid1 does not equal userid2, then hide Page 5, 6, and 7, but show only page 2, otherwise keep going"
Hopefully I didn't confuse anyone and someone could help out!
Give all the <a> tags a class:
Directories
Accounting
Advanced
Security
And then check for the condition and hide it:
if (userid1 != userid2)
$(".nav-links").hide();
Note: This should be really handled on the server side than the client side. Experienced users (and almost everyone now) can access the hidden elements by using the Dev Tools.
Assuming str and username are what you want to compare..
if(str !== username) $("a").hide();
This hides ALL links, as your question stated, but should not be used to prevent users from viewing them. If your links need to be secure then auth should be done on server side.
Also you can get rid of all the free-standing statements that you wrapped in perens. Those don't serve any purpose.
You need to compare the strings and then loop over the links
var username1 = 'username1'
var username2 = 'username2'
// Do compare
if (username1 !== username2) {
// Loop over the links
$.each($('.pxvtablinks a'), function() {
// If it doesn't have a rel attribute equal to '#page2'...
if ($(this).attr('rel') !== '#page2') {
// hide it.
$(this).hide()
}
})
}
Example: https://codepen.io/mark_c/pen/mAQwpE

I need to throw a pop up box based on a selection from a dropdown box that meet a range of criteria

I am trying to throw a pop up box when a selection is made on a drop down box, and the selection meets a range of criteria. (The dropdown box is created from a coldfusion output query). I am new to Javascript so I don't know what I am doing wrong. My code is as follows...
function secondoccupantcheck(obj){
qtenantid = new Array(#ValueList(qRecurring.iTenant_ID)#);
qoccupancy = new Array(#ValueList(qRecurring.ioccupancyposition)#);
qdescription = new Array(#ValueList(qRecurring.cdescription)#);
for (i=0;i<=(qRecurring.length-1);i++){
if ((obj.value ==qtenantid[i]) && (qoccupancy[i] == 1) && (qdescription[i].indexOf("Second Resident")>=0))
{
alert('Resident will be second occupant and occupancy will be zero');
break;
}
}
}
If an occupant in an assisted living house (iTenant_id) wants to move to another room and is currently the main tenant in his or room (iOccupancyposition =1). If he or she will be the second tenant in the room he or she wants to move to, I need to throw an alert box with a message. I can't seem to get it to work. Any help will be appreciated.
A few quick things:
I am assuming you have your JS code surrounded by a CFOUTPUT to
get actual values on client side.
Another assumption include number of values will be same in all
three fields viz. iTenant_ID, ioccupancyposition and
cdescription. If this is not the case or there are consecutive blank values then this logic will not work!
For qdescription you need to use quotedValueList() function
instead of valueList() otherwise browser will throw a JS error.
For the for loop the length should come from qtenantid.length
instead of qRecurring.length OR you need to change your code to: for (i=0;i<=(#qRecurring.recordCount#-1);i++){
Your JavaScrip function is using parameter as an obj and use only
one value out of this object. Why you are passing an object? Pass only the selected value and call is something like val and use it in if condition like: if ((val ==qtenantid[i]) && (qoccupancy[i] == 1) && (qdescription[i].indexOf("Second Resident")>=0))
There are more things that you can check for error handling. Hope this helps.

JavaScript: Detect form submission completion - Further

I tried to comment on the existing post, however I cannot until I have at least 50 'Reputation'.
The question I have is very much the same but my form submits to it's self. I wanted to use JavaScript to detect form data and display it if present, but inset a file if not.
The default action is to insert one of several 'Inserts'. Originally I had the form post to a separate ASP classic processor, but I want it all contained on the same ASP document.
In psudo, I want {If Form then Print Data Else Print 'Welcome' insert).
My psudo above is more VBScriptish, but it's a JavaScript function I want (If (Form.Data==True){Do Nothing}else{SetInset('Welcome.asp');)
I do hope that's a readable question. As I say, much the same question as above link. I'm just kinda trying to justify the question.
<body onload="goSec();AutoRun()">
function AutoRun(){
setAppDiv('AboutUs.asp', 'apDiv1');
}
function chkQryInsert() {
var z=document.location.search;
var zx=z.substr(1);
var params = {}, queries, temp, i, l;
// Split into key/value pairs
queries = zx.split("&");
// Convert the array of strings into an object
for ( i = 0, l = queries.length; i < l; i++ ) {
temp = queries[i].split('=');
params[temp[0]] = temp[1];
if (temp[0]=='Insert'){
setAppDiv(temp[1],'apDiv1');
}
else{
setAppDiv('AboutUs.asp', 'apDiv1');
}
}
}
Why not intercept the post using a button and process your answers before posting back to the server, makes more sense.
Just set the button's onClick event to the name of a JavaScript function. In the JavaScript function you can include a document.forms["myform"].submit();.
To take this a step further you could also include something like this to allow a level of Ajax like functionality, loading an ASP partial page into a particular div.
-- EDIT --
Also, consider best practice when you want to join different forms together - is it really worthwhile doing that? I always separate my mark-up and script from each other; it makes it immeasurably more readable.

Is there a better way to count specific values based on more criteria than using multiple FOR?

This is my very first time using php and javascript, and thanks only to this great site, I managed to glue together pieces of what I need it to do.
Now, I have a .txt file with list of actual skills; based on how many lines there is in the file, the page loads table with same number of rows (I manage data using array, thus foreach).
Then there are 2 other txt files, first with list of all agents, second with list of skills where are currently agents logged in; from this I create second table, where I see listed agents and skill they are logged in (rows) in different teams (columns) (again, all data from .txt I get into arrays, and build the table using foreach).
Now, what I already can do is to be able to count how many agents there are currently logged separately in each skill from different team. Since I installed jquery when I needed some conditioned formating, I also decided to use jquery:
$(document).ready(function(){
var jtym = $("div.tttt").html(); // this is how I manage to get the total number of teams;
var jzel = $("div.hhhh").html(); // this is how I manage to get the total number of used skills;
for ( var j = 1; j <= jtym; j++ ) { // to loop through all teams, e.g. table columns (they have IDs like team1, team2, team3... created using foreach);
for ( var i = 0; i <= jzel; i++ ) { // to loop through all agents in one team, e.g. rows in one column (they have IDs like skill1, skill2, skill3... created using foreach);
var v_skill_u = $( '#team' + j + ':contains("' + $( "[id=skill" + i + "u]" ).html() + '") ').length; // skill1-10 or more I get from txt file into first table; this is how I get what to count;
if (v_skill_u > 0){ // avoid writing if the count is 0 to make it more well arranged;
$( '#skill_log' + i + '_team' + j).text( v_skill_u ); // show the final reasult in table where again column = team and rows are agents logged into skill
}
}
}
});
But it makes the page load for whole 2 seconds with only 5 teams (10 agents each) and 10 skills. So is there any more efficient way to process such task than using multiple FOR?
Thank you so much for help, I love this site; like I said, this is my very first time I try php and javasript and I really love playing with it and I consider myself to be quite good with googling but I could not find any page about this.
Cheers!
edit: I tried without it and the length of loading IS because of this script.
If you're reading the text files with PHP before the headers are sent, I'd create your #skill_log items as PHP strings while you iterate through the text files, to later echo in the page. Doing this with Jquery, you're having to load the files first, then load the whole DOM in the browser before your code even starts running. You don't say how many iterations are happening, but I think it would be much faster in PHP.
I'm not entirely clear on your arrays, but using a PHP function like array_search should let you do this without iterating through both arrays in your code. Maybe like this:
foreach ($skill_array as $enumKey => $skill) {
$key_found = array_search($skill, $team_array);
if($key_found !== false){
$html_output .= '<input id="skill_log' . $enumKey . '_team' . $key_found . ' value="' . $skill . '"';
}
}
Here's answer:
its much faster using php, probably because I have already loaded all the arrays.
I did loop all 3 used arrays (teams, skills, logged agents) with FOREACH, using IF to limit the selection on each step:
FOREACH to divide teams
FOREACH to loop skills within each team
FOREACH to loop all agents logged in
IF statement to filter agents by team
IF statement to filter by skill within selected group of agents
count++ :)
Here's the 5+6 part code:
if (count( array_keys( $agent_subarray, print_r($skill_subarray['Skill']) )) > 0) {
$count++;
}
Thanks for the inspiration!
And if you have some easy tutorial how to create web sgl database and connect it with php I'd be grateful.
Have fun!

Categories