Politically Correct WordPress plugin

Please note that plugin was meant to be fun. Don’t expect to see lots of support for it.

Politically Correct swaps the occasional “politically incorrect” term with a more socially acceptable replacement. For instance, if your author types post-traumatic stress disorder (PTSD), your viewers see post-traumatic stress disorder. If your author types mentally challenged, your viewers see mentally challenged.

Example:

What output shows up if I say “homosexual people”? What about “African-American men”? And “caucasian men”? Does it know the difference between “African-American men” and “black licorice”? Can I say that “Asian people are good at math”?

What about expletives? What happens when I say “have sexual relations you”? “Eat defacate”? “Kiss my rear end”? Does this thing know the difference between “a sexual favor” and “several sexual favors”?

Is this going to give me “post-traumatic stress disorder (PTSD)”? What will the “vision-imparied”, the “hearing-impaired”, and “the disabled” think about this? What about “elderly people”?

If you have a serious web site, perhaps with a rogue author or two, you can use this plugin to help slow down some of the offense. Or, perhaps more likely, you have a personal web site and you think you could have some fun by replacing words with their PC counterparts.

Features:

  • Force filtering on individual posts by use of a custom tag
  • Admin can apply the filter to all users or only to specific users
  • Admin can apply the filter to all categories or only to specific categories

Planned features

  • Allow admins to define custom terms

You can download it here: politically-correct-v0.2.zip

Please note:
Creating this plugin was meant to be a joke, since I find the entire concept of “political correctness” to be not only mentally challenged and wasteful, but I also think it runs completely in opposition to the very nature of “the internet”. It started as a joke, and it continues mostly out of my own desire to learn more about WordPress and its APIs. I won’t be putting a tremendous amount of energy into this plugin, but I provide it both for the enjoyment of those with a sense of humor, and also on the off chance that someone might actually get some legitimate use out of it… such as a multi-user blog with one particularly “brash” author.

But to the losers who are writing in to say it’s a “stupid idea”, I simply say stop taking yourselves so seriously. Instead of whining about what you think is a stupid idea, why don’t you write to me and tell me what you think would be a better idea? Put up or shut up.

Tags: ,

Comments

Freedom of Information!

Freedom of Information, my second WordPress plugin, is just for fun. It filters the content of your post and “redacts” terminology that certain nefarious conspirators wouldn’t want getting out.

Example:

This is a government test of a new top secret plugin for ufo homeland security. I wonder what will happen to George Bush and Karl Rove when I type their names. Do you think John F. Kennedy was involved with the Secret Service’s plot to give H1N1 Swine Flu and Mad Cow Disease to the citizens? I wonder who knows about President Obama’s secret plan to bring socialism to the United States?

Current version is 0.1, and you can download it here: freedom-of-information

Tags: ,

Comments

Add Linked Images To Gallery

screenshot-1Add Linked Images To Gallery
Makes local copies of all the linked images in a post, adding them as gallery attachments on the post itself.

I have a photoblog, for my iPhone. I take a lot of pictures, and I want them to post quickly and easily. And I’m lazy. I want to send the photo to Flickr, and let Flickr update my blog. But I also want my main pages to reflect the latest additions. And what’s more, I want customized images on the front page, and I need to use the gallery to get those.

This WordPress plugin creates local copies of all external linked images in the SRC attribute of IMG tags. It extracts a list of IMG tags in the post, saves copies of those images locally as gallery attachments on the post, and then offers the option to replace the external link with a link to the local copy.

Features

  • Finds all external images linked in the SRC attribute of IMG tags and makes local copies of those images
  • Allows the SRC to be updated to point to those local copies
  • Can be applied to posts in all categories, or only those selected
  • Can be applied to all authors, or only selected authors
  • Administrator has the option to replace the external src with the url of the local copy. Another option allows the plugin to be applied to all external images, or only to those on Flickr.

This plugin is particularly useful for photobloggers, especially those who update using the mail2blog Flickr API. The plugin will saved the linked image file from Flickr locally.

Planned features

  • Add internationalization support
  • Integrate with Flickr API in order to allow always downloading the original image size regardless of which is linked
  • Additional options to allow running the plugin only for specific users or categories

Download

Download the current stable version: Add-Linked-Images-To-Gallery.

Changelog

  • 0.6

    • Suppresses safe_mode warnings from CURL
    • Adds compatibility with WordPress 2.9
  • 0.5
    • Fixes a bug that cause all img tags to be rewritten as the last matched image
  • 0.4
    • Option added to option panel allowing the plugin to run only on posts in specific categories
    • Option added to option panel allowing the plugin to run only on posts by specific authors
  • 0.3
    • Improved pattern matching for images
    • 404 errors not processed
    • Flickr “image-not-found” jpg not processed
    • Improved local file naming
    • Replace feature was replacing URL in entire text. Now only replaces in IMG src.
    • Added feedback when options are saved.
  • 0.2
    • Added options panel
    • User can apply plugin to all external images or choose only to apply to Flickr
    • User can choose to either mark images by custom tag, or to replace image source
    • Custom tag name is user-definable
    • Improved regular expression matching
  • 0.1
    • Initial version

