You are here

Blogs

Adding a custom link to a Drupal 7 Views Template

Anyone familiar with Drupal knows Views. It's great for pulling information from the database and displaying it in just about any format you want. I recently set up a job listing site, which was pretty trivial task in Drupal (I've seen guides on setting up job listing sites in a few Drupal books). The problem I had was when I needed to add a separate "read more" link to the job listing after the description text.

Image of the job listing site

Overriding the default output on the table was simple… Views shows the list of suggested template override filenames under "Advanced → Other → Theme: Information". In my case, the template to create "theme_directory/templates/views-view-field--list-all-jobs--page--body.tpl.php". I started by copying the content of "/sites/all/modules/views/theme/views-view-field.tpl.php" and modifying to taste. Creating the "read more" link to that row's node was done using the following code.

print $output; echo '<a href="', url('node/'. $row-&gt;nid, array('absolute' =&gt; TRUE)), '" class="readMore">Read more…</a>';

The documentation for the function url(...) can be useful in understanding what's happening here. Basically, we're using the node ID to make the URL "node/X", and then asking the "url" function what the absolute URL for that path should be. This returns the full path for that link as defined in the alias for the node.

Automatically resizing Colorbox to IFRAME content

This is going to be a quick mind-dump, and hopefully it's helpful to someone. I swear, I have plans to go back through this blog and make things sensible to the sensible reader some day, but I never take/find the time :-p

I needed a good way to automatically resize a Colorbox popup to the size of the loaded IFRAME content. Colorbox itself provides the callbacks and methods to make this possible, so it was just a problem of calculating the dimensions of the IFRAME's content. The following code assumes that the IFRAME content is on the same domain as your parent page… this code won't work across domains.

The BODY tag, being a block-level element, automatically becomes 100% the width of the IFRAME. If the content of the BODY tag is wider or narrower than the initial IFRAME width (which, since we're trying to auto-calculate the width, it's a safe assumption that the width is different) we'll need to make the BODY tag the correct width before measuring it. I do this in the following code by floating the BODY tag, then removing the float after the measurement is finished.

// Initialize colorbox for gallery links $(function() { if (!$.fn.colorbox) return; // Initialize Colorbox for the IFRAME links, setting a loading width and height and // telling Colorbox to wait until the IFRAME finishes before calling onComplete $(".detailRow .viewGallery").colorbox({ "iframe": true, "fastIframe": false, "innerWidth": 480, "innerHeight": 360, "onComplete": function() { // Do some work to automatically calculate the height and width of the IFRAME's content var iframe = $("iframe.cboxIframe"), body = iframe.contents().find("body"), floatStyle = body.css("float"); // Float the BODY so that it assumes a minimal width body.css("float", "left"); // Resize the colorbox $.colorbox.resize({ "innerWidth": body.width(), "innerHeight": iframe.contents().height() }) // Remove our float style on the BODY body.css("float", floatStyle); } }); });

Javascript Message Window

I'm working on a popup message window for my uncle's game Dark Expanse. The idea is that clicking a star on the star map will pop up a small "e-mail" window displaying messages related to that star. The code is a work in progress, but I just hit a milestone and wanted to upload it quick.

At this point, the data is loaded using a $.getJSON call, displayed in the message selector, and clicking a message loads it into the display area. The last few hours have been spent integrating a scrollbar solution so that the scrollbars are always a fixed width, instead of dealing with browser and UI inconsistencies. I used Tiny Scrollbar created by Maarten Baijs because it was simple, straightforward, and very lightweight. I've also handled up and down arrow keystrokes, and set it so that the scrollbar updates when the newly selected message is outside of the viewport. I'm not sure if anyone else will find this code useful, and I'm not even sure what to call it, but perhaps someone else needs something similar.

Here it is

Format price output with Javascript

What follows is a script to format price output in Javascript. The function takes as its input a single number, forces exactly two decimal points, then adds commas for the the thousands, millions, etc. Finally, before returning the output it adds the dollar symbol and a minus sign if applicable.

