summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/gl_crop.js.coffee
blob: 137d025ed260290d83a735bdd59ea3f01d47f6d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
class GitLabCrop
  constructor: (input, opts = {}) ->
    @fileInput = $(input)

    # We should rename to avoid spec to fail
    # Form will submit the proper input filed with a file using FormData
    @fileInput
      .attr('name', "#{@fileInput.attr('name')}-trigger")
      .attr('id', "#{@fileInput.attr('id')}-trigger")

    # Set defaults
    {
      @exportWidth = 200
      @exportHeight = 200
      @cropBoxWidth = 200
      @cropBoxHeight = 200
      @form = @fileInput.parents('form')

      # Required params
      @filename
      @previewImage
      @modalCrop
      @pickImageEl
      @uploadImageBtn
      @modalCropImg
    } = opts

    # Ensure needed elements are jquery objects
    # If selector is provided we will convert them to a jQuery Object
    @filename = @$(@filename)
    @previewImage = @$(@previewImage)
    @pickImageEl = @$(@pickImageEl)

    # Modal elements usually are outside the @form element
    @modalCrop = if _.isString(@modalCrop) then $(@modalCrop) else @modalCrop
    @uploadImageBtn = if _.isString(@uploadImageBtn) then $(@uploadImageBtn) else @uploadImageBtn
    @modalCropImg = if _.isString(@modalCropImg) then $(@modalCropImg) else @modalCropImg

    @cropActionsBtn = @modalCrop.find('[data-method]')

    @bindEvents()

  $: (selector) ->
    $(selector, @form)

  bindEvents: ->
    self = @
    @fileInput.on 'change', (e) ->
      self.onFileInputChange(e, @)

    @pickImageEl.on 'click', @onPickImageClick
    @modalCrop.on 'shown.bs.modal', @onModalShow
    @modalCrop.on 'hidden.bs.modal', @onModalHide
    @uploadImageBtn.on 'click', @onUploadImageBtnClick
    @cropActionsBtn.on 'click', (e) ->
      btn = @
      self.onActionBtnClick(btn)
    @croppedImageBlob = null

  onPickImageClick: =>
    @fileInput.trigger('click')

  onModalShow: =>
    self = @
    @modalCropImg.cropper(
      viewMode: 1
      center: false
      aspectRatio: 1
      modal: true
      scalable: false
      rotatable: false
      zoomable: true
      dragMode: 'move'
      guides: false
      zoomOnTouch: false
      zoomOnWheel: false
      cropBoxMovable: false
      cropBoxResizable: false
      toggleDragModeOnDblclick: false
      built: ->
        container = $(@).cropper 'getContainerData'
        cropBoxWidth = self.cropBoxWidth;
        cropBoxHeight = self.cropBoxHeight;

        $(@).cropper('setCropBoxData',
          width: cropBoxWidth,
          height: cropBoxHeight,
          left: (container.width - cropBoxWidth) / 2,
          top: (container.height - cropBoxHeight) / 2
        )
    )


  onModalHide: =>
    @modalCropImg
      .attr('src', '') # Remove attached image
      .cropper('destroy') # Destroy cropper instance

  onUploadImageBtnClick: (e) =>
    e.preventDefault()
    @setBlob()
    @setPreview()
    @modalCrop.modal('hide')

  onActionBtnClick: (btn) ->
    data = $(btn).data()

    if @modalCropImg.data('cropper') && data.method
      data = $.extend {}, data
      result = @modalCropImg.cropper data.method, data.option

  onFileInputChange: (e, input) ->
    @readFile(input)

  readFile: (input) ->
    self = @
    reader = new FileReader
    reader.onload = ->
      self.modalCropImg.attr('src', reader.result)
      self.modalCrop.modal('show')

    reader.readAsDataURL(input.files[0])

  dataURLtoBlob: (dataURL) ->
    binary = atob(dataURL.split(',')[1])
    array = []
    for v, k in  binary
      array.push(binary.charCodeAt(k))
    new Blob([new Uint8Array(array)], type: 'image/png')

  setPreview: ->
    @previewImage.attr('src', @dataURL)
    filename = @fileInput.val().replace(/^.*[\\\/]/, '')
    @filename.text(filename)

  setBlob: ->
    @dataURL = @modalCropImg.cropper('getCroppedCanvas',
        width: 200
        height: 200
      ).toDataURL('image/png')
    @croppedImageBlob = @dataURLtoBlob(@dataURL)

  getBlob: ->
    @croppedImageBlob

$.fn.glCrop = (opts) ->
  return @.each ->
    $(@).data('glcrop', new GitLabCrop(@, opts))