I am working on my Portfolio project and for that I have made a International country code selector program for my phone number field. but the problem I'm facing right now is that I have two forms in my homepage one is Consultation Form and another one is Contact Form, and I want to use the same JS program for both Forms.
I don't want to rewrite the same type of program or functions again and again, because that negatively effects the performance of my website. but in the other hand I don't know how can I reuse the same code for two forms. It conflicts when I try to reuse the function.
I have a working dropdown menu for Contact Form, also I want to implement the same logic to Consultation Form by using the same program.
Please help me to figure out this problem.
// Cache the elements
const ccDiv = document.querySelector(".contact-frm-cc");
const ccButton = document.querySelector(".cc-telcode");
const ccContainer = document.querySelector(".cc-container");
const ccSearchInput = document.querySelector(".cc-search-box");
const ccList = document.querySelector(".cc-data-list");
var selectedCountry = ""; // saved by "code"
// Add event listeners to the button, input, and list
// We use a process called "event delegation" on the list
// to catch events from its children as they "bubble up" the DOM
// https://dmitripavlutin.com/javascript-event-delegation/
ccButton.addEventListener("click", handleButton);
ccSearchInput.addEventListener("input", handleInput);
ccList.addEventListener("click", handleListClick);
document.addEventListener("click", handleDocumentClick);
// All of the data held as objects within an array
const data = [
{ name: "Afganistan", code: "93", flag: "afg" },
{ name: "Albania", code: "355", flag: "alb" },
{ name: "Algeria", code: "213", flag: "dza" },
{ name: "American Samoa", code: "1-684", flag: "asm" },
{ name: "Andorra", code: "376", flag: "and" },
{ name: "Angola", code: "244", flag: "ago" },
{ name: "Anguilla", code: "1-264", flag: "aia" },
{ name: "Antarctica", code: "672", flag: "ata" },
{ name: "Antigua and Barbuda", code: "1-268", flag: "atg" },
{ name: "Argentina", code: "54", flag: "arg" },
{ name: "Armenia", code: "374", flag: "arm" },
{ name: "Aruba", code: "297", flag: "abw" },
{ name: "Australia", code: "61", flag: "aus" },
{ name: "Austria", code: "43", flag: "aut" },
{ name: "Azerbaijan", code: "994", flag: "aze" },
{ name: "Bahamas", code: "1-242", flag: "bhs" },
{ name: "Bahrain", code: "973", flag: "bhr" },
{ name: "Bangladesh", code: "880", flag: "bgd" },
{ name: "Barbados", code: "1-246", flag: "brb" },
{ name: "Belarus", code: "375", flag: "blr" },
{ name: "Belgium", code: "32", flag: "bel" },
{ name: "Belize", code: "501", flag: "blz" },
{ name: "Benin", code: "229", flag: "ben" },
{ name: "Bermuda", code: "1-441", flag: "bmu" },
{ name: "Bhutan", code: "975", flag: "btn" },
{ name: "Bolivia", code: "591", flag: "bol" },
{ name: "Bosnia and Herzegovina", code: "387", flag: "bih" },
{ name: "Botswana", code: "267", flag: "bwa" },
{ name: "Brazil", code: "55", flag: "bra" },
{ name: "British Indian Ocean Territory", code: "246", flag: "iot" },
{ name: "British Virgin Islands", code: "1-284", flag: "vgb" },
{ name: "Brunei", code: "673", flag: "brn" },
{ name: "Bulgaria", code: "359", flag: "bgr" },
{ name: "Burkina Faso", code: "226", flag: "bfa" },
{ name: "Burundi", code: "257", flag: "bdi" },
{ name: "Cambodia", code: "855", flag: "khm" },
{ name: "Cameroon", code: "237", flag: "cmr" },
{ name: "Canada", code: "1", flag: "can" },
{ name: "Cape Verde", code: "238", flag: "cpv" },
{ name: "Cayman Islands", code: "1-345", flag: "cym" },
{ name: "Central African Republic", code: "236", flag: "caf" },
{ name: "Chad", code: "235", flag: "tcd" },
{ name: "Chile", code: "56", flag: "chl" },
{ name: "China", code: "86", flag: "chn" },
{ name: "Christmas Island", code: "61", flag: "cxr" },
{ name: "Cocos Islands", code: "61", flag: "cck" },
{ name: "Colombia", code: "57", flag: "col" },
{ name: "Comoros", code: "269", flag: "com" },
{ name: "Cook Islands", code: "682", flag: "cok" },
{ name: "Costa Rica", code: "506", flag: "cri" },
{ name: "Croatia", code: "385", flag: "hrv" },
//------- MORE COUNTRIES TO ADD LATER
];
// Handles the document click - it checks to see if the clicked
// part of the document has a parent element which is either
// `null` or is the HTML element, and then closes the container
// if it's open
function handleDocumentClick(e) {
const { parentElement } = e.target;
document.addEventListener("click", (event) => {
if (!ccDiv.contains(event.target)) {
ccContainer.classList.remove("show-cc-list");
}
});
}
// Filters the data based on the characters
// at the start of the provided name
function filterData(data, value) {
return data.filter((obj) => {
return (
obj.name.toLowerCase().startsWith(value.toLowerCase()) ||
obj.code.toLowerCase().startsWith(value.toLowerCase())
);
});
}
// Create a series of list items based on the
// data passed to it
function createListHtml(data) {
return data.map((obj) => {
const { name, code, flag } = obj;
let isSelected = "";
if (obj.code == selectedCountry) isSelected = "selected-country";
return `
<li class="cc-list-items ${isSelected}" data-name="${name}" data-code="${code}" data-flag="${flag}">
<div class="flag-icon flag-icon-${flag}"></div>
<div class="name">${name} (+${code})</div>
</li>
`;
}).join("");
}
// Toggle the container on/off
function handleButton() {
ccContainer.classList.toggle("show-cc-list");
ccList.innerHTML = createListHtml(data);
}
// No data available list item
function createNoDataHtml() {
return '<li class="nodata">No data available</li>';
}
// When the input is changed filter the data
// according to the current value, and then
// create some list items using that filtered data
function handleInput(e) {
const { value } = e.target;
if (value) {
const filtered = filterData(data, value);
if (filtered.length) {
ccList.innerHTML = createListHtml(filtered);
} else {
ccList.innerHTML = createNoDataHtml();
}
} else {
ccList.innerHTML = createListHtml(data);
}
}
// Create some button HTML
function createButtonHtml(code, flag) {
return `
<div class="flag-icon flag-icon-${flag}"></div>
<option class="cc-code" value="+${code}">+${code}</option>
`;
}
// When an item is clicked, grab the relevant data
// attributes, create the new button HTML, and then
// close the container
function handleListClick(e) {
const item = e.target.closest("li") || e.target;
if (item.classList.contains("cc-list-items")) {
const { code, flag } = item.dataset;
selectedCountry = item.dataset.code;
ccButton.innerHTML = createButtonHtml(code, flag);
ccContainer.classList.remove("show-cc-list");
}
}
.cc-telcode {
margin-bottom: 1em;
display: flex;
justify-content: center;
width: 100%;
}
.cc-telcode div.cc-code,
.cc-list-items div.name {
margin-left: 0.25em;
}
.cc-container {
display: none;
width: 300px;
position: absolute;
}
.show-cc-list {
display: block;
z-index: +999;
}
.cc-data-list {
max-height: 100px;
list-style: none;
margin: 1em 0 0 0;
padding: 0;
overflow-y: scroll;
border: 1px soldi darkgray;
}
.cc-list-items {
display: flex;
padding: 0.25em;
border: 1px solid lightgray;
}
.cc-list-items:hover {
cursor: pointer;
background-color: lightyellow;
}
.selected-country {
cursor: pointer;
background-color: rgb(73, 118, 241);
}
.contact-frm-cc {
width:100px;
}
<link rel="stylesheet" href="https://amitdutta.co.in/flag/css/flag-icon.css">
<!------------- Working Dropdown Menu ------------>
<div class="contact-frm-cc">
<button class="cc-telcode">Tel code</button>
<section class="cc-container">
<input type="text" class="cc-search-box" placeholder="Search for country" />
<ul class="cc-data-list">
</ul>
</section>
</div>
<!------------- Not-Working Dropdown Menu ------------>
<!--
<div class="consult-frm-cc">
<button class="cc-telcode">Tel code</button>
<section class="cc-container">
<input type="text" class="cc-search-box" placeholder="Search for country" />
<ul class="cc-data-list">
</ul>
</section>
</div>
-->
You can create a function to register your form logic, and just pass your root form element.
here is a simple modification based on your code
<!-- https://codepen.io/DlmaK/pen/dyjXYrm -->
Related
HelloWorld.vue
<template>
<div>
<div v-for="(piza, index) in pizas" :key="piza.pname">
{{ piza.pname }}
<List
:content="matchpizza"
:pname="piza.pname"
:qname="quantitys[index] ? quantitys[index].qname : ''"
/>
</div>
</div>
</template>
<script>
import List from "./List.vue";
export default {
name: "HelloWorld",
components: {
List,
},
data() {
return {
pizas: [
{
pname: "chicken pizza",
},
{
pname: "chicken pizza spl",
},
{
pname: "mutton pizza",
},
{
pname: "plain pizza",
},
],
quantitys: [
{
qname: "one",
},
{
qname: "two",
},
{
qname: "three",
},
{
qname: "four",
},
{
qname: "five",
},
],
matchpizza: [
{
matchnum: "1",
availability: "later",
pname: "plain pizza",
qname: "five",
},
{
matchnum: "2",
availability: "buy now",
pname: "chicken pizza",
qname: "one",
},
{
matchnum: "3",
availability: "buy now",
pname: "plain pizza",
qname: "five",
},
{
matchnum: "4",
availability: "buy now",
pname: "chicken pizza spl",
qname: "five",
},
{
matchnum: "5",
availability: "later",
pname: "mutton pizza",
qname: "five",
},
],
};
},
};
</script>
List.vue
<template>
<div>
<div v-if="matchpizza.length > 0">
<div
v-for="match in matchpizza"
:key="match.matchnum"
:class="{
green: match.availability === 'buy now',
red: match.availability === 'later',
}"
>
<div v-for="quantity in quantitys" :key="quantity.qname">
{{ quantity.qname }}
</div>
<div class="next-data-two">{{ match.availability }}</div>
</div>
</div>
<div v-else class="next-data"><p>No availability</p></div>
</div>
</template>
<script>
export default {
components: {},
props: {
content: {
type: Array,
required: true,
},
pname: {
type: String,
required: true,
},
qname: {
type: String,
required: true,
},
},
data: function () {
return {};
},
methods: {},
computed: {
quantitys() {
return this.content.filter((a) => a.qname === this.qname);
},
matchpizza() {
return this.content.filter((a) => a.pname === this.pname);
},
},
};
</script>
<style scoped>
.next-data {
display: flex;
flex-direction: row-reverse;
margin-top: -2%;
margin-right: 40%;
color: blue;
}
.next-data-two {
display: flex;
flex-direction: row-reverse;
margin-top: -1%;
margin-right: 42%;
color: red;
margin-bottom: 1%;
}
</style>
See my working code here:-
https://codesandbox.io/s/data-display-tcr8oj?file=/src/components/HelloWorld.vue
From the helloworld.vue you can see this line :qname="quantitys[index] ? quantitys[index].qname : ''"
Where as per the above code, from the quantitys array. it is not pointing to the particular index value correctly?.
According to my output from codesandbox:-
For chicken pizza it showing as , chicken pizza --> one --> later
But correct path is, chicken pizza --> later --> five
Similarly for others too, having same issue....
Is it because of index position wrong or issue with logic??
As you mentioned your required pathe is chicken pizza --> later --> five.
This path doesnot have to do anything with the quantitys array. You could simply display the details using the content prop itself.
Working Fiddle https://codesandbox.io/s/data-display-forked-kjxuyv
Okay, so I don't know how to properly express my simple problem because of how simple it is, I guess.
Basically, I have an autocomplete done by me in my React project.. I have two inputs "Country" and "City". When I type a country my autocomplete works great giving me suggestions but now I have to make the same for my second input so it would give me a list of cities that depends on which country is typed in the "Country" input...
"United Kingdom" => "London, Birmingham, Bighton etc."
How can I do that? Thank you!
P.S. I already have all the lists of countries and cities, I just don't know how to make the second input to depend on an information in the first one.
Code here
Autocomplete.jsx
https://github.com/lembas-cracker/Weather-app/blob/master/src/Autocomplete.jsx
Form.jsx
https://github.com/lembas-cracker/Weather-app/blob/master/src/Form.jsx
P.S. I already have all the lists of countries and cities, I just don't know how to make the second input to depend on an information in the first one.
If you know which country the city belongs to (perhaps via a key in the city object), you could run a simple filter function to remove any cities that don't belong to that country.
this.state = {
selectedCountry: 'London',
};
const cities = [
{ name: "Toronto", country: "Canada" },
{ name: "London", country: "United Kingdom" }
];
const filteredCities = cities.filter(city => {
return city.country !== this.state.selectedCountry;
});
On your city input field make sure to create an onBlur function to will run the filter on your cities list once the user leaves that input field.
Made a quick example. Did you mean smth like this? Since you haven't provided any part of your source code, I used plain HTML select for the demo.
https://jsfiddle.net/arfeo/n5u2wwjg/204186/
class App extends React.Component {
constructor() {
super();
this.state = {
countryId: 1,
};
}
onCountryChange(countryId) {
this.setState({ countryId: parseInt(countryId) });
}
render() {
return (
<div>
<Input
key="countriesInput"
type="countries"
countryId={this.state.countryId}
onChange={(countryId) => this.onCountryChange(countryId)}
/>
<Input
key="citiesInput"
type="cities"
countryId={this.state.countryId}
/>
</div>
);
}
}
class Input extends React.Component {
constructor() {
super();
this.selectRef = null;
}
renderOptions() {
const countries = [
{
id: 1,
name: 'England',
},
{
id: 2,
name: 'Germany',
},
{
id: 3,
name: 'France',
},
];
const cities = [
{
countryId: 1,
cities: [
{
id: 1,
name: 'London',
},
{
id: 2,
name: 'Liverpool',
},
{
id: 3,
name: 'Salisbury'
}
],
},
{
countryId: 2,
cities: [
{
id: 4,
name: 'Berlin',
},
{
id: 5,
name: 'Frankfurt',
},
],
},
{
countryId: 3,
cities: [
{
id: 6,
name: 'Paris',
},
],
},
];
switch (this.props.type) {
case 'countries': {
return countries.map((country) => (
<option
key={country.id.toString()}
value={country.id}
>
{country.name}
</option>
));
}
case 'cities': {
const citiesMap = cities.filter((city) => city.countryId === this.props.countryId);
if (citiesMap && citiesMap[0]) {
const citiesList = citiesMap[0].cities;
if (citiesList) {
return citiesList.map((city) => (
<option
key={city.id.toString()}
value={city.id}
>
{city.name}
</option>
));
}
}
return null;
}
default: return null;
}
}
render() {
return (
<select name={this.props.type} ref={(ref) => this.selectRef = ref} onChange={() => this.props.onChange(this.selectRef.value)}>
{this.renderOptions()}
</select>
);
}
}
ReactDOM.render(<App />, document.querySelector("#app"))
UPDATE
Make your Form component stateful.
Add a state property for countries in Form (let it be countryId).
Pass this property as a prop into the second Autocomplete component.
When the first Autocomplete changes, change the countryId of the Form.
I've done something similar which may help you.
The Object.keys(instutiontypes) you could use to have an array of countries, instead. Then inside of those values, you can have an array of objects. You could have the cities here, e.g. {value: "Manchester", "label: Manchester", phoneExt: "0114"}
const instutiontypes = {
Kindergarten: [
{ value: "PreK", label: "PreK" },
{ value: "K1", label: "K1" },
{ value: "K2", label: "K2" },
{ value: "K3", label: "K3" },
],
"Primary School": [
{ value: "Grade 1", label: "Grade 1" },
{ value: "Grade 2", label: "Grade 2" },
{ value: "Grade 3", label: "Grade 3" },
{ value: "Grade 4", label: "Grade 4" },
{ value: "Grade 5", label: "Grade 5" },
{ value: "Grade 6", label: "Grade 6" },
],
}
To have the options in my input, I use Object.keys(instutiontypes) to get ['Kindergarten','Primary School']
Then, to get the array of ages to give to my secondary dropdown, I have written this code:
const types = ['Selection1', 'Selection2']
const agesList = [];
for (let i = 0; i < types.length; i++) {
Object.values(institutionTypes[types[i]]).map(({ label }) =>
agesList.push(label)
);
}
This way, the ages dropdown list is dependent on the values passed to institutionTypes.
I'm using mui's <Autocomplete /> components to make them be search dropdowns, with the prop options for the arrays.
I have a mustache file, and I am iterating over the array:
var data = {
sales: [
{
name: "Jim Frost",
region: "USA East",
phone: "212-555-1212",
email: "jfrost#acme-travel.com"
},
{
name: "Jan Smith",
region: "USA West",
phone: "310-555-1212",
},
{
name: "Fred Wesley",
phone: "608-555-1212",
email: "fwesley#acme-travel.com"
},
{
name: "Lisa Moore",
region: "USA South",
phone: "315-555-1212",
email: "lmoore#acme-travel.com"
},
{
name: "Jim Dio",
phone: "+ 44 022-555-1212",
email: "jdio#acme-travel.com"
},
{
name: "Charles Watts",
region: "Spain",
email: "cwatts#acme-travel.com"
},
{
name: "Bert Cooper",
region: "Italy",
email: "bcooper#acme-travel.com"
}
]
};
here is the markup:
<div>
<section>
{{#data.sales}}
<article class="items">
<div class="region">{{{region}}}</div>
</article>
{{/data.sales}}
</section>
</div>
I want to add some special style (like, bold font, color etc) ONLY if the region is USA East.
how can i detect inside this inherent loop in the article element if {{{region}} has a specific value? Given that the comparison will be made against a value that i get from backend, say {{myValue}}, which is manually set to USA East in the backend.
You can add a function in the data which will return the correct class depending on the region value. Something like
data['regionClass'] = function(){
if ( this['region'] == 'USA East' ) {
return "strong green";
}else{
return "";
}
}
And then in the Mustache you can do: <div class="region {{regionClass}}">{{{region}}}</div>
I'm trying to do a form with dropdown dependable options, the problem is that I can just use HTML, Javascript and Ajax, no database, so I have to fill the options directly with jquery, so far this is what I got, but is not working, any help would awesome, thank you :)
$(document).ready(function(){
var countries = [
{
"id": "1",
"name": "Mexico"
},
{
"id": "2",
"name": "USA"
},
{
"id": "3",
"name": "Canada"
}
]
var states = {
'mexico': [{
display: "Ciudad de Mexico",
value: "mx-city"
}, {
display: "Jalisco",
value: "jalisco"
}],
'usa': [{
display: "Texas",
value: "texas"
}, {
display: "Ohio",
value: "ohio"
}],
'canada': [{
display: "Montreal",
value: "montreal"
}, {
display: "Toronto",
value: "toronto"
}]
};
var states = {
'mx-city': [{
display: "Benito Juarez",
value: "benito-juarez"
}, {
display: "Cuauhtemoc",
value: "cuauhtemoc"
}],
'jalisco': [{
display: "Zapopan",
value: "zapopan"
}, {
display: "Guadalajara",
value: "Guadalajara"
}],
'texas': [{
display: "San Antonio",
value: "san-antonio"
}, {
display: "Austin",
value: "austin"
}],
'ohio': [{
display: "Colombus",
value: "colombus"
}, {
display: "Cleveland",
value: "cleveland"
}],
'montreal': [{
display: "Quebec",
value: "Quebec"
}, {
display: "Vermont",
value: "vermont"
}],
'toronto': [{
display: "Ontario",
value: "ontario"
}, {
display: "York",
value: "york"
}]
};
$("#country").on('click',function() {
var pais = $(this).val();
$("#country").find("option").remove();
$(countries).each(function (i) {
$("#country").append('<option id="'+countries[i].id+'">'+countries[i].name+"</option>");
});
console.log(pais);
});
function list(array_list){
$("#child_selection").html("");
$(array_list).each(function (i) {
$("#child_selection").append('<option value="'+array_list[i].value+'">'+array_list[i].display+"</option>");
});
}
$('#child_selection').change(function() {
var state = $(this).val();
if (states[state] == undefined) {
return $("#child").text('Selecciona tu ciudad');
}
list(states[state]);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script><form action="" method="" enctype="application/json">
<br/>Nombre: <input type="text" />
<br/>Edad: <input type="text" />
<br/>Pais:
<select name="country" id="country">
<option value="">Selecciona tu pais</option>
</select>
<br />Estado:
<select name="child_selection" id="child_selection">
<option value="">Selecciona tu estado</option>
</select>
<br/>Ciudad:
<select name="child" id="child">
<option value="">Selecciona tu ciudad</option>
</select>
<input type="submit" value="Submit" />
</form>
First of all you have 2 variables with the same name states and your code is not according to the format of your JSON. Below the code i have fixed. Have a look.
$(document).ready(function() {
var countries = [{
"id": "1",
"name": "Mexico"
}, {
"id": "2",
"name": "USA"
}, {
"id": "3",
"name": "Canada"
}]
var states = {
'mexico': [{
display: "Ciudad de Mexico",
value: "mx-city"
}, {
display: "Jalisco",
value: "jalisco"
}],
'usa': [{
display: "Texas",
value: "texas"
}, {
display: "Ohio",
value: "ohio"
}],
'canada': [{
display: "Montreal",
value: "montreal"
}, {
display: "Toronto",
value: "toronto"
}]
};
var cities = {
'mx-city': [{
display: "Benito Juarez",
value: "benito-juarez"
}, {
display: "Cuauhtemoc",
value: "cuauhtemoc"
}],
'jalisco': [{
display: "Zapopan",
value: "zapopan"
}, {
display: "Guadalajara",
value: "Guadalajara"
}],
'texas': [{
display: "San Antonio",
value: "san-antonio"
}, {
display: "Austin",
value: "austin"
}],
'ohio': [{
display: "Colombus",
value: "colombus"
}, {
display: "Cleveland",
value: "cleveland"
}],
'montreal': [{
display: "Quebec",
value: "Quebec"
}, {
display: "Vermont",
value: "vermont"
}],
'toronto': [{
display: "Ontario",
value: "ontario"
}, {
display: "York",
value: "york"
}]
};
$(countries).each(function(i) {
$("#country").append('<option id="' + countries[i].id + '">' + countries[i].name + "</option>");
});
$("#country").on('change', function() {
list(states[$("#country").val().toLowerCase()]);
});
function list(array_list) {
$("#child_selection").html("");
$(array_list).each(function(i) {
$("#child_selection").append('<option value="' + array_list[i].value + '">' + array_list[i].display + "</option>");
});
}
$('#child_selection').change(function() {
var state = $(this).val();
if (cities[state] == undefined) {
return $("#child").text('Selecciona tu ciudad');
}
array_list = cities[state.toLowerCase()];
$("#child").html("");
$(cities[state]).each(function(i) {
$("#child").append('<option value="' + array_list[i].value + '">' + array_list[i].display + "</option>");
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<br/>Nombre:
<input type="text" />
<br/>Edad:
<input type="text" />
<br/>Pais:
<select name="country" id="country">
<option value="">Selecciona tu pais</option>
</select>
<br />Estado:
<select name="child_selection" id="child_selection">
<option value="">Selecciona tu estado</option>
</select>
<br/>Ciudad:
<select name="child" id="child">
<option value="">Selecciona tu ciudad</option>
</select>
<input type="submit" value="Submit" />
</form>
Hope it helps :)
I am trying to wrap my head around Promises, then , when, and everything else that goes along with it. I am not having much success. Here is what I'm trying to accomplish in English, and maybe somebody can crack the code because so far nothing I've written works.
I am writing a SPA (single page app) for mobile devices. Essentially all the content is is one giant HTML page with a bunch of DIV's. However, only one DIV is shown at a time. The user will have a tab bar to click on each of the icons to show/hide DIV's. Think of something like the Apple App Store interface with "Featured", "Top Charts", "Explore", "Search", and "Updates" at the bottom.
Parse database query of table Businesses for 1 business with AppUrl=example.com
Resulting business objectId is used to query table Navigation for all pieces of the navigation. Things like "Home", "About Us", "Menus", "Events", "Contact", etc.
Resulting navigation items are looped to render DIV's with content in them. The content comes from the tables below depending on the Module column:
"Home" = Photos table
"About Us" = Pages table
"Menus" = Lists table
"Event" = Lists table
That's basically it. Pretty simple, but obviously there are nest queries within #4. I don't know if I should be creating one giant object in my queries and then outputting that? Or creating a bunch of different objects with arrays inside of them? Really kind of lost since this style of syntax is different than say PHP. Advice?
Here is my non-database connected version:
app.get('/', function(req, res){
var frontpageImages = [
{ caption:"Eggplant, Prosciutto, and Pesto Pressed Sandwiches.", file:"image01.jpg", position:"15%" },
{ caption:"Pico de Gallo", file:"image02.jpg", position:"75%" },
{ caption:"B.L.A.T Croque Madame", file:"image03.jpg", position:"20%" },
{ caption:"Double Oreo Brownie Cupcake", file:"image04.jpg", position:"80%" },
{ caption:"Baked Chicken Chimichangas with Monterey Jack Cheese Sauce", file:"image05.jpg", position:"20%" }
]
var menu = [
{ divider:"Appetizers" },
{ name:"French Fries", picture:"menu-french-fries", subname:"$4.95" },
{ name:"Loaded Cheese Fries", picture:"menu-cheese-fries", subname:"$7.95" },
{ name:"Gaelic Chips", picture:"menu-gaelic-chips", subname:"$2.95" },
{ name:"Jalapeno Mac n' Cheese", picture:"menu-jalapeno-mac-n-cheese", subname:"$4.95" },
{ name:"Chicken Wings", picture:"menu-chicken-wings", subname:"$8.50" },
{ name:"Irish Nachos", picture:"menu-irish-nachos", subname:"$8.50" },
{ name:"Black & Tan Onion Rings", picture:"menu-onion-rings", subname:"$6.95" },
{ name:"Mac's Quesadillas", picture:"menu-quesadillas", subname:"$8.50" },
{ name:"Banger Bites", picture:"menu-banger-bites", subname:"$7.95" },
{ divider:"Salads" },
{ name:"Caesar Salad", picture:"menu-caesar-salad", subname:"$6.50" },
{ name:"House Salad", picture:"menu-house-salad", subname:"$6.50" },
{ name:"Buffalo Chicken Salad (Grilled or Battered)", picture:"menu-buffalo-chicken-salad", subname:"$8.95" },
{ divider:"Sandwiches & Burgers" },
{ name:"Rueben", picture:"menu-reuben", subname:"$8.50" },
{ name:"Dublin Corned Beef", picture:"menu-corned-beef-sandwich", subname:"$8.50" },
{ name:"Philly Cheese Steak", picture:"menu-philly-cheese-steak", subname:"$8.50" },
{ name:"Grilled Chicken", picture:"menu-grilled-chicken-sandwich", subname:"$8.50" },
{ name:"Club Sandwich", picture:"menu-club-sandwich", subname:"$8.50" },
{ name:"Not-So-Irish Burger", picture:"menu-irish-burger", subname:"$9.95" },
{ name:"Dirty Burger", picture:"menu-dirty-burger", subname:"$7.95" },
{ name:"Aurora Burger", picture:"menu-aurora-burger", subname:"$10.95" },
{ name:"Bleu Cheese Burger", picture:"menu-bleu-cheese-burger", subname:"$11.95" },
{ name:"Additional Burger Toppings", picture:"menu-burger-toppings", subname:"$0.50" },
{ divider:"Irish Favorites & Entrees" },
{ name:"Beer Battered Fish N' Chips", picture:"menu-fish-and-chips", subname:"$11.50" },
{ name:"Bangers And Mash", picture:"menu-bangers-and-mash", subname:"$10.95" },
{ name:"Shepherd's Pie", picture:"menu-shepherds-pie", subname:"$10.95" },
{ divider:"Brunch" },
{ name:"Irish Breakfast", picture:"menu-irish-breakfast", subname:"$11.50" },
{ name:"American Breakfast", picture:"menu-american-breakfast", subname:"$11.50" },
{ name:"Irish Breakfast Roll", picture:"menu-irish-breakfast-roll", subname:"$8.95" },
{ name:"English Muffin, Scrambled Eggs, Cheddar and Irish Rasher", picture:"menu-irish-rasher", subname:"$7.50" },
{ name:"3 Egg Omelette", picture:"menu-omelette", subname:"$6.50" },
{ name:"Eggs Benedict", picture:"menu-eggs-benedict", subname:"$8.50" },
{ name:"3 Pancakes with Maple Syrup", picture:"menu-pancakes", subname:"$6.00" },
{ name:"Grilled Turkey and Swiss", picture:"menu-grilled-turkey-and-swiss", subname:"$7.00" }
];
var drinks = [
{ name: "Bahama Bomb", desc: "Bacardi 151 Rum, Cruzan Coconut Rum, Creme de Banana, Pineapple juice, and Sprite.", subname: "$9.95" },
{ name: "Tropical Margarita", desc: "Grand Marnier, Cruzan Coconut Rum, Blue Curacao, sour mix, and orange juice. Garnished with lemon, lime, and cherry.", subname: "$10.95" },
{ name: "LOL[emonade]", desc: "Absolute Citron, Triple Sec, muddled lemon and simple syrup, sour mix, and Sprite.", subname: "$9.95" }
];
var events = [
{ divider:"Upcoming Events" },
{ name: "Super Bowl Party", subname: "1/28" },
{ name: "Valentine's Singles Party", subname: "2/14" },
{ divider:"Weekly Events" },
{ name: "Hospitality Night", subname: "Monday" },
{ name: "Trivia Night", subname: "Tuesday" },
{ name: "Karaoke with Liam", subname: "Thursday" }
];
res.render('index', {
nav:[
{ name:"Home", title:"Clark's Bar and Grille", url:"home", icon:"home", module:"home", run:"startSlider", source:frontpageImages },
{ name:"Menu", url:"menu", icon:"cutlery", module:"list", source:menu },
{ name:"Drinks", url:"drinks", icon:"glass", module:"list", source:drinks },
{ name:"Events", url:"events", icon:"calendar", module:"list", source:events },
{ name:"Restaurant Info", title:"Restaurant Info", url:"business-info", icon:"info-circle", module:"business-info" },
{ name:"Instagram Feed", title:"Instagram", url:"instagram", icon:"instagram", module:"instagram", run:"startInstagram" },
{ name:"Like and Follow Us", title:"Social Media", url:"social-media", icon:"thumbs-up", module:"social-media-links" },
{ name:"Contact Clark's", title:"Contact Clark's", url:"contact", icon:"envelope", module:"contact" }
]
});
});
When the page renders now, I have the index.ejs loop the nav object and display each DIV (Home, Menu, Drinks, Events, etc). Each array within the nav object has a key called source which returns the objects for them listed above. The page renders perfectly, it's just not connected to a database. I would like to swap all that out with a DB connected version!
I hope this code will help you, that's the best I can suggest with what you provided:
function handleError(message, error) {
//Handle any error here, for example:
console.error(message, error);
res.send(500, message);
}
var responseContent = {
nav: [],
};
getBusiness(); //start fetching data
function getBusiness() {
var businessQuery = /*query to get element AppUrl=example.com*/;
businessQuery.first().then(
getNavigation,
handleError.bind(null, 'error getting business'));
}
function getNavigations(business) {
var navigationsQuery = /*query to get navigation elements*/;
var promises = [];
navigationsQuery.each(function (navigation) {
promises.push(processNavigation(navigation));
}).then(
function () {
Parse.Promise.when(promises).then(
renderResult,
handleError.bind(null, 'error processing navigations'));
},
handleError.bind(null, 'error iterating navigations'));
}
function processNavigation(navigation) {
var promise = Parse.Promise();
var nav = {
name: /*name*/,
url: /*url*/,
};
responseContent.nav.push(nav);
switch (/*module*/) {
case 'Home':
getPhotosContent(/*args*/).then(
function (source) {
nav.source = source;
promise.resolve();
},
function (error) {
promise.reject(error);
}
);
break;
//can do similar code for 'About Us', 'Menus', ...
default:
promise.resolve();
}
return promise;
}
function getPhotosContent(/*args*/) {
var promise = Parse.Promise();
var results = [];
var photosQuery = /*query to get photos*/;
photosQuery.each(function (photo) {
results.push(photo);
}).then(
function () {
promise.resolve(results);
}, function (error) {
promise.reject(error);
}
);
return promise;
}
function renderResult() {
res.render('index', responseContent);
}