Ordering a complex unordered list with javascript - javascript

I am looking for a way to sort a fairly complicated html unordered list using either standard javascript or jQuery.
Please view the HTML, the order needs to be alphabetical and based on the HTML found inside the ".keywordType span value" but needs to construct the order of the top level li (with the unique keyword_xxx). I've just pasted 2 of the list items out of dozens.
<ul class="keywords">
<li id="keyword_185">
<div class="icon_keyword"></div>
<input type="hidden" class="keywordLabel" value="More opening hours">
<div class="data-wrapper">
<div class="keywordType">
<span class="oh">Payment methods</span>
</div>
<div class="keywordValue">
<span id="keyword_185" class="oh">Credit Card, PayPal</span>
</div>
</div>
<a class="edit" title="Edit keywords"></a>
<a class="delete" title="Delete keywords"></a>
</li>
<li id="keyword_192">
<div class="icon_keyword"></div>
<input type="hidden" class="keywordLabel" value="Monday to Friday: 8:30am to 6:30pm Saturday: 9pm to 6:30pm Sunday: 10 - 4pm">
<div class="data-wrapper">
<div class="keywordType">
<span class="oh">Opening Hours</span>
</div>
<div class="keywordValue">
<span id="keyword_192" class="oh">Monday to Friday: 8:30am to 6:30pm<br>Saturday: 9pm to 6:30pm<br>Sunday: 10 - 4pm</span>
</div>
</div>
<a class="edit" title="Edit keywords"></a>
<a class="delete" title="Delete keywords"></a>
</li>
</ul>
Thanks

var list = $('ul.keywords');
var listItems = $('li', list);
listItems.sort(function (a, b) {
return $(a).text() > $(b).text() ? 1 : -1;
});
list.append(listItems);
You can sort the list of elements (jQuery objects have all the methods of Array, including Array.prototype.sort).
In the comparison function simply compare the text content of the list items. Individual letters will be subsequently compared according to their position in the alphabet (Unicode table, actually). For example, k > a is true.
Finally, just re-append the items to the list.
Demo: http://jsbin.com/igesic

Take a look at this, it exactly matches your requirement.
http://james.padolsey.com/javascript/sorting-elements-with-jquery/

Does this help?
var arr;
$('.keyword span').each( function( i, el){
arr[i] = $(el).text();
});
arr.sort();
I tested it on this question page, the code below orders the list of related questions in the right hand col.
var arr;
$('.question-hyperlink').each( function( i, el){
arr[i] = $(el).text();
});
arr.sort();

Related

Sort Parent Elements by criteria of Child Elements with JavaScript and / or TinySort

I have a series of list items in the following structure. I am trying to use Tinysort to sort the list items of the ordered list class="collection-grid editable ui-sortable". The criteria for sorting is the text in double stars below which is the text of div class collection-item-title.
<div id="collection-items" class="collection-items">
<ol class="collection-grid editable ui-sortable">
<li class="collection-item-container track_play_hilite subscriber-item initial-batch active editing">
<div class="collection-title-details">
<a href="https://sts9.bandcamp.com/album/20190907" class="item-link">
<div class="collection-item-title">
**2019.09.07 :: Red Rocks Amphitheatre :: Morrison, CO**
</div>
</a>
</div>
</li>
<li class="collection-item-container track_play_hilite subscriber-item initial-batch active editing">
<div class="collection-title-details">
<a href="https://sts9.bandcamp.com/album/20190906" class="item-link">
<div class="collection-item-title">
**2019.09.06 :: Red Rocks Amphitheatre :: Morrison, CO**
</div>
</a>
</div>
</li>
</ol>
</div>
What I have so far is the following:
tinysort('ol#collection-grid editable ui-sortable>li',{selector:'div.collection-item-title'});
This doesn't seem to work. I am open to any methods that will work an I am not limited to Tinysort.
I was able to use the below function to sort the items correctly.
function sortUsingNestedText(parent, childSelector, keySelector) {
var items = parent.children(childSelector).sort(function(a, b) {
var vA = $(keySelector, a).text();
var vB = $(keySelector, b).text();
return (vA > vB) ? -1 : (vA < vB) ? 1 : 0;
});
parent.append(items);
}
sortUsingNestedText($('.collection-grid'), "li", "div.collection-item-title");

