Sorry my english is not so good but I hope you will understand my problem.
I made my data base with students names and other details, with all methods, post, get, delete and put. And its all working good. (I am new in programing,begginer, I dont know is it good way to do like I did it).
ime = name // prezime = lastname
var studentiDataStore = {
studenti: [],
postStudent: function(studijId, ime, prezime, brIndexa){
this.studenti.push({
id:this.studenti.length,
studijId: studijId,
ime: ime,
prezime: prezime,
brIndexa: brIndexa
});
return this.studenti[this.studenti.length-1];
},
getStudent: function(id){
if(id){
var targetIndex = -1;
for(var i=0; i<this.studenti.length; i++){
if(this.studenti[i].id===id){
targetIndex = i;
break;
}
}
if(targetIndex>-1){
return this.studenti[targetIndex];
} else {
return null;
}
} else {
return this.studenti;
}
}
},
Now i have this code to draw my students in HTMl
var displayStudents = function(){
var studenti = studentiDataStore.getStudent();
var htmlPresentation = [];
for(var i=0; i<studenti.length; i++){
htmlPresentation.push('<li class="list-group-item">'+ studenti[i].ime + " " + studenti[i].prezime+'</li>');
}
document.getElementById("mainContent").innerHTML = '<ul class="list-group">'+ htmlPresentation.join(" ") + '</ul>'
};
Now i have to make search/filter for my students, i tried to find answer but unsuccessful.
My question is, how to make search filter, when I write first letter(and so on) it show me all names starting with that letter ? Thank you
Add a text input on top of the list
<input type="text" id="searchInput" onkeyup="searchFilter()" placeholder="Search for names..">
then add this function in the script
function searchFilter() {
// Declare variables
var input, filter, ul, li, a, i;
input = document.getElementById('searchInput');
filter = input.value.toUpperCase();
ul = document.getElementsByClassName("list-group")[0];
li = ul.getElementsByTagName('li');
// Loop through all list items, and hide those who don't match the search query
for (i = 0; i < li.length; i++) {
if (li[i].innerHTML.toUpperCase().indexOf(filter) > -1) {
li[i].style.display = "";
} else {
li[i].style.display = "none";
}
}
}
source: https://www.w3schools.com/howto/howto_js_filter_lists.asp
you maybe could get some help from this working example!
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_filter_table
var displayStudents = function(){
var studenti = studentiDataStore.getStudent();
var htmlPresentation = [];
for(var i=0; i<studenti.length; i++){
if((studenti[i].ime+" "+studenti[i].prezime).startsWith("youname"))
htmlPresentation.push('<li class="list-group-item">'+ studenti[i].ime + " " + studenti[i].prezime+'</li>');
}
document.getElementById("mainContent").innerHTML = '<ul class="list-group">'+ htmlPresentation.join(" ") + '</ul>'
};
Related
I'm displaying favorites from localStorage on a page and I'd like to display a message for people that don't have any favorites yet.
This is the div that displays the list which I'd like to repurpose to display the message below when there are no favorites:
<div id='favorites'></div>
And here is the JavaScript that normally shows the favorites:
var options = Array.apply(0, new Array(localStorage.length)).map(function (o, i){
return localStorage.key(i);
});
function makeUL() {
var LIs = '';
var noFavs = 'Hmm, you must\'ve not favorited anything yet. Maybe you\'ll like this one.';
var len = options.length;
if (len === 0) {
document.getElementById('nofavorites').innerHTML = noFavs;
} else {
for (i = 0; i < len; i += 1) {
LIs += '<li>' + options[i] + '</li>';
}
return '<ul>' + LIs + '</ul>';
}
}
document.getElementById('favorites').innerHTML = makeUL();
Right now it just shows undefined.
This is in your html:
<div id='favorites'></div>
<div id='nofavorites'></div>
Your javascript:
var options = Array.apply(0, new Array(localStorage.length)).map(function (o, i){
return localStorage.key(i);
});
function loadFavoriteHTML() {
var favoriteHtml = '';
var noFavs = 'Hmm, you must\'ve not favorited anything yet. Maybe you\'ll like this one.';
var len = options.length;
// Clear html lists
document.getElementById('favorites').innerHTML = '';
document.getElementById('nofavorites').innerHTML = '';
if (len === 0) {
document.getElementById('nofavorites').innerHTML = noFavs;
} else {
for (var i = 0; i < len; i++) {
favoriteHtml+= '<li>' + options[i] + '</li>';
}
var ulHtml= '<ul>' + favoriteHtml+ '</ul>';
document.getElementById('favorites').innerHTML = ulHtml;
}
}
loadFavoriteHTML();
Your code is show undefine because when you dont have favorites list you dont return anything in you makeUI function, and by default the return value is undefined in a function if you dont have return.
I changed your code to set the UI in the function because you edit 2 different div. there is others way to do it. this is a one way.
It's because the makeUL function doesn't return any value when there's no element in the options array.
You'll have to choose between: updating your element inside your function
OR getting the value to insert inside your HTML element returned by your function. But you shouldn't do both.
You might want to change your code into something like this?
var options = Array.apply(0, new Array(localStorage.length)).map(function (o, i) {
return localStorage.key(i);
});
function makeUL() {
var LIs = '';
var noFavs = 'Hmm, you must\'ve not favorited anything yet. Maybe you\'ll like this one.';
var len = options.length;
if (len === 0) {
document.getElementById('favorites').innerHTML = noFavs;
} else {
for (var i = 0; i < len; i += 1) {
LIs += '<li>' + options[i] + '</li>';
}
document.getElementById('favorites').innerHTML = '<ul>' + LIs + '</ul>';
}
}
makeUL();
Plus, you're targeting a nofavorites element that doesn't exist in your example.
Update: I've tried the suggestions in the comments and it's still not working. I really have no idea why. I've consolidated it to a single loop and fixed the syntax errors noted. Here's the code as it looks now:
$(function() {
$("#json-one").change(function() {
var $dropdown = $(this);
$.getJSON("washroutines.json", function(data) {
var vals = [];
var $jsontwo = $("#json-two");
$jsontwo.empty();
for (var i = 0; i < data.length; i++){
if (data[i].make === $dropdown.val()) {
$jsontwo.append("<option value=\"" + data[i].model + "\">" + data[i].model + "</option>");
}
}
});
});
});
Any additional help would be much appreciated!
Original question:
I'm trying to create dependent drop down menus using a json object, and I'm having trouble getting the second menu to populate based on the first. When the first menu changes, the second goes to a bunch of "undefined"s.
$.getJSON("washroutines.json", function(data) {
var vals = [];
for (i = 0; i < data.length; i++){
if (data.make = $dropdown.val()) {
vals.push(data.model);
}
}
var $jsontwo = $("#json-two");
$jsontwo.empty();
for (i = 0; i < vals.length; i++){
$jsontwo.append("<option value\"" + vals[i] + "\">" + vals[i] + "</option>");
}
Please use small words when explaining things to me, I'm new at this!
contents of the JSON:
[{"make":"Maytag","model":"Bravos","prewashCycle":"Whitest Whites"},
{"make":"Maytag","model":"Awesome","prewashCycle":"Awesome Whitest Whites"},
{"make":"Whirlpool","model":"Cabrio","prewashCycle":"Extra Heavy"},
{"make":"Kenmore","model":"Elite","prewashCycle":"Awesome"}]
Try changing your for loop for this
for (var i = 0; i < data.length; i++){
if (data[i].make === $dropdown.val()) {
vals.push(data[i].model);
}
}
Hi im trying to populate ul in html with JSON, i have tried many solutions from this site, but im not having much luck, any suggestions would be gratefully appreciated. Thanks
my code :
<script>
$.getJSON('/simplepie/round/alltables.json', function (data) {
var o = null;
var myArray = new Array();
document.open();
for( var i = 0; i < data.length; i++ )
{
o = data[i];
myArray.push('<li>' + o.title + '</li>');
//document.write(o.source + " <br>" + o.description + "<br>") ;
myArray.push(o.source);
makeUL(o.source);
}
//document.close();
// document.write('Latitude: ' + data.id + '\nLongitude: ' + data.title + '\nCountry: ' + data.description);
function makeUL(array) {
var list = document.createElement('ul');
for(var i = 0; i < array.length; i++) {
var item = document.createElement('li');
item.appendChild(document.createTextNode(array[i]));
list.appendChild(item);
}
return list;
}
});
</script>
</head>
<body>
<ul id="ct"></ul>
</body>
JSON structure
[{"id":"1","source":"Articles | Mail Online",
"time_date":"1422720360",
"title":"Rouhani accuses Iranian hardliners of ",
"description":"DUBAI, Jan 31 (Reuters) - Iranian President Hassan Rouhani",
"link":"http:\/\/www.dailymail.co.uk\/wires\/reuters\/article-2934402\/Rouhani-accuses-Iranian-hardliners-cheering-atom-talks.html?ITO=1490&ns_mchannel=rss&ns_campaign=1490",
"image":"http:\/\/i.dailymail.co.uk\/i\/pix\/m_logo_154x115px.png"}]
Replace your loop with this:
Get a handle on your List since its already in your body <ul id="ct"></ul>:
var ul = document.getElementById("ct");
Then create the li using javascript and append it to your list:
for( var i = 0; i < data.length; i++ )
{
var obj = data[i];
var li = document.createElement("li");
li.appendChild(document.createTextNode(obj.title));
ul.appendChild(li);
}
There is no need for your MakeUL function
Here is a JS Fiddle to help you: http://jsfiddle.net/loanburger/6nrx1zkj/
Thanks to loanburgers solution, i got the code working The o variable needed to be declared.
var ul = document.getElementById("ct");
for( var i = 0; i < data.length; i++ )
{
var o = data[i];
var li = document.createElement("li");
li.appendChild(document.createTextNode(o.title));
ul.appendChild(li);
}
});
I thought this would be easier, but running into a weird issue.
I want to split the following:
theList = 'firstword:subwordone;subwordtwo;subwordthree;secondword:subwordone;thirdword:subwordone;subwordtwo;';
and have the output be
firstword
subwordone
subwordtwo
subwordthree
secondword
subwordone
thirdword
subwordone
subwordtwo
The caveat is sometimes the list can be
theList = 'subwordone;subwordtwo;subwordthree;subwordfour;'
ie no ':' substrings to print out, and that would look like just
subwordone
subwordtwo
subwordthree
subwordfour
I have tried variations of the following base function, trying recursion, but either get into infinite loops, or undefined output.
function getUl(theList, splitOn){
var r = '<ul>';
var items = theList.split(splitOn);
for(var li in items){
r += ('<li>'+items[li]+'</li>');
}
r += '</ul>';
return r;
}
The above function is just my starting point and obviously doesnt work, just wanted to show what path I am going down, and to be shown the correct path, if this is totally off base.
It seems you need two cases, and the difference between the two is whether there is a : in your string.
if(theList.indexOf(':') == -1){
//Handle the no sublist case
} else {
//Handle the sublist case
}
Starting with the no sublist case, we develop the simple pattern:
var elements = theList.split(';');
for(var i = 0; i < elements.length; i++){
var element = elements[i];
//Add your element to your list
}
Finally, we apply that same pattern to come up with the implementation for the sublist case:
var elements = theList.split(';');
for(var i = 0; i < elements.length; i++){
var element = elements[i];
if(element.indexOf(':') == -1){
//Add your simple element to your list
} else {
var innerElements = element.split(':');
//Add innerElements[0] as your parent element
//Add innerElements[1] as your child element
//Increment i until you hit another element with ':', adding the single elements each increment as child elements.
//Decrement i so it considers the element with the ':' as a parent element.
}
}
Keep track of the current list to add items to, and create a new list when you find a colon in an item:
var baseParent = $('ul'), parent = baseParent;
$.each(theList.split(';'), function(i, e) {
if (e.length) {
var p = e.split(':');
if (p.length > 1) {
baseParent.append($('<li>').append($('<span>').text(p[0])).append(parent = $('<ul>')));
}
parent.append($('<li>').text(p[p.length - 1]));
}
});
Demo: http://jsfiddle.net/Guffa/eWQpR/
Demo for "1;2;3;4;": http://jsfiddle.net/Guffa/eWQpR/2/
There's probably a more elegant solution but this does the trick. (See edit below)
function showLists(text) {
// Build the lists
var lists = {'': []};
for(var i = 0, listKey = ''; i < text.length; i += 2) {
if(text[i + 1] == ':') {
listKey = text[i];
lists[listKey] = [];
} else {
lists[listKey].push(text[i]);
}
}
// Show the lists
for(var listName in lists) {
if(listName) console.log(listName);
for(var j in lists[listName]) {
console.log((listName ? ' ' : '') + lists[listName][j]);
}
}
}
EDIT
Another interesting approach you could take would be to start by breaking it up into sections (assuming text equals one of the examples you gave):
var lists = text.match(/([\w]:)?([\w];)+/g);
Then you have broken down the problem into simpler segments
for(var i = 0; i < lists.length; i++) {
var listParts = lists[i].split(':');
if(listParts.length == 1) {
console.log(listParts[0].split(';').join("\n"));
} else {
console.log(listParts[0]);
console.log(' ' + listParts[1].split(';').join("\n "));
}
}
The following snippet displays the list depending on your requirements
var str = 'subwordone;subwordtwo;subwordthree;';
var a = []; var arr = [];
a = str;
var final = [];
function split_string(a){
var no_colon = true;
for(var i = 0; i < a.length; i++){
if(a[i] == ':'){
no_colon = false;
var temp;
var index = a[i-1];
var rest = a.substring(i+1);
final[index] = split_string(rest);
return a.substring(0, i-2);
}
}
if(no_colon) return a;
}
function display_list(element, index, array) {
$('#results ul').append('<li>'+element+'</li>');
}
var no_colon_string = split_string(a).split(';');
if(no_colon_string){
$('#results').append('<ul><ul>');
}
no_colon_string.forEach(display_list);
console.log(final);
working fiddle here
I am having issues figuring out how to resolve the getElementsByClassName issue in IE. How would I best implement the robert nyman (can't post the link to it since my rep is only 1) resolution into my code? Or would a jquery resolution be better? my code is
function showDesc(name) {
var e = document.getElementById(name);
//Get a list of elements that have a class name of service selected
var list = document.getElementsByClassName("description show");
//Loop through those items
for (var i = 0; i < list.length; ++i) {
//Reset all class names to description
list[i].className = "description";
}
if (e.className == "description"){
//Set the css class for the clicked element
e.className += " show";
}
else{
if (e.className == "description show"){
return;
}
}}
and I am using it on this page dev.msmnet.com/services/practice-management to show/hide the description for each service (works in Chrome and FF). Any tips would be greatly appreciated.
I was curious to see what a jQuery version of your function would look like, so I came up with this:
function showDesc(name) {
var e = $("#" + name);
$(".description.show").removeClass("show");
if(e.attr("class") == "description") {
e.addClass("show");
} else if(e.hasClass("description") && e.hasClass("show")) {
return;
}
}
This should support multiple classes.
function getElementsByClassName(findClass, parent) {
parent = parent || document;
var elements = parent.getElementsByTagName('*');
var matching = [];
for(var i = 0, elementsLength = elements.length; i < elementsLength; i++){
if ((' ' + elements[i].className + ' ').indexOf(findClass) > -1) {
matching.push(elements[i]);
}
}
return matching;
}
You can pass in a parent too, to make its searching the DOM a bit faster.
If you want getElementsByClassName('a c') to match HTML <div class="a b c" /> then try changing it like so...
var elementClasses = elements[i].className.split(/\s+/),
matchClasses = findClass.split(/\s+/), // Do this out of the loop :)
found = 0;
for (var j = 0, elementClassesLength = elementClasses.length; j < elementClassesLength; j++) {
if (matchClasses.indexOf(elementClasses[j]) > -1) {
found++;
}
}
if (found == matchClasses.length) {
// Push onto matching array
}
If you want this function to only be available if it doesn't already exist, wrap its definition with
if (typeof document.getElementsByClassName != 'function') { }
Even easier jQuery solution:
$('.service').click( function() {
var id = "#" + $(this).attr('id') + 'rt';
$('.description').not(id).hide();
$( id ).show();
}
Why bother with a show class if you are using jQuery?
Heres one I put together, reliable and possibly the fastest. Should work in any situation.
function $class(className) {
var children = document.getElementsByTagName('*') || document.all;
var i = children.length, e = [];
while (i--) {
var classNames = children[i].className.split(' ');
var j = classNames.length;
while (j--) {
if (classNames[j] == className) {
e.push(children[i]);
break;
}
}
}
return e;
}
I used to implement HTMLElement.getElementByClassName(), but at least Firefox and Chrome, only find the half of the elements when those elements are a lot, instead I use something like (actually it is a larger function):
getElmByClass(clm, parent){
// clm: Array of classes
if(typeof clm == "string"){ clm = [clm] }
var i, m = [], bcl, re, rm;
if (document.evaluate) { // Non MSIE browsers
v = "";
for(i=0; i < clm.length; i++){
v += "[contains(concat(' ', #"+clc+", ' '), ' " + base[i] + " ')]";
}
c = document.evaluate("./"+"/"+"*" + v, parent, null, 5, null);
while ((node = c.iterateNext())) {
m.push(node);
}
}else{ // MSIE which doesn't understand XPATH
v = elm.getElementsByTagName('*');
bcl = "";
for(i=0; i < clm.length; i++){
bcl += (i)? "|":"";
bcl += "\\b"+clm[i]+"\\b";
}
re = new RegExp(bcl, "gi");
for(i = 0; i < v.length; i++){
if(v.className){
rm = v[i].className.match(bcl);
if(rm && rm.length){ // sometimes .match returns an empty array so you cannot use just 'if(rm)'
m.push(v[i])
}
}
}
}
return m;
}
I think there would be a faster way to iterate without XPATH, because RegExp are slow (perhaps a function with .indexOf, it shuld be tested), but it is working well
You can replace getElementsByClassName() with the following:
function getbyclass(n){
var elements = document.getElementsByTagName("*");
var result = [];
for(z=0;z<elements.length;z++){
if(elements[z].getAttribute("class") == n){
result.push(elements[z]);
}
}
return result;
}
Then you can use it like this:
getbyclass("description") // Instead of document.getElementsByClassName("description")