A Fix for PDF Display Issues in Chrome

We came across an interesting bug in Chrome two days in a row, a PDF wouldn’t display correctly. It would be missing either an entire page or just some of the information on the page. There are published work-arounds to disable the built-in Chrome PDF viewer and instead utilize Adobe Acrobat Reader instead and also notices to maybe use a different browser. Let’s be honest here, the fault is the person/company that creates the PDF to make sure to optimze the PDF for the best viewing experience on the web.

Here is the problem, the Chrome PDF viewer cannot work with layered PDF files. I didn’t know layers was possible until just yesterday. Apparently, though I don’t yet know how, you can turn on and off layers (think of Google Maps with turning on and off features on the map). So how do you fix it? In both our our instances, we needed to flatten the PDF. Once we flattened the PDF and optimized it for the web, it showed up correctly in Chrome.

Don’t get me wrong, sometimes you will want those features and then you will need to provide a disclaimer stating that some PDFs may not render correctly in the Chrome browser. At least until Chrome adds support for layers.

A Responsive Google Map Application Template

At work, I am working on rewriting a bunch of maps so that they are consistent and mobile-friendly (a.k.a. responsive). When I starting searching for some basic how-tos I turned up nothing. I did find how to make Google Maps itself responsive. My issue was how do I add a legend and form that will filter or add content to the map and keep it mobile-friendly. Since I couldn’t find anything, I set forth to make something myself. In one weekend, I created a basic framework utilizing Bootstrap, the following week I refined and finalized the application and I think it turned out well.

I made the template open-source so that others can benefit from what I learned and help make this a better template in the future. I hope others can help me make this even more accessible and improve the template further.

I used Bootstrap because that is what I am most familiar with. In the future, if I have time, I want to try to eliminate Bootstrap to reduce the overhead. Once our new website launches, I’ll add some examples of what I created with the template so you can see why I felt this was important.

Here is what the large-screen version looks like:

Large screen view of application
Large screen view of application

Here is the mobile views:

Mobile View of Application
Mobile view of application
Mobile View of Legend
Mobile view of legend
Mobile View of Filter
Mobile view of filter

Do Not Use Comments

This came across my Hacker News feed the other day, “I’ve never seen a language’s style guide recommend avoiding comments before.” After reading the link it became clear that the HN title was link bait. What the Haskel documentation was stating is something any good programmer already knows. Don’t document every line of code.

x = x + 1; // Increment x by 1

This comment is not required as it is obvious what it is doing. My rule of thumb for commenting is; if it’s complicated or was problematic, it requires a comment explaining the why or why not. A good programmer should be able to read through the simple code and know what is going on. However, commenting on why you wrote something the way you did would help yourself or the next guy to know what you were thinking.

This comes to light not only when I am looking at code I wrote 5 years ago, but recently I had a co-worker leave. He didn’t write many (read any) comments in his code. Now in some cases I am running debug just to see what the application is doing before I can think of fixing that bug or making that change.

So do your future self or co-worker a favor and comment… but not too much.

Now monitoring my websites with Google Spreadsheets and Pushover

