How to set the HTML select options from a json - javascript

I got one external .json file, in which a arry is defined as:
var words = [
"a",
"able",
"about",
"account",
"acid",
"across",
"act",
"addition"]
My plan is to import in the .json file via jquery, and then use the values in the array word as the option in a select object.
My understanding is:
<div>
<select size="7" class="selection"></select>
</div>
<script>
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
$.each(result, function (i, word) {
$(".selection").html("<option>word</option>");
});
});
});
</script>
or:
<script>
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
html = ''
for (i = 0; i < results.length; i++) {
html += "<option value=" + result[i] + ">" + result[i] + "</option>";
};
document.getElementById("myselect").innerHTML = html;
});
});
</script>
But neither works here. Please tell me how to fix that.

Your .json-file needs to be like this:
[
"a",
"able",
"about",
"account",
"acid",
"across",
"act",
"addition"
]
Then either of the scripts should work. (First one with one small adjustment)
<div>
<select size="7" class="selection"></select>
</div>
<script>
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
$.each(result, function (i, word) {
$(".selection").append("<option>"+word+"</option>");
});
});
});
</script>
Remember that a .json-file should only contain JSON. Not javascript which is what you had.

You have some typos in your code.
Assuming that you have valid json and parsed words array
var words = [
"a",
"able",
"about",
"account",
"acid",
"across",
"act",
"addition"];
$.each(words, function (i, word) {
$(".selection").append("<option value='"+word+"'>" + word + "</option>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<select size="7" class="selection"></select>
</div>

For your first attempt, you're doing:
$(".selection").html("<option>word</option>");
You should be using something like append, and also make sure you take "word" out of the quotes:
$(".selection").append("<option>" + word + "</option">);
.html() just replaces the data contained within the HTML element, whereas .append() will add them to the end.
This is the issue if you're only getting one value returned.
It looks like in your JSON object you have the data defined in a variable, instead it should just be:
[
"a",
"able",
"about",
"account",
"acid",
"across",
"act",
"addition"
]

this work for me:
$.each(words, function (i, word) {
items+="<option>"+word+"</option>";
});
$(".selection").html(items);

You have several things that need to be fixed. One, is that .html() replaces the innerHTML, doesn't add to it. So, you need to build all the options and then set them. I also, as you had in the second script, put the value of the word as the option value. Note, the inner quotes are also needed. Furthermore, your jQuery of ".selection" will do this to all objects designated with the "selection" class, whereas, in your second script, you seemed to want to only assign one element with an id of "myselect".
<div>
<select size="7" class="selection"></select>
</div>
<script>
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
var html = "";
$.each(result, function (i, word) {
html += "<option value='"+word+"'>"+word+"</option");
});
$(".selection").html(html);
});
});
</script>

