Archive for June, 2012
Building a Better WHD Notifier
by TrueJournals on Jun.29, 2012, under programming, technology
At my work, we use Web Help Desk to track support tickets. It’s a very nice, very slick piece of software, and from my understanding, version 10.2 implements an API going forward. Unfortunately, we use version 10.1.10.1, which doesn’t have the same API.
The problem I ran into was this: often, there are other tasks to be completed, so I’m not just staring at the WHD ticket queue the entire time I’m at work. However, if a client logs a ticket, I have no way of being notified without going to the web help desk page and checking manually. This results in one of two things happening: either I check the ticket queue every few minutes, breaking my workflow on other projects, or a ticket doesn’t get responded to for a while.
I wanted a way to be notified of new or updated tickets that pop up without having to continually go back to the WHD tab of my browser to actually check for new or updated tickets. Unfortunately, without an API, I thought this was going to be difficult. Until I found this: a WHD Notifier for Chrome.
However, this still didn’t quite achieve what I was looking for. While this did provide me with a notification of the number of new or updated tickets within the browser, it didn’t notify me when this number changed. So, I still had to watch my web browser, and even then, continually check this small, inconspicuous number in the top-right corner of my screen. Since Chrome extensions are simply Javascript, HTML and CSS, I decided to try my hand at modifying it to better suit my needs.
Here’s the list of things I needed:
- Pop-up notifications of a change in the number of new/updated tickets (like in Gmail).
- The ability to not save username and password. The computers share a single profile between multiple users, so I don’t want individual passwords saved past the browser session.
- (Optional, if I could figure it out) Grabbing login info from the WHD web login, so you don’t have to go into the extension options every browser session.
After some coding, a lot of trial and error, and a lot of research, I was able to meet all three goals. If you’d find it useful, you can download WHD Notifier version 1.5. Simply configure it with your WHD URL, choose what to display/be notified of, and you’re good to go. If you login to web help desk, the notifier will grab that login information and start updating.
If you’re interested in seeing the source code for this extension, you can find a zip of the source here. I’ll see if I can throw it up on GitHub later today or this weekend. There’s some interesting things being done here — submitting the login form in WHD sends a call to forms.submit() instead of going through the normal submit procedure — this means that I couldn’t simply add an onsubmit handler to capture the login information.
Instead, I inject another piece of JavaScript into the page which overrides the submit() method for all forms. This calls chrome.extension.sendMessage to message the background page with the username and password, then proceeds to call the submit() method I had overridden. You can find the form handling things in autoLogin.js and autoLogin2.js. I had to inject autoLogin2.js on the page because chrome content scripts aren’t allowed to override prototype methods.
If we ever update our WHD installation, I’ll try to update this extension again to use the new API — I should be able to add some more features with that, too. For now, this should work for all versions of WHD 10.0.8 or later.
Update: Code is now on GitHub
Automatically Associating Label and Input, and Setting Width
by TrueJournals on Jun.26, 2012, under technology
When creating forms in HTML, one of the best practices is to always use <label> to associate the labels with their form fields. However, this creates the complication of needing to give each label the “for” attribute, and perhaps wanting some extra magic to set the width of each label so that all the form fields are lined up. Recently, I decided to play around with form fields like this a little to see if I could automate this process using jQuery.
Here’s what I came up with:
var w = 0; $("label").each(function() { if($(this).width()>w) w=$(this).width(); // Assume the input immediately follows the label var input = $(this).next(); input.prop('id', input.prop('name')); $(this).prop('for', input.prop('name')); }); $("label").width(w+10); $("label").css('float', 'left');
And here’s what it does: first, it loops through each label on the page looking for the maximum width. When it finds that, it sets all labels to have a width of (maximum width)+10px. The extra 10px are just so the label and field aren’t directly on top of one another.
In the same loop, this code associates the label with the field next to it. For my sake, I made the assumption that I will always have <label>…</label><input />. If this is not the case, the code will associate the label with the wrong field. It simply sets the next element’s id to be the same as its name, and sets the label’s “for” property to be the element’s name, also.
Use this with caution. If you’re not careful, you could end up with duplicate IDs (a no-no). There are other reasons this code isn’t necessarily a good idea, but it’s good enough for me. For a page with a lazy HTML coder, this will work perfectly.
Bonus: Add input.prop(‘placeholder’, $(this).text()); inside the loop to also set the “placeholder” text to whatever the label is. You could also detect if the browser supports “placeholder”, and hide the label if it does:
var w = 0; $("label").each(function() { if($(this).width()>w) w=$(this).width(); // Assume the input immediately follows the label var input = $(this).next(); input.prop('id', input.prop('name')); input.prop('placeholder', $(this).text()); if('placeholder' in document.createElement('input')) $(this).hide(); $(this).prop('for', input.prop('name')); }); $("label").width(w+10); $("label").css('float', 'left');
Conditional Formatting in Google Docs
by TrueJournals on Jun.05, 2012, under technology
Recently, I was working on a project which involved generating a spreadsheet of a bunch of changes I was making to some information. As part of this, I wanted to color code the rows of the spreadsheet: green would mean OK, yellow would mean a change, and red would mean a problem. I could do all this formatting manually… but I decided to find a way to make Excel do it for me. Enter conditional formatting!
Conditional formatting in Excel is very, very robust. For this project, I needed to change a row’s background color and font color based on three possibilities:
- If Column E has any text, the row should be red.
- If Column A and Column D contain different values (case-insensitive), the row should be yellow.
- Otherwise, the row should be green.
Unfortunately for me, Excel’s conditional formatting works on a per-cell basis. However, Excel does provide the ability to choose conditional formats based on a formula! After some fiddling with Excel functions, I was able to generate formulas to check different cells in the row, then apply the conditional formatting based on that. I ended up with these three formulas, executed in this order, and corresponding with the above three conditions:
- =AND(CELL(“contents”, INDIRECT(CONCATENATE(“E”, ROW())))>0,ROW()>1)
- =AND(CELL(“contents”, INDIRECT(CONCATENATE(“A”, ROW())))<>CELL(“contents”, INDIRECT(CONCATENATE(“D”, ROW()))), ROW()>1)
- =AND(CELL(“contents”, INDIRECT(CONCATENATE(“E”, ROW())))=0, CELL(“contents”, INDIRECT(CONCATENATE(“A”, ROW())))>0)
Wow! First, notice all of these start with an AND function. AND evaluates the conditions given, performs a logical AND on all of them, and returns a boolean true or false based on that. Explanation of the conditions:
- Two conditions:
- CELL(“contents”, INDIRECT(CONCATENATE(“E”, ROW())))>0 checks for text in Column E. If there is nothing in the cell, the value is 0.
- ROW()>1 checks if this cell is NOT in the first row. The first row is my header row, and I don’t need that one color coded.
- Two conditions:
- CELL(“contents”, INDIRECT(CONCATENATE(“A”, ROW())))<>CELL(“contents”, INDIRECT(CONCATENATE(“D”, ROW()))) checks if the contents of the cell in Column A and the contents of the cell in Column D are different. The <> operator is “not equals”, and Excel seems to automatically do a case-insensitive comparison.
- ROW()>1 checks if this cell is NOT in the first row.
- Two conditions:
- CELL(“contents”, INDIRECT(CONCATENATE(“E”, ROW())))=0 ensures that Column E is empty. (Again, the value is 0 if there is nothing in the cell)
- CELL(“contents”, INDIRECT(CONCATENATE(“A”, ROW())))>0 ensures that there is some value in Column A. If there’s no value in Column A, there’s no point in any highlighting.
Alright… So, with all those conditions set up, text is automatically highlighted based on what values are entered. This made editing the spreadsheet really easy: simply type in values, and the highlighting is automatic. If I go back and change something later, the highlighting changes without me needing to do anything. (continue reading…)