Depending on where you are using this script, you may not be able to guarantee that only numbers are being passed to the code. For example, you may need to parse a string on the page to get a number before doing math (to apply a discount, calculate a price difference, etc). The first function will strip out non-numeric characters, then convert the number to a price with two or fewer decimal points. If I remember correctly, the multiplication and division by 100 not only serves to round to 2 decimal points, but also avoids a floating number problem (but I can't remember exactly, or I'd test it…).

// Take a string (possibly containing currency symbols and/or commas), // and strip out the extra characters, returning an actual number. function parsePrice(str) { return Math.round(Number(str.replace(/[^-\d\.]/g, "")) * 100) / 100; } // Take a number, and add all the necessary prettifying characters that // make a number look like a price (currency symbol, minus sign, commas). function formatPrice(price) { // Run toFixed to force exactly 2 decimal points // Note: This will round the thousandths up if applicable. For example, 3.145 // will be rounded to 3.15, but 3.144 will become 3.14 var value = Math.abs(price).toFixed(2), commaRe = /([^,$])(\d{3})\b/; // Add commas in convincing locations while (commaRe.test(value)) { value = value.replace(commaRe, "$1,$2") } // Add the appropriate currency symbol and minus sign if applicable return (price &lt; 0 ? "-$" : "$") + value; }

So for example, say you want to apply a discount of 20% to a product page dynamically (not necessarily a good idea, but it's late and good examples aren't coming to me easily atm). The page lists the product price as "$8.99" in a DIV with the class="price". Using jQuery to get the DIV, you could write:

// Get the price from the page, and parse it to a number var listedPrice = parsePrice($(".price").text()); // Do our multiplication by .8 to get a 20% discount, then format that price and // and display it in the ".discountedPrice" element $(".discountedPrice").text(formatPrice(listedPrice * .8));

… or, you can do the entire bit on one line, if readability isn't an issue :-p

jQuery :checkbox replacement

I had to set up a checkbox replacement for the site http://www.reallysimplesurvey.com/sign-up, so I first went looking for a good replacement. I found one that I'd used before, but it required jQuery UI. Since I hate adding jQuery UI for "simple" tasks, and since trying to get jQuery UI working sanely in Concrete5 can be a bit of a trick, I decided to write my own (people who know me know it doesn't take much to convince me to rewrite Javascript just for kicks and giggles…).

I had some trouble with race conditions in IE, and I didn't spend too much time troubleshooting why, so the code might be sloppier than usual. Also, the only comments in the code at the moment are IE gripes, so my apologies :-p The use of double-class selectors means IE6 won't show when the checkboxes have keyboard focus, but all else should work without problem.

Please take it for a test spin and let me know how it works. This is the first release, so YMMV and feedback is welcome.

Screenshot of checkbox demo

Lossy PNG Compression

I finally found a program that I've been dreaming of for years. Image Analyzer will perform lossy compression on PNGs, preserving the alpha transparency of the PNG file while, in most cases, creating a file comparable in size to a JPEG.

Originally I had hung my hopes on JPEG 2000, which supported alpha transparency as part of the updated JPEG file format. However, application support for the new format never coalesced, and 11 years past the release of the standard it still isn't supported by Firefox or Internet Explorer.

Back to Image Analyzer… Loading a PNG with alpha-transparency into the program will trigger a dialog which asks whether it should "Merge alpha channel with picture?". Choose No to load the alpha channel and RGB data as separate images, then choose the RGB image and choose "Save As" from the File menu. From the save dialog, click the "File format option" button on the right-side of the dialog. Click the "Alpha transparency" checkbox and choose the correct alpha channel from the dropdown that appears. Then choose the compression quality from the slider at the bottom of the dialog. The default quality setting is lossless. I've found a setting of about -7 to be a nice balance between the size of the file and the quality of the output. The "Test" button allows for previewing of each quality setting to find what works best for each image.

The program works like a charm, and the output looks great. This saved my sanity while working on a new gradient-and-dropshadow heavy website that refused to cooperate with my attempts to flatten the images. PNGs again ftw.

jQuery SELECT Dropdown

I'm toying with some code to reproduce a SELECT dropdown using jQuery and some CSS3. The default SELECT element is notoriously difficult to style, but also amazingly difficult to program in a manner that works properly across browsers. I've seen many different projects along the lines of what I've done here, but I finally found one that I liked :-p The original code is from the blog Janko At Warp Speed. I will continue to clean up this code, but for now it is provided without warranty or promise of any kind, so YMMV. For the record, have not even tested in IE yet. Click below for the demo page.

