Archive for the 'Programming' Category

Grabbing a Share of the Pie – Marketing Fiddle Salad Correctly

Aug 01 2013 Published by under Fiddle Salad,Programming

The idea of running Fiddle Salad came in a weird way. At first, I was just making a Python to JavaScript compiler and putting it on a website. It was simple enough, as the compiler was already built for it. The back-end for saving and authentication through Google, Twitter, and Facebook used the same one as Python Fiddle. After the site was launched, I noticed that not many people were interested in writing Python. Also, I got a taste of CoffeeScript, which is now my favorite language.

I think the demise of the Python-only fiddle came as a combination of low traffic and no saves. If nobody ever sees it or uses it, then it is better gone. Fortunately, I had the chance to design and develop the next generation of Fiddle Salad to support other languages.

6067OT_3_13

The real Fiddle Salad was launched in April of 2012. I remembered calling the previous version Python Fiddle. Last January, I decided to do an experiment with the CoffeeScript page by creating a separate app in the Chrome App Store. It turned out to double my number of daily visitors. Last May, it was featured on Lifehacker as one of the best apps for development. So why not do it again?

I waited until the right time. Last month and the previous one, the project received major updates which I will be discussing on the Fiddle Salad blog. Meanwhile, I published more apps in the Chrome App Store.

The difference now is that instead of an app supporting more features that show up in searches, I’ve limited the features that are marketed. This way it targets specific audiences. JavaScript programmers don’t want to find out about the features built for CoffeeScript, and a programmer looking for a CoffeeScript IDE won’t bother with an app that doesn’t have CoffeeScript in the title.

 

No responses yet

Calculating Prime Numbers in Python

Apr 24 2013 Published by under Python Fiddle

The repository of Python code snippets on Python Fiddle now has 742 posted and counting. Among them, there are several for listing prime numbers. The naive approach by factoring definitely isn’t efficient:

Another approach also contains the hidden double for loop:

Way to go with this one, packing a little program into the regular expression:

If I were to do it, I’d implement it with Eratosthenes’s algorithm.

No responses yet

Custom Pins on Bing Maps with an Image Frame

Apr 03 2013 Published by under Programming

On a recent project developing a friend tracking application for BlackBerry 10, I used Bing Maps for showing the locations of people in the contact list because Google Maps did not work on the device. The Bing Maps API has less community support and example code compared to Google Maps. This tutorial explains how to customize a pin in Bing Maps. The goal is to display an arrow pointing to a specific location with a profile picture and the name of the person above it. This is accomplished by using the API where possible with the addition of CSS and images to fill the gap.

To create a PushPin, Location and PushpinOptions objects are passed as arguments.

Bing Map PushPin

the default PushPin

When initializing the PushpinOptions object, the relevant options for positioning and displaying the text are text and textOffset.

var pin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(lat, lon), {
        text: "My Name",
        textOffset: new Microsoft.Maps.Point(-12, 10),
        typeName: 'blackText',
        width: 128
});

In order to display the text label so that the letters appear on a single line, it is necessary to make the div wider by adjusting width. Note that setting the width has shifted the pin, which will be readjusted later. The textOffset option sets the amount the text is shifted from the PushPin icon. By default, the Bing Maps uses a white text label. It can be changed by setting its CSS class using the typeName option. Here, we set the typeName to “blackText”.

.blackText div {
    color: black !important;
}

Bing default PushPin with label

Bing Maps allows the pin to be replaced with an icon, but there is no API for overlaying an image on a pin.

var pin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(lat, lon), {
        text: "My Name",
        width: 128,
        textOffset: new Microsoft.Maps.Point(-12, 10),
        typeName: 'blackText',
        icon: "images/Map_pin2.png",
        height:128
});

Bing default PushPin with icon
However, the goal is to display a dynamic profile picture with a pin below it. The solution is to use the same approach for setting the label color. I inspected the HTML elements with jQuery on $(‘.blackText’). This is a useful technique when the HTML element cannot be located with the mouse cursor in Chrome developer tools or FireBug.

