Alterar a página para visualizar o elemento de listas universais no Bitrix24 em caixa

Olá.



Se você já trabalhou com listas universais no Bitrix24, provavelmente sabe que a página de detalhes de um elemento é completamente idêntica à página de edição. A única diferença é que, se o usuário tiver permissões somente leitura, a página não terá os botões Salvar e Aplicar. Concordo, não é a interface mais agradável.







E por isso, quando no trabalho tornou-se necessário o uso de listas universais, resolvi mudar a página de visualização detalhada, já que estamos usando uma caixa, e as possibilidades de personalização são simplesmente ilimitadas.







24 , , , .



local , . .



— DOM- Javascript.



Na verdade, só precisamos alterar o link para a página detalhada na tabela de lista:







No entanto, na realidade, isso não é tão fácil de implementar, uma vez que você precisa ir para o componente responsável por exibir listas universais e editar o link lá.



Portanto, tomaremos um caminho diferente - através do Javascript abriremos a página no controle deslizante usando a biblioteca bitrix SidePanel.



Existem duas maneiras de fazer isso - em init.php e em seu próprio módulo. Você também precisa registrar sua biblioteca JS.



E embora o segundo método seja mais conveniente, mostrarei o primeiro, e no final do artigo darei um link para o meu módulo.



Então vamos. Todas as ações devem ser realizadas na pasta local.



Primeiro você precisa criar uma pasta separada onde nossa biblioteca será armazenada. Vamos chamá-lo, por exemplo, de visualizador, e ele terá a seguinte estrutura:



/viewer 
-/js
--viewer.js //  js-
-include.php // ,      init.php


Vamos parar um pouco aqui. Para o código php, criei um arquivo separado, que irei incluir no init.php para não sujar o último.



Vamos agora registrar nossa biblioteca usando o antigo método central CJSCore :: RegisterExt :



// include.php

// ..    js- viewer,     
CJSCore::RegisterExt('elementviewer', [ 
    'js' => '/local/viewer/js/viewer.js', //   
    'rel' => ['SidePanel'] // 
]);


Resta apenas conectar esta biblioteca na página de listas universais com o método CJSCore :: Init e, ao que parece, está na bolsa - você pode começar a escrever a própria biblioteca.



Porém, nem tudo é tão simples, pois antes de conectar, você precisa verificar se estamos na página certa. É melhor fazer isso usando expressões regulares, uma vez que o id da lista no endereço pode mudar



// include.php

$pattern = '/\/lists\/(\d+)\/view\//'; //     ,  (\d+) = id 
$server = Bitrix\Main\Context::getCurrent()->getServer(); //  Server,     

if(preg_match($pattern, $server->getRequestUri())) {
       CJSCore::Init(['elementviewer']); //  
}


Então, a biblioteca está conectada, falta escrever. Para fazer isso, crie um arquivo viewer.js (se ainda não o tiver criado) e, antes de mais nada, declare um namespace usando a função BX.namespace :



const ElementViewer = BX.namespace('Viewer');


Agora todas as variáveis ​​e funções podem ser declaradas da seguinte maneira:



ElementViewer.init = function() {

}


Para não escrever todo o código em uma função, vamos dividi-lo em outros menores por conveniência.



A primeira coisa que precisamos fazer é localizar o nó na página que contém o link para a página de detalhes. Para fazer isso, usaremos a função BX.findChildren , que deve nos retornar uma lista de todos os objetos que contêm links para a página de detalhes:



ElementViewer.findCell = function () {
    return BX.findChildren(document, {
        class: 'main-grid-cell-content' // css-    
    }, true);
}


Ao mesmo tempo, escreveremos uma função que extrairá o id da lista e o elemento do link para trabalhos futuros:



ElementViewer.pattern = '/lists/(\\d+)/element/0/(\\d+)'; //        ,    = id ,   = id .

ElementViewer.extractListData = function (url) {
    let match = url.match(this.pattern); //   
    if(match) {
        return {
            list_id: Number(match[1]),
            element_id: Number(match[2])
        };
    }
}


Vamos voltar para BX.findChildren. A peculiaridade desta função é que ela retorna uma lista de todos os objetos com a classe css especificada, e não é um fato que este será um link. Portanto, precisamos verificar, e somente depois disso, cancelar o evento de abertura do link e abrir o controle deslizante:



ElementViewer.init = function (sliderUrl) {

    const cell = this.findCell();

    cell.forEach(item => {

        let itemChild = item.children;
        let child = itemChild[0];

        if(child && child.tagName === 'A') {
            const listData = this.extractListData(child.toString()); //  id     

            if(listData !== undefined) {
                child.addEventListener('click', (e) => {
                    e.preventDefault(); //    
                    this.openSlider(sliderUrl, listData.list_id, listData.element_id); //  
                })
            }
        }
    });

}


Resta-nos escrever a última função que irá abrir o controle deslizante. Para fazer isso, usamos a biblioteca SidePanel :



ElementViewer.openSlider = function (sliderUri, listId, elementId) {

//       POST,       id   
    let sliderParams = {
        list_id: listId,
        element_id: elementId
    }

    return BX.SidePanel.Instance.open(sliderUri, {
        allowChangeHistory: false,
        cacheable: false,
        requestMethod: 'POST',
        requestParams: sliderParams
    });
}


Bem, a biblioteca está escrita, resta chamar a função init após a conexão. Para fazer isso, vamos retornar a include.php, onde o endereço da página é verificado:



if(preg_match($pattern, $server->getRequestUri())) {
       CJSCore::Init(['elementviewer']); //  
       $asset = Bitrix\Main\Page\Asset::getInstance();
       $script = '<script>BX.ready(function() {
  ElementViewer.init();
})</script>';
      $asset->addString($script);
}


O toque final permanece - incluir nosso código em init.php:



// init.php

$file = $_SERVER['DOCUMENT_ROOT'] . '/local/path/to/viewer/include.php';

if(file_exists($file)) {
   require $file;
}


Se tudo for feito corretamente, ao clicar no elemento da lista universal, um controle deslizante será aberto:











Finalmente, como prometido, um link para um módulo que implementa a mesma coisa.



Obrigado pela atenção.



All Articles