You can extend jQuery. The best thing about this approach is you can reuse these extensions when needing to clear or fill a select. Just pass it an array.
$.fn.clearSelect = function() {
return this.each(function() {
if (this.tagName == 'SELECT')
this.options.length = 0;
});
}
$.fn.fillSelect = function(data) {
return this.clearSelect().each(function() {
if (this.tagName == 'SELECT') {
var dropdownList = this;
if (data.length > 0) {
this.disabled = false;
}
$.each(data, function(index, optionData) {
var option = new Option(optionData, optionData);
dropdownList.add(option, null);
});
}
});
}
This extension will allow you to pass your data directly to the select like this
$("#myselectid").fillselect(["a","able","about","account","acid","across","act"]);
I have not tested this, but the snip-it should give you the general idea.
But in your example you could call the extensions this way:
$(document).ready(function () {
$.getJSON("words-small.json", function (result) {
$(".selection").fillSelect(result);
}
});
Just tested and edited the snipet. Test is located here https://jsfiddle.net/4wmj8pkk/

Related

Reusing Javascript code without repasting it again and again

I have the below code, which looks for the text "UID" and changes it to "UID *"
On my page, there are other terms such as "description", "score" and so on. I would also like to append * to these as well - is there a tidy way to get the below code to edit those as well? Only way I know is to repeat this code block again and again?
<script type="text/javascript">
//Mark UID as Mandatory
var CFN = "UID";
$(document).ready(ExecuteOrDelayUntilScriptLoaded(MainFunction, "sp.js"));
function MainFunction() {
Mandatory();
}
function Mandatory(){
$(".ms-accentText").each(function() {
var text = $(this).text();
$(this).text(text.replace(CFN, 'UID *'));
});
}
</script>
EDIT. I tried the below reply, but this didn't work for me, I have got this code now, but again, doesn't seem to work (its trying to add a * onto "UID" and "Description" where found using a multi variable;
<script type="text/javascript">
//Mark UID as Mandatory
var MandatoryCFs = ["UID", "Description"];
$(document).ready(ExecuteOrDelayUntilScriptLoaded(MainFunction, "sp.js"));
function MainFunction() {
Mandatory();
}
function Mandatory(){
$(".ms-accentText").each(function() {
var text = $(this).text();
$(this).text(text.append(MandatoryCFs, ' *'));
});
}
</script>
Replace multiple strings by using list of| Regex
//Mark UID as Mandatory
var MandatoryCFs = ["UID", "Description"];
$(document).ready(ExecuteOrDelayUntilScriptLoaded(MainFunction, "sp.js"));
function MainFunction() {
Mandatory();
}
function Mandatory(){
$(".ms-accentText").each(function() {
var text = $(this).text();
$(this).text(text.replace(new RegExp(MandatoryCFs.join('|'),'g'), '$& *'));
});
}
or like this if you don't need to the replaced strings to be dynamic:
text.replace(/UID|Description/g, '$& *')

Boostrap popover not working with html injection

I'm trying to create dynamic popovers that are generated from a 'dictionary' array that injects HTML into existing text on the page. The code was initially uses for tooltips and worked well but now I am trying to transfer over to popovers. However the html isn't injecting and I'm stuck with it. The aim is to click on a word and have the definition etc popup. I also have a standard popover on the same page that functions correctly. I'm not getting any errors in the console :(
//script.js
$(function() {
var $words = [
{
word: "ね",
kana: "",
romaji: "ne",
definition: "n postposition<br>indicates emphasis, agreement, request for confirmation, etc., is it so, hey, come on, listen, not",
note: ""
},
{
word: " 動画",
kana: "どうが",
romaji: "douga",
definition: "video, movie, moving picture, animation, animated cartoon, in-betweens (animation)",
note: ""
},
{
word: " 今日",
kana: "きょう",
romaji: "kyou",
definition: "adjective today, this day, these days, recently, nowadays",
note: ""
},
{
word: "毎日",
kana: "まいにち",
romaji: "mainichi",
definition: "every day",
note: ""
},
{
word: "も",
kana: "",
romaji: "mo",
definition: "adjective today, this day, these days, recently, nowadays",
note: " te form"
},
{
word: "頑張りましょう",
kana: "がんばりましょう",
romaji: "ganbarimashou",
definition: "verb to persevere, to persist, to keep at it, to hang on, to hold out, to do one\'s best",
note: "lets do"
},
];
$('.define').definitions({
term: $words
});
}); //end $(function()
$(document).ready(function() {
$('[data-toggle="popover"]').popover();
});
/*==================js/jquery.define.js============================*/
var html;
$.fn.definitions = function(words) {
//$.fn alias for jQuery.prototype extends jQuery with your own functions
//console.log("words: ", words); // returns words array
var count = 0;
// Iterate over a jQuery object, executing a function for each matched element.
return this.each(function() {
var _results = [];
var _term = words["term"]; //console.log(_term); //return each definition / word pair object in a single array
var _this = $(this); //console.log(_this);
if (_term.length > 1) {
$.each(_term, function() {
for (let key in _term) {
// iterates over all properties of an object returning value only.
var val = _term[key]; //console.log(val); //returns each dict def / word pair object individually
_results.push(
_this.html(function(index, htmlContent) {
if (
_this
.text()
.toUpperCase()
.indexOf(val["word"].toUpperCase()) >= 0
) {
//console.log(html);
return (html = define_replace(
val["word"],
val["definition"],
val["kana"],
val["romaji"],
val["note"],
htmlContent,
key
)); //html injecting
}
})
);
} //end for...in
});
$("#japanese").html(html); //changed from .text()
} else {
_results.push(
_this.html(function(index, htmlContent) {
if (
_this
.text()
.toUpperCase()
.indexOf(_term["word"].toUpperCase()) >= 0
) {
return (html = define_replace(
_term["word"],
_term["definition"],
_term["kana"],
_term["romaji"],
htmlContent
));
}
})
);
}
}); //end return this.each(function()
}; //end $.fn.definitions
//inject class before and after found word in html
var define_replace = function(word, def, kan, rom, note, html, key) {
//console.log(arguments);
return html.replace(
'<a data-html="true" data-toggle="popover" title="Popover - title" data-content="' + def + '>' + word + " " + '</a>', "gi"
); //html building - replace word + space with html
(n - adv, n, ctr) time;
hours;
(P) < /span></span >
}; // end define_replace
//index.html
<div class="define">
<p id="japanese">ね 、 毎日 動画 今日 も 頑張りましょう</p>
</div>
include popper.min.js before bootstrap.js or use bootstrap.bundle.min.js and Enable popovers everywhere
$(function () {
$('[data-toggle="popover"]').popover()
})

passing a variable to .html() function

<!-- The select drop down menu (works fine) -->
<select id="select-event-type">
<?php foreach ($this->events as $event) {
echo "<option value='" .$event->event_id. "'>" .$event->event_title."</option>";
}?>
</select>
<!-- The javascript, which is supposed to output something according to the chosen option in the select drop down -->
<script>
(function ($) {
var events = <?php echo (count($this->events) > 0) ? json_encode($this->events) : "null"; ?>;
$(document).ready(function() {
$('#select-event-type').change(function() {
if (events) {
var event = events[this.selectedIndex];
$('#event-details').html(event);
}
});
});
})($);
</script>
<!-- In this div the output will be displayed -->
<div id="event-details"></div>
The event variable undefined.
If I for example do this: var event = 'hello' It does output 'hello' as it is supposed to.
So the problem seems to be with this part: events[this.selectedIndex];. What did I do wrong?
I am really new to this. Thank you so much for your help!!
UPDATE:
Console output (in chrome):
<script>
(function ($) {
var events = JSON.parse({"1":{"event_id":"1","event_title":"event1","event_desc":"event1","event_location":"eventlocation","event_requirements":"event1","event_date":"2022-07-20 15:00:00"},"2":{"event_id":"2","event_title":"event2","event_desc":"event2","event_location":"eventlocation","event_requirements":"event2","event_date":"2015-04-20 15:00:00"},"3":{"event_id":"3","event_title":"event3","event_desc":"event3","event_location":"eventlocation","event_requirements":"event3","event_date":"2019-11-20 16:00:00"}}); $(document).ready(function() {
$('#select-event-type').change(function() {
if (events) {
var event = events[$(this).selectedIndex];
$('#event-details').html(event);
}
});
});
</script>
JSON:
{
"1": {
"event_id": "1",
"event_title": "event1",
"event_desc": "event1",
"event_location": "eventlocation",
"event_requirements": "event1",
"event_date": "2022-07-20 15:00:00"
},
"2": {
"event_id": "2",
"event_title": "event2",
"event_desc": "event2",
"event_location": "eventlocation",
"event_requirements": "event2",
"event_date": "2015-04-20 15:00:00"
},
"3": {
"event_id": "3",
"event_title": "event3",
"event_desc": "event3",
"event_location": "eventlocation",
"event_requirements": "event3",
"event_date": "2019-11-20 16:00:00"
}
}
To get the value of the select element use this.value. Thus change:
var event = events[this.selectedIndex];
To:
var event = events[this.value];
However, if you json is an array with indices 0,1,2,3,4 rather than an object with option values as keys then your use of this.selectedIndex is correct.
UPDATE:
In the light of the sample JSON posted the correct code should be:
var event = events[this.selectedIndex + 1].event_title;
Special Note
You can get all the event data by using either:
var event = JSON.stringify( events[this.selectedIndex + 1] ); //gives you a string of everything
Or you could construct how you want it to look like so:
var event = $('<div/>');
$.each( events[this.selectedIndex + 1], function(k,v) {
event.append( $('<div/>',{text:k + ': ' + v}) );
});
See this answer for the jQuery way of accessing the selectedIndex property. Your answer might look like:
var event = events[$(this).prop("selectedIndex")];
Firstly you dont need the 2 ready instances. Try to do it, if dont work please tell me.
<script>
$(document).ready(function() {
var events = <?php echo (count($this->events) > 0) ? json_encode($this->events) : "null"; ?>;
$('#select-event-type').change(function() {
if (events) {
var event = events[$(this).selectedIndex];
$('#event-details').html(event);
}
});
});
</script>
and what means the selectedIndex ?

print array with js and add html with jQuery

i want to print an array with js and just add to every element some data with html()
the code i use is :
<script type="text/javascript">
$(document).ready(function() {
var testArray = ["test1","test2","test3","test4"];
for(var i=0;i<testArray.length;i++){
document.write(" " +testArray[i]+"<br />").html("is the best");
}
});
</script>
but it doesnt works.
HTML:
<div id="myDIV"></div>
JS:
$(document).ready(function() {
var testArray = ["test1","test2","test3","test4"];
var vPool="";
jQuery.each(testArray, function(i, val) {
vPool += val + "<br /> is the best <br />";
});
//We add vPool HTML content to #myDIV
$('#myDIV').html(vPool);
});
Update:
Added demo link: http://jsfiddle.net/aGX4r/43/
Syntax problem mate!
Let me get that for you!
// first create your array
var testArray = ["test1", "test2", "test3", "test4"];
// faster ready function
$(function(){
for( var i=0; i<testArray.length; i++ ) {
current = testArray[i] + '<br />' + 'is the best'; // this is a string with html in it.
$(current).appendTo("body"); // add the html string to the body element.
}
});
First. document.write it's not a good practice.
Then, you code have a little error: Function (as in document.write) doesn't have html method. Thats a jQuery method.
So, in order to print the array in the body, you could do:
$('p').html(["test1","test2","test3","test4"].join('<br />')).appendTo(document.body);
It's a little difficult to tell what you want to do, but if you want to append to an element in your DOM, use jQuery.append();
for(var i=0;i<testArray.length;i++) {
jQuery('#mydiv').append(testArray[i]);
}

Convert JSON to a Multilevel Bulleted List Using JS

Can some one help me make the following JSON data:
{
"main": {
"label":"Main",
"url":"#main"
},
"project": {
"label":"Project",
"url":"#project"
},
"settings": {
"label":"Settings",
"url":"#settings",
"subnav":[
{
"label":"Privacy",
"url":"#privacy"
},
{
"label":"Security",
"url":"#security"
},
{
"label":"Advanced",
"url":"#advanced"
}
]
}
}
into the following bullets list using JS? Assuming you don't know what the first nodes are call labeled (e.g. "main", "project" <- these will be dynamically generated):
Main (#main)
Project (#project)
Settings (#settings)
Privacy (#privacy)
Security (#security)
Advanced (#advanced)
Thanks
Let's not use HTML string-hacking, shall we? That would break as soon as any of the data had characters like < or & in (or " in attribute values). Use DOM methods and you don't have to worry about character escaping:
function createNav(navs) {
var ul= document.createElement('ul');
for (name in navs) {
var nav= navs[name];
var a= document.createElement('a');
a.href= nav.url;
a.appendChild(document.createTextNode(nav.label));
var li= document.createElement('li');
li.id= 'nav-'+name;
li.appendChild(a)
if ('subnav' in nav)
li.appendChild(createNav(nav.subnav));
ul.appendChild(li);
}
return ul;
}
document.getElementById('navcontainer').appendChild(createNav(jsondata));
Most JS frameworks offer shortcuts to make this a bit less wordy. For example with jQuery:
function createNav(navs) {
var ul= $('<ul>');
for (name in navs) {
var nav= navs[name];
var li= $('<li>', {id: name});
li.append($('<a>', {href: nav.url, text: nav.label}));
if ('subnav' in nav)
li.append(createNav(nav.subnav));
ul.append(li);
}
}
$('#navcontainer').append(createNav(jsondata));
Note that either way, you're using an Object literal which means you get no control over the order the list of navs comes out. You have no guarantee that main will be above project. If you want a defined order, you will have to have the returned JSON data be an array.
My code is on JSfiddle.
As JSON parser I used this one.
The main code is a recursive renderer of the parsed JSON:
function recursive_parse(result) {
var html = '<ul>';
for (var k in result) {
html = html + '<li>' + result[k].label + ' (' + result[k].url + ')';
html = html + recursive_parse(result[k].subnav);
html = html + '</li>';
}
html = html + '</ul>';
return html;
}
var result = json_parse($("div#test1111").html());
var html = recursive_parse(result);
$("div#test2222").html(html);

Categories