Not able to nest divs elemnets using JQUERY - javascript

In the starred code is the nested div elements, I have read XML file which has news articles. I want to read and add those to this nested format using jquery.
<div id="for-you-feed" class="container" style="justify-content: center;">
<div class="row view-group " id="rowview">
**
<div class="item grid-group-item col-xs-4 col-lg-4 col-md-6 col-sm-12">
<div class=" thumbnail card border-light" style="width: 20rem; ">
<div class="img-event ">
<img class="group list-group-image img-fluid " src="https://timesofindia.indiatimes.com/photo/74745223.cms " alt=" " />
</div>
<div class="caption card-body ">
<h4 class="group card-title inner list-group-item-heading ">
Hyderabad: Buses with same number plates seized</h4>
<p class="group inner list-group-item-text ">
The transport authorities, under the guidance of deputy transport commissioner Papa Rao, seized four buses that belo</p>
<div class="row ">
<div id="footer1" class="col-xs-12 col-md-6 ">
<p class="lead ">
$21.000</p>
</div>
<div id="footer2" class="col-xs-12 col-md-6 ">
<a class="btn btn-success " href="http://www.jquery2dotnet.com ">Add to cart</a>
</div>
</div>
</div>
</div>
</div>
**
</div>
My code of jquery is below
$(document).ready(function() {
$.get("https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Ftimesofindia.indiatimes.com%2Frssfeeds%2F-2128816011.cms&api_key=mkzfaqsb5gtninv1pddoke81vwmjlyfiissiitvd", function(data, status) {
//$("#rowview").empty();
for (i in data.items) {
console.log(data.items[i].thumbnail);
console.log(data.items[i].title);
console.log(data.items[i].link);
console.log(data.items[i].description);
console.log(data.items[i].description.slice(pos + 4));
var pos = data.items[i].description.indexOf("</a>"),
$divitem = $("</div>").attr('class', 'item grid-group-item col-xs-4 col-lg-4 col-md-6 col-sm-12');
var $divthumb = $("</div>").attr({ "class": 'thumbnail card border-light', style: 'width: 20rem' }),
$divimg = $("</div>").attr('class', 'img-event '),
$imggrp = $("</img>").attr({ "class": 'group list-group-image img-fluid ', src: data.items[i].thumbnail }),
$divcaption = $("</div>").attr('class', 'caption card-body'),
$headcard = $("</h4>").text(data.items[i].title).attr('class', 'group card-title inner list-group-item-heading'),
$paracard = $("</p>").attr('class', 'group inner list-group-item-text').text(data.items[i].description.slice(pos + 4)),
$divrow = $("</div>").attr('class', 'row'),
$divfooter1 = $("</div>").attr({ "class": 'col-xs-12 col-md-6', id: 'footer1' }),
$lead = $("</p>").attr('class', 'lead').text('$21.000'),
$divfooter2 = $("</div>").attr({ "class": 'col-xs-12 col-md-6', id: 'footer2' }),
$atag = $("</a>").attr({ class: 'btn btn-success', href: 'http://www.jquery2dotnet.com' }).text("Add to cart");
$("#rowview").append($divitem.append($divthumb.append([$divimg.append($imggrp), $divcaption.append([$headcard, $paracard, $divrow.append([$divfooter1.append($lead), $divfooter2.append($atag)])])])));
// $($divthumb).append([$divimg, $divcaption]);
//$($divimg).append($imggrp);
// $(divthumb).append(divcaption);
//$($divcaption).append([$headcard, $paracard, $divrow]);
// $(divcaption).append(paracard);
//$(divcaption).append(divrow);
//$($divrow).append([$divfooter1, $divfooter2]);
//$($divfooter1).append($lead);
//$(divrow).append(divfooter2);
// $($divfooter2).append($atag);
// $(".view-group").append($divitem);
}
});
});
I'm not getting the response on my website. I even tried the code in the comments, but didn't work.

