Это была прелюдия, а теперь к делу. Итак, мы с вами загрузили базовый виджет из соответствующего раздела документации amoCRM и с интересом разглядываем содержимое архива widget.zip; ок, ну а что же дальше? Как создать свой собственный виджет, предположим, некую формочку, которая по нажатию submit станет обрабатывать введенные пользователем данные?
Спрашиваете - отвечаю: все несложно. Собственно, для того, чтобы инсталлировать полученный виджет в своей учетке amoCRM (две недели, к слову сказать, бесплатного полнофункционального тестового периода - пробуем) нам с вами придется всего лишь изменить две строчки в файле manifest.json: "code" и "secret_key", заменив дефолтные значения на свои собственные, характерные только для нашей учетной записи - создаем новый виджет, открыв вкладку API, обзываем как душе угодно (это и будет "code", но название должно быть уникальным, учтите), и получаем для него тут же сгенерированный "secret_key". С этим все просто, но необходимо ведь добавить какой-то HTML, а также обработчик?
Начну с утверждения: handler.php виджета amoCRM вы, вероятнее всего, вынуждены будете использовать на каком-то удаленном сервере, т.к. использовать php непосредственно в виджете допустимо только в случае создания публичного, прошедшего модерацию, виджета; т.е. виджета, доступного всем без исключения зарегистрированным пользователям amoCRM. В большинстве случаев, поскольку речь идет о коммерческой разработке, этот вариант неприемлем... ок, таким образом, начнем мы с вами с создания HTML-формы, способной выглядеть вот таким, например, образом:
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js"></script>
</head>
<body>
<form id="form">
<table width="30%" cellspacing="0" cellpadding="4">
<tr><td>Item category</td><td width="80%"><input type="text" name="product_type" value="Наружная реклама" style="width:100%"></td></tr>
<tr><td>Item</td><td><input type="text" name="product" value="Световой короб" style="width:100%" ></td></tr>
<tr><td>Item type</td><td>
<select id="test" name="item_type" style="width:100%" >
<option value="">-------</option>
<option value="square_lightbox">Прямой световой короб</option>
<option value="composite_lightbox">Композитный световой короб</option>
<option value="shaped_lightbox">Фигурный клееный световой короб</option>
<option value="shaped_twosided_lightbox">Двусторонний фигурный световой короб</option>
<option value="click_data_lightbox">Лайтбокс со сменной информацией Click</option>
</select>
</td></tr>
<tr><td>Height</td><td><input type="text" placeholder="Введите значение" name="height" style="width:100%"></td></tr>
<tr><td>Width</td><td><input type="text" placeholder="Введите значение" name="width" style="width:100%"></td></tr>
</table>
<input type="button" onclick="dosubmit()" value="Submit">
</form>
<div id="result" style="padding:5px;">
</div>
<script>
function dosubmit( ) {
new Ajax.Updater( 'result', 'handler.php', { method: 'get',
parameters: $('form').serialize() } );
$('form').reset();
}
</script>
</body>
</html>
В скобках отметим, что использование prototype.js в своем коде в теории вполне здесь допустимо, но на практике вызывает конфликт с априори подключенным jquery.js, поэтому не рекомендуется. Ок, а теперь попробуем интегрировать свой HTML в файл script.js виджета, получаем следующее:
define(['jquery'], function ($) {
var CustomWidget = function () {
var self = this, system = self.system;
this.callbacks = {
settings: function () {
}, init: function () {
/*$.getScript("http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js", function (data, textStatus, jqxhr) {
});*/
return true;
},
bind_actions: function () {
$('.print-calc-form-button').on('click', function () {
$('.mgc-template-modal').remove();
$calc_container = '<form id="form"> <table width="30%" cellspacing="0" cellpadding="4"> <tr><td>Item category</td><td width="80%"><input type="text" name="product_type" value="Outer ads" style="width:100%"></td></tr> <tr><td>Item</td><td><input type="text" name="product" value="Lightbox" style="width:100%" ></td></tr> <tr><td>Item type</td><td> <select id="test" name="item_type" style="width:100%" > <option value="">-------</option> <option value="square_lightbox">Прямой световой короб</option> <option value="composite_lightbox">Композитный световой короб</option> <option value="shaped_lightbox">Фигурный клееный световой короб</option> <option value="shaped_twosided_lightbox">Двусторонний фигурный световой короб</option> <option value="click_data_lightbox">Лайтбокс со сменной информацией Click</option> </select> </td></tr> <tr><td>Height</td><td><input type="text" name="height" style="width:100%"></td></tr> <tr><td>Width</td><td><input type="text" name="width" style="width:100%"></td></tr> </table> <input type="button" value="Submit" class="submit-button"> </form> <div id="result" style="padding:5px;"> </div>';
$('body').append('<div class="modal modal-list modal_print-calc modal_calc-action mgc-calc-modal"> <div class="modal-scroller custom-scroll"> <div class="modal-body modal-body-relative"> <div class="modal-body__inner"> <div class="calc-action__header"><h2 class="calc-action__caption head_2">Расчет стоимости полиграфии</h2> <div class="calc-action__top-controls"> <button type="button" class="button-input button-cancel " tabindex="" id="" style=""><span>Закрыть</span></button> </div> </div>' + $calc_container + ' </div> </div> <div class="default-overlay modal-overlay default-overlay-visible"><span class="modal-overlay__spinner spinner-icon spinner-icon-abs-center"style="display: none;"></span></div> </div> </div>');
$('.mgc-calc-modal .button-cancel').on('click', function () {
$('.mgc-calc-modal').remove();
});
$('.mgc-calc-modal .submit-button').on('click', function (e) {
e.preventDefault();
var formEl = $('.mgc-calc-modal form'),
formData = formEl.serialize();
$.get("https://your_remote_server/ajax-handler-calc-app/handler.php", formData)
.done(function (data) {
//console.log("Data Loaded: " + data);
$('.mgc-calc-modal #result').empty().append(data);
formEl[0].reset();
});
});
});
return true;
},
render: function () {
var lang = self.i18n('userLang');
w_code = self.get_settings().widget_code;
if (typeof(AMOCRM.data.current_card) != 'undefined') {
if (AMOCRM.data.current_card.id == 0) {
return false;
}
}
self.render_template({
caption: {
class_name: 'js-ac-caption',
html: ''
},
body: '',
render: '<div class="ac-form"><div class="print-calc-form-button ac_sub">Калькулятор полиграфии</div></div><link type="text/css" rel="stylesheet" href="/upl/' + w_code + '/widget/style.css" >'
});
return true;
},
contacts: {
selected: function () {
var c_data = self.list_selected().selected;
console.log(c_data);
var names = [],
length = c_data.length;
for (var i = 0; i < length; i++) {
names[i] = {
ecalcs: c_data[i].ecalcs,
phones: c_data[i].phones
};
}
console.log(names);
for (var i = 0; i < length; i++) {
}
$(self.contacts).remove();
self.contacts = names;
}
},
leads: {
selected: function () {
}
},
onSave: function () {
return true;
}
};
return this;
};
return CustomWidget;
});
Ну вот примерно так, for example. Разумеется, делайте для себя лучше и круче, делайте красивее; но сейчас нам с вами важен сугубо принцип. HTML остался практически неизменен, как видите (только строчки кода объединены), плюс подключен style.css; ну, тут уж все совсем как обычно, надеюсь, правилам работы с каскадными таблицами стилей вас обучать не надо, останавливаться на этом моменте не будем. В конце статьи выложен для ознакомления готовый виджет, который не составляет труда (изменив, как уже было сказано выше, "code" и "secret_key" в файле manifest.json) сразу же инсталлировать в свою учетку amoCRM и вдоволь наиграться с дивами и стилями; только не забудьте поместить обработчики (также приложены) на удаленный сервер и правильно прописать путь к нему:
$.get("https://your_remote_server/ajax-handler-calc-app/handler.php", formData)
.done(function (data) {
//console.log("Data Loaded: " + data);
$('.mgc-calc-modal #result').empty().append(data);
formEl[0].reset();
});
Пожалуй, для начала это все, или почти все; как видите, ничего сложного. Области отображения вашего нового виджета в веб-интерфейсе amoCRM регулируются в том же самом manifest.json. Подробнее в документации, а для начала вы попросту можете ограничиться следующей несложной редакцией:
"locations":[
"ccard-1",
"clist-0",
"lcard-1",
"llist-0",
"settings"
],
Допустимо ли в одном-единственном виджете отображать их несколько? - вполне, и это очень несложно: повторяем различный HTML:
bind_actions: function () {
$('.print-calc-form-button').on('click', function () {
$('.mgc-template-modal').remove();
$calc_container =
--------------------------------------
$('.print-calc2-form-button').on('click', function () {
$('.mgc-template-modal').remove();
$calc_container =
--------------------------------------
$('.print-calc3-form-button').on('click', function () {
$('.mgc-template-modal').remove();
$calc_container =
--------------------------------------
return true;
},
и, соответственно:
render: '<div class="ac-form"><div class="print-calc-form-button ac_sub">Наружная реклама</div></div><link type="text/css" rel="stylesheet" href="/upl/' + w_code + '/widget/style.css" > <div class="ac-form"><div class="print-calc2-form-button ac_sub">Широкоформатная печать</div></div><link type="text/css" rel="stylesheet" href="/upl/' + w_code + '/widget/style.css" > <div class="ac-form"><div class="print-calc3-form-button ac_sub">Печать баннеров</div></div><link type="text/css" rel="stylesheet" href="/upl/' + w_code + '/widget/style.css" >'
Впрочем, все это, повторюсь, можно в подробностях увидеть в полностью рабочем примере виджета, который вы теперь уже вполне готовы скачать по прямой ссылке.
Напоследок следует заметить, что в качестве альтернативы описанному способу разработчики amoCRM предлагают и другой: вовсе не обязательно использовать свои шаблоны, можно попробовать воспользоваться уже готовыми здесь темплейтами шаблонизатора twig.js. Правда, далеко не во всех случаях этот путь является оптимальным; позволю себе сослаться на мнение Алексея Рябова, разработчика amoCRM, весьма любезно согласившегося ответить на все мои вопросы:
Учитывая, что у вас три разных модальных окна с разными типами информации — чекбоксами и выпадающими списками, вам будет удобней написать свои шаблоны, чем пытаться совместить наши встроенные (отдельно кнопка, отдельно чекбокс, отдельно список), так как для каждого потребуется вызывать свою функцию.
Создайте в архиве с виджетом папку templates. В неё добавьте свой шаблон. Добавить шаблон в скрипт можно, например, таким кодом.Здесь в переменную загружается шаблон:
var templ = self.render({
href:'templates/template.twig', //путь до шаблона
base_path: self.params.path;
load: callback //вызов функции обратного вызова произойдет только если шаблон существует и загружен
}, params); //параметры для шаблона
Здесь шаблон загружается в панель шаблонов:
self.render_template({
caption: {
class_name: 'class',
html: ''
},
body: '',
render: templ
});
Более подробная информация есть в документации.