Tags: ,

Comments

The Apple tablet computer

MacBook Touch Mockup

MacBook Touch Mockup

The rumor mill has been flying for a while, and I think enough has been confirmed for us to say confidently that Apple is definitely going to release a tablet computer in the beginning of 2010. At this point, I believe we can safely say that computer will have a 10-inch electrostatic touch sensitive screen (like the iPhone), and it will most likely have a HSPDA connection to AT&T.

The part that’s unclear, though, is… well… everything else about it.

But here’s my theory:

The MacBook Air was an incredibly cool new addition to Apple’s laptop lineup, but it was really mostly a sales dud by most measures… and I think the only reason for that was that the price was too high. But I believe the Air was merely an interim product — a way to begin recovering some of the costs associated with designing a completely disconnected, paper-thin computer.

Think about it: if you take a paper-thin tablet computer, lose the touch-screen, and add a keyboard… what are you left with, if not a MacBook air?

So what, then, do I expect to see? I think the iTablet (or whatever they choose to call it) will be exactly that: a MacBook Air, sans keyboard. I believe it will fit into a manilla envelope the way the Air does… and I believe that alone will be enough to distinguish it from all the other tablet computer offerings we’ve seen so far. A 10-inch tablet that fits in an envelope is exactly what every traveler on earth wants.

But that’s not enough. OS X has had some excellent handwriting recognition software for quite a while, but it will be better if I don’t need a tablet to enter it. Such features make this an easy Kindle killer. And in fact, if you include a stylus and allow me to write directly on the screen, you might as well go that extra step allow me to use my new iTablet as the world’s best ever replacement for a Wacom tablet.

And if the rumors I’ve heard about it pairing magically with the iMac as a second screen are true, well, how could you not think it’s worth that $799-999 rumored price?

Tags: , ,

Comments

CSS Blinker

The secret to user-friendly forms in web apps is to draw attention to errors before submitting the form, and to do so without accosting the user with irritating Javscript popups.

After filling in half a dozen (or more) form fields and then pressing the submit button, the user has mentally moved on. Suddenly hearing a “clunk” sound and getting a popup that says “invalid ssn” is jarring to say they least… but it also means the user must now read through all the form labels looking for something that sounds like “invalid ssn”.

My solution is to flash the form field drawing the user’s attention to exactly what information needs to be fixed. And for that, I have created Blinker.js.

Just include Blinker.js into your page. Then, during validation, when a field is not valid, just call Blinker:

1
Blinker.blink('element-id', 'error-classname');

Blinker uses the supplied CSS classname to do the blinking, so you can use any effect you want: change the text color, change the background, underline, add a border, whatever floats your boat. Just declare the desired style in your CSS and then use that class name in your call, along with the DOM ID of the element to flash.

The scrollTo option allows Blinker to scroll a field into the viewport if it’s not visible. The onDelay and offDelay allow you to customize the rate of blinking, and cycle determines the number of times to flash.

Tags: ,

Comments

