Jump to content

Module Textformatter for UIKit images


Juergen
 Share

Recommended Posts

Hello,

I have written a small module which adds UIKit Framework markup to images added with CK-Editor

Here are  some screenshots:

1) Default view

uikit1.jpg

2) Hover over image shows an overlay and a tooltip info

uikit2.jpg

3) Open in UIKit lightbox

uikit3.jpg

 

How does it work?

The module uses Simple HTML DOM Parser for all the manipulations, so this file is also included in the module folder, but it doesnt add any UIKit CSS or Javascript. So you have to load the UIKit framework by yourself.

What manipulations take place?

  • Adds UIKit CSS classes to various tags (figure, anchor, image)
  • Adds "no-align" class to tags (figure, image anchor) without alignment, so it could be also styled with CSS
  • Adds an extra surrounding span container to images with no alignment and no figure tag to force block element behaviour
  • Adds UIKit lightbox attribute to linked images
  • Adds image alt attribute as title attribute for linked images on anchor tags / creates fallback if no alt attribute is present
  • Adds UIKit tooltip attribute to all anchors of linked images (tooltip text can be translated in the module translation file)
  • Adds UIKit overlay containers (additional markup) to linked images for overlay effect on hover

Example of Markup manipulation:

BEFORE
<figure class="align_left hidpi">
<a href="/site/assets/files/5556/bora_bora_3.jpg">
<img alt="Rochen" src="/site/assets/files/5556/bora_bora_3.150x0-is-hidpi.jpg" width="150">
</a>
<figcaption>Rochen</figcaption>
</figure>

AFTER
<figure class="uk-align-left hidpi">
<a href="/site/assets/files/5556/bora_bora_3.jpg" title="Opens the image in a lightbox view" data-uk-tooltip="" data-uk-lightbox="{group:'my-group'}" class="uk-thumbnail">
<div class="uk-overlay uk-overlay-hover">
<img alt="Rochen" src="/site/assets/files/5556/bora_bora_3.150x0-is-hidpi.jpg" width="150">
<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div>
</div>
</a>
<figcaption class="uk-thumbnail-caption">Rochen</figcaption>
</figure>

How to install the module?

Download the module: TextformatterUIKitImages.zip

Github: Download from Github

Extract the folder and upload the unzipped folder (including both files - simple_html_dom.php, TextformatterUIKitImages.module) into the site/modules folder. Please let both files into the TextformatterUIKitImages folder

- TextformatterUIKitImages (folder)

-|- TextformatterUIKitImages.modules (file)

-|- simple_html_dom.php (file)

Install the module as all other modules and add it f.e. to the body field.

Hint: I dont maintain the module, so its only here for people who are using UIKit framework too and want to manipulate the image markup of images added with CKEditor. It can also be used as a starting point for your own image markup manipulation module.

 

Best regards Jürgen

 

  • Like 6
Link to comment
Share on other sites

Please try to delete the file compiler cache. I have installed and deinstalled this module several times for testing purposes and it works in my case. I use the latest PW 3.0.41.

Maybe you can even try to deinstall the module and reinstall it. I am always running Tracy beside and I got no errors.

It seems that simple_html_dom.php is not present in your file compiler cache, because you have uploaded it afterwards.

Link to comment
Share on other sites

Installing the module is fine, but still no luck, I get the following error: Error: Call to a member function find() on boolean (line 35 of /site/assets/cache/FileCompiler/site/modules/TextformatterUIKitImages.module).

 

Sans titre-1.jpg

Edited by flydev
attached screenshot
Link to comment
Share on other sites

Mmmhh! A function like " $html->find" is a syntax of the dom file. Line 35 is the following:

foreach (($html->find('img')) as $img) {

if the file is integrated properly, it must work. I use simple_html_dom.php on another module too without problems. Have you tried to deinstall and delete the module first?

Link to comment
Share on other sites

Yes tested to uninstall and reinstall; I used Tracy in simple_html_dom.php and it look like I always get into the condition where $str is empty and so return false, line #95 in simple_html_dom.php.

// get html dom from string
function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
{
	$dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText);
	if (empty($str) || strlen($str) > MAX_FILE_SIZE)
	{
		$dom->clear();
		return false;
	}
	$dom->load($str, $lowercase, $stripRN);
	return $dom;
}

 

My body field contain mostly text and code formatted by the plugin pbckcode/highlight.js. I dont know if it can interfere.

Link to comment
Share on other sites

It could not be empty if something is in your body field.

