Django: autopaginate template tag causes "Caught an exception while rendering: 'request'"

The template tag "{% autopaginate list_name 15 %}" threw up a little in the mouth when I added it onto a new project.

Problem?

Apparently the following line threw an exception.

File "paginate/templatetags/pagination_tags.py", line 90, in render

The code throwing this error is:

try:
    page_obj = paginator.page(context['request'].page)
except InvalidPage:
    ...

Solution?

In your "settings.py", add the following.

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.request',
)

Whalla, problem solved.

[ Source ]

Lotus Notes: Change the default browser which links open up in

Sticking with Lotus Notes is like being content with using a stone wheel. I mean it might be slow and rough around the edges, but it still gets the job done and thats what matters... right...?

Well anyway, another day in the office, another trick learnt on this old dog. I still cant decide if I'm referring to my work PC or Lotus Notes, but I know that I'm really sick of links in Lotus Notes opening up in Internet Explorer 8.

Its uber slow to start on the even slower computer and every link I click reuses the same tab on IE8 (even when I've changed the stupid settings!!!) and I constantly have to keep clicking back.

Luckily, our miserable Lotus Notes does have an option to change the default program to open up internet links. Unfortunately, its stashed away under a series of convoluted menus.

  • In the menu, click "File"
  • "Preferences"
  • "Location Preferences ..."
  • Select the "Internet Browser" tab
  • Click the little dropdown arrow beside your current browser (Probably says "Microsoft Internet Explorer")image
  • Select "Other"
  • Click on the flashlight icon to find your browser executable.image
  • Remember to click "Save and close"

Now send yet another angry email telling your IT manager to get off his ass and do his job. That is to migrate from this ancient piece of shit to another email exchange system that isn't from the Genghis Khan dynasty.

Related posts

Bash Shell: Passing in arguments to build a reusable command

Aliases are great, but it sucks when you need to mix arguments into certain parts of the command rather than after the alias itself.

There are some things we type on a regular basis which cant be put into aliases. An example would be the command I use to clone from git.

git clone git@git.server.com:git_project_name.git clone_name

I would of liked to use an alias in this way:

alias_name git_project_name clone_name

But when executed, it'll come out as:

git clone git@git.server.com:.git git_project_name clone_name

For this, I've resorted to writing a script called "clone_git.sh".

#! /bin/bash
# script to git clone

PROJECT=$1
shift
SEARCH="git clone git@git.server.com:$PROJECT.git $@"

echo $SEARCH
$SEARCH

Using the script with this syntax:

./clone_git.sh project_name clone_name arg1 arg2 arg3

Will produce:

git clone git@git.server.com:project_name.git clone_name arg1 arg2 arg3

The shift command removes the first argument off the list, so "project_name" will be removed from "$@".

Now if you dont require a variable number of arguments, you can simplify the script by removing the $PROJECT variable, removing shift and replacing "$@" with "$2".

The script will now look like:

#! /bin/bash
# script to git clone

SEARCH="git clone git@git.server.com:$1.git $2"

echo $SEARCH
$SEARCH

Calling the script with the same syntax will now produce:

git clone git@git.server.com:project_name.git clone_name

[ Sources: $@ and Shift ]

Git: Uncommit revision but keep changes

After accidentally committing some stuff to the git repository, I had some trouble finding a way to "uncommit". Luckily a few notes on the net pointed towards the reset command.

git reset HEAD^

This will leave your changes intact, but bump down the revision of your branch.

[ Source ]

Git: Shelving changes and bringing them back later

To stash minor changes away on the shelf for later retrieval, use:

git stash

To display a list of changes you've got on the shelf, use:

git stash list

And to retrieve the changes, use:

git stash apply #

Where # is the ID of the change you want to retrieve.

[ Source - git manual ]

Win7: Windows 7 Whopper

More and more media pops up about the Windows 7 launch press stunts, but one which has caught my interest is the Windows 7 Whopper from Burger King (also known as Hungry Jacks in Australia).

This PR stunt neatly captures three of my favourite things in life; insanely unhealthy foods, nerd stuff and the Japanese.

image

Invention: Alarm Clock with Weather Forecast

Whats the first thing you think of when you reach for the alarm clock? Well, apart from grabbing a hammer and smashing the snooze button to bits. Of course its "Whats the weather like today?" !

Why does it matter? Because that'll greatly determine if you bring an umbrella on a day where there'll be torrential rain or what you wear on a freak cold snap.

Shit transitional seasons like spring or autumn can lay a badass smackdown on your ass harder than a fullbred male netball team complete with Tom Selleck Magnum PI moustaches.

male_netball_team

Windows 7 Marketing Must Be Working If ...

Your parents are excited about it and asking for it to be installed on their computer.

Must be those damn wild tupperware parties they're holding going off chops!

6109

Invention: Hot water pipes that don't lose pressure

How many times have you tried to get the perfect mixture of hot/cold temperature before showering, only to have the hot water slow to a trickle just in time for you to hop in?

The reason behind this is simple. Cold pipes are smaller and expand when heated up. The thicker the pipe, the more pressure is required to push the water through at the same rate, which is why you need to turn up the hot water occasionally.

I wish some day that a smart person would invent a cheap material that would not expand when hot water flows through it, making it unnecessary for me to adjust the temperature!

If Architects Had to Work Like Web Designers

A great rant about the sort of things which web developers have to deal with.

Python: Simple for loops

For example you have a piece of code that runs through and performs an operation on each item in a list.

items = [ 'hello', 'there', 'blah' ]

for i in range(len(items)):
items[i] = items[i].replace('e', 'i')

You can turn it into a 1 line wonder by changing it to:

items = map(lambda x: x.replace('e', 'i'), items)

Or you could just use what triclops mentioned which is MUCH simpler...
items = [word.replace('e', 'i') for word in items]

NOD32: Remove "This message was checked by ESET NOD32 Antivirus" tag from emails

I really hate it when products advertise themselves. Not to say anything bad about NOD32, its a frikken awesome antivirus without all the Norton bloat.

But something that gets annoying is a ridiculously large signature at the end of an email, especially if you're discussing something and the combined signatures end up becoming the bulk of the content.

__________ Information from ESET NOD32 Antivirus, version of virus signature database 4525 (20091020) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

To remove the appended signature at the end of your inbound and outbound emails:

  • Set NOD32 to "Advanced mode"
  • Expand "Antivirus and antispyware"
  • Click on "Email protection"
  • Change the settings for the received and sent emails to "To infected email only" or just disable it altogether.

image

Django: 'Model.fields' refers to field 'fieldname' that is missing from the form.

Weird, I'm certain that this field exists. Checking the model confirmed it. Look, its right there!

published = models.DateTimeField(auto_now_add = True)

Even after restarting the server and deleting *.pyc files, it still refuses to work.

'PromoAdmin.fields' refers to field 'published' that is missing from the form.

Exception Type: ImproperlyConfigured

Exception Value: 'ModelAdmin.fields' refers to field 'fieldname' that is missing from the form.

The solution? Simple. Remove "auto_now_add = True".

published = models.DateTimeField()

The validation of the form meant that fields that DateTimeField is values are automatically entered when added. With that reasoning, they are "read only" and are not displayed on the admin form.

[ Source ]

Win7: Disable Grouping of Taskbar Icons

Despite all the improvements to the taskbar and customisation available, there is still room for improvement. My main gripe with the new taskbar is that the tabs are grouped when they belong to the same application instance.

Fortunately, a fella by the name of RaMMicHaeL has developed 7 Taskbar Tweaker. As of v1.0.1 it allows you to:

  • Use the standard window context menus by default (same as holding shift + right click)
  • Modify the drag + drop behaviour
  • Change middle click behaviour
  • Disable Aero Peek
  • and my favourite, disable grouping of taskbar items

image

The grouping option requires the applications to be restarted, but it can easily be solved when the application runs on startup.

No setup required, just extract and run. Simply brilliant!

[ Source ]

Win7: Nvidia drivers crashed and automatically restored

For the first time, the NVidia drivers I had installed on Windows 7 (v8.15.11.8603, released 27/05/2009) crashed.

Normally, on WinXP, this would of given the operating system some sort of rabid disease akin to UmbrellaCorp's T-Virus leaving you no option but to either set it alight or deliver a swift and strike to the head that would severe the spine.

But alas, Windows 7 just handled it gracefully and simply caught the error, took it by the hand, walked it out the door and said goodbye. It even took the initiative to clean up after the accident and restart the drivers for you.

At first I thought the whole computer crashed. The screen blanked out for a second or two but came back. The theme had reset to a Vista-ish black theme while it stumbled.

A very pleasant surprise. Props to Microsoft for doing something right!

Green Initiative: Compulsory "Earth Hour" every day for offices

A thought as I was riding up the lift to work today. If Earth Hour has proven so effective in savings energy (all unnecessary electronics and lighting is turned off for the hour it takes effect), why not take it to the next step and make it mandatory everyday for offices around the world?

We've seen it work, people are willing. Why not do it?

Microsoft Office: Open up .docx, .pptx and .xlsx In Older Versions of Office

Office 2007 is one of those love me or hate me types of changes. Personally, I think its very much form over function. Too much relearning involved to be practical in the office.

To help promote transition to the new 2007 edition, they've set the new file extensions as default when saving. How fucking annoying!

That means everyone running the older versions of Office will have to either:

I presume that there has been enough complains about this that Microsoft felt the need to release this. It simply provides compatibility with the new format for older versions of Office, allowing them to at least read from the new format.

Get the person using Office 2007 to save in an older format by default.

Compatibility seems limited to Office 2000/2002 and 2003 at most.

[ Source ]

Matching names, titles or products from different systems for similarity

Everybody has slightly different way of naming things. For example, I like to name my music as "Artist - Title" while others prefer "(Artist) Title" or even "Title - Artist".

When it comes to matching product names or models, it gets even worse as some lists will include hyphens in the product names while other lists exclude them.

The "Kingston 128MB PC133" ram stick has the model name "KVR133X64C3Q-128", as some lists will exclude the "-" and display it as "KVR133X64C3Q128".

Sometimes it gets even more ridiculous. I had to match products from my workplace, our internal products database to an external feed which had product names such as "Sony 26 KLHW26 Commercial LCD TV Hotel Model, 1366x768 Resolution, 1300:1, HDMI, Component, S-Video, Composite (KLH-W26)".

I haven't been able to find any one hit wonder method to get this working, and its quite CPU intensive for larger catalogues of information.

The methods are used together in an attempt to find the closest match, with more precise or efficient methods at the top of the stack since they hit more often.

Examples will be written in PHP since its fairly simple to translate into other languages.

function find_matching_product() {
  if ($id = method1()) { return $id; }
  if ($id = method2()) { return $id; }
  // ...
  return null;
}

Prior to performing any matches, it is a good idea to lowercase all the names and strip any non-alphanumerical characters. This will simplify your problems a great deal.

Intel Core 2 Quad Q9550, 2.83GHz, Quad Core, Socket LGA775, 95W TDP, 1333MHz FSB, 2x6MB L2 Cache, Boxed, Yorkfield (BX80569Q9550)

Should become:

intel core 2 quad q9550 283ghz quad core socket lga775 95w tdp 1333mhz fsb 2x6mb l2 cache boxed yorkfield bx80569q9550

Using PHP and regex, it should look something like this:

/**
* Strips any characters other than numbers, letters or spaces from a string.
*/
function strip_string($string) {
  return preg_replace('/[^\da-z ]/', "", $string);
}

Another point to take note of is the use of the fake space (ascii value 160) as a seperator. Replace it with spaces asap!

Method 1: Strip back the longer title

This is a fairly quick and simple one. Trim back the excess on names (separated by spaces) until there is a match. Works best until there are less than 4 words, then it has a fairly high false positive rate.

Name A: intel core 2 quad q9550
Name B: intel core 2 quad q9550 283ghz quad core socket lga775 95w tdp 1333mhz fsb 2x6mb l2 cache boxed yorkfield bx80569q9550

The red writing is to be truncated until there is a match of "intel core 2 quad q9550".

The following function is passed this PHP array, which acts like a dictionary in other languages. The filtered name of the product is used as the key and the ID is the value.

$cache = array(
  'intel core 2 quad q9550' => 12345,
  'dell inspiron 15' => 12346,
  'microsoft 600 keyboard' => 12347,
);

It is also passed the name of the item to match.

function get_matching_product(&$cache, $name) {
  $stripped = strip_string(strtolower($name));

  // Break up the name at spaces and convert it into an array.
  $fragments = explode(' ', $stripped);

  while (count($fragments) > 2) {
    // Convert the array back into a string
    $joint = implode(' ', $fragments);

    // If there is a match for the exact name
    if (!empty($cache[$joint])) {
      return $cache[$joint];
    }

    // Pop the last item off the array
    array_pop($fragments);
  }

  return NULL;
}

Method 2: Exact Model Matching

If you are fortunate for the incoming product data to include a model number somewhere, use it!

function get_matching_product(&$cache, $model) {
  $stripped = strip_string(strtolower($model));

  // Dont bother if its less than 4 characters long. Too many false positives.
  if (strlen($stripped) < 4) {
    return null;
  }

  // Search our cache
  foreach ($cache as $key => $id) {
    // Find model number string within name
    if (strpos($key, $model) !== FALSE) {
      return $id;
    }
  }

  return null;
}

Method 3: Fragment count matching

If we cant find an exact match, we should attempt to do a best effort match rating it against success threshold such as 75%.

In this method we:

  • Split the clean test name and clean cached name by spaces
  • Intersect the arrays/dictionaries
  • Count the number of intersected values
  • Count the total number of fragments in the cached name array
  • Check the matching ratio and determine a pass/fail criteria

This method will match something like

edimax br6574n wireless 80211bgn broadband router with 4 gigabit ports switch

with something like

edimax nmax wireless 80211n gigabit broadband router br6574n

Even though the fragments are in a different order, they can still be contained within the other name. Counting up the coloured matches (edimax, br6574n, wireless, broadband, router and gigabit), we find there are 6 matches from the intersection out of the possible 8 fragments, which is exactly 75%.

function get_matching_product(&$cache, $model) {
  $stripped = strip_string(strtolower($model));
  $fragments = explode(' ', $stripped);

  // Search our cache
  foreach ($cache as $key => $id) {
    $title = explode(' ', $key);
    $matches = array_intersect($title, $fragments);

    // Count
    $m = count($matches);
    $t = count($title);

    // Match at least 75% of the original title
    if (($m > 1) && (($m / $t) * 100) >= 75) {
      return $id;
    }
  }

  return null;
}

Method 4: Levenshtein distance

This algorithm processes the number of insertions, replacements and deletions required to make one string the same as another and returns the "distance" from one string to another. The distance is an indication on how different the strings are.

Calculating the difference between two words can be a costly process, so I didn't bother with this method.

If you are interested, the PHP function is built into levenshtein(). Another function of interest is similar_text().

Success Rate?

Using the first 3 methods explained, we've matched approximately 2,000 of our products out of 4,000 in the cache against 15,000 external products.

The methods used here are fairly simple but cooked up without much regard to efficiency.

If you have more success with another method, let me know. It'd be interesting to see what other methods there are.

JS Syntax Highlighter

Good software that configurable and does exactly what you want is often hard to come by. Since I've started this blog, I've always wanted a good syntax highlighter that looks nice but was flexible enough to support a large number of languages. I've tried quite a few, but each had their own annoying little quirks.

Lucky for me, a smart chap called Alex Gorbatchev has created an awesome open source syntax highlighter in Javascript. It simply searches through for all "pre" tags with a specific classname and applies the highlighting once your page is loaded.

To use it, import the following files into your HTML file within the "head" tag.

<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>

If you do not wish to use the latest version, replace "current" with the specific version you want. Alex has been nice enough to host the files for us and make it available for public use.

The brush files extend the syntax highlighter functionality to include other languages such as C#, JS, PHP or C++. Be sure to import the files you need.

The following example imports SQL and C++ brushes for use.

<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'/>

If you want to know what other brushes are available, they are listed here.

To configure Syntax Highlighter, you can do so by using the following:

<script type='text/javascript'>
// Makes Syntax Highlighting work for blogger.com sites
SyntaxHighlighter.config.bloggerMode = true;

// Customize tab size
SyntaxHighlighter.defaults['tab-size'] = 2;
// ... more options

// This applies the highlighting
SyntaxHighlighter.all();
</script>

For more configuration options, see here.

When you wish to apply the highlighting onto a specific block of code, place the code within a "pre" tag and apply a CSS class "brush: php" (if you're displaying PHP). Find the right brush alias here.

<pre class="brush: cpp;">
HWND getDesktopHandle();

// Provides visual clues on the state of the application.
void UpdateUI() {
  HMENU menu = GetMenu(m_hWnd);
  LPHIDEDESKTOPINIINFO info = m_map.open();

  CheckMenuItem(menu, ID_MENU_ENABLED, MF_BYCOMMAND | (info->hExplorerLib ? MF_CHECKED : MF_UNCHECKED));
  CheckMenuItem(menu, ID_MENU_STARTUPWITHWINDOWS, MF_BYCOMMAND | (IsAutoStartup() ? MF_CHECKED : MF_UNCHECKED));

  m_map.close(info);
}
</pre>

Its also important to note that alot of WYSIWYG blog editors are not very "pre" tag friendly. Fortunately, this is configurable in Syntax Highlighter by changing the "tagName" option to something else like "div".

There you have it! Now you have fully functional, very pretty syntax highlighting.

[ Sources ]

Django: Quick and easy template tags

Compared to Drupal, Django makes it incredibly easy to create new template tags. All you have to do is create the template tag file, a template file to populate and start using it.

First, create the template tag file "whatever.py" in your "project/app/templatetags" folder. This contains the template tag(s) which you want to make available to your templates.

The file should contain a template tag declaration similar to the following:

from django.conf import settings
from django.template import Library

register = Library()

@register.inclusion_tag('app/list_of_stuff.html', takes_context = True)
def app_list_of_stuff(context, arg):
user = context['user']
return { 'user': user, 'arg': arg, 'plus': arg + 10 }

Now create a template which renders the data returned by the template tag. In either "project/app/templates/app" or "project/templates/app", create a file called "list_of_stuff.html".

With it, paste in the following:

<ul class="list_of_stuff">
<li>{{user.id}}</li>
<li>{{user}}</li>
<li>{{arg}}</li>
<li>{{plus}}</li>
</ul>

Now when you wish to use your new tag in a template, add "{{ load whatever }}" to load the tag then "{% app_list_of_stuff 5 %}" to use it. The "5" is just passed into the tag as the "arg" parameter.

[ Source ]

Git: Revert a single file

Use "git checkout -- filename" to revert a file. The "--" ensures that it recognises filename as a path and not a branch.

[ Source ]

Windows Media Player: Command Line Arguments

If you've wanted to start Media Player up in "Play Mode" or "Library Mode", you can modify the shortcut icon to include some arguments which affect its startup behaviour.

To start it in Library Mode (which looks better in Windows 7) or Playing Mode (better in XP), change the shortcut to the following

"C:\Program Files\Windows Media Player\wmplayer.exe" /Task MediaLibrary

Library Mode looks better in Windows 7, but Now Playing Mode looks better in XP, so to use that replace "MediaLibrary" with "NowPlaying".

There are loads of other options listed below.

"path\filename.wmv"
Description: Start and play the file.
Example: wmplayer "c:\filename.wma"

/fullscreen
Description:

Play the specified file in full-screen mode.

You must specify the name of the content to play.

Example: wmplayer "c:\filename.wmv" /fullscreen

/Device:{DVD|AudioCD}
Description: Play a DVD or audio CD.
Example: wmplayer /device:AudioCD

"path\filename?WMPSkin=skin name"
Description: Open the Player using the specified skin.
Example: wmplayer "c:\filename.wma?wmpskin=headspace"

/Service:keyname
Description: Open the Player showing the online store specified by keyname.
Example: wmplayer /Service:blah

/Task {NowPlaying|MediaGuide|CDAudio|CDWrite|
MediaLibrary|RadioTuner|PortableDevice|SkinViewer}
Description: Open the Player in the task specified.
Example: wmplayer /Task NowPlaying

/Task Services /Service servicename
Description:

Open the Player in the Premium Services feature, showing the service specified by the servicename parameter.

This value is the unique name for the service. If the specified service has not been previously viewed, the servicename parameter is ignored.

Opens the specified online store in Windows Media Player 10 or later.

Example: wmplayer /Task Services /Service ServiceName

/Task ServiceTask#
Description: Open the Player in the online store service task pane specified by #.
Example: wmplayer /Task ServiceTask2

/Playlist PlaylistName
Description: Open the Player and play the specified playlist.
Example: wmplayer /Playlist MyTracks

/Schema:{Music|Pictures|Video|TV|Other}
Description:

Open the Player, showing the specified media category.

Requires Windows Media Player 11.

Example: wmplayer /Schema:Pictures /Task:PortableDevice

 

[ Source ]

Invention: Inside Car Window Cleaner Thingymabobby

If you've ever owned a car for over a year, you'll know how annoying it is to drive during the colder rainy seasons due to the window fogging up from the inside.

This is due to some moisture crap in the car that heats up during the day and sticks to the inside of the window. The moisture can be from passengers, garbage in the car or just the cleaning agents people use to keep the interior clean.

When it comes to rubbing that crap off, oh man, you'll need elbow grease and determination. That shit is hard to get off. It takes a few hard rubs to get it off, a good cloth that wont dust it up and also a good angle to sit at.

The front window is fairly easy to clean compared to the back one, as you'd have to reach further into a weird position. Not to mention the fact that you'll NEVER be able to clean the very last bit of the window =\

Someone needs to invent a long arm cleaning thing like a broom for the inside of the car that just wipes it clean. Something like a window wiper would be awesome! One swipe and whalla, visibility is restored!

Win7: Choose between versions at setup

If you've downloaded the RTM version of Windows 7 and for some reason DONT want the Ultimate edition, there's an easy way to choose upon installation.

It does involve editing the image prior to burning, so you'll need a program like MagicISO or PowerISO to do that.

Once you open up the ISO image, you have two choices:

a) Delete iso://sources/ei.cfg (Easiest)
Save and burn the image. When the installer runs, it will ask you which version you wish to install.

Now you're done :)

b) Modify iso://sources/ei.cfg to set the default (Harder)

