Hello my name is Chris, I'm a software engineer based in Madison, WI USA.

I love all things JavaScript, and also many server-side solutions.

My work

As a software engineer for Flexion, Inc., I develop enterprise level JavaScript web applications. I have implemented solutions most recently with Backbone.js but also with the Dojo Toolkit and even home grown frameworks.

I was a contributor to the Dojo Foundation project dGrid, and wrote documentation and tutorials for the toolkit. I also contributed to a toolkit called Mulberry which is used to develop mobile apps with JavaScript.

During my tenure as a Academic Technologist at UW-Madison I developed several games and simulations, as well as integrated the djatoka image server into the Forward library portal. Before that, I supported and developed a health insurance application, and even before that I worked for a startup in the time and attendance industry. To view my full work history, click "Work Timeline" up above.

Chris Barrett

Portfolio

CRM screenshot
Commodities Risk Management

Commodities Risk Management was a grant funded project to develop a simulation of the commodities market. The UI in this app is almost 100% javascript courtesy of the Dojo toolkit.

birdie publishing screenshot
Birdie Publishing

www.birdiepublishing.com
Birdie Publishing is a small publishing firm in the craft/resale niche market. The site is mostly written using the Dojo Toolkit, including a small online catalog and a smart form to get listed in their guides. The catalog is completely dynamic, using data in the database.


Malaria screenshot
Malaria - The Game

Malaria The game was a functioning prototype that will be used to teach nursing students about the effects and deterrents to catching Malaria.

VC screenshot
VirtualCase - Moodle Module

Private
The VirtualCase Moodle module was built for the University of Wisconsin School of Pharmacy. VirtualCase is a clinical environment simulation, it uses a dynamic branching tree to allow the student to traverse a decision making process. This module was written in PHP with some front end YUI JavaScript.

Code Samples

