Tuesday, January 31, 2012

Google: Adding Google Plus button to your content pages

Perhaps the best documented out of the social share buttons.

It's quite straight forward if you read the API page.

A simple example with asynchronous loading would be:

<g:plusone></g:plusone>

<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>

That's it!

If you want to configure it, the options are listed on the page under Configuration.

Detecting Plus One Click Event

This is incredibly easy compared to Facebook's API!

<g:plusone callback="googleplus_callback"></g:plusone>

Now in your Javascript function, just check if the state is "on".

function googleplus_callback(response) {
alert(response['state'] == 'on');
}

Ah, so developer friendly!

4e31e0a74eb3d

See my other posts about sharing buttons for Facebook and Twitter.

Sources

Facebook: Add "like" button to your content pages

Bloody hell this was more cryptic than it should have been. You have two options.

Easy way

First option is the deprecated (but still used on YouTube) "share" button.

You simply just create a link in a new window like:

<a rel="nofollow" href=http://www.facebook.com/sharer.php?u=encodedURL&t=encodedTitle">Facebook</a>

It's easy because you can style it whatever way you want.

Drawback is you can't display the number of shares/likes.

Hard way

OK, don't say I didn't warn you.

  • Sign up for a Facebook developers account.
  • Once you're done, click on "Create new App" (umm yeah "App", right... wtf?)
  • When you fill in the "App Domain", be sure to tick "Website" below and fill that in too. It's stupid, I know. Otherwise you'll get an error:

Error
You have specified an App Domain but have not specified a Site URL or a Mobile Web URL

thatawesomeshirt.com must be derived from your Site URL or your Mobile Web URL.

  • Now in your page HTML, add "og" and "fb" namespaces:
<html
lang="en" xml:lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:og="http://ogp.me/ns#"
xmlns:fb="http://www.facebook.com/2008/fbml">
  • In the HTML <head> tag, add in the following properties:
<meta property="og:title" content="That Awesome Shirt!" />
<meta property="og:description" content="The best shirts from a collection of online stores rolled into one site for you to browse, add to your wishlist and rate." />
<meta property="og:image" content="http://www.thatawesomeshirt.com/media/images/logo75.png"/>
<meta property="og:url" content="http://www.thatawesomeshirt.com/ "/>
<meta property="og:type" content="blog" />
<meta property="og:site_name" content="That Awesome Shirt" />
<meta property="fb:admins" content="00000xxx" />
<meta property="fb:app_id" content="00000xxx" />
  • Remember to change fb:admins and fb:app_id to your IDs. It's on the app dashboard.
  • Man, what a face full of crap. Good thing is the OpenGraph meta tags seem to be used by a bunch of other services now so the hard work won't be only for Facebook.
  • Bad news is when you realise all those tags change dynamically on each page...
  • Finally, to add the "Like" button... go to the Like Button page and generate the HTML.
  • Paste the script at the top of the <body> tag.
  • Paste the <div> where you want the share button to appear.
  • Finally, you're done.

Extra reading

If you want to detect when the user has Liked or Un-Liked your content, you can modify the script a little.

<script type="text/javascript">
function fb_callback(add_or_remove) {
alert(add_or_remove);
}

// This allows you to detect when the button is clicked.
window.fbAsyncInit = function() {
FB.Event.subscribe('edge.create', function(response) {
fb_callback(true);
});

FB.Event.subscribe('edge.remove', function(response) {
fb_callback(false);
});
};