This will change the default installation and will not prompt you what version you wish to install.

Extract ei.cfg to a temporary location and edit it with Notepad. The default values for ei.cfg are:

[EditionID]
Ultimate
[Channel]
Retail
[VL]
0

Change the values to any of the possible values:

  • EditionID
    "Ultimate", "Professional", "HomePremium", "HomeBasic" or "Starter".
  • Channel
    "Retail" or "OEM"
  • VL (Volume License)
    "1" (true) or "0" (false)

Once thats done, update the image and burn it.

[ Source ]

Invention: Mannequins with Gel Breasts

Walking through the shopping centre on the way to work, I noticed the lingerie store had some nice tidbits on mannequins.

However, the mannequins had plastic figures, which makes it a bit unrealistic as it doesn't show how the garments offered "proper support".

So, I put forth the idea that someone needs to start producing mannequins with gel chests (or whatever material is more appropriate) so it provides a more realistic example of how the item will look the customer.

Win7: Taskbar tooltips don't go away or become sticky on hover over items, even when mouse goes away

Sometimes a strange quirk occurs with Windows 7 when the taskbar tooltip constantly appears, even when the mouse isn't on an item.

I'm still not sure what causes it, but symptoms are:

  1. Move your mouse over one of the taskbar items (even if its briefly without stopping)
  2. Move the mouse away
  3. If the tooltip shows up, you've got the same problem I have.
  4. Now if you move the mouse horizontally around the screen (whilst not on the taskbar), the tooltip will change to match the taskbar item which is vertically below the cursor.

