Selecting last element of a list - mootools

Trying to select the last element of a list, I can't grasp the fundamentals of getElements, here is the html code
<section class="main">
<ul>
<li>Lorem ipsum dolor sit amet.</li>
<li>Consectetur adipisicing.</li>
<li>Lorem ipsum dolor</li>
</ul>
</section>
see this selectors:
main = $$('section.main') // ok
main.getElements('li').getFirst() // .getFirst is not a function
main.getElements('li').getLast() // Object [ li, li, li, li, li, li ]
main.getElements('ul').getLast('li') // Object [ ul ]
main.getElement('ul').getElements('li').getLast().getLast() // li, Works!!
getLast should return the last element of an array, is it?

A lot of mootools functions, when applied to an array, apply that function to every element in that array.
$$ returns an Array. so 'main' is an Array
getElements('li'), when invoked on an Array, invokes itself on every element of that Array. So now you've got an Array of Arrays. (actually, they're Elements objects, but let's ignore that)
main.getElements('li').getLast() returns you the last array in that Array of Arrays, which is why you're still getting an array instead of an element.
In other words, main.getElements('li').getLast() is equivalent to: main.getLast().getElements('li').

Related

how to fetch first ul element items from nokogiri in rails?

i am having the following html that contains 2 UL elements.
<ul>
1
2
3
<ul>
4
5
6
i am using the following logic to get the data from only first Ul element. but iam getting data from both ul elements. How can i fetch the data only from a first UL element?
uls = xyz_html.css('ul li')
uls.each do |li|
#ul_list_1 << li.text
end
#ul_list_1 displaying all the data as an array like [1, 2,3, 4,5,6] but i need output [1,2,3]
i tried the following logic also but i did not get the output
uls = xyz_html.css('ul:first-child li')
uls.each do |li|
#ul_list_1 << li.text
end
Can some one help me with this
You can use first-of-type CSS selector, which returns first occurence of given element, so:
xyz_html.css('ul:first-of-type li')
More info: https://css-tricks.com/almanac/selectors/f/first-of-type/

React: How to provide procedurally generated <li> elements distinct HTML id values?

I'm rendering a map of items retrieved from a database and filtered via the value state of an input field and attempting to then set the state of the input field as the value stored in some list item on click. I figured that using document.getElementById().innerHTML would allow me to retrieve the content stored within the appropriate tag and then set it to state which does work, the issue I'm facing is that it will only retrieve the innerHTML of the first item rendered in the map.
I've tried solutions ranging from applying UUID to making the mapped content available to the window and transfering the state of the individual objects but each disparate solution only moves the value of the first item to state - any ideas?
Rendered Content:
window.filteredItems = this.state.items.filter(
(item) => {
return item.companyNameObj.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
}
);
<div className="fixed-width">
<div className="search-container">
<form>
<input type="text" name="search" className="search-bar" placeholder="Search: " onChange={this.handleChange} value={this.state.search} />
</form>
<ul className="search-results">
{window.filteredItems.map((item) => {
return (
<div className="distinct-result-container">
<li key={item.id}>
<div className="image-container">
<img src={item.imageObj} alt={item.companyNameObj + " logo."}/>
</div>
<div className="company-container">
<span onClick={this.stateTransfer}><h3 id={"ID"}>{item.companyNameObj}</h3></span>
<p>Owned by: {item.ownerNameObj}</p>
</div>
</li>
</div>
)
})}
</ul>
</div>
<Footer />
</div>
);
stateTransfer()
stateTransfer(id) {
var search = this.state.search;
var uniqueID = document.getElementById("ID").innerHTML;
this.setState({
search: uniqueID
});
}
The current content of stateTransfer() doesn't represent any significant attempts at approaching a solution to this issue, it's just the minimum required implementation to move the innerHTML content to the input fields value.
EDIT: I've further clarified on the task at hand and a potential solution in the comments below (which follow this), I'm just hoping someone is able to help me with the actual implementation.
#DILEEPTHOMAS The list is comprised of data pulled from a Firebase Realtime Database and is rendered via mapping the filteredList and a search query; that functoionality works fine - what I need is to be able to click the element of any distinct li and have the innerHTML (the text stored in that li's item.companyNameObj) be moved to the value of the input field (so users can navigate the search content with re-typing).
#JoshuaLink I can't necessarily configure the items of the list any
further as it's just data pulled from an external database - I believe
the appropriate solution is to somehow provide a unique HTML ID value
to each newly rendered li and have that selected ID moved to
stateTransfer() where it can be set as the input fields value, I'm
just struggling with the actual implementation of this.
EDIT 2: I've managed to figure out a solution to both parts of the problem as described above - I'll post it as an answer below.
I managed to solve both parts of my problem:
The key issue, which was moving the text stored in each distinct li to the input value, which was apparently easily solved by making my stateTransfer() function accept an event and passing the .innerText value of the h3 through the event (I assumed I would have to use .innerHTML, which would require me to provide each distinct li with a unique generated ID) as follows:
stateTransfer(e) {
var search = this.state.search;
var innerText = e.target.innerText
this.setState({
search: innerText
})
}
The secondary issue, (which I incorrectly assumed was integral to implementing a solution to my question), assigning unique HTML id values to my procedurally generated li's was solved by implementing a for-loop in a componentDidUpdate() function which iterates through the current total length of the list and and assigns an id with the loop iterator concatenated to the end of the string as follows:
componentDidUpdate() {
var i;
var searchCompanyNames = document.querySelectorAll('.comapnyNames');
for(i = 0; i < searchCompanyNames.length; i++) {
searchCompanyNames[i].id = 'companyName-' + i;
}
}
Whilst I didn't need to assign unique ID's to the li's in the correct implementation, it's a useful trick worth noting nonetheless.

