]> _ Git - cubeextranet.git/commitdiff
Merge master branch to html5video and solve conflicts. WIP #897 @1
authorstephen@cubedesigners.com <stephen@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Thu, 29 Jun 2017 17:27:21 +0000 (17:27 +0000)
committerstephen@cubedesigners.com <stephen@cubedesigners.com@f5622870-0f3c-0410-866d-9cb505b7a8ef>
Thu, 29 Jun 2017 17:27:21 +0000 (17:27 +0000)
inc/ws/Util/html5/html5video/class.ws.html5.compiler.php
inc/ws/Util/html5/html5video/class.ws.html5.links.php

index 177f78ccfd2594ad9ce18acb9e8c905db1cb747e..7b67d3e859006a057931d192037f6dae37c68189 100644 (file)
@@ -38,6 +38,7 @@ class wsHTML5Compiler {
                'js/libs/fluidbook/fluidbook.desktop.js',
                'js/libs/fluidbook/fluidbook.service.js',
                'js/libs/fluidbook/fluidbook.l10n.js',
+               'js/libs/fluidbook/fluidbook.slider.js',
                'js/libs/fluidbook/fluidbook.nav.js',
                'js/libs/fluidbook/fluidbook.touch.js',
                'js/libs/fluidbook/fluidbook.interact.js',
@@ -87,10 +88,10 @@ class wsHTML5Compiler {
                'js/widget.js'
        );
 
-    // Collection of LESS files to be compiled
-    // Filename with no extension, relative to the /style directory in the player build folder
-    public $lessFiles = ['fluidbook'];
-    public $lessFilesExtras = []; // Extra files that will be copied when compiling LESS (eg. used to allow video-js-core.css to be copied)
+       // Collection of LESS files to be compiled
+       // Filename with no extension, relative to the /style directory in the player build folder
+       public $lessFiles = ['fluidbook'];
+       public $lessFilesExtras = []; // Extra files that will be copied when compiling LESS (eg. used to allow video-js-core.css to be copied)
 
        public $specialCSS = array();
        public $phonegapStandardPlugins = array('ios' => array('ExternalFileUtil'),
@@ -157,11 +158,14 @@ class wsHTML5Compiler {
        protected $multiApp = false;
        protected $pageLabels = array();
        protected $stylesheets = array();
+       protected $logfp = null;
+       protected $logtime = null;
 
 
        function __construct($book_id, $version = 'stable', $phonegap = false, $phonegapVersion = 'latest', $dir = null, $standalone = false, $appcache = false, $home = false) {
                global $core;
 
+
                $this->phonegapVersion = wsHTML5::getPhonegapVersion($phonegapVersion);
                $this->appcache = $appcache;
                $this->multiApp = $this->home = $home;
@@ -187,6 +191,7 @@ class wsHTML5Compiler {
                        return;
                }
                $this->book_id = $book_id;
+               $this->log('Start compilation');
 
                if (is_null($dir)) {
                        $this->dir = WS_BOOKS . '/html5/' . $book_id . '/';
@@ -201,6 +206,7 @@ class wsHTML5Compiler {
                if (!file_exists($this->dir)) {
                        mkdir($this->dir, 0777, true);
                }
+               $this->log('Clean vdir');
 
                $this->daoBook = new wsDAOBook($core->con);
                $this->book = $this->daoBook->selectById($book_id);
@@ -247,6 +253,20 @@ class wsHTML5Compiler {
                $this->config = cubeObject::merge($this->book->parametres->toStandardObject(), $this->theme->parametres->toStandardObject());
        }
 
+       public function log($step) {
+               $currenttime = microtime(true);
+               if (null === $this->logfp) {
+                       $this->logfp = fopen('/var/log/extranet/htmlconversions/' . $this->book_id . '.log', 'w+');
+               }
+               if (null === $this->logtime) {
+                       $this->logtime = $currenttime;
+               }
+               $time = $currenttime - $this->logtime;
+               $log = $step . ' | ' . round($time, 3) . 's' . "\n";
+               fwrite($this->logfp, $log);
+               $this->logtime = $currenttime;
+       }
+
        public function addPageLabel($page, $label) {
                $this->pageLabels[$label] = $page;
        }
@@ -276,6 +296,8 @@ class wsHTML5Compiler {
 
        public function compile() {
 
+               $this->log('Start compile process');
+
                $dirsToCreate = array('data/images', 'data/contents', 'data/background', 'data/thumbnails', 'data/style');
                if (in_array('flv', $this->getVideosFormats())) {
                        $dirsToCreate[] = 'swf';
@@ -310,17 +332,27 @@ class wsHTML5Compiler {
                if (file_exists($this->vdir . '/swf')) {
                        $this->copy($this->assets . '/swf/video.swf', $this->vdir . '/swf/video.swf');
                }
-
+               $this->log('Copied assets');
                $this->loadPlugins();
+               $this->log('Plugins loaded');
                $this->writeImages();
+               $this->log('Images written');
                $linksCSS = $this->writeLinks();
+               $this->log('Links written');
                $this->writeCSS($this->vdir . '/data/style/style_%d.css', $linksCSS);
+               $this->log('CSS written');
                $this->writeLangs();
+               $this->log('Langs written');
                $this->writeIndex();
+               $this->log('Index written');
                $this->writeTexts();
+               $this->log('Texts written');
                $this->writeExtras();
+               $this->log('Extras written');
                $this->writeJs();
+               $this->log('Js written');
                $this->writeCache();
+               $this->log('Cache written');
        }
 
        protected function loadPlugins() {
@@ -363,16 +395,16 @@ class wsHTML5Compiler {
 
        public function getVideosFormats($poster = true) {
                $res = [];
-//
-//        if (!$this->phonegap) {
-//                     $res = array('ogv', 'webm', 'mp4', 'flv');
-//             } elseif ($this->phonegap == 'ios') {
-//                     $res = array('mp4');
-//             } else if ($this->phonegap == 'android') {
-//                     $res = array('webm', 'mp4');
-//             }
+               //
+               //        if (!$this->phonegap) {
+               //                      $res = array('ogv', 'webm', 'mp4', 'flv');
+               //              } elseif ($this->phonegap == 'ios') {
+               //                      $res = array('mp4');
+               //              } else if ($this->phonegap == 'android') {
+               //                      $res = array('webm', 'mp4');
+               //              }
 
-        $res[] = 'mp4';
+               $res[] = 'mp4';
 
                if ($poster) {
                        $res[] = 'jpg';
@@ -429,37 +461,37 @@ class wsHTML5Compiler {
                file_put_contents($cacheFile, implode("\n", $lines));
        }
 
-    /**
-     * Helper function to add a unique script entry to the JS stack.
-     * Normally this is a relative path but it can be an external URL.
-     * External URLs are added to the pluginJs collection instead of jsFiles.
-     * Duplicate paths are ignored.
-     * @param $path
-     */
-    public function addJs($path) {
-
-        // If JS is external, it will be included via the pluginJs collection
-        // Otherwise, it will be compiled into the main JS file
-        $collection = (preg_match('#^https?://#i', $path) === 1) ? 'pluginJs' : 'jsFiles';
-
-        if (!in_array($path, $this->$collection)) {
-            $this->{$collection}[] = $path;
-        }
+       /**
+        * Helper function to add a unique script entry to the JS stack.
+        * Normally this is a relative path but it can be an external URL.
+        * External URLs are added to the pluginJs collection instead of jsFiles.
+        * Duplicate paths are ignored.
+        * @param $path
+        */
+       public function addJs($path) {
+
+               // If JS is external, it will be included via the pluginJs collection
+               // Otherwise, it will be compiled into the main JS file
+               $collection = (preg_match('#^https?://#i', $path) === 1) ? 'pluginJs' : 'jsFiles';
+
+               if (!in_array($path, $this->$collection)) {
+                       $this->{$collection}[] = $path;
+               }
        }
 
-    /**
-     * Helper function to add a unique stylesheet entry to the LESS stack for compilation
-     * Duplicate paths are ignored.
-     * @param $path The path of the file relative to the /style folder, without any extension
-     * @param $extra_files Optional array of extra files that should be copied across for use during LESS compilation
-     */
-    public function addLess($path, $extra_files = []) {
-        if (!in_array($path, $this->lessFiles)) {
-            $this->lessFiles[] = $path;
-        }
-
-        // Make sure no duplicates are added here either
-        $this->lessFilesExtras = array_unique(array_merge($this->lessFilesExtras, $extra_files));
+       /**
+        * Helper function to add a unique stylesheet entry to the LESS stack for compilation
+        * Duplicate paths are ignored.
+        * @param $path The path of the file relative to the /style folder, without any extension
+        * @param $extra_files Optional array of extra files that should be copied across for use during LESS compilation
+        */
+       public function addLess($path, $extra_files = []) {
+               if (!in_array($path, $this->lessFiles)) {
+                       $this->lessFiles[] = $path;
+               }
+
+               // Make sure no duplicates are added here either
+               $this->lessFilesExtras = array_unique(array_merge($this->lessFilesExtras, $extra_files));
        }
 
        protected function writeIndex() {
@@ -497,6 +529,11 @@ class wsHTML5Compiler {
                if ($this->book->parametres->googleAnalyticsCustom != '') {
                        $ga .= $this->book->parametres->googleAnalyticsCustom;
                }
+
+               $statsfooter = '';
+               if ($this->book->parametres->statsCustom != '') {
+                       $statsfooter = $this->book->parametres->statsCustom;
+               }
                // Feuilles de style
                $sheets = array_merge($this->stylesheets, $this->specialCSS);
 
@@ -564,7 +601,7 @@ class wsHTML5Compiler {
                }
 
 
-               $vars = array('titre', 'credits', 'ga', 'style', 'script', 'pagesContents', 'description', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon', 'svg');
+               $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'pagesContents', 'description', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon', 'svg');
                foreach ($vars as $v) {
                        $html = str_replace('<!-- $' . $v . ' -->', $$v, $html);
                }
@@ -593,13 +630,13 @@ class wsHTML5Compiler {
 
                $thtml = $uhtml;
 
-               $vars = array('titre', 'credits', 'ga', 'style', 'script', 'pagesContents', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon');
+               $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'pagesContents', 'print', 'hiddenContents', 'splash', 'cache', 'bgcolor', 'message', 'favicon');
                foreach ($vars as $v) {
                        $uhtml = str_replace('<!-- $' . $v . ' -->', $$v, $uhtml);
                }
 
                $script .= "\n\t\t" . '<script type="text/javascript" charset="utf-8">window.tester = true;</script>';
-               $vars = array('titre', 'credits', 'ga', 'style', 'script', 'print', 'hiddenContents', 'splash', 'message');
+               $vars = array('titre', 'credits', 'statsfooter', 'ga', 'style', 'script', 'print', 'hiddenContents', 'splash', 'message');
                foreach ($vars as $v) {
                        $thtml = str_replace('<!-- $' . $v . ' -->', $$v, $thtml);
                }
@@ -873,7 +910,7 @@ class wsHTML5Compiler {
                        }
                        if (file_exists($minimized)) {
                                $mintime = filemtime($minimized);
-                           $reminimize = false;
+                               $reminimize = false;
                        } else {
                                $mintime = 0;
                                $reminimize = true;
@@ -1058,10 +1095,12 @@ class wsHTML5Compiler {
                if ($this->backgroundsPrefix == 'p') {
                        $srcPrefix = 'h';
                }
+               $thumbs = array();
                foreach ($this->pages as $page => $infos) {
+                       $docdir = wsDocument::getDir($infos['document_id']);
                        if ($this->svg) {
-                               $orig = wsDocument::getDir($infos['document_id']) . 'html/p' . $infos['document_page'] . '.svg';
-                               $opt = wsDocument::getDir($infos['document_id']) . 'html/o' . $infos['document_page'] . '.svg';
+                               $orig = $docdir . 'html/p' . $infos['document_page'] . '.svg';
+                               $opt = $docdir . 'html/o' . $infos['document_page'] . '.svg';
 
                                $svg = $orig;
                                if (file_exists($opt) && filesize($opt) > 0) {
@@ -1072,10 +1111,11 @@ class wsHTML5Compiler {
                        }
 
                        foreach ($this->getResolutions() as $r) {
-                               $ok = $this->copy(wsDocument::getDir($infos['document_id']) . 'html/' . $srcPrefix . $r . '-' . $infos['document_page'] . '.jpg', $this->vdir . '/data/background/' . $r . '/' . $this->backgroundsPrefix . $page . '.jpg');
+                               $ok = $this->copy($docdir . 'html/' . $srcPrefix . $r . '-' . $infos['document_page'] . '.jpg', $this->vdir . '/data/background/' . $r . '/' . $this->backgroundsPrefix . $page . '.jpg');
                                if (!$ok && $r = 300) {
                                        $this->maxRes = 150;
                                }
+                       $this->copy(WS_DOCS . '/' . $infos['document_id'] . '/p' . $infos['document_page'] . '.jpg', $this->vdir . '/data/thumbnails/p' . $page . '.jpg');
                        }
 
                        $thumb = false;
@@ -1083,16 +1123,54 @@ class wsHTML5Compiler {
                                $thumb = wsPDFConvert::getThumbFromPDF(WS_BOOKS . '/working/' . $this->book->book_id . '/' . $this->book->parametres->pdfThumbnails, $page);
                        }
                        if (!$thumb) {
-                               $thumb = wsDocument::getDir($infos['document_id']) . 'p' . $infos['document_page'] . '.jpg';
+                               $thumb = $docdir . 'p' . $infos['document_page'] . '.jpg';
                        }
 
-
-                       $this->copy($thumb, $this->vdir . '/data/thumbnails/p' . $page . '.jpg');
+                       $thumbs[$page] = $thumb;
 
                        if ($page == 1) {
-                               $this->_makeCover(wsDocument::getDir($infos['document_id']) . 'html/t36-' . $infos['document_page'] . '.jpg');
+                               $this->_makeCover($docdir . 'html/t36-' . $infos['document_page'] . '.jpg');
+                       }
+                       $this->makeThumbSprites($thumbs);
+                       $this->log('Copied image ' . $page);
+               }
+       }
+
+       public function makeThumbSprites(array $thumbs) {
+               $cols = 10;
+               $rows = 10;
+               $perSprite = $cols * $rows;
+               $k = 0;
+               $res = '';
+               $pages = count($thumbs);
+
+               $hash = '';
+               for ($i = 1; $i <= $pages; $i += $perSprite) {
+                       $num = min(1 + $pages - $i, $perSprite);
+                       $srows = ceil($num / $cols);
+                       $files = array();
+                       $mtime = 0;
+                       for ($j = 0; $j < $perSprite; $j++) {
+                               $p = $i + $j;
+                               if ($p > $pages) {
+                                       break;
+                               }
+                               $files[] = $thumbs[$p];
+                               $hash .= $thumbs[$p] . '--' . filemtime($thumbs[$p]);
+                       }
+
+                       $cache = WS_CACHE . '/thumbsprites/' . hash('sha256', $hash) . '.jpg';
+                       $dest = $this->vdir . '/data/thumbnails/s' . $k . '.jpg';
+                       if (!file_exists($cache)) {
+                               $ratio = $this->width / $this->height;
+                               $thumbh = round(100 / $ratio);
+                               $cmd = 'montage ' . implode(' ', $files) . ' -geometry 100x' . $thumbh . '!+0+0 -background transparent -tile ' . $cols . 'x' . $srows . ' ' . $cache;
+                               $res .= `$cmd`;
                        }
+                       copy($cache, $dest);
+                       $k++;
                }
+               return $res;
        }
 
        protected function _makeCover($orig) {
@@ -1136,10 +1214,16 @@ class wsHTML5Compiler {
                return true;
        }
 
+       protected function _lessBoolean($val) {
+               return $val ? 'true' : 'false';
+       }
+
        protected function writeCSS($file, $links) {
                $res = array();
 
                $lessVariables = array();
+               $lessVariables['slider-display'] = $this->_lessBoolean($this->theme->parametres->pagesBar);
+               $lessVariables['slider-thumb-background'] = wsHTML5::colorToCSS($this->theme->parametres->pageBarThumbBack);
 
                // General theme
                $cssWidth = $this->cssWidth;
@@ -1157,8 +1241,11 @@ class wsHTML5Compiler {
                $offsetLeft2 = $offsetLeft * 2;
                $offsetTop = round(($this->optimalHeight - $cssHeight) / 2, 3);
                $navTop = ($cssHeight - 40 - 100) / 2;
-               $leftOfRightPage=(floor($cssWidth)-1).'px';
+               $leftOfRightPage = (floor($cssWidth) - 1) . 'px';
 
+               $lessVariables['z'] = $this->z;
+               $lessVariables['book-page-width'] = $w;
+               $lessVariables['book-page-height'] = $h;
 
                $res[] = '.portrait #pages,.portrait .doublePage.page,.page,.doublePage._3d,#shadow>div{width:' . $w . ';max-width:' . $w . ';height:' . $h . ';max-height:' . $h . '}';
                $res[] = '.doublePage,#pages,#links{width:' . $w2 . ';max-width:' . $w2 . ';height:' . $h . ';max-height:' . $h . '}';
@@ -1173,12 +1260,10 @@ class wsHTML5Compiler {
                $res[] = '#links.right{left:-' . $w . ';}';
                $res[] = '.landscape #shadow>div.right{left: ' . $w . ';}';
                $res[] = '.landscape .page.right{left:' . $w . '}';
-               if ($this->theme->parametres->displayPageNumber) {
-                       $res[] = '#pagesnumbers{font-size: ' . (12 * $this->z) . 'px;margin: ' . (5 * $this->z) . 'px 0 0 0;top:' . $h . ';color:' . wsHTML5::colorToCSS($this->theme->parametres->colorPageNumber) . '}';
-                       $res[] = '#pagesnumbers div{width:' . $w . '}';
-               } else {
-                       $res[] = '#pagesnumbers{display:none;}';
-               }
+
+               $lessVariables['page-number-color'] = wsHTML5::colorToCSS($this->theme->parametres->colorPageNumber);
+               $lessVariables['display-page-number'] = $this->_lessBoolean($this->theme->parametres->displayPageNumber);
+
                $res[] = '.doublePage._2d,.doublePage._3d{' . wsHTML5::writeCSSUA('transition', 'all ' . $this->book->parametres->mobileTransitionDuration . 's ease-in-out') . '}';
 
                $res[] = '.background{' . wsHTML5::writeCSSUA('transform-origin', 'top left') . ';}';
@@ -1274,11 +1359,10 @@ class wsHTML5Compiler {
                        $res[] = '#shadow>div{' . wsHTML5::writeCSSUA('box-shadow', '0 0 20px ' . $shadowColor) . '}';
                }
 
+               $lessVariables['links-color']=wsHTML5::colorToCSS($this->theme->parametres->linksColor);
+
                // Links Styles
                $res = array_merge($res, $links);
-               $res[] = '.link a.displayArea:hover,.link a.displayArea.animating{background-color:' . wsHTML5::colorToCSS($this->theme->parametres->linksColor, 0.4) . ';}';
-               $res[] = '.link a.displayArea:hover{opacity:1 !important;}';
-               $res[] = '.link a.displayArea{-webkit-tap-highlight-color:' . wsHTML5::colorToCSS($this->theme->parametres->linksColor, 0.4) . ';background-color:' . wsHTML5::colorToCSS($this->theme->parametres->linksColor, 0.0001) . ';}';
 
                // Bookmarks
                if (!isset($this->book->parametres->bookmarkCornerSize)) {
@@ -1312,12 +1396,14 @@ class wsHTML5Compiler {
                # Index
                $ratio = $this->width / $this->height;
                $thumbh = round(100 / $ratio);
+               $this->config->thumbHeight = $thumbh;
                $lessVariables['thumb-height'] = $thumbh . 'px';
 
-               # Tooltip
-               $res[] = '#tooltip{background-color:' . wsHTML5::colorToCSS($this->theme->parametres->tooltipBackColor) . ';color:' . wsHTML5::colorToCSS($this->theme->parametres->tooltipTextColor) . ';}';
+               #tooltip
+               $lessVariables['tooltip-background'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipBackColor);
+               $lessVariables['tooltip-color'] = wsHTML5::colorToCSS($this->theme->parametres->tooltipTextColor);
 
-        # ZoomPopup close button background
+               # ZoomPopup close button background
                $res[] = '.zoomPopupClose {background-color:' . wsHTML5::colorToCSS($this->theme->parametres->couleurB) . ';}';
 
 
@@ -1341,8 +1427,8 @@ class wsHTML5Compiler {
 
                $tmp = CubeIT_Files::tmpdir();
 
-               copy($this->assets . '/style/variables.less', $tmp . '/variables.less');
-               copy($this->assets . '/style/mixins.less', $tmp . '/mixins.less');
+               $from = $this->assets . '/style/*';
+               `cp -r $from $tmp`;
 
                $bookVariables = array();
                foreach ($variables as $k => $v) {
@@ -1350,38 +1436,38 @@ class wsHTML5Compiler {
                }
                file_put_contents($tmp . '/book-variables.less', implode("\n", $bookVariables));
 
-        // Also copy any "extra" files that might be needed by LESS compilation
-        // (eg. video-js-core.css is needed by videojs.less)
-        foreach ($this->lessFilesExtras as $extra) {
-            $destination_extra = $tmp . '/' . $extra;
+               // Also copy any "extra" files that might be needed by LESS compilation
+               // (eg. video-js-core.css is needed by videojs.less)
+               foreach ($this->lessFilesExtras as $extra) {
+                       $destination_extra = $tmp . '/' . $extra;
                        if (!is_dir(dirname($destination_extra))) {
                                mkdir(dirname($destination_extra), 0777, true);
                        }
-            copy($this->assets . '/style/' . $extra, $destination_extra);
-        }
+                       copy($this->assets . '/style/' . $extra, $destination_extra);
+               }
 
                foreach ($this->lessFiles as $f) {
 
-            $source_less = $this->assets . '/style/' . $f . '.less';
-            $destination_less = $tmp . '/' . $f . '.less';
-            $destination_css = 'style/' . $f . '.css';
+                       $source_less = $this->assets . '/style/' . $f . '.less';
+                       $destination_less = $tmp . '/' . $f . '.less';
+                       $destination_css = 'style/' . $f . '.css';
 
                        if (!file_exists($source_less)) {
                                continue;
                        }
 
-            // LESS file might be in a subfolder, so create if it doesn't exist
+                       // LESS file might be in a subfolder, so create if it doesn't exist
                        if (!is_dir(dirname($destination_less))) {
                                mkdir(dirname($destination_less), 0777, true);
                        }
-            // Generated CSS file might be in a subfolder, so create if it doesn't exist
+                       // Generated CSS file might be in a subfolder, so create if it doesn't exist
                        if (!is_dir(dirname($this->vdir . '/' . $f . '.css'))) {
                                mkdir(dirname($this->vdir . '/' . $f . '.css'), 0777, true);
                        }
 
                        // Less files must be copied to temporary directory so they'll
-            // have access to the variables generated in book-variables.less
-            copy($source_less, $destination_less);
+                       // have access to the variables generated in book-variables.less
+                       copy($source_less, $destination_less);
                        $less = new CubeIT_CommandLine('lessc');
                        $less->setArg('plugin', 'less-plugin-clean-css');
                        $less->setArg(null, $destination_less);
index 4f9c46ff5f2bf967c622dc0907033622b6c69fba..b4a31233f6230fab71728d3bbfc3f365693390f5 100644 (file)
@@ -22,6 +22,7 @@ class wsHTML5Link {
        public $video_service;
        public $inline;
        public $display_area;
+       public $read_mode;
        public $infobulle;
        public $extra;
        public $id;
@@ -85,9 +86,6 @@ class wsHTML5Link {
                                        return new webVideoPopupLink($id, $init, $compiler);
                                }
                        case 11:
-                               if ($init['to'] == 'fullScreen') {
-                                       return null;
-                               }
                                return new actionLink($id, $init, $compiler);
                        case 12:
 
@@ -355,7 +353,6 @@ class tooltipLink extends normalLink {
 }
 
 class htmlMultimediaImage extends wsHTML5Link {
-
        public function getHTMLContainerClass() {
                return parent::getHTMLContainerClass() . ' multimedia';
        }
@@ -389,13 +386,20 @@ class htmlMultimediaPopupImage extends normalLink {
 
        public function getURL() {
                $this->copyExternalFile($this->alternative);
-               return '#/multimedia/' . md5($this->alternative);
+               $read = ($this->read_mode) ? 'r_' : '';
+               return '#/multimedia/' . $read . md5($this->alternative);
        }
 
+
        public function getAdditionnalContent() {
                $dim = getimagesize($this->wdir . '/' . $this->alternative);
-               $markup = '<div  class="multimediaContainer"><img data-width="' . $dim[0] . '" data-height="' . $dim[1] . '" src="' . wsHTML5Link::getUniversalLocation($this->alternative) . '" width="' . $dim[0] . '" height="' . $dim[1] . '" class="multimedia" /></div>';
-               return ' data-multimedia="' . rawurlencode($markup) . '" ';
+
+               $markup = '<div class="multimediaContainer "><img data-width="' . $dim[0] . '" data-height="' . $dim[1] . '" src="' . wsHTML5Link::getUniversalLocation($this->alternative) . '" width="' . $dim[0] . '" height="' . $dim[1] . '" class="multimedia" /></div>';
+               $read = '';
+               if ($this->read_mode) {
+                       $read = ' data-readmode="1"';
+               }
+               return $read . ' data-multimedia="' . rawurlencode($markup) . '" ';
        }
 
        public function keep() {
@@ -506,10 +510,10 @@ class internalLink extends normalLink {
 }
 
 class videoLink extends wsHTML5Link {
-    public static function addVideoJS($compiler) {
-        $compiler->addJs('js/libs/videojs/video.js');
-        $compiler->addLess('videojs/videojs', ['videojs/video-js-core.css']);
-    }
+       public static function addVideoJS($compiler) {
+               $compiler->addJs('js/libs/videojs/video.js');
+               $compiler->addLess('videojs/videojs', ['videojs/video-js-core.css']);
+       }
 
        public function getClasses() {
                return array_merge(['videoLink'], parent::getClasses());
@@ -726,10 +730,7 @@ class actionLink extends internalLink {
        protected $_share = array('facebook', 'twitter', 'googleplus', 'linkedin', 'viadeo');
 
        public function getURL() {
-               if (in_array($this->to, $this->_share)) {
-                       return '#';
-               }
-               return '#/' . $this->to;
+               return '#';
        }
 
        public function getClasses() {
@@ -744,7 +745,7 @@ class actionLink extends internalLink {
                if (in_array($this->to, $this->_share)) {
                        return parent::getAdditionnalContent() . ' data-service="' . $this->to . '" ';
                } else {
-                       return parent::getClasses();
+                       return parent::getClasses() . ' data-action="' . $this->to . '" ';
                }
        }
 
@@ -994,16 +995,16 @@ class webVideoPopupLink extends videoPopupLink {
 
        public function getURL() {
 
-        switch($this->video_service) {
-            case 1: // Dailymotion
-                return '#/webvideo/dailymotion/' . $this->to;
-            break;
-            case 2: // Vimeo
-                return '#/webvideo/vimeo/' . $this->to;
-            break;
-            default:
-                return '#/video/' . $this->to;
-        }
+               switch ($this->video_service) {
+                       case 1: // Dailymotion
+                               return '#/webvideo/dailymotion/' . $this->to;
+                               break;
+                       case 2: // Vimeo
+                               return '#/webvideo/vimeo/' . $this->to;
+                               break;
+                       default:
+                               return '#/video/' . $this->to;
+               }
        }
 
        public function getAdditionnalContent() {
@@ -1202,6 +1203,10 @@ class haguenauManifLink extends internalLink {
 
 class zoomLink extends normalLink {
 
+       public function getHTMLContainerClass() {
+               return parent::getHTMLContainerClass() . ' zoomarea';
+       }
+
        public function getDefaultTooltip() {
                return 'zoom in';
        }
@@ -1233,7 +1238,6 @@ class zoomLink extends normalLink {
 
                $p = wsDAOBook::getDocumentPage($this->compiler->book_id, $this->page);
                $pdfpath = wsDocument::getDir($p['document_id']) . 'original.pdf';
-
                $leftfile = CubeIT_CommandLine_Poppler::extractArea($pdfpath,
                        $p['document_page'],
                        array('x' => $this->left, 'y' => $this->top, 'width' => $this->width, 'height' => $this->height),