Simplifying a messy jQuery function [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 10 months ago.
Improve this question
JS newb here. I'm incorporating the code below into a backstretch slider, with the aim of including small text arrays with each rotation of a carousel. It's all working as planned, only it's not very clean code at all. I'm just wondering if someone knows how to go about neatening this up? Thanks a lot!
jQuery(document).ready(function ($) {
var items = [{
img: "/i/photos/Gallery/home/010.jpg",
name: "Name 1",
title: "Title 1",
desc: "Description 1.",
caption: "Read More",
link: "#"
},
{
img: "/i/photos/Gallery/home/020.jpg",
name2: "Name 1",
title2: "Title 1",
desc2: "Description 1.",
caption2: "Read More",
link2: "#"
},
{
img: "/i/photos/Gallery/home/030.jpg",
name3: "Name 1",
title3: "Title 1",
desc3: "Description 1.",
caption3: "Read More",
link3: "#"
}
];
var options = {
fade: 800,
duration: 7000
};
var images = $.map(items, function (i) {
return i.img;
});
var slideshow = $("#slider").backstretch(images, options);
$(window).on("backstretch.show", function (e, instance) {
var theName = items[instance.index].name;
var theTitle = items[instance.index].title;
var theDesc = items[instance.index].desc;
var theCaption = items[instance.index].caption;
var theLink = items[instance.index].link;
var theName2 = items[instance.index].name2;
var theTitle2 = items[instance.index].title2;
var theDesc2 = items[instance.index].desc2;
var theCaption2 = items[instance.index].caption2;
var theLink2 = items[instance.index].link2;
var theName3 = items[instance.index].name3;
var theTitle3 = items[instance.index].title3;
var theDesc3 = items[instance.index].desc3;
var theCaption3 = items[instance.index].caption3;
var theLink3 = items[instance.index].link3;
if (theLink) {
$(".backstretch-caption").html(
'<h1 class="bs-name">' + theName + '</h1>' +
'<h2 class="bs-title">' + theTitle + '</h2>' +
'<p class="bs-desc">' + theDesc + '</p>' +
'<a class="bs-link" href="' + theLink + '">' + theCaption + '</a>')
.show();
}
if (theLink2) {
$(".backstretch-caption").html(
'<h1 class="bs-name">' + theName2 + '</h1>' +
'<h2 class="bs-title">' + theTitle2 + '</h2>' +
'<p class="bs-desc">' + theDesc2 + '</p>' +
'<a class="bs-link" href="' + theLink2 + '">' + theCaption2 + '</a>')
.show();
}
if (theLink3) {
$(".backstretch-caption").html(
'<h1 class="bs-name">' + theName3 + '</h1>' +
'<h2 class="bs-title">' + theTitle3 + '</h2>' +
'<p class="bs-desc">' + theDesc3 + '</p>' +
'<a class="bs-link" href="' + theLink3 + '">' + theCaption3 + '</a>')
.show();
}
});
});

The most important change to make here is to remove the incremental property names in the objects in your array; use the same property name in each object. Then your code dealing with that array can be simplified as the property names are static.
You can also make the syntax a little less verbose by storing a reference to items[instance.index] in a variable to reuse, and also by using template literals to build your HTML. The latter could be made even more simple by including the HTML in the page on load, and hiding/updating/showing the relevant text labels as necessary - I'll leave that as an exercise for the OP to implement if desired though.
var items = [
{ img: "/i/photos/Gallery/home/010.jpg", name: "Name 1", title: "Title 1", desc: "Description 1.", caption: "Read More", link: "#" },
{ img: "/i/photos/Gallery/home/020.jpg", name: "Name 1", title: "Title 1", desc: "Description 1.", caption: "Read More", link: "#" },
{ img: "/i/photos/Gallery/home/030.jpg", name: "Name 1", title: "Title 1", desc: "Description 1.", caption: "Read More", link: "#" }
];
jQuery($ => {
var images = items.map(item => item.img);
var slideshow = $("#slider").backstretch(images, {
fade: 800,
duration: 7000
});
$(window).on("backstretch.show", function (e, instance) {
let item = items[instance.index];
if (item.link) {
$(".backstretch-caption").html(`
<h1 class="bs-name">${item.name}</h1>
<h2 class="bs-title">${item.title}</h2>
<p class="bs-desc">${item.desc}</p>
<a class="bs-link" href="${item.link}">${item.caption}</a>`)
.show();
}
});
});
Finally, be wary of using the Backstretch library. It hasn't had a meaningful update since 2017 and seems very outdated. In fact, it's now possible to do what that library does using CSS, such as using vw/vh units for fonts and various other techniques for background imagery.

Related

.Animate() on dynamically generated content

I am creating a website where I append progress-bar to div from JSON file.
Everything is working fine, but I can't figure out how to animate all progress-bar with their own value.
These values are loaded from the JSON file and I am only able to animate them all to one value not to their own one.
Code :
$.getJSON( "skills.json", function(data){
Skills = data;
$.each(Skills, function (title, val) {
var markup = "<div class='progress-item'>";
markup += "<span class='progress-title'>" + val.title + "</span>";
markup += "<div class='progress'>";
markup += "<div class='progress-bar'" + "style=width:" + val.value + "%" + ">" + "<span class='progress-percent'>" + val.value + "%" + "</span></div>";
markup += "</div>";
markup += "</div>";
$('.progress-wrapper').append(markup);
});
});
So this generates 3 progress-bar cause I have 3 values in my JSON file.
I tried something like :
$(".progress-bar").animate({width: val.value +"%"});
But it change the width of all my progress-bar even if they got all different in the JSON object.
JSON file :
[{
"title": "Skill 1",
"description": "Skill 1 description",
"value": 100
},
{
"title": "Skill 2",
"description": "Skill 2 description",
"value": 50
}
]
Thanks in advance for the help

Javascript - Unable to display UL, instead get [object HTMLUListElement]

I asked a question a day ago about getting the length of an array that was nested inside an array that was inside an object. Now that I am able to get the correct information to console, I am getting the following in place of where the text should be:
[object HTMLUListElement]
Here is the code I am working with (please keep in mind I have been scouring the forums for answers, so there may be some code that is left over from different recommendations that is useless):
var experience = document.getElementById('experience');
var entryDescriptions = document.createElement('ul');
for (i = 0; i < resumeData.experience.length; i++) {
var experienceEntryDiv = document.createElement('div');
experienceEntryDiv.className = "experienceEntryDiv";
var entryTitle = '<h1>' + resumeData.experience[i].title + '</h1>';
var entryOrganization = '<h2>' + resumeData.experience[i].organization + '</h2>';
var entryYears = '<h1 class="text-right"><small>' + resumeData.experience[i].startYear + ' - ' + resumeData.experience[i].endYear + '</small></h1>';
for (j = 0; j < resumeData.experience[i].descriptions.length; j++) {
descriptionCounts = resumeData.experience[i].descriptions.length;
console.log(descriptionCounts);
var entryDescItem = document.createElement('li');
entryDescItem.className = "entryDescItem";
var entrydesc = document.createTextNode(resumeData.experience[i].descriptions[j]);
entryDescItem.appendChild(entrydesc);
entryDescriptions.appendChild(entryDescItem);
}
var entryHTML =
'<div class="entry">' +
'<div class="row">' +
'<div class="col-md-9">' + entryTitle + entryOrganization + '</div>' +
'<div class="col-md-3">' + entryYears + '</div>' +
'</div>' +
'<div class="row"><ul>' + entryDescriptions + '</ul><hr /></div>' +
'</div>' +
'<br />';
experienceEntryDiv.innerHTML = entryHTML;
experience.appendChild(experienceEntryDiv);
}
Here is my data (there is more data, I am just showing an example):
var resumeData = {
experience: [{
title: 'Title',
organization: 'Company Name',
startYear: 2017,
endYear: 2017,
descriptions: [
'Using code stuff',
'Used more code stuff'
]
},
{
title: 'Title',
organization: 'Company Name',
startYear: 2017,
endYear: 2017,
descriptions: [
'Using code stuff',
'Used more code stuff'
]
},
{
title: 'Title',
organization: 'Company Name',
startYear: 2017,
endYear: 2017,
descriptions: [
'Using code stuff',
'Used more code stuff'
]
},
{
title: 'Title',
organization: 'Company Name',
startYear: 2017,
endYear: 2017,
descriptions: [
'Using code stuff',
'Used more code stuff'
]
}
]
}
Originally, I was trying to figure out how to get the length in the second FOR loop. That got worked out, but now when I pull up the page, I get the Title, Organization, start and end years, but for descriptions I get:
[object HTMLUListElement]
Thanks!
I would recommend using either all dom node creation (like the first part of your code) or all string concatenation (like the second part).
A quick (and VERY DIRTY, imo) workaround, would be:
...<ul>'+entryDescriptions.innerHTML+'</ul>...
You're concatenating (adding) a string with a DOM Object.
var entryHTML =
'<div class="entry">' +
'<div class="row">' +
'<div class="col-md-9">' + entryTitle + entryOrganization + '</div>' +
'<div class="col-md-3">' + entryYears + '</div>' +
'</div>' +
'<div class="row"><ul>' + entryDescriptions + '</ul><hr /></div>' + //<--HERE
'</div>' +
'<br />';
You can either pull the text out of the object using Javascript, or update the page with entryHTML, then use Javascript to append the object entryDescriptions

How to format a text in a mailto function

I have two arrays and an object. One array conatins product codes, and another contains the quantities thereof. For example, the first quantity in the quantities array is the quantity of the product code that is the first one in the product code array. I also have an object that contains customer data. It would look something like this:
customer={
name:' firstname lastname',
email: 'example#domain.com',
company: "company name",
phone_number: 'phone number',
}
the arrays would look like this:
product_codes=[code_1; code_2; code_3];
quantities=[23, 56, 45];
Say that all of this is being mailed to customersupport#example.com.
I am familiar with the basics of the mailto function, but I would like to know if there is a way to format the body of the email so that it looks something like this:
...................................
Name: customer.name
email: customer.email
company name: customer.company
phone number: customer.phone_number
product code 1: corresponding quantity
product code 2: corresponding quantity
product code 3: corresponding quantity
...............................................
I would also like to be able to add any other given codes and quantities, as I am not sure of how many there will be. Is this even possible? If so, how? Please explain so that I can not only use it, but also understand how it works. Thanks!
If I'm not being clear enough, please let me know so I can edit it for greater clarity.
var sendEmail = function() {
var customer, body, quantities, product_codes;
customer = {
name: 'First Last',
email: 'example#example.com',
company: 'Company',
phone_number: 'phone number',
}
body = 'Name: '+ customer.name;
body += '\nEmail: '+ customer.email;
body += '\nCompany: '+ customer.company;
body += '\nPhone Number: '+ customer.phone_number;
product_codes = ['code_1', 'code_2', 'code_3'];
quantities = [23, 56, 45];
for(var i = 0; i < product_codes.length; i += 1) {
body += '\nProduct Code '+ product_codes[i] +': '+ quantities[i];
}
subject = 'Your Subject';
window.location = 'mailto:customersupport#example.com?body='+ encodeURIComponent(body) +'&subject='+ encodeURIComponent(subject);
};
// execute this function when the user clicks the #send-email button
var button = document.getElementById('send-email');
button.addEventListener('click', sendEmail);
I would build the string in a function:
HTML:
Click to Email
JAVASCRIPT:
//stuff you specified...
var customer={
name:' firstname lastname',
email: 'example#domain.com',
company: "company name",
phone_number: 'phone number',
}
var product_codes=['alpha', 'beta', 'gamma'];
var quantities=[23, 56, 45];
/* Assign a click action onto the link */
var yourLink = document.getElementById("thelink");
yourLink.onclick = function() {
var elf = "%0A"; //Encoded Line Feed
mailtoBody = "Name: " + customer.name + elf
+ "Email: " + customer.email + elf
+ "Company Name: " + customer.company + elf
+ "Phone Number: " + customer.phone_number + elf;
for (var i=0; i < product_codes.length; i++) {
mailtoBody += product_codes[i] + ": " + quantities[i] + elf;
}
location.href = "mailto:you#example.com?body=" + mailtoBody;
}
Here's a working example:
http://jsbin.com/kigutuhiqa/edit?html,js,output
It sounds to me like you want to construct the body of a message. If this is the case, you can create a function that builds the body of your message by taking in the 3 objects you mentioned: customer, codes, and quantity.
For example, you can do something like
function buildBody(cust, codes, quant){
var body = "";
body += "Name: " + cust.name + "\n";
body += "Email: " + cust.email + "\n";
body += "Company Name: " + cust.companyname + "\n";
for(var i=0; i<codes.length; ++i)
body += "Product Code " + codes[i] + ": " quant[i] + "\n";
return body;
}
I have not tested this code, but hopefully you get the idea.

Bootstrap jQuery Calendar

I've found an awesome open source calendar at http://bootstrap-calendar.azurewebsites.net/index-bs3.html
I'm trying to load this project as described [link removed]
As in the demo, there is a dynamic list on the side of the calendar that does update with the events as you scroll through. How ever unlike the demo, my events are not getting listed in the calendar view. They don't show up on the calendar! :(
I did add a couple extra json data options, but the required ones weren't changed. Here's an example of my json data:
{
"success": 1,
"result": [{
"id": "########",
"title": "Event NAme",
"start_time": "2014-08-23T18:30:00-0500",
"start": "1408836600",
"end_time": "",
"end": "0",
"class": "event-info",
"url": "http://..."
}]
}
I don't think it's a bug, but not sure why it's not working as expected.
Their code:
onAfterEventsLoad: function(events) {
if(!events) {
return;
}
var list = $('#eventlist');
list.html('');
$.each(events, function(key, val) {
$(document.createElement('li'))
.html('' + val.title + '')
.appendTo(list);
});
},
My code:
'onAfterEventsLoad': function(events) {
if(!events) {
return;
}
var list = $('#eventlist');
list.html('');
$.each(events, function(key, val) {
var d = new Date(val.start_time),
date = weekday[d.getDay()] + ", " + monthNames[d.getMonth()] + " " + d.getDate() + ", " + d.getYear();
$(document.createElement('li'))
.html('<a title="' + date + '" href="' + val.url + '">' + val.title + '</a><br/><small>' + jQuery.timeago(d) + '</small>')
.appendTo(list);
});
},
The url you are trying to load events from is simply returning {"success":1} and not any events for the onAfterEventsLoad handler to iterate through.
This is the cause of your problem, the calendar code is all working fine as far as I can see.

JSON Loop through nested array

This is my JS ("data" is from the json call):
if (data.projectReports.length) {
for (var i in data.projectReports){
var report = data.projectReports[i];
$('#reports').append(
'<div class="report-description">' +
'<h2>' + report.header + '</h2>' +
'<p>' + report.text + '</p>' +
'</div>' +
'<ul class=\"report-moreinfo\">' +
// I want to loop through "persons" here.
'</ul>'
);
}
} else
. . .
This is my JSON:
{
"projectReports":[
{
"header":"Headline",
"text":"Description of item",
"estimate":10,
"actual":7,
"persons":{
"Robert":5,
"Erik":10,
"Juan":3
}
}
]
}
I am new to JSON and after searching for an answer and actually finding a few different answers, new problems arose so I thought I would post the question in it's entirety here.
Where the comment is in my JavaScript code, I want to loop through report.persons.
In all of the solutions I found they could point directly to "header" or "text" like I have done before, but in this case I just have a key and value. How would I go about doing something like this?
<li><p> persons.key </p><p> persons.value </p></li>
I understand that I will have to do another for loop, but my knowledge isn't good enough to be able to figure out on my own how to construct it.
This is pretty basic stuff
var personsMarkup = "";
for (var i in persons){
if (persons.hasOwnProperty(i)){
console.log(i); // the key
console.log(persons[i]); // the value
// cancat this all together
personsMarkup =+ "<li><p>"+i+"</p><p>"+persons[i]+"</p></li>";
}
}
and then:
$('#reports').append(
/* ... */
'<ul class=\"report-moreinfo\">' +
personsMarkup +
'</ul>';
/* ... */
);
For your code I'd use a function that loops through reports.persons and returns what you need:
var showPersons = function(persons){
var appendedData = '';
for (var person in persons) {
if (!persons.hasOwnProperty(person)) continue;
appendedData += '<li><p>' + person + '</p><p>' + persons[person] +'</p></li>'
}
return appendedData;
};
And now you can use this to append all that stuff inside the <ul> tags:
listPersons(report.persons);
If you wanted the code read closer to what you wanted (and to be able to use person.name and person.value), you'd need to have the JSON in this format:
{
"projectReports": [
{
"header": "Headline",
"text": "Description of item",
"estimate": 10,
"actual": 7,
"persons": [
{
"name": "Robert",
"value": 5
},
{
"name": "Erik",
"value": 10
},
{
"name": "Juan",
"value": 3
}
]
}
]
}
Use for (.. in ..)
$('#reports').append(
'<div class="report-description">' +
'<h2>' + report.header + '</h2>' +
'<p>' + report.text + '</p>' +
'</div>' +
'<ul class=\"report-moreinfo\">');
for (var personKey in report.persons){
$('#reports').append('<li><p>' + personKey + '</p><p>' + report.persons[personKey] + '</p></li>');
}
$('#reports').append(
'</ul>'
);

Categories

Resources