Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
var Paste;

Paste = (function() {
  class Paste {
    static mountNonInputable(nonInputable) {
      var paste;
      paste = new Paste(createHiddenEditable().appendTo(nonInputable), nonInputable);
      $(nonInputable).on('click', () => {
        return paste._container.focus();
      });
      paste._container.on('focus', () => {
        return $(nonInputable).addClass('pastable-focus');
      });
      return paste._container.on('blur', () => {
        return $(nonInputable).removeClass('pastable-focus');
      });
    }

    static mountTextarea(textarea) {
      var paste;
      if (!window.ClipboardEvent) {
        return this.mountContenteditable(textarea);
      }
      // Firefox only
      paste = new Paste(createHiddenEditable().insertBefore(textarea), textarea);
      $(textarea).on('keypress', (ev) => {
        if ('v' !== String.fromCharCode(ev.charCode)) {
          return;
        }
        if (!(ev.ctrlKey || ev.metaKey)) {
          return;
        }
        return paste._container.focus();
      });
      $(paste._target).on('pasteImage', () => {
        return $(textarea).focus();
      });
      $(paste._target).on('pasteText', () => {
        return $(textarea).focus();
      });
      $(textarea).on('focus', () => {
        return $(textarea).addClass('pastable-focus');
      });
      return $(textarea).on('blur', () => {
        return $(textarea).removeClass('pastable-focus');
      });
    }

    static mountContenteditable(contenteditable) {
      var paste;
      paste = new Paste(contenteditable, contenteditable);
      $(contenteditable).on('focus', () => {
        return $(contenteditable).addClass('pastable-focus');
      });
      return $(contenteditable).on('blur', () => {
        return $(contenteditable).removeClass('pastable-focus');
      });
    }

    constructor(_container, _target) {
      this._container = _container;
      this._target = _target;
      this._container = $(this._container);
      this._target = $(this._target).addClass('pastable');
      this._container.on('paste', (ev) => {
        var clipboardData, i, item, len, reader, ref, ref1, results;
        if (((ref = ev.originalEvent) != null ? ref.clipboardData : void 0) != null) {
          clipboardData = ev.originalEvent.clipboardData;
          if (clipboardData.items) {
            ref1 = clipboardData.items;
            // Chrome & Safari(text-only)
            results = [];
            for (i = 0, len = ref1.length; i < len; i++) {
              item = ref1[i];
              if (item.type.match(/^image\//)) {
                results.push(reader = new FileReader());
              } else {
                results.push(void 0);
              }
            }
            return results;
          }
        }
      });
    }

  };

  // Element to receive final events.
  Paste.prototype._target = null;

  // Actual element to do pasting.
  Paste.prototype._container = null;

  return Paste;

}).call(this);
```

Response:
class Paste
  # Element to receive final events.
  _target: null

  # Actual element to do pasting.
  _container: null

  @mountNonInputable: (nonInputable)->
    paste = new Paste createHiddenEditable().appendTo(nonInputable), nonInputable
    $(nonInputable).on 'click', => paste._container.focus()

    paste._container.on 'focus', => $(nonInputable).addClass 'pastable-focus'
    paste._container.on 'blur', => $(nonInputable).removeClass 'pastable-focus'

  @mountTextarea: (textarea)->
    return @mountContenteditable textarea unless window.ClipboardEvent
    # Firefox only
    paste = new Paste createHiddenEditable().insertBefore(textarea), textarea
    $(textarea).on 'keypress', (ev)=>
      return unless 'v' == String.fromCharCode ev.charCode
      return unless ev.ctrlKey || ev.metaKey
      paste._container.focus()
    $(paste._target).on 'pasteImage', =>
      $(textarea).focus()
    $(paste._target).on 'pasteText', =>
      $(textarea).focus()

    $(textarea).on 'focus', => $(textarea).addClass 'pastable-focus'
    $(textarea).on 'blur', => $(textarea).removeClass 'pastable-focus'

  @mountContenteditable: (contenteditable)->
    paste = new Paste contenteditable, contenteditable

    $(contenteditable).on 'focus', => $(contenteditable).addClass 'pastable-focus'
    $(contenteditable).on 'blur', => $(contenteditable).removeClass 'pastable-focus'

  constructor: (@_container, @_target)->
    @_container = $ @_container
    @_target = $ @_target
    .addClass 'pastable'
    @_container.on 'paste', (ev)=>
      if ev.originalEvent?.clipboardData?
        clipboardData = ev.originalEvent.clipboardData
        if clipboardData.items
          # Chrome & Safari(text-only)
          for item in clipboardData.items
            if item.type.match /^image\//
              reader = new FileReader()


Prompt:
class Paste
  # Element to receive final events.
  _target: null

  # Actual element to do pasting.
  _container: null

  @mountNonInputable: (nonInputable)->
    paste = new Paste createHiddenEditable().appendTo(nonInputable), nonInputable
    $(nonInputable).on 'click', => paste._container.focus()

    paste._container.on 'focus', => $(nonInputable).addClass 'pastable-focus'
    paste._container.on 'blur', => $(nonInputable).removeClass 'pastable-focus'

  @mountTextarea: (textarea)->
    return @mountContenteditable textarea unless window.ClipboardEvent
    # Firefox only
    paste = new Paste createHiddenEditable().insertBefore(textarea), textarea
    $(textarea).on 'keypress', (ev)=>
      return unless 'v' == String.fromCharCode ev.charCode
      return unless ev.ctrlKey || ev.metaKey
      paste._container.focus()
    $(paste._target).on 'pasteImage', =>
      $(textarea).focus()

Response:
$(paste._target).on 'pasteText', =>
      $(textarea).focus()

    $(textarea).on 'focus', => $(textarea).addClass 'pastable-focus'
    $(textarea).on 'blur', => $(textarea).removeClass 'pastable-focus'

  @mountContenteditable: (contenteditable)->
    paste = new Paste contenteditable, contenteditable

    $(contenteditable).on 'focus', => $(contenteditable).addClass 'pastable-focus'
    $(contenteditable).on 'blur', => $(contenteditable).removeClass 'pastable-focus'

  constructor: (@_container, @_target)->
    @_container = $ @_container
    @_target = $ @_target
    .addClass 'pastable'
    @_container.on 'paste', (ev)=>
      if ev.originalEvent?.clipboardData?
        clipboardData = ev.originalEvent.clipboardData
        if clipboardData.items
          # Chrome & Safari(text-only)
          for item in clipboardData.items
            if item.type.match /^image\//
              reader = new FileReader()


Response:
reader.onload = (event)=>
                @_handleImage event.target.result
              reader.readAsDataURL item.getAsFile()
            if item.type == 'text/plain'
              item.getAsString (string)=>
                @_target.trigger 'pasteText', text: string
        else
          # Firefox
          if clipboardData.types.length
            text = clipboardData.getData 'Text'
            @_target.trigger 'pasteText', text: text
          else
            @_checkImagesInContainer (src)=>
              @_handleImage src
      # IE
      if clipboardData = window.clipboardData
        if (text = clipboardData.getData 'Text')?.length
          @_target.trigger 'pasteText', text: text
        else
          for file in clipboardData.files
            @_handleImage URL.createObjectURL(file)
            @_checkImagesInContainer ->

  _handleImage: (src)->
    loader = new Image()
    loader.onload = =>
      canvas = document.createElement 'canvas'
      canvas.width = loader.width
      canvas.height = loader.height
      ctx = canvas.getContext '2d'
      ctx.drawImage loader, 0, 0, canvas.width, canvas.height
      dataURL = null
      try
        dataURL = canvas.toDataURL 'image/png'
      if dataURL
        @_target.trigger 'pasteImage',
          dataURL: dataURL
          width: loader.width
          height: loader.height
    loader.src = src

  _checkImagesInContainer: (cb)->
    timespan = Math.floor 1000 * Math.random()
    img["_paste_marked_#{timespan}"] = true for img in @_container.find('img')
    setTimeout =>
      for img in @_container.find('img')
        cb img.src unless img["_paste_marked_#{timespan}"]
        $(img).remove()
    , 1


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
reader.onload = (event)=>
                @_handleImage event.target.result
              reader.readAsDataURL item.getAsFile()
            if item.type == 'text/plain'
              item.getAsString (string)=>
                @_target.trigger 'pasteText', text: string
        else
          # Firefox
          if clipboardData.types.length
            text = clipboardData.getData 'Text'
            @_target.trigger 'pasteText', text: text
          else
            @_checkImagesInContainer (src)=>
              @_handleImage src
      # IE
      if clipboardData = window.clipboardData
        if (text = clipboardData.getData 'Text')?.length
          @_target.trigger 'pasteText', text: text
        else
          for file in clipboardData.files
            @_handleImage URL.createObjectURL(file)
            @_checkImagesInContainer ->

  _handleImage: (src)->
    loader = new Image()
    loader.onload = =>
      canvas = document.createElement 'canvas'
      canvas.width = loader.width
      canvas.height = loader.height
      ctx = canvas.getContext '2d'
      ctx.drawImage loader, 0, 0, canvas.width, canvas.height
      dataURL = null
      try
        dataURL = canvas.toDataURL 'image/png'
      if dataURL
        @_target.trigger 'pasteImage',
          dataURL: dataURL
          width: loader.width
          height: loader.height
    loader.src = src

  _checkImagesInContainer: (cb)->
    timespan = Math.floor 1000 * Math.random()
    img["_paste_marked_#{timespan}"] = true for img in @_container.find('img')
    setTimeout =>
      for img in @_container.find('img')
        cb img.src unless img["_paste_marked_#{timespan}"]
        $(img).remove()
    , 1
```

Response:
var clipboardData, file, i, len, ref, ref1, text;

reader.onload = (event) => {
  return this._handleImage(event.target.result);
};

reader.readAsDataURL(item.getAsFile());

if (item.type === 'text/plain') {
  item.getAsString((string) => {
    return this._target.trigger('pasteText', {
      text: string
    });
  });
} else {
  // Firefox
  if (clipboardData.types.length) {
    text = clipboardData.getData('Text');
    this._target.trigger('pasteText', {
      text: text
    });
  } else {
    this._checkImagesInContainer((src) => {
      return this._handleImage(src);
    });
  }
}

// IE
if (clipboardData = window.clipboardData) {
  if ((ref = (text = clipboardData.getData('Text'))) != null ? ref.length : void 0) {
    this._target.trigger('pasteText', {
      text: text
    });
  } else {
    ref1 = clipboardData.files;
    for (i = 0, len = ref1.length; i < len; i++) {
      file = ref1[i];
      this._handleImage(URL.createObjectURL(file));
      this._checkImagesInContainer(function() {});
    }
  }
}

({
  _handleImage: function(src) {
    var loader;
    loader = new Image();
    loader.onload = () => {
      var canvas, ctx, dataURL;
      canvas = document.createElement('canvas');
      canvas.width = loader.width;
      canvas.height = loader.height;
      ctx = canvas.getContext('2d');
      ctx.drawImage(loader, 0, 0, canvas.width, canvas.height);
      dataURL = null;
      try {
        dataURL = canvas.toDataURL('image/png');
      } catch (error) {}
      if (dataURL) {
        return this._target.trigger('pasteImage', {
          dataURL: dataURL,
          width: loader.width,
          height: loader.height
        });
      }
    };
    return loader.src = src;
  },
  _checkImagesInContainer: function(cb) {
    var img, j, len1, ref2, timespan;
    timespan = Math.floor(1000 * Math.random());
    ref2 = this._container.find('img');
    for (j = 0, len1 = ref2.length; j < len1; j++) {
      img = ref2[j];
      img[`_paste_marked_${timespan}`] = true;
    }
    return setTimeout(() => {
      var k, len2, ref3, results;
      ref3 = this._container.find('img');
      results = [];
      for (k = 0, len2 = ref3.length; k < len2; k++) {
        img = ref3[k];
        if (!img[`_paste_marked_${timespan}`]) {
          cb(img.src);
        }
        results.push($(img).remove());
      }
      return results;
    }, 1);
  }
});


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
var clipboardData, file, i, len, ref, ref1, text;

reader.onload = (event) => {
  return this._handleImage(event.target.result);
};

reader.readAsDataURL(item.getAsFile());

if (item.type === 'text/plain') {
  item.getAsString((string) => {
    return this._target.trigger('pasteText', {
      text: string
    });
  });
} else {
  // Firefox
  if (clipboardData.types.length) {
    text = clipboardData.getData('Text');
    this._target.trigger('pasteText', {
      text: text
    });
  } else {
    this._checkImagesInContainer((src) => {
      return this._handleImage(src);
    });
  }
}

// IE
if (clipboardData = window.clipboardData) {
  if ((ref = (text = clipboardData.getData('Text'))) != null ? ref.length : void 0) {
    this._target.trigger('pasteText', {
      text: text
    });
  } else {
    ref1 = clipboardData.files;
    for (i = 0, len = ref1.length; i < len; i++) {
      file = ref1[i];
      this._handleImage(URL.createObjectURL(file));
      this._checkImagesInContainer(function() {});
    }
  }
}

({
  _handleImage: function(src) {
    var loader;
    loader = new Image();
    loader.onload = () => {
      var canvas, ctx, dataURL;
      canvas = document.createElement('canvas');
      canvas.width = loader.width;
      canvas.height = loader.height;
      ctx = canvas.getContext('2d');
      ctx.drawImage(loader, 0, 0, canvas.width, canvas.height);
      dataURL = null;
      try {
        dataURL = canvas.toDataURL('image/png');
      } catch (error) {}
      if (dataURL) {
        return this._target.trigger('pasteImage', {
          dataURL: dataURL,
          width: loader.width,
          height: loader.height
        });
      }
    };
    return loader.src = src;
  },
  _checkImagesInContainer: function(cb) {
    var img, j, len1, ref2, timespan;
    timespan = Math.floor(1000 * Math.random());
    ref2 = this._container.find('img');
    for (j = 0, len1 = ref2.length; j < len1; j++) {
      img = ref2[j];
      img[`_paste_marked_${timespan}`] = true;
    }
    return setTimeout(() => {
      var k, len2, ref3, results;
      ref3 = this._container.find('img');
      results = [];
      for (k = 0, len2 = ref3.length; k < len2; k++) {
        img = ref3[k];
        if (!img[`_paste_marked_${timespan}`]) {
          cb(img.src);
        }
        results.push($(img).remove());
      }
      return results;
    }, 1);
  }
});
```

Response:
reader.onload = (event)=>
                @_handleImage event.target.result
              reader.readAsDataURL item.getAsFile()
            if item.type == 'text/plain'
              item.getAsString (string)=>
                @_target.trigger 'pasteText', text: string
        else
          # Firefox
          if clipboardData.types.length
            text = clipboardData.getData 'Text'
            @_target.trigger 'pasteText', text: text
          else
            @_checkImagesInContainer (src)=>
              @_handleImage src
      # IE
      if clipboardData = window.clipboardData
        if (text = clipboardData.getData 'Text')?.length
          @_target.trigger 'pasteText', text: text
        else
          for file in clipboardData.files
            @_handleImage URL.createObjectURL(file)
            @_checkImagesInContainer ->

  _handleImage: (src)->
    loader = new Image()
    loader.onload = =>
      canvas = document.createElement 'canvas'
      canvas.width = loader.width
      canvas.height = loader.height
      ctx = canvas.getContext '2d'
      ctx.drawImage loader, 0, 0, canvas.width, canvas.height
      dataURL = null
      try
        dataURL = canvas.toDataURL 'image/png'
      if dataURL
        @_target.trigger 'pasteImage',
          dataURL: dataURL
          width: loader.width
          height: loader.height
    loader.src = src

  _checkImagesInContainer: (cb)->
    timespan = Math.floor 1000 * Math.random()
    img["_paste_marked_#{timespan}"] = true for img in @_container.find('img')
    setTimeout =>
      for img in @_container.find('img')
        cb img.src unless img["_paste_marked_#{timespan}"]
        $(img).remove()
    , 1


Prompt:
reader.onload = (event)=>
                @_handleImage event.target.result
              reader.readAsDataURL item.getAsFile()
            if item.type == 'text/plain'
              item.getAsString (string)=>
                @_target.trigger 'pasteText', text: string
        else
          # Firefox
          if clipboardData.types.length
            text = clipboardData.getData 'Text'
            @_target.trigger 'pasteText', text: text
          else
            @_checkImagesInContainer (src)=>
              @_handleImage src
      # IE
      if clipboardData = window.clipboardData
        if (text = clipboardData.getData 'Text')?.length
          @_target.trigger 'pasteText', text: text
        else
          for file in clipboardData.files
            @_handleImage URL.createObjectURL(file)
            @_checkImagesInContainer ->

  _handleImage: (src)->

Response:
loader = new Image()
    loader.onload = =>
      canvas = document.createElement 'canvas'
      canvas.width = loader.width
      canvas.height = loader.height
      ctx = canvas.getContext '2d'
      ctx.drawImage loader, 0, 0, canvas.width, canvas.height
      dataURL = null
      try
        dataURL = canvas.toDataURL 'image/png'
      if dataURL
        @_target.trigger 'pasteImage',
          dataURL: dataURL
          width: loader.width
          height: loader.height
    loader.src = src

  _checkImagesInContainer: (cb)->
    timespan = Math.floor 1000 * Math.random()
    img["_paste_marked_#{timespan}"] = true for img in @_container.find('img')
    setTimeout =>
      for img in @_container.find('img')
        cb img.src unless img["_paste_marked_#{timespan}"]
        $(img).remove()
    , 1


Response:
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    $(element).find('img').each (i, img)->
      getImageData img.src, cb
   ), 1
getImageData = (src, cb)->
  loader = new Image()
  loader.onload = ->
    canvas = document.createElement 'canvas'
    canvas.width = loader.width
    canvas.height = loader.height
    ctx = canvas.getContext '2d'
    ctx.drawImage loader, 0, 0, canvas.width, canvas.height
    dataURL = null
    try
      dataURL = canvas.toDataURL 'image/png'
    catch
    if dataURL
      cb
        dataURL: dataURL
        width: loader.width
        height: loader.height
  loader.src = src

$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1
    position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = (event)=>
              getImageData event.target.result, (data)->
                $(div).trigger 'pasteImage', data
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string
      else


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    $(element).find('img').each (i, img)->
      getImageData img.src, cb
   ), 1
getImageData = (src, cb)->
  loader = new Image()
  loader.onload = ->
    canvas = document.createElement 'canvas'
    canvas.width = loader.width
    canvas.height = loader.height
    ctx = canvas.getContext '2d'
    ctx.drawImage loader, 0, 0, canvas.width, canvas.height
    dataURL = null
    try
      dataURL = canvas.toDataURL 'image/png'
    catch
    if dataURL
      cb
        dataURL: dataURL
        width: loader.width
        height: loader.height
  loader.src = src

$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1
    position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = (event)=>
              getImageData event.target.result, (data)->
                $(div).trigger 'pasteImage', data
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string
      else
```

Response:
var $, getImageData, readImagesFromEditable;

$ = jQuery;

readImagesFromEditable = function(element, cb) {
  return setTimeout((function() {
    return $(element).find('img').each(function(i, img) {
      return getImageData(img.src, cb);
    });
  }), 1);
};

getImageData = function(src, cb) {
  var loader;
  loader = new Image();
  loader.onload = function() {
    var canvas, ctx, dataURL;
    canvas = document.createElement('canvas');
    canvas.width = loader.width;
    canvas.height = loader.height;
    ctx = canvas.getContext('2d');
    ctx.drawImage(loader, 0, 0, canvas.width, canvas.height);
    dataURL = null;
    try {
      dataURL = canvas.toDataURL('image/png');
    } catch (error) {

    }
    if (dataURL) {
      return cb({
        dataURL: dataURL,
        width: loader.width,
        height: loader.height
      });
    }
  };
  return loader.src = src;
};

$.paste = function() {
  var div;
  div = document.createElement('div');
  div.contentEditable = true;
  return $(div).css({
    width: 1,
    height: 1,
    position: 'fixed',
    left: -100,
    overflow: 'hidden'
  // backgroundColor: '#ccc'
  }).on('paste', function(ev) {
    var clipboardData, item, j, len, reader, ref, ref1, results;
    if (((ref = ev.originalEvent) != null ? ref.clipboardData : void 0) != null) {
      clipboardData = ev.originalEvent.clipboardData;
      if (clipboardData.items) { //webkit
        ref1 = clipboardData.items;
        results = [];
        for (j = 0, len = ref1.length; j < len; j++) {
          item = ref1[j];
          if (item.type.match(/^image\//)) {
            reader = new FileReader();
            reader.onload = (event) => {
              return getImageData(event.target.result, function(data) {
                return $(div).trigger('pasteImage', data);
              });
            };
            reader.readAsDataURL(item.getAsFile());
          }
          if (item.type === 'text/plain') {
            results.push(item.getAsString(function(string) {
              return $(div).trigger('pasteText', {
                text: string
              });
            }));
          } else {
            results.push(void 0);
          }
        }
        return results;
      } else {

      }
    }
  });
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
var $, getImageData, readImagesFromEditable;

$ = jQuery;

readImagesFromEditable = function(element, cb) {
  return setTimeout((function() {
    return $(element).find('img').each(function(i, img) {
      return getImageData(img.src, cb);
    });
  }), 1);
};

getImageData = function(src, cb) {
  var loader;
  loader = new Image();
  loader.onload = function() {
    var canvas, ctx, dataURL;
    canvas = document.createElement('canvas');
    canvas.width = loader.width;
    canvas.height = loader.height;
    ctx = canvas.getContext('2d');
    ctx.drawImage(loader, 0, 0, canvas.width, canvas.height);
    dataURL = null;
    try {
      dataURL = canvas.toDataURL('image/png');
    } catch (error) {

    }
    if (dataURL) {
      return cb({
        dataURL: dataURL,
        width: loader.width,
        height: loader.height
      });
    }
  };
  return loader.src = src;
};

$.paste = function() {
  var div;
  div = document.createElement('div');
  div.contentEditable = true;
  return $(div).css({
    width: 1,
    height: 1,
    position: 'fixed',
    left: -100,
    overflow: 'hidden'
  // backgroundColor: '#ccc'
  }).on('paste', function(ev) {
    var clipboardData, item, j, len, reader, ref, ref1, results;
    if (((ref = ev.originalEvent) != null ? ref.clipboardData : void 0) != null) {
      clipboardData = ev.originalEvent.clipboardData;
      if (clipboardData.items) { //webkit
        ref1 = clipboardData.items;
        results = [];
        for (j = 0, len = ref1.length; j < len; j++) {
          item = ref1[j];
          if (item.type.match(/^image\//)) {
            reader = new FileReader();
            reader.onload = (event) => {
              return getImageData(event.target.result, function(data) {
                return $(div).trigger('pasteImage', data);
              });
            };
            reader.readAsDataURL(item.getAsFile());
          }
          if (item.type === 'text/plain') {
            results.push(item.getAsString(function(string) {
              return $(div).trigger('pasteText', {
                text: string
              });
            }));
          } else {
            results.push(void 0);
          }
        }
        return results;
      } else {

      }
    }
  });
};
```

Response:
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    $(element).find('img').each (i, img)->
      getImageData img.src, cb
   ), 1
getImageData = (src, cb)->
  loader = new Image()
  loader.onload = ->
    canvas = document.createElement 'canvas'
    canvas.width = loader.width
    canvas.height = loader.height
    ctx = canvas.getContext '2d'
    ctx.drawImage loader, 0, 0, canvas.width, canvas.height
    dataURL = null
    try
      dataURL = canvas.toDataURL 'image/png'
    catch
    if dataURL
      cb
        dataURL: dataURL
        width: loader.width
        height: loader.height
  loader.src = src

$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1
    position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = (event)=>
              getImageData event.target.result, (data)->
                $(div).trigger 'pasteImage', data
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string
      else


Prompt:
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    $(element).find('img').each (i, img)->
      getImageData img.src, cb
   ), 1
getImageData = (src, cb)->
  loader = new Image()
  loader.onload = ->
    canvas = document.createElement 'canvas'
    canvas.width = loader.width
    canvas.height = loader.height
    ctx = canvas.getContext '2d'
    ctx.drawImage loader, 0, 0, canvas.width, canvas.height
    dataURL = null
    try
      dataURL = canvas.toDataURL 'image/png'
    catch
    if dataURL
      cb
        dataURL: dataURL
        width: loader.width
        height: loader.height
  loader.src = src

Response:
$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1
    position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = (event)=>
              getImageData event.target.result, (data)->
                $(div).trigger 'pasteImage', data
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string
      else


Response:
if clipboardData.types.length
          if (text = clipboardData.getData 'Text')?.length
            $(div).trigger 'pasteText', text: text
        else
          readImagesFromEditable div, (data)->
            $(div).trigger 'pasteImage', data
    if clipboardData = window.clipboardData # ie
      if (text = clipboardData.getData 'Text')?.length
        $(div).trigger 'pasteText', text: text
      else
        readImagesFromEditable div, (data)->
          $(div).trigger 'pasteImage', data

    setTimeout (->
        $(div).html('')
      ), 2
  return $ div


Prompt:
if clipboardData.types.length
          if (text = clipboardData.getData 'Text')?.length
            $(div).trigger 'pasteText', text: text
        else
          readImagesFromEditable div, (data)->
            $(div).trigger 'pasteImage', data
    if clipboardData = window.clipboardData # ie
      if (text = clipboardData.getData 'Text')?.length

Response:
$(div).trigger 'pasteText', text: text
      else
        readImagesFromEditable div, (data)->
          $(div).trigger 'pasteImage', data

    setTimeout (->
        $(div).html('')
      ), 2
  return $ div


Response:
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    console.log $(element).find('img').length
    $(element).find('img').each (i, img)->
      getImageData img.src, cb
   ), 1
getImageData = (src, cb)->
  loader = new Image()
  loader.onload = ->
    canvas = document.createElement 'canvas'
    canvas.width = loader.width
    canvas.height = loader.height
    ctx = canvas.getContext '2d'
    ctx.drawImage loader, 0, 0, canvas.width, canvas.height
    dataURL = null
    try
      dataURL = canvas.toDataURL 'image/png'
    catch
    if dataURL
      cb
        dataURL: dataURL
        width: loader.width
        height: loader.height
  loader.src = src

$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1
    position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = (event)=>
              getImageData event.target.result, (data)->
                $(div).trigger 'pasteImage', data
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    console.log $(element).find('img').length
    $(element).find('img').each (i, img)->
      getImageData img.src, cb
   ), 1
getImageData = (src, cb)->
  loader = new Image()
  loader.onload = ->
    canvas = document.createElement 'canvas'
    canvas.width = loader.width
    canvas.height = loader.height
    ctx = canvas.getContext '2d'
    ctx.drawImage loader, 0, 0, canvas.width, canvas.height
    dataURL = null
    try
      dataURL = canvas.toDataURL 'image/png'
    catch
    if dataURL
      cb
        dataURL: dataURL
        width: loader.width
        height: loader.height
  loader.src = src

$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1
    position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = (event)=>
              getImageData event.target.result, (data)->
                $(div).trigger 'pasteImage', data
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string
```

Response:
var $, getImageData, readImagesFromEditable;

$ = jQuery;

readImagesFromEditable = function(element, cb) {
  return setTimeout((function() {
    console.log($(element).find('img').length);
    return $(element).find('img').each(function(i, img) {
      return getImageData(img.src, cb);
    });
  }), 1);
};

getImageData = function(src, cb) {
  var loader;
  loader = new Image();
  loader.onload = function() {
    var canvas, ctx, dataURL;
    canvas = document.createElement('canvas');
    canvas.width = loader.width;
    canvas.height = loader.height;
    ctx = canvas.getContext('2d');
    ctx.drawImage(loader, 0, 0, canvas.width, canvas.height);
    dataURL = null;
    try {
      dataURL = canvas.toDataURL('image/png');
    } catch (error) {

    }
    if (dataURL) {
      return cb({
        dataURL: dataURL,
        width: loader.width,
        height: loader.height
      });
    }
  };
  return loader.src = src;
};

$.paste = function() {
  var div;
  div = document.createElement('div');
  div.contentEditable = true;
  return $(div).css({
    width: 1,
    height: 1,
    position: 'fixed',
    left: -100,
    overflow: 'hidden'
  // backgroundColor: '#ccc'
  }).on('paste', function(ev) {
    var clipboardData, item, j, len, reader, ref, ref1, results;
    if (((ref = ev.originalEvent) != null ? ref.clipboardData : void 0) != null) {
      clipboardData = ev.originalEvent.clipboardData;
      if (clipboardData.items) { //webkit
        ref1 = clipboardData.items;
        results = [];
        for (j = 0, len = ref1.length; j < len; j++) {
          item = ref1[j];
          if (item.type.match(/^image\//)) {
            reader = new FileReader();
            reader.onload = (event) => {
              return getImageData(event.target.result, function(data) {
                return $(div).trigger('pasteImage', data);
              });
            };
            reader.readAsDataURL(item.getAsFile());
          }
          if (item.type === 'text/plain') {
            results.push(item.getAsString(function(string) {
              return $(div).trigger('pasteText', {
                text: string
              });
            }));
          } else {
            results.push(void 0);
          }
        }
        return results;
      }
    }
  });
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
var $, getImageData, readImagesFromEditable;

$ = jQuery;

readImagesFromEditable = function(element, cb) {
  return setTimeout((function() {
    console.log($(element).find('img').length);
    return $(element).find('img').each(function(i, img) {
      return getImageData(img.src, cb);
    });
  }), 1);
};

getImageData = function(src, cb) {
  var loader;
  loader = new Image();
  loader.onload = function() {
    var canvas, ctx, dataURL;
    canvas = document.createElement('canvas');
    canvas.width = loader.width;
    canvas.height = loader.height;
    ctx = canvas.getContext('2d');
    ctx.drawImage(loader, 0, 0, canvas.width, canvas.height);
    dataURL = null;
    try {
      dataURL = canvas.toDataURL('image/png');
    } catch (error) {

    }
    if (dataURL) {
      return cb({
        dataURL: dataURL,
        width: loader.width,
        height: loader.height
      });
    }
  };
  return loader.src = src;
};

$.paste = function() {
  var div;
  div = document.createElement('div');
  div.contentEditable = true;
  return $(div).css({
    width: 1,
    height: 1,
    position: 'fixed',
    left: -100,
    overflow: 'hidden'
  // backgroundColor: '#ccc'
  }).on('paste', function(ev) {
    var clipboardData, item, j, len, reader, ref, ref1, results;
    if (((ref = ev.originalEvent) != null ? ref.clipboardData : void 0) != null) {
      clipboardData = ev.originalEvent.clipboardData;
      if (clipboardData.items) { //webkit
        ref1 = clipboardData.items;
        results = [];
        for (j = 0, len = ref1.length; j < len; j++) {
          item = ref1[j];
          if (item.type.match(/^image\//)) {
            reader = new FileReader();
            reader.onload = (event) => {
              return getImageData(event.target.result, function(data) {
                return $(div).trigger('pasteImage', data);
              });
            };
            reader.readAsDataURL(item.getAsFile());
          }
          if (item.type === 'text/plain') {
            results.push(item.getAsString(function(string) {
              return $(div).trigger('pasteText', {
                text: string
              });
            }));
          } else {
            results.push(void 0);
          }
        }
        return results;
      }
    }
  });
};
```

Response:
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    console.log $(element).find('img').length
    $(element).find('img').each (i, img)->
      getImageData img.src, cb
   ), 1
getImageData = (src, cb)->
  loader = new Image()
  loader.onload = ->
    canvas = document.createElement 'canvas'
    canvas.width = loader.width
    canvas.height = loader.height
    ctx = canvas.getContext '2d'
    ctx.drawImage loader, 0, 0, canvas.width, canvas.height
    dataURL = null
    try
      dataURL = canvas.toDataURL 'image/png'
    catch
    if dataURL
      cb
        dataURL: dataURL
        width: loader.width
        height: loader.height
  loader.src = src

$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1
    position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = (event)=>
              getImageData event.target.result, (data)->
                $(div).trigger 'pasteImage', data
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string


Prompt:
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    console.log $(element).find('img').length
    $(element).find('img').each (i, img)->
      getImageData img.src, cb
   ), 1
getImageData = (src, cb)->
  loader = new Image()
  loader.onload = ->
    canvas = document.createElement 'canvas'
    canvas.width = loader.width
    canvas.height = loader.height
    ctx = canvas.getContext '2d'
    ctx.drawImage loader, 0, 0, canvas.width, canvas.height
    dataURL = null
    try
      dataURL = canvas.toDataURL 'image/png'
    catch
    if dataURL
      cb
        dataURL: dataURL
        width: loader.width
        height: loader.height
  loader.src = src

Response:
$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1
    position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = (event)=>
              getImageData event.target.result, (data)->
                $(div).trigger 'pasteImage', data
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string


Response:
else
        if clipboardData.types.length
          if (text = clipboardData.getData 'Text')?.length
            $(div).trigger 'pasteText', text: text
        else
          readImagesFromEditable div, (data)->
            $(div).trigger 'pasteImage', data
    if clipboardData = window.clipboardData # ie
      if (text = clipboardData.getData 'Text')?.length
        $(div).trigger 'pasteText', text: text
      else
        readImagesFromEditable div, (data)->
          $(div).trigger 'pasteImage', data

    setTimeout (->
        $(div).html('')
      ), 2
  return $ div


Prompt:
else
        if clipboardData.types.length
          if (text = clipboardData.getData 'Text')?.length
            $(div).trigger 'pasteText', text: text
        else
          readImagesFromEditable div, (data)->
            $(div).trigger 'pasteImage', data
    if clipboardData = window.clipboardData # ie
      if (text = clipboardData.getData 'Text')?.length

Response:
$(div).trigger 'pasteText', text: text
      else
        readImagesFromEditable div, (data)->
          $(div).trigger 'pasteImage', data

    setTimeout (->
        $(div).html('')
      ), 2
  return $ div


Response:
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    console.log $(element).find('img').length
    $(element).find('img').each (i, img)->
      loader = new Image()
      loader.onload = ->
        canvas = document.createElement 'canvas'
        canvas.width = loader.width
        canvas.height = loader.height
        ctx = canvas.getContext '2d'
        ctx.drawImage loader, 0, 0, canvas.width, canvas.height
        dataURL = null
        try
          dataURL = canvas.toDataURL 'image/png'
        catch
        cb dataURL if dataURL
      loader.src = img.src
   ), 1
$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1
    position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = =>
              $(div).trigger 'pasteImage', dataURL: event.target.result
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string
      else
        if clipboardData.types.length
          if (text = clipboardData.getData 'Text')?.length
            $(div).trigger 'pasteText', text: text
        else
          readImagesFromEditable div, (dataURL)->
            $(div).trigger 'pasteImage', dataURL: dataURL
    if clipboardData = window.clipboardData # ie


Prompt:
$ = jQuery
readImagesFromEditable = (element, cb)->
  setTimeout (->
    console.log $(element).find('img').length
    $(element).find('img').each (i, img)->
      loader = new Image()
      loader.onload = ->
        canvas = document.createElement 'canvas'
        canvas.width = loader.width
        canvas.height = loader.height
        ctx = canvas.getContext '2d'
        ctx.drawImage loader, 0, 0, canvas.width, canvas.height
        dataURL = null
        try
          dataURL = canvas.toDataURL 'image/png'
        catch
        cb dataURL if dataURL
      loader.src = img.src
   ), 1
$.paste = ->
  div = document.createElement 'div'
  div.contentEditable = true
  $(div).css
    width: 1
    height: 1

Response:
position: 'fixed'
    left: -100
    overflow: 'hidden'
    # backgroundColor: '#ccc'
  .on 'paste', (ev)->
    if ev.originalEvent?.clipboardData?
      clipboardData = ev.originalEvent.clipboardData
      if clipboardData.items #webkit
        for item in clipboardData.items
          if item.type.match /^image\//
            reader = new FileReader()
            reader.onload = =>
              $(div).trigger 'pasteImage', dataURL: event.target.result
            reader.readAsDataURL item.getAsFile()
          if item.type == 'text/plain'
            item.getAsString (string)->
              $(div).trigger 'pasteText', text: string
      else
        if clipboardData.types.length
          if (text = clipboardData.getData 'Text')?.length
            $(div).trigger 'pasteText', text: text
        else
          readImagesFromEditable div, (dataURL)->
            $(div).trigger 'pasteImage', dataURL: dataURL
    if clipboardData = window.clipboardData # ie


Response:
if (text = clipboardData.getData 'Text')?.length
        $(div).trigger 'pasteText', text: text
      else
        readImagesFromEditable div, (dataURL)->
          $(div).trigger 'pasteImage', dataURL: dataURL

    setTimeout (->
        $(div).html('')
      ), 2
  return $ div


Prompt:
if (text = clipboardData.getData 'Text')?.length
        $(div).trigger 'pasteText', text: text
      else
        readImagesFromEditable div, (dataURL)->
          $(div).trigger 'pasteImage', dataURL: dataURL

Response:
setTimeout (->
        $(div).html('')
      ), 2
  return $ div


Response:
req.validators =
  _general: (val, key) ->
    if key.match /^_.*id$/i  # _ObjectId type
      return if "#{val}".match /[0-9a-f]{24}/ then true else false
    if key.match /Date$/i  # Date type
      val = Number(val) if val.match /^\d{13}$/
      date = new Date(val)
      return if date.getDate() then true else false
    if key.match /url$/i
      return if validator.isURL(val) then true else false
    return true
  limit: (limit) ->
    limit = parseInt(limit)
    return true if 0 < limit < 100
    return false
  email: (email) ->
    email = email.trim()
    return false unless validator.isEmail(email)
    return true
  mobile: (mobile) ->
    /^\+?[0-9]{1}[0-9]{3,14}$/.test mobile
  emails: (emails) ->
    return false unless toString.call(emails) is '[object Array]'
    return emails.every (email) -> validator.isEmail(email)
  role: (role) ->
    return role in ['owner', 'admin', 'member']
  shortName: (shortName) ->
    return true if shortName.match /^[a-z_-]+$/i
    false
  timezone: (timezone) -> if moment().tz(timezone)._z then true else false

# Custom setter for specific key


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
req.validators =
  _general: (val, key) ->
    if key.match /^_.*id$/i  # _ObjectId type
      return if "#{val}".match /[0-9a-f]{24}/ then true else false
    if key.match /Date$/i  # Date type
      val = Number(val) if val.match /^\d{13}$/
      date = new Date(val)
      return if date.getDate() then true else false
    if key.match /url$/i
      return if validator.isURL(val) then true else false
    return true
  limit: (limit) ->
    limit = parseInt(limit)
    return true if 0 < limit < 100
    return false
  email: (email) ->
    email = email.trim()
    return false unless validator.isEmail(email)
    return true
  mobile: (mobile) ->
    /^\+?[0-9]{1}[0-9]{3,14}$/.test mobile
  emails: (emails) ->
    return false unless toString.call(emails) is '[object Array]'
    return emails.every (email) -> validator.isEmail(email)
  role: (role) ->
    return role in ['owner', 'admin', 'member']
  shortName: (shortName) ->
    return true if shortName.match /^[a-z_-]+$/i
    false
  timezone: (timezone) -> if moment().tz(timezone)._z then true else false

# Custom setter for specific key
```

Response:
req.validators = {
  _general: function(val, key) {
    var date;
    if (key.match(/^_.*id$/i)) { // _ObjectId type
      if (`${val}`.match(/[0-9a-f]{24}/)) {
        return true;
      } else {
        return false;
      }
    }
    if (key.match(/Date$/i)) { // Date type
      if (val.match(/^\d{13}$/)) {
        val = Number(val);
      }
      date = new Date(val);
      if (date.getDate()) {
        return true;
      } else {
        return false;
      }
    }
    if (key.match(/url$/i)) {
      if (validator.isURL(val)) {
        return true;
      } else {
        return false;
      }
    }
    return true;
  },
  limit: function(limit) {
    limit = parseInt(limit);
    if ((0 < limit && limit < 100)) {
      return true;
    }
    return false;
  },
  email: function(email) {
    email = email.trim();
    if (!validator.isEmail(email)) {
      return false;
    }
    return true;
  },
  mobile: function(mobile) {
    return /^\+?[0-9]{1}[0-9]{3,14}$/.test(mobile);
  },
  emails: function(emails) {
    if (toString.call(emails) !== '[object Array]') {
      return false;
    }
    return emails.every(function(email) {
      return validator.isEmail(email);
    });
  },
  role: function(role) {
    return role === 'owner' || role === 'admin' || role === 'member';
  },
  shortName: function(shortName) {
    if (shortName.match(/^[a-z_-]+$/i)) {
      return true;
    }
    return false;
  },
  timezone: function(timezone) {
    if (moment().tz(timezone)._z) {
      return true;
    } else {
      return false;
    }
  }
};

// Custom setter for specific key


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
req.validators = {
  _general: function(val, key) {
    var date;
    if (key.match(/^_.*id$/i)) { // _ObjectId type
      if (`${val}`.match(/[0-9a-f]{24}/)) {
        return true;
      } else {
        return false;
      }
    }
    if (key.match(/Date$/i)) { // Date type
      if (val.match(/^\d{13}$/)) {
        val = Number(val);
      }
      date = new Date(val);
      if (date.getDate()) {
        return true;
      } else {
        return false;
      }
    }
    if (key.match(/url$/i)) {
      if (validator.isURL(val)) {
        return true;
      } else {
        return false;
      }
    }
    return true;
  },
  limit: function(limit) {
    limit = parseInt(limit);
    if ((0 < limit && limit < 100)) {
      return true;
    }
    return false;
  },
  email: function(email) {
    email = email.trim();
    if (!validator.isEmail(email)) {
      return false;
    }
    return true;
  },
  mobile: function(mobile) {
    return /^\+?[0-9]{1}[0-9]{3,14}$/.test(mobile);
  },
  emails: function(emails) {
    if (toString.call(emails) !== '[object Array]') {
      return false;
    }
    return emails.every(function(email) {
      return validator.isEmail(email);
    });
  },
  role: function(role) {
    return role === 'owner' || role === 'admin' || role === 'member';
  },
  shortName: function(shortName) {
    if (shortName.match(/^[a-z_-]+$/i)) {
      return true;
    }
    return false;
  },
  timezone: function(timezone) {
    if (moment().tz(timezone)._z) {
      return true;
    } else {
      return false;
    }
  }
};

// Custom setter for specific key
```

Response:
req.validators =
  _general: (val, key) ->
    if key.match /^_.*id$/i  # _ObjectId type
      return if "#{val}".match /[0-9a-f]{24}/ then true else false
    if key.match /Date$/i  # Date type
      val = Number(val) if val.match /^\d{13}$/
      date = new Date(val)
      return if date.getDate() then true else false
    if key.match /url$/i
      return if validator.isURL(val) then true else false
    return true
  limit: (limit) ->
    limit = parseInt(limit)
    return true if 0 < limit < 100
    return false
  email: (email) ->
    email = email.trim()
    return false unless validator.isEmail(email)
    return true
  mobile: (mobile) ->
    /^\+?[0-9]{1}[0-9]{3,14}$/.test mobile
  emails: (emails) ->
    return false unless toString.call(emails) is '[object Array]'
    return emails.every (email) -> validator.isEmail(email)
  role: (role) ->
    return role in ['owner', 'admin', 'member']
  shortName: (shortName) ->
    return true if shortName.match /^[a-z_-]+$/i
    false
  timezone: (timezone) -> if moment().tz(timezone)._z then true else false

# Custom setter for specific key


Prompt:
req.validators =
  _general: (val, key) ->
    if key.match /^_.*id$/i  # _ObjectId type
      return if "#{val}".match /[0-9a-f]{24}/ then true else false
    if key.match /Date$/i  # Date type
      val = Number(val) if val.match /^\d{13}$/
      date = new Date(val)
      return if date.getDate() then true else false
    if key.match /url$/i
      return if validator.isURL(val) then true else false
    return true
  limit: (limit) ->
    limit = parseInt(limit)
    return true if 0 < limit < 100
    return false
  email: (email) ->

Response:
email = email.trim()
    return false unless validator.isEmail(email)
    return true
  mobile: (mobile) ->
    /^\+?[0-9]{1}[0-9]{3,14}$/.test mobile
  emails: (emails) ->
    return false unless toString.call(emails) is '[object Array]'
    return emails.every (email) -> validator.isEmail(email)
  role: (role) ->
    return role in ['owner', 'admin', 'member']
  shortName: (shortName) ->
    return true if shortName.match /^[a-z_-]+$/i
    false
  timezone: (timezone) -> if moment().tz(timezone)._z then true else false

# Custom setter for specific key


Response:
req.setters =
  _tagIds: (_tagIds) -> _.uniq _tagIds
  limit: (limit) -> Number(limit)


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
req.setters =
  _tagIds: (_tagIds) -> _.uniq _tagIds
  limit: (limit) -> Number(limit)
```

Response:
req.setters = {
  _tagIds: function(_tagIds) {
    return _.uniq(_tagIds);
  },
  limit: function(limit) {
    return Number(limit);
  }
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
req.setters = {
  _tagIds: function(_tagIds) {
    return _.uniq(_tagIds);
  },
  limit: function(limit) {
    return Number(limit);
  }
};
```

Response:
req.setters =
  _tagIds: (_tagIds) -> _.uniq _tagIds
  limit: (limit) -> Number(limit)


Response:
_ = require "underscore"
Dataflow = require "../Dataflow/Dataflow"

module.exports = spread = (start, end, increment=1) ->
  if _.isArray(start)
    return new Dataflow.Spread(start)

  if increment == 0
    throw "Spread increment cannot be 0"
  if !_.isFinite(increment)
    throw "Spread increment must be finite"

  n = (end - start) / increment
  array = (start + increment * i for i in [0 ... n])
  return new Dataflow.Spread(array)


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
_ = require "underscore"
Dataflow = require "../Dataflow/Dataflow"

module.exports = spread = (start, end, increment=1) ->
  if _.isArray(start)
    return new Dataflow.Spread(start)

  if increment == 0
    throw "Spread increment cannot be 0"
  if !_.isFinite(increment)
    throw "Spread increment must be finite"

  n = (end - start) / increment
  array = (start + increment * i for i in [0 ... n])
  return new Dataflow.Spread(array)
```

Response:
var Dataflow, _, spread;

_ = require("underscore");

Dataflow = require("../Dataflow/Dataflow");

module.exports = spread = function(start, end, increment = 1) {
  var array, i, n;
  if (_.isArray(start)) {
    return new Dataflow.Spread(start);
  }
  if (increment === 0) {
    throw "Spread increment cannot be 0";
  }
  if (!_.isFinite(increment)) {
    throw "Spread increment must be finite";
  }
  n = (end - start) / increment;
  array = (function() {
    var j, ref, results;
    results = [];
    for (i = j = 0, ref = n; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ? ++j : --j) {
      results.push(start + increment * i);
    }
    return results;
  })();
  return new Dataflow.Spread(array);
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
var Dataflow, _, spread;

_ = require("underscore");

Dataflow = require("../Dataflow/Dataflow");

module.exports = spread = function(start, end, increment = 1) {
  var array, i, n;
  if (_.isArray(start)) {
    return new Dataflow.Spread(start);
  }
  if (increment === 0) {
    throw "Spread increment cannot be 0";
  }
  if (!_.isFinite(increment)) {
    throw "Spread increment must be finite";
  }
  n = (end - start) / increment;
  array = (function() {
    var j, ref, results;
    results = [];
    for (i = j = 0, ref = n; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ? ++j : --j) {
      results.push(start + increment * i);
    }
    return results;
  })();
  return new Dataflow.Spread(array);
};
```

Response:
_ = require "underscore"
Dataflow = require "../Dataflow/Dataflow"

module.exports = spread = (start, end, increment=1) ->
  if _.isArray(start)
    return new Dataflow.Spread(start)

  if increment == 0
    throw "Spread increment cannot be 0"
  if !_.isFinite(increment)
    throw "Spread increment must be finite"

  n = (end - start) / increment
  array = (start + increment * i for i in [0 ... n])
  return new Dataflow.Spread(array)


Prompt:
_ = require "underscore"
Dataflow = require "../Dataflow/Dataflow"

module.exports = spread = (start, end, increment=1) ->
  if _.isArray(start)
    return new Dataflow.Spread(start)

Response:
if increment == 0
    throw "Spread increment cannot be 0"
  if !_.isFinite(increment)
    throw "Spread increment must be finite"

  n = (end - start) / increment
  array = (start + increment * i for i in [0 ... n])
  return new Dataflow.Spread(array)


Response:
{LocalStorage} = require('../')

exports.SameDirectoryTwiceTest =

  theTest: (test) ->
    localStorage1 = new LocalStorage('./scratch10')
    localStorage2 = new LocalStorage('./scratch10')

    localStorage1.setItem("key1", "value1")

    test.equal(localStorage1.getItem('key1'), localStorage2.getItem('key1'))

    localStorage1._deleteLocation()
    test.done()


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
{LocalStorage} = require('../')

exports.SameDirectoryTwiceTest =

  theTest: (test) ->
    localStorage1 = new LocalStorage('./scratch10')
    localStorage2 = new LocalStorage('./scratch10')

    localStorage1.setItem("key1", "value1")

    test.equal(localStorage1.getItem('key1'), localStorage2.getItem('key1'))

    localStorage1._deleteLocation()
    test.done()
```

Response:
var LocalStorage;

({LocalStorage} = require('../'));

exports.SameDirectoryTwiceTest = {
  theTest: function(test) {
    var localStorage1, localStorage2;
    localStorage1 = new LocalStorage('./scratch10');
    localStorage2 = new LocalStorage('./scratch10');
    localStorage1.setItem("key1", "value1");
    test.equal(localStorage1.getItem('key1'), localStorage2.getItem('key1'));
    localStorage1._deleteLocation();
    return test.done();
  }
};


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
var LocalStorage;

({LocalStorage} = require('../'));

exports.SameDirectoryTwiceTest = {
  theTest: function(test) {
    var localStorage1, localStorage2;
    localStorage1 = new LocalStorage('./scratch10');
    localStorage2 = new LocalStorage('./scratch10');
    localStorage1.setItem("key1", "value1");
    test.equal(localStorage1.getItem('key1'), localStorage2.getItem('key1'));
    localStorage1._deleteLocation();
    return test.done();
  }
};
```

Response:
{LocalStorage} = require('../')

exports.SameDirectoryTwiceTest =

  theTest: (test) ->
    localStorage1 = new LocalStorage('./scratch10')
    localStorage2 = new LocalStorage('./scratch10')

    localStorage1.setItem("key1", "value1")

    test.equal(localStorage1.getItem('key1'), localStorage2.getItem('key1'))

    localStorage1._deleteLocation()
    test.done()


Prompt:
{LocalStorage} = require('../')

exports.SameDirectoryTwiceTest =

  theTest: (test) ->
    localStorage1 = new LocalStorage('./scratch10')
    localStorage2 = new LocalStorage('./scratch10')

Response:
localStorage1.setItem("key1", "value1")

    test.equal(localStorage1.getItem('key1'), localStorage2.getItem('key1'))

    localStorage1._deleteLocation()
    test.done()


Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    cancel = end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    cancel = end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null
```

Response:
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
*/
"use strict";
Quo.Gestures.add({
  name: "rotation",
  events: ["rotate", "rotating", "rotateLeft", "rotateRight"],
  handler: (function(base) {
    var GAP, ROTATION_LIMIT, _last, _num_rotations, _start, _target, cancel, end, move, start;
    GAP = 5;
    ROTATION_LIMIT = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > ROTATION_LIMIT) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    return cancel = end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
  })(Quo.Gestures)
});


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
*/
"use strict";
Quo.Gestures.add({
  name: "rotation",
  events: ["rotate", "rotating", "rotateLeft", "rotateRight"],
  handler: (function(base) {
    var GAP, ROTATION_LIMIT, _last, _num_rotations, _start, _target, cancel, end, move, start;
    GAP = 5;
    ROTATION_LIMIT = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > ROTATION_LIMIT) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    return cancel = end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
  })(Quo.Gestures)
});
```

Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    cancel = end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null


Prompt:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

Response:
start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    cancel = end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null


Response:
_sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->
      theta = Math.atan2(A.y-B.y, A.x-B.x)
      (if theta < 0 then theta + 2 * Math.PI else theta) * 180 / Math.PI

    _check = (moving) ->
      if moving
        base.trigger _target, "rotating", _last
      else if Math.abs(_last.delta) > GAP
        base.trigger _target, "rotate", _last
        ev = if _last.delta > 0 then "rotateRight" else "rotateLeft"
        base.trigger _target, ev, _last

    start: start
    move: move
    end: end


Prompt:
_sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->
      theta = Math.atan2(A.y-B.y, A.x-B.x)
      (if theta < 0 then theta + 2 * Math.PI else theta) * 180 / Math.PI

    _check = (moving) ->
      if moving

Response:
base.trigger _target, "rotating", _last
      else if Math.abs(_last.delta) > GAP
        base.trigger _target, "rotate", _last
        ev = if _last.delta > 0 then "rotateRight" else "rotateLeft"
        base.trigger _target, ev, _last

    start: start
    move: move
    end: end


Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null
```

Response:
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
*/
"use strict";
Quo.Gestures.add({
  name: "rotation",
  events: ["rotate", "rotating", "rotateLeft", "rotateRight"],
  handler: (function(base) {
    var GAP, ROTATION_LIMIT, _last, _num_rotations, _start, _target, end, move, start;
    GAP = 5;
    ROTATION_LIMIT = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > ROTATION_LIMIT) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    return end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
  })(Quo.Gestures)
});


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
*/
"use strict";
Quo.Gestures.add({
  name: "rotation",
  events: ["rotate", "rotating", "rotateLeft", "rotateRight"],
  handler: (function(base) {
    var GAP, ROTATION_LIMIT, _last, _num_rotations, _start, _target, end, move, start;
    GAP = 5;
    ROTATION_LIMIT = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > ROTATION_LIMIT) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    return end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
  })(Quo.Gestures)
});
```

Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null


Prompt:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

Response:
start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null


Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null
```

Response:
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
*/
"use strict";
Quo.Gestures.add({
  name: "rotation",
  events: ["rotate", "rotating", "rotateLeft", "rotateRight"],
  handler: (function(base) {
    var GAP, ROTATION_LIMIT, _last, _num_rotations, _start, _target, end, move, start;
    GAP = 5;
    ROTATION_LIMIT = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > ROTATION_LIMIT) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    return end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
  })(Quo.Gestures)
});


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
*/
"use strict";
Quo.Gestures.add({
  name: "rotation",
  events: ["rotate", "rotating", "rotateLeft", "rotateRight"],
  handler: (function(base) {
    var GAP, ROTATION_LIMIT, _last, _num_rotations, _start, _target, end, move, start;
    GAP = 5;
    ROTATION_LIMIT = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > ROTATION_LIMIT) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    return end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
  })(Quo.Gestures)
});
```

Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null


Prompt:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@namespace Quo.Gestures
@class Rotation

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : ["rotate", "rotating", "rotateLeft", "rotateRight"]

  handler : do (base = Quo.Gestures) ->
    GAP = 5
    ROTATION_LIMIT = 20

    _target = null
    _num_rotations = 0
    _start = null
    _last = null

Response:
start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > ROTATION_LIMIT
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null


Response:
_sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->
      theta = Math.atan2(A.y-B.y, A.x-B.x)
      (if theta < 0 then theta + 2 * Math.PI else theta) * 180 / Math.PI

    _check = (moving) ->
      if moving then base.trigger _target, "rotating", _last
      else if Math.abs(_last.delta) > GAP
        base.trigger _target, "rotate", _last
        ev = if _last.delta > 0 then "rotateRight" else "rotateLeft"
        base.trigger _target, ev, _last

    start: start
    move: move
    end: end


Prompt:
_sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->
      theta = Math.atan2(A.y-B.y, A.x-B.x)
      (if theta < 0 then theta + 2 * Math.PI else theta) * 180 / Math.PI

    _check = (moving) ->
      if moving then base.trigger _target, "rotating", _last

Response:
else if Math.abs(_last.delta) > GAP
        base.trigger _target, "rotate", _last
        ev = if _last.delta > 0 then "rotateRight" else "rotateLeft"
        base.trigger _target, ev, _last

    start: start
    move: move
    end: end


Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : "rotate,rotating,rotateLeft,rotateRight".split(",")
  handler : do (gm = Quo.Gestures) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->


Prompt:
Convert this CoffeeScript to JavaScript.
```coffeescript
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : "rotate,rotating,rotateLeft,rotateRight".split(",")
  handler : do (gm = Quo.Gestures) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->
```

Response:
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
*/
"use strict";
Quo.Gestures.add({
  name: "rotation",
  events: "rotate,rotating,rotateLeft,rotateRight".split(","),
  handler: (function(gm) {
    var IMPOSIBLE_ROTATION_FACTOR, TRIGGER_ANGLE, _last, _num_rotations, _rotation, _sign, _start, _target, end, move, start;
    TRIGGER_ANGLE = 5;
    IMPOSIBLE_ROTATION_FACTOR = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
    _sign = function(num) {
      if (num < 0) {
        return -1;
      } else {
        return 1;
      }
    };
    return _rotation = function(A, B) {};
  })(Quo.Gestures)
});


Prompt:
Convert this JavaScript to CoffeeScript.
```javascript
/*
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
*/
"use strict";
Quo.Gestures.add({
  name: "rotation",
  events: "rotate,rotating,rotateLeft,rotateRight".split(","),
  handler: (function(gm) {
    var IMPOSIBLE_ROTATION_FACTOR, TRIGGER_ANGLE, _last, _num_rotations, _rotation, _sign, _start, _target, end, move, start;
    TRIGGER_ANGLE = 5;
    IMPOSIBLE_ROTATION_FACTOR = 20;
    _target = null;
    _num_rotations = 0;
    _start = null;
    _last = null;
    start = function(target, data) {
      if (data.length === 2) {
        _target = target;
        _num_rotations = 0;
        return _start = _rotation(data[0], data[1]);
      }
    };
    move = function(target, data) {
      var delta;
      if (_start && data.length === 2) {
        delta = _rotation(data[0], data[1]) - _start;
        if (_last && Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR) {
          delta += 360 * _sign(_last.delta);
        }
        if (Math.abs(delta) > 360) {
          _num_rotations++;
          delta -= 360 * _sign(_last.delta);
        }
        _last = {
          touches: data,
          delta: delta,
          rotationsCount: _num_rotations
        };
        return _check(true);
      }
    };
    end = function(target, data) {
      if (_start && _last) {
        _check(false);
        _target = null;
        _num_rotations = 0;
        _start = null;
        _last = null;
        return _start = null;
      }
    };
    _sign = function(num) {
      if (num < 0) {
        return -1;
      } else {
        return 1;
      }
    };
    return _rotation = function(A, B) {};
  })(Quo.Gestures)
});
```

Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : "rotate,rotating,rotateLeft,rotateRight".split(",")
  handler : do (gm = Quo.Gestures) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->


Prompt:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.Gestures.add
  name    : "rotation"
  events  : "rotate,rotating,rotateLeft,rotateRight".split(",")
  handler : do (gm = Quo.Gestures) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0

Response:
_start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->


Response:
theta = Math.atan2(A.y-B.y, A.x-B.x)
      (if theta < 0 then theta + 2 * Math.PI else theta) * 180 / Math.PI

    _check = (is_moving) ->
      if is_moving then gm.trigger _target, "rotating", _last
      else if Math.abs(_last.delta) > TRIGGER_ANGLE
        gm.trigger _target, "rotate", _last
        ev = if _last.delta > 0 then "rotateRight" else "rotateLeft"
        gm.trigger _target, ev, _last

    start: start
    move: move
    end: end


Prompt:
theta = Math.atan2(A.y-B.y, A.x-B.x)
      (if theta < 0 then theta + 2 * Math.PI else theta) * 180 / Math.PI

    _check = (is_moving) ->
      if is_moving then gm.trigger _target, "rotating", _last
      else if Math.abs(_last.delta) > TRIGGER_ANGLE

Response:
gm.trigger _target, "rotate", _last
        ev = if _last.delta > 0 then "rotateRight" else "rotateLeft"
        gm.trigger _target, ev, _last

    start: start
    move: move
    end: end


Response:
###
Quo Rotation Gestures: rotate, rotating, rotateLeft, rotateRight

@author Ignacio Olalde Ramos <ina@tapquo.com> || @piniphone
###
"use strict"

Quo.gesture.add
  name    : "rotation"
  events  : "rotate,rotating,rotateLeft,rotateRight".split(",")
  handler : do (gm = Quo.gesture) ->

    TRIGGER_ANGLE             = 5
    IMPOSIBLE_ROTATION_FACTOR = 20

    _target         = null
    _num_rotations  = 0
    _start          = null
    _last           = null

    start = (target, data) ->
      if data.length is 2
        _target = target
        _num_rotations = 0
        _start = _rotation(data[0], data[1])

    move = (target, data) ->
      if _start and data.length is 2
        delta = _rotation(data[0], data[1]) - _start
        if _last and Math.abs(_last.delta - delta) > IMPOSIBLE_ROTATION_FACTOR
          delta += (360 * _sign(_last.delta))
        if Math.abs(delta) > 360
          _num_rotations++
          delta -= (360 * _sign(_last.delta))
        _last = {touches: data, delta: delta, rotationsCount: _num_rotations}
        _check(true)

    end = (target, data) ->
      if _start and _last
        _check(false)
        _target = null
        _num_rotations = 0
        _start = null
        _last = null
        _start = null

    _sign = (num) -> if num < 0 then -1 else 1

    _rotation = (A, B) ->