<a href="#" class="blackText MapPushpinBase" style="position: absolute; cursor: inherit; overflow: hidden; pointer-events: all; left: -64px; top: -128px; width: 128px; height: 128px; line-height: 0px;">
<img src="images/Map_pin2.png">
<div style="position: absolute; text-align: center; width: 100%; font-weight: bold; font-style: normal; font-variant: normal; font-size: 10pt; line-height: normal; font-family: Arial, Helvetica, sans-serif; color: rgb(255, 255, 255); left: -12px; top: 10px;">My Name</div>
</a>

Since blackText is an anchor tag, it is possible to insert a background image for it:

a.blackText {
    background-image: url("images/Map_pin2.png");
    background-repeat: no-repeat;
}

and replace the pin image in the API call with the profile picture:

var pin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(lat, lon), {
        text: "My Name",
        width: 128,
        textOffset: new Microsoft.Maps.Point(-12, 10),
        typeName: 'blackText',
        icon: "http://placekitten.com/80/80",
        height:128
});

Bing PushPin overlay image
The next step is to reposition the image and the label. Since the CSS border width can push the content in the CSS box model, the border width should be set before adjusting margins and padding.

I added an orange frame around the profile image to make it fit with the pin.The background color shows through the padding, with the margin adjustment pushing the image to the right.

a.blackText img{
    margin-left: 8px;
    margin-top: 0px;
    padding:5px;
    background-color:#ff4500;
    -webkit-border-radius: 2px;
}
var imageHeight = 80;
var pin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(lat, lon), {
        text: "My Name",
        width: 168,
        textOffset: new Microsoft.Maps.Point(50, imageHeight/2),
        typeName: 'blackText',
        icon: "http://placekitten.com/80/80",
        height:128
});

Bing PushPin with custom image
As a bonus, why not add a pink double border? Simply override the default image border with a higher priority rule.

a.blackText img{
    margin-left: 2px;
    margin-top: 0px;
    padding:5px;
    border:3px solid #ffb6c1 !important;
    background-color:#ff4500;
    -webkit-border-radius: 2px;
}

Bing PushPin custom image double border
Finally, the pin needs to be repositioned over its original location. The anchor option sets the (x, y) offset of the pin relative to the width and height.

var pin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(lat, lon), {
        text: "My Name",
        width: 168,
        textOffset: new Microsoft.Maps.Point(50, imageHeight/2),
        typeName: 'blackText',
        icon: "http://placekitten.com/80/80",
        anchor: new Microsoft.Maps.Point(52,112),
        height:128
});

Bing PushPin anchor position

No responses yet

Course Planner Lower Case Course Names

Dec 19 2012 Published by under CourseTree

For a long time, I’ve been accustomed to hitting the Caps Lock key when entering course codes in the URL box when using the Waterloo Course Planner. It’s the quickest way to navigate to a course. However, whenever I didn’t capitalize course codes, no course is shown. This is because the database/ORM layer requires cases to match. So now I’ve implemented lower case course codes so that ‘/calendar/engl/101a’ redirects to  ‘/calendar/ENGL/101A’ .

No responses yet

Knockout or Grails with jQuery

Sep 26 2012 Published by under Programming

Knowing when to use Knockout or not is an art. Plain jQuery works fine for keeping track of unchecked users that were checked before.

var existingUsers;
function setExistingUsers () {
    existingUsers = [];
    $('#userList input[type="checkbox"]').each(function () {
        if($(this).attr('checked')) existingUsers.push($(this).val())
    });
}

$('form').submit(function(){
    var unselectedUsers = [];
    $('#userList input[type="checkbox"]:not(:checked)').each(function () {
        unselectedUsers.push($(this).val())
    });
    $('[name="_deletedUsers"]').val(JSON.stringify(_.intersect(existingUsers, unselectedUsers)));
});
$('#allUsers').click(function(){
    if ($(this).is(":checked")) {
        $('#userList input[type="checkbox"]').prop('checked', true);
    } else {
        $('#userList input[type="checkbox"]').prop('checked', false);
    }
})

jQuery is used here for the “All” checkbox to select all users and to find the deleted users when submitting the form. Another part of the page displays the selected users for ordering with a sortable interface, so that users can be assigned priorities. Whenever a user is checked, he is added to the bottom of list. Whenever he is unchecked, he is removed from the sortable interface. With two views on the same data that need to be maintained, code without a proper MVC structure gets messy as the application grows. I even had to change Underscore‘s default “<% %>” templating to avoid conflicts with GSP.