I'll try to record it next time the bug occurs.

One solution is to simply restart the Explorer process, but of course you lose some taskbar icons which is quite annoying.

Twig - The Flexible, Fast and Secure Template Language for PHP

It really feels weird reading something like this, especially when you've had nothing to do with it!

http://www.twig-project.org

I've personally never tried it before, but hey if its any good let me know.

Drupal: Using #ahah to modify forms

Often it is useful to dynamically modify forms by adding or removing form elements with Javascript or Ajax. Drupal 6 makes it easy to do that, using the element attribute #ahah which will react to specified events.

Getting started with AHAH (Asychronous HTML and HTTP, which is really just a fancy name for Ajax) is fairly difficult at first, but once you have a reusable pattern it should be fairly easy.

The following example will add a new option into the select dropdown everytime the user clicks add.

Firstly, you need to define the AHAH attribute on the element upon form declaration.

function example_admin_something_form($form_state) {
  $form = array();
  // The dropdown which gets refreshed when new items are added.
  $form['example_dropdown'] = array(
    '#type' => 'select',
    '#title' => 'Example Dropdown',
    '#options' => array(),
    '#prefix' => "<div id='example-select-wrapper'>",
    '#suffix' => '</div>',

  );
  // The magical AHAH button. This does not cause a page reload.
  $form['add'] = array(
    '#type' => 'button',
    '#value' => 'Add',
    '#ahah' => array(
      'event' => 'click',
      'path' => "example/ahah/add_option",
      'wrapper' => "example-select-wrapper",
      'method' => 'replace',
    ),

  );

  // A textfield which allows the user to enter in new select options.
  $form['new_option'] = array(
    '#type' => 'textfield',
    '#title' => t('New Option Name'),
  );

  // Submit button to actually save the form data.
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Save',
  );

  return $form;
}