Update code and it is working. Hope it helps.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sidebar demo</title>
<script
src="https://code.jquery.com/jquery-3.5.0.min.js"
integrity="sha256-xNzN2a4ltkB44Mc/Jz3pT4iU1cmeR0FkXs4pru/JxaQ="
crossorigin="anonymous"></script>
</head>
<body>
<div id="rowview"> </div>
<script>
$(document).ready(function() {
$.get("https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Ftimesofindia.indiatimes.com%2Frssfeeds%2F-2128816011.cms&api_key=mkzfaqsb5gtninv1pddoke81vwmjlyfiissiitvd", function(data, status) {
for (i in data.items) {
console.log(data.items[i].thumbnail);
console.log(data.items[i].title);
console.log(data.items[i].link);
console.log(data.items[i].description);
console.log(data.items[i].description.slice(pos + 4));
var pos = data.items[i].description.indexOf("</a>"),
$divitem = $("<div>").attr('class', 'item grid-group-item col-xs-4 col-lg-4 col-md-6 col-sm-12');
var $divthumb = $("<div>").attr({ "class": 'thumbnail card border-light', style: 'width: 20rem' }),
$divimg = $("<div>").attr('class', 'img-event '),
$imggrp = $("<img>").attr({ "class": 'group list-group-image img-fluid ', src: data.items[i].thumbnail }),
$divcaption = $("<div>").attr('class', 'caption card-body'),
$headcard = $("<h4>").text(data.items[i].title).attr('class', 'group card-title inner list-group-item-heading'),
$paracard = $("<p>").attr('class', 'group inner list-group-item-text').text(data.items[i].description.slice(pos + 4)),
$divrow = $("<div>").attr('class', 'row'),
$divfooter1 = $("<div>").attr({ "class": 'col-xs-12 col-md-6', id: 'footer1' }),
$lead = $("<p>").attr('class', 'lead').text('$21.000'),
$divfooter2 = $("<div>").attr({ "class": 'col-xs-12 col-md-6', id: 'footer2' }),
$atag = $("<a>").attr({ class: 'btn btn-success', href: 'http://www.jquery2dotnet.com' }).text("Add to cart");
$("#rowview").append($divitem.append($divthumb.append([$divimg.append($imggrp), $divcaption.append([$headcard, $paracard, $divrow.append([$divfooter1.append($lead), $divfooter2.append($atag)])])])));
// $($divthumb).append([$divimg, $divcaption]);
//$($divimg).append($imggrp);
// $(divthumb).append(divcaption);
//$($divcaption).append([$headcard, $paracard, $divrow]);
// $(divcaption).append(paracard);
//$(divcaption).append(divrow);
//$($divrow).append([$divfooter1, $divfooter2]);
//$($divfooter1).append($lead);
//$(divrow).append(divfooter2);
// $($divfooter2).append($atag);
// $(".view-group").append($divitem);
}
});
});
</script>
</body>
</html>

Related

Display information from an array in a modal

I have 3 boxes, each box contains different information, this box also has a "View rewards" button, I need that when I click for example on box 3, a modal receives the information listed in my rewards array, it contains 3 lines of objects with ID, Title and Description information, each box contains its id I need the information of each one specifically to appear in the modal when clicking on the button of one of the modals.
Boxs print
Output modal print <- I need this result
const rewards = [
{
id: 1,
desc:
`
teste
`
},
{
id: 2,
desc:
`
teste 2
`
},
{
id: 3,
desc:
`
teste3
`
},
{
id: 4,
desc:
`
teste 4
`
}
]
const box =
[
{
id: 1,
titulo: "dfgdstd",
imagem: "src/images/item.png",
desc:
`+ 160 Gcoins,
+ 1 Mastery Box (Standard),
`,
link: "#",
recompensa: ``
},
{
id: 2,
titulo: "MasteryBox",
imagem: "src/images/item.png",
desc: `+ 160 Gcoins,
+ 1 Mastery Box (Minor),
`,
link: "#",
recompensa: ``
},
{
id: 3,
titulo: "MasteryBox",
imagem: "src/images/item.png",
desc: `+ 160 Gcoins,
+ 1 Mastery Box (Minor),
+ 1 Mastery Box (Standard),
`,
link: "#",
recompensa: ``
},
]
const section_1 = add => {
const boxes = $("#boxes");
/*/ Boxes benefĂ­cios/*/
boxes.append
(`
<div class="box" style="background: url(https://i.imgur.com/TgM0mIc.png); width: 270px; height: 350px; color:#fff;">
<div class="box-title">${add.titulo}</div>
<div class="box-body">
<img class="d-block mx-auto"src="${add.imagem}" style="margin-top: 70px;">
<div class="box-desc text-center mt-3">${add.desc.split(",").join("<br/>")}</div>
</div>
<div class="box-footer">
<a id="box-button" style="width:193px; height: 37px;" class="mx-auto d-block box_button" href="${add.link}">
<img src="https://i.imgur.com/CiWhLm6.png"></a>
</div>
</div>
`);
}
const p_modal = add => {
const modals = $("#promoModal");
modals.append
(`
<div class="promo_modal_wrap col-lg-5 mx-auto">
<span id="promo-close">x</span>
<div class="promo_modal_content">
<div class="promo_modal_title">
${add.titulo}
</div>
${add.desc}
</div>
</div>
`)
}
box.forEach(add => section_1(add));
rewards.forEach(add => p_modal(add));
<html>
<head>
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.1/dist/css/bootstrap.min.css">
</head>
<body>
<div class="promo_modal_wrap col-lg-5 mx-auto"></div>
<div class="row">
<div id="boxes" class="d-flex align-items-center"></div>
</div>
</body>
</html>

