Populate menu with a text file eg text.txt - javascript

I am trying to build a kiosk on a local machine only. I'm planning to use JavaScript to make the menu lists functional. Here is my html code example.
<ul class="sf-menu">
<li class="current">
Area1
<ul>
<li>
John's Store
</li>
<li class="current">
Katy's store
<ul>
<li class="current">Orange</li>
<li>Watermelon</li>
<li>Apple</li>
</ul>
</li>
<li>
Catherine's Store
<ul>
<li>Banana</li>
<li>Pear</li>
<li>Cherry</li>
</ul>
</li>
</ul>
</li>
<li>
Area2
<ul>
<li>
Peter
<ul>
<li>Apple</li>
<li>Rockmelon</li>
</ul>
</li>
<li>
Lynda
<ul>
<li>Strawberry</li>
<li>Jackfruit</li>
<li>Orange</li>
</ul>
</li>
</ul>
</li> <!--current-->
</ul> <!--sf-menu-->
The person who is going to update/change the menu(which is going to be massive) is going to use a simple text file eg notepad - .txt (for certain reasons). Is there any way to update the menu items with a simple text file? Can I use a JavaScript or jQuery plugin/code?
Any direction would be appreciated.

You can do this using .get:
var textFile = "SCHEME://DOMAIN/FILENAME.txt";
jQuery.get(textFile, function(textFileData) {
//Parse file and populate menu based on specs.
//textFileData will have the text
}
If you want the text back for each line you can do (assuming the names are separated by a newline):
var EachLineInTextFile= textFileData.responseText.split("\n");
for (var i = 0, len = EachLineInTextFile.length; i < len; i++)
{
//This will give you each name from here you can put the name where you want it
}
A sample would be:
<script type="text/javascript">
$(document).ready(function () {
var textFile = "http://localhost/MyDomain/Menu.txt";
jQuery.get(textFile, function (textFileData) {
var EachLineInTextFile = textFileData.responseText.split("\n");
for (var i = 0, len = EachLineInTextFile.length; i < len; i++) {
STORE_TO_REPLACE = EachLineInTextFile[i];
//STORE_TO_REPLACE: I would have to the entire format of your file to do this.
}
})
});
</script>
From here, if you need help replacing the values in your list take a look at this article
Or, if you want to replace them all you can use .each to iterate through your list.

Related

All texts in HTML elements should have a new line character['\n']

Every text value inside an HTML element needs a new line character. Here is the dart method I used to do it. However, it failed to add new lines for the given type of HTML elements. I would like to know how can I change this method which can success for all types of cases.
Thanks in advance.
Code
dom.Element loop(dom.Element node){
final List<dom.Element> elements = node.children;
for (int i = 0; i < elements.length; i++){
if(elements[i].hasContent() && elements[i].children.isEmpty){
elements[i].innerHtml = '${elements[i].text}\n';
continue;
} else
if(elements[i].children.isNotEmpty){
loop(elements[i]);
}
}
return node;
}
Input HTML element
<div>
<ul>
<li>test1</li>
<li>
test2
<ul>
<li>
test3
<ul>
<li>test4</li>
<li>test5</li>
</ul>
</li>
<li>test6</li>
</ul>
</li>
<li>test7</li>
</ul>
</div>
Expected result
<div>
<ul>
<li>test1\n</li>
<li>
test2\n
<ul>
<li>
test3\n
<ul>
<li>test4\n</li>
<li>test5\n</li>
</ul>
</li>
<li>test6\n</li>
</ul>
</li>
<li>test7\n</li>
</ul>
</div>
Here is a javascript implementation of the answer (You can change it to dart easily)
function loop(node) {
const elements = node.children
for(const element of elements) {
if(element.children.length > 0) loop(element)
else if(element.textContent.length > 0) {
element.innerHTML = element.textContent + " \\n "
}
}
}
This works except it won't change the text of a parent node. If you add \n to a parent node like li2 you will get the \n after everything including its children, there is no way to just select that initial text that I can see. You may need to do more research in that area.
The output of the above function.
<div>
<ul>
<li>test1\n</li>
<li>
test2
<ul>
<li>
test3
<ul>
<li>test4\n</li>
<li>test5\n</li>
</ul>
</li>
<li>test6\n</li>
</ul>
</li>
<li>test7\n</li>
</ul>
</div>

Add active_section class to section of menu

I've got an html menu as below...
<ul class="menu" id="menu">
<ul class='section' id='section_1'>
<li><span id='section_title_1' class='section_title'><a href='#' id='section_link_1'>Against the odds.</a></span>
<ul>
<li id='exhibit_1' class='exhibit_title'> → Introduction
</li>
<li id='exhibit_2' class='exhibit_title'><a href='../against-the-odds/deriving-functions'> → Deriving functions</a>
</li>
<li id='exhibit_3' class='exhibit_title'><a href='../against-the-odds/exploiting-odds'> → Exploiting odds</a>
</li>
<li id='exhibit_4' class='exhibit_title'><a href='../against-the-odds/betting_history'> → Betting history</a>
</li>
</ul>
</li>
</ul>
<ul class='section' id='section_2'>
<li><span id='section_title_2' class='section_title'><a href='http://themathsproject.co.uk' id='section_link_2'>Remembering everything.</a></span>
<ul>
<li id='exhibit_104' class='exhibit_title'><a href='#'>black swans</a>
</li>
</ul>
</li>
</ul>
<ul class='section' id='section_5'>
<li><span id='section_title_5' class='section_title'><a href='http://themathsproject.co.uk' id='section_link_5'>Running faster.</a></span>
<ul>
<li id='exhibit_107' class='exhibit_title'><a href='#'>possible areas to explore</a>
</li>
<li id='exhibit_108' class='exhibit_title'><a href='#'>developing the model</a>
</li>
<li id='exhibit_109' class='exhibit_title'><a href='#'>performance</a>
</li>
</ul>
</li>
</ul>
<ul class='section' id='section_4'>
<div class='bot'>
<p>twitter
<br />
facebook
</p>
</div>
</ul>
</ul>
It's composed of several "sections" which house links (relevant to the section). Each section has a main title (e.g. Against the odds.) and several sub-sections (which are stored in another ul) like "deriving functions". The subsections are set to display: none by default (I have jQuery which opens the sub-sections if the user wishes to).
The problem:
Once the user clicks on a sub-section link (e.g. www.themathsproject.co.uk/against-the-odds/deriving-functions), I want the sub-section which houses the link (in the case id=section_1) to be open on the page reload so that the user can easily navigate to other links in the section. The other sub-sections would remain closed.
I would like to write a jQuery function which compares the current page url to the links in each section, and, if it finds a match, assign the "active_section" class to the relevant section. Unfortunately, I don't know how to do this.
I've been stuck on this all day and have made little headway.
I would greatly appreciate any help,
Jack
Your post is a little chaotic, so I will try to give you a general tips.
To get last element of your url use
var name = window.href.substr(this.href.lastIndexOf('/') + 1)
Now you can get all your subsections and iterate over them (for example using jQuery):
$('.sub-section').each(function() {
if ($(this).attr('id') === name) {
$(this).addClass('active');
}
});
If your ID's are different than names in url, you can create dictionary to map your equivalents:
var sectionMap = { "section-name-1": "sectionID1" };
And after you get url using first line of code I have provided, you can do:
name = sectionMap[name];

Append array to a class in javascript

I have an array in javascript called menuElm that has <ul> elements in it:
<ul id="1"></ul>
<ul id="2"></ul>
<ul id="3"></ul>
I have a page in HTML that has the following:
<ul id="menu">
<li class="menu-item"></li>
<li class="menu-item"></li>
<li class="menu-item"></li>
</ul>
I want to add the elements of menuElm to the HTML page so it would look like this:
<ul id="menu">
<li class="menu-item">
<ul id="1"></ul>
</li>
<li class="menu-item">
<ul id="2"></ul>
</li>
<li class="menu-item">
<ul id="3"></ul>
</li>
</ul>
I have tried the following, but the <ul> elements just wont show up in the page nor in the code:
function CreateMenu() {
var menuElm;
var k = 0;
menuElm = createElm("ul");
menuElm.id = ++k;
for (var i = 0; i < menuElm.length; ++i) {
document.getElementsByClassName("menu-item")[i].appendChild(menuElm[i]);
}
}
I am new with JavaScript, what am I doing wrong?
menuElm.length
The ul element doesn't have a length, so you are looping from 0 to 0, which is 0 iterations.
menuElm = createElm("ul");
This function isn't defined. You need document.createElement('ul');
menuElm = createElm("ul");
menuElm.id = ++k;
You appear to be creating one list item, and then changing its ID and appending it multiple times.
You need a new list item each time you go around the loop.
appendChild(menuElm[i]);
You've been treating menuElm as an element previously. It isn't an array, [i] makes no sense here.
$("#menu").find('li').each(function(i){
$(this).append(menuElm[i]);
});
/* if you want to use jquery here is the code to append */

Looking for elements with specific depth in JavaScript

I need to write a function in pure JavaScript witn no framework to get all specific tags, but only from first level under parent.
For example: I need to call some function on first <ul> and get all <li> from first level of it (<li> with text 1.2 and <li> with text 2.1)
<div id="sideNavigation">
<ul>
<li class=" act open ">
1.2
<ul>
<li class=" ">
1.2
<ul>
<li class=" ">
1.3
<ul>
<li class=" ">1.4</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class=" ">
2.1
<ul>
<li class=" ">2.2.1</li>
<li class=" ">2.2.2</li>
<li class=" ">2.2.3</li>
</ul>
</li>
</ul>
</div>
I've been trying to do it like this:
var allLi = document.getElementById("sideNavigation").getElementsByTagName("li");
but it returns all <li> in this div not only first level <li>. Do you have any quick method to solve my problem or do I have to implement a new function to detect depth of nodes
You can use the attribute .children to get those "li"
var firstDepthLi = document.getElementById("sideNavigation").children[0].children;
If you want a generic function you can create something like:
var getElementsByDepth = function(el, tagname, depth) {
var children = el.children;
var res = new Array();
for(var i=0; i<children.length; i++) {
if (children[i].tagName == tagname) {
res.push(children[i]);
if (depth > 0)
res.concat(getElementsByDepth(children[i], tagname, depth-1));
}
}
return res;
}
Try:
var allLi = document.getElementById("sideNavigation").getElementsByTagName("li")[0];
That should return the first li element out of all li's on the page. Change the zero at the end to a different number to get a different element. You could even set a variable for the value:
var liNum = 0;
var allLi = document.getElementById("sideNavigation").getElementsByTagName("li")[liNum];
And in a function:
function getLi(depth) {
var specificLi = document.getElementById("sideNavigation").getElementsByTagName("li")[depth];
return specificLi;
}
var firstLi = getLi(0);
console.log(firstLi);
<div id="sideNavigation">
<ul>
<li>First list tag</li>
<li>Second list tag</li>
<li>Third list tag</li>
</ul>
</div>
And to make the function even shorter, you could just do:
function getLi(depth) {
return document.getElementById("sideNavigation").getElementsByTagName("li")[depth];
}
That should work. :)