var existingUsers;
_.templateSettings = {
  interpolate : /\{\{(.+?)\}\}/g
};
var escalationUserTemplate =  _.template("<span>{{ name }}</span>");
function setExistingUsers () {
    existingUsers = [];
    $('#userList input[type="checkbox"]').each(function () {
        if($(this).attr('checked')) existingUsers.push($(this).val())
    });
    $('#sortable').html(_.map(existingUsers, function(user) {
        escalationUserTemplate({name: user})
    }).join(''));
    $('#userList input[type="checkbox"]').click(function () {
        setExistingUsers()
    });
}

$('form').submit(function(){
    var unselectedUsers = [];
    $('#userList input[type="checkbox"]:not(:checked)').each(function () {
        unselectedUsers.push($(this).val())
    });
    $('[name="_deletedUsers"]').val(JSON.stringify(_.intersect(existingUsers, unselectedUsers)));
});
$('#allUsers').click(function(){
    if ($(this).is(":checked")) {
        $('#userList input[type="checkbox"]').prop('checked', true);
    } else {
        $('#userList input[type="checkbox"]').prop('checked', false);
    }
});

Setting the HTML for the other view each time a checkbox state changes is a lot less efficient than using Knockout. It even comes with a templating system that uses the HTML DOM, which is much better than having it in a string. Knockout’s MVC structure facilitated with managing users. I wrote a model to handle user filtering, checking/unchecking all users, and for showing different sections of the view depending on a radio box group.

User = (data) ->
  @name = ko.observable(data.name)
  @selected = ko.observable(_.include(existingUsers, data.id))
  @id = data.id
  @departments = data.departments
  @

ViewModel = ->
  @filter = ko.observable('')
  @selectedDepartment = ko.observable(pagingGroup)
  @users = ko.observableArray([])
  @departments = ko.observableArray([])
  @pagingGroupType = ko.observable('broadcast')

  @filteredUsers = ko.computed( =>
    filter = @filter().toLowerCase()
    department = @selectedDepartment()
    unless filter or department
      @users()
    else
      usersByName = @users()
      if filter
        usersByName = ko.utils.arrayFilter usersByName, (item) ->
          ko.utils.stringStartsWith item.name().toLowerCase(), filter
      if department
        usersByName = ko.utils.arrayFilter usersByName, (item) ->
          _.include(item.departments, department)
      usersByName
  )

  @selectedUsers = ko.computed( =>
    department = @selectedDepartment()
    _.chain(@users())
      .filter((user) =>
        user.selected()
      )
      .filter((user) =>
        if department
          _.include(user.departments, department)
        else
          true
      )
      .value()
  )

  @selectAllFilteredUsers = =>
    _.each(@filteredUsers(), (user) ->
      user.selected(true)
    )

  @deselectAllFilteredUsers = =>
    _.each(@filteredUsers(), (user) ->
      user.selected(false)
    )

  mappedUsers = $.map(accountUsers, (item) ->
    new User(item)
  )
  @users mappedUsers
  allDepartments = _.union.apply({}, _(mappedUsers).map( (user) ->
    user.departments
  ))

  @departments allDepartments
  @

window.viewModel = new ViewModel()

ko.applyBindings(viewModel)

The views for user selection and ordering was also very straightforward. I used jQuery UI’s sortable lists for ordering users.

<div class="select-block flexcroll" data-bind="foreach: filteredUsers">
    <div class="select-box" id="userList">
        <label><input type="checkbox" data-bind="value: id, checked: selected, attr: { index: $index }" /><span data-bind="text: name"></span></label>
    </div>
</div>
...
<div id="sortable" class="connectedSortable select-block flexcroll selectors" data-bind="foreach: selectedUsers">
    <span data-bind="text: name"></span>
</div>

The best part is the old code for finding deleted users is still relevant.

$('form').submit(function(){
    var unselectedUsers = [];
    $('#userList input[type="checkbox"]:not(:checked)').each(function () {
        unselectedUsers.push(parseInt($(this).val()))
    });
    $('#userList input[type="checkbox"]').each(function(index){
        $(this).attr('name', 'members[' + index + '].user.id'); // Grails automatically saves one to many relationships
    })
    $('[name="_deletedUsers"]').val(JSON.stringify(_.intersect(existingUsers, unselectedUsers)));
});
$('#allUsers').click(function(){
    if ($(this).is(":checked")) {
        viewModel.selectAllFilteredUsers()
    } else {
        viewModel.deselectAllFilteredUsers()
    }
})

