Archives

Archives / 2010 / May
  • Dynamic Project Listing for XAMPP

    I’m a big fan of two very simple products, XAMPP and WampServer. Both are pre-packaged install kits composed of Apache, MySQL, and PHP (among other tools). They’re the perfect answer to getting a LAMP/WAMP/MAMP stack running quicky for some local PHP development.

    Over the years I’ve installed each of these products manually on all platforms they support and installation experiences range from simple to complex. However for quick development, they’re great tools as they give you a simple setup that is no-mess and no fuss. Just run the installer and you’ll have a WAMP or LAMP stack in minutes to develop off of (WampServer only supports Windows but XAMPP supports Linux, Mac, and Windows).

    What is It?

    One feature I really like with WampServer is the project listing. It’s a simple thing that just lists your folders under your root Apache directory and gives you an easy interface to get to new projects quickly. Just drop a new project in a folder and it shows up on your home page.

    Here’s what it looks like in WampServer:

    wampserverprojects

    Here’s how you can have the same thing with XAMPP.

    XAMPP uses frames and has a few more “behind-the-scenes” files to make it go, however at heart of it, it’s still the same thing. Apache web server. The only difference is it doesn’t have that nice automated way to displays your htdocs folders so taking a nod from WampServer, here’s what we need to do to get a similar effect in XAMPP.

    Do It Yourself

    First you’ll need to create a new file. Call it naviother.inc and put it in the c:\xampp\htdocs\xampp directory. The contents of this folder should look like this:

       1:  <br/><a class="n" target="content" onclick="h(this);" href="/projects.php">Projects</a><br>

    Now create a new PHP file in the root folder (c:\xampp\htdocs) called projects.php with this code:

       1:  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       2:      "http://www.w3.org/TR/html4/loose.dtd">
       3:  <html>
       4:  <head>
       5:      <link href="xampp/xampp.css" rel="stylesheet" type="text/css">
       6:      <title>
       7:      </title>
       8:      <base target="_blank"/>
       9:  </head>
      10:  <body>
      11:   
      12:  <?php
      13:      $handle=opendir(".");
      14:      $projectContents = '';
      15:      while ($file = readdir($handle)) 
      16:      {
      17:          if (is_dir($file) && ($file != "..") && ($file != ".")) 
      18:          {        
      19:              $projectContents .= '<li><a href="'.$file.'">'.$file.'</a>';
      20:              $projectContents .= '</li>';
      21:          }
      22:      }
      23:      closedir($handle);
      24:      if (!isset($projectContents))
      25:          $projectContents = "No Projects";
      26:  ?>
      27:   
      28:  <ul id="projectList">
      29:      <?php echo $projectContents ?>
      30:  </ul>
      31:   
      32:  </body>
      33:  </html>

    Visit your local installation and you’ll see a new link on the sidebar at the bottom of the Tools section called Projects.

    xamppprojects

    Click on it and you’ll see this (I’ve added a few sample folders):

    xampprojects2

    Now just add new folders under c:\xampp\htdocs and they’ll appear here.

    How it Works

    So how does this work? It’s really simple.

    First you need to know how XAMPP builds the sidebar which contains all those links. Inside the xampp directory under htdocs (the Apache folder) is a file called navi.php. This file contains all the sidebar navigation for the homepage. Down around line 57 you’ll see something like this:

       1:  <tr valign="top">
       2:      <td align="right" class="navi">
       3:          <?php
       4:              $navi = array('navitools.inc', 'naviservers.inc', 'naviother.inc');
       5:              foreach ($navi as $inc) {
       6:                  if (is_readable($inc)) {
       7:                      include $inc;
       8:                  }
       9:              }
      10:          ?>
      11:          <br><br>
      12:      </td>
      13:  </tr>
     

    This section just loops through an array of files (navitools.inc, naviservers.inc, and naviother.inc) and includes the contents of each one in line 7. 

    The file navitools.inc contains links to phpMyAdmin and Webalizer (the first two entries under the Tools sidebar). naviservers.inc contains links to Mercury Mail and FileZilla FTP. 

    naviother.inc is the oddball here because in the default installation of XAMPP, it doesn’t exist. Yet the code looks for it and if it’s present, includes it. This is the file we create to put our contents in here.

    So the contents of naviother.inc just contains a link to our Projects page (projects.php) we create.

       1:  <br/><a class="n" target="content" onclick="h(this);" href="/projects.php">Projects</a><br>

    We’re just cloning the contents you see in the other *.inc files and setting the target to “content” which is the main frame on the page.

    Note: If you just installed the “Lite” version (which doesn’t contains the additional servers) you might not have these files or entries but the basic structure should be the same.

    Now that we have our Projects link we can move onto the projects.php file it links to. Here’s the code again for that file:

     
       1:  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       2:      "http://www.w3.org/TR/html4/loose.dtd">
       3:  <html>
       4:  <head>
       5:      <link href="xampp/xampp.css" rel="stylesheet" type="text/css">
       6:      <title>
       7:      </title>
       8:      <base target="_blank"/>
       9:  </head>
      10:  <body>
      11:   
      12:  <?php
      13:      $handle=opendir(".");
      14:      $projectContents = '';
      15:      while ($file = readdir($handle)) 
      16:      {
      17:          if (is_dir($file) &amp;&amp; ($file != "..") &amp;&amp; ($file != ".")) 
      18:          {        
      19:              $projectContents .= '<li><a href="'.$file.'">'.$file.'</a>';
      20:              $projectContents .= '</li>';
      21:          }
      22:      }
      23:      closedir($handle);
      24:      if (!isset($projectContents))
      25:          $projectContents = "No Projects";
      26:  ?>
      27:   
      28:  <ul id="projectList">
      29:      <?php echo $projectContents ?>
      30:  </ul>
      31:   
      32:  </body>
      33:  </html>

    This is just a HTML file with some PHP code embedded to get our folder listings.

    • Line 5 contains a link to the xampp.css stylesheet so we can maintain the same look and feel as the rest of the site
    • Line 8 contains the base target we want our links to open up into. Since we’re listing projects I decided I wanted everything to open up in a new window (or tab). You might want it to just replace the frame contents or swap out the current window so modify this accordingly.
    • Line 13 starts our PHP code and gets a handle to the current directory.
    • Line 15 reads in each subfolder or file
    • Line 17 checks to see if the current item is a directory and also excludes processing the two “dot” directories.
    • Line 19 appends the folder name to a variable named projectContents as a HTML list item with a hyperlink to the folder.
    • Line 24 checks to see if we have any folders to display and if not, sets the contents indicating this.
    • Line 28-30 displays the items in an unordered list

    A Little Extra

    Here’s a couple of things you can do to spice up a boring directory listing. First we’ll add the “Your Projects” header to page:

       1:  <h1>Your Projects</h1>
       2:   
       3:  <ul id="projectList">
       4:      <?php echo $projectContents ?>
       5:  </ul>

    Which gives us this:

    xampprojects3

    Next, as your project list grows you might find the unordered list a little bland and boring (and long). We’ll toss a little jQuery love into the mix to spice things up and use the ListNav plugin to display our boring unordered list of folders a better light. ListNav is a nice little plugin that can transform your unordered list into something fun (as with most jQuery plugins, with next to no addtional code).

    First download a copy of jQuery and the ListNav plugin and drop the files into a /scripts directory under your htdocs folder.

    Next let’s make a slight modification to the output of our unordered list by wrapping it in some extra tags that jQuery can pick up:

       1:  <h1>Your Projects</h1>
       2:  <div id="projectWrapper">
       3:      <div id="projectList-nav"></div><br/>
       4:      <ul id="projectList">
       5:          <?php echo $projectContents ?>
       6:      </ul>
       7:  </div>

    Now finallly add jQuery, the ListNav plugin, and this javascript to the top of your projects.php file (or bottom if you prefer):

       1:  <script type="text/javascript" src="scripts/jquery-1.4.2.js"></script>
       2:  <script type="text/javascript" src="scripts/jquery.listnav-2.1.js"></script>
       3:  <script type="text/javascript">
       4:  $(document).ready(function(){
       5:      $('#projectList').listnav();
       6:  });
       7:  </script>

    The only piece of code we’re writing is a selector to find our unordered list (projectList) and call the listnav() plugin.

    Now our boring list has turned into this cool looking navigation control:

    xamppprojects-jquerylistnav 

    I used the CSS from #DemoFour in the ListNav code to get the box effect here, but XAMPP does make it a little tricky. The ListNav creates classes for each letter in the navigation bar (using a single letter style name). However XAMPP also does this in it’s stylesheet so you might notice the letters D, N and others look a little “off”.

    Here’s the CSS override you can add to a new stylesheet and just include in your projects.php file to fix it up:

       1:  /* fix for some classes that xampp defines */
       2:  a.n:link, .n, .d, .h 
       3:  { 
       4:      color:#BB3902;
       5:      background-color:#F8E8A0;
       6:      font-size:12px;
       7:  }
       8:   
       9:  #projectWrapper
      10:  {
      11:      width:100%;
      12:  }
      13:   
      14:  #projectList li
      15:  {
      16:      list-style: none;
      17:      float:left;
      18:  }
      19:   
      20:  #projectList a 
      21:  {
      22:      width:185px;
      23:      display:block;
      24:      text-decoration:none;
      25:      border:1px solid silver;
      26:      padding:10px;
      27:      margin:0 10px 10px 0px;
      28:  }

    All Done!

    Hope that helps and gives you a little mod for your local PHP/MySQL development. I highly recommend checking out XAMPP or WampServer if you’re just looking to get your LAMP/WAMP stack up and running quickly so you can focus on building software rather than installing tools. You pick which one you want to go with but XAMPP has the advantage of being fully portable as you can install it on a USB stick and run it right from the install directory without having to drop anything on your local drive.

    Enjoy!

  • Content Query Web Part and the Yes/No Field

    The Content Query Web Part (CQWP) is a pretty powerful beast. It allows you to do multiple site queries and aggregate the results. This is great for rolling up content and doing some summary type reporting. Here’s a trick to remember about Yes/No fields and using the CQWP.

    If you’re building a news style site and want to aggregate say all the announcements that people tag a certain way, up onto the home page this might be a solution.

    First we need to allow a way for users of all our sites to mark an announcement for inclusion on our Intranet Home Page. We’ll do this by just modifying the Announcement Content type and adding a Yes/No field to it. There are alternate ways of doing this like building a new Announcement type or stapling a feature to all sites to add our column but this is pretty low impact and only affects our current site collection so let’s go with it for now, okay? You can berate me in the comments about the proper way I should have done this part.

    Go to the Site Settings for the Site Collection and click on Site Content Types under the Galleries.

    image

    This takes you to the gallery for this site and all subsites. Scroll down until you see the List Content Types and click on Announcements.

    image

    Now we’re modifying the Announcement content type which affects all those announcement lists that are created by default if you’re building sites using the Team Site template (or creating a new Announcements list on any site for that matter).

    image

    Click on Add from new site column under the Column list. This will allow us to create a new Yes/No field that users will see in Announcement items. This field will allow the user to flag the announcement for inclusion on the home page. Feel free to modify the fields as you see fit for your environment, this is just an example.

    image

    Now that we’ve added the column to our Announcements Content type we can go into any site that has an announcement list, modify that announcement and flag it to be included on our home page.

    image

    See the new Featured column? That was the result of modifying our Announcements Content Type on this site collection.

    Now we can move onto the dirty part, displaying it in a CQWP on the home page. And here is where the fun begins (and the head scratching should end).

    On our home page we want to drop a Content Query Web Part and aggregate any Announcement that’s been flagged as Featured by the users (we could also add the filter to handle Expires so we don’t show old content so go ahead and do that if you want).

    First add a CQWP to the page then modify the settings for the web part. In the first section, Query, we want the List Type to be set to Announcements and the Content type to be Announcement so set your options like this:

    image

    Click Apply and you’ll see the results display all Announcements from any site in the site collection.

    image

    I have five team sites created each with a unique announcement added to them.

    Now comes the filtering. We don’t want to include every announcement, only ones users flag using that Featured column we added.

    At first blush you might scroll down to the Additional Filters part of the Query options and set the Featured column to be equal to Yes:

    image

    This seems correct doesn’t it? After all, the column is a Yes/No column and looking at an announcement in the site, it displays the field as Yes or No:

    image

    However after applying the filter you get this result:

    image

    (I have the announcements from Team Site 1 and Team Site 4 flagged as Featured)

    Huh?

    It’s BACKWARDS!

    Let’s confirm that. Go back in and change the Additional Filters section from Yes to No and hit Apply and you get this:

    image

    Wait a minute? Shouldn’t I see Team Site 1 and 4 if the logic is backwards? Why am I seeing the same thing as before. What gives…

    For whatever reason, unknown to me, a Yes/No field (even though it displays as such) really uses 1 and 0 behind the scenes. Yeah, someone was stuck on using integer values for booleans when they wrote SharePoint (probably after a long night of white boarding ways to mess with developers heads) and came up with this.

    The solution is pretty simple but not very discoverable. Set the filter to include your flagged items like so:

    image

    And it will filter the items marked as Featured correctly giving you this result:

    image

    This kind of solution could also be extended and enhanced. Here are a few suggestions and ideas:

    • Modify the ItemStyle.xsl file to add a new style for this aggregation which would include the first few paragraphs of the body (or perhaps add another field to the Content type called Excerpt or Summary and display that instead)
    • Add an Image column to the Announcement Content type to include a Picture field and display it in the summary
    • Add a Category choice field (Employee News, Current Events, Headlines, etc.) and add multiple CQWPs to the home page filtering each one on a different category

    I know some may find this topic old and dusty but I didn’t see a lot out there specifically on filtering the Yes/No fields and the whole 1/0 trick was a little wonky, so I figured a few pictures would help walk through overcoming yet another SharePoint weirdness.

    With a little work and some creative juices you can easily us the power of aggregation and the CQWP to build a news site from content on your team sites.

  • SharePoint – The Most Important Feature

    Watching twitter and doing a search for SharePoint and you see a lot (almost one every few minutes) of tweets about the top 10 new features in SharePoint. What answer do you get when you ask the question, “What’s the most important feature in SharePoint?”. Chances are the answer will vary. Some will say it’s the collaboration aspect, others might say it’s the new ribbon interface, multi-item editing, external content types, faceted search, large list support, document versioning, Silverlight, etc. The list goes on. However I think most people might be missing the most important feature that’s sitting right under their noses all this time.

    SharePoint? What's that?

    The most important feature of SharePoint? It’s called User Empowerment.

    Huh? What? Is that something I find in the Site Actions menu?

    Nope. It’s something that’s always been there in SharePoint, you just need to get the word out and support it.

    How many times have you had a team ask you for a team site (assuming you had SharePoint up and running). Or to create them a contact list. Or how long have you employed that guy in the corner who’s been copying and pasting content from Corporate Communications into the web from a Word document.

    Let’s stop the insanity. It doesn’t have to be this way.

    SharePoint’s strongest feature isn’t anything you can find in the Site Settings screen or Central Admin. It’s all about empowering your users and letting them take control of their content. After all, SharePoint really is a bunch of tools to allow users to collaborate on content isn’t it? So why are you stepping in as IT and helping the user every moment along the way. It’s like having to ask users to fill out a help desk ticket or call up the Windows team to create a folder on their desktop or rearrange their Start menu. This isn’t something IT should be spending their time doing nor is it something the users should be burdened with having to wait until their friendly neighborhood tech-guy (or gal) shows up to help them sort the icons on their desktop.

    SharePoint IS all about empowerment. Site owners can create whatever lists and libraries they need for their team, and if the template isn’t there they can always turn to my friend and yours, the Custom List. From that can spew forth approval tracking systems, new hire checklists, and server inventory. You’re only limited by your imagination and needs. Users should be able to create new sites as they need. Want a blog to let everyone know what your team is up to? Go create one, here’s how. What’s a blog you ask? Here’s what it is and why you would use one.

    SharePoint is the shift in the balance of power and you need, and an IT group, let go of certain responsibilities and let your users run with the tools. A power user who knows how to create sites and what features are available to them can help a team go from the forming stage to the storming stage overnight. Again, this all hinges on you as an IT organization and what you can and empower your users with as far as features go. Running with tools is great if you know how to use them, running with scissors not recommended unless you enjoy trips to the hospital.

    With Great Power really does come great responsibility.

    With Great Power comes Great Responsibility so don’t go out on Monday and send out a memo to the organization saying “This Bil guy says you peeps can do anything so here it is, knock yourself out” (for one, they’ll have no idea who this Bil guy is). This advice comes with the task of getting your users ready for empowerment. Whether it’s through some kind of internal training sessions, in-house documentation; videos; blog posts; on how to accomplish things in SharePoint, or full blown one-on-one sit downs with teams or individuals to help them through their problems. The work is up to you. Helping them along also should be part of your governance (you do have one don’t you?). Just because you have InfoPath client deployed with your Office suite, doesn’t mean users should just start publishing forms all over your SharePoint farm. There should be some governance behind that in what you’ll support and what is possible.

    The other caveat to all this is that SharePoint is not everything for everyone. It can’t cook you breakfast and impregnate your cat or solve world hunger. It also isn’t suited for every IT solution out there. It’s a horrible source control system (even though some people try to use it as such) and really can’t do financials worth a darn. Again, governance is key here and part of that governance and your responsibility in setting up and unleashing SharePoint into your organization is to provide users guidance on what should be in SharePoint and (more importantly) what should not be in SharePoint. There are boundaries you have to set where you don’t want your end users going as they might be treading into trouble. Again, this is up to you to set these constraints and help users understand why these pylons are there. If someone understands why they can’t do something they might have a better understanding and respect for those that put them there in the first place. Of course you’ll always have the power-users who want to go skiing down dead mans curve so this doesn’t work for everyone, but you can catch the majority of the newbs who don’t wander aimlessly off the beaten path.

    At the end of the day when all things are going swimmingly your end users should be empowered to solve the needs they have on a day to day basis and not having to keep bugging the IT department to help them create a view to show only approved documents. I wouldn’t go as far as business users building out full blown solutions and handing the keys to SharePoint Designer or (worse) Visual Studio to power-users might not be a path you want to go down but you also don’t have to lock up the SharePoint system in a tight box where users can’t use what’s there.

    So stop focusing on the shiny things in SharePoint and maybe consider making a shift to what’s really important. Making your day job easier and letting users get the most our of your technology investment.