Recursive script inclusion with REQUIRE (C#)

This is the C# version of the script I posted earlier. It’s also available as a VB.net version.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Collections;
using System.IO;
using System.Web;
 
public partial class javascript : System.Web.UI.Page
{
	private Stack files;
 
	protected void Page_Load(object sender, EventArgs e)
    {
		files = new Stack();
		Response.ContentType = "application/x-javascript";
		Response.Write(GetFile("js/Contacts.js"));
	}
 
	private string GetFile(string path)
	{
		string result = "";
		string filespec = HttpContext.Current.Request.PhysicalApplicationPath +
						 path.Replace("/", "\\");
 
		filespec = Path.GetFullPath(filespec);
 
		//if the file is already loaded, then exit
		if(files.Contains(filespec))
			return "";
 
		//add this file to the loaded list
		files.Push(filespec);
 
		//load the file
		string s = "";
		bool b = false;
		try {
			StreamReader sr = File.OpenText(filespec);
			do {
				b = true;
				s = sr.ReadLine() + "\n";
				if(s.IndexOf("//LIBRARY:") == 0)
					b = false;
 
				if(s.IndexOf("//REQUIRES:") == 0) {
					b = false;
					s = s.Replace("//REQUIRES:", "").Trim();
					result = result + GetFile(".." + s);
					s = "";
				}
				result = result + s;
			} while (sr.Peek() != -1 && !b);
			result = result + sr.ReadToEnd() + "\n";
			sr.Close();
		} catch {
			result = "\n/* Error loading file: " + filespec + " */\n"
		}
		return result;
    }
}

Tags: , ,

Comments

Recursive script inclusion with REQUIRE

One thing that tends to seriously limit the “best practices” when it comes to enterprise development and code reuse for Javascript is a lack of INCLUDE or REQUIRE functionality.

Code reuse and portability requires various functionality to be compartmentalized into individual .js files containing only related functionality, but on the web, including several files means making lots of unnecessary roundtrips, which can add up to a huge performance cost in the load time of your pages.

Good compartmentalized code also necessitates some sort of REQUIRE mechanism, which allows one unit of code (ie, script file) to specify when it won’t run properly without another unit of code.

Thus, while working on a VB.Net project, I created this simple Javascript loader, which looks at the name of the directory in which an app resides, and then looks for a javascript file by that name and loads it. Directives can be placed in that Javascript file (and in any subsequent file) requiring the inclusion of additional script files.

Not only does this allow for easier inclusion of libraries as needed, but it also makes it easier to strip out unused code if/when it is no longer needed by an app.

This source code is also available in a C# version.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Imports System.IO
 
Partial Class javascript
	Inherits System.Web.UI.Page
 
	Private files As Stack
 
	Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
		files = New Stack()
		Response.ContentType = "application/x-javascript"
		Response.Write(GetFile("js/Contacts.js"))
	End Sub
 
	Private Function GetFile(ByVal path As String) As String
		Dim result As String = ""
		Dim filespec As String = HttpContext.Current.Request.PhysicalApplicationPath & path.Replace("/", "\")
 
		filespec = IO.Path.GetFullPath(filespec)
 
		'if the file is already loaded, then exit
		If files.Contains(filespec) Then Return ""
 
		'add this file to the loaded list
		files.Push(filespec)
 
		'load the file
		Dim s As String = ""
		Dim b As Boolean = False
		Try
			Dim sr As StreamReader = File.OpenText(filespec)
			Do
				b = True
				s = sr.ReadLine() & vbCrLf
				If s.IndexOf("//LIBRARY:") = 0 Then
					b = False
				End If
				If s.IndexOf("//REQUIRES:") = 0 Then
					b = False
					s = s.Replace("//REQUIRES:", "").Trim()
					result = result & GetFile(".." & s)
					s = ""
				End If
				result = result & s
			Loop While sr.Peek() <> -1 And Not b
			result = result & sr.ReadToEnd() & vbCrLf
			sr.Close()
		Catch ex As Exception
			result = vbCrLf & "/* Error loading file: " & filespec & " */" & vbCrLf
		End Try
 
		Return result
	End Function
 
End Class

This could be easily updated to work for CSS files as well.

Tags: ,

Comments

Javascript XML extensions

While several features of Microsoft’s DOMDocument object are not supported by standards, it’s hard to deny that many of them are quite useful, and probably should be standardized.

When writing AJAX web apps, you need easy access to XML nodes. And more than anything, you need it to be cross-browser capable. To that end, I often include the following script in my AJAX apps.

/**
 * XML functions
 */
if (window.ActiveXObject) {
	/* Functions for IE */
	domLoadXml=function(xml){
		var doc=new ActiveXObject('MSXML2.DOMDocument');
		doc.async=false;
		doc.loadXML(xml);
		return doc;
	}
}else{
	/* Functions for non-IE browsers */
	domLoadXml=function(xml){
		var parser=new DOMParser();
		return parser.parseFromString(xml,'text/xml');
	}
	//fill in the missing convenience methods for Firefox
	Element.prototype.selectSingleNode=function(xpath){
		var xpe=new XPathEvaluator();
		var n=xpe.evaluate(xpath,this,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
		if(n!=null) return n.singleNodeValue;
		else return null;
	}
	Element.prototype.selectNodes=function(xpath){
		var xpe=new XPathEvaluator();
		var xpr=xpe.evaluate(xpath,this,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);
		var nodes=new Array();
		if(xpr!=null){
			var el=xpr.iterateNext();
			while(el){
				nodes.push(el);
				el=xpr.iterateNext();
			}
		}
		return nodes;
	}
	if(typeof HTMLElement.prototype.__defineGetter__ != 'undefined'){
		Element.prototype.__defineGetter__('xml', function() {return XMLSerializer().serializeToString(this);} );
		Element.prototype.__defineGetter__('text', function() {return this.textContent;} );
		Element.prototype.__defineSetter__('text', function(s) {this.textContent=s;} );
		//Element.prototype.__defineSetter__('xml', function(s) {} );
	}
}

Tags: ,

Comments

Javascript String functions

For any serious enterprise web apps, there are a handful of default Javascript functions I like to include in order to make my life easier in the long run.

Today, I present some handy extensions to the String object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
String.prototype.trim = function () {
	return this.replace(/(^\s+)|(\s+$)/, '');
}
String.prototype.addTrailingSlash = function () {
	return ('/' != this.charAt(this.length - 1)) ? this.toString() + '/' : this.toString();
}
String.prototype.left = function (n) {
	if (n <= 0) return "";
	else if (n > String(this).length) return this;
	else return String(this).substring(0,n);
}
String.prototype.right = function (n){
    if (n <= 0) return "";
    else if (n > String(this).length) return str;
    else {
       var iLen = String(this).length;
       return String(this).substring(iLen, iLen - n);
    }
}

The .trim() method is generally quite useful everywhere where text input is accepted.

The .addTrailingSlash() method is a nice way to help guarantee that you get valid paths and URLs when variables are involved.

The other two methods — .left() and .right() — are merely a conveniece at times, and I actually don’t find myself using them much as I prefer proper use of the .substring() method.

Tags:

Comments

WordPress rocks

I am writing this from my iPhone. This proves that wordpress rocks and that the iPhone is awesome. :)

Tags: ,

Comments