Protractor Map or Filter function on a table which is having repeater with inside div elements

Below is the html for a table with repeater> div> a> span.
How I can work with filter or Map function to get the compare the second column value i.e idea = ideaOne + ideaTwo + ideaThree + ideaFour along with first column value in loop as this is an anchor tag. Also what would be the proper way to deal with all table values.
Repeater gives me the complete table values but when we use filter & try to click on the first cell value, it's did perform any action neither fail the It block. console value shows all the repeater values are coming in array.
Page Object Class-
getAllTableValues: function () {
return element.all(by.repeater('idea in ctrl.ideaList.ideas')).filter(function(elem) {
return elem.getText().then(function(text) {
return text === 'K';
});
}).click();
},
Spec Class:
tablePage.getAllTableValues().then(function (val) {
console.log("####"+ val);
});
Html Code:
<ul class="total_ideas">
<!----><li ng-repeat="idea in ctrl.ideaList.ideas" class="" style="">
<div class="protractor testing">
<a class="item_idea" ui-sref="xxx.xxx.xxx.xxx.xxx({
'id': idea.id,
'value': idea.name,
'start': (ctrl.dateRange.start | date: 'M-d-y'),
'end': (ctrl.dateRange.end | date: 'M-d-y')
})" href="/xxx/xxx/;value=K">
K
</a>
</div>
<div class="protractor test testing">
<span ng-bind="ctrl.getTotalIdeas(idea)">6</span>
</div>
<div class="protractor test testing">
<span ng-bind="idea.testTerms[ctrl.period].ideaOne">2</span>
</div>
<div class="protractor test testing">
<span ng-bind="idea.testTerms[ctrl.period].ideaTwo">2</span>
</div>
<div class="protractor test testing">
<span ng-bind="idea.testTerms[ctrl.period].ideaThree">2</span>
</div>
<div class="protractor test testing">
<span ng-bind="idea.testTerms[ctrl.period].ideaFour">0</span>
</div>
</li><!----><li ng-repeat="idea in ctrl.ideaList.ideas" class="">
</li><!---->
</ul>
Please suggest here.

Highlight [class.active] of nested ngFor element in Angular2

I am displaying my nested for loop correctly but I am having trouble when highlighting the individual selected li element in the nested array, so the undesired result is everything in that row highlights based on whatever number i is.
<div class="nopadding week" style="width: 12%;" *ngFor="let day of Schedule; let j = index">
<ul class="nopadding">
<div *ngFor="let hour of day.hours; let i = index" class="hours">
<li class="hour" [ngClass]="{watched: hour.assignments.length> 0, unassigned: hour.assignments.length <= 0}" (click)="selectedtimeslot(hour.assignments, i)" [class.active]="i == selectedRow">
{{hour.assignments.length}}
</li>
</div>
</div>
</ul>
</div>
In my component I have the function that set that value of the selected row.
selectedtimeslot(item: any, index:any) {
this.selectedRow = index;
this.highlightGuardian.changeNav(item);
}
scss
li.active {
background-color:#123456 !important;
color: white;
}
I think I know my problem is that I am nit giving the [class.active] any information about the parents index in order to correctly highlight the selected element
You are correct that your issue is you aren't giving it any parent information, so it is highlighting the selected index of every parent.
Instead of making your selectedRow be equal to a number, make it an hour, and send it the hour, like so.
<div *ngFor="let hour of day.hours; let i = index" class="hours">
<li class="hour" [ngClass]="{watched: hour.assignments.length> 0, unassigned: hour.assignments.length <= 0}" (click)="selectedtimeslot(hour.assignments, hour)" [class.active]="hour == selectedRow">
{{hour.assignments.length}}
</li>
</div>
This will ensure that it only matches that single div, as it will do an object compare, instead of an index compare.