Apparently prettifier doesn't like IE7, sorry!
//function settradeaction is part of the DataController, every function in //DataController is either called via XHRPost or XHRGet, it is the //primary mechanism with which the front end javascript talks to the backend php public function settradeAction() { $this->_helper->layout()->disableLayout(); $this->_helper->viewRenderer->setNoRender(); if($this->getRequest()->isXmlHttpRequest()) { $sessionId = $this->_namespace->sId; $profileId = $this->_namespace->profileId; $tradingDate = $this->_namespace->date; $currentDate = time(); $realDate = $this->_namespace->vdList[$tradingDate]; $formData = $this->getRequest()->getPost(); $json = stripslashes($formData['data']); $dojoData = new Zend_Dojo_data(); $dojoData->fromJson($json); $trade = new Model_Trade(); foreach ($dojoData as $item) { //echo $item['title'] . ': ' . $item['description'] . "\n"; $long = $item['longForm']; $short = (0-$item['shortForm']); $margin = $item['marginReq']; $monthId = $item['month']; $price = $item['price']; $commodityId = $item['commodityId']; $quantity = $long + $short; if((abs($margin) >0 || $monthId == 13) && abs($price) >0 && $quantity != 0) { //then a trade needs to be processed $trade->saveTrade((int)$sessionId, (int)$commodityId, (int)$monthId, (int)$realdate, (int)$tradingDate, (int)$quantity, $price,$margin, $profileId); } } $rules = Model_ProfileRulesFactory::Create($profileId, $sessionId, $tradingDate,$realDate); $rules->lastCall(); ... return "sucess"; } } ///////////////////////////////////// //end of controller example////////// ///////////////////////////////////// //saveTrade is part of the trade model public function saveTrade($sessionId,$commodityId,$monthId,$realDate, $tradingDate,$quantity,$price,$margin,$profileId) { //function saveTrade saves an user input trade //(buy or sell, long or short - or cash trade) and updates all related records // saves to assets, marginaccount, moneymarketaccount, orders, transactions // saves to financialtransfer and transactionlog //need to check if player has enough money to do this trade $rules = Model_ProfileRulesFactory::Create($profileId, $sessionId, $tradingDate,$realDate); $yay = $rules->saveTrade($commodityId,$monthId,$quantity); if($yay) { $log = new Model_TransactionLog(); if($quantity > 0) { $log->saveLog($commodityId, $monthId, $price, self::B, $quantity, $tradingDate, $sessionId); } else { $log->saveLog($commodityId, $monthId, $price, self::S, $quantity, $tradingDate, $sessionId); } $transaction = new Model_Transactions(); $transfer = new Model_FinancialTransfer(); //so we need to retrieve the list of current assets, and then //determine which to buy and sell based off of transaction date //update priceOut, quantity, and margin $commodity = new Model_Commodities(); $commodity->find($commodityId); $brokerFee = $commodity->getBrokerFee(); //inventory gets handled in the profilerules /***Save Assets data **/ $contractSize = $commodity->getContractSize(); $marginReq = $commodity->getMargin(); $assets = $transaction->getPositionsByCommodity($sessionId, $commodityId,$monthId); $totalReturn = 0; //need to iterate through current assets of same commodity, month to alter position foreach($assets as $transaction) {//asset is a model_transaction object $oldQuantity = $transaction->getQuantity(); if(($oldQuantity < 0 && $quantity < 0) || ($oldQuantity > 0 && $quantity > 0)) { //just add a new record, not an offset $newTrans = new Model_Transactions(); $newTrans->setMonthId($monthId); $newTrans->setCommodityId($commodityId); $newTrans->setPriceIn($price); $newTrans->setQuantity($quantity); $newTrans->setTransactionDate($tradingDate); $newTrans->setSessionId($sessionId); $newTrans->setMargin($margin); $newTrans->save(); $fee = $quantity * ($brokerFee/2) * -1; //divided in half because the other half will be taken out when the position is offset $transfer->saveMoneyMarket($fee, $sessionId, self::BROKER_FEE, $tradingDate); $transfer->saveMoneyMarket((0-$margin), $sessionId, self::MARGIN_REQ, $tradingDate); //increasing the margin requirements $transfer->saveMarginAccount($margin, $sessionId, self::FROM_MM, $tradingDate); $quantity = 0; $totalReturn = 0; break; } ... } }
//This is a chunk of code that is called on each row of the pending grid. //I needed a more powerful way of manipulating the data shown beyond normal formatter functions dojo.declare("dojox.grid.formatterScopeObj", null, { store: null, margins: {}, totalMargin: 0, constructor: function(kwArgs){ this.store = kwArgs.store; //this.margins = []; this.totalMargin = 0; }, fmtBuySell: function(item) { var long1 = store.getValue(item,"longForm"); var short1 = store.getValue(item,"shortForm"); var val = long1 - short1; if(val > 0) { return "B"; } else { return "S"; } }, determinePosition: function(pendingItem,pendingMargin){ var identity = this.store.getIdentity(pendingItem); var pendingPosition = this.fmtBuySell(pendingItem);//should be a B or S var gotItem = function(item) { if(item == null) { return; } var position = positionStore.getValue(item,"position"); if(position == "Long" && pendingPosition == "S" || position == "Short" && pendingPosition == "B") { pendingMargin *= -1;//as in a reduction in margin } }; positionStore.fetchItemByIdentity({identity: identity, onItem: gotItem}); return pendingMargin; }, updateMarginTotal: function(margin) { if(typeof(margin)!== 'undefined') { this.totalMargin = margin; } var total = "Margin Change: " + dojo.currency.format(this.totalMargin, {currency: "USD"}); dijit.byId("marginTotal").set("content",total); }, fmtMargin: function(item){ var identity = this.store.getIdentity(item); var margin = 0; var long1 = this.store.getValue(item,"longForm"); var short1 = 0; short1 -= this.store.getValue(item,"shortForm"); var amount = short1 + long1; if(!this.margins[identity]){ margin = this.store.getValue(item, "margin"); var marginReq = margin * Math.abs(amount); if(amount != 0) { this.margins[identity] = amount; marginReq = this.determinePosition(item,marginReq); } this.store.setValue(item, "marginReq", marginReq); this.totalMargin +=marginReq; this.updateMarginTotal(); } else { if(this.margins[identity]==amount) {//nothing changed margin = this.store.getValue(item,'marginReq'); } else {//something has changed, need to rerun calculations var margin = this.store.getValue(item,"marginReq"); margin2 = this.totalMargin - margin; this.updateMarginTotal(margin2); delete this.margins[identity]; this.fmtMargin(item); } } return dojo.currency.format(margin, {currency: "USD"}); }, fmtCommodity: function(item) { if(this.store !== store) { console.log("stores do not match! "); } var long1 = this.store.getValue(item,"longForm"); var short1 = 0; short1 -= this.store.getValue(item,"shortForm"); var commodity = this.store.getValue(item,"commodity"); var month = this.store.getValue(item,"monthName"); if(month != "Cash"){ month = month.substring(0,3); } var amount = short1 + long1; return amount + " " + month + " " + commodity; }, fmtItem: function(value, idx){ if(!this.store.isItem(value)){ return " "; } } }); .... var pendingLayout = [{field:"_item",formatter: "fmtBuySell", width:"10%",name: "B/S"}, {field:"_item",formatter: "fmtCommodity", width:"10%",name: "Commodity"}, {field:"_item",formatter: "fmtMargin", width:"10%",name: "Margin"} ]; var formatObj = new dojox.grid.formatterScopeObj({store:store}); pendingGrid = new dojox.grid.DataGrid({selectionMode:"none",formatterScope: formatObj,query:"{!(shortForm:0 AND longForm:0) AND !price:0}", style:"height: 300px; width: 100%;", store:store,escapeHTMLInData:"false",id:"pendGrid",structure:pendingLayout},pos3); dijit.byId("pendingGridPane").set("content",pendingGrid); pendingGrid.startup();
#this is a test RoR app that uses the djatoka gem for the djatoka image viewer class DjatokaController < ApplicationController def index @formats = [['image/jpeg','image/jpeg'],['image/gif','image/gif'],['image/png','image/png'],['image/jp2','image/jp2'],['image/pnm','image/prm'],['image/tiff','image/tiff'],['image/bmp','image/bmp']] @rotates = [['None','0'],['90','90'],['180','180'],['270','270']] @levels = [[1,1],[2,2],[3,3],[4,4],[5,5],[6,6],[7,7],[8,8],[9,9],[10,10],['MAX','MAX']] @tags = [['djatoka_smallbox_image_tag','djatoka_smallbox_image_tag'], ['djatoka_bottom_right_square_image_tag','djatoka_bottom_right_square_image_tag'], ['djatoka_top_left_square_image_tag','djatoka_top_left_square_image_tag'], ['djatoka_square_image_tag','djatoka_square_image_tag'], ['djatoka_image_tag','djatoka_image_tag']] if !params[:resolver] @default_pid = '1711.dl:2HZ3TEVNP3UA786' @rftid = 'http://memory.loc.gov/gmd/gmd433/g4330/g4330/np000066.jp2' #default image @resolver = 'http://depot-test.library.wisc.edu/adore-djatoka/resolver' #default server @format = 'image/jpeg' #default image format @rotate = 0 #rotate works in 90 degree increments @level = 1 # 1-10 or "MAX" @region = "" #four numbers delimited by commas, no spaces @region1 = 0 @region2 = 0 @region3 = 0 @region4 = 0 @scale = 75 #as a default, it scales the height of the image to the value provided @clevel = 0 #don't think this works, may need some certain type of jp2 image that has "layers" @tag = "djatoka_image_tag" else @rftid = params[:rftid] @pid = @rftid.match('1711.dl(%3A|:)[^/]+') ? @rftid.match('1711.dl(%3A|:)[^/]+')[0] : nil @rftid = "http://depot-test.library.wisc.edu/repository/fedora/#{@pid}/datastreams/JP2/content" if @pid @resolver = params[:resolver] @format = params[:format] @rotate = params[:rotate] @level = params[:level] @region1 = params[:region1] @region2 = params[:region2] @region3 = params[:region3] @region4 = params[:region4] @scale = params[:scale] #@clevel = params[:clevel] @tag = params[:tag] # if(location.href.match('1711.dl(%3A|:)[^/]+')) # @titleUrl = 'http://' + host + '/fedora/objects/' + pid + '/methods/1711.dl:SDefineUWDCObject/getTitle'; # else # @titleUrl = 'http://' + host + '/title/' + pid; if @region3 != "0" && @region4 != "0" @region = "#{@region1},#{@region2},#{@region3},#{@region4}" end #if end #if end #index end #class #End of controller #Start of view <!DOCTYPE html> <html> <head> <title>Djatoka Gem Test App</title> <%= csrf_meta_tag %> </head> <body> <h1>Test us out some djatoka</h1> <div id="container1" style="width:100%;" <div id="image" style="width:50%;float:left;border: 1px;"> <% # Available helpers: # djatoka_smallbox_image_tag ( rft_id,params {}) params can be both djatoka query and image tag parameters # djatoka_bottom_right_square_image_tag () # djatoka_top_left_square_image_tag () # djatoka_square_image_tag () # djatoka_image_tag () #with available parameters being: :scale, :class, :resolver, :format, :rotate, :clayer(doesn't work?), :region, :level %> <% if !@scale.nil? %> <%= send(@tag.to_sym, @rftid, :scale => @scale, :class => 'djatoka_image', :alt => 'djatoka supplied image', :id => 'djatokaImage', :resolver => @resolver, :format => @format, :rotate => @rotate )%> <% else %> <%= send(@tag.to_sym, @rftid, :class => 'djatoka_image', :alt => 'djatoka supplied image', :id => 'djatokaImage', :resolver => @resolver, :format => @format, :rotate => @rotate )%> <% end %>
URL: <%= @resolver %>?url_ver=Z39.88-2004
&svc_id=info:lanl-repo/svc/getRegion
&svc_val_fmt=info:ofi/fmt:kev:mtx:jpeg2000
&rft_id=<%= @rftid %>
&svc.scale=<%= @scale %>
&svc.format=<%= @format %>
&svc.rotate=<%= @rotate %>
&svc.level=<%= @level %>
&svc.region=<%= @region %> </div> <div id="form" style="width:50%;float:right;"> <h1>Configure Image</h1> <%= form_tag :action =>'index', :id => 'djatokaForm' %> <%= label_tag 'rftid' %> <%= text_field_tag 'rftid', @rftid, "size" => 75 %>
<%= label_tag 'resolver' %> <%= text_field_tag 'resolver', @resolver, "size" => 75 %>
<%= label_tag 'scale' %> <%= text_field_tag 'scale', @scale, "size" => 20 %>
<%= label_tag 'format' %> <%= select_tag 'format', options_for_select(@formats, @format) %>
<%= label_tag 'rotate' %> <%= select_tag 'rotate', options_for_select(@rotates,@rotate) %>
<%= label_tag 'level' %> <%= number_field_tag 'level', @level, :in => 1...10 %>
<%= label_tag 'region' %> <%= number_field_tag 'region1', @region1 %> <%= number_field_tag 'region2', @region2 %> <%= number_field_tag 'region3', @region3 %> <%= number_field_tag 'region4', @region4 %>
<%= label_tag 'Image Tag Format' %> <%= select_tag 'tag', options_for_select(@tags,@tag) %>
<%= submit_tag 'Load' %>
#Quick load testing python script #load tests a RoR app loading Jp2 images from the djatoka image server from net.grinder.plugin.http import HTTPRequest from net.grinder.script.Grinder import grinder from net.grinder.script import Test import os # # tag initialization of this module grinder.logger.output( '[ test_runner.py ]' ) # # initialize data sources for tests data_dir = './data' imgpids = open( ( '%s/imgpids.txt' % data_dir ), 'r' ).readlines() #ipidx = 0 # # define base test runner to be subclassed by all actual tests class TestRunner: def __init__( self ): # initialize base parameters self.site_url = 'http://%s' % os.environ['SERVICE_NAME'] self.url = '%s' % os.environ['URL'] self.scale = '%s' % os.environ['SCALE'] self.tag = '%s' % os.environ['IMAGE_TAG'] self.rotate = '%s' % os.environ['ROTATE'] self.format = '%s' % os.environ['FORMAT'] self.test = Test( 1, 'djatoka-image-basic' ) self.req = self.test.wrap( HTTPRequest() ) self.rsp = None self.ipidx = 0 return def __call__( self ): # run a query and report result only if verified grinder.statistics.delayReports = 1 self.rsp = self.req.GET( self.test_query() ) if self.rsp.statusCode == 200: grinder.statistics.forLastTest.setSuccess( 1 ) else: print self.rsp.statusCode return def next_pid( self ): pid = imgpids[self.ipidx].rstrip( '\n' ) self.ipidx = self.ipidx + 1 return pid def test_query( self ): #new url is http://depot-test.library.wisc.edu/TIRIS/content/reference/*.jp2 #http://depot-test.library.wisc.edu/adore-djatoka/resolver?url_ver=Z39.88-2004&rft_id=http://depot-test.library.wisc.edu/TIRIS/content/reference/1984.01.001.01.jp2&svc_id=info:lanl-repo/svc/getRegion url = '%s/%s/&rft_id=%s&svc.scale=%s&svc.format=%s&svc.rotate=%s' % ( self.site_url, self.url, self.next_pid(),self.scale,self.format,self.rotate ) grinder.logger.output( url ) return url