// Normal loading of the SDK asynchronously below
(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=00000xxx";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>

2Yq2Q

Facebook, making you do things the hard way.

See my other posts about sharing buttons for Twitter and GooglePlus.

Sources

Twitter: Add share/tweet button on your content pages

Visit the Twitter Buttons page to generate your own.

To customise it a bit, you'll have to get your hands a little dirty.

Taking this for example:

<a href="https://twitter.com/share" class="twitter-share-button" data-url="http://twigstechtips.blogspot.com" data-text="I found this stupid post" data-via="myawesomeshirt" data-hashtags="shirts">Tweet</a>

<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

The first line is where your options go. A simple <a> tag which the Twitter API detects and replaces with a button.

If you don't declare a certain variable, it will simply revert to the default.

  • data-url is the URL you wish to share. By default it will share the current page URL.
  • data-text is the text which will be tweeted along with the link. By default, this is the page title.
  • data-via is who you retweeted from I suppose? I set this to the site's twitter account. Default is empty.
  • data-hashtags are the hashtags you want to append to the end of the tweet.

The second line asynchronously loads the Twitter API script. This is important because it won't halt the rest of your page from loading.

See my other posts about sharing buttons for Facebook and GooglePlus.

Sunday, January 29, 2012

CSS: Use display inline-block on Internet Explorer 6 and 7

IE6 has a pretty bad reputation for being incompatible with standards, and these days IE7 is the new IE6.

One of the biggest gripes I have about it is the inability to use display inline-block! It's the saviour of all layout rendering issues, yet shamed by IE.

Well, luckily there's a "compatibility hack" for it.

.shirt-details .tabs {
font-weight: bold;
font-size: larger;
display: inline-block;
/* IE6/7 */
*display: inline;
padding: 3px 10px;
height: 20px;
}

Whalla, problem solved.

uFCzAEven Christian Bale deliciously agrees.

Source

Tuesday, January 24, 2012

Opera: Using Firefox style keyboard shortcuts in Opera

Getting sick of Firefox and their stupid rolling releases. Even more so with the speed and memory usage. Switching between browsers hasn't really been a problem for me when it comes to vanilla installs, except for Opera.

What the heck is that Ctrl+K shortcut? Most browsers seem to focus to the search or address controls when it's pressed. Opera on the other hand goes to some weird profiles thing.

To make it more like Firefox:

  • Just open up your Opera browser and click/paste this link.
  • When a dialog shows up asking if you want to use the keyboard layout, click "Yes".

image

  • That's it! New settings already applied.

If you want to go all out and make it look and feel like Firefox, see the source link below.

Source

Wednesday, January 18, 2012

Django: Displaying form errors under a certain field during clean()

For the most part, the forms class works pretty well. Unless you're trying to specify exactly where an error should show up in the clean() function...

If you're using fieldname_clean() methods, then this isn't a problem.

However, during your clean() method you find that it makes more sense to target an error towards a certain field, you can't do it by simply raising a forms.ValidationError.

Luckily, it's still relatively simple to do.

def clean(self):
data = self.cleaned_data

# This error shows up under form.non_field_errors
try:
shirt = Shirt.objects.get(title__iexact = data['title'])
raise forms.ValidationError("A shirt with a similar name already exists.")
except Shirt.DoesNotExist:
pass

# Show an error under the "description" field
self._errors["description"] = self.error_class(forms.ValidationError("error message of your choice).messages)

return data

Now you're able to specify error messages to any field in the form.

xf2srb
<3 Django

Tuesday, January 17, 2012

Windows 7: Downloading Service Pack 1

My my, so many damn files to choose from for SP1.

image

Take a look for yourself!

Files of interest

  • 7601.17514.101119-1850_Update_Sp_Wave1-GRMSP1.1_DVD.iso

The first one contains the whole SP1 she-bang for 32bit, 64bit AMD and 64bit Intel chipsets. It assumes that you're going to be using this DVD multiple times on various machines.

  • windows6.1-KB976932-IA64.exe
  • windows6.1-KB976932-X64.exe
  • windows6.1-KB976932-X86.exe

The last 3 are the specific files for each chipset architecture. This saves you from downloading the packs you don't need.

  • Windows_Win7SP1.7601.17514.101119-1850.AMD64CHK.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.AMD64FRE.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.IA64CHK.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.IA64FRE.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.X86CHK.Symbols.msi
  • Windows_Win7SP1.7601.17514.101119-1850.X86FRE.Symbols.msi

The ones in between aren't terribly useful for the majority of us. It's for people who want to debug the installation process and stuff like that.

Source

Django: Send email with attachment

Usually send_mail() will suffice for most emailing functionality, but when you need to attach something, the helpful Django wrapper function won't allow it.

If you need to add attachments to your emails, you'll have to go deeper.

image

Alright, down to the nitty gritty.

from django.core.mail.message import EmailMessage

email = EmailMessage()
email.subject = "New shirt submitted"
email.body = html_message
email.from_email = "ThatAwesomeShirt! <no-reply@thatawesomeshirt.com>"
email.to = [ "somefakeaddress@hotmail.com", ]



email.attach_file("hellokitty.jpg") # Attach a file directly

# Or alternatively, if you want to attach the contents directly

file = open("hellokitty.jpg", "rb")
email.attach(filename = "hellokitty.jpg", mimetype = "image/jpeg", content = file.read())
file.close()

email.send()

And that is all folks.

Source

Django docs: Sending email

Disable auto playing video on SMH.com.au (and other Fairfax sites) without logging in

Fuck having to log in to disable autoplay of videos. That shit shouldn't be on unless you turn it on.

DogHumpsCatsHead
It's like being raped in the skull... but given a choice if you want to sign up or not.

This snippet removes the video altogether, but to be honest you don't miss it at all.

These instructions are for Firefox, but are probably similar for other browsers.

  • Install the AdBlockPlus Firefox addon.
  • Tools menu
  • AdBlockPlus
  • Filter Preferences

image

  • Custom Filters
  • Add filter
  • Paste in "smh.com.au,theage.com.au,brisbanetimes.com.au,nationaltimes.com.au,watoday.com.au,domain.com.au##div.cT-imageMultimedia" without quotes
  • Save and close. That's it!

image 

Source

Where Greasemonkey scripts have failed, a big thanks goes to Tim Bennett for posting this tip!

Python: Various ways to sort lists and tuples

I was amazed to how many ways there were to sort lists in Python. Better yet, you DON'T need to create a new function to sort things like you do in PHP.

Basic Sorting

Create a copy of the list

sorted([5, 2, 3, 1, 4])

[1, 2, 3, 4, 5]

Sort and modify the list

This method only works for lists.

a = [5, 2, 3, 1, 4]
a.sort()
a

[1, 2, 3, 4, 5]

Sort by Key

Pyhon 2.4 brings the "key" argument to sorted().

For example, we use the tuple:

student_tuples = [
('john', 'A', 15),
('jane', 'B', 12),
('dave', 'B', 10),
]
sorted(student_tuples, key=lambda student: student[2]) # sort by age

[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Or a class:

class Student:
def __init__(self, name, grade, age):
self.name = name
self.grade = grade
self.age = age

student_objects = [
Student('john', 'A', 15),
Student('jane', 'B', 12),
Student('dave', 'B', 10),
]
sorted(student_objects, key=lambda student: student.age) # sort by age

[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Sort by key has some helper functions called itemgetter() and attrgetter() which do what the above examples do. It also allows for multiple levels of sorting.

from operator import itemgetter, attrgetter

sorted(student_tuples, key=itemgetter(1,2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

Reverse order

Easy enough, there's a "reverse" argument in sorted() to do that.

sorted(a, reverse = True)

Source

This post was an extract of the things I found helpful from the Python wiki docs. See the link below for more information.