I am trying to organize a observablearray that has inside 2 boolean values and a price. I need via knockout and 2 checkboxes, filter the elements by these two values. Also sort by price ( ascending and descending) the displayed values . I don't put any code because I'm new in knockout and I can't see the way to make these actions.
Appreciate someone who instructed me.
Simple answer, I tried with this, but making some changes on my personal viewModel to supply my needs. So, I make something like this:
self.elementsToShow = ko.pureComputed(function () {
// Represents a filtered and ordered list of elements
var recomend = self.showRecommended(); //chekbox 1
var special = self.showSpecial(); // checkbox2
var sorting = self.currentSortDirection(); //sort direction: price or rating //ascending or descending, represented by an observableArray with that conditions and the //selectedSortDirection
if (!recomend && !special) return self.myOservableArray().sort(function (a, b) {
//in case that no one of the checkboxes where selected but the sort direction was't by default
if (sorting.price != null) {
var fp = sorting.price ? -1 : 1;
ap = parseInt(a.price);
bp = parseInt(b.price);
return ap == bp ? 0 : (fp * (ap < bp ? -1 : 1));
}
else if (sorting.rate != null) {
var f = sorting.rate ? -1 : 1;
ar = parseFloat(a.rating);
br = parseFloat(b.rating);
return ar == br ? 0 : (f * (ar < br ? -1 : 1));
}
});
return ko.utils.arrayFilter(self.myOservableArray(), function (element) {
return (element.recommended != "0" && recomend) || (element.offer != "" && special); //some other conditions for the relection of the checkboxes in the observableArray
}).sort(function (a, b) {
if (sorting.price != null) {
var fs = sorting.price ? -1 : 1;
ap = a.price;
bp = b.price;
return ap == bp ? 0 : (fs * (ap < bp ? -1 : 1));
}
if (sorting.rate != null) {
var fu = sorting.rate ? -1 : 1;
ar = a.rating;
br = b.rating;
return ar == br ? 0 : (fu * (ar < br ? -1 : 1));
}
});
}, self);
Related
The code below shows my current workings. the commented out line sorts my divs but leaves the empty divs at the top.
the 4 lines above do not make a difference
I think I'm missing something really simple here
//Group 1
var alphabeticallyOrderedDivs7 = $('.group1').sort(function getSort(a, b) {
if($(a).find(a).text() === "") return 1;
if($(b).find(b).text() === "") return -1;
if($(a).find(a).text() === $(b).find(b).text()) return 0;
return $(a).find(a).text() < $(b).find(b).text()) ? -1 : 1;
//return String.prototype.localeCompare.call($(a).text().toLowerCase(), $(b).text().toLowerCase());
});
You can simply do this:
//Group 1
var alphabeticallyOrderedDivs7 = $('.group1').sort(function getSort(a, b) {
//Assuming $(a).text() and $(b).text() is the content of the div
return $(a).text() < $(b).text() ? 1 : $(a).text() > $(b).text() ? -1 : 0;
});
I have a scenario like this
var a,b;
if(a > 0 || b > 0){
var truthValue = // The value which was executed as true in the if condition either a or b
}
Now how do i identify which value is executed as true. I can write a separate if condition for both but in the process of minimizing the LOC i am trying this way.
Any help is appreciated.
Like this?
var truth, a=11, b=0;
if((truth = a) > 0 || (truth = b) > 0){
document.write(truth + "<br>")
}
var a=0, b=22;
if((truth = a) > 0 || (truth = b) > 0){
document.write(truth + "<br>")
}
var a,b;
a =1;
b=2;
if(((a > 0)? (truthValue =a) : false) || ((b > 0)? (truthValue =b) : false)){
alert(truthValue);
}
The following is a natural sort function I pulled from somewhere I forget exactly. I'm looking to modify it so that empty or null values always sort to the bottom regardless of asc/desc.
Here is what I have right now:
function gridNaturalSorter(a, b) {
if(a[sortcol])
a = a[sortcol].replace(/<(?:.|\n)*?>/gm, '');
if(b[sortcol])
b = b[sortcol].replace(/<(?:.|\n)*?>/gm, '');
if(b)
b = b.toString().substr(0, 15);
if(a)
a = a.toString().substr(0, 15);
var re = /(^([+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?)?$|^0x[0-9a-f]+$|\d+)/gi,
sre = /(^[ ]*|[ ]*$)/g,
dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
hre = /^0x[0-9a-f]+$/i,
ore = /^0/,
i = function(s) {
return gridNaturalSorter.insensitive && (''+s).toLowerCase() || ''+s
},
// convert all to strings strip whitespace
x = i(a).replace(sre, '') || '',
y = i(b).replace(sre, '') || '',
// chunk/tokenize
xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
// numeric, hex or date detection
xD = parseInt(x.match(hre)) || (xN.length != 1 && x.match(dre) && Date.parse(x)),
yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null,
oFxNcL, oFyNcL;
// first try and sort Hex codes or Dates
if (yD)
if ( xD < yD ) return -1;
else if ( xD > yD ) return 1;
// natural sorting through split numeric strings and default strings
for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
// handle numeric vs string comparison - number < string - (Kyle Adams)
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
return (isNaN(oFxNcL)) ? 1 : -1;
}
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
else if (typeof oFxNcL !== typeof oFyNcL) {
oFxNcL += '';
oFyNcL += '';
}
if (oFxNcL < oFyNcL)
return -1;
if (oFxNcL > oFyNcL)
return 1;
}
return 0;
}
If you know how to implement multiple comparators and a comparator that sorts null to bottom that's quite easy.
To implement multiple comparators, you just have to return the result of the first comparator that doesn't return 0.
Here I also created a withComparators helper function that allows to compose multiple comparators together. If you understand this code you will be able to easily come up with your own solution for your specific problem.
Note that your gridNaturalSorter function is a comparator just like nullsToBottom is in my example.
E.g.
var items = ['test', null, 'test1', 'test3', null, 'test4'];
items.sort(withComparators(nullsToBottom, textAsc));
//["test", "test1", "test3", "test4", null, null]
function nullsToBottom(a, b) {
return a === b? 0 : a === null? 1 : -1;
}
function textAsc(a, b) {
return a < b? -1 : +(a > b);
}
function withComparators() {
var comparators = arguments;
return function (a, b) {
var len = comparators.length, i = 0, result;
for (; i < len; i++) {
result = comparators[i](a, b);
if (result) return result;
}
return 0;
};
}
I am trying to implement a custom sorting in slick grid. I am using this as a reference https://github.com/mleibman/SlickGrid/wiki/DataView#sorting. I want to force rows with specific properties to always sort to the bottom of the grid. (I tried to get a working example of slickgrid to work in jsfiddle.net but I couldn't.) I have tried this but it's not working.
var gridData =[
{ Id:1, Code: '232046', Depth2: 4000,},
{ Id:2, Code: '23247', Depth2: 2000 },
{ Id:3, Code: '12543', Depth2: 1500, rowoption_stickyorder: 1 }
];
grid.onSort.subscribe(function (e, args) {
var footerOrderProperty = 'rowoption_stickyorder';
var comparer = function (a, b) {
var result = (a[args.sortCol.field] > b[args.sortCol.field]) ? 1 : -1;
if (b[footerOrderProperty] != undefined || a[footerOrderProperty] != undefined)
result = -1;
return result;
}
dataview.sort(comparer, args.sortAsc);
});
What am I missing?
if (b[footerOrderProperty] != undefined || a[footerOrderProperty] != undefined)
result = -1;
Won't work. false || true places an object/row with the property above one that does not have it.
var bb = b[footerOrderProperty],
aa = a[footerOrderProperty];
if(aa && !bb){
result = 1;
}
else if(!aa && bb)
{
result = -1
}
See my fiddle
Note: Fiddle won't work in Chrome due to the mime type issue and the common workaround of making the resource rawgithub doesn't seem to be working.
Origineil, great work! Your suggestion got me 99% of the way there. I really want to have the columns sortable in both directions and keep the rows at the bottom. I modified your code to take in account the sortOrder and it works like a champ.
grid.onSort.subscribe(function (e, args) {
console.log(args.sortAsc)
var footerOrderProperty = 'rowoption_stickyorder';
var comparer = function (a, b) {
var result = (a[args.sortCol.field] > b[args.sortCol.field]) ? 1 : -1;
var bb = b[footerOrderProperty],
aa = a[footerOrderProperty];
if (aa && !bb) {
result = args.sortAsc ? 1 : -1;
} else if (!aa && bb) {
result = args.sortAsc ? -1 : 1;
} else if (aa != undefined && bb != undefined) {
result = (aa > bb) ? 1 : -1;
result *= args.sortAsc ? 1 : -1
}
console.log(a.id + " | " + b.id + " " + result)
return result
}
dataView.sort(comparer, args.sortAsc);
});
Here is the updated fiddle.
I have following piece of code and this has started breaking after i included Prototype.js into the page.
function JsonArrayByProperty(objArray, prop, direction) {
if (arguments.length < 2) throw new Error("sortJsonArrayByProp requires 2 arguments");
var direct = arguments.length > 2 ? arguments[2] : 1; //Default to ascending
if (objArray && objArray.constructor === Array) {
var propPath = (prop.constructor === Array) ? prop : prop.split(".");
objArray.sort(function (a, b) {
for (var p in propPath) {
if (a[propPath[p]] && b[propPath[p]]) {
a = a[propPath[p]];
b = b[propPath[p]];
}
}
a = a.match(/^\d+$/) ? +a : a;
b = b.match(/^\d+$/) ? +b : b;
return ((a < b) ? -1 * direct : ((a > b) ? 1 * direct : 0));
});
}
}
It breaks at following lines with error
Uncaught TypeError: Object #<Object> has no method 'match'
a = a.match(/^\d+$/) ? +a : a;
b = b.match(/^\d+$/) ? +b : b;
Your problem most likely starts on this line:
for (var p in propPath) {
Once you add prototype.js to your page, you cannot use the common (but incorrect) shortcut of iterating over an array using for(foo in bar). That's because array elements are no longer simple strings or floats, they are full-fledged "extended" objects that happen to evaluate back to strings or floats if you iterate over them correctly.
for(var i = 0; i < propPath.length; i++) {
will get you back on track.