Skip to content

Instantly share code, notes, and snippets.

@vasia123
Created February 17, 2017 19:53
Show Gist options
  • Save vasia123/e60342d48e3d44881c6075a1f8af01be to your computer and use it in GitHub Desktop.
Save vasia123/e60342d48e3d44881c6075a1f8af01be to your computer and use it in GitHub Desktop.
Инструкция по созданию TV для табличных данных динамического размера в Modx Revolution.
<?php
if(!class_exists('GridTVRender')) {
class GridTVRender extends modTemplateVarInputRender {
public function getTemplate() {
return $this->modx->getOption('core_path').'components/gridtv/tv/input/tpl/gridtv.tpl';
}
public function process($value,array $params = array()) {
}
}
}
return 'GridTVRender';
<style>
{literal}
table.editable th {
padding:5px 10px;
background:#E4E9EE;
font-weight:bold;
height:20px;
}
table.editable td {
background:#e9e9e9;
padding:5px 10px;
height:20px;
}
table.editable input{
width:50px;
}
{/literal}
</style>
<table id="table{$tv->id}" class="editable" >
<tbody id="tbody{$tv->id}">
</tbody>
</table>
<input type="hidden" id="tv{$tv->id}" name="tv{$tv->id}" value="{$tv->value}">
<script type="text/javascript">
{literal}
var data=[[{"type":"TH","value":"Рост/Размер"}]];
{/literal}
if (document.getElementById("tv{$tv->id}").value != "") {
data = JSON.parse(document.getElementById("tv{$tv->id}").value.replace(/\'/gi, '"'));
}
var tbody = document.getElementById("tbody{$tv->id}");
for (var r = 0; r < data.length; r++) {
var tr = document.createElement("tr");
if (r == 0) {
tr.id = "frow{$tv->id}";
}
for (var c = 0; c < data[r].length; c++) {
if (undefined != data[r][c]) {
var cell = document.createElement(data[r][c].type);
var input = document.createElement("input");
input.type = "text";
input.value = data[r][c].value;
input.onkeyup = function (e) {
document.getElementById("tv{$tv->id}").value = tableToJson{$tv->id}();
}
cell.appendChild(input);
tr.appendChild(cell);
}
}
if (r == 0) {
var btn = document.createElement("button");
btn.onclick = addColumn{$tv->id};
btn.textContent = "+";
var btn2 = document.createElement("button");
btn2.onclick = deleteColumn{$tv->id};
btn2.textContent = "-";
var cth = document.createElement("th");
cth.id = "cth{$tv->id}";
cth.appendChild(btn);
cth.appendChild(btn2);
tr.appendChild(cth);
}
tbody.appendChild(tr);
}
var btn = document.createElement("button");
btn.onclick = addRow{$tv->id};
btn.textContent = "+";
var btn2 = document.createElement("button");
btn2.onclick = deleteRow{$tv->id};
btn2.textContent = "-";
var rth = document.createElement("th");
var tr = document.createElement("tr");
tr.id = "rth{$tv->id}";
rth.appendChild(btn);
rth.appendChild(btn2);
tr.appendChild(rth);
tbody.appendChild(tr);
function addColumn{$tv->id}() {
var node = document.getElementById("frow{$tv->id}");
var input = document.createElement("input");
input.type = "text";
input.onkeyup = function (e) {
document.getElementById("tv{$tv->id}").value = tableToJson{$tv->id}();
}
var th = document.createElement("th");
th.appendChild(input);
node.insertBefore(th, document.getElementById("cth{$tv->id}"));
rebuidlTable{$tv->id}();
}
function addRow{$tv->id}() {
var node = document.getElementById("tbody{$tv->id}");
var tr = document.createElement("tr");
var input = document.createElement("input");
input.type = "text";
input.onkeyup = function (e) {
document.getElementById("tv{$tv->id}").value = tableToJson{$tv->id}();
}
var th = document.createElement("th");
th.appendChild(input);
tr.appendChild(th);
node.insertBefore(tr, document.getElementById("rth{$tv->id}"));
rebuidlTable{$tv->id}();
}
function rebuidlTable{$tv->id}() {
var frow = document.getElementById("frow{$tv->id}");
var tbody = document.getElementById("tbody{$tv->id}");
//console.log(tbody.childElementCount);
var rows = tbody.childElementCount - 2;
var cols = frow.childElementCount - 1;
for (var i = 1; i <= rows; i++) {
var cm = cols - tbody.children[i].childElementCount;
for (var j = 0; j < cm; j++) {
var td = document.createElement("td");
var input = document.createElement("input");
input.type = "text";
input.onkeyup = function (e) {
document.getElementById("tv{$tv->id}").value = tableToJson{$tv->id}();
}
td.appendChild(input);
tbody.children[i].appendChild(td);
}
}
}
function deleteRow{$tv->id}() {
if (tbody.childElementCount >= 3) {
tbody.children[tbody.childElementCount - 2].remove();
}
}
function deleteColumn{$tv->id}() {
for (var i = 0; i < tbody.childElementCount - 1; i++) {
var rows = tbody.children[i].children;
if ((i > 0) && (rows.length > 1)) {
rows[rows.length - 1].remove();
} else {
if (rows.length > 2) {
rows[rows.length - 2].remove();
}
}
}
}
function tableToJson{$tv->id}() {
var arr = Array();
var rows = document.getElementById("tbody{$tv->id}").children;
for (var i = 0; i < rows.length; i++) {
var cells = rows[i].children;
arr[i] = Array();
for (var j = 0; j < cells.length; j++) {
if (cells[j].textContent != "+-") {
if (cells[j].getElementsByTagName("input").length > 0) {
var val = cells[j].getElementsByTagName("input")[0].value;
} else {
var val = cells[j].textContent;
}
arr[i].push({
"type": cells[j].tagName,
"value": val
});
}
}
}
if (arr[arr.length - 1].length == 0) {
arr.pop();
}
return JSON.stringify(arr).replace(/\"/gi, "'");
}
</script>
<?php
$corePath = $modx->getOption('core_path',null,MODX_CORE_PATH).'components/gridtv/';
// были проблемы с аякосом минишопа, поэтому поставил ограничение - не запускаться при аякс запросах
$isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
if (!$isAjax) {
switch ($modx->event->name) {
case 'OnTVInputRenderList':
$modx->event->output($corePath.'tv/input/');
break;
case 'OnTVOutputRenderList':
$modx->event->output($corePath.'tv/output/');
break;
case 'OnTVInputPropertiesList':
$modx->event->output($corePath.'tv/inputoptions/');
break;
case 'OnTVOutputRenderPropertiesList':
$modx->event->output($corePath.'tv/properties/');
break;
}
}
1. Создаем Пространство имен:
Имя - gridtv
Путь к ядру - {core_path}components/gridtv/
Путь к активам - {assets_path}components/gridtv/
2. Создаем папки core/components/gridtv/tv/input/tpl/
3. В core/components/gridtv/tv/input размещаем файл gridtv.class.php
4. В core/components/gridtv/tv/input/tpl размещаем файл gridtv.tpl
5. Создаем новый плагин (файл plugin.php) и отмечаем указанные в нем события:
OnTVInputRenderList
OnTVOutputRenderList
OnTVInputPropertiesList
OnTVOutputRenderPropertiesList
6. Создаем новую TV и выбираем тип gridtv
7. Пример сниппета для обработки тв в файле plugin.php
Взято с https://modx.ru/novosti-i-stati/article/222/ и улучшено.
<?php
$page = $modx->getObject('modResource', $modx->resource->id);
$data = $modx->fromJSON(str_replace("'", '"', $page->getTVValue("grid")));
if(count($data) > 1){
$out = '<table><tbody>';
$frow = true;
foreach($data as $row){
$out .= "<tr>";
foreach($row as $cell){
if($frow){
$out .= '<th class="first_row">'.$cell['value'].'</th>';
}else{
if($cell['type'] == "TH"){
$out .= '<th>'.$cell['value'].'</th>';
}else{
$out .= '<td>'.$cell['value'].'</td>';
}
}
}
$out .= "</tr>";
$frow = false;
}
return $out."</tbody></table>";
}
@vasia123
Copy link
Author

// TODO: не хватает комментов в javascript коде и возможности удалить произвольный столбец/строку - соответственно и добавить.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment