tags:

views:

93

answers:

1

I am using jquery to sort through a group of paragraph tags (kudos to Aaron Harun). It pulls the value "letter" (a letter) from the url string and displays only paragraphs that start with that letter. It hides all others and also consolidates the list so that there are no duplicates showing.

See the code:

var letter = '<?php  echo(strlen($_GET['letter']) == 1) ? $_GET['letter'] : ''; ?>'

function finish(){
    var found_first = [];
    jQuery('p').each(function(){     
    if(jQuery(this).text().substr(0,1).toUpperCase() == letter){
    if(found_first[jQuery(this).text()] != true){
        jQuery(this).addClass('current-series');
        found_first[jQuery(this).text()] = true;
    }else{
        jQuery(this).hide();
    }
    }
    else{ jQuery(this).hide();}
   })


}

Been working with this all day and I have 2 Questions on this:

  1. Is there a way to get it to ignore the word 'The', if it's first? For example, if a paragraph starts with 'The Amazing', I would like it to show up on the 'A' page, not the 'T' page, like it currently is.

  2. Is there a way to have a single page for (all) numbers? For example, the url to the page would be something similar to domain.com/index.php?letter=0 and this would show only the paragraph tags that start with a number, any number. I can currently do this with single numbers but, I would like 1 page for all numbers.

+2  A: 

Hiya! I ended up rewriting the script, but made a working demo for you :)

/* Return a unique array */
Array.prototype.getUnique = function(){
 var u = {}, a = [], i, l;
 for(i = 0, l = this.length; i < l; ++i){
  if(this[i] in u) continue;
  a.push(this[i]);
  u[this[i]] = 1;
 }
 return a;
}

/* Show paragraph containing first letter (or number if zero) */
function finish(letter){
 var t, txt, found = [];
 if (letter.match(/\d/)) { letter = "0"; } // set letter to zero if it is any number
 $('p').each(function(){
  // grab first 20 characters so we don't need to split the entire paragraph
  txt = $(this).text().substr(0,20).split(' ');
   if (txt[0].toLowerCase() == 'the') { txt.shift(); } // remove first element if it's "the"
  t = txt[0].match(/\d/) ? "0" : txt[0].substr(0,1).toLowerCase(); // set zero for digits or get first letter
  found.push(t); // Add letter/number to array
  if ((t == "0" && letter == "0") || t == letter.substr(0,1).toLowerCase()){ // show paragraph
   $(this).addClass('current-series').show();
  } else {
   $(this).hide();
  }
 })
 return found.getUnique().sort();
}

Update: Ok I finally understand what you mean by consolidated! YAY! You mean you only want the unique entries to show! I've updated the demo and I've also added a small script that grabs the letter variable from the URL, so you really don't need to use php for this:

Note in the demo, I had to remove the select list, but you can change the selected letter (for the demo only) by modifying this line:

 var letter = getletter() || '0';

Change the '0' to whatever letter you want to display (for the demo only). In the live version, it'll grab the letter from the URL automatically.

/* get letter from URL */
function getletter(){
 var p = (new RegExp("[\\?&]letter=([^&#]*)")).exec(window.location.href);
 return (p===null) ? "" : p[1];
}

/* Show paragraph containing first letter (or number if zero) */
function finish(){
 var t, txt, found = [];
 // get letter from url or set to zero if it doesn't exist
 var letter = getletter() || '0';
 // set letter to zero if it is any number
 if (letter.match(/\d/)) { letter = "0"; }
 $('p').each(function(){
  // grab first 20 characters so we don't need to split the entire paragraph
  txt = $(this).text().substr(0,20).split(' ');
  // remove first element if it's "the"
  if (txt[0].toLowerCase() == 'the') { txt.shift(); }
  t = txt[0].match(/\d/) ? "0" : txt[0].substr(0,1).toLowerCase(); // set zero for digits or get first letter
  // show paragraph if unique and matches letter
  if ((found[$(this).text()] != true) && ((t == "0" && letter == "0") || t == letter.substr(0,1).toLowerCase())){
   $(this).addClass('current-series').show();
   found[$(this).text()] = true;
  } else {
   $(this).hide();
  }
 })
}
fudgey
@Fudgey - Thats awesome but, I doesn't seem to be picking up the 'letter' variable from the URL string. Thoughts?
Batfan
I was playing with the script a little and changed -- function finish(letter){ -- to -- function finish(){ -- Now it is picking up the variable in the URL string. However, it is not consolidating the list, so that only unique items are shown. :P
Batfan
Since your code wasn't clear on how you made your consolidated list, I made the `finish` function return the list as an array. If you look at the demo you will see `var f = finish(letter);` where f contains this list. I could help you further if you provided that bit of code.
fudgey
@Fudgey - Sure. Here is a live example. Using the code you provided. -- http://bit.ly/aikxFh
Batfan
I attempted to combine the 2 scripts last night but, had no luck :P
Batfan
@Batfan: I see it works (although I'm not sure why X-23 is showing up as a number only), but I still don't see how the old script was consolidating the list... can you share your old code?
fudgey
@Fudgey - The old code is in the original question. Looks like it makes use of the var 'found_first' and has to do with this line --- found_first[jQuery(this).text()] = true; ---
Batfan
@Batfan: I don't see what happens with the `found_first` array after it is done in the original finish function. All it contains at the end is a list of the visible elements.
fudgey
@Fudgey - I'm not sure then. Thats pretty much the entire thing. I still have the old version live. See if that helps --- http://bit.ly/9bvZ7g
Batfan
Ok, I finally got what you mean... unique entries! I've updated the demo and the code above. I hope that is what you wanted!
fudgey
Oops, you won't need the unique portion of the script anymore, so I removed it.
fudgey
@Fudgey - Nice job man! Thats exactly it. Thanks so much!
Batfan