parent
fa9325577f
commit
3f8fa07a82
@ -0,0 +1,80 @@ |
||||
<?php |
||||
|
||||
|
||||
namespace App\View; |
||||
|
||||
/** |
||||
* Collapsible text box widget |
||||
*/ |
||||
class CollapsibleTextBoxWidget |
||||
{ |
||||
private $maxHeight; |
||||
private $collapsing; |
||||
private $text; |
||||
private $srPrefix; |
||||
private $srEscape; |
||||
|
||||
/** |
||||
* Add a prefix inside the text box shown only to screen readers, Lynx etc. |
||||
* |
||||
* @param string $content |
||||
* @param bool $escape - use html escape, default true |
||||
* @return $this |
||||
*/ |
||||
public function srPrefix($content, $escape=true) |
||||
{ |
||||
$this->srEscape = $escape; |
||||
$this->srPrefix = $content; |
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @param string $text - text to show |
||||
* @param int $thresholdLength - mb_character length that triggers the collapsible behavior; choose experimentally |
||||
* @param string $maxHeight - max height CSS value (e.g. 8em) |
||||
*/ |
||||
public function __construct($text, $thresholdLength, $maxHeight) |
||||
{ |
||||
$this->text = $text; |
||||
$this->collapsing = mb_strlen($text) > $thresholdLength; |
||||
$this->maxHeight = $maxHeight; |
||||
} |
||||
|
||||
private function processText($t) |
||||
{ |
||||
$out = e($t); |
||||
$out = str_replace("\r\n", "\n", $out); |
||||
|
||||
$out = '<p class="last-p-mb-0"> '.str_replace("\n\n", |
||||
" </p>". '<p class="last-p-mb-0"> ', $out).' </p>'; |
||||
|
||||
$out = nl2br($out); |
||||
|
||||
$out = preg_replace('|(https?://[^\s]+)|i', '<a href="\1">\1</a>', $out); |
||||
|
||||
return $out; |
||||
} |
||||
|
||||
public function render() |
||||
{ |
||||
$content = $this->processText($this->text); |
||||
|
||||
$prefix = ''; |
||||
if ($this->srPrefix) { |
||||
$prefix = '<span class="sr-only">'. |
||||
($this->srEscape ? e($this->srPrefix) : $this->srPrefix). |
||||
' </span>'; |
||||
} |
||||
|
||||
if ($this->collapsing) { |
||||
return '<div class="block-collapse" style="max-height:'.$this->maxHeight.'">' . $prefix . $content . '</div>'; |
||||
} else { |
||||
return $prefix.'<div>' . $prefix . $content . '</div>'; |
||||
} |
||||
} |
||||
|
||||
public function __toString() |
||||
{ |
||||
return (string) $this->render(); |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
.block-collapse { |
||||
overflow: hidden; |
||||
text-overflow: ellipsis; |
||||
position: relative; |
||||
|
||||
&::before, |
||||
&::after { |
||||
position: absolute; |
||||
right: 0; |
||||
bottom: 0; |
||||
text-align: right; |
||||
height: 1.7em; |
||||
line-height: 1.7em; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
&::after{ |
||||
content: ''; |
||||
width: 70%; |
||||
background: linear-gradient(to right, rgba(255, 255, 255, 0), white 90%); |
||||
} |
||||
|
||||
&::before { |
||||
content: '▼'; |
||||
z-index: 10; |
||||
color: $gray-500; |
||||
} |
||||
|
||||
&.reveal { |
||||
max-height: unset !important; // override inline styles |
||||
|
||||
&::before, &::after { |
||||
display: none; |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue