Link to home
Start Free TrialLog in
Avatar of Chris24
Chris24

asked on

Auto links???

I have a directory that has 60 or so PDF documents in it. These documents change regularly which creates a VERY high maintenance situation. Rather than manually creating 60 or links on a page, does anyone have any ideas of how I could read into the directory and automatically generate a page which contains links to all of the files in that directory? Would there be an app out there on the market that I could purchase? Java app? Thoughts?

Thanks,
Chris
Avatar of Rakafkaven
Rakafkaven

A more complete answer is: not with Javascript alone.  Javascript runs on the client's machine, and the client can't scan your server's directories (which is good!).  Some simple server-side scripting, however, will create a list that can be passed to your page in either formatted HTML or as Javascript variables.
Avatar of Chris24

ASKER

Correct. I know Javascript cannot ... Guess I shouldn't have posted in the Javascript area but not knowing what language should be used, I figured here was as good a place as any.

Thank you,
Chris
Do you have sufficient access to your server to create scripts?  What you're looking to do is not particularly complicated, and depending on what sorts of scripts your server is set up to run (php, cgi, asp, etc), it should be a snap even if you're new.

No harm in asking in the Javascript area-- your script can hand back formatted HTML, which makes JS unnecessary; but you may also choose to pass the list in as text that JS will handle dynamically.   So JS may well have a role in the process yet.
Avatar of Chris24

ASKER

If I can show the value in having a script such as this, I can have I.S. turn on PHP, cgi, or ASP. I did find the following script which is very very simple PHP.

I don't know PHP that well so it really isn't very simple to me. :

<?php

if ($handle = opendir('pdf/')) {

     // Looping through files
   while (false !== ($file = readdir($handle))) {
             // Check the file name, if it's doc[1-4].pdf then show link to it
       echo "<font size=\"2\" face=\"Arial, Helvetica, sans-serif\"><a href=\"/pdf/$file\">$file</a></font><br>";
   }

   closedir($handle);
}
?>

All of the PDF documents begin with a 6 digit number. There are to be 8 separate pages. Each page contains a range of the PDF documents. Example: Page 1 contains all PDFs falling between 100000 and 199999, Page 2 contains 200000 to 299999. and so on up to 999999. Any ideas of how to edit this script to search for the ranges and list only those files that fall within that range?

Thanks,
Chris
Avatar of Chris24

ASKER

Would would be even better is if something could read some of the meta-data out of the PDF file so it could title the link as the title of the document... Possible?
First off, make your links to the pages (which will really just be one page) like this:
   http://www.mypage.com/whatever/listofpdfs.html?min=100000&max=199999
(the only part that matters is the question mark and everything after it-- the rest should be whatever your current setup is)
If you can't do this, then we'll just need a different php script in every list page, which is okay but kind of dumb and a royal pain.  So instead of having:
   http://www.mypage.com/whatever/listofpdfs1.html
   http://www.mypage.com/whatever/listofpdfs2.html
   http://www.mypage.com/whatever/listofpdfs3.html
   ...
we'll just have one page, http://www.mypage.com/whatever/listofpdfs.html and then change the arguments after it:
   http://www.mypage.com/whatever/listofpdfs.html?min=100000&max=199999
   http://www.mypage.com/whatever/listofpdfs.html?min=200000&max=299999
   http://www.mypage.com/whatever/listofpdfs.html?min=300000&max=399999
   ...
and the php script buried in the middle of listofpdfs.html (which again, can be named whatever it is currently) will see the arguments and figure out which pdfs to display.

So put your PHP exactly where you would've had your hand-written list of pdfs; I'm going to use simple line breaks, but tables or HTML lists aren't any harder to do-- the php will be parsed by the server and create that list in the HTML exactly as though you had hand-entered it.  I'll explain what each bit does as well as my changes.


--   if ($handle = opendir('pdf/')) {

++ anything starting with a '$' is a variable.  'opendir(pdf/)' simply opens a directory and returns a reference to that directory, or "FALSE" if the directory can't be opened.  So that 'if' statement basically says "if you can open the pdf/ directory, make variable "$handle" point to it and then do everything between these curly braces.  If you can't open the pdf/ directory, don't bother with the rest of this stuff."


--  while (false !== ($file = readdir($handle))) {

++ this does what it says, and is explained best here: http://us2.php.net/manual/en/function.readdir.php.  Very similar to the opendir, except now we're grabbing the files from inside the directory we just opened one by one-- every time you call readdir on a given directory object, it goes to the next available file.


Your script mentions checking format, but doesn't actually do so.  So we'll have to.  We want to verify a ".pdf" extention, and a substring of the first six characters that's greater than "min" but less than "max".  I'm less sure about the document title, but I'll look into it.

I'm going to be away from my keyboard from a bit, but I promise to finish up soon if no one else does before me.
Avatar of Chris24

ASKER

Wow! Thank you!
Avatar of Chris24

ASKER

Can we also return the results in a table and alternate the row colors? First column would be the filename and link to the file while the second column would be the document title (if we can pull the title)

Thanks,
Chris
Avatar of Chris24

ASKER

By the way, the page(s) that I am trying to make dynamic are here: http://www.gfs.com/content_us/msds/msds.html


Thanks,
Chris
My apologies, that was a very long "little bit" that I was away for.

Seeing the actual page has complicated things a bit, mostly in dealing with the human-readable title.  From what I've found (and I certainly may have missed something), there are two levels of metadata that contain a "title": the filesystem metadata and the Acrobat-specific metadata.  It is possible, but not simple, to pull the filesystem title; it is possible and simple to pull the Acrobat title but ONLY if you are in an Acrobat application.  That's all a moot point, however, since a random sampling I grabbed from your page shows that the title displayed on the web page usually doesn't exist on any level of the file metadata.  Worse, there isn't one consistent type of form, so we can't write an Acrobat script to pull the Title out of any particular field in the form-- heck, some of the documents are just pure images with no "text" content at all (107662, for example).

So we're back to human-level intervention; someone has to manually enter the display titles, and there's no way around that (since they don't consistently exist anywhere else).  And since those display titles aren't linked to the file in any way, PHP is going to have a tough time lining them up.

The code you found that we were editing would work fine for the question you asked (displaying the contents of a directory); but the solution you actually need (displaying the contents of a directory and lining it up with another column of data with no current hard data relation) is not possible with this method.

All is not necessarily lost, however.  We can write a simple HTML/JS app that will create a text file that lists each six-digit code joined to its description; the PHP will then reference this text file and match where it can to populate the output table.  Maintenance will be reduced to simply opening this HTML page any time an item is added or changed, and editing the description field.  This would require:
1.) Maintenance user is running Windows.
2.) HTML maintenance app file is stored somewhere locally; it won't (thankfully) work if accessed through the internet, so there's no point in putting it on the server.
3.) Maintenance user is able to turn down security settings in Internet Explorer to allow ActiveX controls to run for this particular file (user should NOT turn down general security level of IE unless user is a masochist).

There are other ways, but all the ones I can think of (using a database being the most obvious) qualify as "more complicated than they're worth".  If this proposed solution is also more complicated than it's worth, just let me know and I'll see what we can do.  
One other possibility, which is much less complicated on the front end but a bit more hassle for maintenance:  keep the item/description pairs in an XML or CSV file, and the maintaining user just edits that file by hand when changes are made.

Oh, and as for displaying in a table and setting the alternating background color (no matter what method is used)-- yes, easy as pie.
If seems questionable to bother with any of the listed techniques, since they still all involve some human maintenance, here are the advantages over the 100% manual process you are currently using:
1.) List is populated with contents of the directory, so adding and deleting an item from the page is done simply by adding or removing a file from the folder.
2.) Dividing the list into the three pages is done automatically.
3.) The tabs will now all point to the same page, reducing overhead if the site is ever changed.
4.) Sorting, formatting, etc all handled automatically--add an item at any place in the list/description file, and it will show up in the proper place in the list.
Avatar of Chris24

ASKER

Thank you. Not a problem. I agree with the 100% automatic process. My main reason behind this posting was to reduce or eliminate maintenance.

Let's go about it this way ... No title is needed except for what we already have which is file name. Previously, what I was thinking of doing was have the department here that actually owns those documents enter the meta data themselves. Big projecct initially but once done, it will only need to be done only when a new one is added. I read I could possibly use PDFLib. Not sure. Anyhow, the products are actually identified by that item number instead of  the product name anyhow.

So using one PHP doc using the min and max method that you mentioned above and alternating the table row colors would suffice for what I'm looking for. I'll then just need to do some sort of if statement to make sure the correct tab on that page is active.

Thanks,
Chris
I'll include the handling of the tabs.  One other issue:  are the spanish pdfs in the same directory?
Avatar of Chris24

ASKER

Yes they are ... crap ... they all contain the word Spanish in the filename. ie 123456_Spanish_GFS.pdf or 123456_Spanish.pdf. I guess I need to exclude these files in the other lists or move them into their own directory and have a separate PHP for the Spanish ones.

Thanks,
Chris
Excellent! Picking up where we left off:

First, we get the length of the filename (including extention), since anything under 10 isn't something we want.  This also gets filters out the '.' and '..' directory files.

