In a CMS that returns a list of results from a search, I have a list of items that looks something like this:
<ul class="results_odd_row">
<li class=title> Title </li>
<li class=published> Year </li>
<li class="author"> Author </li>
<li class="avail"> Out; try Another Search</li>
</ul>
<ul class="results_even_row">... </ul>
<ul class="results_odd_row">... </ul>
...etc...
For the "try another search" link, I'd like to append onto the url some information about the record, like "http://another.search?title=[title]&author=[author]", so that information can be used to execute the other search.
How can I identify elements that have no specific ID, and where there are multiple elements of the same class on the same page? In pseudo code, what I want might be something like:
1. href = base URL (http://another.search) plus
2. the text from the first <li> element above with class="title"
3. the text from the first <li> element above with class="author"
Also, I'm limited by the CMS to whatever javascript I can use within the A tag.
If it's not already obvious, I'm a complete newbie with javascript, so please don't feel your potential response is insultingly basic.
You can build your query string in this way
var baseUrl = "http://another.search"
var author = $('.results_even_row .author, .results_odd_row .author').first().text();
var title = $('.results_even_row .title, .results_odd_row .title').first().text();
var queryString = baseUrl + "?title=[" + title + "]&author=[" + author + "]"
Try it here.
Then you just use this string for the next search.
Related
I am trying to find a way to do something with JavaScript. I have a list of exercises, they are 5, and I want when I click on one of them, this exactly one to be transferred to another list(right one), this will be the exercises the user choose from the left list, and if he changes his mind, to be able to return this exercise to the left list. Also, when some exercises are chosen, to be visible only on the right site.
<ul id="left" th:each="exercise : ${exercises}">
<button type="submit">
<li th:text="${exercise.name}">
</button>
</li>
</ul>
<ul id="right" th:each="exercise : ${exercises}">
<button type="submit">
<li th:text="${exercise.name}">
</button>
</li>
</ul>
Something like that.
(I build the whole project with Java and Spring)
I assume the 2 lists come from the Back End and are rendered on the UI.
You need to send a request to the server to tell that an item that clicked on to the server "API endpoint" to move the item to the 2nd list
If you are using ajax you need to send a get request to get the updated lists
If you are using Spring MVC that will require reloading the View to update the UI
If the lists are built on the Front end and then will be submitted to the server
You need to remove the element from 1st list and then add it to the 2nd list
<ul id="left">
<li id="i" onclick="remove(this)">Item that clicked on</li>
</ul>
<ul id="right">
<li id="li1">li 1</li>
<li id="li2">li 2</li>
</ul>
<script>
function remove(el) {
const textContent = el.textContent;
// copy classes or id or anything
el.remove();
addElementToRightList(textContent);
}
function addElementToRightList(textContent) {
const parent = document.querySelector("#right");
const element = document.createElement("li");
// do stuff with element eg: set text by getting it from item that clicked on using textContent
element.textContent = textContent;
parent.appendChild(element);
}
</script>
I've created a custom multifield component (titled "breadcrumbs") that will be used as a page's breadcrumbs nav. Each multifield item consists of a textfield and a pathbrowser. I want to list out each multifield item as an anchor tag with the "text" property as the text and the "link" property as the href.
right now, i just have my html listing out the properties as follows:
<div>
<p>${properties.text}</p>
<p>${properties.link}</p>
</div>
which outputs this to the page:
text 1,text 2
link 1,link 2
I know how to use data-sly-list and data-sly-repeat for each of the properties to get a list of all the texts and links like this:
<ul data-sly-list="${properties.text}">
<li><p>${items}</p></li>
</ul>
<ul data-sly-list="${properties.link}">
<li><p>${items}</p></li>
</ul>
but is there a way to list out both properties into one element that would look something like this:
<ul data-sly-repeat.breadcrumbs="${properties}">
<li>
<a href="${breadcrumbs.text}">
${breadcrumbs.link}
</a>
</li>
</ul>
I have also tried data-sly-use with a custom js file, but also can't get multiple properties to loop in one element.
I'd strongly recommend going with a multifield that stores the fields as JSON or nodes like ACS multifield so you get a better data structure for your purpose. I do not recommend the below solution unless you are 100% certain that both link and text are going to be the same length AND in the correct order.
that said, assuming text and link are each multivalued properties, here is what you can do:
<ul data-sly-list.textItem="${properties.text}">
<li>
<a data-sly-attribute.href="${properties.link[textItemList.index]}">
${textItem}
</a>
</li>
</ul>
this will print:
ul>
<li>
<a title-href="link1">
</a>
</li>
<li>
<a title-href="link2">
</a>
</li>
</ul>
since the var name for data-sly-list, the custom identifier textItemList is created. We are interested in the member index on textItemList and use that to display the item at the same index in link by doing: properties.link[textItemList.index]
read more about data-sly-list in the spec
*note: you can also do this with the data-sly-repeat
For example,
var relevantItems = ul.querySelectorAll('li.someClass[data-x=someData]')
Should only match these elements from the outer, referenced <ul>:
<ul>
<!-- This <li> matches -->
<li class="someClass" data-x="someData">
<ul>
<!-- depending on the query, there may be some extra matches within the hierarchy, but these should not be searched or included in the results -->
</ul>
</li>
<!-- need to also includes additional matches like this one: -->
<li class="someClass" data-x="someData">
</li>
</ul>
Right now I have a couple of options:
Use JavaScript to loop over childNodes/children array and compare the className and dataset.x variables traditionally.
Give each <ul> its own id and use the #id> prefix feature like so:
ul.querySelectorAll('#' + ul.id + ' > li....')
Is there a simpler syntax, or alternative function, e.g. filtering the childNodes List somehow, to achieve the same query? (without adding an external library i.e. jQuery)
Ok lets say I have:
<title>Monkey</title>
and then some navigation:
<ul id="navigation">
<li>
Monkey
</li>
</ul>
As the site loads, the title of the page gets stored as a variable, then I want the string to match anything within #navigation, in this case it is Monkey. After finding the string of text it then assigns a class:
<ul id="navigation">
<li class="current">
Monkey
</li>
</ul>
Are there any examples people can refer me to?
Try this:
$('#navigation a').filter(function() {
return $(this).text() == document.title;
}).closest('li').addClass('current');
I am using a vendor-supplied API that uses javascript to output HTML that essentially looks like this:
<li class="parent_class"> Parent Name </li>
<div class="child_class">
<li> Child Name 1 </li>
<li> Child Name 2 </li>
</div>
<li class="parent_class"> Parent Name 2 </li>
<div class="child_class">
<li> Child Name 1 </li>
<li> Child Name 2 </li>
</div>
And so on. This is the code I'm going for:
<li class="parent_class"> Parent Name
<ul id="xc">
<li> Child Name 1 </li>
<li> Child Name 2 </li>
</ul> </li>
<li class="parent_class"> Parent Name 2 </li>
<ul id="1">
<li> Child Name 1 </li>
<li> Child Name 2 </li>
</ul></li>
(Just in case it is useful: I will be putting a <ul> tag before the API call and a </ul> tag after it to close up the whole list.)
Using more javascript, I've figured out how to replace the </div> with the </ul></li> using regular expression replace, but I'm not sure how to replace the </li><div> tags with the <ul> tags, because those need to be different every time. The first <ul> MUST be <ul id="xc"> (due to even more code I don't have control over). The other <ul>s must each have an ID, but those can be randomly generated.
I have a vague idea that I can use the exec method to create an array of all instances of </li></div>, set array[0] to <ul id="xc"> and then set array[1] to <ul id="1">, array[2] to <ul id="2"> and so on, but I'm not sure if that's a good idea (or how exactly to do it).
Thanks in advance.
Assuming you receive the HTML as a string (as opposed to a document), you can convert it using this function:
function mogrify (input) {
// 1) replace </li><div> with <ul>
var i = 0;
var out = input.replace(/<\/li>\s*<div[^>]*>/g, function () {
var listID = i == 0
? "xc"
: "xc_" + (Math.floor(Math.random() * 1e9) + 1);
++i;
return '<ul class="' + listID + '">';
});
// 2) replace </div> with </ul></li>, like you described:
return out.replace(/<\/div>/g, "</ul></li>");
}
Note that the input HTML is syntactically invalid, as is using bare numbers as ID attributes.
Use a DOM parser which is perfectly suited for mark up languages such as HTML, NOT regular expressions.
You can use .getElementsByTagName and .getAttribute to grab what divisions you need and setAttribute, createElement, appendChild to create.