Sort div by span class

EDIT
I have this working in fiddle http://jsfiddle.net/gandjyar/HM67V/ but can't get it working outside of fiddle... ideas?
I have the following code:
<div id="sort">
<p>Sort Communities By: North | South | East | West | ALL
</p>
</div>
<div class="fp-floorplans">
<div id="fp-link">
Community 1
</div>
<div id="wpcf-field-location" class="wpcf-field-checkboxes wpcf-field-location">
<span class="wpcf-field-name wpcf-field-checkboxes wpcf-field-location-name">Loation:</span>
<span class="wpcf-field-value wpcf-field-checkboxes-value wpcf-field-location-value">South</span>
</div>
<div id="wpcf-field-schools" class="wpcf-field-textfield wpcf-field-schools">
<span class="wpcf-field-name wpcf-field-textfield wpcf-field-schools-name">School(s):</span>
<span class="wpcf-field-value wpcf-field-textfield-value wpcf-field-schools-value">Southwest</span>
</div>
<div id="wpcf-field-price-starting-at" class="wpcf-field-textfield wpcf-field-price-starting-at">
<span class="wpcf-field-name wpcf-field-textfield wpcf-field-price-starting-at-name">Price Starting At:</span>
<span class="wpcf-field-value wpcf-field-textfield-value wpcf-field-price-starting-at-value">$100's</span>
</div>
</div>
<div class="fp-floorplans">
<div id="fp-link">
Community 2
</div>
<div id="wpcf-field-location" class="wpcf-field-checkboxes wpcf-field-location">
<span class="wpcf-field-name wpcf-field-checkboxes wpcf-field-location-name">Loation:</span>
<span class="wpcf-field-value wpcf-field-checkboxes-value wpcf-field-location-value">East</span>
</div>
<div id="wpcf-field-schools" class="wpcf-field-textfield wpcf-field-schools">
<span class="wpcf-field-name wpcf-field-textfield wpcf-field-schools-name">School(s):</span>
<span class="wpcf-field-value wpcf-field-textfield-value wpcf-field-schools-value">Southeast</span>
</div>
<div id="wpcf-field-price-starting-at" class="wpcf-field-textfield wpcf-field-price-starting-at">
<span class="wpcf-field-name wpcf-field-textfield wpcf-field-price-starting-at-name">Price Starting At:</span>
<span class="wpcf-field-value wpcf-field-textfield-value wpcf-field-price-starting-at-value">$100's</span>
</div>
</div>
and I want to be able to sort by North, South, East, West for the 'wpcf-field-location-value' or just ascending for the 'wpcf-field-schools-value'.
I've tried implementing some suggestions that I've found but none have worked. (Jquery - sort DIV's by innerHTML of children and Sorting divs by number inside div tag and jQuery)
First: you can't have same id values in your html. You can add a user attribute by giving it data-id. An id property value must be unique for the whole document.
Since North,South,East,West are not alphabetically ordered you need to replace them with another value.
Using the code provided here (with some edits): Jquery - sort DIV's by innerHTML of children
var direction={north:0,south:1,east:2,west:3}
function sortOn(primary){
primary=primary.toLowerCase();
for(item in direction){
if(direction[item]===0){
break;
}
}
var tmp=direction[primary];
direction[primary]=0;
direction[item]=tmp;
var items = $(".fp-floorplans").sort(function(a, b) {
var vA = $(a).find("wpcf-field-location-value").text().trim().toLowerCase();
var vB = $(b).find("wpcf-field-location-value").text().trim().toLowerCase();
if(directions[vA]===directions[vB]){
//secondary search
vA = $(a).find("wpcf-field-schools-value").text().trim().toLowerCase();
vB = $(b).find("wpcf-field-schools-value").text().trim().toLowerCase();
return (vA < vB) ? -1 : (vA > vB) ? 1 : 0;
}
// primary searh (a and b cannot be the same)
return (vA < vB) ? -1 : 1;
});
}
sortOn("west");
To change the priority of the order (like west first) you can change the directions variable before sorting:
direction={north:3,south:1,east:2,west:0}
Fist you need to see what value currently holds the 0 and then replace it with the new on.

I am having a few problems trying to create a jquery live search function for basic data set?

I am designing a simple jquery live search function within a widget on a site i'm developing. I have borrowed some code I found and it is working great. The problem is though that instead of using a list like this:
<ul>
<li>Searchable Item 1</li>
<li>Searchable Item 2</li>
etc
I am using a list like this:
<ul>
<li>
<a href="#">
<div class="something>
<img src="something.jpg">
<p>Searchable Item 1</p>
</div>
</a>
</li>
etc.
As you can see the text I want to search is in the p tag. The functions I have used are searching all the other stuff (a href, div, img) and matching text found in those tags as well as the item within the p tag. Sorry if my explanation is a bit confusing but I will show you an example of the code here:
//includes im using
<script type="text/javascript" src="js/jquery-1.7.min.js" ></script>
<script type="text/javascript" src="js/quicksilver.js"></script>
<script type="text/javascript" src="js/jquery.livesearch.js"></script>
//document ready function
$(document).ready(function() {
$('#q').liveUpdate('#share_list').fo…
});
//actual search text input field
<input class="textInput" name="q" id="q" type="text" />
//part of the <ul> that is being searched
<ul id="share_list">
<li>
<a href="#">
<div class="element"><img src="images/social/propellercom_icon.jpg… />
<p>propeller</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="element"><img src="images/social/diggcom_icon.jpg" />
<p>Digg</p>
</div>
</a>
</li>
<li>
<a href="#">
<div class="element"><img src="images/social/delicios_icon.jpg" />
<p>delicious</p>
</div>
</a>
</li>
</ul>
also here is the jquery.livesearch.js file I am using
jQuery.fn.liveUpdate = function(list){
list = jQuery(list);
if ( list.length ) {
var rows = list.children('li'),
cache = rows.map(function(){
return this.innerHTML.toLowerCase();
});
this
.keyup(filter).keyup()
.parents('form').submit(function(){
return false;
});
}
return this;
function filter(){
var term = jQuery.trim( jQuery(this).val().toLowerCase() ), scores = [];
if ( !term ) {
rows.show();
} else {
rows.hide();
cache.each(function(i){
var score = this.score(term);
if (score > 0) { scores.push([score, i]); }
});
jQuery.each(scores.sort(function(a, b){return b[0] - a[0];}), function(){
jQuery(rows[ this[1] ]).show();
});
}
}
};
I believe the problem lies here:
var rows = list.children('li'),
cache = rows.map(function(){
return this.innerHTML.toLowerCase();
});
it is just using whatever it finds between the li tags as the search term to compare against the string entered into the text input field. The search function actually does work but seems to find too many matches and is not specific as I am also using a quicksilver.js search function that matches terms that are similar according to a score. When I delete all the other stuff from the li list (a href, img, div, etc) the search function works perfectly. If anyone has any solution to this I would be really greatful, I have tried things like:
return this.children('p').innerHTML but it doesn't work, I'm ok with PHP, C++, C# etc but totally useless with javascript and Jquery, they're like foreign languages to me!
In the jquery.livesearch.js file I believe you can replace this line:
var rows = list.children('li'),
with:
var rows = list.children('li').find('p'),
This should make it so the livesearch plugin will only search the paragraph tags in your list.
You will need to change the .show()/.hide() lines to reflect that you are trying to show the parent <li> elements since you are now selecting the child <p> elements:
Change:
rows.show();//1
rows.hide();//2
jQuery(rows[ this[1] ]).show();//3
To:
rows.parents('li:first').show();//1
rows.parents('li:first').hide();//2
jQuery(rows[ this[1] ]).parents('li').show();//3

Categories

Resources