Technology list

Languages

  • Javascript (Dojo, YUI, jquery)
    CoffeScript
    PHP
    Ruby
    Python
    Perl
    Java
    ColdFusion
    PL/SQL
    C++

Databases

  • mysql
    sql server
    oracle
    db2
    hsqldb
  • Servers

  • Apache
    Node
    Tomcat
    Jetty
    IIS

Frameworks

  • ZendFramework
    Rails
    CodeIgnitor
  • Moodle
    Drupal
    WordPress
    SugarCRM
  • VCS

  • SVN
    CVS
    Git

Work Experience

(click on the timeline to view my past work experience)

Oct 2012-Present

Flexion, Inc

JavaScript Engineer
  • Accomplish nearly impossible feats of JavaScript coding daily
  • Brought expertise to a struggling project and successfully deployed a new product to market
  • Single Page standardized testing app with strict requirements
  • Used backbone.js, coffeescript, d3.js as well as the web audio api

April 2012-Oct 2012

Toura, LLC

JavaScript Engineer
  • Lead JavaScript developer for the open source Mulberry toolkit
  • Mulberry is a JS framework that allows you to build mobile apps, platform agnostic
  • Built on the Dojo Toolkit as well as PhoneGap
  • Wrote custom Android and iOS plugins

May 2011-April 2012

