Mat5hias Mat5hias - 3 months ago 5
Javascript Question

Order/Sort text and numbers works in Firefox and Chrome, but not Safari

I wrote a jQuery script to sort the results by year which works fine in most browsers. In the case safari browsers the results are listed like this:

2006
ALL
2007
2008
2009
etc.

Of course the list should apear like this.

ALL
2006
2007
2008
2009
etc.

I don't understand why the results vary.



var li = $('#filter .milo-filter');
li.sort(function(a, b) {
if(parseInt($(a).text()) > parseInt($(b).text()))
return 1;
else return -1;
});
$('#filter').empty().html(li);

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div class="milo-portfolio-filters clearfix">
<ul data-option-key="filter" id="filter">
<li class="milo-filter">
<a class="selected " title="All" data-option-value="*" href="#">All</a>
</li>
<li class="milo-filter">
<a title="2015" data-option-value=".2015" href="#">2015</a>
</li>
<li class="milo-filter">
<a title="2011" data-option-value=".2011" href="#">2011</a>
</li>
<li class="milo-filter">
<a title="2006" data-option-value=".2006" href="#">2006</a>
</li>
<li class="milo-filter">
<a title="2007" data-option-value=".2007" href="#">2007</a>
</li>
<li class="milo-filter">
<a title="2008" data-option-value=".2008" href="#">2008</a>
</li>
<li class="milo-filter">
<a title="2013" data-option-value=".2013" href="#">2013</a>
</li>
<li class="milo-filter">
<a title="2010" data-option-value=".2010" href="#">2010</a>
</li>
<li class="milo-filter">
<a title="2009" data-option-value=".2009" href="#">2009</a>
</li>
<li class="milo-filter">
<a title="2014" data-option-value=".2014" href="#">2014</a>
</li>
<li class="milo-filter">
<a title="2012" data-option-value=".2012" href="#">2012</a>
</li>
</ul>
</div>





Here is a Codepen for better understanding.
http://codepen.io/scooma/pen/yJKxPJ

Answer

When there is no absolute equality status between two members the browser is not required to give them in the order that you think it should (since you don't really know the exact order the browser send the members of your array to the sort function).

As for the problem in your code, if you will check parseInt("All") < parseInt(2015) and parseInt("All") > parseInt(2015) you will see that both return false.

Here is an example with the exact same code, but the returned value is different in chrome and firefox (due to the exact "problem"):

a = [1, 2, 3, 41, 42]
a.sort(function(a, b) {
  if (a == 41) {
    a = 4;
  }
  if (b == 41) {
    b = 4;
  }
  if (a == 42) {
    a = 4;
  }
  if (b == 42) {
    b = 4;
  }
  
  if (a > b) {
    return 1;
  }
  return -1;
})
console.log(a)

Return value in Chrome: [1, 2, 3, 41, 42 ]
Return value in Safari: [1, 2, 3, 42, 41 ]

The solution

The solution for that is to check if the value you have is a text, and depends on that to return the relevant value (1/-1):

var li = $('#filter .milo-filter');
li.sort(function(a, b) {
    if(isNaN(parseInt($(a).text()))) {
      // If we can't parse the first element as a number, it is probably text, and it should appear first
       return -1;
    }
    if(isNaN(parseInt($(b).text()))) {
      // If we can't parse the second element as a number, it is probably text, and it should appear last
       return 1;
    }
    if (parseInt($(a).text()) > parseInt($(b).text())) {
        return 1;
    }
    return -1;
});

$('#filter').empty().html(li);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div class="milo-portfolio-filters clearfix">
            <ul data-option-key="filter" id="filter"> 
                  <li class="milo-filter">
                    <a class="selected " title="All" data-option-value="*" href="#">All</a>
                </li>
             
                            <li class="milo-filter">
                    <a title="2015" data-option-value=".2015" href="#">2015</a>
                </li>
                            <li class="milo-filter">
                    <a title="2011" data-option-value=".2011" href="#">2011</a>
                </li>
                            <li class="milo-filter">
                    <a title="2006" data-option-value=".2006" href="#">2006</a>
                </li>
                            <li class="milo-filter">
                    <a title="2007" data-option-value=".2007" href="#">2007</a>
                </li>
                            <li class="milo-filter">
                    <a title="2008" data-option-value=".2008" href="#">2008</a>
                </li>
                            <li class="milo-filter">
                    <a title="2013" data-option-value=".2013" href="#">2013</a>
                </li>
                            <li class="milo-filter">
                    <a title="2010" data-option-value=".2010" href="#">2010</a>
                </li>
                            <li class="milo-filter">
                    <a title="2009" data-option-value=".2009" href="#">2009</a>
                </li>
                            <li class="milo-filter">
                    <a title="2014" data-option-value=".2014" href="#">2014</a>
                </li>
                            <li class="milo-filter">
                    <a title="2012" data-option-value=".2012" href="#">2012</a>
                </li>
                        </ul>
        </div>

Comments