Related
Desired Functionality: On selecting a checkbox, a span is created with an id & data attribute same as the checkbox and appended to a div. On clicking the 'x' on this span should uncheck the checkbox and remove the span as well.
Issue: On selecting the checkbox, an additional span with an 'undefined' label is created.
JSFIDDLE
var filtersApplied = [];
$('.ps-sidebar').on('change', 'input[type=checkbox]', function () {
var me = $(this);
console.log('me', me);
if (me.prop('checked') === true) {
filtersApplied.push([
...filtersApplied,
{ id: me.attr('id'), data: me.attr('data-filter-label') }
]);
} else {
filtersApplied = filtersApplied.map(function (item, index) {
return item.filter(function (i) {
return i.id !== item[index].id;
});
});
}
if (filtersApplied.length === 0) {
$('.ps-plans__filters').hide();
$('.ps-plans__filters-applied').html('');
} else {
$('.ps-plans__filters').show();
var filtersAppliedHtml = '';
filtersApplied.map(function (elements) {
console.log('items', elements);
return elements.map(function (el, i) {
console.log('item', el);
return (filtersAppliedHtml +=
'<span class="ps-plans__filter" id="' + el.id + '_' + i +'">' +el.data +
'<span class="icon-remove-circle remove-filter" data-filter="' +el.data +'"> X</span></span>');
});
});
console.log('filtersAppliedHtml', filtersAppliedHtml);
console.log($('.ps-plans__filters-applied').html(filtersAppliedHtml));
}
});
Your undefined label is because of the ...filtersApplied
if (me.prop('checked') === true) {
filtersApplied.push([
//this ...filtersApplied
{ id: me.attr('id'), data: me.attr('data-filter-label') }
]);
Note that filtersApplied is an array and you're making a push(), this method inserts a value in the end of the array, so your ...filtersApplied makes no sense. Just remove it and you'll be fine. You can se more here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
there are few thing that need to be fixed.
when adding an element you should not push filtersApplied along with new object. instead you better do arr = [...arr, obj];
when remove an item you could apply a filter instead based on me.attr('id'). with map you would get undefined values;
after that you would map only once to build your html content, not twice;
var filtersApplied = [];
$('.ps-sidebar').on('change', 'input[type=checkbox]', function () {
var me = $(this);
if (me.prop('checked') === true) {
filtersApplied = [
...filtersApplied,
{ id: me.attr('id'), data: me.attr('data-filter-label') }
];
} else {
filtersApplied = filtersApplied.filter(function (item, index) {
return me.attr('id') !== item.id;
});
}
if (filtersApplied.length === 0) {
$('.ps-plans__filters').hide();
$('.ps-plans__filters-applied').html('');
} else {
$('.ps-plans__filters').show();
var filtersAppliedHtml = '';
filtersApplied.map(function (el, i) {
return (filtersAppliedHtml +=
'<span class="ps-plans__filter" id="' +
el.id +
'_' +
i +
'">' +
el.data +
'<span class="icon-remove-circle remove-filter" data-filter="' +
el.data +
'"> X</span></span>');
});
$('.ps-plans__filters-applied').html(filtersAppliedHtml);
}
});
I am get where condition(value) from getcondition(req, Sequelize)
code is:
options.where = getcondition(req, Sequelize);
options.include = [{
model: hp_builders,
required: true
}, { .... },{ .... }]
hp_property.findAndCountAll(options, {
subQuery: false
}).then(function(result) {
res.json(result);
});
so for different requests .i have to assign different value in options.where = getcondition(req, Sequelize);
so how can i write in an effective manner for getcondition(req, Sequelize);
my getcondition(req, Sequelize) function code is:
function getcondition(req, Sequelize) {
var condition = JSON.parse(req.query.selector);
if (condition.hasOwnProperty("city_id")) {
if (condition.hasOwnProperty("Inhibition")){
console.log(JSON.stringify(condition));
return {
$and: [{
hp_city_id: condition.city_id
},
Sequelize.literal("`hp_property`.`hp_property_inhibition_status_id` IN (" + condition.Inhibition + ")"),
]
}
}
if (condition.hasOwnProperty("bedrooms") && condition.hasOwnProperty("budgetPrice")) {
var budgetPrice = condition.budgetPrice.split(",");
var minRange = budgetPrice[0];
var maxRange = budgetPrice[1];
return {
$and: [{
hp_city_id: condition.city_id
},
Sequelize.literal("`hp_unit_details`.`hp_unit_type_id` IN (" + condition.bedrooms + ")"),
Sequelize.literal("`hp_unit_details.hp_unit_prices`.`price_per_sqft` * `hp_unit_details`.`property_size` BETWEEN " + minRange + " AND " + maxRange)
]
}
}
if (condition.hasOwnProperty("bedrooms") && !condition.hasOwnProperty("budgetPrice")) {
return {
$and: [{
hp_city_id: condition.city_id
},
Sequelize.literal("`hp_unit_details`.`hp_unit_type_id` IN (" + condition.bedrooms + ")")
]
}
} else if (condition.hasOwnProperty("budgetPrice") && !condition.hasOwnProperty("bedrooms")) {
var budgetPrice = condition.budgetPrice.split(",");
var minRange = budgetPrice[0];
var maxRange = budgetPrice[1];
return {
$and: [{
hp_city_id: condition.city_id
},
Sequelize.literal("`hp_unit_details.hp_unit_prices`.`price_per_sqft` * `hp_unit_details`.`property_size` BETWEEN " + minRange + " AND " + maxRange)
]
}
}
return {
hp_city_id: condition.city_id
}
}
else if (condition.hasOwnProperty("id")) {
if (condition.hasOwnProperty("Inhibition")){
console.log(JSON.stringify(condition));
return {
$and: [{
hp_builders_id: condition.id
},
Sequelize.literal("`hp_property`.`hp_property_inhibition_status_id` IN (" + condition.Inhibition + ")"),
]
}
}
if (condition.hasOwnProperty("bedrooms") && condition.hasOwnProperty("budgetPrice")) {
var budgetPrice = condition.budgetPrice.split(",");
var minRange = budgetPrice[0];
var maxRange = budgetPrice[1];
return {
$and: [{
hp_builders_id: condition.id
},
Sequelize.literal("`hp_unit_details`.`hp_unit_type_id` IN (" + condition.bedrooms + ")"),
Sequelize.literal("`hp_unit_details.hp_unit_prices`.`price_per_sqft` * `hp_unit_details`.`property_size` BETWEEN " + minRange + " AND " + maxRange)
]
}
}
if (condition.hasOwnProperty("bedrooms") && !condition.hasOwnProperty("budgetPrice")) {
return {
$and: [{
hp_builders_id: condition.id
},
Sequelize.literal("`hp_unit_details`.`hp_unit_type_id` IN (" + condition.bedrooms + ")")
]
}
} else if (condition.hasOwnProperty("budgetPrice" && !condition.hasOwnProperty("bedrooms"))) {
var budgetPrice = condition.budgetPrice.split(",");
var minRange = budgetPrice[0];
var maxRange = budgetPrice[1];
return {
$and: [{
hp_builders_id: condition.id
},
Sequelize.literal("`hp_unit_details.hp_unit_prices`.`price_per_sqft` * `hp_unit_details`.`property_size` BETWEEN " + minRange + " AND " + maxRange)
]
}
}
return {
hp_builders_id: condition.id
}
} else if (condition.hasOwnProperty("location_id")) {
console.log(JSON.stringify(req.query.selector) + ".....");
return {
hp_location_id: condition.location_id
}
}
}
Split in function and store conditions and function pointer in an array
var conditions = [
{
keys: [
{"key": "id", required:true}
{"key": "price", required:false}
],
function: fn1
},
{
keys: [
{"key": "id", required:false}
{"key": "price", required:false}
],
function: fn2
}
];
function checkKey(obj, id, required)
{
if(required)
return obj.hasOwnProperty(id);
else
return !obj.hasOwnProperty(id);
}
function checkKeys(obj, keys)
{
var condition = true;
for(var i = 0; i < keys.length; i++)
{
condition &= checkKey(obj, keys[i].key, keys[i].required);
}
return condition;
}
for(var i = 0; i < conditions.length; i++)
{
if(checkKeys(obj, conditions[i].keys))
return conditions[i].function(obj);
}
There are awesome JavaScript switch Statements. Use them when you have such terrible conditions.
UPD: Example of using switch:
function getcondition(req, Sequelize) {
const condition = JSON.parse(req.query.selector);
switch (true) {
case (condition.hasOwnProperty('city_id')): {
// ...
}
case (condition.hasOwnProperty('id')): {
// ...
}
case (condition.hasOwnProperty('location_id')): {
// ...
}
}
}
Note that the switch-case will break at the first occurance of any true statement. So, be careful while using break and return statements.
Using switch statements could actually help but in your case most conditions are too complicated. For syntax, follow this link : W3Schools javascript switch
What you could do in term of good practices would be creating sub_functions called in each condition. You can also gather a few tasks in your sub-functions and add if statements. This will lighten your function.
In term of good practices however, your sub-functions should not be redundant, try and choose carefully so that each function you write has a different purpose than the others.
EDIT : I previously said that your function should only have one return statement. This is not entirely true, as this convention can sometime make the code less easy to understand. That being said, it is a question of personal taste. A good compromise would be to put a return statement at the beginning of the function for error cases, and use another return statement at the end for classic result return.
You could also use pattern matching. See this link : Pattern matching with javascript.
i tried like this but i want more less and good code,plase give some other corrections
function getcondition1(req, Sequelize) {
var condition = JSON.parse(req.query.selector);
if (condition.hasOwnProperty("city_id")) {
return comparison(condition,"city_id","hp_city_id");
}
else if (condition.hasOwnProperty("id")) {
return comparison(condition,"id","hp_builders_id");
}
else if (condition.hasOwnProperty("location_id")) {
return comparison(condition,"location_id","hp_location_id");
}
}
function comparison(condition,id,dbId){
var obj={};
var andCondition=[];
var subCondition={};
if (condition.hasOwnProperty("Inhibition")){
subCondition[dbId]=condition.id;
andCondition.push(subCondition,Sequelize.literal("`hp_property`.`hp_property_inhibition_status_id` IN (" + condition.Inhibition + ")"));
obj['$and']=andCondition;
return obj;
}
if (condition.hasOwnProperty("bedrooms") && condition.hasOwnProperty("budgetPrice")) {
var budgetPrice = condition.budgetPrice.split(",");
var minRange = budgetPrice[0];
var maxRange = budgetPrice[1];
subCondition[dbId]=condition.id;
andCondition.push(subCondition,Sequelize.literal("`hp_unit_details`.`hp_unit_type_id` IN (" + condition.bedrooms + ")"),Sequelize.literal("`hp_unit_details.hp_unit_prices`.`price_per_sqft` * `hp_unit_details`.`property_size` BETWEEN " + minRange + " AND " + maxRange));
obj['$and']=andCondition;
return obj;
}
if (condition.hasOwnProperty("bedrooms") && !condition.hasOwnProperty("budgetPrice")) {
subCondition[dbId]=condition.id;
andCondition.push(subCondition,Sequelize.literal("`hp_unit_details`.`hp_unit_type_id` IN (" + condition.bedrooms + ")"))
obj['$and']=andCondition;
return obj;
} else if (condition.hasOwnProperty("budgetPrice") && !condition.hasOwnProperty("bedrooms")) {
var budgetPrice = condition.budgetPrice.split(",");
var minRange = budgetPrice[0];
var maxRange = budgetPrice[1];
subCondition[dbId]=condition.id;
andCondition.push(subCondition,Sequelize.literal("`hp_unit_details.hp_unit_prices`.`price_per_sqft` * `hp_unit_details`.`property_size` BETWEEN " + minRange + " AND " + maxRange))
obj['$and']=andCondition;
return obj;
}
obj[dbId] =condition.id
return obj;
}
What i'm trying to accomplish is to loop through this JSON, and compare the "start_time" and "end_time" to ensure the times don't overlap. I'm having trouble implementing this.
I found this: validate two times but none of it makes any sense nor is it using JSON but it's the closest i've found. Could I use jQuery to do this?
{
"Line_1":{
"artist":"Audien",
"day":"1",
"start_time":"13:00",
"end_time":"14:00",
"stage":"main"
},
"Line_2":{
"artist":"Slushii",
"day":"1",
"start_time":"13:30",
"end_time":"14:30",
"stage":"eclipse"
},
"Line_3":{
"artist":"DJ Snake",
"day":"1",
"start_time":"15:00",
"end_time":"16:00",
"stage":"main"
},
"Line_4":{
"artist":"Marshmello",
"day":"2",
"start_time":"14:15",
"end_time":"15:15",
"stage":"horizon"
}
}
Expected output:
Audien & Slushii Conflict!
DJ Snake Does not Conflict with anyone!
Marshmello Does not Conflict with anyone!
*Notice Days 1 & 2
Here is a rather verbose prototype for your learning purposes. It uses moment.js and twix.js.
Demo: https://jsfiddle.net/JAAulde/5v7yksk3/4/
HTML for prototype code:
<ul id="output"></ul>
JS for prototye code
var data = {
"Line_1":{
"artist":"Audien",
"day":"1",
"start_time":"13:00",
"end_time":"14:00",
"stage":"main"
},
"Line_2":{
"artist":"Slushii",
"day":"1",
"start_time":"13:30",
"end_time":"14:30",
"stage":"eclipse"
},
"Line_3":{
"artist":"DJ Snake",
"day":"1",
"start_time":"15:00",
"end_time":"16:00",
"stage":"main"
},
"Line_4":{
"artist":"Marshmello",
"day":"2",
"start_time":"14:15",
"end_time":"15:15",
"stage":"horizon"
}
},
tmp_day = '2000-01-01',
outer_key,
outer,
inner_key,
inner,
tmp_range,
checked = {},
conflict_found = {},
conflicts = [],
i;
for (outer_key in data) {
if (Object.prototype.hasOwnProperty.call(data, outer_key)) {
outer = data[outer_key];
tmp_range = moment(tmp_day + 'T' + outer.start_time).twix(tmp_day + 'T' + outer.end_time);
checked[outer_key] = true;
for (inner_key in data) {
if (Object.prototype.hasOwnProperty.call(data, inner_key) &&
outer_key !== inner_key &&
!checked[inner_key]
) {
inner = data[inner_key];
if (outer.day === inner.day &&
(
tmp_range.contains(tmp_day + 'T' + inner.start_time) ||
tmp_range.contains(tmp_day + 'T' + inner.end_time)
)
) {
conflict_found[outer_key] = true;
conflict_found[inner_key] = true;
conflicts.push([
outer_key,
inner_key
]);
}
}
}
}
}
// Output:
document.getElementById('output').innerHTML = '';
for (i = 0; i < conflicts.length; i++) {
document.getElementById('output').innerHTML += '<li><strong>' + data[conflicts[i][0]].artist + '</strong> conflicts with <strong>' + data[conflicts[i][1]].artist + '</strong></li>';
}
for (outer_key in data) {
if (Object.prototype.hasOwnProperty.call(data, outer_key) &&
!conflict_found[outer_key]
) {
document.getElementById('output').innerHTML += '<li><strong>' + data[outer_key].artist + '</strong> does not conflict with anyone</li>';
}
}
My solution:
var json = {
"Line_1":{
"artist":"Audien",
"day":"1",
"start_time":"13:00",
"end_time":"14:00",
"stage":"main"
},
"Line_2":{
"artist":"Slushii",
"day":"1","start_time":"13:30",
"end_time":"14:30",
"stage":"eclipse"
},
"Line_3":{
"artist":"DJ Snake",
"day":"1",
"start_time":"15:00",
"end_time":"16:00",
"stage":"main"
},
"Line_4":{
"artist":"Marshmello",
"day":"2",
"start_time":"17:15",
"end_time":"15:15",
"stage":"horizon"
}
};
function timeToDate(timeStr) {
var whateverDate = '01/01/1980 ';
return Date.parse(whateverDate + timeStr);
}
for (item in json) {
var st = json[item].start_time;
var et = json[item].end_time;
var datesCorrect = (timeToDate(st) < timeToDate(et)) ? 'true' : 'false';
console.log(item + ' dates correct: ' + datesCorrect);
};
Demo: https://jsfiddle.net/dhf89twr/1/
I'm working on a project to open up custom dialogue boxes.
I'm trying to make it so in the settings object, you can specify the custom buttons' names as the names of objects, with the button's info inside. I am wondering, how do I get the name of the buttons' names?
My current code that I have is this:
function resetTools() {
Dialogue.open({
message: "Are you sure you want to reset all chat rooms?",
buttons: {
yes: {
styleSheetClass: "dangerbtn",
onclick: function() {
// Do stuff here
}
},
no: {
onclick: function() {
// Do other stuff here
}
}
}
})
}
var Dialogue = {
open: function(settings) {
var message = settings.message;
var buttons = message.buttons;
for (var i = 0; i < buttons.length; i++) {
var cls = buttons[i].styleSheetClass.length ? buttons[i].styleSheetClass + " dialogueButton" : "dialogueButton";
$(".dialogue .buttons").append('<div class="' + cls + '">' + +'</div>');
}
}
}
Thanks for any help.
You can use a for...in loop to get an object's keys, and remember to use hasOwnProperty to test for a property's existence
for (var key in buttons) {
if (buttons.hasOwnProperty(key)) {
// key could be 'yes' or 'no'
// access the value using buttons[key]
}
}
Or you can use Object.keys which is introduced in es5.1
Object.keys(buttons).forEach(function(key) {
// do something with buttons[key]
})
There are two mistakes...
First is
var buttons = message.buttons;
Which will make the buttons to be undefined.
It should be
var buttons = settings.buttons;
Next, since your buttons is an object you will need a for..in loop to extract key names..
So at the end of the day your code should look
var Dialogue = {
open: function(settings) {
var message = settings.message;
var buttons = settings.buttons; // <<<< NOTE: It's settings.buttons.
for (var button in buttons) {
console.log(button); // This will give you yes in 1st iteration and no in 2nd.
var cls = buttons[button].styleSheetClass.length ? buttons[button].styleSheetClass + " dialogueButton" : "dialogueButton";
$(".dialogue .buttons").append('<div class="' + cls + '">' + +'</div>');
}
}
}
Object.keys(buttons).forEach(function (name) {
var button = buttons[name];
// now you have both
});
You've got a problem on line 24 (25 in this snippet). You're using buttons as if it were an array.
function resetTools() {
Dialogue.open({
message: "Are you sure you want to reset all chat rooms?",
buttons: {
yes: {
styleSheetClass: "dangerbtn",
onclick: function() {
// Do stuff here
}
},
no: {
onclick: function() {
// Do other stuff here
}
}
}
})
}
var Dialogue = {
open: function(settings) {
var message = settings.message;
var buttons = settings.buttons;
// vvv buttons isn't an array, it's an object
for (var i = 0; i < buttons.length; i++) {
var cls = buttons[i].styleSheetClass.length ? buttons[i].styleSheetClass + " dialogueButton" : "dialogueButton";
$(".dialogue .buttons").append('<div class="' + cls + '">' + +'</div>');
}
}
}
Here's a fix:
function resetTools() {
Dialogue.open({
message: "Are you sure you want to reset all chat rooms?",
buttons: [
{
name: 'Yes',
styleSheetClass: "dangerbtn",
onclick: function() {
// Do stuff here
}
}, {
name: 'No',
onclick: function() {
// Do stuff here
}
},
]
})
}
var Dialogue = {
open: function(settings) {
var message = settings.message;
var buttons = message.buttons;
for (var i = 0; i < buttons.length; i++) {
var cls = buttons[i].styleSheetClass != undefined ? buttons[i].styleSheetClass + " dialogueButton" : "dialogueButton";
$(".dialogue .buttons").append('<div class="' + cls + '">' + buttons[i].name +'</div>');
}
}
}
I've tweaked the object that the dialogue is opened with to have buttons as an array with the name as a property of each object in the array.
Try using Object.keys() on settings.button.yes
var Dialogue = {
open: function(settings) {
var message = settings.message;
var buttons = setting.buttons.yes;
Object.keys(buttons).forEach(function(button) {
if (button === "styleSheetClass") {
var cls = buttons[button].length
? buttons[button] + " dialogueButton"
: "dialogueButton";
$(".dialogue .buttons")
.append('<div class="' + cls + '">' + +'</div>');
}
})
}
}
You can use jQuery and do it like this:
$.each(buttons, function(button_name, button) {
// code ...
});
Or without jQuery:
var keys = Object.keys(buttons);
for(var i = 0; i < keys.length; i++) {
var button_name = keys[i];
var button = buttons[button_name];
// code ...
}
Object.keys gives you names of elements in this object.
You can use console.log(Object.keys(buttons)) to preview it.
I'm trying to figure out how to make a function that adds the values of the elements chosen by the user and be able to display the results via prompt and console.log. Also, I'm wondering if there is a way to do it in which I don't need to specify the elements selected in order for the function to find within the code which elements were selected and execute the addition function. Because obviously if the list of options were longer I wouldn't want to have to make a new function for each potential combination of selections. As a side note, I guess the same problem would apply to the if statements, would switch statements be the most efficient way to tackle needs for "DRY" code in that instance?
My javascript code: Please assume that the user selects only the first elements of the nested arrays. Also, that term "one" is worth $8.
var selection = new Array (3);
selection[0] = new Array ('$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8');
selection[1] = new Array ('phone1', 'phone2', 'phone3');
selection[2] = new Array ('one', 'two', 'three');
function pickPhone () {
var yourPhone = prompt("pick phone: phone1: $1, phone2: $2, phone3: $3");
if (yourPhone == selection[1][0]) {
console.log(selection[1][0] + " will cost: " + selection[0][0]);
alert(selection[1][0] + " will cost: " + selection[0][0]);
pickTerm ();
} if (yourPhone == "phone2") {
alert(selection[1][1] + " will cost: " + selection[0][1]);
} if (yourPhone == "phone3") {
alert(selection[1][2] + " will cost: " + selection[0][2]);
}
}
function pickTerm () {
var yourTerm = prompt("pick term: one, two or three?");
if (yourTerm == selection[2][0]) {
alert("Your total so far is: ??");
}
}
pickPhone ();
Any help is greatly appreciated, thank you.
A solution that keeps your arrays
http://jsfiddle.net/OxyDesign/o10ezyun/
JS
var selection = new Array(3);
selection[0] = new Array(1,2,3,4,5,6,7,8);
selection[1] = new Array('phone1', 'phone2', 'phone3');
selection[2] = new Array('one', 'two', 'three');
var firstValue;
function pickPhone() {
var yourPhone = prompt("pick phone: phone1: $1, phone2: $2, phone3: $3"),
index = selection[1].indexOf(yourPhone);
if(!~index){
pickPhone();
}else{
firstValue = selection[0][index];
alert(selection[1][index] + " will cost: $" + firstValue);
pickTerm();
}
}
function pickTerm() {
var yourTerm = prompt("pick term: one, two or three?"),
index = selection[2].indexOf(yourTerm),
finalValue = '$'+(firstValue+selection[0][index]);
if(!~index){
pickTerm();
}else{
alert("Your total so far is: "+finalValue);
}
}
pickPhone();
I'am not sure what problem you are actually solving.
How long these lists are (phones, costs, etc)?
What type of mapping is set for those items?
For now I'd recommend to merge corresponding values in objects like this:
// item -> cost
var phones = [
{title: 'phone1', cost: '$1'},
{title: 'phone2', cost: '$2'},
{title: 'phone3', cost: '$3'}
],
terms = [
{title: 'one', cost: '$8'},
{title: 'two', cost: '$2'},
{title: 'three', cost: '$3'}
],
phonesListWithCosts = (function(list) {
return list.reduce(function(memo, item) {
return memo + item.title + ': ' + item.cost;
}, '');
}(phones)),
termsList = (function(list) {
return list.reduce(function(memo, item) {
return memo + ', ' + item.title;
}, '');
}(terms)),
findBy = function(array, property, value) {
return array.filter(function(item) {
return item[property] === value;
})[0];
},
getItem = function(list, promptMessage) {
var selectedItemTitle = prompt(promptMessage);
return findBy(list, 'title', selectedItemTitle);
},
getItemCost = function(item) {
return parseInt(item.cost.replace(/\D/g, ''), 10);
},
pickPhone = function() {
var selectedPhone = getItem(phones, 'pick phone: ' + phonesListWithCosts),
firstPhone = phones[0],
message;
if (selectedPhone) {
message = [selectedPhone.title, 'will cost:', selectedPhone.cost].join(' ');
console.log(message);
alert(message);
if (selectedPhone === firstPhone) {
pickTerm(getItemCost(selectedPhone));
}
}
},
pickTerm = function(accumCost) {
var selectedTerm = getItem(terms, 'pick term: ' + termsList),
totalCost,
message;
if (selectedTerm) {
totalCost = accumCost + getItemCost(selectedTerm);
message = 'Your total so far is: $' + totalCost;
alert(message);
}
};
pickPhone();
jsbin demo.