Cambiar la página para ver el elemento de listas universales en Bitrix24 en caja

Hola.



Si alguna vez ha trabajado con listas universales en Bitrix24, probablemente sepa que la página de detalles de un elemento es completamente idéntica a la página de edición. La única diferencia es que si el usuario tiene permisos de solo lectura, la página no tendrá los botones Guardar y Aplicar. De acuerdo, no es la interfaz más agradable.







Y así, cuando en el trabajo se hizo necesario usar listas universales, decidí cambiar la página de vista detallada, ya que estamos usando un cuadro, y las posibilidades de personalización son simplemente ilimitadas.







24 , , , .



local , . .



— DOM- Javascript.



De hecho, solo necesitamos cambiar el enlace a la página detallada en la tabla de lista:







Sin embargo, en realidad, esto no es tan fácil de implementar, ya que debe ir al componente responsable de mostrar listas universales y editar el enlace allí.



Por lo tanto, tomaremos una ruta diferente: a través de Javascript, abriremos la página en el control deslizante usando la biblioteca bitrix de SidePanel.



Hay dos formas de hacer esto: en init.php y en su propio módulo. También necesita registrar su biblioteca JS.



Y aunque el segundo método es más conveniente, les mostraré el primero, y al final del artículo les daré un enlace a mi módulo.



Entonces vamos. Todas las acciones deben realizarse en la carpeta local.



Primero, debe crear una carpeta separada donde se almacenará nuestra biblioteca. Llamémoslo, por ejemplo, visor, y tendrá la siguiente estructura:



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


Detengámonos aquí un poco. Para el código php, creé un archivo separado, que luego incluiré en init.php para no ensuciar este último.



Ahora registremos nuestra biblioteca usando el antiguo método CJSCore :: RegisterExt :



// include.php

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


Solo queda conectar esta biblioteca en la página de listas universales con el método CJSCore :: Init y, al parecer, está en la bolsa: puede comenzar a escribir la biblioteca en sí.



Sin embargo, no todo es tan sencillo, ya que antes de conectarse, debe verificar que estamos en la página correcta. Es mejor hacer esto usando expresiones regulares, ya que la identificación de la lista en la dirección puede cambiar



// include.php

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

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


Entonces, la biblioteca está conectada, queda escribirla. Para hacer esto, cree un archivo viewer.js (si no lo ha creado antes) y antes que nada declare un espacio de nombres usando la función BX.namespace :



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


Ahora todas las variables y funciones se pueden declarar de la siguiente manera:



ElementViewer.init = function() {

}


Para no escribir todo el código en una función, vamos a dividirlo en otras más pequeñas para mayor comodidad.



En primer lugar, debemos encontrar el nodo en la página que contiene el enlace a la página de detalles. Para hacer esto, usaremos la función BX.findChildren , que debería devolvernos una lista de todos los objetos que contienen enlaces a la página de detalles:



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


Al mismo tiempo, escribiremos una función que extraerá el id de la lista y el elemento del enlace para seguir trabajando:



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])
        };
    }
}


Volvamos a BX.findChildren. La peculiaridad de esta función es que devuelve una lista de todos los objetos con la clase css especificada, y no es un hecho que será un enlace. Por lo tanto, debemos verificar, y solo después cancelar el evento de apertura de enlace y abrir el control 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); //  
                })
            }
        }
    });

}


Nos queda escribir la última función que abrirá el control deslizante. Para hacer esto, usamos la 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
    });
}


Bueno, la biblioteca está escrita, queda llamar a la función init después de conectarse. Para hacer esto, regresemos a include.php, donde se verifica la dirección de la página:



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);
}


El toque final permanece: incluir nuestro código en init.php:



// init.php

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

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


Si todo se hace correctamente, cuando haga clic en el elemento de la lista universal, se abrirá un control deslizante:











Finalmente, como se prometió, un enlace a un módulo que implementa lo mismo.



Gracias por su atención.



All Articles