### Configure Customer Portal State Names
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/settings/SettingsPortal.html
Allows customization of state names as they appear to customers in the portal. This example iterates through workflows and states to set customer-facing names.
```Smarty
{foreach $workflows as $wf}
{if count($workflows) > 1}
{/if}
{foreach $wf->getAllStates() as $s}
{$name = $s->getOption('customer_portal_name')}
{if empty($name)}
{$name = $s->getName()}
{/if}
{/foreach}
{/foreach}
```
--------------------------------
### Helpdesk History Update
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/backend/BackendSidebar.html
Updates the Helpdesk history if there is existing history data. This is part of the initial setup for the Helpdesk controller.
```javascript
$.wa.helpdesk_history.updateHistory({"history":[]});
```
--------------------------------
### Helpdesk Controller Initialization
Source: https://github.com/webasyst/helpdesk/blob/master/templates/layouts-legacy/Mobile.html
Initializes the Helpdesk controller with necessary configuration options. This includes URLs, user ID, and debugging settings. It also handles initial routing based on the current hash or defaults to the last page.
```javascript
$.wa.helpdesk_controller.init({
url: "{$wa_url|escape:javascript}",
user_id: {$wa->user('id')},
backend_url: "{wa_backend_url()|escape:javascript}",
admin: {$admin|intval},
accountName: "{$wa->accountName(false)|escape:javascript}",
global_admin: {$global_admin|intval},
disable_shared_filters: {$disable_shared_filters|intval},
is_debug: {waSystemConfig::isDebug()|intval},
paginator_type: {json_encode($paginator_type|default:'page')}
});
if (empty($content)) {
if($.wa.helpdesk_controller.getHash()) {
$.wa.helpdesk_controller.dispatch();
} else {
$.wa.helpdesk_controller.lastPage();
}
}
```
--------------------------------
### Initialize Add Fields Menus
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/constructor/Constructor.html
Initializes the menus for adding new fields.
```javascript
function initAddFieldsMenus(menus) { menus.each(function() {
```
--------------------------------
### Checklist Utility Functions
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/requests/RequestsSearch.html
Provides helper functions to get the text of selected items in a checklist and to determine if a checklist is empty.
```javascript
var getChecklistTitle = function(ul) {
var text = ul.find('input:checked').map(function() {
return $(this).closest('label').text().trim();
}).toArray().join(', ');
return text;
};
var isChecklistEmpty = function(ul) {
return !ul.find('input:checked').length;
};
```
--------------------------------
### Initialize Helpdesk Controller
Source: https://github.com/webasyst/helpdesk/blob/master/templates/layouts-legacy/Backend.html
Initializes the Helpdesk controller with configuration options. This is typically called on page load to set up the application's core functionality.
```javascript
$.wa.helpdesk_controller.init({
url: "{$wa_url|escape:javascript}",
user_id: {$wa->user('id')},
backend_url: "{wa_backend_url()|escape:javascript}",
admin: {$admin|intval},
accountName: "{$wa->accountName(false)|escape:javascript}",
global_admin: {$global_admin|intval},
disable_shared_filters: {$disable_shared_filters|intval},
is_debug: {waSystemConfig::isDebug()|intval},
paginator_type: {json_encode($paginator_type|default:'page')}
});
```
--------------------------------
### Get Connector Points by Action
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/settings/SettingsWorkflow.html
Provides a function to retrieve connector points, either for the entire state or for a specific action within the state.
```javascript
state.getConnectors = function(action) { if (!action) { return state.connectors; } return state.actions[action].connectors; };
```
--------------------------------
### Initial FAQ Hash Setting (JavaScript)
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/faq/FaqLayout.html
Sets the initial hash in the URL based on the number of categories and FAQs. If no categories exist and no FAQs exist, it directs to 'new'. Otherwise, it directs to 'category/none'.
```javascript
{if count($categories) <= 0}
{if $faq_count <= 0}
$.wa.helpdesk_controller.setHash('#/faq/new/');
{else}
$.wa.helpdesk_controller.setHash('#/faq/category/none/');
{/if}
{/if}
```
--------------------------------
### Get Intermediate Point for Arrows
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/settings/SettingsWorkflow.html
Calculates the coordinates for an intermediate point used in drawing curved arrows, based on two points and a distance.
```javascript
var getInterPoint = function(p1, p2, distance) { if (!distance) { distance = 20; } var rad = p1.d * Math.PI / 180; return { x: p1.x + distance*Math.cos(rad), y: p1.y - distance*Math.sin(rad) }; };
```
--------------------------------
### Checklist Utility Functions
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/requests/RequestsSearch.html
Provides utility functions for handling checklist elements, including getting the selected text and checking if the checklist is empty.
```javascript
var getChecklistTitle = function(ul) { var text = ul.find('input:checked').map(function() { return $(this).closest('label').text().trim(); }).toArray().join(', '); return text || '[\`select\`]' }; var isChecklistEmpty = function(ul) { return !ul.find('input:checked').length; };
```
--------------------------------
### Navigation Links and Keyboard Shortcuts
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/requests/RequestsInfo.html
Sets up 'Back to', 'prev', and 'next' links for navigating between requests. Includes event listeners for keyboard shortcuts (Ctrl+Left/Right arrow) to switch requests when the page hasn't changed.
```javascript
if ($.wa.helpdesk_controller.lastView && $.wa.helpdesk_controller.currentView !== 'split') {
(function() {
var hpaging = $('#hd-last-view').closest('.h-paging-top-wrapper');
hpaging.data('left', hpaging.offset().left);
hpaging.removeClass('hidden');
var link = $('#hd-last-view');
var hpaging = link.closest('.h-paging-top-wrapper');
if ($.wa.helpdesk_controller.lastView.title) {
link.attr('href', $.wa.helpdesk_controller.lastView.hash || '#/');
link.find('.h-paging-top-title').text($.wa.helpdesk_controller.lastView.title);
}
if ($.wa.helpdesk_controller.lastView.ids) {
var ids = $.wa.helpdesk_controller.lastView.ids;
var i = $.inArray('{$request.id}', ids);
if (i >= 0) {
var paging = hpaging.find('.h-paging-top').show();
ids[i-1] && paging.find('.prev').removeClass('hidden').attr('href', '#/request/'+ids[i-1]);
ids[i+1] && paging.find('.next').removeClass('hidden').attr('href', '#/request/'+ids[i+1]);
paging.find('.index-total').text($.wa.helpdesk_controller.lastView.count);
paging.find('.index-current').text($.wa.helpdesk_controller.lastView.offset + i + 1);
var h;
$(document).on('keyup', h = function(e) {
var t = $(e.target);
if (!t.is('body') && !t.is(document)) {
return;
}
if (pageChanged()) {
$(document).off('keyup', h);
return;
}
if ((e.ctrlKey || e.metaKey) && !(e.altKey || e.shiftKey)) {
var a = null;
if (e.which == 37) { // left arrow
a = paging.find('.prev');
} else if (e.which == 39) { // right arrow
a = paging.find('.next');
}
if (a && a.is(':visible')) {
window.location.hash = a.attr('href');
}
}
});
}
}
})();
}
```
--------------------------------
### Set Placeholder for Action Name
Source: https://github.com/webasyst/helpdesk/blob/master/lib/workflow/templates-legacy/Basic_settings.html
Sets a placeholder attribute for an element if the action ID is not yet defined. This guides the user to enter an action name.
```smarty
{if !strlen($action->getId())}
container.attr('placeholder', '[\`action name\`]');
{/if}
```
--------------------------------
### FAQ JavaScript Initialization and Event Handling
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/faq/FaqLayout.html
Initializes FAQ functionality on page load. It sets up a keydown event listener for the search input to trigger a hash change on Enter key press, and initializes sortable functionality for FAQ categories.
```javascript
$(function() { $('.h-faq-search').keydown(function(e) { if (e.keyCode === 13) { $.wa.setHash('#/faq/search/' + encodeURIComponent($(this).val())); } }); $.helpdesk_faq.initFaqCategoriesDroppable(); $('#h-faq-categories').sortable({ distance: 5, opacity: 0.75, items: 'li.h-category:not(.h-faq-none)', axis: 'y', update: function(event, ui) { var id = $(ui.item).data('categoryId'); var before_id = $(ui.item).next().data('categoryId'); var self = $(this); $.post('?module=faq&action=categoryMove', { id: id, before_id: before_id }, function(r) { if (r.status !== 'ok') { self.sortable('cancel'); } }, 'json'); } }); {if count($categories) <= 0} {if $faq_count <= 0} $.wa.helpdesk_controller.setHash('#/faq/new/'); {else} $.wa.helpdesk_controller.setHash('#/faq/category/none/'); {/if} {/if} });
```
--------------------------------
### Helpdesk Cron Command
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/settings/SettingsCron.html
This is the command to be set up in your web-hosting control panel to automate Helpdesk tasks. Ensure you use the exact command provided.
```bash
{$cron_command}
```
--------------------------------
### Initialize Helpdesk FAQ Editor
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/faq/Faq.html
Initializes a rich text editor for the FAQ answer field with specified buttons, language, and CSRF token. Use this when creating or editing FAQ entries.
```javascript
$.wa.helpdesk_controller.initEditor( $form.find('.h-answer'), { buttons: ['format', 'bold', 'italic', 'underline', 'deleted', 'lists', 'link', 'image', 'horizontalrule'], lang: "{substr($wa->locale(), 0, 2)}", saveButton: $('#hd-source-editor-save'), placeholder: '[ `Write an answer here` ]', _csrf: {waRequest::cookie(' _csrf', '')|json_encode} } );
```
--------------------------------
### Focus on Name Input if Empty
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/faq/Faq.html
Automatically focuses the 'name' input field for FAQ settings if it is currently empty. This improves user experience by guiding the user to enter a name first.
```javascript
var name_input = $('.h-faq-question-settings .h-name');
if (!name_input.val()) {
name_input.focus();
}
```
--------------------------------
### Initialize Editor Form and Dialog
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/editor/EditorState.html
Sets up the editor form, dialog buttons, and handles form submission with AJAX. Includes basic validation and error display.
```javascript
(function() { "use strict"; var is_exists = !!({$data.id|json_encode}); var form = $('#hd-{$uniqid}'); var dialog = form.closest('.dialog'); var delay = 0; var dialog_buttons = dialog.find('.dialog-footer').empty().addClass('flexbox middle'); dialog_buttons.append( $('').click(function() { form.submit(); return false; }) ); dialog_buttons.append($('')); var $submit = dialog_buttons.find(':submit'); form.submit(function() { const loadingSubmit = $.wa.helpers.createLoadingSubmit($submit).show(); $.post(form.attr('action'), form.serialize(), function(r) { loadingSubmit.hide(); r = String(r).trim(); if (r === 'ok') { $.wa.helpdesk_controller.redispatch(); $.wa.dialogHide(); } else if (r) { r = r.replace(new RegExp('
\.+
'), ''); form.parent().html(r); } }); return false; }); {if $errors} {foreach $errors as $field_name => $e} form.find('["name"="{$field_name}"]
```
```javascript
').addClass('state-error').after($('').text("{$e}")); {/foreach} form.on('keyup', 'input.state-error:text,textarea.state-error', function() { $(this).removeClass('state-error').siblings('.state-error-hint').remove(); }); form.on('change', '.state-error', function() { $(this).removeClass('state-error').siblings('.state-error-hint').remove(); }); {/if}
```
--------------------------------
### Date Range Filtering
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/requests/RequestsSearch.html
Processes start and end date inputs for specified fields to create filter parameters. It supports greater than or equal to, less than or equal to, and exact range matching.
```javascript
$.each(['created', 'range_id'], function(i, name) { var start = wrapper.find('input["name="' + name + '"_start"]'); var end = wrapper.find('input["name="' + name + '"_end"]'); var start_val = $.trim(start.val()); var end_val = $.trim(end.val()); if (!start_val && !end_val) { return; } if (start_val && !end_val) { filters.push({ name: name, op: '>=', param: [start_val] }); } else if (!start_val && end_val) { filters.push({ name: name, op: '<=', param: [end_val] }); } else { filters.push({ name: name, op: ':', param: [start_val + '--' + end_val] }); } });
```
--------------------------------
### JavaScript for Helpdesk Form Preview Initialization
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/sources/SourcesFormPreview.html
Initializes the form preview by selecting the form, changing the submit button type to 'button', and replacing the original form with a div to contain its HTML. This prepares the form for preview rendering.
```javascript
$(function() {
var form = $('form.wa-hd-frontend-form');
form.find('input[type=submit]').attr('type', 'button');
var form_id = form.attr('id');
var html = form.html();
form.replaceWith('');
$('#' + form_id).html(html);
});
```
--------------------------------
### Error Class Removal on Input
Source: https://github.com/webasyst/helpdesk/blob/master/lib/sources/templates/customerportal/customerportal.html
Clears the 'error' class and associated error message from an input field when the user starts typing or changes the input. This provides immediate feedback on correction.
```javascript
form.on('keyup change', '.error', function() { $(this).removeClass('error').siblings('.errormsg').remove(); });
```
--------------------------------
### Initialize Request Form Menu and Settings
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/requests/RequestsAdd.html
Initializes the 'select another form' menu and handles the display and submission of request form settings. This code runs when the document is ready.
```javascript
$(function() {
'use strict';
var menu = $('.h-sidebar .h-new-request-forms').clone()
.find('.h-text').text('[\`select another form\`]')
.end()
.css({
width: '',
display: 'inline-block',
fontSize: '0.6em',
marginTop: '2px',
marginLeft: '50px'
}).appendTo('#c-core-content .h-header-block h1');
menu.css($.extend({
position: 'absolute'
}, menu.position()));
menu.find('.h-text').closest('b').after('');
menu.find('.darr').after('');
$.wa.helpdesk_controller.initClickableMenu(menu);
if ($form_id !== 'backend') {
menu.find('.menu-v')
.find('li[data-id="' + $form_id + '"]").hide()
.end()
.find('li.h-new').show()
.end()
.find('li.hr').show();
}
var header_width = $('#c-core-content .h-header-block h1').width();
var header_text_width = $('#c-core-content .h-header-block h1 span').width();
var max_menu_width = Math.max(header_width - header_text_width, 200);
var max_menu_item_width = 0;
menu.find('ul').css({
width: max_menu_width,
maxWidth: max_menu_width
}).show().find('a').each(function() {
max_menu_item_width = Math.max($(this).css({
display: 'inline',
overflowX: 'hidden'
}).width(), max_menu_item_width);
}).end().hide();
var correction = 26;
if (max_menu_item_width + correction < max_menu_width) {
menu.find('ul').css({
width: max_menu_item_width + correction
});
}
if ($form_id === 'backend' && $helpdesk_backend_rights > 1) {
var settings = $('.h-source-settings');
var toggle = $('.h-source-settings-toggle');
toggle.click(function() {
settings.show();
$(this).hide();
menu.hide();
$('.h-form-content').hide();
});
settings.find('.cancel').click(function() {
settings.hide();
toggle.show();
menu.show();
$('.h-form-content').show();
}).end().find('input[type=button]').click(function() {
var form = settings.find('form');
$.post('?module=requests&action=add&form_id=' + $form_id, form.serialize(), function(html) {
var tmp = $('
').html(html);
$('.h-source-settings').html(tmp.find('.h-source-settings').html());
tmp.remove();
if (!$('.h-source-settings .errormsg').length) {
$.wa.helpdesk_controller.redispatch();
}
});
});
}
});
```
--------------------------------
### Initial Focus on Visible Form Fields
Source: https://github.com/webasyst/helpdesk/blob/master/lib/sources/templates/customerportal/customerportal.html
Sets the focus to the first visible input, textarea, or select element in the form when the page loads. This improves usability by guiding the user to the first interactive element.
```javascript
form.find('input:visible,textarea,select').focus();
```
--------------------------------
### Initialize Datepicker for Period Selection
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/requests/RequestsSearch.html
This JavaScript code initializes the datepicker widget for elements with the class 'h-choose-period'. It sets the date format to 'yy-mm-dd' and triggers a change event for both start and end date inputs.
```javascript
$('.h-choose-period').each(function() {
var start_input = $('.h-datepicker:first', this);
var end_input = $('.h-datepicker:last', this);
$('.h-datepicker', this).datepicker({ dateFormat: 'yy-mm-dd' }).change();
});
})();
```
--------------------------------
### FAQ Form Initialization and Event Handling (JavaScript)
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/faq/Faq.html
Initializes the FAQ form, handles navigation back links, and sets up confirmation dialogs for unsaved changes. It also manages the display of frontend URL and comment sections based on checkbox states.
```javascript
var wa_url = '{$wa_url}', wa_app = 'helpdesk'; $(function() { {if $id && !$faq.id} $.wa.setHash('#/faq/new/'); return; {/if} var button = $(':submit'); var updateBackLink = function(href, name) { $('.h-faq-question-settings .h-header-block').show(); $('.h-faq-question-settings .h-prev').attr('href', href).html('← ' + name); }; var hideBackLink = function() { $('.h-faq-question-settings .h-header-block').hide(); }; {if $faq.id} if ($.wa.helpdesk_controller.faq_context && $.wa.helpdesk_controller.faq_context.type === 'search') { var query = $.wa.helpdesk_controller.faq_context.query; updateBackLink('#/faq/search/' + query + '/', query); } else { updateBackLink('#/faq/category/{$category.id}', '{$category.name|escape}'); } {else} if ($.wa.helpdesk_controller.faq_context && $.wa.helpdesk_controller.faq_context.type === 'category') { var category_id = $.wa.helpdesk_controller.faq_context.query; var category_li = $('#h-faq-categories li[data-category-id="' + category_id + '"]'); if (category_li.length) { updateBackLink('#/faq/category/' + (category_id || 'none') + '/', category_li.find('.name').html()); } else { hideBackLink(); } } else { hideBackLink(); } {/if} $('#h-faq-categories') .find('li.selected').removeClass('selected') .end() .find('li[data-category-id="{$category.id}"]').addClass('selected'); $.wa.helpdesk_controller.confirmLeave( function() { return $('.h-faq-question-settings').find(':submit').hasClass('yellow'); }, '[`Unsaved changes will be lost if you leave this page now.`]', '[`Are you sure?`]', function() { return !$('.h-faq-question-settings').is(':visible'); }, 'h-faq' ); $('.h-faq-question-settings').submit(function() { var form = $(this); form.find('.h-answer').waEditor('sync'); form.find('.h-save-loading').show(); form.find('span.error').remove(); form.find('.error').removeClass('error'); form.find('.h-after-save-animation').remove(); $.post(form.attr('action'), form.serialize(), function(r) { $.helpdesk_faq.changeButton(button, true); if (r.status === 'ok') { form.find(':submit').parent().each(function() { $(' '+"[`Saved`]"+'').animate({ opacity: 0 }, 1000, function() { $(this).remove(); }).appendTo($(this)); }); $('.h-delete-faq-question').show(); $('.h-faq-question-settings').find('[name="id"].val(r.data.faq.id); $('.h-faq-question-settings .h-faq-url-link').removeClass('h-disabled'); $.helpdesk_faq.updateCounters(r.data.counters); $('.h-faq-url-link').attr('href', "{$wa->getUrl('/', true)}faq/{$category.url}/" + r.data.faq.url + "/"); {if !$faq.id} $.wa.setHash('#/faq/' + r.data.faq.id + '/'); {/if} } else { $.each(r.errors, function(i, er) { $('input[name="' + er[1] + '"]').addClass('error').parent().append(' ' + er[0] + ''); }); } form.find('.h-save-loading').hide(); }, 'json'); return false; }); $('.h-faq-question-settings').on('click', '.h-faq-url-link', function (e) { $(this).hasClass('h-disabled') && e.preventDefault(); }); $('.h-delete-faq-question').off('click').click(function() { var id = $('.h-faq-question-settings').find('[name="id"]').val(); if (id && confirm('[`Are you sure?`]')) { $.post('?module=faq&action=delete', { id: id }, function(r) { $.wa.setHash('#/faq/category/{if $category.id > 0}{$category.id}{else}none{/if}/'); $.wa.helpdesk_controller.redispatch(); $.helpdesk_faq.updateCounters(r.data.counters); }, 'json'); } }); $('input[type="checkbox"] [name="is_public"]').change(function() { if ($(this).is(':checked')) { $('.h-frontend-url').slideDown(); if (!$('input[name="faq_url"]').val()) { $('.h-frontend-url').addClass('h-disabled'); } } else { $('.h-frontend-url').slideUp(); } // for translit $('input[name="question"]').trigger('keydown'); }); $('input[type="checkbox"] [name="is_backend"]').change(function() { if ($(this).is(':checked')) { $('.h-faq-comment').slideDown(); } else { $('.h-faq-comment').slideUp(); } }); $('select[name=category_id]').change(function() { var el = $(this); var category_id = el.val(); var prev_category_id = el.data('prev_val'); if (category_id == '0') { $('.h-faq-site-visibility').hide(); $('.h-frontend-url').hide(); } else {
```
--------------------------------
### JavaScript for Bulk Actions Initialization
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/backend/BackendBulk.html
Initializes JavaScript for bulk actions, determining selected request IDs and preparing for dialogs or confirmations.
```javascript
(function() { "use strict"; var $header = $('#hd-requests-header'); {if isset($selected_ids)} var grid_wrapper = null; var selected_ids = {json_encode($selected_ids)}; {else} var grid_wrapper = $('#c-core-content').find('.requests-table').parent(); var selected_ids = grid_wrapper.find('tr.selected').map(function() { return $(this).attr('rel'); }).get(); {/if} if (!selected_ids || !selected_ids.length) { return; }
```
--------------------------------
### Initialize Datepickers for Period Selection
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/requests/RequestsSearch.html
Initializes jQuery UI datepicker widgets for start and end date inputs within elements having the class 'h-choose-period'. This is used for selecting date ranges. Ensure jQuery UI is loaded.
```javascript
$('.h-choose-period').each(function() { var start_input = $('.h-datepicker:first', this); var end_input = $('.h-datepicker:last', this); $('.h-datepicker', this).datepicker({ dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true }).change(); }); })();
```
--------------------------------
### Initialize Clickable Menu and Handle Field Selection
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/constructor/Constructor.html
Initializes a clickable menu and handles the selection of request fields. Appends the selected field to the target location and saves the field choice via an AJAX post request. Use this for dynamic field management in the constructor.
```javascript
var menu = $(this);
var place = 'left';
var target = $('.h-fields-location[data-place="' + place + '"]');
$.wa.helpdesk_controller.initClickableMenu(menu);
menu.off('click', '.h-available-fields .h-choose-field').on('click', '.h-available-fields .h-choose-field', function() {
var item = $(this).closest('.h-new-request-field');
var field = item.find('.h-field').clone().show();
target.append(field.show());
menus.find('.h-new-request-field[data-id="' + item.data('id') + '"]').hide();
if (field.data('id') === 'tags') {
initTagsField(field);
}
if (!menu.find('.h-new-request-field:visible').length) {
menu.find('.h-no-available-fields').show();
}
$.post('?module=constructor&action=requestFieldSave', { id: field.data('id'), place: place });
});
```
--------------------------------
### Helpdesk Form JavaScript Initialization
Source: https://github.com/webasyst/helpdesk/blob/master/lib/sources/templates-legacy/form/form_backend.html
Initializes the helpdesk form with CSRF token, form URL, and charset. Includes logic for clearing validation errors and setting up the Redactor rich text editor.
```javascript
(function() { var form = $('#{$uniqid}'); var iframe = $('#{$uniqid}-target'); // Charset and form URL in hidden fields form.find('input.charset').val(document.charset || document.characterSet); var loc; if (window.parent === window) { loc = document.location.toString(); } else { loc = document.referrer; } form.find('input[name="form_url"]').val(loc); // Clear validation errors when user changes corresponding field form.on('change keyup', '.error', function() { $(this).removeClass('error').siblings('.errormsg').remove(); }); var redactor = $('#h-text-redactor'); {if !empty($source.params.fld_text.redactor)} $.Redactor.opts.regexps.linkyoutube = null; redactor.redactor({ minHeight: 250, maxHeight: 250, lang: '{substr($wa->locale(), 0, 2)}', buttons: ['format', 'bold', 'italic', 'underline', 'deleted', 'lists', 'link', 'image', 'horizontalrule'], focus: false {if !empty($source.params.fld_text.placeholder)} ,placeholder: '{$source.params.fld_text.placeholder}' {/if} }); {/if} $('.subfields-placeholder').each(function() { $(this).find('.field').each(function() { var text = $(this).find('>span').text(); $(this).find(':input').attr('placeholder', text); }); }); // Save var rand; form.submit(function() { form.find('.loading').show(); form.find(':submit').attr('disabled', true); {if !empty($source.params.fld_text.redactor)} $('#h-text-textarea').val(redactor.redactor('code.get')); {/if} // catch iframe load event when uploading finishes var r = rand = Math.random(); iframe.one('load', function() { setTimeout(function() { if (r != rand) { return; } form.find('.error').removeClass('error'); form.find('.errormsg').remove(); form.find(':submit').attr('disabled', false); try { var json = iframe.contents().find("body").html(); if (json) { json = eval('('+json+')'); if (json.errors) { // Highlight validation errors for (var fld_name in json.errors) { if (json.errors.hasOwnProperty(fld_name)) { if (fld_name) { var el = form.find('[name="'+fld_name+'"]'); if (el.length) { el.addClass('error').parent().append($('').text(json.errors[fld_name])); continue; } } form.find(':submit').parent().append($('').text(json.errors[fld_name])); } } form.find('.loading').hide(); {if !empty($source.params.fld_captcha)} // Clear captcha field and reload image (function() { var div = form.find('.wa-captcha'); var captcha = div.find('.wa-captcha-img'); captcha.length && captcha.attr('src', captcha.attr('src').replace(/\?.\*$/,'?rid='+Math.random())); div.find('input').val(''); return false; })(); {/if} return; } } } catch (e) { // Security exception: attempt to access data from foreign domain. // Can't do anything about it except this notice. Hopefully everything is OK there.
```
--------------------------------
### Show Action Settings (JavaScript)
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/editor/EditorNewaction.html
Calls the showActionSettings method from the helpdesk controller to display the settings for a new action. This is used when a new action is being created.
```javascript
(function() {
"use strict";
$.wa.helpdesk_controller.showActionSettings(
"{$wf->getId()}",
"{$state->getId()}",
"",
"helpdeskWorkflowBasicAction",
"[\`Save`]",
```
--------------------------------
### Initialize Sticky Element for FAQ Settings
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/faq/Faq.html
Applies sticky behavior to a specified element at the bottom of the FAQ question settings. This ensures the element remains visible or accessible as the user scrolls.
```javascript
$.helpdesk_faq.sticky($('#h-sticky-bottoms'), $('.h-faq-question-settings'));
```
--------------------------------
### Initialize Reply-to-Reply State Change
Source: https://github.com/webasyst/helpdesk/blob/master/lib/sources/templates-legacy/email/email_settings.html
Sets up an event listener for changes in the reply-to-reply state dropdown. It dynamically generates options for the action dropdown based on the selected state.
```javascript
var initRtr = function() {
$('.reply-to-reply-state').unbind('change').change(function() {
var html = '';
var state_id = $(this).val() || '';
/*
```
--------------------------------
### Initialize Editable Form Constructor
Source: https://github.com/webasyst/helpdesk/blob/master/lib/sources/templates-legacy/form/form_settings.html
Sets up the form constructor interface, including calculating label and input widths, and making labels editable.
```javascript
var editableForm = function($el, initial_position) {
var $preview = $el.find('[data-form-constructor="preview"]'),
$form_width = $el.find('[data-form-constructor="form-width"]'),
$available_fields = $el.find('[data-form-constructor="available-fields"]')
.find('[data-fld-id]'),
$caption_place = $el.find('[data-form-constructor="caption-place"]'),
$editable_inputs = $el.find('[data-editable-element="true"]'),
delay = 100;
// Calculates label and inputs width in form constructor
var calcLabelWidth = function (type) {
var $captions = $preview.find('[data-form-constructor="caption"]'),
$labels = $captions.find('label'),
$placeholders = $preview.find('[data-form-constructor="placeholder"]');
$labels.css({
'white-space': 'nowrap',
'width': 'auto'
});
$captions.removeClass('left above none hidden');
$placeholders.removeClass('left above');
var values = $labels.map(function(i, el) {
return parseInt($(el).width());
}).get();
var max_wl_px = Math.max.apply(null, values),
max_wl_p = max_wl_px / (parseInt($preview.width()) / 100) + 1,
max_ml_p = (max_wl_p + 2) > 50 ? 50 : (max_wl_p + 2),
form_edit_place = 0;
if (type === 'above') {
max_wl_p = 100;
max_ml_p = 0;
$captions.addClass('above');
$placeholders.addClass('above');
} else if (type === 'none') {
max_wl_p = max_ml_p = 0;
$captions.addClass('none hidden');
} else {
if (max_wl_px <= 2) {
max_wl_p = max_ml_p = 0;
form_edit_place = 10;
$captions.addClass('none');
}
$captions.addClass('left');
$placeholders.addClass('left');
}
$captions.width((max_wl_p + form_edit_place) + '%');
$preview.find('[data-form-constructor="captions-width"]').val(max_wl_p);
$placeholders.css('margin-left', (max_ml_p + form_edit_place) + '%');
$preview.find('[data-form-constructor="inputs-marginleft"]').val(max_ml_p);
$labels.css({
'white-space': 'normal',
'width': '100%'
});
};
// Calculates form width
var calcFormWidth = function (w) {
w = w < 200 ? 200 : w;
w = w > 600 ? 600 : w;
$(this).val(w);
$preview.animate({
width: w
}, delay, function() {
calcLabelWidth($caption_place.find(':checked').val());
});
};
// Makes labels editable
var editableInput = function (el) {
var $el = $(el),
$input = $el.next(),
$icon = $el.prev();
var switchEls = function() {
$el.addClass('hidden');
$input.removeClass('hidden').focus();
$el.parents('.caption.left').width('48%')
.siblings('.placeholder').css('margin-left', '50%');
};
$el.on('click', function(e) {
switchEls();
});
$icon.on('click', function() {
switchEls();
});
$input.on('blur', function() {
$input.addClass('hidden');
if ($el.hasClass('editable_button')) {
$el.val($input.val()).removeClass('hidden');
} else {
$el.text($input.val()).removeClass('hidden');
}
calcLabelWidth($caption_place.find(':checked').val());
});
$input.on('keydown', function(e) {
var code = e.keyCode || e.which;
switch (code) {
case 13: //on enter, esc
```
--------------------------------
### Initialize EditorState Form and Dialog
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/editor/EditorState.html
Sets up the form submission, dialog buttons (Save, Cancel), and handles form submission response by replacing content. Includes basic error display and handling for form fields.
```javascript
(function() { "use strict"; var form = $("#hd-{$uniqid}"); var dialog = form.closest('.dialog'); var delay = 0; // Dialog buttons var dialog_buttons = dialog.find('.dialog-buttons-gradient').empty(); dialog_buttons.append( $(")").click(function() { form.submit(); return false; }) ); dialog_buttons.append(" [\`or\`] "); dialog_buttons.append($(''+"[\`cancel\`]"+'').click(function() { $.wa.dialogHide(); })); form.submit(function() { dialog_buttons.append(''); $.post(form.attr('action'), form.serialize(), function(r) { form.parent().html(r); }); return false; }); {if $errors} {foreach $errors as $field_name => $e} form.find('[name="{$field_name}"]').addClass('error').after($('').text("{$e}")); {/foreach} form.on('keyup', 'input.error:text,textarea.error', function() { $(this).removeClass('error').siblings('.errormsg').remove(); }); form.on('change', '.error', function() { $(this).removeClass('error').siblings('.errormsg').remove(); }); {/if}
```
--------------------------------
### CSS for Helpdesk Form Preview
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/sources/SourcesFormPreview.html
Provides styling for the form preview, including layout, margins, font sizes, and element spacing. Ensures proper display of form fields and values.
```css
#core-content { margin-top: 80px; }
#core-content .wa-form { margin: 0 auto; }
#core-content .wa-field .field span { display: block; width: 100%; font-size: 0.9em; }
#core-content .wa-form .wa-field .wa-value p { line-height: 1.0em; margin-bottom: 0; }
#core-content .wa-form .wa-field.fldc_address .wa-value p { line-height: 1.6em; }
.wa-form .wa-field .wa-value label { display: block; margin: 0; }
input[type="checkbox"] { margin-top: 5px; }
input[type="radio"] { margin: 5px 0; }
```
--------------------------------
### Initialize FAQ URL Transliteration
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions/faq/Faq.html
Sets up transliteration for the FAQ URL input field, using the question field as the source and disabling a link element upon editing. This ensures user-friendly URLs.
```javascript
$.helpdesk_faq.translitInput( $('input[name="faq_url"]'), $('input[name="question"]'), function () { $form.find('.h-faq-url-link').addClass('h-disabled'); } );
```
--------------------------------
### Customer Portal JavaScript Initialization
Source: https://github.com/webasyst/helpdesk/blob/master/templates/actions-legacy/settings/SettingsPortal.html
Initializes the customer portal settings form with event handlers for submission, custom assignment focus, state checkbox logic, action label styling, and sticky buttons.
```JavaScript
(function() {
"use strict";
var form = $('#customer-portal-settings-form');
form.on('submit', function() {
form.find(':submit').after('');
$.post(form.attr('action'), form.serialize(), function(r) {
form.parent().html(r);
});
return false;
});
// Custom assignment: focus text field when user clicks the radio
$('#custom-radio').on('focus', function() {
setTimeout(function() {
$('#custom-radio').siblings('input:text').focus();
}, 0);
});
// Checkbox logic for states
$('#states-config input:checkbox').change(function() {
var cb = $(this);
var tr = cb.closest('tr');
if (cb.is(':checked')) {
tr.find('input:text').prop('disabled', false);
tr.removeClass('disabled');
} else {
tr.find('input:text').prop('disabled', true);
tr.addClass('disabled');
}
}).change();
// Color of action labels depending on whether they are turned on
$('#actions-config').on('change', 'select', function() {
var select = $(this);
if (select.val()) {
select.closest('tr').removeClass('disabled');
} else {
select.closest('tr').addClass('disabled');
}
}).find('select').change();
// Submit button behaviour
$('#sticky-bottom-buttons').sticky({
fixed_css: {
bottom: 0,
background: '#fff',
width: '100%',
margin: '0'
},
fixed_class: 'sticky-bottom-shadow'
});
form.one('change', function() {
form.find(':submit').removeClass('green').addClass('yellow');
});
})();
```
--------------------------------
### Email Settings Routing Logic
Source: https://github.com/webasyst/helpdesk/blob/master/lib/sources/templates-legacy/email/email_settings_rtr.html
This snippet demonstrates the logic for setting up email routing rules based on sender, request state, and available actions. It uses a template engine's syntax for conditional rendering and loops.
```HTML
[`If the sender of the message is`] {foreach $\_actors as $\_id=>$\_name} {$\_name} {/foreach} [`and request state is`] [`