I used a previous version of this free monitoring tool, but I recently setup their new version. It is quite neat. Basically, it uses Google’s infrastructure to constantly hit your website and if it doesn’t get a 200 status back, it will contact you via email or SMS saying your site is down. While this was nice, I really wanted to use Pushover more. So I looked through their API and discovered it is very easy to send messages. So I modified their script and now I get notifications via Pushover. Here are the changes that you need to perform.

  1. Add two new rows after the SMS notifications row.
  2. Call the title’s what you want, but I went with “Pushover API Token ::” on A5 and “Pushover User Key ::” on A6.
  3. I created a new Pushover app
  4. I put the new app’s API token in B5 and my user key in B6.5. Go to Tools | Script editor…
  5. Then add the following code to the function logMessage(url, message) funtion in the script after the email portion:
    if (sheet.getRange(“B5”).getValue() != “”){           var options = {               ‘method’: ‘post’            };    var url = ‘https://api.pushover.net/1/messages.json?’     + ‘token=’ + sheet.getRange(“B5”).getValue()    + ‘&user=’ + sheet.getRange(“B6”).getValue()    + ‘&message=’ + alert    + ‘&title=’ + “Site ” + message;    var response = UrlFetchApp.fetch(url, options);        }

Controlling a Epson TM-T20 on the IBM i (or iSeries)

The past couple days I was on a mission to look for a way to replace our aging dot-matrix receipt printer. We got some new printers to go with our new credit card processor. These printers are Epson TM-T20 thermal printers. I had some problems finding the information to have the printer cut the paper and to get it to eject the cash drawer. I am documenting what I found here for people in the future to figure out.

You need these codes embedded in the spool file. The first hex character, 03, tells the OS we are sending ASCII characters. The second, 06, tells the OS that the next x characters are ASCII.

  • To cut the paper – X'03060D0A1D564220'
  • To eject the cash drawer 1 – X'03051B703040F0'
  • To eject the cash drawer 2 – X'03051B703140F0'

Add a custom IBM i library list to a C# application

Ever find that you need to add a custom library list to a C# application that works with IBM i data? Here is what you need to do. Add LibraryList= to your connection string. So that would look like:

connectionString="DataSource=127.0.0.1;DefaultCollection=MYMAINLIB;Naming=sql;
UserID=USERNAME;Password=PASSWORD;LibraryList=MYMAINLIB,LIB2,LIB3;"

Creating a better emailed statement in RPG using CGIDEV2

We had some… problems with our utility bill emails. They weren’t worded clearly enough that some people were getting confused. See, when I wrote this, used the only approach I knew and manually assembled a string of text until the email was created (depended upon if they were auto-pay or not), but over all the emails were very similar. We like to be customer friendly, so we decided we better make the emails clearer.

After working with our communications department, they came up with a very good set of emails… that don’t work well with how I am currently assembling the emails. Damn!

So, I walked back to my desk feeling like “Oh crap! I have a lot of changes to do.” Then I had the thought that too bad I can’t template… oh yes I can! CGIDEV2 does that! Since I haven’t done much in that field, I figured I would hit up the midrange.com WEB400 community to see what else there is out there. I came back with a list of a few frameworks, but most people basically said that CGIDEV2 was the best place to start. One helpful person, gave me the following list:

I decided to use CGIDEV2 as that was the most promoted package. After I had it installed, tried to figure out what I needed in order to do what I want. Here is the minimal information that is needed:

First you need to add the following two copybooks to your D-specs:

/copy CGIDEV2/qrpglesrc,prototypeb
/copy CGIDEV2/qrpglesrc,usec

Then in my loop I did the following:

dow (not %eof());

// Clear the buffer to make sure it is empty.
callp ClrHtmlBuffer();

// Pull the correct message.
if (autopay());
callp gethtmlIFS(‘/utilityBillText/UtilityBillAutoPay.txt’);
else;
callp gethtmlIFS(‘/utilityBillText/UtilityBillRegular.txt’);
endif;

// Update the variables in the message
callp updHTMLvar(‘custnum’:%editw(CustN:’0 – ‘));
callp updHTMLvar(‘serviceaddr’:%trim(Adrs));
callp updHTMLvar(‘balance’:%char(balance));
callp updHTMLvar(‘duedate’:%char(%date(DueDt):*usa));

// “Write” the file into the buffer
callp wrtsection(’email_body’);
// Save the file to the IFS in the tmp directory.
rc = WrtHtmlToStmf(‘/tmp/emailbody.txt’);

// Send email through MailTool (http://bvstools.com)
SendMailAttachment(fromAddr:
%trim(toAddr):
”:
”:
subject:’*ATT’:’/tmp/emailbody.txt’);

read FILE;

enddo;

Suprisingly this worked the first time! Now if the communications department ever wants to change the email, all I need to do is update the text and the email is now changed.

I hope this helps others that are looking at doing this.

How to Debug a Batch Program

Via BVS/Tools – FAQ

How do I debug an RPG program in batch?
Submit your program into batch and make sure it is held. Do this by either holding the job queue that you are submitting the job to, or use the HOLD(*YES) option on the SBMJOB command.

  • Use the WRKUSRJOB and display the job you with to debug with the display job option (5).
  • Write down the user name, job name and number.
  • Start a service job using STRSRVJOB entering the name, job name and number from the previous step.
  • STRDBG PGM(YOURPGM) – Press F12 to exit the source display (Sorry, can’t enter breakpoints yet).
  • Release your submitted job by releasing the job queue or the job itself.
  • A display will appear asking you to press F10 function key. Press F10 and you will be brought to a command line.
  • Enter DSPMODSRC and enter your breakpoints.
  • Leave source display and command line by pressing F3 until you are back to the screen that asks you to press F10 to enter breakpoints.
  • Press Enter to start your job.
  • After that the job begins running and stops at the first breakpoint reached.
    Also, you can create a simple CL to combine the two commands to make it easier to use. I created a command STRBTCHDBG so it is really simple to use. I might post the source to that later.

Chili Bread Bowls

I have been loving the Artisan Bread in 5 Minutes series of books so today when we thought that making bread bowls and chili sounded good I went to my bible of bread.

To start with, make your own favorite chili and let it simmer all day in the crock pot (because it tastes better that way).

I then turned to the original Artisan Bread in 5 Minutes a day book. I choose the master recipe, the boule since it was easy to work with and I knew it had a nice crust to prevent it from loosing shape when the chili was added. I tried several sizes of loaves to see what size worked the best. We discovered that while the 1/2 lb loaf was too small to hold more than 1 scoop of chili, it was just the right size for a complete meal.

Loaves of bread cooling

The 1/4 lb loaves were way too small. The 3/8 (or so) lb loaves were just right for the kids.

All I did was take a sharp knife and cut a circle in the top pushing the blade most of the way in. Then pull out the bread until it was a good bowl. I did nothing special on the inside beyond that. Now you can see the finished product.

The only problem? It takes so long to bake enough bread if we were to have more guests!