Now the AJAX call for users in a department has been replaced with front-end filtering, which also allows for searching by names using the filter observable.

No responses yet

Convert Grails 2 View to Use Knockout JS

Sep 20 2012 Published by under Programming

When the basic functionality of a web application has been developed, it’s time to add interactive features. Filtering a list of users is one task that is better done on the client side than on the server, to provide faster response. First, the Groovy variables need to be converted to JSON to be rendered in the view.

def newMessage = {
  def user = User.get(session.user.id)
  def account = CustomerAccount.get(session.account.id)
  [messageInstance: new Message(params), usersForAllDepartments: userService.getUsersForAllDepartments(user)]
}
def newMessage = {

  ...
  [messageInstance: new Message(params), usersForAllDepartments: userService.getUsersForAllDepartments(user).collect{[id: it.id, name: it.name]} as JSON]
}

Next, change the looping constructs and logic to use Knockout:

<div class="select-box"><label><span class="mark m-red">${user.name}</span></label></div>
<!-- ko foreach: recipients -->
<div class="select-box"><label><input type="checkbox" name="recipientUserList[]" data-bind="value: id, checked: selected" /></label></div>
<!-- /ko -->

Simply replace the tags with Knockout’s containerless control flow tags and bind to data values. Knockout is more terse, as the user for each iteration doesn’t need to be referenced. Render the JSON list of users on the page before the main part of the JavaScript code, which I like to keep in a separate deferred (CoffeeScript) file.

<script type="text/javascript">// <![CDATA[
usersForAllDepartments = ${usersForAllDepartments};
// ]]></script>

Finally, apply Knockout’s bindings to it with the user list loaded.

function Recipient(data) {
  this.name = ko.observable(data.name);
  this.selected = ko.observable(false);
  this.id = data.id;
}
function MessageViewModel() {
  var self = this;
  self.recipients = ko.observableArray([]);

  // Load initial state
  var mappedRecipients = $.map(usersForAllDepartments, function(item) { return new Recipient(item) });
  self.recipients(mappedRecipients);
}
ko.applyBindings(new MessageViewModel());

The rendered HTML looks exactly the same as before (except for data-bind).

<div class="select-block flexcroll">
<!-- ko foreach: recipients -->
<div class="select-box"><label><input type="checkbox" name="recipientUserList[]" value="5" data-bind="value: id, checked: selected" /><span class="mark m-red" data-bind="text: name">Bobby Tester</span></label></div>
<div class="select-box"><label><input type="checkbox" name="recipientUserList[]" value="3" data-bind="value: id, checked: selected" /><span class="mark m-red" data-bind="text: name">Manfred Moser</span></label></div>
<div class="select-box"><label><input type="checkbox" name="recipientUserList[]" value="2" data-bind="value: id, checked: selected" /><span class="mark m-red" data-bind="text: name">Sys Admin</span></label></div>
<!-- /ko -->
</div>

One response so far

Course Planner Wikipedia Links

Sep 09 2012 Published by under CourseTree

After contacting the author of the NLP parsing site, I got the Wikipedia linking service back running again for course descriptions. These links were helpful at the start for getting ahead of the official course calendar in search rankings.

As usual, I received no notice about server migrations which caused the site to go down in a few intervals while I worked on and off last summer, connecting to the cloud infrastructure. Now these mined keywords have become a reliable starting point for YouTube video searches, which can be seen on many of the pages, CS 486, for example. At any rate, one word phrases are too short as they won’t return relevant videos and are ignored. However, in some instances, as in CS 486, “planning” and “uncertainty” are keywords in the domain. One solution for this problem from my artificial intelligence class is to use a Bayesian classifier to categorize the Wikipedia page. I have applied this technique to external course links, with mixed results. Perhaps the Bayesian classifier is not trained enough or the categories are not partitioned into specific subjects. On the other hand, it works well for categories it knows, showing an MIT course titled “Techniques in Artificial Intelligence” for CS 486.

No responses yet

Planning For the Next Version of Fiddle Salad: How I Nearly Jumped to My Next Project

