Development Automagic bulleted lists using PHP and textareas

Discussion in 'Software' started by OneSeventeen, 24 Jul 2006.

  1. OneSeventeen

    OneSeventeen Oooh Shiny!

    Joined:
    3 Apr 2002
    Posts:
    3,454
    Likes Received:
    2
    I want to be able to make multi-level bullited lists in plain text where PHP can then convert them into <ul> or <ol>'s

    For example, I want PHP to convert:
    Code:
    *Foo
    **sub-item of foo
    **second sub-item of foo
    *Bar
    **Sub item of bar
    ***sub item of the sub item of bar
    
    into:
    • Foo
      • sub-item of foo
      • second sub-item of foo
    • Bar
      • Sub item of bar
        • sub item of the sub item of bar

    Any tips on how to do this? I'm okay with not allowing multiple paragraphs on a single list, since these are just simple shownotes for a podcast...
    I would, however, like to be able to have as many levels as possible.
     
  2. RTT

    RTT #parp

    Joined:
    12 Mar 2001
    Posts:
    14,120
    Likes Received:
    74
    Wikipedia can do this, check out their source?
     
  3. eek

    eek CAMRA ***.

    Joined:
    23 Jan 2002
    Posts:
    1,600
    Likes Received:
    14
    str_replace("***", "<ul class='x'>", $guff)
    str_replace("**", "<ul class='y'>", $guff)
    str_replace("*", "<ul class='z'>", $guff)

    in that order should work... you also need to add closing tags but that is easy enough.

    To make it better and more fool proof you would be better off using regex.
     
  4. jezmck

    jezmck Minimodder

    Joined:
    25 Sep 2003
    Posts:
    4,456
    Likes Received:
    36
    using classes to simulate nesting ain't so good for accessibility, plus of course pride. ;)
    I'd go with RTTs suggestion.
     
  5. eek

    eek CAMRA ***.

    Joined:
    23 Jan 2002
    Posts:
    1,600
    Likes Received:
    14
    There is no pride with copying code from Wikipedia ;)
     
  6. OneSeventeen

    OneSeventeen Oooh Shiny!

    Joined:
    3 Apr 2002
    Posts:
    3,454
    Likes Received:
    2
    Not to mention it is easier said than done (copying one section of code without getting too much or too little).

    I just thought of something though, could I just loop through the text line by line, and set 2 variables: $currentCount and $previousCount

    Then, if the $currentCount is greater than the $previous Count, add a "<ul><li>", but if it is less than the $previousCount, add a "</li></ul></li>", otherwise simply add a "</li><li>".

    Then use the previous count at the very end to close the remaining items off...

    I'll try it out and post the code when I get something close.
     
  7. eek

    eek CAMRA ***.

    Joined:
    23 Jan 2002
    Posts:
    1,600
    Likes Received:
    14
    Yes you could :)
     
  8. OneSeventeen

    OneSeventeen Oooh Shiny!

    Joined:
    3 Apr 2002
    Posts:
    3,454
    Likes Received:
    2
    Apparently so...
    click for demo

    Probably innefficient and could have better features, but it works!

    leaving off the leading asterisk of a line closes off all current lists and inserts a paragraph with class "listHeader".

    As far as I can tell, it generates standards compliant source code... and all without having to worry about recursive functions and whatnot (which is what I tried to use in the past)

    Edit: if you think I should change something, please let me know.. I wouldn't mind fleshing this out a bit into an efficient yet better featured app...

    Perhaps including a function name to run on each line, so you can use this function to generate the list, but use another function to format each line of the results?
     
    Last edited: 25 Jul 2006
  9. DougEdey

    DougEdey I pwn all your storage

    Joined:
    5 Jul 2005
    Posts:
    13,933
    Likes Received:
    33
    I broked it already, doesn't produce anything when you miss a level.

    I.e.

    Code:
    *Foo
    ***BAR
     
  10. OneSeventeen

    OneSeventeen Oooh Shiny!

    Joined:
    3 Apr 2002
    Posts:
    3,454
    Likes Received:
    2
    Correct, for this sample I have no error messages displayed, and so far that is the only way to have it return false... in the "view source" page I even mention the fact that it is "not tolerant of weird stuff".

    I need to find a way to handle that, because as far as I know, HTML standards don't support starting with nested lists, do they?

    If so it would be simple to support it, but I don't want to support something that breaks standards...
     
  11. OneSeventeen

    OneSeventeen Oooh Shiny!

    Joined:
    3 Apr 2002
    Posts:
    3,454
    Likes Received:
    2
    Okay, I found out that it is perfectly fine with standards to start a nested list without any content, but only if you include the <li> tag, so it looks pretty ugly, but it meets standards.

    Updated Script
     
  12. Firehed

    Firehed Why not? I own a domain to match.

    Joined:
    15 Feb 2004
    Posts:
    12,574
    Likes Received:
    16
    Heh, going by the comment in the source, it looks like you came across the same site I did for hierarchies in PHP :p

    Anyways, you may want to consider just cleaning up the generated HTML code a bit with indenting (just some "\t"s in there), but that's just personal preference. I'm completely obsessive when it comes to code indenting, even if it is for stuff generated for copy and pasting.
     
  13. OneSeventeen

    OneSeventeen Oooh Shiny!

    Joined:
    3 Apr 2002
    Posts:
    3,454
    Likes Received:
    2
    Actually I could never find a page on how to do this. I just came up with the idea one day (about 2 or 3 months after I first wanted to convert asterisks into bulletted lists)

    Yeah, I normally do tabs when writing code, but I was lazy on this one. I might see what it would take later on to add the proper number of tabs, but I'm not overly concerned, since I'm not using this to generate static HTML... I'll be running my lists through this function each time I generate the page (until I get more traffic, at which time I'll cache the pages)

    Edit: I've added the option to pass a function name as a second variable, so it will pass each line through the function of your choice before displaying it...

    so calling generateList($listText, "strtoupper");
    would make a list based on $listText, and would capitalize everything.

    Of course you could put in your own custom function as well... which is what I did for the test. My function replaces something like this: {Jeremiah 1:17} with a link to an online bible reference of Jeremiah 1:17

    Of course your function could bold, italicize, etc.
     
    Last edited: 25 Jul 2006
  14. Hwulex

    Hwulex What's a Dremel?

    Joined:
    1 Feb 2002
    Posts:
    4,007
    Likes Received:
    1
    Could you not just do something like:

    PHP:
    $string preg_replace"/\\n\*+(.*)/i""\\n&lt;li&gt;\1&lt;\/li&gt;"$string );
    Hmm, actually, maybe not. Ignore me.

    Looked at MarkDown?
     
  15. OneSeventeen

    OneSeventeen Oooh Shiny!

    Joined:
    3 Apr 2002
    Posts:
    3,454
    Likes Received:
    2
    MarkDown looks cool, but I don't know perl, and wouldn't know how to mod it to suit my needs.

    I'm going to use this current tool specifically for my podcasting website's shownotes, so it helps to only use the features I want.

    Is there a way to use preg_replace to replace something that surrounds text, such as:
    Find _some text_ and replace it with <em>some text</em>, or find
    [http://www.example.com|Example Website|Some website] and replace it with:
    <a href="http://www.example.com" title="ExampleWebsite" class="externalLink">Some
    Website</a>

    ??
     

Share This Page