Sort HTML emlements by child contents

I have these elements in a list. I want to sort the list alphabetically but how do i do that if the text that i want to sort it by is in a child element?
<div class="entry">
<button class="title btn btn-primary">Tale of Memories</button>
</div>
Without seeing your code, it is difficult to know exactly how things will work. Here is a generic solution:
Select all the elements in the list (eg: using querySelectorAll).
Transform the result of step 1 into an array (eg: with this solution from andrewmu)
Use the native sort() method to sort the array (providing your own function to compare values based on whatever you want).
Rewrite the content of the list with the content of the array.
Here is a demo. In it, we sort the list not based on the text directly in each item, but on the text from the span within each of them (for that reason the FA item goes first instead of last). In your case, you will want to change the compare function to get whichever element you want the items to be compared by:
// step 1: select the list items
var items = document.querySelectorAll("#mylist li");
// step 2: convert the node list into an array
var itemsarray = Array.prototype.slice.call(items, 0)
// step 3: sort the array using your own compare function
itemsarray.sort(function(a,b) {
return a.querySelector("span").innerHTML > b.querySelector("span").innerHTML;
});
// step 4: empty the list, and insert the sorted items
var ml = document.getElementById("mylist");
ml.innerHTML = "";
for (var x = 0; x < itemsarray.length; x++) {
ml.appendChild(itemsarray[x]);
}
<ul id="mylist">
<li><span>E</span></li>
<li><span>D</span></li>
<li><span>B</span></li>
<li>F<span>A</span></li>
<li><span>C</span></li>
</ul>

How to do a match with div with a custom-data of 'x' to a json object with the same value of 'x'?

I am not sure if this is achievable.
I have a list of li that all has a custom attribute with an unique value. I also have a JSON file that has a list of objects. Each object has a specific field that has the same value
Problem: I am trying to match the li attribute 'x' with the value 'x' inside the JSON. If that match is correct I want to grab all the fields inside the same object as 'x' and place it inside the li with attribute 'x'.
Please help, I am not sure how to start this. I will need some sample or even a jsfiddle example.
JSON Structure
[
{
"word": "hello",
"favnumber": "0070",
"item": "item1",
"color": "red"
},
{
"word": "hello world",
"favnumber": "0233070",
"item": "item2",
"color": "blue"
},
{
"word": "hello mom",
"favnumber": "0070",
"item": "item3",
"color": "pink"
},
{
"word": "hello dad",
"favnumber": "0070",
"item": "item4",
"color": "silver"
}
]
HTML Structure
<div>
<li data-item="item1">1</li>
<li data-item="item2">2</li>
<li data-item="item3">3</li>
<li data-item="item4">4</li>
</div>
HTML New Structure
<div>
<li data-item="item1">hello , 0070, item1, red</li>
<li data-item="item2">hello world, 0233070, item2, blue</li>
<li data-item="item3">hello mom, 231213, item3, pink</li>
<li data-item="item4">hello dad, 007021312, item4, silver</li>
</div>
You can split the overall task into simple sub-steps:
Query the DOM tree to extract the elements that have certain attributes (in your case, [data-item=*]).
For each of those elements, get the data-item attribute's value.
Loop through the JSON object, that represents an array, to find the element of this array respective to the DOM element found at the previous step.
Replace the DOM element's child text node to arbitrary value.
Let's walk through it.
Query the DOM tree to find elements with certain attributes
This is achieved with the help of document.querySelectorAll DOM API. The method takes the selector as its first parameter, pretty similar to what you'd write in CSS:
var items = document.querySelectorAll('[data-item]');
Now, inside items variable, you have a NodeList of elements. First step done.
Get the attribute value for every element
This is simple and can be done with something like
var name = items[0].getAttribute('data-item');
Now the name var stores a string that represents the [data-item]'s attribute value.
Since you have an array of NodeList elements, you have to loop through it:
for (var e in items) {
var element = items[e];
var name = element.getAttribute('data-item');
//...
}
Find the element in data array by element's property value
Now you have to put a loop into a loop so you can find an element that concurs with the element.
Like this:
for (var e in items) {
var element = items[e];
var name = element.getAttribute('data-item');
for (var i in data) {
var item = data[i];
// ...
}
}
Here, the item variable stores an object, one of many within the initial JSON array (named data in this particular example).
Next, you have to check if the item is one you need or not. In you case,
if (name == item.item) {
//...
}
because item's property item stores the value that has to concur with the value of [data-item] attribute of the DOM element.
Now, finally...
Replace the value
You may need something more specific to your task, but this example shows a simple element.innerText replacement.
Let's pretend you're within the if statement and its condition evaluated to true. Next, you want to do something like
var text = [];
text.push(item.word);
text.push(item.favnumber);
text.push(item.item);
text.push(item.color);
element.innerText = text.join(", ");
And that's it, basically.
You can see how the whole snippet works in this fiddle: http://jsfiddle.net/3r4rmLth/

