Showing posts with label ajax. Show all posts
Showing posts with label ajax. Show all posts

Saturday, November 28, 2015

Groovy framework for AWS lambda

I was playing with AWS lambda recently and I find it pretty exciting. It is cheap, does not require any maintenance and it is simple. The biggest problem I found so far, is lack of tooling. AWS has web UI which does what it supposed to do, but is far from pleasant. AWS command line tools and API are much better, but are AWS centric. So, I have created tool to work with AWS lambda. It uses some convention now, but can be adjusted to whatever feels right for specific situation, idea is that it is just one script with few lines of code. Basically, it does 2 things: uploads application and local testing. I have created small example that illustrates how and what it does.

Example is trivial application that increments number by clicking on button. It is SPA, with static client in S3 and two API functions add and get.

All lambda code is just single Groovy script. It consists of router function, dependencies and logic. Router function is what will be mapped to lambda. It is function that accepts map and returns map. Input map can be plain request JSON, or some additional parameters can be injected at API gateway. Even for this trivial case it was a good idea and I injected configuration parameters - AWS access and secret keys and region for DynamoDB access, so they are hidden at admin level and are environment specific. Simplest way to do routing is just by using some designated parameter, in this example, it is called "function". Doing it with real URI will need AWS configuration, and it is not very convenient and flexible.

In this simple example, router script does logic, but for more complex cases it is better to be just router and logic would be in dependencies.

During packaging Groovy script is compiled and packaged together with all dependencies into uberjar which is required by AWS. After that, it is uploaded via AWS API.

Development can be done and tested locally by using mock server. Mock server mimics AWS, parses input into JSON like lambda, injects parameters like API gateway, includes Access-Control-Allow-Origin and separates configuration via config.js, supports debug and reloading.

Friday, January 2, 2015

CanJS and ClojureScript

I don't really like compiled JavaScript languages, but if I had to choose - I like ClojureScript the most. It is big friends with Om MVC framework, which is based on React.js. React is another component framework like CanJS, but is too verbose to my tastes and has less features out of the box, so I like CanJS more. Only problem is that it does not have a lot of integration with ClojureScript. But it is pretty easy to solve, because ClojureScipt and CanJS are both amazing and flexible. There is example of simple component, there is ClojureScript:

(ns myexample
  (:require [domina :refer [by-id set-html!]]
            [domina.css :refer [sel]]))

