OpenSencillo  2016.106
Long live the simplicity of PHP
 All Data Structures Namespaces Files Functions Pages
main.js
1 (function (factory) {
2  if (typeof define === 'function' && define.amd) {
3  define(['jquery'], factory);
4  } else if (typeof exports === 'object') {
5  // Node / CommonJS
6  factory(require('jquery'));
7  } else {
8  factory(jQuery);
9  }
10 })(function ($) {
11 
12  'use strict';
13 
14  var console = window.console || { log: function () {} };
15 
16  function CropAvatar($element) {
17  this.$container = $element;
18 
19  this.$avatarView = this.$container.find('.avatar-view');
20  this.$avatar = this.$avatarView.find('img');
21  this.$avatarModal = this.$container.find('#avatar-modal');
22  this.$loading = this.$container.find('.loading');
23 
24  this.$avatarForm = this.$avatarModal.find('.avatar-form');
25  this.$avatarUpload = this.$avatarForm.find('.avatar-upload');
26  this.$avatarSrc = this.$avatarForm.find('.avatar-src');
27  this.$avatarData = this.$avatarForm.find('.avatar-data');
28  this.$avatarInput = this.$avatarForm.find('.avatar-input');
29  this.$avatarSave = this.$avatarForm.find('.avatar-save');
30  this.$avatarBtns = this.$avatarForm.find('.avatar-btns');
31 
32  this.$avatarWrapper = this.$avatarModal.find('.avatar-wrapper');
33  this.$avatarPreview = this.$avatarModal.find('.avatar-preview');
34 
35  this.init();
36  console.log(this);
37  }
38 
39  CropAvatar.prototype = {
40  constructor: CropAvatar,
41 
42  support: {
43  fileList: !!$('<input type="file">').prop('files'),
44  blobURLs: !!window.URL && URL.createObjectURL,
45  formData: !!window.FormData
46  },
47 
48  init: function () {
49  this.support.datauri = this.support.fileList && this.support.blobURLs;
50 
51  if (!this.support.formData) {
52  this.initIframe();
53  }
54 
55  this.initTooltip();
56  this.initModal();
57  this.addListener();
58  },
59 
60  addListener: function () {
61  this.$avatarView.on('click', $.proxy(this.click, this));
62  this.$avatarInput.on('change', $.proxy(this.change, this));
63  this.$avatarForm.on('submit', $.proxy(this.submit, this));
64  this.$avatarBtns.on('click', $.proxy(this.rotate, this));
65  },
66 
67  initTooltip: function () {
68  this.$avatarView.tooltip({
69  placement: 'bottom'
70  });
71  },
72 
73  initModal: function () {
74  this.$avatarModal.modal({
75  show: false
76  });
77  },
78 
79  initPreview: function () {
80  var url = this.$avatar.attr('src');
81 
82  this.$avatarPreview.empty().html('<img src="' + url + '">');
83  },
84 
85  initIframe: function () {
86  var target = 'upload-iframe-' + (new Date()).getTime(),
87  $iframe = $('<iframe>').attr({
88  name: target,
89  src: ''
90  }),
91  _this = this;
92 
93  // Ready ifrmae
94  $iframe.one('load', function () {
95 
96  // respond response
97  $iframe.on('load', function () {
98  var data;
99 
100  try {
101  data = $(this).contents().find('body').text();
102  } catch (e) {
103  console.log(e.message);
104  }
105 
106  if (data) {
107  try {
108  data = $.parseJSON(data);
109  } catch (e) {
110  console.log(e.message);
111  }
112 
113  _this.submitDone(data);
114  } else {
115  _this.submitFail('Image upload failed!');
116  }
117 
118  _this.submitEnd();
119 
120  });
121  });
122 
123  this.$iframe = $iframe;
124  this.$avatarForm.attr('target', target).after($iframe.hide());
125  },
126 
127  click: function () {
128  this.$avatarModal.modal('show');
129  this.initPreview();
130  },
131 
132  change: function () {
133  var files,
134  file;
135 
136  if (this.support.datauri) {
137  files = this.$avatarInput.prop('files');
138 
139  if (files.length > 0) {
140  file = files[0];
141 
142  if (this.isImageFile(file)) {
143  if (this.url) {
144  URL.revokeObjectURL(this.url); // Revoke the old one
145  }
146 
147  this.url = URL.createObjectURL(file);
148  this.startCropper();
149  }
150  }
151  } else {
152  file = this.$avatarInput.val();
153 
154  if (this.isImageFile(file)) {
155  this.syncUpload();
156  }
157  }
158  },
159 
160  submit: function () {
161  if (!this.$avatarSrc.val() && !this.$avatarInput.val()) {
162  return false;
163  }
164 
165  if (this.support.formData) {
166  this.ajaxUpload();
167  return false;
168  }
169  },
170 
171  rotate: function (e) {
172  var data;
173 
174  if (this.active) {
175  data = $(e.target).data();
176 
177  if (data.method) {
178  this.$img.cropper(data.method, data.option);
179  }
180  }
181  },
182 
183  isImageFile: function (file) {
184  if (file.type) {
185  return /^image\/\w+$/.test(file.type);
186  } else {
187  return /\.(jpg|jpeg|png|gif)$/.test(file);
188  }
189  },
190 
191  startCropper: function () {
192  var _this = this;
193 
194  if (this.active) {
195  this.$img.cropper('replace', this.url);
196  } else {
197  this.$img = $('<img src="' + this.url + '">');
198  this.$avatarWrapper.empty().html(this.$img);
199  this.$img.cropper({
200  aspectRatio: 1,
201  preview: this.$avatarPreview.selector,
202  crop: function (data) {
203  var json = [
204  '{"x":' + data.x,
205  '"y":' + data.y,
206  '"height":' + data.height,
207  '"width":' + data.width,
208  '"rotate":' + data.rotate + '}'
209  ].join();
210 
211  _this.$avatarData.val(json);
212  }
213  });
214 
215  this.active = true;
216  }
217  },
218 
219  stopCropper: function () {
220  if (this.active) {
221  this.$img.cropper('destroy');
222  this.$img.remove();
223  this.active = false;
224  }
225  },
226 
227  ajaxUpload: function () {
228  var url = this.$avatarForm.attr('action'),
229  data = new FormData(this.$avatarForm[0]),
230  _this = this;
231 
232  $.ajax(url, {
233  type: 'post',
234  data: data,
235  dataType: 'json',
236  processData: false,
237  contentType: false,
238 
239  beforeSend: function () {
240  _this.submitStart();
241  },
242 
243  success: function (data) {
244  _this.submitDone(data);
245  },
246 
247  error: function (XMLHttpRequest, textStatus, errorThrown) {
248  _this.submitFail(textStatus || errorThrown);
249  },
250 
251  complete: function () {
252  _this.submitEnd();
253  }
254  });
255  },
256 
257  syncUpload: function () {
258  this.$avatarSave.click();
259  },
260 
261  submitStart: function () {
262  this.$loading.fadeIn();
263  },
264 
265  submitDone: function (data) {
266  console.log(data);
267 
268  if ($.isPlainObject(data) && data.state === 200) {
269  if (data.result) {
270  this.url = data.result;
271 
272  if (this.support.datauri || this.uploaded) {
273  this.uploaded = false;
274  this.cropDone();
275  } else {
276  this.uploaded = true;
277  this.$avatarSrc.val(this.url);
278  this.startCropper();
279  }
280 
281  this.$avatarInput.val('');
282  } else if (data.message) {
283  this.alert(data.message);
284  }
285  } else {
286  this.alert('Failed to response');
287  }
288  },
289 
290  submitFail: function (msg) {
291  this.alert(msg);
292  },
293 
294  submitEnd: function () {
295  this.$loading.fadeOut();
296  },
297 
298  cropDone: function () {
299  this.$avatarForm.get(0).reset();
300  this.$avatar.attr('src', this.url);
301  this.stopCropper();
302  this.$avatarModal.modal('hide');
303  },
304 
305  alert: function (msg) {
306  var $alert = [
307  '<div class="alert alert-danger avater-alert">',
308  '<button type="button" class="close" data-dismiss="alert">&times;</button>',
309  msg,
310  '</div>'
311  ].join('');
312 
313  this.$avatarUpload.after($alert);
314  }
315  };
316 
317  $(function () {
318  return new CropAvatar($('#crop-avatar'));
319  });
320 
321 });