Тема: Конвертувати таблицю в контейнер
Потрібно адаптувати старий сайт для мобільних телефоні і планшетів, цей сайт містить багато таблицю, які мають в залежності від пристрою адаптуватися під розмір екрану (для планшетів - зменшитися, для телефонів - стати списком), так як таблиця досить не зручна (наприклад, як таблицю можна показати у вигляді списку для мобільних телефонів ?) я вирішив конвертувати її в контейнер.
Написав клас для конвертації, але він досить "сирий" і взагалі я думаю що конвертацію можна зробити за допомогою регулярних виразів, але не знаю як.
class converToDiv
{
private $index = 0;
private $beginTag = -1;
private $endTag = -1;
private $tagName = '';
private $isTagOpened;
private $HTML_table;
private $HTML_tableLen = -1;
private $replaceTag = array();
private $standardTags = true;
private $namespace_ = '';
private function replaceTagOnDiv()
{
if(!isset($this->replaceTag[$this->tagName])) return;
$newTag = '<';
if($this->isTagOpened)
{
$newTag .= 'div class="'.$this->replaceTag[$this->tagName].'"';
}
else
{
$newTag .= '/div';
}
$newTag .= '>';
$pattern = substr(
$this->HTML_table,
$this->beginTag,
$this->endTag - $this->beginTag + 1
);
$this->HTML_table =
str_replace($pattern, $newTag, $this->HTML_table);
$this->index = $this->beginTag + strlen($newTag) - 1;
}
private function clearTagVar()
{
$this->beginTag = -1;
$this->endTag = -1;
$this->tagName = '';
$this->isTagOpened = 0;
$this->HTML_tableLen = strlen($this->HTML_table);
}
private function beginTagFun()
{
$this->beginTag = $this->index;
//check that the tag is closed or opened
if($this->HTML_table[++$this->index]=='/')
{
$this->isTagOpened = false;
//Go to the next symbol (skip a '/' symbol)
++$this->index;
}
else
{
$this->isTagOpened = true;
}
//Try to get the name
do
{
if(
$this->HTML_table[$this->index] != ' ' &&
$this->HTML_table[$this->index] != '>'
)
$this->tagName .= $this->HTML_table[$this->index];
else
break;
}
while(
/*If the loop goes beyond the possible values*/
++$this->index < $this->HTML_tableLen
);
}
private function endTagFun()
{
$this->endTag = $this->index;
//start to replace ...
$this->replaceTagOnDiv();
$this->clearTagVar();
}
private function skipQuotationMarks()
{
//determine the type of quotation marks
$typeOfQuotationMarks = $this->HTML_table[$this->index];
//skip quotation marks
while(
$this->index < $this->HTML_tableLen &&
$typeOfQuotationMarks != $this->HTML_table[++$this->index]
);
}
private function findTag()
{
$insideTag = false;
for($this->index = 0; $this->index < $this->HTML_tableLen; $this->index++)
{
if($this->HTML_table[$this->index]==='<')
{
$this->beginTagFun();
$insideTag = true;
}
if ($this->HTML_table[$this->index]==='>')
{
$this->endTagFun();
$insideTag = false;
}
if (
($this->HTML_table[$this->index]==='\'' ||
$this->HTML_table[$this->index]==='"') &&
$insideTag
)
{
$this->skipQuotationMarks();
}
}
}
private function initStandardTags()
{
if( !$this->standardTags )
return;
$this->replaceTag['table'] = $this->namespace_ . 'styleTable';
$this->replaceTag['tbody'] = $this->namespace_ . 'styleTbody';
$this->replaceTag['th'] = $this->namespace_ . 'styleTh';
$this->replaceTag['tr'] = $this->namespace_ . 'styleTr';
$this->replaceTag['td'] = $this->namespace_ . 'styleTd';
$this->replaceTag['caption'] = $this->namespace_ . 'styleCaption';
$this->replaceTag['colgroup'] = $this->namespace_ . 'styleColgroup';
$this->replaceTag['col'] = $this->namespace_ . 'styleCol';
$this->replaceTag['thead'] = $this->namespace_ . 'styleThead';
$this->replaceTag['tfoot'] = $this->namespace_ . 'styleTfoot';
}
public function printConvertedTable()
{
echo $this->HTML_table;
}
public function getConvertedTable()
{
return $this->HTML_table;
}
public function functionsetSpecificTags($currentTagName, $replacementTagName)
{
$this->replaceTag[strval($currentTagName)] = strval($replacementTagName);
}
public function setStandardTags($val)
{
$this->standardTags = boolval($val);
}
public function setHTMLTable($HTML_table)
{
$this->HTML_table = $HTML_table;
}
public function setNamespace($namespace_)
{
$this->namespace_ = $namespace_;
}
public function runConverToDiv()
{
$this->initStandardTags();
$this->clearTagVar();
$this->findTag();
}
function __construct($HTML_table, $namespace_ = '')
{
$this->HTML_table = $HTML_table;
$this->namespace_ = $namespace_;
}
}
Як з ним працювати:
1) Спочатку створюється об'єкт
в якості параметрів можна передати (перший параметр) весь HTML код, в такому випадку тегі що не відносяться до таблиці будуть пропущені, або HTML код таблиці
(другий параметр) простір імен для CSS. (не обов'язково)
$ob = new converToDiv($str, 'st_');
або створити об'єкт, і встановити функціями HTML код і простір імен
$ob = new converToDiv();
$ob->setHTMLTable($str);
$ob->setNamespace( 'st_' );
2) (не обов'язково) Вказати чи використовувати стандартні тегі, які відносяться до таблиці. Під стандартними тегами мається на увазі:
table, tbody, th, tr, td, caption, colgroup, col, thead, tfoot
$ob->setStandardTags(true);
якщо встановити false - масив тегів буде пустий
3) (не обов'язково) Додати нові тегі які потрібно замінити
$currentTagName - який тег потрібно знайти і замінити
$replacementTagName - на що потрібно замінити
$ob->setSpecificTags($currentTagName, $replacementTagName);
4) Виконати конвертацію
$ob->runConverToDiv();
5) Отримати результат
Вивести результат
$ob->printConvertedTable();
Або
Отримати у вигляді рядка
$ob->getConvertedTable();
CSS класи будуть називатися
[простір імен]_style[тег, перший символ великий];
наприклад:
[простір імен] = my_,
[тег, перший символ великий] = table,
my_styleTable;
Ну, а дальше пишіть CSS стилі, наприклад так
.st_styleTr
{
display: -webkit-flex;
display: flex;
-webkit-justify-content: center;
justify-content: center;
border-color: red;
border-style: solid;
border-width: 1px;
}
.st_styleTd
{
height: auto;
margin: 1px auto;
padding: 2px;
border-color: green;
border-style: solid;
border-width: 1px;
width: -webkit-fill-available;
}
Замітка:
- Звичайно, цей клас потрібно використати для заміні таблиці, але не фільтрації вмісту при відкриті сторінки, тому що цей клас забирає багато ресурсів і сповільнює роботу сторінки
- Щоб цей клас нічого "зайвого" не зробив, варто зробити резервну копію сайту і попередньо перевірити чи точно сторінка має таблиці
if( strpos($content, '<table') === false ) return $content;
$ob = new converToDiv($str, 'st_');
...
- Клас не розрахований на помилки, тобто якщо якийсь тег не буде закриватися, чи ще щось подібне станеться, результат буде непередбачуваний
Можливо хтось стикався з проблемою адаптації таблиці під мобільні телефони і планшети, як це вирішується ?
Якщо хтось зацікавлений в цьому класі, допоможіть доробити "об'єднання комірок", поки що цей клас ніяк не реагує на об'єднання комірок, і можливо зробити його "біль продуманим".
Клас не прокоментований, бо він відносно малий, думаю вам буде зрозуміло як він працює і без коментарів.