$sLen = strlen($file);
if($sLen >= 10

Once we know it's at least 10 characters long, we check the last four to make sure they're '.pdf'  We could do this in a new 'if' statement, but it's simpler to add this on as a condition of the one we were just using.  Line breaks don't matter (usually) in PHP; the semicolon ends the statement.  So add as many line breaks and tabs as you need to make it readable for you.

&& substr($file, $sLen - 4, 4) == '.pdf') {

Now we'll grab the item code and add it to an array that I'm going to pretend we already declared way up top.

(the forgotten declaration):  $aFileList = array();

array_push($aFileList,substr($file, 0, 6));

Throw in some closing brackets to end our if statement and the while loop.  Now we can start creating the rows themselves.

There are several methods for alternating highlighting in a table, but since we're already in PHP and I don't know what kind of environment we'll be in for JS or CSS, we'll go with a brute-force and dead-simple PHP hard-coding method.  To keep track of what row we're on, we'll throw a counter variable at towards the top of our script:

$iRowCt = 0;

Now, back inside the consequence of our 'if', we iterate that counter and divide the result by two, checking for remainder-- basically determining if it's even or odd (this operation is called 'modulus', and is represented in PHP with the '%' symbol).  We use that to create our 'tr' definition.  In PHP, the '.' is a string concatenator, and the /n creates a newline in the output -- unnecessary, but if you view source it'll be more legible.

$iRowCt = iRowCt + 1;
if ($iRowCt % 2 == 0) {
  $sRowDef = "<tr bgcolor = '#e6e6e6'> . /n;
} else {
   $sRowDef = "<tr bgcolor = '#e6e6e6'> . /n;
}

...okay, this commenting is getting pretty lengthy.  I'm going to post the suggested code and you can ask about anything you'd like to know.
Avatar of Chris24

ASKER

Phew .. OVERLOAD! lolol Understanding PHP a lot more though so thanks for that!
ASKER CERTIFIED SOLUTION
Avatar of Rakafkaven
Rakafkaven

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Chris24

ASKER

It bombs out at:
Parse error: parse error, unexpected T_LNUMBER, expecting T_VARIABLE or '$' in c:\documents and settings\csimpson\Desktop\server2go\htdocs\testrun.php on line 49
Avatar of Chris24

ASKER

I fixed it ...                                 . \n . for some odd reason was causing the issue. It works GREAT! Except for 1 issue. I can't figure out where you specify the range ie display all PDFs from 100000 to 199999 etc. The 800000 - 900000 tab is only showing the 800000 files but not the 900000 files.

Here's my edited code:

<?php
$aFileList = array();
$aTabs = array();
$codeMin = $_GET['min'];
$sEsp = $_GET['esp'];

if($codeMin < 1 || $codeMin > 8) {
  $codeMin = 1;
}

if ($sEsp != 'true' && $sEsp != 'false'){
  $sEsp = 'false';
}

if ($handle = opendir('files/')) {
     // Looping through files
   while (false !== ($file = readdir($handle))) {
    $sLen = strlen($file);
    if($sLen >= 10
      && substr($file, $sLen - 4, 4) == '.pdf'){
        if($sEsp == 'true' && isSpanish($file) == 'true') {
            array_push($aFileList,$file);
        } elseif($sEsp == 'false'
          && isSpanish($file) == 'false'
          && $codeMin == substr($file, 0, 1)) {
            array_push($aFileList,$file);
        }
    } //end if 10-char pdf
   } //while
   closedir($handle);
   sort($aFileList);

$aTabs[1] = "100_200_off";
$aTabs[2] = "200_300_off";
$aTabs[3] = "300_400_off";
$aTabs[4] = "400_500_off";
$aTabs[5] = "500_600_off";
$aTabs[6] = "600_700_off";
$aTabs[7] = "700_800_off";
$aTabs[8] = "800_900_off";
$aTabs[9] = "espanol_off";

if($sEsp = 'true') {
  $aTabs[9] = str_replace("_off", "_on", $aTabs[9]);
} else {
  $aTabs[$codeMin] = str_replace("_off", "_on", $aTabs[$codeMin]);
}
//create base table
echo '<table width="100%" border="0" cellpadding="0" cellspacing="0">
                         <tr>
                                   <td>';
//create tab table
echo '<table width="100%" border="0" cellpadding="0" cellspacing="0">
                         <tr>
                                   <td>';
//create tab cells                                  
if($codeMin>4) {
  echo '<td align="left" valign="bottom"><a href="msds_test.php?min=1&esp=false"><img src="images/body/prev.jpg" alt="" border="0"></a></td>';
'\n';
  for($tabCt = 5; $tabCt<=8;$tabCt++){
    echo '<td width="87"><a href="msds_test.php?min=' . $tabCt . '&esp=false"><img src="images/body/' . $aTabs[$tabCt] . '.jpg" border="0"></a></td>';
'\n';
  }
  echo '<td width="87"><a href="msds_test.php?min=5&esp=true"><img src="images/body/' . $aTabs[9] . '.jpg" border="0"></a></td>';
'\n';
} else {
  for($tabCt = 1; $tabCt<=4;$tabCt++){
    echo '<td width="87"><a href="msds_test.php?min=' . $tabCt . '&esp=false"><img src="images/body/' . $aTabs[$tabCt] . '.jpg" border="0"></a></td>';
'\n';
  }
    echo '<td width="87"><a href="msds_test.php?min=5&esp=true"><img src="images/body/' . $aTabs[9] . '.jpg" border="0"></a></td>';
'\n';
    echo '<td width="100%" align="right" valign="bottom"><a href="msds_test.php?min=5&esp=false"><img src="images/body/next.jpg" alt="" border="0"></a>';
}
//end tab cells, row, table
echo '</tr></table></td></tr>';
//this next part seems mostly pointless, but it's on your original          
echo          '<tr>
                                        <td>
                                        <table width="100%" border="0" cellspacing="2" cellpadding="1">
                                      <tr bgcolor="white">
                                        <td width="24"><br>
                                        </td>
                                        <td width="100"><br>
                                        </td>
                                      </tr>';
//begin creating the content rows
foreach($aFileList as $key => $value) {
  if($key % 2 == 0){
    echo "<tr bgcolor = '#e6e6e6'>\n";
  } else {
    echo "<tr>\n";
  }
  echo '<td width="24"><img src="../images/acro_icon_sm.gif" alt="" height="16" width="16" border="0"></td>';
'\n';
  echo '<td width="100%"><a href="files/' . $value . '" target="msdsinside">' . $value . '</a></td>';
'\n';
  echo '</tr>';
'\n';
} //end foreach

//close remaining tables
echo '</table></td></tr></table>';

} //end if $handle

function isSpanish($fName){
  if(strlen(stristr($fName, 'spanish')) > 0) {
    return 'true';
  } else {
    return 'false';
  }
}
?>
Avatar of Chris24

ASKER

Now that I think about it. It is working perfect. Exactly how I defined. I need to create a 900000 - 999999 tab ... lolol

Actually, instead of creating a new tab. I am going to change the 800000 - 900000 tab to say 800000 - 999999. Where do I edit the code to have that tab pull 800000 to 999999??

Thanks,
Chris

This bit toward the top:

       if($sEsp == 'true' && isSpanish($file) == 'true') {
            array_push($aFileList,substr($file, 0, 6));
        } elseif($sEsp == 'false'
          && isSpanish($file) == 'false'
          && $codeMin == substr($file, 0, 1)) {
            array_push($aFileList,$file);

Needs to be replaced with:

        if($sEsp == 'true' && isSpanish($file) == 'true') {
            array_push($aFileList,$file);
        } elseif($sEsp == 'false'
          && isSpanish($file) == 'false'){
             if($codeMin=8 && 
                 (substr($file, 0, 1) ==  8
              || substr($file, 0, 1) == 9)){
                     array_push($aFileList,$file);
              } elseif ($codeMin == substr($file, 0, 1)) {
                 array_push($aFileList,$file);

(also fixed a mistake that would've broken your spanish links)
You don't see the code looking for values between 1000000 and 1999999 (etc) because I cheat and just compare the first character of the filename to the single digit that gets passed in the URL (min=1, for example).

This is the stretch of code that happens while we're looping through the files in the directory.  At the point where it begins, we've just verified that the filename is at least 10 chars long and ends in pdf.  What we're doing here is seeing whether or not we're looking for spanish files.  If we are, and the filename contains 'spanish', we toss its name into the array we use to populate the page.  If we're not looking for Spanish, then we make sure the name does not contain 'spanish' and then proceed to make sure the first character of the filename matches the 'min=x' argument we passed in the URL.

Of course, this new bit now checks to see if the code is 8, and if it is, the file gets added to the array if it begins with 8 OR 9.  If the code is anything other than 8, it uses the old method and just matches the first digit to the variable.  This code is getting sort of embarassingly hacked-together (lots of nested if-elseif statements are a pain to read, much less change), but it should still work for the new 800-999 tab.  Be sure that the 'on' and 'off' jpgs have the same name as the old ones, or else change the code.

If you do decide to go with a separate 900-999 tab, there are a few other things that will need to be changed.  Pretty minor stuff, most a result of me not planning as well as I should've.

Good job on the debugging, incidentally.  I keep writing this code in places where I'm not able to test it, but you did great without me.

Avatar of Chris24

ASKER

Hmmm, that broke it. Now it only shows 800000 through 999999 no matter what tab you're on.... Sorry ...
Doh!  Should be:

   if($codeMin==8 && 

not:

   if($codeMin=8 && 

We want to compare (==), not assign (=).
Avatar of Chris24

ASKER

You ROCK! The best help I've received yet since being a member! A HUGE learning experience too!

Chris
My pleasure.  Thank you for your patience!
Avatar of Chris24

ASKER

My patience? No way, thank you for yours!