Regex for index of string match spanning across several XML tags

I'm trying to insert a link in TLF. Normally you would simply simply use
var linkElement:LinkElement = textArea.textFlow.interactionManager.applyLink( ... );
The problem is that, if I create a link which spans across differently formatted text (bold, italic, etc), or heaven forbid across paragraphs and list items, it completely and utterly crashes and burns. Link formatting is completely lost, and list structures collapse.
Simply adding a LinkElement via addChild() doesn't work either, if we're going to keep both the formatting and the structure within the selected text.
Ripping out the textFlow for the selection with interactionManager.cutTextScrap(...), wrapping it in a LinkElement with interactionManager.applyLink( ... ), and then "pasting" back in... also creates a mess.
So I have to create my own link insertion routine.
What I've resolved to do is to:
1) convert the textflow tags to a string
2) find the start and end indexes of the selection within the textflow string
3) insert the following string at the start index:
</span><a href="[hrefVar]" target="[targetVar]"><span>
4) insert the following string at the end index:
</span></a><span>
5) reconvert the textflow string into a textflow object for the TextArea
And voila! Instant RTF link!
The only problem is... I have no idea how to write a regex parsing equation which can find the start and ending indexes for a string match inside XML markup where the result may be spread across several tags.
For instance, if the TextFlow is (abbreviated):
<TextFlow><p><span>Lorem Ip</span><span fontWeight="bold">sum do</span><span>
lor sit am</span><span fontStyle="italic">et, consectetur adipiscing elit.
</span></p></TextFlow>
Say, for instance, the user has selected "Ipsum dolor sit amet" to be converted into a link. I need to find the first and last indexes of "Ipsum dolor sit amet" within that RTF markup, and then insert the strings indicated in 3) & 4) above, so that the end result looks like this:
<TextFlow><p><span>Lorem </span><a href="http://www.google.ca" target="_blank">
<span>Ip</span><span fontWeight="bold">sum do</span><span>lor sit am</span>
<span fontStyle="italic">et</span></a><span>, consectetur adipiscing elit.
</span></p></TextFlow>
You might lose some style formatting, but I can fix that later parsing through the textflow formatting.
What I need is the regex to do step 2).
I know the regex to ignore tags and strip out the text between tags, and how to find a string match of the selected text in the stripped textflow text... but not how to find the match indexes within the original (unstripped) textflow string.
Anyone?
IMHO better way is to go through out the string instead of trying to go with regex.
Here is an idea for quick dirty way, this code need to be improved, but anyway it might give directions.
So main goal might be just "throw out" tags and match text, but counting gow many chars passed within the process.
//This code might need revision for not to get < and > symbols as fake tags starting and finishing points, also reseting searchwhen text not completly done.
var sourceStr:String = '<TextFlow><p><span>Lorem Ip</span><span fontWeight="bold">sum do</span><span>lor sit am</span><span fontStyle="italic">et, consectetur adipiscing elit.</span></p></TextFlow>';
var searchStr:String = "Lorem Ipsum d";
var indexes:Object = firstLast(sourceStr, searchStr);
trace(indexes.startIndex,indexes.finishIndex);
function firstLast(sourceStr:String, searchStr:String):Object
{
var indexCounter:int = -1;
var searchFlag:Boolean = true;
var searchPos:int = 0;
var searchChar:String;
var sourceChar:String;
var startIndex:int;
var finishIndex:int;
for (var i:int = 0; i < sourceStr.length; i++ )
{
indexCounter++;
sourceChar = sourceStr.substr(i, 1);
if (sourceChar == "<")
{
searchFlag = false;
}
else if (sourceChar == ">")
{
searchFlag = true;
}
if (!searchFlag)
{
continue;
}
searchChar = searchStr.substr(searchPos, 1);
if (sourceChar == searchChar)
{
if (searchPos == 0)
{
startIndex = indexCounter;
}
if (searchPos == searchStr.length - 1)
{
finishIndex = indexCounter;
}
searchPos++;
}
}
return { startIndex:startIndex, finishIndex:finishIndex };
}