Create a menu path which links to your menu handler.

function hook_menu() {
  $path['example/ahah/add_option'] = array(
    'page callback' => 'example_ahah_add_option_js',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  return $path;
}

And now for the handler.

function example_ahah_add_option_js() {
  // Retrieve the cached form
  $form_state = array('submitted' => FALSE);
  $form_build_id = $_POST['form_build_id'];
  $form = form_get_cache($form_build_id, $form_state);
  // -----
  // You can modify the form here to append new options
  $new_option = $_POST['new_option'];
  $options = $form['example_dropdown']['#options'];
  if (!empty($new_option)) {
    // If the key isnt important to you, just use this line.
    // $form['example_dropdown']['#options'][] = $new_option;
    // I use "Array + Array" here as it maintains the keys if necessary.
    // array_merge() does not maintain the keys.
    $form['example_dropdown']['#options'] = $options + array($new_option);
  }
  // End editable code
  // -----
  // Reset the cached form. Without doing this, Drupal will think this
  // is an externally modified form attack and ignore the data.
  form_set_cache($form_build_id, $form, $form_state);
  $form += array('#post' => $_POST, '#programmed' => FALSE);
  $form = form_builder($_POST['form_id'], $form, $form_state);
  // -----
  // Now we should render only the part of the form we wish to update.
  // This will provide the output to place into the wrapper.
  drupal_json(array(
    'status'   => TRUE,
    'data'     => theme('status_messages') . drupal_render($form['example_dropdown']),
  ));
}

Now the form should append a new option, only if text is entered into the textfield. For more options for the #ahah attribute (such as events, effects or progress bars), see the documentation.

[ Sources ]

  • Drupal Documentation for #ahah
    You've probably seen this already, but a good place to start when getting an brief overview.
  • Getting going with AHAH and Drupal 6
    This has nice flowcharts and describes (with images) what the #ahah options are.
  • Drupal 6 AHAH forms: Making New Fields Work
    A bare bones code snippet which works and offers some light explanation. It is a good idea to wrap the reusable code fragments into a new function as he did. Would probably better to rename $form in easy_ahah_form_field() to $field.

    My tutorial is based upon this code fragment, which ignores step #5 (the submit handler step) in the link below.
  • Doing AHAH Correctly in Drupal 6
    Detailed description of how the process works. This is not noob friendly and will hurt your brain.

Drupal: Using #autocomplete_path on textfield elements

Sometimes it is useful to have some sort of auto-complete features when typing. Drupal provides some API for you to hook into in case you want to add it.

Firstly, when declaring your textfield in the form, add the #autocomplete_path attribute in your form declaration.

$form['example'] = array(
  '#type' => 'textfield',
  '#title' => t('Example Textfield'),
  '#autocomplete_path' => 'path/to/callback',
);

Now you need to create a menu callback which hooks the path to the callback in your hook_menu() definition.

$path['path/to/callback'] = array(
  'page callback' => 'module_auto_complete_does_something',
  'type' => MENU_CALLBACK,
);

Finally, you need to create the callback. It will need to return some JSON output, but all we need to worry about is creating an array which with meaningful keys. The values in the array are used for labels. drupal_json() will handle the rest.

function module_auto_complete_does_something($string) {
  $matches = array();
  $res = db_query("SELECT * FROM term_data WHERE name ~* '%s' ORDER BY LOWER(name)", $string);

  while ($row = db_fetch_array($res)) {
    $matches[$row['tid']] = $row['name'];
  }

  // Optional: Sort the results
  // asort($matches);

  drupal_json($matches);
}

And there you have it, a fully working auto complete for a textfield.

Additional arguments:

If you need to pass additional arguments to the callback, you can do so by modifying the menu hook.

$path['path/to/callback/%/%'] = array(
  'page callback' => 'module_auto_complete_does_something',
  'page arguments' => array(3, 4),
  'type' => MENU_CALLBACK,
);

The $string argument is automatically passed to the function by the API. If you wish to add arguments to the callback, place the $string argument as the last parameter.

function module_auto_complete_does_something($arg1, $arg2, $string) {
  ...

Drupal: Caching frequently used data

Often you will need to cache data in your projects to save valuable processing power and reduce hits on the database server.

Drupal provides caching functionality to you via the use of cache_get() and cache_set() functions.

/**
* Retrieves some sort of data.
*/
function module_get_rows($catid) {
  $key = "module_get_rows_$catid";
  $cache = cache_get($key);

  if ($cache) {
    return $cache->data;
  }

  $res = db_query("SELECT * FROM table_data WHERE catid = %d", $catid);
  $rows = array();

  while ($res && ($row = db_fetch_array($res))) {
    $rows[$row['catid'] = $row;
  }

  cache_set($key, $rows, 'cache', time() + 900);
  return $rows;
}

The example does the following:

  1. Create a cache key which is dependant on the $catid argument. This ensures that all the values are cached are depending on the category requested.
  2. Try to get an existing cache value using cache_get().
  3. If the cache is valid, return $cache->data.
  4. Otherwise, generate the cache data.
  5. Store the data using cache_set(). The cache will expire in the current time + 15 minutes, which is written as time() + 900 seconds.
  6. Return the data so the calling function can continue processing.

Logitech Driving Force Wireless: PS button on steering wheel doesn't work

The wireless steering wheel I've got for my PS3 is bloody fantastic! I love it!

But one small quirk is that the damn PS button doesn't work. Logitech is blaming the game since it may not of been designed to work with the faux PS button.

Shouldn't they all work with the PS button? Especially since the controller that comes with the PS3 has a little PS button on it. I would of expected it to at least work with Gran Turismo 5 Prologue =(

answer
Guess the question has been asked alot of times.

[ Source ]

Novell: An unexpected error occurred while attempting to unlock the workstation.

"Error: Workstation Locked"

An unexpected error occurred while attempting to unlock the workstation.

Try unlocking the workstation again, or select a different credential type for unlock.

Error -1497 (0xFFFFFA27)

If you ever got an error logging in with the Novell login box with the eDirectory option, try logging in with another option and running this registry command under "Start" > "Run".

reg ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Novell\NICI" /f /t REG_DWORD /v EnableUserProfileDirectory /d 1

[ Source ]

PHP: Easy way to strip unwanted characters off a string

$output = preg_replace('/[^\da-z A-Z]/', '', $input);

This will remove any characters other than:

  • \d (Numbers)
  • a-z (Lower case characters)
  • A-Z (Upper case characters)
  • And spaces (There is a space between "z" and "A")

Nokia Phones: Check your Firmware Software Version

Key in the following into the keypad. It'll show up as soon as you enter the last character.

*#0000#

Drupal 6: Define a numeric field type in the database schema

Often it is useful to define numeric fields in the database for information such as pricing or measurement.

In Drupal, the way to define a numeric type is to also declare the "precision" option.

$schema['products'] = array(
  'description' => t('Stores product data.'),
  'fields' => array(
    'prodid' => array('type' => 'int', 'not null' => TRUE),
    'manufacturer' => array('type' => 'text'),
    'product_name' => array('type' => 'text'),
    'description' => array('type' => 'text'),
    'price' => array('type' => 'numeric', 'precision' => 2),
  ),
  'primary key' => array(prodid'),
);

 
Copyright © Twig's Tech Tips
Theme by BloggerThemes & TopWPThemes Sponsored by iBlogtoBlog