How to rearrange list?

Im trying to rearrange a list. I've got for example a list with categories:
<ul class="category">
<li class="cat1 active">cat1</li>
<li class="cat2 active">cat2</li>
<li class="cat3">cat3</li>
<li class="cat4">cat4</li>
</ul>
and a list with subjects
<ul class="subjects">
<li class="sub1">sub1</li>
<li class="sub2">sub2</li>
<li class="sub3">sub3</li>
<li class="sub4">sub4</li>
<li class="sub5">sub5</li>
<li class="sub6">sub7</li>
<li class="sub7">sub7</li>
<li class="sub8">sub8</li>
</ul>
What I want to do is when a certain category has the class active, some subjects will go to the top of the list. for example like this:
<ul class="subjects">
<li class="sub3">sub3</li>
<li class="sub5">sub5</li>
<li class="sub8">sub8</li>
<li class="sub1">sub1</li>
<li class="sub2">sub2</li>
<li class="sub4">sub4</li>
<li class="sub6">sub6</li>
<li class="sub7">sub7</li>
</ul>
I can do this with this code:
if($('li.cat1').hasClass('active')){
$('.sub3, .sub5, .sub8').insertBefore($('.subjects li:first-child'));
}
But then the real problem starts when multiple categories is active. I have done it like so:
if($('li.cat1').hasClass('active')){
$('.sub3, .sub5, .sub8').insertBefore($('.subjects li:first-child'));
}
if($('li.cat2').hasClass('active')){
$('.sub3, .sub4, .sub7').insertBefore($('.subjects li:first-child'));
}
The result is this:
<ul class="subjects">
<li class="sub4">sub4</li>
<li class="sub7">sub7</li>
<li class="sub3">sub3</li>
<li class="sub5">sub5</li>
<li class="sub8">sub8</li>
<li class="sub1">sub1</li>
<li class="sub2">sub2</li>
<li class="sub6">sub6</li>
</ul>
the order is now 4,7,3,5,8. Those are the numbers that have been selected but how do I rearrange them into: 3,4,5,7,8,1,2,6? Could someone help me with this? Here is the JsFiddle http://jsfiddle.net/NTPd4/2/
You could do 2 things to make it ALL good. First, make an sort method to suit your needs (i went by alpha of inner html, pik your poison). Second, make a variable for a jQuery object you can simply add elements too.
Next, use the variable in your if statements to gather the elements you want. Then before inserting, sort them!
Example
function sortAlpha(a,b){
return a.innerHTML.toLowerCase() > b.innerHTML.toLowerCase() ? 1 : -1;
};
var activeSubjects = $();
if ($('li.cat1').hasClass('active')) {
activeSubjects = activeSubjects.add($('.sub5, .sub3, .sub8'))
}
if ($('li.cat2').hasClass('active')) {
activeSubjects = activeSubjects.add($('.sub3, .sub4, .sub7'))
}
activeSubjects.sort(sortAlpha).insertBefore($('.subjects li:first-child'));
I think the .add will sort them automigikally, but keep in mind, you could also use the sort function straightforward, like:
$('.sub5, .sub3, .sub8').sort(sortAlpha);
Also, for your current setup (where all text is same except for number) you could use a sort function like:
function sortNum(a,b) {
return parseInt($(a).text().substring(3)) - parseInt($(b).text().substring(3));
}
However, the sortAlpha will probably better suite your needs in the long run. As I mentioned before, you can arrange your sort function how you like.
If you want all five elements in their original order, you need to move them at the same time. Use .add() to combine them:
$('.sub3, .sub5, .sub8').add('.sub3, .sub4, .sub7').prependTo($('.subjects'));
Or, integrating it into your code:
var $selector = $();
if ($('li.cat1').hasClass('active')) {
$selector = $selector.add('.sub3, .sub5, .sub8');
}
if ($('li.cat2').hasClass('active')) {
$selector = $selector.add('.sub3, .sub4, .sub7');
}
$selector.prependTo('.subjects');
http://jsfiddle.net/mblase75/GYfpv/

Categories

Resources