123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666 |
- (function ($) {
- /*
- *
- * provides feedback form for zammad
- *
- <button id="zammad-feedback-form">Feedback</button>
- <script id="zammad_form_script" src="http://localhost:3000/assets/form/form.js"></script>
- <script>
- $(function() {
- $('#zammad-feedback-form').ZammadForm({
- messageTitle: 'Feedback Form', // optional
- messageSubmit: 'Submit', // optional
- messageThankYou: 'Thank you for your inquiry (#%s)! We\'ll contact you as soon as possible.', // optional
- messageNoConfig: 'Unable to load form config from server. Maybe feature is disabled.', // optional
- showTitle: true,
- lang: 'de', // optional, <html lang="xx"> will be used per default
- modal: true,
- attachmentSupport: false,
- attributes: [
- {
- display: 'Name',
- name: 'name',
- tag: 'input',
- type: 'text',
- placeholder: 'Your Name',
- defaultValue: '',
- },
- {
- display: 'Email',
- name: 'email',
- tag: 'input',
- type: 'email',
- required: true,
- placeholder: 'Your Email',
- defaultValue: function () {return User.email;},
- },
- {
- display: 'Message',
- name: 'body',
- tag: 'textarea',
- required: true,
- placeholder: 'Your Message…',
- defaultValue: '',
- rows: 7,
- },
- {
- display: 'Attachments',
- name: 'file[]',
- tag: 'input',
- type: 'file',
- repeat: 3,
- },
- ]
- });
- });
- </script>
- */
- var pluginName = 'ZammadForm',
- defaults = {
- lang: undefined,
- debug: false,
- noCSS: false,
- prefixCSS: 'zammad-form-',
- showTitle: false,
- messageTitle: 'Zammad Form',
- messageSubmit: 'Submit',
- messageThankYou: 'Thank you for your inquiry! We\'ll contact you as soon as possible.',
- messageNoConfig: 'Unable to load form config from server. Maybe feature is disabled.',
- attachmentSupport: false,
- attributes: [
- {
- display: 'Name',
- name: 'name',
- tag: 'input',
- type: 'text',
- id: 'zammad-form-name',
- required: true,
- placeholder: 'Your Name',
- defaultValue: '',
- },
- {
- display: 'Email',
- name: 'email',
- tag: 'input',
- type: 'email',
- id: 'zammad-form-email',
- required: true,
- placeholder: 'Your Email',
- defaultValue: '',
- },
- {
- display: 'Message',
- name: 'body',
- tag: 'textarea',
- id: 'zammad-form-body',
- required: true,
- placeholder: 'Your Message…',
- defaultValue: '',
- rows: 7,
- },
- ],
- translations: {
- // ZAMMAD_TRANSLATIONS_START
- 'cs': {
- 'Attachments': 'Přílohy',
- 'Email': 'Email',
- 'Message': 'Zpráva',
- 'Name': 'Jméno',
- 'Your Email': 'Váš e-mail',
- 'Your Message…': 'Vaše zpráva…',
- 'Your Name': 'Vaše jméno',
- },
- 'de': {
- 'Attachments': 'Anhänge',
- 'Email': 'E-Mail',
- 'Message': 'Nachricht',
- 'Name': 'Name',
- 'Your Email': 'Ihre E-Mail',
- 'Your Message…': 'Ihre Nachricht…',
- 'Your Name': 'Ihr Name',
- },
- 'es': {
- 'Attachments': 'Adjuntos',
- 'Email': 'Correo electrónico',
- 'Message': 'Mensaje',
- 'Name': 'Nombre',
- 'Your Email': 'Tu correo electrónico',
- 'Your Message…': 'Su mensaje…',
- 'Your Name': 'tu Nombre',
- },
- 'et': {
- 'Attachments': 'Manused',
- 'Email': 'E-post',
- 'Message': 'Teade',
- 'Name': 'Nimi',
- 'Your Email': 'Sinu Meiliaadress',
- 'Your Message…': 'Sinu Teade…',
- 'Your Name': 'Sinu Nimi',
- },
- 'fr': {
- 'Attachments': 'Pièces jointes',
- 'Email': 'E-mail',
- 'Message': 'Message',
- 'Name': 'Nom',
- 'Your Email': 'Votre email',
- 'Your Message…': 'Votre message…',
- 'Your Name': 'Votre nom',
- },
- 'hr': {
- 'Attachments': 'Privitci',
- 'Email': 'E-pošta',
- 'Message': 'Poruka',
- 'Name': 'Ime',
- 'Your Email': 'Vaš e-mail',
- 'Your Message…': 'Vaša poruka…',
- 'Your Name': 'Vaše ime',
- },
- 'hu': {
- 'Attachments': 'Csatolmányok',
- 'Email': 'E-mail',
- 'Message': 'Üzenet',
- 'Name': 'Név',
- 'Your Email': 'Az Ön e-mail címe',
- 'Your Message…': 'Az Ön üzenete…',
- 'Your Name': 'Az Ön neve',
- },
- 'it': {
- 'Attachments': 'Allegati',
- 'Email': 'Email',
- 'Message': 'Messaggio',
- 'Name': 'Nome',
- 'Your Email': 'Il tuo indirizzo e-mail',
- 'Your Message…': 'Il tuo messaggio…',
- 'Your Name': 'Il tuo nome',
- },
- 'lt': {
- 'Attachments': 'Prisegtukai',
- 'Email': 'El. paštas',
- 'Message': 'Žinutė',
- 'Name': 'Vardas',
- 'Your Email': 'Jūsų el. paštas',
- 'Your Message…': 'Jūsų žinutė…',
- 'Your Name': 'Jūsų vardas',
- },
- 'nl': {
- 'Attachments': 'Bijlagen',
- 'Email': 'E-mail',
- 'Message': 'Bericht',
- 'Name': 'Naam',
- 'Your Email': 'Je e-mailadres',
- 'Your Message…': 'Je bericht…',
- 'Your Name': 'Je naam',
- },
- 'pl': {
- 'Attachments': 'Załączniki',
- 'Email': 'E-mail',
- 'Message': 'Wiadomość',
- 'Name': 'Nazwa',
- 'Your Email': 'Adres e-mail',
- 'Your Message…': 'Twoja wiadomość…',
- 'Your Name': 'Imię i nazwisko',
- },
- 'pt-br': {
- 'Attachments': 'Anexos',
- 'Email': 'Email',
- 'Message': 'Mensagem',
- 'Name': 'Nome',
- 'Your Email': 'Seu Email',
- 'Your Message…': 'Sua Mensagem…',
- 'Your Name': 'Seu nome',
- },
- 'ru': {
- 'Attachments': 'Вложения',
- 'Email': 'Электронная почта',
- 'Message': 'Сообщение',
- 'Name': 'Имя',
- 'Your Email': 'Ваша почта',
- 'Your Message…': 'Ваше сообщение…',
- 'Your Name': 'Ваше имя',
- },
- 'sr': {
- 'Attachments': 'Прилози',
- 'Email': 'Имејл',
- 'Message': 'Порука',
- 'Name': 'Назив',
- 'Your Email': 'Ваш имејл',
- 'Your Message…': 'Ваша порука…',
- 'Your Name': 'Ваше име',
- },
- 'sr-latn-rs': {
- 'Attachments': 'Prilozi',
- 'Email': 'Imejl',
- 'Message': 'Poruka',
- 'Name': 'Naziv',
- 'Your Email': 'Vaš imejl',
- 'Your Message…': 'Vaša poruka…',
- 'Your Name': 'Vaše ime',
- },
- 'sv': {
- 'Attachments': 'Bilagor',
- 'Email': 'E-post',
- 'Message': 'Meddelande',
- 'Name': 'Namn',
- 'Your Email': 'Din mejl',
- 'Your Message…': 'Ditt meddelande…',
- 'Your Name': 'Ditt namn',
- },
- 'zh-cn': {
- 'Attachments': '附件',
- 'Email': '邮件地址',
- 'Message': '消息',
- 'Name': '名称',
- 'Your Email': '您的邮件地址',
- 'Your Message…': '',
- 'Your Name': '您的尊姓大名',
- },
- 'zh-tw': {
- 'Attachments': '附件',
- 'Email': '電子郵件',
- 'Message': '訊息',
- 'Name': '名稱',
- 'Your Email': '請留下您的電子郵件地址',
- 'Your Message…': '',
- 'Your Name': '您的尊姓大名',
- },
- // ZAMMAD_TRANSLATIONS_END
- }
- };
- function Plugin(element, options) {
- this.element = element
- this.$element = $(element)
- this._defaults = defaults;
- this._name = pluginName;
- this._endpoint_config = '/api/v1/form_config'
- this._endpoint_submit = '/api/v1/form_submit'
- this._script_location = '/assets/form/form.js'
- this._css_location = '/assets/form/form.css'
- this._src = document.getElementById('zammad_form_script').src
- this.css_location = this._src.replace(this._script_location, this._css_location)
- this.endpoint_config = this._src.replace(this._script_location, this._endpoint_config)
- this.endpoint_submit = this._src.replace(this._script_location, this._endpoint_submit)
- this.options = $.extend(true, {}, defaults, options)
- if (!this.options.lang) {
- this.options.lang = $('html').attr('lang')
- }
- if (this.options.lang) {
- this.options.lang = this.options.lang.replace(/-.+?$/, '')
- this.log('debug', "lang: " + this.options.lang)
- }
- this._config = {}
- this._token = ''
- this.init()
- }
- Plugin.prototype.init = function () {
- var _this = this,
- params = {}
- _this.log('debug', 'init', this._src)
- if (!_this.options.noCSS) {
- _this.loadCss(_this.css_location)
- }
- if (_this.options.attachmentSupport === true || _this.options.attachmentSupport === 'true') {
- var attachment = {
- display: 'Attachments',
- name: 'file[]',
- tag: 'input',
- type: 'file',
- repeat: 1,
- }
- _this.options.attributes.push(attachment)
- }
- if (_this.options.agreementMessage) {
- var agreement = {
- display: _this.options.agreementMessage,
- name: 'agreement',
- tag: 'input',
- type: 'checkbox',
- id: 'zammad-form-agreement',
- required: true,
- defaultValue: '',
- }
- _this.options.attributes.push(agreement)
- }
- _this.log('debug', 'endpoint_config: ' + _this.endpoint_config)
- _this.log('debug', 'endpoint_submit: ' + _this.endpoint_submit)
- // load config
- if (this.options.test) {
- params.test = true
- }
- params.fingerprint = this.fingerprint()
- $.ajax({
- method: 'post',
- url: _this.endpoint_config,
- cache: false,
- processData: true,
- data: params
- }).done(function(data) {
- _this.log('debug', 'config:', data)
- _this._config = data
- }).fail(function(jqXHR, textStatus, errorThrown) {
- if (jqXHR.status == 401) {
- _this.log('error', 'Faild to load form config, wrong authentication data!')
- }
- else if (jqXHR.status == 403) {
- _this.log('error', 'Faild to load form config, feature is disabled or request is wrong!')
- }
- else {
- _this.log('error', 'Faild to load form config!')
- }
- _this.noConfig()
- });
- // show form
- if (!this.options.modal) {
- _this.render()
- }
- // bind form on call
- else {
- this.$element.off('click.zammad-form').on('click.zammad-form', function (e) {
- e.preventDefault()
- _this.render()
- return true
- })
- }
- }
- // load css
- Plugin.prototype.loadCss = function(filename) {
- if (document.createStyleSheet) {
- document.createStyleSheet(filename)
- }
- else {
- $('<link rel="stylesheet" type="text/css" href="' + filename + '" />').appendTo('head')
- }
- }
- // send
- Plugin.prototype.submit = function() {
- var _this = this
- // check min modal open time
- if (_this.modalOpenTime) {
- var currentTime = new Date().getTime()
- var diff = currentTime - _this.modalOpenTime.getTime()
- _this.log('debug', 'currentTime', currentTime)
- _this.log('debug', 'modalOpenTime', _this.modalOpenTime.getTime())
- _this.log('debug', 'diffTime', diff)
- if (diff < 1000*10) {
- alert('Sorry, you look like a robot!')
- return
- }
- }
- // disable form
- _this.$form.find('button').prop('disabled', true)
- $.ajax({
- method: 'post',
- url: _this.endpoint_submit,
- data: _this.getParams(),
- cache: false,
- contentType: false,
- processData: false,
- }).done(function(data) {
- // Remove the errors from the form.
- _this.$form.find('.zammad-form-group--has-error').removeClass('zammad-form-group--has-error')
- // Deprecated code, can be removed in future versions:
- _this.$form.find('.has-error').removeClass('has-error')
- // set errors
- if (data.errors) {
- $.each(data.errors, function( key, value ) {
- _this.$form.find('[name=' + key + ']').closest('.'+ _this.options.prefixCSS +'group').addClass('zammad-form-group--has-error')
- // Deprecated code, can be removed in future versions:
- _this.$form.find('[name=' + key + ']').closest('.form-group').addClass('has-error')
- })
- if (data.errors.token) {
- alert(data.errors.token)
- }
- _this.$form.find('button').prop('disabled', false)
- return
- }
- // ticket has been created
- _this.thanks(data)
- }).fail(function() {
- _this.$form.find('button').prop('disabled', false)
- alert('The form could not be submitted!')
- });
- }
- // get params
- Plugin.prototype.getParams = function() {
- var _this = this
- var formData = new FormData(_this.$form[0])
- /* unfortunaly not working in safari and some IEs - https://developer.mozilla.org/en-US/docs/Web/API/FormData
- if (!formData.has('title')) {
- formData.append('title', this.options.messageTitle)
- }
- */
- if (!_this.$form.find('[name=title]').val()) {
- formData.append('title', this.options.messageTitle)
- }
- if (this.options.test) {
- formData.append('test', true)
- }
- formData.append('token', this._config.token)
- formData.append('fingerprint', this.fingerprint())
- _this.log('debug', 'formData', formData)
- return formData
- }
- Plugin.prototype.closeModal = function() {
- if (this.$modal) {
- this.$modal.remove()
- }
- }
- // render form
- Plugin.prototype.render = function(e) {
- var _this = this
- _this.closeModal()
- _this.modalOpenTime = new Date()
- _this.log('debug', 'modalOpenTime:', _this.modalOpenTime)
- var element = "<div class=\"" + _this.options.prefixCSS + "modal\">\
- <div class=\"" + _this.options.prefixCSS + "modal-backdrop js-zammad-form-modal-backdrop\"></div>\
- <div class=\"" + _this.options.prefixCSS + "modal-body js-zammad-form-modal-body\">\
- <form class=\"zammad-form\"></form>\
- </div>\
- </div>"
- if (!this.options.modal) {
- element = '<div><form class="zammad-form"></form></div>'
- }
- var $element = $(element)
- var $form = $element.find('form')
- if (this.options.showTitle && this.options.messageTitle != '') {
- $form.append('<h2>' + this.options.messageTitle + '</h2>')
- }
- $.each(this.options.attributes, function(index, value) {
- var valueId = _this.options.modal ? value.id + '-modal' : value.id + '-inline'
- var item
- if (value.type == 'checkbox'){
- item = $('<div class="form-group '+ _this.options.prefixCSS +'group"></div>');
- } else {
- // Deprecated class "form-group" can be removed in future versions.
- item = $('<div class="form-group '+ _this.options.prefixCSS +'group"><label for="' + valueId +'"> ' + _this.T(value.display) + '</label></div>');
- }
- var defaultValue = (typeof value.defaultValue === 'function') ? value.defaultValue() : value.defaultValue;
- for (var i=0; i < (value.repeat ? value.repeat : 1); i++) {
- if (value.tag === 'input') {
- if (value.type === 'checkbox'){
- var label = $('<label for="' + valueId + '"><input type="' + value.type + '" name="' + value.name + '" id="' + valueId + '" class="' + _this.options.prefixCSS + 'checkbox" ' + (value.required === true ? ' required' : '') + '>' + _this.T(value.display) + '</label>')
- item.append(label)
- } else {
- // Deprecated class "form-control" can be removed in future versions.
- item.append('<input class="form-control '+ _this.options.prefixCSS +'control" id="' + valueId + '" name="' + value.name + '" type="' + value.type + '" placeholder="' + _this.T(value.placeholder) + '" value="' + (defaultValue || '') + '"' + (value.required === true ? ' required' : '') + '>')
- }
- }
- else if (value.tag == 'textarea') {
- // Deprecated class "form-control" can be removed in future versions.
- item.append('<textarea class="form-control '+ _this.options.prefixCSS +'control" id="' + valueId + '" name="' + value.name + '" placeholder="' + _this.T(value.placeholder) + '" rows="' + value.rows + '"' + (value.required === true ? ' required' : '') + '>' + (defaultValue || '') + '</textarea>')
- }
- }
- $form.append(item)
- })
- $form.append('<button type="submit" class="btn">' + this.options.messageSubmit + '</button')
- this.$modal = $element
- this.$form = $form
- // bind on close
- $element.find('.js-zammad-form-modal-backdrop').off('click.zammad-form').on('click.zammad-form', function (e) {
- e.preventDefault()
- _this.closeModal()
- return true
- })
- // bind form submit
- $element.off('submit.zammad-form').on('submit.zammad-form', function (e) {
- e.preventDefault()
- _this.submit()
- return true
- })
- // show form
- if (!this.options.modal) {
- _this.$element.html($element)
- }
- // append modal to body
- else {
- $('body').append($element)
- }
- }
- // thanks
- Plugin.prototype.thanks = function(data) {
- var thankYou = this.options.messageThankYou
- if (data.ticket && data.ticket.number) {
- thankYou = thankYou.replace('%s', data.ticket.number)
- }
- var message = $('<div class="js-thankyou zammad-form-thankyou">' + thankYou + '</div>')
- this.$form.html(message)
- }
- // unable to load config
- Plugin.prototype.noConfig = function(e) {
- var message = $('<div class="js-noConfig">' + this.options.messageNoConfig + '</div>')
- if (this.$form) {
- this.$form.html(message)
- }
- this.$element.html(message)
- }
- // log method
- Plugin.prototype.log = function() {
- var args = Array.prototype.slice.call(arguments)
- var level = args.shift()
- if (!this.options.debug && level == 'debug') {
- return
- }
- args.unshift(this._name + '||' + level)
- console.log.apply(console, args)
- var logString = ''
- $.each( args, function(index, item) {
- logString = logString + ' '
- if (typeof item == 'object') {
- logString = logString + JSON.stringify(item)
- }
- else if (item && item.toString) {
- logString = logString + item.toString()
- }
- else {
- logString = logString + item
- }
- })
- $('.js-logDisplay').prepend('<div>' + logString + '</div>')
- }
- // translation method
- Plugin.prototype.T = function() {
- var string = arguments[0]
- var items = 2 <= arguments.length ? slice.call(arguments, 1) : []
- if (this.options.lang && this.options.lang !== 'en') {
- if (!this.options.translations[this.options.lang]) {
- this.log('debug', "Translation '" + this.options.lang + "' needed!")
- }
- else {
- translations = this.options.translations[this.options.lang]
- if (!translations[string]) {
- this.log('debug', "Translation needed for '" + this.options.lang + "' " + string + "'")
- }
- string = translations[string] || string
- }
- }
- if (items) {
- for (i = 0, len = items.length; i < len; i++) {
- item = items[i]
- string = string.replace(/%s/, item)
- }
- }
- return string
- }
- Plugin.prototype.fingerprint = function () {
- var canvas = document.createElement('canvas')
- var ctx = canvas.getContext('2d')
- var txt = 'https://zammad.com'
- ctx.textBaseline = 'top'
- ctx.font = '12px \'Arial\''
- ctx.textBaseline = 'alphabetic'
- ctx.fillStyle = '#f60'
- ctx.fillRect(125,1,62,20)
- ctx.fillStyle = '#069'
- ctx.fillText(txt, 2, 15)
- ctx.fillStyle = 'rgba(100, 200, 0, 0.7)'
- ctx.fillText(txt, 4, 17)
- return canvas.toDataURL()
- }
- $.fn[pluginName] = function (options) {
- return this.each(function () {
- var instance = $.data(this, 'plugin_' + pluginName)
- if (instance) {
- instance.$element.empty()
- $.data(this, 'plugin_' + pluginName, undefined)
- }
- $.data(
- this, 'plugin_' + pluginName,
- new Plugin(this, options)
- );
- });
- }
- }(jQuery));
|