form.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. (function ($) {
  2. /*
  3. *
  4. * provides feedback form for zammad
  5. *
  6. <button id="feedback-form">Feedback</button>
  7. <script id="zammad_form_script" src="http://localhost:3000/assets/form/form.js"></script>
  8. <script>
  9. $(function() {
  10. $('#feedback-form').ZammadForm({
  11. messageTitle: 'Feedback Form',
  12. messageSubmit: 'Submit',
  13. messageThankYou: 'Thank you for your inquiry! We\'ll contact you soon as possible.',
  14. messageNoConfig: 'Unable to load form config from server. Maybe featrue is disabled.',
  15. showTitle: true,
  16. modal: true,
  17. attributes: [
  18. {
  19. display: 'Name',
  20. name: 'name',
  21. tag: 'input',
  22. type: 'text',
  23. placeholder: 'Your Name',
  24. },
  25. {
  26. display: 'Email',
  27. name: 'email',
  28. tag: 'input',
  29. type: 'email',
  30. placeholder: 'Your Email',
  31. },
  32. {
  33. display: 'Message',
  34. name: 'body',
  35. tag: 'textarea',
  36. placeholder: 'Your Message...',
  37. rows: 7,
  38. },
  39. ]
  40. });
  41. });
  42. </script>
  43. */
  44. var pluginName = 'ZammadForm',
  45. defaults = {
  46. debug: false,
  47. noCSS: false,
  48. showTitle: false,
  49. messageTitle: 'Zammad Form',
  50. messageSubmit: 'Submit',
  51. messageThankYou: 'Thank you for your inquiry! We\'ll contact you soon as possible.',
  52. messageNoConfig: 'Unable to load form config from server. Maybe featrue is disabled.',
  53. attributes: [
  54. {
  55. display: 'Name',
  56. name: 'name',
  57. tag: 'input',
  58. type: 'text',
  59. placeholder: 'Your Name',
  60. },
  61. {
  62. display: 'Email',
  63. name: 'email',
  64. tag: 'input',
  65. type: 'email',
  66. placeholder: 'Your Email',
  67. },
  68. {
  69. display: 'Message',
  70. name: 'body',
  71. tag: 'textarea',
  72. placeholder: 'Your Message...',
  73. rows: 7,
  74. },
  75. ]
  76. };
  77. function Plugin( element, options ) {
  78. this.element = element;
  79. this.$element = $(element)
  80. this.options = $.extend( {}, defaults, options) ;
  81. this._defaults = defaults;
  82. this._name = pluginName;
  83. this._endpoint_config = '/api/v1/form_config'
  84. this._endpoint_submit = '/api/v1/form_submit'
  85. this._script_location = '/assets/form/form.js'
  86. this._css_location = '/assets/form/form.css'
  87. this._src = document.getElementById('zammad_form_script').src
  88. this.css_location = this._src.replace(this._script_location, this._css_location)
  89. this.endpoint_config = this._src.replace(this._script_location, this._endpoint_config)
  90. this.endpoint_submit = this._src.replace(this._script_location, this._endpoint_submit)
  91. this._config = {}
  92. this.init();
  93. }
  94. Plugin.prototype.init = function () {
  95. var _this = this
  96. _this.log('debug', 'init', this._src)
  97. if (!_this.options.noCSS) {
  98. _this.loadCss(_this.css_location)
  99. }
  100. _this.log('debug', 'endpoint_config: ' + _this.endpoint_config)
  101. _this.log('debug', 'endpoint_submit: ' + _this.endpoint_submit)
  102. // load config
  103. $.ajax({
  104. url: _this.endpoint_config,
  105. }).done(function(data) {
  106. _this.log('debug', 'config:', data)
  107. _this._config = data
  108. }).fail(function(jqXHR, textStatus, errorThrown) {
  109. if (jqXHR.status == 401) {
  110. _this.log('error', 'Faild to load form config, feature is disabled!')
  111. }
  112. else {
  113. _this.log('error', 'Faild to load form config!')
  114. }
  115. _this.noConfig()
  116. });
  117. // show form
  118. if (!this.options.modal) {
  119. _this.render()
  120. }
  121. // bind form on call
  122. else {
  123. this.$element.on('click', function (e) {
  124. e.preventDefault()
  125. _this.render()
  126. return true
  127. })
  128. }
  129. }
  130. // load css
  131. Plugin.prototype.loadCss = function(filename) {
  132. if (document.createStyleSheet) {
  133. document.createStyleSheet(filename)
  134. }
  135. else {
  136. $('<link rel="stylesheet" type="text/css" href="' + filename + '" />').appendTo('head')
  137. }
  138. }
  139. // send
  140. Plugin.prototype.submit = function() {
  141. var _this = this
  142. // check min modal open time
  143. if (_this.modalOpenTime) {
  144. var currentTime = new Date().getTime()
  145. var diff = currentTime - _this.modalOpenTime.getTime()
  146. _this.log('debug', 'currentTime', currentTime)
  147. _this.log('debug', 'modalOpenTime', _this.modalOpenTime.getTime())
  148. _this.log('debug', 'diffTime', diff)
  149. if (diff < 1000*8) {
  150. alert('Sorry, you look like an robot!')
  151. return
  152. }
  153. }
  154. $.ajax({
  155. method: 'post',
  156. url: _this.endpoint_submit,
  157. data: _this.getParams(),
  158. }).done(function(data) {
  159. // removed errors
  160. _this.$form.find('.has-error').removeClass('has-error')
  161. // set errors
  162. if (data.errors) {
  163. $.each(data.errors, function( key, value ) {
  164. _this.$form.find('[name=' + key + ']').closest('.form-group').addClass('has-error')
  165. })
  166. return
  167. }
  168. // ticket has been created
  169. _this.thanks()
  170. }).fail(function() {
  171. alert('Faild to submit form!')
  172. });
  173. }
  174. // get params
  175. Plugin.prototype.getParams = function() {
  176. var _this = this,
  177. params = {}
  178. $.each( _this.$form.serializeArray(), function( index, item ) {
  179. params[item.name] = item.value
  180. })
  181. if (!params.title) {
  182. params.title = this.options.messageTitle
  183. }
  184. _this.log('debug', 'params', params)
  185. return params
  186. }
  187. Plugin.prototype.closeModal = function() {
  188. if (this.$modal) {
  189. this.$modal.remove()
  190. }
  191. }
  192. // render form
  193. Plugin.prototype.render = function(e) {
  194. var _this = this
  195. _this.closeModal()
  196. _this.modalOpenTime = new Date()
  197. _this.log('debug', 'modalOpenTime:', _this.modalOpenTime)
  198. var element = '<div class="modal">\
  199. <div class="modal-backdrop js-close"></div>\
  200. <div class="modal-body">\
  201. <form class="zammad-form"></form>\
  202. </div>\
  203. </div>'
  204. if (!this.options.modal) {
  205. element = '<div><form class="zammad-form"></form></div>'
  206. }
  207. var $element = $(element)
  208. var $form = $element.find('form')
  209. if (this.options.showTitle && this.options.messageTitle != '') {
  210. $form.append('<h2>' + this.options.messageTitle + '</h2>')
  211. }
  212. $.each(this.options.attributes, function( index, value ) {
  213. var item = $('<div class="form-group"><label>' + value.display + '</label></div>')
  214. if (value.tag == 'input') {
  215. item.append('<input class="form-control" name="' + value.name + '" type="' + value.type + '" placeholder="' + value.placeholder + '">')
  216. }
  217. else if (value.tag == 'textarea') {
  218. item.append('<textarea class="form-control" name="' + value.name + '" placeholder="' + value.placeholder + '" rows="' + value.rows + '"></textarea>')
  219. }
  220. $form.append(item)
  221. })
  222. $form.append('<button type="submit" class="btn">' + this.options.messageSubmit + '</button')
  223. this.$modal = $element
  224. this.$form = $form
  225. // bind on close
  226. $element.find('.js-close').on('click', function (e) {
  227. e.preventDefault()
  228. _this.closeModal()
  229. return true
  230. })
  231. // bind form submit
  232. $element.on('submit', function (e) {
  233. e.preventDefault()
  234. _this.submit()
  235. return true
  236. })
  237. // show form
  238. if (!this.options.modal) {
  239. _this.$element.html($element)
  240. }
  241. // append modal to body
  242. else {
  243. $('body').append($element)
  244. }
  245. }
  246. // thanks
  247. Plugin.prototype.thanks = function(e) {
  248. var message = $('<div class="js-thankyou">' + this.options.messageThankYou + '</div>')
  249. this.$form.html(message)
  250. }
  251. // unable to load config
  252. Plugin.prototype.noConfig = function(e) {
  253. var message = $('<div class="js-noConfig">' + this.options.messageNoConfig + '</div>')
  254. if (this.$form) {
  255. this.$form.html(message)
  256. }
  257. this.$element.html(message)
  258. }
  259. // log method
  260. Plugin.prototype.log = function() {
  261. var args = Array.prototype.slice.call(arguments)
  262. var level = args.shift()
  263. if (!this.options.debug && level == 'debug') {
  264. return
  265. }
  266. args.unshift(this._name + '||' + level)
  267. console.log.apply(console, args)
  268. var logString = ''
  269. $.each( args, function(index, item) {
  270. logString = logString + ' '
  271. if (typeof item == 'object') {
  272. logString = logString + JSON.stringify(item)
  273. }
  274. else if (item && item.toString) {
  275. logString = logString + item.toString()
  276. }
  277. else {
  278. logString = logString + item
  279. }
  280. })
  281. $('.js-logDisplay').prepend('<div>' + logString + '</div>')
  282. }
  283. $.fn[pluginName] = function ( options ) {
  284. return this.each(function () {
  285. if (!$.data(this, 'plugin_' + pluginName)) {
  286. $.data(this, 'plugin_' + pluginName,
  287. new Plugin( this, options ));
  288. }
  289. });
  290. }
  291. }(jQuery));