I dont think that there is js conflict, but you can try to disable the plugin for testing purposes.

It is quite difficult for me, because in my case everything works as expected. It would be good if another person would install the module and try it out if it works.

<?php
/**
 * TextformatterUIKitImages (0.0.1)
 * This little Textformatter adds UIKit classes and markup to images added with CKEditor
 * Uses simple_html_dom.php because native dom makes problems by using HTML5 tags
 * @author Juergen Kern
 * 
 * ProcessWire 2.x
 * Copyright (C) 2011 by Ryan Cramer
 * Licensed under GNU/GPL v2, see LICENSE.TXT
 * 
 * http://www.processwire.com
 * http://www.ryancramer.com
 * 
 */
class TextformatterUIKitImages extends Textformatter implements Module
{
    public static function getModuleInfo()
    {
        return array(
            'title' => "TextformatterUIKitImages",
            'version' => "0.0.1",
            'summary' => "This little Textformatter adds UIKit classes and markup to images added with CKEditor",
            'author' => "Juergen Kern",
            'singular' => true,
            'permanent' => false,
            'requires' => array(
                "PHP>=5.4.0",
                "ProcessWire>=2.5.28",
                ""
            )
        );
    }
    public function format(&$str)
    {
        //check if simple_html_dom.php is included by another module before - prevent double including
        if (function_exists('file_get_html')) { //check for the file_get_html function
            //do nothing
        } else {
            require_once 'simple_html_dom.php';
        }
        $html        = str_get_html($str);
        //Manipulating figcaption with uikit css class   
        $figcaptions = $html->find('figcaption');
        foreach ($figcaptions as $caption) {
            $caption->class = 'uk-thumbnail-caption'; //add class to figure caption tag
        }
        foreach (($html->find('img')) as $img) {
            //manipulate image links with tooltip and lightbox attributes
            if ($img->parent->tag == 'a') {
                $pageId                            = (int) wire($this->page)->get('id'); //get current page id for lightbox group             
                $img->parent->{'data-uk-tooltip'}  = ''; //add tooltip attribute
                $img->parent->{'data-uk-lightbox'} = '{group:\'' . $pageId . '\'}'; //add lightbox attribute
                if ($img->alt) {
                    $img->parent->title = $img->alt; //add alt attribute as anchor title
                } else {
                    $img->parent->title = __("Lightbox view of the image"); //add default anchor title
                }
            }
            //create case types
            if (($img->parent->tag != 'a') && ($img->parent->tag != 'figure')) {
                $case = 'img';
            }
            if (($img->parent->tag == 'a') && ($img->parent->parent->tag != 'figure')) {
                $case = "a img";
            }
            if ($img->parent->tag == 'figure') {
                $case = "figure img";
            }
            if (($img->parent->tag == 'a') && ($img->parent->parent->tag == 'figure')) {
                $case = "figure a img";
            }
            switch ($case) {
                case 'img':
                    //create space before image class
                    if ($img->class) {
                        $img->class = ' ' . $img->class;
                    }
                    $img->class = 'uk-thumbnail' . $img->class;
                    if (strpos($img->class, 'align_left') !== false) {
                        $img->class = str_replace('align_left', 'uk-align-left', $img->class);
                    } elseif (strpos($img->class, 'align_right') !== false) {
                        $img->class = str_replace('align_right', 'uk-align-right', $img->class);
                    } elseif (strpos($img->class, 'align_center') !== false) {
                        $img->class = str_replace('align_center', 'uk-align-center uk-text-center', $img->class);
                    } else {
                        $img->class     = $img->class . ' no-align';
                        $img->outertext = '<span class="uk-display-block uk-margin-bottom">' . $img->outertext . '</span>';
                    }
                    break;
                case 'a img':
                    $img->parent->class = 'uk-thumbnail ' . $img->class;
                    if (strpos($img->class, 'align_left') !== false) {
                        $img->parent->class = str_replace('align_left', 'uk-align-left', $img->parent->class);
                        $img->outertext     = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>';
                    } elseif (strpos($img->class, 'align_right') !== false) {
                        $img->parent->class = str_replace('align_right', 'uk-align-right', $img->parent->class);
                        $img->outertext     = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>';
                    } elseif (strpos($img->class, 'align_center') !== false) {
                        $img->parent->class     = str_replace('align_center', 'uk-align-center uk-display-inline-block', $img->parent->class);
                        $img->outertext         = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>';
                        $img->parent->outertext = '<span class="uk-display-block uk-text-center test">' . $img->parent->outertext . '</span>';
                    } else {
                        $img->parent->class     = $img->class . ' no-align uk-thumbnail';
                        $img->outertext         = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>';
                        $img->parent->outertext = '<span class="uk-display-block uk-margin-bottom">' . $img->parent->outertext . '</span>';
                    }
                    $img->class = null;
                    break;
                case 'figure img':
                    if (strpos($img->parent->class, 'align_left') !== false) {
                        $img->parent->class = str_replace('align_left', 'uk-align-left', $img->parent->class);
                    } elseif (strpos($img->parent->class, 'align_right') !== false) {
                        $img->parent->class = str_replace('align_right', 'uk-align-right', $img->parent->class);
                    } elseif (strpos($img->parent->class, 'align_center') !== false) {
                        $img->parent->class = str_replace('align_center', 'uk-align-center uk-text-center', $img->parent->class);
                    } else {
                        $img->parent->class = 'uk-display-inline-block no-align';
                    }
                    $img->class = 'uk-thumbnail';
                    break;
                case 'figure a img':
                    if (strpos($img->parent->parent->class, 'align_left') !== false) {
                        $img->parent->parent->class = str_replace('align_left', 'uk-align-left', $img->parent->parent->class);
                        $img->outertext             = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>';
                    } elseif (strpos($img->parent->parent->class, 'align_right') !== false) {
                        $img->parent->parent->class = str_replace('align_right', 'uk-align-right', $img->parent->parent->class);
                        $img->outertext             = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>';
                    } elseif (strpos($img->parent->parent->class, 'align_center') !== false) {
                        $img->parent->parent->class = str_replace('align_center', 'uk-align-center uk-text-center', $img->parent->parent->class);
                        $img->outertext             = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>';
                    } else {
                        $img->parent->parent->class = $img->parent->parent->class . ' no-align uk-display-inline-block';
                        $img->outertext             = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>';
                    }
                    $img->parent->class = 'uk-thumbnail';
                    $img->class         = null;
                    break;
            }
        }
        $str = $html;
    }
}

 