(.extend can/Component
  #js {:tag "my-component"
       :scope #js {:value 3
                   :increment #(.attr % "value" (inc (.attr % "value")))}})

(set-html! (by-id "my-root") (can/view "my-template" {}))


And HTML:

<html>
<body>
  <div id="my-root"></div>
  <script type="text/mustache" id="my-template">
    <my-component>
      Value: {{value}} <input type="button" can-click="increment" value="Increment"/>
    </my-component>
  </script>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js"></script>
  <script src="http://canjs.com/release/latest/can.jquery.js"></script>
  <script src="base.js" type="text/javascript"></script>
  <script src="myexample.js" type="text/javascript"></script>
  <script type="text/javascript">goog.require("myexample");</script>
</body>
</html>



Tuesday, July 22, 2014

CanJS execute code on component initialization

I didn't found it described anywhere, but it works for me. If you need to execute code after component initialization, you can add init method to scope and it is executed after component is created.

    scope: {
      init: function() {
        runme();
      }
    }

Thursday, July 3, 2014

Updating model elements of CanJS component scope

CanJS scope is simple map and when you need to retrieve new element from server the easiest way seems just to assign new model to property, like:

  scope.attr('todos', new Todo.List({date:val}));

This is easy and works, but not best solution, as values blink on screen. This is because initial list is empty and values are added after they are loaded, so more smooth and reactive (bazinga!) way to do it, will be by model's findAll method callback, like:

  Todo.findAll({date:val}, function(todos){ scope.attr('todos', todos) });

Additional benefit of this approach is that you can use new values for whatever you might need besides displaying them.

Thursday, June 12, 2014

CanJS is not calling Mustache function when value is updated

Mustache can map not only specific values to template, but also results of the functions, which is sometimes handy. There is example.

But recently, when I was using this feature inside of CanJS template, it only rendered results for the first time and did nothing when values were changing. This was not working properly:

  can.Component.extend({
    tag: "sum",
    scope: {
      model: new can.Model({x: 2, y:3}),
      result: function() {
        return this.model.x * this.model.y;
      }
    },
    template: '<input can-value="model.x">*<input can-value="model.y">={{result}}'
  });

As I found out, problem was that it was missing proper value invocation and simply calling values via attr method fixes the problem.
This works fine:

  can.Component.extend({
    tag: "sum",
    scope: {
      model: new can.Model({x: 2, y:3}),
      result: function() {
        return this.model.attr('x') * this.model.attr('y');
      }
    },
    template: '<input can-value="model.x">*<input can-value="model.y">={{result}}'
  });

Wednesday, June 4, 2014

Accessing multiple objects from CanJS events in components

CanJS components have nice and easy way to access context object from event, just as parameter:

{{#books}}
  <input type="button" can-click="add" />
{{/books}}

add: function(book) {
  books.add(book);
}

But what if you need also parent object, or object from some other hierarchy. To do it, CanJS can bind DOM objects to any data, and in components this is usually context. Just add special property {{data '...'}} to DOM element in your Mustache template, for example:

{{#shelves}}
  <h1>{{name}}</h1>
  <div {{data 'shelf'}}>
    {{#books}}
      <input type="button" can-click="add" {{data 'book'}} />
    {{/books}}
  </div>
{{/shelves}}

And you can access all objects like:

add: function(context, el) {
  var book = el.data('book');
  var shelf = el.parent().data('shelf');
  shelf.add(book);
}

Friday, May 9, 2014

Chaining jQuery promises in for cycle

JQuery has nice support for promises, but some stuff is not obvious and recently I just stuck with one particular problem: I had to prepare a bunch of closures in for cycle and added them to deferred object which was resolved afterwards. All of them had to be executed strictly one after another, but there are ajax calls so I cann't do it old fashioned way, since sinchronous ajax is weird.
So I did this:

function doPromise(someVar) {
  return function() {
    return $.ajax({ type: 'POST', url: 'http://myurl', success: doStuff, error: panic});
  }
};
function start() {
  var promise = $.Deferred();
  for (var i=0;i<10;i++) {
    promise.then(doPromise(i) );
  }
  promise.resolve();
};


And I was expecting it being called one after another, which was not the case and all of them fired simultaniously. As I found out finally, all thens are equal and I had to add them, not to original promise, but dirrectly to each other, which is a little confusing to me, but works. So this is the correct code for my case:

function start() {
  var original = $.Deferred();
  var promise = original;
  for (var i=0;i<10;i++) {
    promise = promise.then(doPromise(i) );
  }
  original.resolve();
};


Thursday, April 3, 2014

MeteorJS like application in Grails

MeteorJS is new web framework that combines server-side and client-side programming into one, leaving mostly just client-side. I am defenitely not expert with tool and just seen demo on their homepage, but WOW effect is sure impressive. It suppose to kill all Rails and server-side development in general. Thank god I am full-stack developer, but anyway I am scared.

General idea behind this framework is autogenerating all server-side code, leaving mostly just configuration. Similar feature was recently introduced in Grails, so I was wondering - is it possible to create something similar to MeteorJS in Grails. And there is my experience.

Basically, it needs autogenerated REST, Javascript ORM and server push. REST is Grails feature since version 2.3; for client-side ORM I picked CanJS as it looks most similar to Meteor; for server push in Grails I picked spring-websocket plugin (because it is first result in Google, why else?). Unfortunately, spring-websocket is M1 and it relies on Spring 4, so Grails is 2.4M1 too, so it is not production safe, but MeteorJS is 0.8.0 now too, so we are even.

Application idea is simple TODO app. You can find full source here. There is defenitely some boilerplate code as it is not plugin, but I think in general it is pretty similar to MeteorJS example. It consists of 3 meaningful components: view, controller and domain object.

View is Mustache template, and is pretty straightforward if you are familiar with CanJS:

<h1>test</h1>
<table>
{{#todos}}
  <tr>
    <td>{{description}}</td><td><input type="checkbox" can-value="done"></td>
    <td><input type="button" value="Delete" can-click="delete"></td>
    </tr>
{{/todos}}
</table>

Description
<input type="text" can-value="description">
<input type="button" can-click="add" value="Add">

Controller is CanJS component with ORM definition:

var Todo = can.Model({
  findAll: function(id)   {return $.get('/grails-meteor-example/todos.json/')},
  findOne: function(id)   {return $.get('/grails-meteor-example/todos.json/'+id)},
  create:  function(data) {return $.post('/grails-meteor-example/todos.json/', data)},
  update:  function(id)   {return $.ajax({type: 'PUT',    url: '/grails-meteor-example/todos.json/'+id })},
  destroy: function(id)   {return $.ajax({type: 'DELETE', url: '/grails-meteor-example/todos/'+id, contentType: 'application/json' })}
}, {});

can.Component.extend({
  tag: "todos",
  template: can.view("todos.mustache"),
  scope: {
    todos: new Todo.List({}),
    description: can.compute(''),
    add: function() {
      new Todo({'description':this.description(), 'done':false}).save();
      this.description('');
    },
    delete: function(todo) {
      todo.destroy();
    }
  },
  events: {
    "{todo} change": function(){
      this.scope.attr('todos', new Todo.List({}));
    }
  }
});

$(document).ready(function() {
  $("body").html( can.view.mustache("<todos></todos>"));
});


Domain is Grails domain object mapped as REST controller:

package org.grmeteor

import grails.rest.Resource

@Resource(uri='/todos')
class Todo {
  String description
  boolean done
}


View is totally similar to MeteorJS. Controller is similar, but also contains ORM definition and server push event. Both could be easily autogenerated with Grails plugin, but at least push can be also left for practical applications (probably, you will not want to have notification with millions of parallel users). Domain is pure Grails overhead, but it would probably still be needed for SQL backends in MeteorJS (and hey, those server-side devs want to eat too!).

Of course there are other files too, like server push sender and client side HTML container for CanJS, but these are mostly static and sure can be easily hidden by plugin. So only part that is missing to make Grails MeteorJS-cool is plugin itself, which even if not for practical cases could be nice to have for WOW effect and MVPs.

Wednesday, April 2, 2014

Grails REST redirect after DELETE with jQuery

If you do delete from AJAX request (directly or via framework), sometimes Grails REST controller redirects response to index method, which when done with DELETE method leads to 405 HTTP error.
This happens because of incorrect content type in request. To fix it, contentType needs to be explicitly set in request, like:

$.ajax({
    url: '/todos/'+id,
    type: 'DELETE',
    contentType: 'application/json'
  })

Thursday, March 20, 2014

CanJS incorrectly places elements in table row

After rendering this HTML in CanJS, 'tests' elements got placed before table and not after previous cell as it is supposed to be:

<thead>
  <tr>
    <th>Test</th>
    <th><input type="button" value="Test"></th>
    {{#tests}}
      <th>{{name}}</th>
    {{/tests}}
  </tr>
</thead>

Problem was that input tag was not closed, which is usually fine with HTML, but confuses CanJS. After closing it, everything was working as expected.

Wednesday, April 10, 2013

Setting style by custom property dynamically in AngularJS

Angular JS lets to set and update style and class based on some custom property. Unfortunately, it does not support placeholders now, for example:


<!-- This works -->
<td ng-style="myStyle">


<!-- This does not -->
<td ng-style="myStyle{{test}}">



Fortunately, it works with controller's methods, so this still can be done like:


<td ng-style="getMyStyle(test)">

where getMyStyle is controller's method.

Friday, February 10, 2012

JavaScript parseInt does not work as expected when parameter starts with 0

There is standard way to parse Strings into Numbers in JavaScript by using parseInt function. But sometimes it works unexpected, and for example, returns 0 when you expect 8. If that is the case, then most probably problem is that when parameter starts with 0 (like '08') parseInt treats it as octal number and changes radix to 8.
This is annoying and can take some time to discover. Luckily, it is easy to fix by specifying radix directly as second parameter. For example like:

parseInt('08', 10)




Friday, February 3, 2012

Freezing table header with JQuery

When you have long table on page, with a lot of numbers, and you scroll down and header is not visible anymore, it is often difficult to track what number is which column. One nice solution to this problem is to lock and freeze table header when scrolling page.
Unfortunately there is no ready out of the box solution with JQuery for this problem. Fortunately, it is easy to implement with few methods. There are examples how to do it, but for some reason they didn't worked well in my situation (no support for resize and horizontal scroll), so I have adjusted them for my situation.

For example, you have your table named tabs.

First, you have to create invisible table that will hold frozen header.

<table cellpadding='0' cellspacing='0' id="header-fixed"  style="position: fixed; top: 0px; display:none;"></table>

Then just add this Javascript:

     <script type="text/javascript">
       var tableOffset;
       var header;
       var fixedHeader;

       function resize() {
         var totalwidth = $('#tabs').css('width');
         fixedHeader.css('width', totalwidth);
         var widths = [];
         $('#tabs thead th').each(function() {
           widths.push($(this).width());
         });
         var i=0;
         $('#header-fixed th').each(function() {
           this.width = widths[i];
           i++;
         });
       }
       function resizeAndShow() {
         var offset = $(this).scrollTop();
         if (offset >= tableOffset && fixedHeader.is(":hidden")) {
           fixedHeader.show();
           resize();
         } else if (offset < tableOffset) {
           fixedHeader.hide();
         }
         fixedHeader.css('left', $('#tabs').position().left - $(this).scrollLeft());
       };
        $(document).ready(function() {
          tableOffset = $("#tabs").offset().top;
          header = $("#tabs > thead").clone();
          fixedHeader = $("#header-fixed").append(header);

          $(window).bind("scroll", resizeAndShow);
          $(window).resize(resize);
        });
     </script>

This is it.

Monday, July 4, 2011

Handling HTML changes via DOMSubtreeModified

Recently, I needed to handle changes in DOJO rich text editor. It supports all traditional events, but my problem was that I needed to handle also copy/pastes and especially mouse copy/pastes (right button context menu), as I have found, it does not counts as mouse events. After some investigation I have found nice, but for some reason not so popular event DOMSubtreeModified.
So I am able to handle all changes by subscribing to changes like:
rte.addEventListener("DOMSubtreeModified", function(){
   ...
}

One issue with this approach is that it is not supported by all browsers and is depricated by W3, but I need this feature for controlled environment.

Sunday, March 14, 2010

Ajax mock

One thing missing in QUnit and other javascript frameworks that I was looking for is mocking. Mock is object that replaces some complicated system, to simplify tests.
For example, I want to test javascript that I have ajax calls.

function serverSideSum(v1, v2) {
  $.post('http://localhost/sum', {val1: v1, val2: v2}, function(data) {
    $('#result').text(data.result);
  });
}

Normally, to make them work I have to run server that would answer to my calls. There is a number of problems
  • It is much slower compared to normal javascript tests
  • It requires infrastructure
  • How to check that my javascript sends correct data?
  • How to validate response or be sure that server part is not broken
Other option is to replace calls to real server with artificial function calls that always returns good results.
  • It is fast
  • Runs without server
  • Can check input data
  • Server response is always as good as you need

It is very easy to create mock in javascript. You just have to redefine some function. For example in JQuery ajax calls are sent by calling $.post() and $.get()
methods. So mock can be:

$.post = function(url, data, func) {
  func({result:4});
};



We can check parameters too:

$.post = function(url, data, func) {
  equals(data.val1, 2);
  equals(data.val2, 2);
  func({result:4});
};

And complete test looks like:

test("server side 2+2=4", function() {
  $.post = function(url, data, func) {
    equals(data.val1, 2);
    equals(data.val2, 2);
    func({result:4});
  };
  serverSideSum(2, 2);
  equals(4, $('#result').text());
});

Nice, but what if there are several calls to same ajax method during one function invocation?
For example, our function will also get number of calls to server:

function serverSideSum(v1, v2) {
  $.post('http://localhost/sum', {val1: v1, val2: v2}, function(data) {
    $('#result').text(data.result);
  });
  $.post('http://localhost/counter', {}, function(data) {
    $('#counter').text(data.count);
  });
}

Finally we can update our test to something like:

test("server side 2+2=4", function() {
  ajaxMock([
    [{result:4}, function(data) {equals(data.val1, 2); equals(data.val2, 2);}],
    [{count:123}, function(data) {}]
  ]);
  serverSideSum(2, 2);
  equals(4, $('#result').text());
  equals(123, $('#counter').text());
});


Function ajaxMock has one parameter - array of objects, and every object represents one ajax call and consists of call results and function thatvalidates input parameters.
Implementation of this method can be something like this:

function ajaxMock(params) {
  ajaxCallsCounter = 0;
  ajaxCallsParams = params;
  var callback = function(url, data, func) {
    ajaxCallsParams[ajaxCallsCounter][1](data);
    func(ajaxCallsParams[ajaxCallsCounter][0]);
    ajaxCallsCounter++;
  }
  $.get = callback;
  $.post = callback;
}

All ajax calls are stored in memory. After ajax call, array index ajaxCallsCounter will be increased and will not be called again, so this ensures that all ajax calls are done only once and in correct order.
Additionaly, you can verify that all calls were made by comparing array index with it's length, like this:

equals(ajaxCallsCounter, ajaxCallsParams.length);

Friday, March 5, 2010

Javascript unit testing

Javascript unit test framework is just plain html file loaded in browser, which executes your javascript code in predefined order.
It is quite easy to create it from scratch, but there is a plenty of ready frameworks, that provide nice reports and allow to run different combinations of tests.
I tried QUnit and it quite ok. It is just basically several files, that you have to download - javascript and css. Then you have to create new html file where you will describe your tests. Also from this html you have to link QUnit files and javascript code that you want to test. Unless you want to put your functions in test file, you must have javascript in separate file.
So, in the end you will have something like this:

<html>
  <head>
    <script src="jquery-1.3.2.js"></script>
    <script src="testrunner.js"></script>
    <script type="text/javascript" src="code.js" ></script>
    <link rel="stylesheet" href="testsuite.css" type="text/css"/>
    <script type="text/javascript">

    </script>
  </head>
  <body>
    <ol id="tests"></ol>
    <div id="main"></div>
  </body>
</html>


Where code.js is your javascript code to test.
<ol id="tests"></ol> and <div id="main"></div> is where QUnit puts it's stats.
Now you can start to write tests.
For example, our code.js has something like:

function sum(v1, v2) {
  return v1 + v2;
}


To test it, we should have to call method test, for example like

test("2+2=4", function() {
  var result = sum(2, 2);
  equals(4, result);
});


If your code accesses some html element, there are several options - you can include your real html code into tests.html body, or you can mock it with some trivial html element. You can also add and destroy necessary html elements in test scenario. In general, include is probably best option as it avoids dublication, but simple mock elements was best choise in my cases so far. Drawbacks of include is that it requires server-side code and calls.
For example, if your code is

function showSum(v1, v2) {
  $('#result').text(sum(v1, v2));
}


You can add div element with id 'result'. And now all your tests will look like:

<html>
  <head>
    <script src="jquery-1.3.2.js"></script>
    <script src="testrunner.js"></script>
    <script type="text/javascript" src="code.js" ></script>
    <link rel="stylesheet" href="testsuite.css" type="text/css"/>
    <script type="text/javascript">
      test("2+2=4", function() {
        var result = sum(2, 2);
        equals(4, result);
      });
      test("show 2+2=4", function() {
        showSum(2, 2);
        equals(4, $('#result').text());
      });
    </script>
  </head>
  <body>
    <ol id="tests"></ol>
    <div id="main"></div>
    <div id="result"></div>
  </body>
</html>


Now we have some state between tests (value in 'result' div) and it is not good, because it can confuse tests and bring some surprizes.
Traditional way how to clean state between tests is to reset it. It is normally done in methods setup or teardown.
Setup is called before every test and supposed to prepare test for running and teardown is called after every test and supposed to clean environment after test.
In QUnit it is set in function 'module', like this:

module("my tests", {
  setup: function() {
    $('#result').text('12345');
  },
  teardown: function() {
    $('#result').text('');
  }
});


Here we set result to some value, for example, to check that it really updates value, but not appends. And in teardown we reset 'result' div to it's initial empty state for next test. It usually has more sence in big projects with many state parameters.