jQuery sortable in nested element

I have a list with categories and questions (which can both be added dynamically), at the moment I am able to sort the categories using jQuery sortable, but not the questions underneath the categories.
I've tried just adding another .sortable function on the question wrap element but it is not responding at all.
My code at the moment:
// HTML template for new fields
const template = `
<div class="row sortwrap">
<div class="col-md-8">
<input type="text" name="category[]" placeholder="" class="form-control name_list catinput" />
<i class="mdi mdi-sort dragndrop"></i>
<div class="questionlist questionwrap">
<div class="row">
<div class="col-md-8">
<button class="btn btn-success questionbutton">Extra vraag</button>
<input type="text" name="question[]" placeholder="1. Voeg een vraag toe" class="form-control name_list questioninput" />
</div>
<div class="col-md-4">
</div>
</div>
</div>
</div>
<div class="col-md-4">
<button id="addcategory" class="btn btn-danger btn_remove removebutton">X</button>
</div>
</div>`;
const vraagTemplate = `
<div class="row" id="question">
<div class="col-md-8">
<input type="text" name="question[]" class="form-control name_list questioninput" />
</div>
<div class="col-md-4">
<button class="btn btn-danger btn_remove">X</button>
</div>
</div>`;
// Count numbers and change accordingly when field is deleted
function updatePlaceholders() {
// Sortable code
// $('#dynamic_field').sortable( "refresh" );
let df = $('#dynamic_field');
df.find('input[name^=cat]').each(function(i) {
$(this).attr("placeholder", i + 1 + ". Voeg een categorie toe");
});
df.find('.sortwrap').each(function(i) {
$(this).attr("id", i + 1);
});
df.find('.questionlist').each(function() {
$(this).find('input[name^=qu]').each(function(i) {
$(this).attr("placeholder", i + 1 + ". Voeg een vraag toe");
});
});
}
// Append question template
$('#dynamic_field').on('click', '.questionbutton', function() {
let $ql = $(this).closest('.questionlist');
$ql.append($(vraagTemplate));
updatePlaceholders();
});
// Delete
$('#dynamic_field').on('click', '.btn_remove', function() {
$(this).closest('.row').remove();
updatePlaceholders();
});
$('#addcategory').on('click', function() {
let t = $(template)
$('#dynamic_field').append(t);
updatePlaceholders();
});
$(function() {
$('#addcategory').trigger('click');
$('#question').sortable();
$('#dynamic_field').sortable({
cancel: '.questionwrap',
placeholder: "ui-state-highlight"
});
});
This is my sortable code:
$(function() {
$('#addcategory').trigger('click');
$('#question').sortable();
$('#dynamic_field').sortable({
cancel: '.questionwrap',
placeholder: "ui-state-highlight"
});
#question is the wrap of my question list and #dynamic_field is the wrap of my category element (the questions are also inside this element).
How can I make my questions also sortable? And also only make then sortable inside their parent div (so I can't drag a question from one category to the other but only within its own category).
One of the first thing I have noticed about your code is that the ID is repeated for each creation of a dynamic element. This will cause a lot of issues when you have 6 #question elements. This can be addressed by adding the ID to the element when it's created and creating a unique ID. For example, if there are 0 #questions then you can count that and add 1.
<div id="question-1"></div>
<script>
var id = $("[id|='question']").length + 1;
</script>
In this, id would be 2. there is one element that contains "question" and the |= selector will look for that before the - in a ID name. Can also use ^= selector.
Making use of handle will help a lot too. This will help allow proper sorting of nested items versus their parents. Also containment is helpful here too unless you want to move them between lists.
Consider the following code. It's a little clunky and I hope you can see what I am referring to.
$(function() {
function makeSortable(obj, options) {
console.log("Make Sortable", obj);
obj.sortable(options);
obj.disableSelection();
}
function updateSort(obj) {
console.log("Update Sortable", obj);
obj.sortable("refresh");
}
function addQuestion(q, c) {
console.log("Add Question", q, c);
var makeSort = $("[id|='question']", c).length === 0;
var question = $("<div>", {
class: "question",
id: "question-" + ($("div[id|='question']", c).length + 1)
});
question.append($("<div>", {
class: "col-md-8"
}).html(q));
question.append($("<div>", {
class: "col-md-4"
}).html("<button class='btn btn-danger btn-remove'>X</button>"));
question.appendTo($(".catcontent", c));
console.log(makeSort, question, c);
if (makeSort) {
makeSortable($(".catcontent", c), {
containment: "parent",
items: "> div.question"
});
} else {
updateSort($("[id|='question']", c).eq(0).parent());
}
}
function makeCategory(name) {
console.log("Make Category", name);
var makeSort = $("[id|='category']").length === 0;
var cat = $("<div>", {
class: "category ui-widget",
id: "category-" + ($("[id|='category']").length + 1)
});
cat.append($("<div>", {
class: "cathead ui-widget-header"
}).html(name + "<i class='btn btn-add-question'>+</i>"));
cat.append($("<div>", {
class: "catcontent ui-widget-content col-md-8"
}));
cat.appendTo($("#cat-wrapper"));
if (makeSort) {
makeSortable($("#cat-wrapper"), {
handle: ".cathead",
items: "> div.category"
});
} else {
updateSort($("#cat-wrapper"));
}
}
$('#addcategory').on('click', function() {
let t = $(template);
$('#dynamic_field').append(t);
updatePlaceholders();
});
$(".categorybutton").click(function(e) {
e.preventDefault();
makeCategory($(".catinput").val());
$(".catinput").val("");
});
$(".catwrap").on("click", ".btn-add-question", function(e) {
e.preventDefault();
var resp = prompt("Question to Add:");
addQuestion(resp, $(this).parent().parent());
});
});
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="http://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="row sortwrap">
<div class="col-md-8">
New Category
<input type="text" class="form-control catinput" placeholder="Category Name" />
</div>
<div class="col-md-4">
<button class="btn btn-success categorybutton">Add</button>
</div>
</div>
<div id="cat-wrapper" class="row catwrap">
</div>
Hope that helps.

Changing Button Text on Text Input - JS, RoR

I have a Price Range button that when clicked will open a popover. In that popover, there are two input boxes. A Min Rent box and a Max Rent box. Once values are entered in that box I would like the Price Range box to now display the values that were previously entered. Something like $2000 to $2500. I have looked and looked on Google and other StackOverflow questions and answers, but I am not sure how to accomplish this. Any help would be greatly appreciated!
Erb File:
<div class="col-md-2 col-xs-6">
<a tabindex="0" class="button btn-transparent" id="listing-price-selector" role="button" data-toggle="popover">Price Range <span class="caret"></span></a>
</div>
<div id="listing-price-content" style="display: none;">
<div class="container-fluid">
<div class="row">
<div class="col-xs-6">
<div class="input-group input-group-sm">
<span class="input-group-addon" id="basic-addon1">$</span>
<%= f.text_field :min_price, class: "form-control", placeholder: "Min Rent", data: { "binding-name" => "min-price" } %>
</div>
</div>
<div class="col-xs-6">
<div class="input-group input-group-sm">
<span class="input-group-addon" id="basic-addon1">$</span>
<%= f.text_field :max_price, class: "form-control", placeholder: "Max Rent", data: { "binding-name" => "max-price" } %>
</div>
</div>
</div>
</div>
</div>
JS File:
$('#listing-price-selector').popover( {
html: true,
trigger: 'manual',
placement: 'bottom',
template: '<div class="popover price-range-pop" role="tooltip"><div class="arrow"></div><div class="popover-content"></div></div>',
content: function() {
return $('#listing-price-content').html();
}
});
I think what you need is to trigger a function from a change event (keyup) on either of the inputs inside the popover.
The tricky thing here, at least to me, is that the content of the popover is dynamically generated, so trying to assign an event handler for those elements at page load won't work.
What does work is to assign the event handler once those elements have been generated.
There are events that are fired for the popover itself that you can assign a handler on, and that will get you where you need.
$("[data-toggle='popover']").on('shown.bs.popover', function(){
$("#listing-price-selector").next().find("#min-price").keyup(modPrice);
$("#listing-price-selector").next().find("#max-price").keyup(modPrice);
});
and then modPrice can be a function to fix the value of the price range box. Something like:
function modPrice(){
var mn = $("#listing-price-selector").next().find("#min-price").val();
var mx = $("#listing-price-selector").next().find("#max-price").val();
mn = (mn == "") ? 0 : mn;
mx = (mx == "") ? 0 : mx;
$("#listing-price-selector").text(mn + " to " + mx);
}
In there you can do a lot more processing, such as making sure max is over min, or whatever you like.
Hope this helps!
PS - got the popover events from W3Schools ref page: http://www.w3schools.com/bootstrap/bootstrap_ref_js_popover.asp
PPS - and for fun, I made a snippet example, here it is:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="col-md-2 col-xs-6">
<a tabindex="0" class="button btn-transparent" id="listing-price-selector" role="button" data-toggle="popover">Price Range <span class="caret"></span></a>
</div>
<div class="input-group input-group-sm">
<span class="input-group-addon" id="basic-addon1">$</span>
<input type="text" id="priceBox" />
</div>
<div id="listing-price-content" style="display: none;">
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<div class="input-group input-group-sm">
<label>Min</label>
<span class="input-group-addon" id="basic-addon1">$</span>
<input type="text" id="min-price" />
</div>
</div>
<div class="col-xs-12">
<div class="input-group input-group-sm">
<label>Max</label>
<span class="input-group-addon" id="basic-addon1">$</span>
<input type="text" id="max-price" />
</div>
</div>
</div>
</div>
</div>
<script>
$('#listing-price-selector').popover( {
html: true,
trigger: 'click',
placement: 'bottom',
template: '<div class="popover price-range-pop" role="tooltip"><div class="arrow"></div><div class="popover-content"></div></div>',
content: function() {
return $('#listing-price-content').html();
}
});
$("[data-toggle='popover']").on('shown.bs.popover', function(){
$("#listing-price-selector").next().find("#min-price").keyup(modPrice);
$("#listing-price-selector").next().find("#max-price").keyup(modPrice);
});
$("[data-toggle='popover']").on('hide.bs.popover', function(){
modPrice();
});
function modPrice(){
var mn = $("#listing-price-selector").next().find("#min-price").val();
var mx = $("#listing-price-selector").next().find("#max-price").val();
mn = (mn == "") ? 0 : mn;
mx = (mx == "") ? 0 : mx;
$("#priceBox").val(mn + " to " + mx);
$("#listing-price-selector").text(mn + " to " + mx);
}
</script>

How to display the div elements in row by row

I have a html code which displays ads ,but the ads are display like a coloumn vise, but I want them to display in a horizontal row .How can we display the horizontal rows.And ads are which are coming dynamically based on the user selection.How can we display these ads in a row wise fashion .
Html code is :
<div class="row">
<div class="col-md-3" id="adsid"></div>
</div>
Code snippet from JS:
<input type="checkbox" id=' + s[i]['id']['0'] + ' />
<a href="#" class="list-group-item ">
<input type="hidden" id="adsid" name="adsrunning" value=' + s[i]['id']["0"] + '/>
<h4 class="list-group-item-heading">
<font color="blue">' + s[i]['hea']["0"] + '</font>
</h4>
<p class="list-group-item-text">' + s[i]['desc']["0"] + '</p>
<p class="list-group-item-text">' + s[i]['desc2']["0"] + '</p>
<p class="list-group-item-text">
<font color="green">' + s[i]['url']["0"] + '</font>
</p>
</a><br/>
And JS is :
$("#groupid").change(function () {
$("#adsid").html("");
var grpvalue = $("#groupid").val();
var accid = $('#accountid').val();
var adsarray = [];
$.ajax({
type: "post",
dataType: 'json',
url: "pages/ads.php",
data: "adgroup=" + grpvalue + "&accid=" + accid,
success: function (s) {
for (var i = 0; i < s.length; i++) {
var head = s[i]['hea']["0"];
//alert(head);
var adid = s[i]['id']["0"];
var desc1 = s[i]['desc']["0"];
var desc2 = s[i]['desc2']["0"];
var url = s[i]['url']["0"];
var p = document.createElement('p');
var txt = document.createTextNode(head);
p.appendChild(txt);
//$('adsid').append(p);
adsarray.push(head, adid, desc1, desc2, url);
$("#adsid").append("");
$("#adsid").append('<input type="checkbox" id=' + s[i]['id']['0'] + ' /><input type="hidden" id="adsid" name="adsrunning" value=' + s[i]['id']["0"] + '/><h4 class="list-group-item-heading"><font color="blue">' + s[i]['hea']["0"] + '</font></h4><p class="list-group-item-text">' + s[i]['desc']["0"] + '</p><p class="list-group-item-text">' + s[i]['desc2']["0"] + '</p><p class="list-group-item-text"><font color="green">' + s[i]['url']["0"] + '</font></p><br/>');
}
}
});
});
And Json Data is:
[{
"hea": {
"0": "Kidney Stone Removal"
},
"id": {
"0": "40602813172"
},
"desc": {
"0": "Get treated at top kidney center"
},
"desc2": {
"0": "Take a free advice from our experts"
},
"url": {
"0": "www.ainuindia.com"
}
}]
I think your questions i answered here:
http://www.w3schools.com/css/css_float.asp
Use float to place the "rows" next to each other.
Though i would recommend you to change your "row" class to something more appropriate if possible. Since row are explicitly saying that it's a row, in other words a vertical alignment.
You can use ul li tag as bellow give style to li as list-style:none
<div class="row">
<ul >
<li class="col-md-3 col-sm-3 col-xs-6"><img src="" /><span class="badge">Lorem ipsum</span></li>
<li class="col-md-3 col-sm-3 col-xs-6"><img src="" /><span class="badge">Lorem ipsum</span></li>
<li class="col-md-3 col-sm-3 col-xs-6"><img src="" /><span class="badge">Lorem ipsum</span></li>
<li class="col-md-3 col-sm-3 col-xs-6"><img src="" /><span class="badge">Lorem ipsum</span></li>
</ul>
</div>
If you can modify the html of ad, try replacing col-md-3 by col-sm12 so the whole thing would read:
<div class="row">
<div class="col-sm-12" id="adsid">
</div>
</div>
I'm assuming you're using bootstrap, so having col-md-3 makes it float left with width 33%. On medium screen.

Isolate just the element that was clicked

I'm just getting started with Angular and running up against some roadblocks in my understanding of certain core concepts. To better familiarize myself with this new framework I'm attempting to build a trivial application: "Would You Rather?". I present the user two questions, they pick one, I highlight their choice, and show how many votes each question has from previous users.
It sounds simple but I'm still stuck in a jQuery frame of mind; I want to select the element based on $(this) or $("#id").
I have a factory with an array of question objects. Each object has a firstQuestion and secondQuestion key that maps to a question, as well as a firstVotes and secondVotes key with the corresponding number of votes. I'm using a QuestionsCtrl to control scope and take action when a user makes a choice.
Here's my index.html file:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>Would You Rather?</title>
<link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="container" ng-app="wouldYouRatherApp">
<div ng-controller="QuestionsCtrl">
<div class="container">
<div class="row text-center">
<h1 class="col-md-12">Would you rather...</h1>
</div>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-{{buttonClass}}" ng-click="recordAnswer('first')">{{question.firstQuestion}}</h2>
<span class="badge" ng-show="badge.show">{{question.firstVotes}}</span>
</div>
</div>
<div class="row text-center">
<h3 class="col-md-12"><small>or</small></h3>
</div>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-{{buttonClass}}" ng-click="recordAnswer('second')">{{question.secondQuestion}}</h2>
<span class="badge" ng-show="badge.show">{{question.secondVotes}}</span>
</div>
</div>
<br>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-primary" ng-show="showNextQuestion" ng-click="nextQuestion()">Next Question <span class="glyphicon glyphicon-forward"></span></h2>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.min.js"></script>
<script type="text/javascript" src="./main.js"></script>
</body>
</html>
And here's my main.js file:
var app = angular.module("wouldYouRatherApp", []);
app.factory("Badges", function() {
return {show: false}
})
app.factory("Questions", function() {
var Questions = [{
firstQuestion: "Ride a horse?",
firstVotes: 101,
secondQuestion: "Ride a cowboy?",
secondVotes: 212
},
{
firstQuestion: "Kiss a frog?",
firstVotes: 13,
secondQuestion: "Lick a slug?",
secondVotes: 23
},
{
firstQuestion: "Play Monopoly?",
firstVotes: 12,
secondQuestion: "Play Risk?",
secondVotes: 17
}];
return Questions;
})
app.controller("QuestionsCtrl", function($scope, Badges, Questions) {
$scope.question = Questions.shift();
$scope.buttonClass = 'default';
$scope.showNextQuestion = false;
$scope.badge = Badges;
$scope.recordAnswer = function(choice) {
console.log("User chose: " + choice);
$scope.buttonClass = 'success';
// increment votes badge
$scope[choice+'Votes'] += 1;
Badges.show = true;
$scope.showNextQuestion = true;
}
$scope.nextQuestion = function() {
$scope.question = Questions.shift();
Badges.show = false;
$scope.buttonClass = 'default';
$scope.showNextQuestion = false;
}
})
A live example can be found here: http://jsfiddle.net/t99TL/2/
The app's expected behavior is as follows:
Two questions are presented to the user.
The user clicks on one of the buttons.
That question is highlighted. And the votes badge is incremented. Both votes badges are displayed.
A 'Next Question' button is presented to the user.
When he/she clicks on the 'Next Question' button, a new question is loaded.
I feel like I probably need to create a directive for each individual question... but I'm not sure how to start, or if I'm even on the right path. Any advice on obstacles I'm going to face further down the line is much appreciated (i.e. Updating the votes attribute for the question, etc.).
There are a lot to change to make it work the way you want. This code is not perfect, just a demonstration.
HTML:
<div class="container" ng-app="wouldYouRatherApp">
<div ng-controller="QuestionsCtrl">
<div class="container">
<div class="row text-center">
<h1 class="col-md-12">Would you rather...</h1>
</div>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-{{question.firstQuestion.buttonClass}}" ng-click="recordAnswer(question.firstQuestion)">{{question.firstQuestion.text}}</h2>
<span class="badge" ng-show="badge.show">{{question.firstQuestion.votes}}</span>
</div>
</div>
<div class="row text-center">
<h3 class="col-md-12"><small>or</small></h3>
</div>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-{{question.secondQuestion.buttonClass}}" ng-click="recordAnswer(question.secondQuestion)">{{question.secondQuestion.text}}</h2>
<span class="badge" ng-show="badge.show">{{question.secondQuestion.votes}}</span>
</div>
</div>
<br>
<div class="row text-center">
<div class="col-md-12">
<h2 class="btn btn-lg btn-primary" ng-show="showNextQuestion" ng-click="nextQuestion()">Next Question <span class="glyphicon glyphicon-forward"></span></h2>
</div>
</div>
</div>
</div>
JS:
var app = angular.module("wouldYouRatherApp", []);
app.factory("Badges", function() {
return {show: false}
})
app.factory("Questions", function() {
var Questions = [{
firstQuestion: {
text:"Ride a horse?",
votes: 101,
buttonClass : 'default'
},
secondQuestion: {
text:"Ride a cowboy?",
votes: 212,
buttonClass : 'default'
},
},
{
firstQuestion: {
text:"Kiss a frog?",
votes: 13,
buttonClass : 'default'
},
secondQuestion: {
text:"Lick a slug?",
votes: 23,
buttonClass : 'default'
}
},
{
firstQuestion: {
text:"Play Monopoly?",
votes: 12,
buttonClass : 'default'
},
secondQuestion: {
text:"Play Risk?",
votes: 17,
buttonClass : 'default'
}
}];
return Questions;
})
app.controller("QuestionsCtrl", function($scope, Badges, Questions) {
$scope.question = Questions.shift();
$scope.buttonClass = 'default';
$scope.showNextQuestion = false;
$scope.badge = Badges;
$scope.recordAnswer = function(choice) {
choice.buttonClass = 'success';
choice.votes++;
Badges.show = true;
$scope.showNextQuestion = true;
}
$scope.nextQuestion = function() {
$scope.question.firstQuestion.buttonClass = "default";
$scope.question.secondQuestion.buttonClass = "default";
$scope.question = Questions.shift();
Badges.show = false;
$scope.showNextQuestion = false;
}
})
DEMO

Categories

Resources