• Re-use legacy forms with this one weird trick...

    Part of working with a legacy codebase means dealing with obnoxious monolithic forms. Oftentimes we’re able to budget resources to refactor these forms for client-facing parts of the site, but it can be difficult to justify rewriting internal tools along the way.

    This leads to an unpleasant experience for other groups (not to mention maintenance annoyances) as we move more tools into Backbone, forcing our teams to work within 2 different application paradigms.

    So, I’ve been forging an unholy alliance between PHP scripts and our Backbone modules through $.ajax by extracting the forms from one templating system and injecting them into a View.

    Module.ActionsView = Backbone.Marionette.LayoutView.extend({
        events: {
          "click a.legacy-action": "loadLegacyForm"
        },
        loadLegacyForm: function(e){
          e.preventDefault();
    
          $.ajax({
            url: $(e.currentTarget).attr('href'),
            type: "GET",
            context: this,
            data: {
              // any params you may need for this form
            }
          }).done(function(response){
            // what now?
          });
        }
      });

    The raw source is generally annoying to work with… using $.load can allow you to extract one element, but sometimes you might need other components from the page. This is the cleanest method I’ve found to get what you want out of some arbitrary markup-string:

    $.ajax({
        // ...
      }).done(function(response){
        
        var form = $("<div/>").append(response).find('form[name="sweet-form"]');
    
      });

    So what should we do with this form element? We could simply drop it into the DOM via $.html, but then submitting the form would send us out of our single page app. We could define some event listeners, but then we have to remember to clean up, and so on.

    Since we’re already within a Backbone / Marionette app, we can take advantage of the nice event listener sytax by injecting it via the View’s el. All together now:

    Module.ActionsView = Backbone.Marionette.LayoutView.extend({
        regions: {
          "legacyForm": "div#legacy-form-container"
        },
        events: {
          "click a.legacy-action": "loadLegacyForm"
        },
        loadLegacyForm: function(e){
          e.preventDefault();
    
          $.ajax({
            url: $(e.currentTarget).attr('href'),
            type: "GET",
            context: this,
            data: {
              // any params you may need for this form
            }
          }).done(function(response){
            var form = $("<div/>").append(response).find('form[name="sweet-form"]');
    
            var view = new Module.LegacyFormView({ el: form });
    
            this.legacyForm.show(view);
    
          });
        }
      });

    Et voila: Module.LegacyFormView can add a handler for Marionette.View.onRender events, handle submit events via $.ajax, and we can make the LayoutView listen to the LegacyFormView, then work some magic, etc.; the sky’s the limit.

  • Subdivisions

    One of my favorite things about building software is the opportunity to explore new libraries / tools on an almost daily basis, so in putting together this blog I’ve taken some time to evaluate some libs that [for whatever reason] we haven’t integrated into our workflow at the office.

    I decided to go with grunt at first as the name was already familiar to me, but didn’t really evaluate it or look into alternatives. The config did seem a little verbose but the syntax was easy to pick up with a minimal amount of debugging / trial-error.

    Shortly thereafter a colleague of mine mentioned how much he enjoyed gulp for his side projects. I won’t make this YAPCGG (Yet Another Post Comparing Gulp and Grunt), but I will say this: while there’s no productivity gain (at the moment) for switching, I’ll be doing so for no other reason than the joy of learning !

  • So Futere

    Music is irrevocably intertwined with my mood / flow for the day, alternately reflecting and giving rise to my internal state.

    During my late-night working hours the above sounds are the soundtrack to my mental-flow. This style of music has so much groove / soul, and yet can also serve as a sort of ambiance to just about anything. As long as it’s happening at night.

    A friend of mine who happens to be a lawyer in a fancy law office (well, I’d like to imagine that it’s fancy at least) passed along some of these sounds to her boss one evening (whom I also imagine to be fancy), and he really took a liking to them, emailing her at 5A with his feedback on various moments in sound.

    Now I often imagine some man in a suit and tie poring over some complicated litigation in his darkened office, subtlely nodding his head as he crafts his argument.

    Anyway, I tried to create this blog in which I separated music from technical subjects and [after a completely inordinate amount of time spent pondering] came to the conclusion that doing so wouldn’t be an accurate reflection of me or how I think.

    And legit blogging is about keepin’ it real.

  • Ajax Goon

    Lazy wisps of nag champa in the air, some lovely tea from T2, soundtrack to this evening provided by Paul Galbraith. Earlier I put together a really fine rye-Manhattan earlier, slowly improving my technique.

    Steady progress putting this thing together:

    • set up asset management via Bower, pulled in a base set of components to work with
    • set up a Gruntfile.js to build out concat’d / minified JS / LESS assets using this as an example (note that I’ve pushed the jekyll root one level deeper to avoid an extra rsync-exclude file for bower / npm components / etc. during my deploy):
    module.exports = function(grunt) {
    
        grunt.initConfig({
          less: {
            production: {
              options: {
                paths: ["bower_components/bootstrap/less/"],
                yuicompress: true
              },
              files: {
                "jekyll/assets/css/application.min.css": "jekyll/_less/application.less"
              }
            }
          },
          uglify: {
            jquery: {
              files: {
                'jekyll/assets/js/jquery.min.js': 'bower_components/jquery/dist/jquery.js'
              }
            },
            bootstrap: {
              files: {
                'jekyll/assets/js/bootstrap.min.js': ['bower_components/bootstrap/js/collapse.js',
                                               'bower_components/bootstrap/js/scrollspy.js',
                                               'bower_components/bootstrap/js/button.js',
                                               'bower_components/bootstrap/js/affix.js']
              }
            }
          },
          copy: {
            bootstrap: {
              files: [
                { expand: true, cwd: 'bower_components/bootstrap/fonts/', src: ['**'], dest: 'jekyll/assets/fonts/' }
              ]
            },
            bootstrap: {
              files: [
                { expand: true, cwd: 'jekyll/_images/', src: ['**'], dest: 'jekyll/assets/img/' }
              ]
            }
          },
          exec: {
            build: {
              cwd: 'jekyll/', cmd: 'jekyll build'
            },
            serve: {
              cwd: 'jekyll/', cmd: 'jekyll serve --watch' // note: this doesn't work on *BSD
            },
            deploy: {
              cmd: 'rsync --progress -a --delete -e "ssh -q" ' // manual deployment for local changes 'cause the above
            },
            deploy_remote: {
              cmd: 'rsync --progress -a --delete -e "ssh -q" ' // make it live
            }
          }
        });
    
        grunt.loadNpmTasks('grunt-contrib-uglify');
        grunt.loadNpmTasks('grunt-contrib-less');
        grunt.loadNpmTasks('grunt-contrib-copy');
        grunt.loadNpmTasks('grunt-exec');
    
        grunt.registerTask('default', [ 'less', 'uglify', 'copy', 'exec:build' ]);
        grunt.registerTask('deploy', [ 'default', 'exec:deploy' ]);
        grunt.registerTask('deploy_remote', [ 'default', 'exec:deploy_remote' ]);
    
      };
    • push’d a new repo to my host (with appropriate access controls via gitolite of course)
    • Bootstrap’d (Bootstrap-ified?) the default theme and added salt to taste

    Eventually I’d like to convert to SASS, but for now I’ll focus on making this thing live, as well as optimizing my environment for making content, eg. some better YASnippets as well as using org-mode as the base for constructing these posts.

    Lots to do.

  • Remote Views

    ‘Wuff, Wuff!!’ goes my terminal’s vbell_msg.

    Here I sit on a foggy late Tuesday evening, sipping some shiitake / tofu miso soup + sake, trying oncemore to decide what / why I should blogging.

    The task seems somehow daunting. I could easily decide what I’d write for a given audience, ie. a group of social media acquaintances, but I draw a blank when attempting to put something together for nobody in particular.

    For now this is all living within a local VirtualBox until I have time to determine my deployment process. Maybe it’ll finally happen this year !

subscribe via RSS