Tumblr
Moved to tumblr: http://urlencode.tumblr.com/
Blog of Titus Stone; Part programmer, part... wait... what?
Moved to tumblr: http://urlencode.tumblr.com/
Posted by titus at 7:08 PM 0 comments
Labels: moved
Occasionally the situation comes up in web development where you have a highly styled tag such as
<div> or <li> that you want to make clickable. This often happens when you have a list of items in which you want to make the entire item clickble instead of just the title for example. The standard fare for doing so is to set { cursor: pointer; } with CSS then to bind the .click event to the tag (in jQuery as so)....
$('#myDivTag').click(function() { // your code here });
<style type="text/css"> #myDivWrapper { display: block; } #myDiv { } </style> <a id="myDivWrapper"> <div id="myDiv"> ... content ... </div> </a>
<style type="text/css"> #myDiv { position: relative; } a.clickable-overlay { position: absolute; top: 0; left: 0; height: 100%; width: 100%; z-index: 1; display: block; background-color: transparent; } </style> <div id="myDiv"> ... content ... <a class="clickable-overlay" href="#wherever"></a> </div>
Posted by titus at 6:44 AM 2 comments
mind.location = unknown
http://www.zazzle.com/javascript_mind_tshirt-235892961444457742
I wonder what the value of the variable unknown is?
import_soul
http://www.zazzle.com/import_soul_tshirt-235715645595867505
Posted by titus at 5:27 PM 0 comments
Labels: random
Well it's past midnight and I'm musing about web templating in Python for Tornado or AppEngine. The thing about most Python templating engines that I notice is...
Posted by titus at 8:20 PM 0 comments
Labels: template, web-frameworks
I like Komodo Edit. It's simple but at the same time functional enough to be useful. It also does code completion, supports Python, and is cross-platform. (Side note: If only it supported Scala, then it would be like the **aaaaahhh** perfect editor).
I've had this idea kicking around for a while of starting a Komodo color themes/schemes website. The idea is simple. You create a theme, then share it on the site. Other people can download it or Vote/"Like" it. Most-liked themes bubble to the top. I'm thinking of a simple architecture using Google App Engine (python) + Tornado. We'll see.
In the mean time I sure did waste like 2 hours of what should have been productive programming time putting together a bunch of themes for Komodo Edit. Here are some previews of them...
Posted by titus at 7:34 PM 3 comments
Labels: komodo-edit, komodo-themes
So it's midnight and I'm programming Scala (heh). I'm actually starting to be able to write little scripts in Scala. Here's a quick one that I put together, inspired by Chapter 3 of "Programming Scala" which reads a source code file and formats the file to the screen with line numbers.
I tried to be as functional as possible. The "formatSourceLine" I felt was getting close to the concept, using recursion, immutable values, and always returning a value (avoiding the side effect of printing from within the function).
The actual output from this script is:
D:\Development\Scala>scala file.scala file.scala
1 | import scala.io.Source
2 |
3 | if (args.length > 0) {
4 |
5 | def formatSourcePrefix(line: Int, suffix: String, max: Int = 5):
6 | var prefix: String = ""
7 | for (i <- 1 to (max - line.toString.length))
8 | prefix += " "
9 | prefix + line.toString + suffix
10 | }
11 |
12 | def formatSourceLine(lines: List[String], line: Int = 1,
13 | val out = output + formatSourcePrefix(line, " | ")
14 | if (lines.length > 1)
15 | formatSourceLine(lines.tail, line + 1, out)
16 | else
17 | out
18 | }
19 |
20 | // Read file from disk
21 | val lines = Source.fromPath(args(0)).getLines().toList
22 |
23 | // Print results to screen
24 | println
25 | print(formatSourceLine(lines))
26 |
27 | }
28 | else {
29 | // Print out proper syntax
30 | Console.err.println
31 | Console.err.println("scala file.scala [filename]")
32 | }
Posted by titus at 11:58 PM 1 comments
Labels: functional-programming, scala
How can you print the string value of a floating point value of 5 in Scala?
scala> 5.toString // Wrong! res16: java.lang.String = 5 scala> 5. toString res17: java.lang.String = 5.0
scala> 4.+(1) res20: Double = 5.0 scala> 4 .+(1) res21: Int = 5
Posted by titus at 11:05 AM 1 comments
Labels: scala
Whenever I learn new programming languages, there is invariably features of the language that will surprise me. One of those in Scala (one of many actually) is abstract types. When I first read the textual description of an abstract type, I wondered what use it would ever entail. However, the authors of Programming Scala gave a very clear example of proper use.
This code snippet comes from Chapter 2 of the book.
Starting with an abstract class, we can declare an abstract type. In this case, type "In" on our class "BulkReader" is abstract. It's there, but it does not have a concrete type associated with it. Yet, our value "Source" is typed as type "In". How can this be?
abstract class BulkReader {
type In
val source: In
def read: String
}The magic comes when we declare a concrete version of "BulkReader" and can assign a concrete type to "In":class StringBulkReader(val source: String) extends BulkReader {
type In = String
def read = source
}
class FileBulkReader(val source: File) extends BulkReader {
type In = File
def read = {
val in = new BufferedInputStream(new FileInputStream(source))
val numBytes = in.available()
val bytes = new Array[Byte](numBytes)
in.read(bytes, 0, numBytes)
new String(bytes)
}
}Very cool! In our two concrete instances of "BulkReader" we assigned two different types to our abstract type "In". Note that the value typed as In, "source" is actually part of the concrete class's constructor which is, at this point for me, completely mind bending in terms of flexibility towards class design.Posted by titus at 9:07 AM 0 comments
Labels: scala
I've been quite fascinated with Haskell as a language. It's purely functional, ridiculously strict typing, and algebraic syntax were completely foreign to me before I began learning about it. I wouldn't say that I learned Haskell, but I did learn about it. I learned enough to know that it's a bit over my head at this point and that I need a better theoretical foundation before I attempt to tackle it again.
So in the mean time I wanted to take on something more transitional. I had considered F#. It seems like a great choice, especially since I already know C# and am familiar with the .NET platform. But it's a Microsoft language and I was hoping for something more portable (actually, I'm harboring a secret desire to use a functional programming language to one day code for Lego Mindstorms NXT with).
I happened to stumble upon Lift again yesterday. I had heard about it before when I was looking at other web frameworks after watching a keynote from the author of Seaside at Djangocon.
However, I realized something important about Lift and Scala which I had never caught before: Scala compiles to java bytecode. Java can be run on Google App Engine. I can use Scala/Lift to write for App Engine.
Suddenly I'm hooked. Oh, awesome, and the book "Programming Scala" is available freely online. Mmmm... looks like I have my reading for my traveling this summer.
Posted by titus at 8:40 AM 0 comments
Labels: functional-programming, haskell, scala
Getting a job doesn't seem like a fun activity to many people. I'm in the thick of it right now. The problem is when you have a skill set that you really like and that you feel confident with that no company wants. I feel like I'm in that place with Python/Django.
Sure, I've worked on the "corporaty" systems, ASP.NET, MVC, C#, etc., but what I'd really prefer to work on is python/Django on the web. It doesn't seem like there are any companies hiring for that in Denver (or maybe I need to come up with a better way to find them?). So I end up in an odd place where I wonder if it would be worth a.) going back to the corporaty things that get jobs (MSSQL, ASP, etc.) or b.) learning a newer but similar technology (RoR), and gamble that someone will hire me because I have previous experience in Django.
No one in Colorado needs Django work done?
Posted by titus at 4:05 PM 0 comments
I was waiting on the wife at Ross Dress for Less the other day, when I happened to notice something: They sell laptop bags! Since when did Ross start carrying those? Surprisingly they had a selection of name brands at, you guessed it, discount prices.
I ended up buying a Targus Messenger Fusion in dark gray/green for the Toshiba 13.3" I got a few months ago. It was marked down to $18.99 (compared to $26.50 online). It's a pretty nice looking laptop bag with built-in padding and tons of pockets/storage. It has an interesting feature in that it comes with multiple straps so you can keep the green one out for a young/hip look, or put the dark one one for a more serious professional look.
Posted by titus at 12:57 PM 1 comments
Labels: laptop
One of the neat features of Django's ORM is Model inheritance (table-level). It allows several neat data design patterns to occur. Here's an example. Let's say we're developing a website for a game company. The company sells two types of products: board games and video games. All of the products will share some data in common, name and product_id for example, but we also need to store specific details about each. Using model inheritance we can do something as follows.
class Product(models.Model):In a real use-case scenario you'd most likely have more than 1 field per, but for this example I wanted to keep things simple.
name = models.CharField(max_length=75)
product_id = models.SmallIntegerField()
price = models.DecimalField()
class BoardGame(Product):
num_of_players = models.SmallIntegerField()
game_type = models.CharField(max_length=50)
class VideoGame(Product):
PLATFORM_CHOICES = (
('wii', 'Wii),
('xb3', 'Xbox 360'),
('ps3', 'Playstation 3'),
)
platform = models.CharField(max_length=3, choices=PLATFORM_CHOICES)
b = BoardGame.objects.all()[1]Another thing that's cool is child instances have a parent instance record. Using the "Djangopoloy" game from above, which is technically type BoardGame, one could still query Product and retrieve it.
print b.name
>>> 'Djangopoly'
p = Product.objects.get(name='Djangopoly')This is really useful, but sometimes you need to go the opposite direction, and this is where Django's implementation stops. The link can't go from a Product model instance to a BoardGame. It can't retrieve state as if it was of type BoardGame.
print p.platformBecause the need for this seems to be arising more often than not lately for me, I put together a re-usbale bit of code to overcome this limitation. I'll post the code below (a GitHub gist), but using it is actually quite simple.
>>> CAN'T DO THAT!
from inheritance.models import ChildAwareModelThen, an inner class "Inheritance" is supplied to describe children of the model.
class Product(ChildAwareModel):
...
pass
class Product(ChildAwareModel):Only children that need to be reversed to should be set. Once that is configured, a method "get_child_model()" will become available, and can be used like so:
...
class Inheritance:
children = (
'myapp.models.BoardGame',
'myapp.mdoels.VideoGame',
)
p = Product.objects.get(name='Djangopoly')I'm finding this particularly useful when I've created an aggregate type page -- that is a page that shows a summary of all the generic types (Product) -- but need to on user-click show them some type of product-specific detail.
b = p.get_child_model()
print b.num_of_players
>>> 4
Posted by titus at 3:15 PM 3 comments
Labels: django, django-models, inheritance
Soooooo... I think I'm going to put in a proposal at work. All commit messages for our Mercurial DVCS need to be in 16-year-old girl language....
I can't be the only programmer who finds reading a chore? And what about those 5-billion page programming tomes? Am I the only one who never finishes those?
Posted by titus at 11:55 PM 0 comments
Labels: haskell, ipod, javascript, kindle, RWH
Is it just me, or is it hard to find a good jQuery-based date picker? Or maybe I'm just picky.
The widget needs to support selecting a date range (there goes most of them). And it needs to be able to support configuring a starting and ending time. And it has to support Themeroller (there goes whatever few remained).
So as it seems is starting to become a norm for me, I'm working on a custom jQuery widget. It's been provisionally named "LoneRangeSelector". It's for a custom web-app-calendar sort of thing.
Provisionally, here's my progress thus far...
The main goal is to make an interface that's quick and easy to setup the date-related parameters of an event, without having to enter 4 different fields (start date, start time, end date, end time).
The secondary goal is that as a byproduct of having a single widget, there is quite a bit less error checking that needs to be done (ie. it's impossible to type in an ending date that occurs before the starting date).
I actually re-created the calendar code instead of trying to modify jQuery UI's datepicker, though it does implement identical css classes so the Themeroller appearance is the same.
The lower portion has been one of the more challenging. I think the time slider needs to have some type of time indication on it, because just at first glance there's no way you konw that it spans midnight to midnight.
Concept:
Posted by titus at 4:16 PM 0 comments
Labels: jquery, jquery-ui, lonerangeselector, widget
I wanted to transition the Django site I work with primarily to use Google's jQuery CDN. However, when developing locally, it's often faster to just use a local copy. What I wanted was a way to toggle which copy of jQuery was being used based on the environment.
Environment Detection
Before we can toggle the jQuery location, we need to have a way to detect which environment we're running in.I previously blogged about how I have my settings.py configured. There are different ways to do this. One is to use local_settings.py, the other is to have conditional code in your main settings.py which determines values. Either way works.
As for my setting, on the webserver is a folder structure that resembles...
\webrootMy webserver pulls double duty, hosting both a production version ("prod") and a staging/testing version ("devel"). In my settings.py file I'm using this to determine which environment Django is running in...
\django_devel
\django_prod
import os
DJANGO_ROOT = os.path.abspath(os.path.dirname(__file__))
#
# Globals for determining settings
#
STAGING = PRODUCTION = DEVELOPMENT = False
if 'django_devel' in DJANGO_ROOT:
STAGING = True
elif 'django_prod' in DJANGO_ROOT:
PRODUCTION = True
else:
DEVELOPMENT = True
import settings
from django import template
from django.conf import settings
register = template.Library()
# -----------------------------------------------------------------------------
# jQuery
# -----------------------------------------------------------------------------
@register.tag
def jquery(parser, token):
return JQueryNode()
class JQueryNode(template.Node):
def render(self, context):
jquery = 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js'
jquery_ui = 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js'
if getattr(settings, 'DEVELOPMENT', True):
media_url = getattr(settings, 'MEDIA_URL', '/media/')
jquery = '%sjs/jquery-1.3.2.min.js' % media_url
jquery_ui = '%sjs/jquery-ui-1.7.2.custom.min.js' % media_url
return '<script type="text/javascript" src="%s"></script><script type="text/javascript" src="%s"></script>' % (jquery, jquery_ui)
{% load jquery %}{% jquery %}
Posted by titus at 9:31 AM 1 comments
Labels: django, jquery, settings.py
It seems this question has been coming up a lot on Stack Overflow, and I wrote a pretty lengthy response which I'll include here. The original question is #1883266.
Q: I'm building a web application that needs to have content on the page updated in real time without a page refresh (like a chat or messaging application). How do I do this with Django? In other words, how do I use AJAX with Django?
A: There's a lot going on in order to make this process work...
This can be confusing when you're first starting because it's not always clear what the client does and what the server does, but if the large problem is broken down I think you'll find it's a simple process.
If the client is going to regularly poll the server for new chat entries, then the server (django) needs to have some type of API to do so. Your biggest decision will be what data type the server returns. You can choose from: rendered HTML, XML, YAML, or JSON. The lightest weight is JSON, and it's supported by most of the major javascript frameworks (and django includes a JSON serializer since it's that awesome).
# (models.py)
# Your model I'm assuming is something to the effect of...
class ChatLine(models.Model):
screenname = model.CharField(max_length=40)
value = models.CharField(max_length=100)
created = models.DateTimeField(default=datetime.now())
# (urls.py)
# A url pattern to match our API...
url(r'^api/latest-chat/(?P<seconds_old>\d+)/$',get_latest_chat),
# (views.py)
# A view to answer that URL
def get_latest_chat(request, seconds_old):
# Query comments since the past X seconds
chat_since = datetime.datetime.now() - datetime.timedelta(seconds=seconds_old)
chat = Chat.objects.filter(created__gte=comments_since)
# Return serialized data or whatever you're doing with it
return HttpResponse(simplejson.dumps(chat),mimetype='application/json')
[
{
'value':'Hello World',
'created':'2009-12-10 14:56:11',
'screenname':'tstone'
},
{
'value':'And more cool Django-ness',
'created':'2009-12-10 14:58:49',
'screenname':'leethax0r1337'
},
]
<div> tag which we'll call <div id="chatbox"> which will hold whatever the incoming chat messages are. Our javascript simple needs to poll the server API that we created, check if there is a response, and then if there are items, append them to the chat box.<!-- I'm assuming you're using jQuery -->
<script type="text/javascript">
LATEST_CHAT_URL = '{% url get_latest_chat 5 %}';
// On page start...
$(function() {
// Start a timer that will call our API at regular intervals
// The 2nd value is the time in milliseconds, so 5000 = 5 seconds
setTimeout(updateChat, 5000)
});
function updateChat() {
$.getJSON(LATEST_CHAT_URL, function(data){
// Enumerate JSON objects
$.each(data.items, function(i,item){
var newChatLine = $('<span class="chat"></span>');
newChatLine.append('<span class="user">' + item.screenname + '</span>');
newChatLine.append('<span class="text">' + item.text + '</span>');
$('#chatbox').append(newChatLine);
});
});
}
</script>
<div id="chatbox">
</div>
Posted by titus at 9:20 AM 0 comments
Labels: ajax, django, javascript
One of the annoying things about using multiple platforms is when one platform has a useful utility (no matter how small) and the other platform doesn't. Have you ever needed to regularly check an Apache log file on your Windows development machine? The shell user inside me says "just tail it"... but this is Windows.
However, I just found a really amazing tool called BareTail.
BareTail "connects" to a log file, and shows you an automatically updated (live) tail of that file. It basically allows this situation to happen:
I have a window up on my developer machine (in the 2nd monitor) which is the tail of the Apache error log. Every time something is written to that log, BareTail pushes it into the window on my screen. I see log entries in real time.
Let me tell you, it makes debugging Apache error log issues much more efficient.
Posted by titus at 11:02 AM 0 comments
I happened upon an administrative assistant today who was renaming files using Windows Explorer. She had a folder with about 50 or so sub-folders, many of which contained sub-folders of their own. Every file needed to be renamed with the company name prefixing it. So for example, the file "january-charts.pdf" needed to be renamed to "Company - january-charts.pdf".
"You know", I said, "I could help that go a little faster if you're interested." I happened to know that these files needed to be sent as of yesterday, so I figured she wouldn't mind me helping to trim an hour or two off them getting out. That must mean it's time for Python Neenjah! (In case you missed it, that was a somewhat veiled reference to xkcd 'Regular Expressions')
A month or two ago I had put together a re-usable python module to allow easy recursively searching a directory. I know, I know, python already includes similar functionality. But it was weird to me, and I wanted a simpler and more flexible format. The module I built, inspire by some ideas I found around the internet, allows a callback to be specified whenever a file is found. It means you can do virtually anything from that directory search, and never really be concerned about how it does it.
from dirsearch import DirSearch
def search_callback(file):
print file
dir = DirSearch('C:\Path\Whatever', show_output=True)
dir.search(search_callback)
Posted by titus at 8:42 AM 0 comments
Being primarily a Django developer, it was only a matter of time until MarkEdit came with Django integration.
I added to the GitHub repo today a simple app which provides a widget that renders MarkEdit through Django. It's probably a bit more difficult to use than the jQuery plugin because it makes some assumptions about your Django configuration and usage (as do many Django apps). In any case, an initiated Django developer should be able to figure it out just fine.
In addition to the source update, the wiki has also been updated with documentation for the Django integration.
An of course, here's a screenshot of MarkEdit in the admin (running under Grappelli):
Posted by titus at 9:10 AM 0 comments
© Blogger template 'Minimalist G' by Ourblogtemplates.com 2008
Back to TOP