更改页面以查看盒装Bitrix24中通用列表的元素

你好。



如果您曾经在Bitrix24中使用过通用列表,那么您可能知道元素的详细信息页面与编辑页面完全相同。唯一的区别是,如果用户具有只读权限,则该页面将没有“保存”和“应用”按钮。同意,而不是最愉快的界面。







因此,在工作中有必要使用通用列表时,我决定更改详细视图页面,因为我们使用的是框,并且自定义的可能性是无限的。



重要警告



Bitrix24的创建者强烈不鼓励更改公司门户界面,因为包装盒中的公共部分等同于内核,并且在更新系统时,存在删除所有修改内容的风险。



如果您决定将所需的模板复制到本地文件夹并根据需要模拟它们,那么它们将不受更新的影响。但是新功能也不会应用到它们。



因此,在这种情况下,唯一正确的方法是通过Javascript修改DOM树。



实际上,我们只需要更改列表表中详细页面的链接即可:







但是,实际上,这并不是那么容易实现,因为 您需要进入负责显示通用列表的组件,然后在其中编辑链接。



因此,我们将采取不同的途径-通过Javascript,我们将使用SidePanel bitrix库在滑块中打开页面。



有两种方法可以执行此操作-在init.php和您自己的模块中。您还需要注册您的JS库。



而且虽然第二种方法更方便,但我将向您展示第一种,在本文的结尾,我将提供指向我的模块的链接。



所以走吧 所有操作必须在本地文件夹中执行。



首先,您需要创建一个单独的文件夹,用于存储我们的库。让我们称它为查看器,它将具有以下结构:



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


让我们在这里停一下。对于php代码,我创建了一个单独的文件,然后将其包含在init.php中,以免乱扔后者。



现在让我们使用旧的核心CJSCore :: RegisterExt方法注册我们的库



// include.php

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


它仍然仅是使用CJSCore :: Init方法将通用列表页面上的该库连接起来的,而且似乎已经放在袋子里了-您可以开始编写该库本身。



但是,并非所有事情都那么简单,因为 连接之前,您需要检查我们在正确的页面上。最好使用正则表达式执行此操作,因为 地址中列表的ID可以更改



// include.php

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

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


因此,库已连接,仍需编写。为此,请创建一个viewer.js文件(如果您之前尚未创建过),首先我们使用BX.namespace函数声明一个名称空间



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


现在,可以通过以下方式声明所有变量和函数:



ElementViewer.init = function() {

}


为了不将所有代码写在一个函数中,为方便起见,我们将其分解为较小的代码。



首先,我们需要在页面上找到包含详细信息页面链接的节点。为此,我们将使用BX.findChildren函数,该函数应向我们返回包含包含详细信息页面链接的所有对象的列表:



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


同时,我们将编写一个函数,该函数将从链接中提取列表的ID和元素,以进行进一步的工作:



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


让我们回到BX.findChildren。该函数的独特之处在于它返回具有指定css类的所有对象的列表,并且这不是链接是事实。因此,我们需要检查,只有在那之后,取消链接打开事件并打开滑块:



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

}


我们仍然需要编写最后一个将打开滑块的函数。为此,我们使用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
    });
}


好吧,库已编写,连接后仍然可以调用init函数。为此,让我们返回include.php,在其中检查页面地址:



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


最后的接触仍然是-将我们的代码包含在init.php中:



// init.php

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

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


如果一切都正确完成,那么当您单击通用列表的元素时,将打开一个滑块:











最后,如所承诺的,将链接到实现相同功能模块



感谢您的关注。



All Articles