ace-editable.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /**
  2. Image editable input.
  3. **/
  4. (function ($) {
  5. "use strict";
  6. var Image = function (options) {
  7. this.init('image', options, Image.defaults);
  8. if('on_error' in options.image) {
  9. this.on_error = options.image['on_error'];
  10. delete options.image['on_error']
  11. }
  12. if('on_success' in options.image) {
  13. this.on_success = options.image['on_success'];
  14. delete options.image['on_success']
  15. }
  16. if('max_size' in options.image) {
  17. this.max_size = options.image['max_size'];
  18. delete options.image['max_size']
  19. }
  20. this.initImage(options, Image.defaults);
  21. };
  22. //inherit from Abstract input
  23. $.fn.editableutils.inherit(Image, $.fn.editabletypes.abstractinput);
  24. $.extend(Image.prototype, {
  25. initImage: function(options, defaults) {
  26. this.options.image = $.extend({}, defaults.image, options.image);
  27. this.name = this.options.image.name || 'editable-image-input';
  28. },
  29. /**
  30. Renders input from tpl
  31. @method render()
  32. **/
  33. render: function() {
  34. var self = this;
  35. this.$input = this.$tpl.find('input[type=hidden]:eq(0)');
  36. this.$file = this.$tpl.find('input[type=file]:eq(0)');
  37. this.$file.attr({'name':this.name});
  38. this.$input.attr({'name':this.name+'-hidden'});
  39. this.options.image.allowExt = this.options.image.allowExt || ['jpg', 'jpeg', 'png', 'gif'];
  40. this.options.image.allowMime = this.options.image.allowMime || ['image/jpg', 'image/jpeg', 'image/png', 'image/gif'];
  41. this.options.image.maxSize = self.max_size || this.options.image.maxSize || false;
  42. this.options.image.before_remove = this.options.image.before_remove || function() {
  43. self.$input.val(null);
  44. return true;
  45. }
  46. this.$file.ace_file_input(this.options.image).on('change', function(){
  47. var $rand = (self.$file.val() || self.$file.data('ace_input_files')) ? Math.random() + "" + (new Date()).getTime() : null;
  48. self.$input.val($rand)//set a random value, so that selected file is uploaded each time, even if it's the same file, because inline editable plugin does not update if the value is not changed!
  49. }).closest('.ace-file-input').css({'width':'150px'}).closest('.editable-input').addClass('editable-image');
  50. this.$file
  51. .off('file.error.ace')
  52. .on('file.error.ace', function(e, info) {
  53. if( !self.on_error ) return;
  54. if( info.error_count['ext'] > 0 || info.error_count['mime'] > 0 ) {
  55. //wrong ext or mime?
  56. self.on_error(1);
  57. }
  58. else if( info.error_count['size'] > 0 ) {
  59. //wrong size
  60. self.on_error(2);
  61. }
  62. });
  63. }
  64. });
  65. Image.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
  66. tpl: '<span><input type="hidden" /></span><span><input type="file" /></span>',
  67. inputclass: '',
  68. image:
  69. {
  70. style: 'well',
  71. btn_choose: 'Change Image',
  72. btn_change: null,
  73. no_icon: 'fa fa-picture-o',
  74. thumbnail: 'large'
  75. }
  76. });
  77. $.fn.editabletypes.image = Image;
  78. }(window.jQuery));
  79. //Wysiwyg
  80. (function ($) {
  81. "use strict";
  82. var Wysiwyg = function (options) {
  83. this.init('wysiwyg', options, Wysiwyg.defaults);
  84. //extend wysiwyg manually as $.extend not recursive
  85. this.options.wysiwyg = $.extend({}, Wysiwyg.defaults.wysiwyg, options.wysiwyg);
  86. };
  87. $.fn.editableutils.inherit(Wysiwyg, $.fn.editabletypes.abstractinput);
  88. $.extend(Wysiwyg.prototype, {
  89. render: function () {
  90. this.$editor = this.$input.nextAll('.wysiwyg-editor:eq(0)');
  91. this.$tpl.parent().find('.wysiwyg-editor').show().ace_wysiwyg(
  92. {
  93. toolbar:
  94. [
  95. 'bold',
  96. 'italic',
  97. 'strikethrough',
  98. 'underline',
  99. null,
  100. 'foreColor',
  101. null,
  102. 'insertImage'
  103. ]
  104. }
  105. )
  106. .prev().addClass('wysiwyg-style2')
  107. .closest('.editable-input').addClass('editable-wysiwyg')
  108. .closest('.editable-container').css({'display':'block'});//if display is inline-block, putting large images inside the editor will expand it out of bounding box!
  109. if(this.options.wysiwyg && this.options.wysiwyg.css)
  110. this.$tpl.closest('.editable-wysiwyg').css(this.options.wysiwyg.css);
  111. },
  112. value2html: function(value, element) {
  113. $(element).html(value);
  114. return false;
  115. },
  116. html2value: function(html) {
  117. return html;
  118. },
  119. value2input: function(value) {
  120. this.$editor.html(value);
  121. },
  122. input2value: function() {
  123. return this.$editor.html();
  124. },
  125. activate: function() {
  126. //this.$editor.focus().get(0).setSelectionRange(200,200);
  127. }
  128. });
  129. Wysiwyg.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
  130. tpl: '<input type="hidden" /><div class="wysiwyg-editor"></div>',
  131. inputclass: 'editable-wysiwyg',
  132. wysiwyg: {
  133. }
  134. });
  135. $.fn.editabletypes.wysiwyg = Wysiwyg;
  136. }(window.jQuery));
  137. /**
  138. Spinner editable input.
  139. **/
  140. (function ($) {
  141. "use strict";
  142. var Spinner = function (options) {
  143. this.init('spinner', options, Spinner.defaults);
  144. this.initSpinner(options, Spinner.defaults);
  145. this.nativeUI = false;
  146. try {
  147. var tmp_inp = document.createElement('INPUT');
  148. tmp_inp.type = 'number';
  149. this.nativeUI = tmp_inp.type === 'number' && this.options.spinner.nativeUI === true
  150. } catch(e) {}
  151. };
  152. //inherit from Abstract input
  153. $.fn.editableutils.inherit(Spinner, $.fn.editabletypes.abstractinput);
  154. $.extend(Spinner.prototype, {
  155. initSpinner: function(options, defaults) {
  156. this.options.spinner = $.extend({}, defaults.spinner, options.spinner);
  157. },
  158. /**
  159. Renders input from tpl
  160. @method render()
  161. **/
  162. render: function() {
  163. },
  164. /**
  165. Activates input: sets focus on the first field.
  166. @method activate()
  167. **/
  168. activate: function() {
  169. if(this.$input.is(':visible')) {
  170. this.$input.focus();
  171. $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length);
  172. if(!this.nativeUI) {
  173. var val = parseInt(this.$input.val());
  174. var options = $.extend({value:val}, this.options.spinner);
  175. this.$input.ace_spinner(options);
  176. }
  177. else {
  178. this.$input.get(0).type = 'number';
  179. var options = ['min', 'max', 'step']
  180. for(var o = 0 ; o < options.length; o++) {
  181. if(options[o] in this.options.spinner)
  182. this.$input.attr(options[o] , this.options.spinner[options[o]])
  183. }
  184. }
  185. }
  186. },
  187. /**
  188. Attaches handler to submit form in case of 'showbuttons=false' mode
  189. @method autosubmit()
  190. **/
  191. autosubmit: function() {
  192. this.$input.keydown(function (e) {
  193. if (e.which === 13) {
  194. $(this).closest('form').submit();
  195. }
  196. });
  197. }
  198. });
  199. Spinner.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
  200. tpl: '<input type="text" />',
  201. inputclass: '',
  202. spinner:{
  203. min:0,
  204. max:100,
  205. step:1,
  206. icon_up:'fa fa-plus',
  207. icon_down:'fa fa-minus',
  208. btn_up_class:'btn-success',
  209. btn_down_class:'btn-danger'
  210. }
  211. });
  212. $.fn.editabletypes.spinner = Spinner;
  213. }(window.jQuery));
  214. /**
  215. Slider editable input.
  216. **/
  217. (function ($) {
  218. "use strict";
  219. var Slider = function (options) {
  220. this.init('slider', options, Slider.defaults);
  221. this.initSlider(options, Slider.defaults);
  222. this.nativeUI = false;
  223. try {
  224. var tmp_inp = document.createElement('INPUT');
  225. tmp_inp.type = 'range';
  226. this.nativeUI = tmp_inp.type === 'range' && this.options.slider.nativeUI === true
  227. } catch(e) {}
  228. };
  229. //inherit from Abstract input
  230. $.fn.editableutils.inherit(Slider, $.fn.editabletypes.abstractinput);
  231. $.extend(Slider.prototype, {
  232. initSlider: function(options, defaults) {
  233. this.options.slider = $.extend({}, defaults.slider, options.slider);
  234. },
  235. /**
  236. Renders input from tpl
  237. @method render()
  238. **/
  239. render: function() {
  240. },
  241. /**
  242. Activates input: sets focus on the first field.
  243. @method activate()
  244. **/
  245. activate: function() {
  246. if(this.$input.is(':visible')) {
  247. this.$input.focus();
  248. $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length);
  249. if(!this.nativeUI) {
  250. var self = this;
  251. var val = parseInt(this.$input.val());
  252. var width = this.options.slider.width || 200;
  253. var options = $.extend(this.options.slider , {
  254. value:val,
  255. slide: function( event, ui ) {
  256. var val = parseInt(ui.value);
  257. self.$input.val(val);
  258. if(ui.handle.firstChild == null) {//no tooltips attached to it
  259. $(ui.handle).prepend("<div class='tooltip top in' style='display:none; top:-38px; left:-5px;'><div class='tooltip-arrow'></div><div class='tooltip-inner'></div></div>");
  260. }
  261. $(ui.handle.firstChild).show().children().eq(1).text(val);
  262. }
  263. });
  264. this.$input.parent().addClass('editable-slider').css('width', width+'px').slider(options);
  265. }
  266. else {
  267. this.$input.get(0).type = 'range';
  268. var options = ['min', 'max', 'step']
  269. for(var o = 0 ; o < options.length; o++) {
  270. if(options[o] in this.options.slider) {
  271. this.$input[0][options[o]] = this.options.slider[options[o]]
  272. }
  273. }
  274. var width = this.options.slider.width || 200;
  275. this.$input.parent().addClass('editable-slider').css('width', width+'px');
  276. }
  277. }
  278. },
  279. value2html: function(value, element) {
  280. },
  281. /**
  282. Attaches handler to submit form in case of 'showbuttons=false' mode
  283. @method autosubmit()
  284. **/
  285. autosubmit: function() {
  286. this.$input.keydown(function (e) {
  287. if (e.which === 13) {
  288. $(this).closest('form').submit();
  289. }
  290. });
  291. }
  292. });
  293. Slider.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
  294. tpl: '<input type="text" /><span class="inline ui-slider-green"><span class="slider-display"></span></span>',
  295. inputclass: '',
  296. slider:{
  297. min:1,
  298. max:100,
  299. step:1,
  300. range: "min"
  301. }
  302. });
  303. $.fn.editabletypes.slider = Slider;
  304. }(window.jQuery));
  305. /**
  306. ADate editable input.
  307. **/
  308. (function ($) {
  309. "use strict";
  310. var ADate = function (options) {
  311. this.init('adate', options, ADate.defaults);
  312. this.initDate(options, ADate.defaults);
  313. this.nativeUI = false;
  314. try {
  315. var tmp_inp = document.createElement('INPUT');
  316. tmp_inp.type = 'date';
  317. this.nativeUI = tmp_inp.type === 'date' && this.options.date.nativeUI === true
  318. } catch(e) {}
  319. };
  320. //inherit from Abstract input
  321. $.fn.editableutils.inherit(ADate, $.fn.editabletypes.abstractinput);
  322. $.extend(ADate.prototype, {
  323. initDate: function(options, defaults) {
  324. this.options.date = $.extend({}, defaults.date, options.date);
  325. },
  326. /**
  327. Renders input from tpl
  328. @method render()
  329. **/
  330. render: function() {
  331. this.$input = this.$tpl.find('input.date');
  332. },
  333. /**
  334. Activates input: sets focus on the first field.
  335. @method activate()
  336. **/
  337. activate: function() {
  338. if(this.$input.is(':visible')) {
  339. this.$input.focus();
  340. }
  341. if(!this.nativeUI) {
  342. var inp = this.$input;
  343. this.$input.datepicker(this.options.date)
  344. var picker = inp.data('datepicker');
  345. if(picker) {
  346. inp.on('click', function() {
  347. picker.show();
  348. })
  349. .siblings('.input-group-addon').on('click', function(){
  350. picker.show();
  351. })
  352. }
  353. }
  354. else {
  355. this.$input.get(0).type = 'date';
  356. }
  357. },
  358. /**
  359. Attaches handler to submit form in case of 'showbuttons=false' mode
  360. @method autosubmit()
  361. **/
  362. autosubmit: function() {
  363. this.$input.keydown(function (e) {
  364. if (e.which === 13) {
  365. $(this).closest('form').submit();
  366. }
  367. });
  368. }
  369. });
  370. ADate.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
  371. tpl:'<div class="input-group input-group-compact"><input type="text" class="input-medium date" /><span class="input-group-addon"><i class="fa fa-calendar"></i></span></div>',
  372. date: {
  373. weekStart: 0,
  374. startView: 0,
  375. minViewMode: 0
  376. }
  377. });
  378. $.fn.editabletypes.adate = ADate;
  379. }(window.jQuery));