how to filter through json object - javascript

Javascript
var obj = {
"name" : ["alex","bob","ajhoge"],
"age" : [30,31,33]
};
to output "alex" for instance
document.write(obj["name"][0])
so how to filter through obj to fetch all data like
html
<ul>
<li>name
<ul>
<li>alex</li>
<li>bob</li>
<li>ajhoge</li>
</ul>
</li>
<li>age
<ul>
<li>30</li>
<li>31</li>
<li>33</li>
</ul>
</li>
</ul>
thank you

var x;
for (x in obj) {
if (obj.hasOwnProperty(x)) {
<li>x</ul>
<ul>
obj[x].forEach(function (elem) {
return "<li>" + elem + "</li>";
});
</ul>
}
}
You could work with something of this kind. Please note
Do not use an document.write
The inner loops inside the for are pseudo code.

Related

I want to translate my HTML text

I wanted to translate texts in my web site I used this code, I know that I'm close to get the right solution.
Somewhere in my HTML code:
<ul class="nav navbar-nav navbar-right">
<li>A PREPOS</li>
<li>SERVICES</li>
<li>PORTFOLIO</li>
<li>PRICING</li>
<li>CONTACT</li>
<li> </li>
<li ><a class="lang">FR</a></li>
<li ><a class="lang">EN</a></li>
</ul>
and this is my JavaScript code :
var dictionary, set_lang;
// Object literal behaving as multi-dictionary
dictionary = {
"fr": {
"menu" : {
"about": "à propos",
"services": "services"
}
},
"en": {
"menu" : {
"about": "about",
"services": "services"
}
}
};
// Function for swapping dictionaries
set_lang = function (dictionary) {
$("[data-translate]").text(function () {
var key = $(this).data("translate");
if (dictionary.hasOwnProperty(key)) {
console.log(dictionary[key]);
return dictionary[key];
}
});
};
// Swap languages when menu changes
$(".lang").click(function() {
var language = $(this).html().toLowerCase();
console.log(language);
if (dictionary.hasOwnProperty(language)) {
set_lang(dictionary[language]);
}
});
// Set initial language to French
set_lang(dictionary.fr);
});
In this part :
<li>A PREPOS</li>
The Text 'A PREPOS' can't be translated, but when I change It to:
<li>A PREPOS</li>
I can see my object 'menu' using console.log
Your dictionary logic is totally off. services i.e: will always be services and there's not good reason to use an additional menu layer. Redundant and repetitive should be avoided.
Rather use properties like:
var dictionary = { // props in alphabetical order ok? promise?
// prop : {fr, en}
about : {fr:"à propos", en:"about"},
services : {fr:"services", en:"servicesssss"}
};
function translate( lan ) {
$("[data-translate]").text(function(){
var data = this.dataset.translate.split("|");
var prop = data[0]; // the dictionary property name
var style = data[1]; // "uppercase", "lowercase", "capitalize"
if(!prop in dictionary) return console.error("No "+ prop +" in dictionary");
var trans = dictionary[prop][lan]; // The translated word
// Do we need to apply styles?
if(style==="capitalize"){
trans = trans.charAt(0).toUpperCase() + trans.slice(1);
} else if(style==="uppercase"){
trans = trans.toUpperCase();
} else if( style==="lowercase"){
trans = trans.toLowerCase();
}
return trans;
});
}
// Swap languages when menu changes
$("[data-lang]").click(function() {
translate( this.dataset.lang );
});
// Set initial language to French
translate("fr");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav navbar-nav navbar-right">
<li>A PREPOS</li>
<li>SERVICES</li>
<li> </li>
<li><a data-lang="fr">FR</a></li> <!-- data-* attributes can be helpful -->
<li><a data-lang="en">EN</a></li>
</ul>
Your problem is that your call to dictionary.hasOwnProperty("menu.about") returns false.
You need to traverse the tree of objects so you're getting the property like this:
dictionary["menu"]["about"]
I've put together a simple recursive example on how you can traverse the tree of objects.
// Object literal behaving as multi-dictionary
dictionary = {
"fr": {
"menu": {
"about": "à propos",
"services": "services"
}
},
"en": {
"menu": {
"about": "about",
"services": "services"
}
}
};
// Function for swapping dictionaries
set_lang = function(dictionary) {
$("[data-translate]").text(function() {
var key = $(this).data("translate");
return parseSubObject(dictionary, key);
});
};
function parseSubObject(obj, str) {
var props = str.split(".");
var thisProp = props.shift();
if (obj.hasOwnProperty(thisProp)) {
if (props.length == 0) {
return obj[thisProp];
} else {
return parseSubObject(obj[thisProp], props.join('.'));
}
} else {
return null;
}
}
// Swap languages when menu changes
$(".lang").click(function() {
var language = $(this).text().toLowerCase();
if (dictionary.hasOwnProperty(language)) {
set_lang(dictionary[language]);
}
});
// Set initial language to French
set_lang(dictionary.fr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="nav navbar-nav navbar-right">
<li>A PREPOS</li>
<li>SERVICES</li>
<li>PORTFOLIO</li>
<li>PRICING</li>
<li>CONTACT</li>
<li> </li>
<li><a class="lang">FR</a></li>
<li><a class="lang">EN</a></li>
</ul>
You're assuming that dictionary.fr.menu.about (à propos) is the same as dictionary.fr['menu.about'] (undefined).
Note the data structure of each section of dictionary.fr.menu.about:
dictionary: Object
dictionary.fr: Object
dictionary.fr.menu: Object
dictionary.fr.menu.about: String
In order to get to the String, you need to walk the objects, which you can do with this code:
set_lang = function(dictionary) {
$("[data-translate]").text(function() {
var key = $(this).data("translate").split('.'),
val = dictionary[key.shift()];
while(key.length) {
val = val[key.shift()];
}
return val;
});
};
Snippet:
var dictionary, set_lang;
// Object literal behaving as multi-dictionary
dictionary = {
"fr": {
"menu": {
"about": "à propos",
"services": "services"
}
},
"en": {
"menu": {
"about": "about",
"services": "services"
}
}
};
// Function for swapping dictionaries
set_lang = function(dictionary) {
$("[data-translate]").text(function() {
var key = $(this).data("translate").split('.'),
val = dictionary[key.shift()];
while(key.length) {
val = val[key.shift()];
}
return val;
});
};
// Swap languages when menu changes
$(".lang").click(function() {
var language = $(this).html().toLowerCase();
console.log(language);
if (dictionary.hasOwnProperty(language)) {
set_lang(dictionary[language]);
}
});
// Set initial language to French
set_lang(dictionary.fr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav navbar-nav navbar-right">
<li>A PREPOS</li>
<li>SERVICES</li>
<li>PORTFOLIO</li>
<li>PRICING</li>
<li>CONTACT</li>
<li> </li>
<li><a class="lang">FR</a></li>
<li><a class="lang">EN</a></li>
</ul>

How can I locate text within a list and replace it with new text?

I'm trying to write a function that searches the DOM for one text and replace it with another. In other words, I have this html:
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
<li>Item4</li>
<li>Item5</li>
</ul>
Now I want to find 'Item4' and replace it with 'newItem4'.
I've been able to find 'Item4' but can't figure out how to replace it with new text. Here's the code inside my function so far:
var array = ['Item1', 'Item2', 'Item3', 'Item4', 'Item5'];
function replace() {
var x = document.querySelectorAll('ul');
var newText = document.createTextNode('newItem4');
for (var i = 0; i < array.length; i++) {
if (array[i] === 'Item4') {
}
}
That's as far as I've gotten. Not sure if I'm on the right track or not.
This is how you find it in HTML,
var lis = document.querySelectorAll('li');
lis.forEach(function(li){
if(li.innerText.trim() == "Item4" )
li.innerText = "NewItem4";
});
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
<li>Item4</li>
<li>Item5</li>
</ul>
This is how you do with array
var array = ['Item1', 'Item2', 'Item3', 'Item4', 'Item5'];
array[array.indexOf('Item4')] = 'newItem4'
function replace() {
var li = document.getElementsByTagName("li");
for (var i = 0; i < li.length; i++) {
if(li[i].innerHTML =="Item4")
li[i].innerHTML ='newItem4';
}
}
replace();
document.getElementsByTagName("ul")[0].setAttribute("id", "myID");
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
<li>Item4</li>
<li>Item5</li>
</ul>
//index is the child number(li) and text is string to replace
function findAndReplace(index, text) {
$("ul li:nth-child(" + index + ")").html(text);
}
You could do something like this to replace.
document.querySelector("button").addEventListener("click",
function() {
let searchText = document.querySelector("#searchText").value,
replaceText = document.querySelector("#replaceText").value;
[].forEach.call(document.querySelectorAll("li"), function(element) {
if (element.innerText === searchText) {
element.innerText = replaceText;
};
});
});
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
<li>Item4</li>
<li>Item5</li>
</ul>
Search Text:
<input type="text" id="searchText" />Replace Text:
<input type="text" id="replaceText" />
<button>Change
</button>
You could also simply do this, if you use jQuery
$(function() {
$("li:contains('Item4')").html("NewItem4");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
<li>Item4</li>
<li>Item5</li>
</ul>

radomize ul tag not working

this is probably an easy question for you guys but I'm very new to coding and can't figure out this. I have a code that I want to randomize the given choices in the questions, and I've found a script online that does that but it's not working. I don't know what the
// shuffle only elements that don't have "group" class
$ul.find("li[class!='single_question', 'question', 'title', 'text']").each(function() {
means so I tried to put all id that I don't need to randomize in it but it's still not working.
Can someone help me this please? Also is there anyway I can add choice "A", choice "B", choice "C", and choice "D" in front of each given options so even after the options(answers) are randomized, the A,B,C,D options will still be in order? Thank you. Here's the code:
HTML:
<!DOCTYPE html>
<html>
<body>
<script src="JQ.js"></script>
<script src="function.js"></script>
<link href="style.css" rel="stylesheet" />
<div id="quiz_container">
<ul class="quiz_container">
<li class="single_question" data-question-id="1" data-correct-answer="1">
<div class="question">
<h1 class="title">P.1 Grammar Review</h1>
<p class="text">1. "What is your name__"</p>
</div>
<ul class="options">
<li value="1">?</li>
<li value="2">.</li>
<li value="3">,</li>
</ul>
<div class="result"></div>
</li>
<li class="single_question" data-question-id="2" data-correct-answer="b">
<div class="question">
<p class="text">2. "Do you like the banana__"</p>
</div>
<ul class="options">
<li value="a">.</li>
<li value="b">?</li>
<li value="c">,</li>
</ul>
<div class="result"></div>
</li>
</div>
</body>
</html>
JS:
$(document).ready(function () {
/*
* shuffles the array
* #param {Array} myArray array to shuffle
*/
function shuffleArray(myArray) {
for (var i = myArray.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = myArray[i];
myArray[i] = myArray[j];
myArray[j] = temp;
}
return myArray;
}
var $ul, $li, li_content, li_list;
// find all lists to shuffle
$("#quiz_container > ul").each(function () {
$ul = $(this);
li_list = [];
// shuffle only elements that don't have "group" class
$ul.find("li[class!='single_question', 'question', 'title', 'text']").each(function () {
// add content to the array and remove item from the DOM
li_list.push($(this).html());
$(this).remove();
});
// shuffle the list
li_list = shuffleArray(li_list);
while (li_content = li_list.pop()) {
// create <li> element and put it back to the DOM
$li = $("<li />").html(li_content);
$ul.append($li);
}
});
$("#contact_div").show();
});
$(document).on('click', '.single_question .options li', function () {
// Save the question of the clicked option
question = $(this).parents('.single_question');
// Remove If Anyother option is already selected
question.find('.selected').removeClass('selected');
// Add selected class to the clicked li
$(this).addClass('selected');
// selected option value
selected_answer_value = $(this).attr("value");
// Value of correct answer from '.single-question' attribute
correct_answer_value = question.attr("data-correct-answer");
correct_answer_text = question.find('.options').find("li[value='" + correct_answer_value + "']").text();
if (correct_answer_value == selected_answer_value)
result = "<div class='correct'> Correct ! </div>";
else
result = "<div class='wrong'> Correct answer is -> " + correct_answer_text + "</div>";
// Write the result of the question
$(this).parents('.single_question').find('.result').html(result);
// Calculate the score
score_calculator();
});
/**
* It loops through every question and increments the value when "data-correct-answer" value and "option's value" are same
*/
function score_calculator() {
score = 0;
$('.single_question').each(function () {
question = $(this);
if (question.attr('data-correct-answer') == question.find('.selected').attr("value")) {
score++;
}
});
$('.correct_answers').html(score);
}
It looks like you're using jQuery, even though the question isn't tagged as such. If that's the case, you can use a code snippet written by Chris Coyier of CSS-Tricks called shuffle children.
Here's an example of the code in action.
$.fn.shuffleChildren = function() {
$.each(this.get(), function(index, el) {
var $el = $(el);
var $find = $el.children();
$find.sort(function() {
return 0.5 - Math.random();
});
$el.empty();
$find.appendTo($el);
});
};
$("ul.randomized").shuffleChildren();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Static List:</h4>
<ul>
<li>First element</li>
<li>Second element</li>
<li>Third element</li>
<li>Fourth element</li>
</ul>
<h4>Randomized List:</h4>
<ul class="randomized">
<li>First element</li>
<li>Second element</li>
<li>Third element</li>
<li>Fourth element</li>
</ul>
In order to apply it to your own code, all you'd need to do is modify the CSS selector at the bottom of the jQuery snippet. In your case, ul.options might be a good choice.
Here are a couple of examples using your markup:
jsFiddle
Self-Contained HTML Doc

jQuery: Convert Attribute Values to Nested Array (Strings to Numbers)

Using jQuery, I would like to get each attribute value, insert it into an array and then insert each array into an array.
From this HTML:
<ul>
<li data-bbox="-121,20,-36,30">Item 1</li>
<li data-bbox="-122,30,-46,40">Item 2</li>
<li data-bbox="-123,40,-56,50">Item 3</li>
</ul>
I'm trying to create this type of nested array:
var bboxArray = [
[-121,20,-36,30],
[-122,30,-46,40],
[-123,40,-56,50]
];
...and convert the strings to numbers.
I'm assuming I need to do something like this:
var bboxArray = [];
$('li[data-bbox]').each(function() {
bboxArray.push($(this).attr('data-bbox').split(','));
});
Working Example
While your code does work, it is returning strings instead of the numbers you have in your required output this will do that:
I simply added .map(Number) at the end of your push
$('li[data-bbox]').each(function() {
bboxArray.push($(this).attr('data-bbox').split(',').map(Number));
});
You can use the .map() method like so:
var bboxArray = $('ul > li').map(function() {
return [ $(this).data('bbox').split(',') ];
}).get();
var bboxArray = $('ul > li').map(function() {
return [ $(this).data('bbox').split(',') ];
}).get();
console.log( bboxArray );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li data-bbox="-121,20,-36,30">Item 1</li>
<li data-bbox="-122,30,-46,40">Item 2</li>
<li data-bbox="-123,40,-56,50">Item 3</li>
</ul>

Group list-items into sub-lists based on a data attribute

I want to append the <li> from one <ul> to another <ul> that's created on the fly. I want to group the list-items into new sub-lists based on their data-group attribute.
<ul id="sortable1">
<li data-group="A">test</li>
<li data-group="A">test1</li>
<li data-group="B">test2</li>
<li data-group="B">test3</li>
<li data-group="C">test4</li>
</ul>
Basically I'm trying to loop through this list and grap all <li> from each group, and then move it to another <ul>.
This is what I have so far, but I'm not getting the expected results. I have done this in Excel in the past but can't get it to work with jQuery.
var listItems = $("#sortable1").children("li");
listItems.each(function (idx, li) {
var product = $(li);
//grab current li
var str = $(this).text();
if (idx > 0) {
//append li
str += str;
if ($(this).data("group") != $(this).prev().data("group")) {
//I should be getting test and test1.
//but alert is only giving test1 test1.
alert(str);
//need to break into groups
//do something with groups
}
}
});
How about something like this:
$(function() {
var sortable = $("#sortable1"),
content = $("#content");
var groups = [];
sortable.find("li").each(function() {
var group = $(this).data("group");
if($.inArray(group, groups) === -1) {
groups.push(group);
}
});
groups.forEach(function(group) {
var liElements = sortable.find("li[data-group='" + group + "']"),
groupUl = $("<ul>").append(liElements);
content.append(groupUl);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="sortable1">
<li data-group="A">test</li>
<li data-group="A">test1</li>
<li data-group="B">test2</li>
<li data-group="B">test3</li>
<li data-group="C">test4</li>
</ul>
<div id="content">
</div>
I hope I didn't misunderstand you.

Categories