Всем привет.
У меня стояла задача реализовать добавление так называемого аккордеона в визуальны редактор битрикса. Так чтобы можно было и в описание секции инфоблока и в описание для анонса и в подробное описание элементов, да и просто в файл на страницу.
Схема работы в общих чертах такая: по нажатии на кнопку в панели инструментов редактора появляется окно, в котором блоки, в каждом из которых input для заголовка и textarea для самого текста аккордеона, причём textarea должен был быть также с визуальным редактором.
А когда аккордеон уже на странице то нужно вывести блок на подобии блока с размещённым на странице компоненте. Такие блоки называются суррогатами. При двойном щелчке на этот суррогат нужно открыть окно редактирования этого аккордеона.
Забегая немного вперед скажу, что быстро разобраться как подключить стандартный визуальный редактор битрикса для изменения элементов аккордина у меня не получилось и я не долго думаю прикрутил TinyMCE.
Для написания кода аккордеона я создал файл accordion.js и положил его в папку /bitrix/admin/htmleditor2/
Для подключения этого файла в админке я в файле /bitrix/php_interface/admin_header.php прописал код:
Далее я представлю код аккордеона с комментариями(пишу всё на скорую руку):
У меня стояла задача реализовать добавление так называемого аккордеона в визуальны редактор битрикса. Так чтобы можно было и в описание секции инфоблока и в описание для анонса и в подробное описание элементов, да и просто в файл на страницу.
Схема работы в общих чертах такая: по нажатии на кнопку в панели инструментов редактора появляется окно, в котором блоки, в каждом из которых input для заголовка и textarea для самого текста аккордеона, причём textarea должен был быть также с визуальным редактором.
А когда аккордеон уже на странице то нужно вывести блок на подобии блока с размещённым на странице компоненте. Такие блоки называются суррогатами. При двойном щелчке на этот суррогат нужно открыть окно редактирования этого аккордеона.
Забегая немного вперед скажу, что быстро разобраться как подключить стандартный визуальный редактор битрикса для изменения элементов аккордина у меня не получилось и я не долго думаю прикрутил TinyMCE.
Для написания кода аккордеона я создал файл accordion.js и положил его в папку /bitrix/admin/htmleditor2/
Для подключения этого файла в админке я в файле /bitrix/php_interface/admin_header.php прописал код:
CJSCore::Init(array("jquery"));//JQuery куда без него $APPLICATION->AddHeadScript("/bitrix/admin/htmleditor2/accordion.js"); //Сам файл аккордеона $APPLICATION->AddHeadScript("//cdn.tinymce.com/4/tinymce.min.js"); //И TinyMCE |
Далее я представлю код аккордеона с комментариями(пишу всё на скорую руку):
//Событие до иницализации самого редактора, тут мы и будем писать BX.addCustomEvent('OnEditorInitedBefore', function(toolbar) { var EDITOR = this; //Загнал обьект редактора в переменную чтобы в любой момент получить к нему доступ function AccordionDialog(tag){ //Описываем конструктор обьект для работы с аккордеоном. Передаём сюда тег суррогата var self = this; //Сам обьект this.editor = EDITOR; // Редактор this.dialogContent = $("<div></div>"); //Содержание окна добавления/редактирования аккордеона this.tmpls = { accordion: $("<div class='accordion-list'></div>"), accordionItem: "" + "<div id='accordion-item-#NUM#' data-num='#NUM#' class='accordion-item'>" + "<table style='width:100%;'>" + "<tr>" + "<td style='width: 80%;'>" + "<input style='width:100%; box-sizing: border-box; height: 30px;' id='accordion-title-#NUM#' class='form-control title' value='asdasd' type='text'>" + "</td>" + "<td style='width: 20%;'>" + "<input style='width:100%;' type='button' value='Удалить' id='delete-item-#NUM#' class='delete-item'>" + "</td>" + "</tr>" + "<tr>" + "<td colspan='2'>" + "<textarea id='accordion-text-#NUM#' class='text' name='text[]'></textarea>" + "</td>" + "</tr>" + "</table>" + "</div>" } // Шаблона блока редактирования элемента аккордеона if(typeof tag != 'undefined'){ // если мы передали тег в констуртор то получаем параметры тега там у нас в json хранится содеражание всего аккордеона var params = tag.params; } this.data = {}; // тут мы храним содержимое аккордеона для манипуляций if(typeof params != 'undefined') { //Обработка входых парметров if (typeof params.items != 'undefined') { //Если среди парметров есть элменты аккордеона то добавляем их в data this.data.items = params.items; } else { this.data.items = []; } } else { this.data.items = []; this.data.items.push({ title: "", text: "" }); } this.Dialog = new BX.CDialog({ //Инициализаци окна добавления/редактирования аккордеона title: "Аккордеон", min_width: 400, min_height: 400, content: self.GetContent(), buttons: [ //Кнопки в окне {// Кнопка применяет изменения или добавляет аккордеон title: "OK", name: 'saveAccordion', id: 'saveAccordion', action: function () { var _thisBtn = this; // Сама кнопка html = self.GetAccrodionHTML(); //Метод получает html аккордеона if(typeof tag != 'undefined'){ tag.params.html = html; // чёт уж не помню для чего это, } else { EDITOR.selection.InsertHTML(html); //Вставляем аккордеона в редактор } setTimeout(function(){ EDITOR.synchro.FullSyncFromIframe(); //Спустя немного времени обновляем содержииме чтобы применился новый аккордеон }, 50); this.parentWindow.Close(); //Закрываем окно $(this.parentWindow.DIV).remove(); //Удаляем окно из DOM-a } }, { //Кнопка добавляем блок для редактирования элемента аккордеона title: "Еще", className: "adm-btn-add", action: function () { self.data.items.push({ //Добавляем пустой элемент в нашу переменную с содержимым аккордеона title: "", text: "" }) self.RmoveTinyMCE(); //Убираем TinyMCE $content = $(self.Dialog.GetContent()); //Получаем содержимое окна редактирования аккордеона $content.find('.accordion-item').each(function(){ //Находим все блоки для редактирвания аккордеона var index = $(this).attr("data-num"); // Тут мы храним порядковый номер блока self.data.items[index].title = $(this).find('.title').val() //добавляем заголовок блока в переменную где хранится содержимое аккордеона self.data.items[index].text = $(this).find('.text').val() //добавляем текст блока в переменную где хранится содержимое аккордеона }); self.Dialog.SetContent(self.GetContent()); //Метод генерирует содержимое кона редактора аккоржеона. self.InitTinyMCE(); //Метод добавляет TinyMCE self.InitDeleteEvent(); //Инициализируем событие на удаление блока аккордеона } }, { //Отмена title: BX.message('JS_CORE_WINDOW_CANCEL'), id: 'cancel', name: 'cancel', action: function () { this.parentWindow.Close(); //Закрываем окно self.RmoveTinyMCE(); //Убираем TinyMCE $(this.parentWindow.DIV).remove(); //Удаляем DOM окна } } ] }); } AccordionDialog.prototype = { GetContent: function(){ //Метотд получает сожержимое окна редактора аккордеона var self = this; var accordion = $(self.tmpls.accordion.clone()); for(var i in self.data.items){ var item = ""; item = self.tmpls.accordionItem; item = item.replace(/#NUM#/g, i); var $item = $(item); $item.find('.title').attr("value", this.data.items[i].title); $item.find('.text').text(this.data.items[i].text); accordion.append($item); } self.dialogContent.html(""); self.dialogContent.append(accordion); return self.dialogContent.html(); }, RefreshContent: function(){ //Метотд обновляет содержимое окна редактора аккордеона var self = this; self.RmoveTinyMCE(); self.Dialog.SetContent(self.GetContent()); self.InitTinyMCE(); }, InitDeleteEvent: function(){ //Метод инициализирует событие на удаление блока аккордеона var self = this; $('.delete-item').click(function(){ var index = $(this).parent().attr('data-num'); self.DeleteItem(index); self.RefreshContent(); self.InitDeleteEvent(); }) }, GetAccrodionHTML: function(){ //Метотд получает html аккордеона по данным из this.data var self = this; var html = "<div class='accordion'>"; self.RmoveTinyMCE(); $content = $(self.Dialog.GetContent()); $content.find('.accordion-item').each(function(){ var index = $(this).attr("data-num"); self.data.items[index].title = $(this).find('.title').val() self.data.items[index].text = $(this).find('.text').val() }); for (var i = 0; i < self.data.items.length; i++) { html += "<div class='accordion-item'><div class='title'>" + self.data.items[i].title + "</div><div class='text'>" + self.data.items[i].text + "</div></div>"; } html += "</div>"; return html; }, Show: function () { //Метотд показывает окно редактора аккордеона this.Dialog.Show(); this.InitTinyMCE(); this.InitDeleteEvent(); }, DeleteItem: function(index){ //Метотд удаляет блок для редактирования элемента аккордеона var self = this; if(self.data.items.length <= 1) return; if(typeof self.data.items[index] != 'undefined') { delete self.data.items[index]; var tmpData = []; for(var i in self.data.items){ if(i != index || typeof self.data.items[i] != 'undefined') tmpData.push(self.data.items[i]) } self.data.items = tmpData; console.debug(tmpData); } }, RmoveTinyMCE: function(){ //Убираем TinyMCE tinymce.remove(); }, InitTinyMCE: function(){ //Добавляем TinyMCE for (var i = 0; i < this.data.items.length; i++) { tinymce.init({ selector: '#accordion-text-' + i, height: 200, theme: 'modern', plugins: [ "advlist autolink autosave link image lists charmap print preview hr anchor pagebreak spellchecker", "searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking", "table contextmenu directionality emoticons template textcolor paste fullpage textcolor colorpicker textpattern" ], toolbar1: "newdocument fullpage | bold italic underline strikethrough | alignleft aligncenter alignright alignjustify | styleselect formatselect fontselect fontsizeselect", toolbar2: "cut copy paste | searchreplace | bullist numlist | outdent indent blockquote | undo redo | link unlink anchor image media code | insertdatetime preview | forecolor backcolor", toolbar3: "table | hr removeformat | subscript superscript | charmap emoticons | print fullscreen | ltr rtl | spellchecker | visualchars visualblocks nonbreaking template pagebreak restoredraft", content_css: [ '//fonts.googleapis.com/css?family=Lato:300,300i,400,400i', '//www.tinymce.com/css/codepen.min.css' ] }); } } } this.AddCustomParser(function (content) {// А а это событие которое парсит содержимое и добавляет суррогаты var _this = EDITOR.phpParser,//Переменная в которой хранится парсер виз. редактора index = 0; _this.arAccordions = {}; var $content = $("<div></div>"); //Тут будет содержимое виз.редактора. $content.append(content); //Добавляем содержиме в переменную $content.find(".accordion").each(function(){ //Бежим по аккордеонам var div = $("<div></div>"); var items = []; $(this).find('.accordion-item').each(function(){ //Бежим по каждому элементу аккодреона items.push({ title: $(this).find('.title').text().trim(), text: $(this).find('.text').html().trim(), }) // Добавляем в переменную где храним содержимое аккордеона }); div.append($(this).clone()); _this.arAccordions[index] = { html: div.clone().html(), items: items }; $(this).replaceWith("#BXACCORD_" + (index++) + "#"); //Заменяем найденый аккордеон на строку вида #BXACCORD_0# или #BXACCORD_5# }); content = $content.html(); content = content.replace(/#BX(ACCORD)_(\d+)#/g, function(str, type, ind){ var res = EDITOR.phpParser.GetSurrogateHTML("accordion", "Аккордеон", "Аккордеон", _this.arAccordions[ind]); return res || str; });//Заменяем строки типа #BXACCORD_0# на суррогат return content; //Возвращаем новое содержимое виз. редактора }); this.AddButton({ //Метотд для добавления кнопки на панель инструментов редактора iconClassName: 'bxhtmled-button', src: '/bitrix/images/closed_c1.png', id: 'typograf', title: 'typograf', //action: "insertAnchor" handler: function (e) { var Dialog = new AccordionDialog(); Dialog.Show(); } }); BX.addCustomEvent("OnGetBxNodeList", function(e, t){ var _this = this.phpParser; _this.arBxNodes.accordion = { Parse: function(params){ return _this._GetUnParsedContent(params.html); } }; }); BX.addCustomEvent("OnSurrogateDblClick", function(e, t){ // Событие на двойной клик по суррогату var html = ""; if(t.tag != 'accordion') return; if(typeof EDITOR.bxTags[t.id] != 'undefined'){ var Dialog = new AccordionDialog(t); Dialog.Show(); } }) }); |