The work done on Fiddle Salad this month would not have been possible without last month’s planning. Furthermore, Fiddle Salad would not have been my idea if I did not invest time in building Python Fiddle. Python Fiddle was really the end product of 9 years of dreams of running a high performance computer and the result of my experience using Gentoo Linux. So I bought a computer to build Python Fiddle, which also turned out to be necessary to run the latest IDE and development tools to build Fiddle Salad.  When I started working with the Python interpreter in JavaScript,  it was horrendously slow. It took about 20 seconds to load and took up almost 1GB of memory. Any text editor except Vim without syntax highlighting was quick enough to edit the 12MB source code file.

Fiddle Salad is an evolution of both the original idea and code base that belonged to Python Fiddle. Now it is really Fiddle Salad that’s driving the development of Python Fiddle, because they share much of the code base. 

So this is the third major milestone, which I almost gave up on before I embarked on it. Before I started work on this milestone, actually a day or two before I planned, I suddenly noticed huge, discouraging signs. They came as shocking surprises. For example, I discovered a hidden option in an application I have used often before that had some of the functionality I was going to build. If that wasn’t enough, it was actually quite popular and many people probably knew that feature. As another example, I discovered another application that was more innovative in certain aspects than the application I planned to build. I got still more examples, but they aren’t worth repeating here.

As a habit, I reached for my next plan and the best tools I have available. I then realized that I would be throwing away about 8 months of work and the plans for this month, which worked out so well. Although I had no reason and no incentive at all to work on Fiddle Salad, I did so only because I enjoyed every moment of it. I believe that’s what we are all here for, the very drumbeat of the universe.

In the end, those serious signs got swallowed up by my project, as I managed to either include their ideas or integrate them right into it. Fiddle Salad is really the culmination and peak of all live web development environments, having the best features in all of them and in my imagination.

No responses yet

Firefox Could Not Get Domain for Worker

Mar 31 2012 Published by under Firefox,Python Fiddle

While wrapping up the Fiddle Salad project and doing cross browser testing, I found that Firefox wouldn’t run my project, at least on a local host.

This was one of the reasons I couldn’t get a stable release all in one shot. I initially thought it was caused by the IP address or the port number, but others report it’s just a problem with not having a domain. So one way is to add a domain mydomain.com in the Windows host file in C:\Windows\System32\drivers\etc.

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
    127.0.0.1       localhost
    127.0.0.1       myapp.com

The changes are applied immediately after saving, and I’m able to run the site locally in Firefox.

Another way is to use one of the Worker polyfills that bypasses the Firefox security checks. I suggest fakeworker, but in my case I would need to rewrite some code to be compatible with the old API to use it. Of course, this was only one of the many problems I found on the uploaded version, so I had to prioritize which problems to fix first. It’s always better to go for the efficiency gains at the start and visible results at the end. So I made a Django media sync javascript debug processor for future debug purposes on the production site.

No responses yet

Enumerables in JavaScript

Feb 18 2012 Published by under Programming,Python Fiddle

Creating clean, readable code is a primary imperative when working with large systems. Today, I have factored the knockout view model from a single object for both projects into an inheritance based hierarchy. Now in the middle of it, I’m replacing a programmingLanguage variable with a language class that also handles the language for the style sheet (LESS, SCSS) and document (Jade, ECO).

var Language = Class.$extend({
    __init__: function () {
        LANGUAGE = {
            PYTHON: 0,
            JAVASCRIPT: 1,
            LESS: 2,
            CSS: 3,
            HTML: 4
        };
        LANGUAGE_TYPE = {

            STYLE: 1,
        }
    }
})

Then I paused and thought it didn’t seem right. I remember Enums were more terse in C. So I decided to us an Enum class.

function Enum() {
    var obj = new Object();
    for (var i = 0; i < arguments.length; i++) {
        obj[arguments[i]] = i;
    }
    return obj;
}

var Language = Class.$extend({
    __init__: function () {
        LANGUAGE = Enum('PYTHON', 'JAVASCRIPT', 'LESS', 'CSS', 'HTML');
        LANGUAGE_TYPE = Enum('SCRIPT', 'STYLE', 'DOCUMENT');
    }
})

Now I like that much better. It’s like automatic numbering, except I don’t have to read it.

No responses yet

« Prev - Next »