Link to comment
Share on other sites

I have included a check if "simple_html_dom.php" is included by another module before, because I ran into an issue where 2 Textformatter modules use this file and both have included it. I have used "require_once" to prevent this behaviour but unfortunately it doesn work.

Therefore I run a check before the "require_once" which checks if a special function is loaded before.

        //check if simple_html_dom.php is included by another module before - prevent double including
        if (function_exists('file_get_html')) { //check for the file_get_html function
         //do nothing
        } else {
        require_once 'simple_html_dom.php';
        }

Description:

If the function "file_get_html" is loaded before by another module, skip the including of the simple_html_dom.php.

It works but if anyone has a better idea please let me know. The update is included in the download link of the first entry.

Link to comment
Share on other sites

I uninstalled the module, applied your change (the zipped file didn't include the modifications),  deleted the plugin pbckcode and commented the JS code, reinstalled the module and applied the Textformatter, still no luck, same error:

Quote

Fatal error: Call to a member function find() on boolean in /www/sites/blog/wwwroot/site/assets/cache/FileCompiler/site/modules/TextformatterUIKitImage/TextformatterUIKitImages.module on line 35


Its crazy. It will be cool if someone with a site build with the Uikit frameworks could try too. And if you want I can give you a superuser access to the site. For information I didnt tried on a fresh pw install (I need it on this site).

 

Edit:

The function check shouldn't be for the str_get_html() instead of file_get_html() ?

 

Link to comment
Share on other sites

26 minutes ago, flydev said:

(the zipped file didn't include the modifications)

No the zip file only includes the testing if  a special function  called "file_get_html" exists. It has nothing to do with str_get_html. You can also test for "str_get_html". These are special functions of simple_html_dom.php.

I only check if they are loaded before in another instance - if not then include the php file. The problem is that if they were loaded before you will get a "cannot redeclare class" error.

You can send me temp access data via PM and I will try it.

Link to comment
Share on other sites

instead of trying to figure out elsewhere if a class is loaded (file is included) or not, i only do it inside the file that should be included.

if(!class_exists("myClassName")) {
  class myClassName {
    // ...
  }
}

This way, one can include it multiple times in any order from everywhere without worrying.

  • Like 2
Link to comment
Share on other sites

Thanks for your hint @horst

the included file is an external library and for update reasons I prevent it from changes. Otherwise I have always to take care of my changes after updates. My first thought was that if I use "require_once" to include the file would prevent it from loading more than 1 time, but unfortunately this doesnt work.

Link to comment
Share on other sites

Code was rewritten to force better integration with CKEditor.

I have discovered problems with additionaly added figure tags and CKEditor. The editor has produced several empty paragraph tags. Replacing figure tags (block elements) with span tags (inline elements) has solved this problem and validates against W3C validator.

The manipulation code was also rewritten for better readableness. To see all changes please visit the Github page.

@flydev

I have tried to make the manipulations with native dom, but unfortunately it doesnt support HTML5 tags, so I have to use an external library.

Link to comment
Share on other sites

Module updated! There were some cases where the module has produced an error on boolean. This happens if the field where you have added the Textformatter is on the page but it is still empty. Then the manipulation functions fail. I have corrected this with a simple if condition check to prevent this error.

  • Like 3
Link to comment
Share on other sites

  • 10 months later...

For all of you who do not want to install a module: I have written a code snippet which could be copied into the ready.php.

But first of all you have to include the Simple HTML dom parser to your project - I recommend to install it via composer.

This is important because the manipulation of the markup depends on this library.

I use the manipulations only on my "body" field, so therefore I wrote 

if($page->template->hasField('body')){

but you can change the name of the field according to your needs.

So here we go: Copy this code into your ready.php

/**
 * UIkit Textformatter for body field
 * 
 * Changes various HTML elements to UIKit markup elements in the body field
 *
 * Tables
 * Unordered lists
 * Unordered list items
 * Ordered lists
 * Tooltips on links
 * Blockquotes     
 */
if($page->template->hasField('body')){
  $bodydom = HtmlDomParser::str_get_html($page->body);
  if (!empty($bodydom)) {
        //tables
        $tables = $bodydom->find('table');
        foreach($tables as $table){
          $table->style = null;
          $table->cellspacing = null;
          $table->cellpadding = null;
          $table->border = null;
          if($table->class){
          $table->class = 'uk-table '.$table->class;
          } else {
          $table->class = 'uk-table';
          }
        }
        //unordered lists
        $ulists = $bodydom->find('ul');
        foreach($ulists as $list){
         if($list->class){  
          $list->class = 'contentlist uk-list uk-list-space '.$list->class;
         } else {
          $list->class = 'contentlist uk-list uk-list-space';
         }
        }
        //unordered list items
        foreach($bodydom->find('ul li') as $li){
         $li->innertext = $li->innertext;
        }
        //ordered lists        
        $olists = $bodydom->find('ol');
        foreach($olists as $list){
         if($list->class){  
          $list->class = 'custom-counter '.$list->class;
         } else {
          $list->class = 'custom-counter';
         }
        }        
        //textlinks
        $anchors = $bodydom->find('a');
        foreach($anchors as $a){
          if(!empty(strip_tags($a->innertext))){
             $a->class = "textlink";
             $a->{'data-uk-tooltip'}  = '';
          }
        }
        //blockquotes
        $blockquotes = $bodydom->find('blockquote');
        foreach($blockquotes as $b){
           $b->innertext = '<i class="fa fa-quote-left fa-2x uk-align-left"></i>'.$b->innertext;
        } 
            //Manipulating figcaption with uikit css class   
            foreach (($bodydom->find('figcaption')) as $caption) {
                $caption->class = 'uk-thumbnail-caption'; //add class to figure caption tag
            }
            foreach (($bodydom->find('img')) as $img) {
                //manipulate image links with tooltip and lightbox attributes
                if ($img->parent->tag == 'a') {
                    $pageId                            = (int) wire($this->page)->get('id'); //get current page id for lightbox group             
                    $img->parent->{'data-uk-tooltip'}  = ''; //add tooltip attribute
                    $img->parent->{'data-uk-lightbox'} = '{group:\'' . $pageId . '\'}'; //add lightbox attribute
                    if ($img->alt) {
                        $img->parent->title = $img->alt; //add alt attribute as anchor title
                    } else {
                        $img->parent->title = __("Lightbox view of the image"); //add default anchor title
                    }
                }
                //create case types
                if (($img->parent->tag != 'a') && ($img->parent->tag != 'figure')) {
                    $case = 'img';
                }
                if (($img->parent->tag == 'a') && ($img->parent->parent->tag != 'figure')) {
                    $case = "a img";
                }
                if ($img->parent->tag == 'figure') {
                    $case = "figure img";
                }
                if (($img->parent->tag == 'a') && ($img->parent->parent->tag == 'figure')) {
                    $case = "figure a img";
                }
                switch ($case) {
                    case 'img':
                        //create space before image class
                        if ($img->class) {
                            $img->class = ' ' . $img->class;
                        }
                        $img->class = 'uk-thumbnail' . $img->class;
                        if (strpos($img->class, 'align_left') !== false) {
                            $img->class = str_replace('align_left', 'uk-align-left', $img->class);
                        } elseif (strpos($img->class, 'align_right') !== false) {
                            $img->class = str_replace('align_right', 'uk-align-right', $img->class);
                        } elseif (strpos($img->class, 'align_center') !== false) {
                            $img->class = str_replace('align_center', 'uk-align-center uk-text-center', $img->class);
                        } else {
                            $img->class     = $img->class . ' no-align';
                            $img->outertext = '<span class="uk-display-block uk-margin-bottom">' . $img->outertext . '</span>';
                        }
                        break;
                    case 'a img':
                        $img->parent->class = 'uk-thumbnail ' . $img->class;
                        if (strpos($img->class, 'align_left') !== false) {
                            $img->parent->class = str_replace('align_left', 'uk-align-left', $img->parent->class);
                            $img->outertext     = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>';
                        } elseif (strpos($img->class, 'align_right') !== false) {
                            $img->parent->class = str_replace('align_right', 'uk-align-right', $img->parent->class);
                            $img->outertext     = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>';
                        } elseif (strpos($img->class, 'align_center') !== false) {
                            $img->parent->class     = str_replace('align_center', 'uk-align-center uk-display-inline-block', $img->parent->class);
                            $img->outertext         = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>';
                            $img->parent->outertext = '<span class="uk-display-block uk-text-center test">' . $img->parent->outertext . '</span>';
                        } else {
                            $img->parent->class     = $img->class . ' no-align uk-thumbnail';
                            $img->outertext         = '<span class="uk-overlay uk-overlay-hover">' . $img->outertext . '<span class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></span></span>';
                            $img->parent->outertext = '<span class="uk-display-block uk-margin-bottom">' . $img->parent->outertext . '</span>';
                        }
                        $img->class = null;
                        break;
                    case 'figure img':
                        if (strpos($img->parent->class, 'align_left') !== false) {
                            $img->parent->class = str_replace('align_left', 'uk-align-left', $img->parent->class);
                        } elseif (strpos($img->parent->class, 'align_right') !== false) {
                            $img->parent->class = str_replace('align_right', 'uk-align-right', $img->parent->class);
                        } elseif (strpos($img->parent->class, 'align_center') !== false) {
                            $img->parent->class = str_replace('align_center', 'uk-align-center uk-text-center', $img->parent->class);
                        } else {
                            $img->parent->class = 'uk-display-inline-block no-align';
                        }
                        $img->class = 'uk-thumbnail';
                        break;
                    case 'figure a img':
                        if (strpos($img->parent->parent->class, 'align_left') !== false) {
                            $img->parent->parent->class = str_replace('align_left', 'uk-align-left', $img->parent->parent->class);
                            $img->outertext             = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>';
                        } elseif (strpos($img->parent->parent->class, 'align_right') !== false) {
                            $img->parent->parent->class = str_replace('align_right', 'uk-align-right', $img->parent->parent->class);
                            $img->outertext             = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>';
                        } elseif (strpos($img->parent->parent->class, 'align_center') !== false) {
                            $img->parent->parent->class = str_replace('align_center', 'uk-align-center uk-text-center', $img->parent->parent->class);
                            $img->outertext             = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>';
                        } else {
                            $img->parent->parent->class = $img->parent->parent->class . ' no-align uk-display-inline-block';
                            $img->outertext             = '<div class="uk-overlay uk-overlay-hover">' . $img->outertext . '<div class="uk-overlay-panel uk-overlay-background uk-overlay-icon"></div></div>';
                        }
                        $img->parent->class = 'uk-thumbnail';
                        $img->class         = null;
                        break;
                }
            }        
        //add manipulations to body field
        $page->body = $bodydom; 
  }
}

Thats all!

All these elements will be enriched with UIKit 2 Markup. Remember: If Simple HTML Dom Parser is not correctly installed, you will get an error.

Some of the styles I use are the ones that I prefer. Maybe you prefer an other style that UIKit offers. So you can change the CSS classes to your prefered style. This code only should give you an inspiration on how to manipulate markup.

Best regards.

 

 

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...