SitePen, Inc.

Software Engineer
  • Develop and support enterprise level web apps with Dojo
  • Write and update Dojo documentation
  • Write and update Dojo tutorials
  • Contribute to dgrid, part of the Dojo Foundation
  • Develop and maintain internal business applications

Sept 2008-May 2011

University of Wisconsin-Madison Madison, WI
DoIT – Academic Technology

Academic Technology Developer

Learning Solutions

  • Green dollar unit
  • Multiple projects of $50k - $100k each
  • Malaria: the game. PHP/mysql
  • VirtualCase – A Moodle module that simulates a clinical environment. PHP/mysql with YUI elements
  • Commodities Risk Management – a simulation of the commodities market. ZF/mysql/Dojo

Shared Development Group

  • Loaned for six months to SDG
  • Worked on Ruby, Python, and Java apps
  • Optimized Tomcat instance for Djatoka Image Server

Jan 2007-Sept 2008

University of Wisconsin-Madison Health Services
Madison, WI

Web Developer
  • Supported SHIP (Student Health Insurance Program) Online
  • Develop enhancements and debug using JSP and Java
  • Oracle back-end
  • Integrated Crystal Reports 10 report interface
  • Research and advise on future web technology trends
  • Business analysis and development in ColdFusion 8 for an internal Web App.
  • Database design in MySql 5
  • Future planning for development of new web portal

Feb 2006 –Jan 2007

dChron, inc.
Burlington, WI

Java Developer
  • Involved in all aspects of the development life cycle for dChron’s dComm (data communication software).
  • Developed in Java, using Eclipse’s SDK
  • Developed both www.dchron.com and www.timetrakmidwest.com
  • Database experience with Hypersonic DB

May 2004 – Feb 2006

Northwestern Mutual
Milwaukee, WI

Systems Specialist
  • Certification in Oracle’s PL/SQL, 9i, 10g
  • Supported the largest and most complex system at Northwestern Mutual
  • Debugged extensively in both Oracle and VB
  • Worked on many small projects from design to implementation and support
  • Supported nightly processing
  • Primary contact between our team and business clients
  • Supported Actuate reports and processing for the system

Fall 2003

Earthly Elements
Madison, WI

Web Site Developer
  • Contracted through Earthly Elements to develop website
  • Used Html, Macromedia’s Flash, and JavaScript.
  • Was posted at www.earthlyelements.com

Spring 2003

Western Racine County Health Department
Burlington, WI

Web Site Developer
  • Contracted through Aurora Healthcare to create a website for the health department.
  • Used Html, Macromedia’s Flash, and JavaScript
  • Posted at http://www.wrchd.org (not responsible for current design theme)

2002

Runzheimer Int’l
Rochester, WI

Information Technology Intern
  • Duties included web-based application design and implementation using ASP. Used Microsoft’s SQL Server.
  • Created procedures using SQL to move data from Excel and Access to the mainframe using COBOL.

My blog

Top bar menu animation

Coming Soon!

26 January 2012

How-to: Work experience timeline

Creating a work experience timeline with Dojox Charting!

14 December 2011

Presenting at web-5 conf!

I'll be presenting on two topics at the Web-5 conf in Beziers, France in April!

Get in touch

Please fill out the form on the right to contact me, alternatively you can drop me an email chris@christopherbarrett.name

I am always open to discuss interesting opportunities.