Update (2011-02-23)

I finally got around to adding OPTGROUP support for a project I'm doing, and I added a few examples showing how the code can be used for site navigation (UL-LI-A dropdown navigation, instead of using a SELECT with an "onchange" handler). My next set of goals is to add keypress support, figure out the best way to make sure the dropdowns always show the same value as the SELECT (even after a page refresh), and maybe add a few more display styles.

Update (2011-05-23)

I'm still doing work on this project (amazingly). I finally organized the CSS, moving it and the Javascript out of the HTML and into their own files. I also added a download archive and slapped a license at the top of each file (I've been using this code frequently and the license links back to this site). I plan on adding SELECT MULTIPLE and keystroke functionality for a project. I'm hoping ARIA support is not far behind.

Screenshot of the dropdown demo

CSS3 tabs for your webpage

I wanted a nice, almost 100% CSS styled layout for my Javascript tabs. So with the help of the CSS Gradient Generator I set about doing that. All the gradients and rounded edges are CSS3-based, with the exception of the gradients used by IE (PNGs generated by the aforementioned website). Please check out the demo, let me know what you think. I have a feeling some fixes will be necessary for IE6, but I'm getting there…

I am also struggling to add CSS3 drop shadows to the tabs. I'm not sure if there's a simple way to do it so the tabs don't overlap onto the area below the tab. If someone wants to take a swing at it, please let me know.

Screenshot of the tab demo

Preventing Javascript alerts

This is a quick blog post, but I thought it was worth sharing. There have been a few times where I haven't had control over all the code on a page, and something on the page insists on spitting out an alert. Often this happens at the worst possible times, like when I'm trying to load another page in an IFRAME. I work with a lot of different e-commerce platforms (the current system giving me grief is Network Solutions Commerce Space, formerly Monster Commerce), and each platform does things differently.

If I want to add an item to the shopping cart using an IFRAME, the CommerceSpace platform spits out a Javascript alert every time an item is added. That's a little ridiculous (not to mention so 2000 and late…). So here you go… drop this in the page as early as possible.

window.alert = function(str) { window.console &amp;&amp; console.log("Alert: " + str); };

That's it. Now any unwanted alerts will be sent to the window.console instead. If you still want to be able to use window.alert later, make sure to save a reference to it first (see Prevent js alert() from pausing timers at Stack Overflow).

I just found out about window.stop() as well… I'm thinking this might be fun and useful as well. Preventing the little "page loading" jogger from running longer than necessary? Or as Jeff said…

(01:56:59 PM) Me: whoa! how have I never seen this before? http://www.java2s.com/Tutorial/JavaScript/0380__Window/windowstop.htm
(01:57:06 PM) Me: Floating Cart? I'm just saying...
(02:28:07 PM) Jeff: all this talk makes me hungry for ice cream

Faking the CSS "box-shadow" property in IE

Note: All of this information has been supplanted by the up-and-coming CSS3 PIE library. CSS3 PIE offers a much better method for mimicking CSS3 elements in IE than anything mentioned below.

I was toying with the IE-only "filter" CSS property, trying to get it to reproduce the look of the new "box-shadow" property. There are several pages (such as Chris Casciano's blog) describing the problem, and some interesting solutions. I found two interesting pieces of code on the web during my search.

The first looks like a variation of the jQuery Box Shadow plugin mentioned on Chris's blog. It was originally part of the jQuery UI package, then it was spun off into a (now deprecated) jQuery Enchant library. A copy of the code can be viewed at http://dev.jquery.com/browser/trunk/fx/current/fx.shadow.js?rev=3827. What I found interesting was the use of IE-only CSS expressions to make sure the drop shadow was always absolutely positioned at the correct place on the page.

The second uses VML and IE behaviors to generate the drop shadow, and also supports rounded corners (http://code.google.com/p/box-shadow/). However, the author says there are some limitations with the VML that I know already have work-arounds (see the DD_roundies library). I'm curious if this could be extended a little more.

Pages

Subscribe to RSS - blogs