Jump to content

RockPdf - mPDF helper module


bernhard

Recommended Posts

1 hour ago, dragan said:

Yeah... using inline SVGs works just fine... until you want to style fills or strokes via CSS.

Yeah, I also had this problem. I managed to style the icon using inline styles (doing that manually first), eg <path fill=red ... > but I couldn't find a way to control the size of the icon. I tried several approches. I even used the SVG as <img src=...> but then the coloring part didn't work any more. TTF now works find for both situations except for duotone icons (which would be nice but not necessary).

1 hour ago, dragan said:

I have the fonts both in site/templates/fonts/ as well as in site/assets/RockPDF/fonts/. I have now also placed them in site/modules/RockPdf/vendor/mpdf/mpdf/ttfonts, cleared modules cache, but the error persists.

Please follow the new readme exactly, I'm using the font https://www.fontsquirrel.com/fonts/rock-salt successfully in my PDF:

L8xga4w.png

This is my setup for this font + fontawesome pro:

    /** @var RockPdf $pdf */
    $pdf = $this->modules->get('RockPdf');
    $pdf->settings([
      'mode' => 'utf-8',
      'format' => 'A3-L',
      'dpi' => 300,
      'img_dpi' => 300,

      // fonts
      'fontdata' => (new \Mpdf\Config\FontVariables())->getDefaults()['fontdata'] + [
        'fancy' => [
          'R' => 'RockSalt.ttf',
          'I' => 'RockSalt.ttf',
        ],
        "fab" => [
          'R' => "fa-brands-400.ttf",
          'I' => "fa-brands-400.ttf",
        ],
        "fad" => [
          'R' => "fa-duotone-900.ttf",
          'I' => "fa-duotone-900.ttf",
        ],
        "fal" => [
          'R' => "fa-light-300.ttf",
          'I' => "fa-light-300.ttf",
        ],
        "far" => [
          'R' => "fa-regular-400.ttf",
          'I' => "fa-regular-400.ttf",
        ],
        "fas" => [
          'R' => "fa-solid-900.ttf",
          'I' => "fa-solid-900.ttf",
        ],
      ],
    ]);
    ...

Then I can just add the "fancy" class to get the RockSalt font. Don't forget to define the font in CSS:

.fancy { font-family: fancy; }

Does that help?

  • Like 1
Link to comment
Share on other sites

I have also recently used https://www.joypixels.com/ for converting emojis from UTF8 into something that works in a PDF. I use this to format messages created in a CkEditor field with the emoji plugin into a PDF summary of messages. It's not perfect, but seems to match almost all emojis from the CkEditor plugin.

Would be curious if anyone has any other suggestions on this front.

Link to comment
Share on other sites

@bernhard Thanks for the hints. I didn't notice I was uploading .otf files instead of .ttf - my 2nd facepalm moment yesterday...

As to the other issue I mentioned: I found out it's not related to RockPDF at all. I got some really weird issues with render() / wireRenderFile() - but only when I ran my code inside Tracy console. In a regular template everything works as expected. The issue was with matrix repeaters that are called with $child->render('offer_matrix') inside the template, where I use field template files* - suddenly PW wouldn't find these anymore.

* site/templates/fields/matrix.php
site/templates/fields/matrix/body.php
site/templates/fields/matrix/gallery.php
site/templates/fields/matrix/slideshow.php
etc.

Link to comment
Share on other sites

9 hours ago, dragan said:

but only when I ran my code inside Tracy console. In a regular template everyting works as expected.

I think you might have come up against this bug (https://github.com/processwire/processwire-issues/issues/511). If you think it is related, perhaps you could nudge Ryan on that issue as he seems to be ignoring my concerns on this, especially when it's a really easy fix.

  • Like 2
Link to comment
Share on other sites

Just updated the readme with an example of page cropping marks and bleed margins sometimes necessary for printing:

Page margins for print with cropmarks

// thx to https://stackoverflow.com/a/50245034/6370411
$pdf = $modules->get('RockPdf');
$pdf->settings([
  'mode' => 'utf-8',
  'format' => [214, 301],
  'img_dpi' => 300,
]);
$pdf->write('
<style>
  @page {
    /* regular A4 paper size is 210x297 */
    size: 211mm 298mm; /* trying some weird format to make sure it works */
    marks: crop;
  }
</style>
Content
');
d($pdf->save());

img

img

You see that the Trim Box shows our custom values 211x298 whereas the bounding box would show the paper size (214x301).

Real life example using RockPdf and RockLESS

// parts of RockPdfCalendar module

  public function init() {
    $this->w = $w = 420; // paper width in mm
    $this->h = $h = 297; // paper height in mm
    $this->b = $b = 2; // bleed in mm

    /** @var RockPdf $pdf */
    $pdf = $this->modules->get('RockPdf');
    $pdf->settings([
      'mode' => 'utf-8',
      'format' => [($w+2*$b), ($h+2*$b)],
      'dpi' => 300,
      'img_dpi' => 300,
    ]);
    $this->addBackground($pdf);
    $this->addStyles($pdf);

    $this->pdf = $pdf;
  }

  /**
   * Add Background PDF
   * @return void
   */
  public function addBackground($pdf) {
    $page = $this->pages->get("template=settings");
    $pdfs = $page->getUnformatted('calendarbackground');
    if(!$pdfs OR !$pdfs->count()) return; // no field or no file
    $pdf->set('SetDocTemplate', $pdfs->first()->filename);
  }

  /**
   * Add styles
   */
  public function addStyles($pdf) {
    /** @var RockLESS $less */
    $less = $this->modules->get('RockLESS');
    $less->vars = [
      'w' => $this->w."mm",
      'h' => $this->h."mm",
      'b' => $this->b."mm",
    ];
    $css = $less->getCSS(__DIR__ . "/style.less")->css;
    $pdf->write("<style>\n$css</style>");
  }

Then all you have to do is call $modules->get('RockPdfCalendar')->show() to render the pdf in the browser 🙂

  • Like 1
Link to comment
Share on other sites

Just discovered a technique that can save you lots of time and headache!

Debugging can be a pain when creating PDFs, but it gets a lot simpler if you use this handy trick. I'm hooking into pageNotFoud to create the pdf:

$this->addHookBefore('ProcessPageView::pageNotFound', $this, 'renderCalendar');

If everything goes right, the calendar shows up in the browser:

xFg5SxG.png

But there's one problem: We don't know anything about errors, warnings, etc. Logging them into the pw logs is a pain compared to the Tracy Debugbar, so here's how you can have both - the generated HTML of the PDF and the debug bar:

We create the PDF BEFORE the 404 is thrown, but we create the HTML AFTER the 404:

$this->addHookBefore('ProcessPageView::pageNotFound', $this, 'renderCalendar');
$this->addHookAfter('ProcessPageView::pageNotFound', $this, 'renderCalendarDebug');

  /**
   * Render PDF calendar
   */
  public function renderCalendar(HookEvent $event) {
    $url = $event->arguments(1);
    $cal = $this->modules->get('RockPdfCalendar');

	// check url etc
    ...
    // generate the PDF
    $pdf = $cal->pdf; /** @var RockPdf $pdf */
    ...

    $title = 'Kaumberg Kalender ' . date("Y-m", $start);
    $pdf->set('setTitle', $title);
    $pdf->write($cal->render());

    // if html get parameter is set we return the html output
    $this->session->calHTML = null;
    if($this->user->isSuperuser() AND $this->input->get->html) {
      $this->session->calHTML = $pdf->html();
      return;
    }
    $pdf->show("$title.pdf");
    die();
  }

  /**
   * Output calendar for debugging
   * @return void
   */
  public function renderCalendarDebug(HookEvent $event) {
    if($this->session->calHTML) $event->return = $this->session->calHTML;
  }

D6vvaPD.png

😎

  • Like 1
Link to comment
Share on other sites

  • 1 month later...

Thanks for another great module @bernhard

Wanted to share my experiences changing from Pages2PDF to RockPdf. Wasn't quite as straightforward as I'd hoped. Such is life, but I got there. Pages2Pdf uses mPDFv5+ while RockPdf uses mPDFv7+ and I needed some of the newer features.

Things Iearned along the way:

1. If you need to use @page, you lose everything in the template 

$pdf->set('header', '...');

 settings. This has nothing to do with RockPdf but a 'feature' of mPDF

2. It's much easier to add custom fonts to RockPdf than Pages2PDF

3. You can display images in a circle using background-image but they don't print so that's not helpful, LOL

This is NOT a full tutorial but hopefully will give you some pointers on how I got RockPdf working for a fairly specific PDF design.

RockPdf template settings:

<?php

    $pdf = $modules->get('RockPdf');

    $pdf->settings([
        'fontdata' => (new \Mpdf\Config\FontVariables())->getDefaults()['fontdata'] + [
             "montserrat" => [
                'R' => "montserrat-regular.ttf",
                'B' => "montserrat-bold.ttf",
            ],
            "montserratlight" =>[
                'R' => "montserrat-light.ttf"
            ],
            "montserratthin" => [
                'R' => "montserrat-thin.ttf"
            ]
        ],

        'defaultheaderline' => 0,

        'font_size' => 9,
        'mode' => 'utf-8',
        'font' => 'montserrat',
        'page_format' => 'A4',
    ]);

    $css = wireRenderFile($config->paths->templates . 'RockPdf/styles-v3.css');
    $pdf->write("<style>" . $css . "</style>");

    $body = wireRenderFile($config->paths->templates . 'RockPdf/profile_pdf_cv-v3.php');
    $pdf->write($body);

    $pdfFile = $sanitizer->pageName($profile->title) . "-" . $profile->id . ".pdf";

    $pdf->show($pdfFile);
    die();

//    Remove old Pages2PDF settings
//    $mpdf->markupMain   = $config->paths->templates . 'RockPdf/profile_pdf_cv-v3.php';
//    $mpdf->markupHeader = $config->paths->templates . 'RockPdf/_header-v3.php';
//    $mpdf->markupFooter = $config->paths->templates . 'pages2pdf/_footer-v2.php';
//    $mpdf->cssFile = $config->paths->templates . 'RockPdf/styles-v3.css';
//    $mpdf->pageOrientation = 'P';
//    $mpdf->pageFormat = 'A4';
//    $mpdf->topMargin = 9.5;
//    $mpdf->rightMargin = 0;
//    $mpdf->bottomMargin = 9;
//    $mpdf->leftMargin = 0;
//    $mpdf->headerMargin = 0;
//    $mpdf->footerMargin = 0;
//    $mpdf->fontSize = 9;
//    $mpdf->mode = 's';
//    $mpdf->font = 'montserrat';

Header code:

    <div style="
        background-color: #007ee5;
        height: 10mm;
        margin: 0;
        top: 0;
        left: 0;
        right: 0;
        width: 100%;
">
    </div>

Page layout code:

<?php

// header is the same on all pages but need more spacing on all pages except the first
$header = wireRenderFile($config->paths->templates . 'RockPdf/_header-v3.php');
?>
<htmlpageheader name="myHeaderFirst" style="display:none">
    <?=$header?>
</htmlpageheader>

<htmlpageheader name="myHeader" style="display:none">
    <?=$header?>
</htmlpageheader>

<sethtmlpageheader name="myHeaderFirst" value="on" show-this-page="1" />
<sethtmlpageheader name="myHeader" value="on" />



<div class="user-dets">

CSS:

/*
Additional fonts added to:
site/assets/RockPdf/fonts

*/
@page {
    margin: 15mm 0 0 0; /* <any of the usual CSS values for margins> */
    /*(% of page-box width for LR, of height for TB) */
    margin-header: 0; /* <any of the usual CSS values for margins> */
    margin-footer: 9mm; /* <any of the usual CSS values for margins> */
    marks: none;/*crop | cross | none*/
    header: html_myHeader;
}

@page :first {
    margin: 9.5mm 0 0 0; /* <any of the usual CSS values for margins> */
    /*(% of page-box width for LR, of height for TB) */
    margin-header: 0; /* <any of the usual CSS values for margins> */
    margin-footer: 9mm; /* <any of the usual CSS values for margins> */
    marks: none;/*crop | cross | none*/
    header: html_myHeaderFirst;

}

Hope this is useful.

Cheers
psy

 

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

Thx for sharing your experience @psy 🙂 

43 minutes ago, psy said:

Wasn't quite as straightforward as I'd hoped. Such is life, but I got there.

mPdf is unfortunately not really a pleasure to work with 😞 It feels a bit like designing websites 20 years ago with lots of custom table layouts, custom styles, paddings, margins etc... But as you said: I also got there almost everytime and I didn't find a better solution yet.

Writing your styles as LESS can be helpful because you can create simple custom classes for any element and to the complex styling in CSS. Using LESS ensures that your style stays easy to maintain because you can use class inheritance and variables. RockPdf plays really well together with RockLESS. I added an example to the readme:

Combine RockPdf and RockLESS

$pdf = $modules->get('RockPdf');
$less = $modules->get('RockLESS');
$style = "
@padding-s: 10pt;
.border { border: 1pt solid #afafaf; }
.hello { .border; color: blue; padding-top: @padding-s; }
.world { .border; color: red; padding-top: @padding-s * 2; }
";
$css = "\n".$less->parse($style);
$pdf->write("<style>$css</style>");
$pdf->write("<div class='hello'>hello</div>");
$pdf->write("<div class='world'>world</div>");
d($pdf->save());

img

img

This is the result of $pdf->html()

<style>
.border {
  border: 1pt solid #afafaf;
}
.hello {
  border: 1pt solid #afafaf;
  color: blue;
  padding-top: 10pt;
}
.world {
  border: 1pt solid #afafaf;
  color: red;
  padding-top: 20pt;
}
</style>
<div class='hello'>hello</div>
<div class='world'>world</div>

 

  • Like 3
Link to comment
Share on other sites

8 hours ago, bernhard said:

mPdf is unfortunately not really a pleasure to work with 😞 It feels a bit like designing websites 20 years ago with lots of custom table layouts, custom styles, paddings, margins etc...

@bernhard Oh so true! Pdf's can look different between browser views and Acrobat Reader too. 

  • Like 1
Link to comment
Share on other sites

On 4/22/2020 at 10:18 PM, bernhard said:

Writing your styles as LESS can be helpful because you can create simple custom classes for any element and to the complex styling in CSS.

Hi @bernhard

Yes, RockLESS, SCSS and other CSS preprocessors can be useful. One thing I learned the hard way however is that the header is loaded before any HTML or CSS. The only way I could style the header to look as intended was with inline styles. I certainly used classes with the limited CSS styling available from mPDF in the body. Maybe there's a better way, just didn't have the time or patience to explore.

Another limitation was with tables... I needed a centered heading and left aligned text within a table cell. Nope, if the <td> is left aligned, so is everything within the cell. Had to revert to divs which had an impact on the design. Told the graphic designer to live with it - it is what it is! LOL

Having said that, love your module and mPDF, even with its constraints, is still the best HTML to PDF converter.

 

  • Like 2
Link to comment
Share on other sites

Aligning things is tricky, but most things work using nested tables (that's what I meant when saying "like 20 years ago"). What about this?

$pdf = $modules->get('RockPdf');
$table = '
<style>
td { border: 1pt solid black; }
.center {text-align: center;}
</style>
<table>';
$table .= '<tr><td class="center">foo</td><td>bar</td></tr>';
$table .= '<tr><td>Donec vitae sapien ut libero</td><td>Donec vitae sapien ut libero</td></tr>';

$td = "<table><tr><td class='center'>sub-heading</td></tr><tr><td>Phasellus ullamcorper ipsum rutrum nunc</td></tr></table>";
$table .= "<tr><td>Donec vitae sapien ut libero</td><td>$td</td></tr>";

$table .= '</table>';
$pdf->write($table);
d($pdf->save()); // generate pdf

zEj9LUg.png

  • Like 2
Link to comment
Share on other sites

Yep, that's a solution - 20yrs ago HTML/CSS 😂 

In my particular case there are other factors. The user can choose to include/exclude bits which makes it an ugly, logistical nightmare.

34 minutes ago, psy said:

Told the graphic designer to live with it - it is what it is! LOL

 

  • Like 1
Link to comment
Share on other sites

  • 3 months later...
On 10/17/2018 at 7:36 PM, charger said:

Did anyone else encounter problems with `show()` and `download()`? If I use them, all I get is blank pages resulting in an invalid PDF. The `save()` function works as expected though.

I’m running PW 3.0.98 with PHP 7.1.12 and RockPdf 1.0.1

For anybody facing this problem which in my case invalid pdf will generate error  "one or more XREF chunks were not found".
Solved it by placing the rockpdf instance php code block on top of anything else.

Link to comment
Share on other sites

2 hours ago, pwfans said:

Solved it by placing the rockpdf instance php code block on top of anything else.

Thx for the report. Can you please give us some more details, I don't really understand what you mean 🙂 

Link to comment
Share on other sites

  • 1 month later...

Hi @bernhard,

thank you for the module, which is helpful in keeping the project structure clean.

I also use the MPDF barcode component to generate QR codes of the page URL.
For this it was necessary to add the MPDF QR Code library to the RockPDF module using following command inside the /site/modules/RockPdf directory:

$ composer require mpdf/qrcode

It would be great if this was already available in the basic version of the module so as not to jeopardize the upgradeability.
What do you think, is it interesting to add or rather an unusual special case?

Link to comment
Share on other sites

I have the pdf render in a function to keep my template clean.

On top of the function I do

// maps
    $images = $page->flightplan_images;
    $image = "";
    foreach ($images as $i){
        $image .= '<img src="' . $i->url . '" uk-image>';
    }

 

Tried both $pdf->write() with some html with $image and

$mpdf->WriteHTML() with some html with $image.

 

All is there except for the images.

How do I output images in a pdf.

Link to comment
Share on other sites

I use a textarea on the frontend that is saved in form. In that textarea on the frontpage paragraphs remain visible after save.

In the pdf all text is rendered after each other.

What is the best way to preserve paragraphs both on the page and the pdf?

Link to comment
Share on other sites

  • 4 months later...

Hello all,

once again I have a problem how to integrate the PDF output into my page ...
(With a direct output I get it in the meantime, see here).

But now I use the standard template "Regular" (which is already included in the installation) and it uses the "Markup regions" method as output strategy.

Well, and this is where I get stuck. Because if I try it with the same method as in the link above, it wants to open a PDF in the browser, but there is ALWAYS an error message.

However, it can't be the code, a) I've already tried it only with the most necessary and b) any test code works wonderfully in "Tracy", whether I want to output it directly or save it, everything works.

Now I'm unfortunately a bit at the end of my ideas and hope to get some helpful tips from the community.

Would be happy, thank you and stay healthy
cu Ralf

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By Marco Ro
      Hi guys!
      I'm a bit anxious because this is the first module I present! (beta modulo) But I will finally be able to share something with the community too! :)
      This is a BETA version of the PayPal payment system called: PayPal Commerce Platform.
      It is an advanced system (Business Pro account is needed) that brings various benefits in terms of fees and above all integrates direct payment with credit/debit cards. 
      The module integrates with Padloper 0.0.2, which is the current installation I'm using.
      This system integrates the classic PayPal buy button, the alternative or local payment method and the new payment system: credit/debit cards that doesn't go through the PayPal account. It is a Stripe-style payment, it connects directly with the bank and integrates 3D security validation.
      I say that it is a BETA because this module currently only works with Sandbox account, to put it live you need to change API url manually (manually for the moment).
      Because this module is not ready for live:
      I would like to have your opinion on how I built the module (is the first one I do). I don't want to share something that is not fish but I need a comparison with someone more experienced than me, for be sure that this is the best way to code the module.
      If you want to try this I created a git, you will find all the instructions for installation and correct operation. (Git has a MIT licensed)
      https://github.com/MarcooRo/processwire-PayPal-Commerce-Platform I hope I did something that you guys can like :)
    • By monollonom
      (once again I was surprised to see a work of mine pop up in the newsletter, this time without even listing the module on PW modules website 😅. Thx @teppo !)
      FieldtypeQRCode
      Github: https://github.com/romaincazier/FieldtypeQRCode
      Modules directory: https://processwire.com/modules/fieldtype-qrcode/
      A simple fieldtype generating a QR Code from the public URL of the page, and more.
      Using the PHP library QR Code Generator by Kazuhiko Arase.

      Options
      In the field’s Details tab you can change between .gif or .svg formats. If you select .svg you will have the option to directly output the markup instead of a base64 image. SVG is the default.
      You can also change what is used to generate the QR code and even have several sources. The accepted sources (separated by a comma) are: httpUrl, editUrl, or the name of any text/URL/file/image field.
      If LanguageSupport is installed the compatible sources (httpUrl, text field, ...) will return as many QR codes as there are languages. Note however that when outputting on the front-end, only the languages visible to the user will be generated.
      Formatting
      Unformatted value
      When using $page->getUnformatted("qrcode_field") it returns an array with the following structure:
      [ [ "label" => string, // label used in the admin "qr" => string, // the qrcode image "source" => string, // the source, as defined in the configuration "text" => string // and the text used to generate the qrcode ], ... ] Formatted value
      The formatted value is an <img>/<svg> (or several right next to each other). There is no other markup.
      Should you need the same markup as in the admin you could use:
      $field = $fields->get("qrcode_field"); $field->type->markupValue($page, $field, $page->getUnformatted("qrcode_field")); But it’s a bit cumbersome, plus you need to import the FieldtypeQRCode's css/js. Best is to make your own markup using the unformatted value.
      Static QR code generator
      You can call FieldtypeQRCode::generateQRCode to generate any QR code you want. Its arguments are:
      string $text bool $svg Generate the QR code as svg instead of gif ? (default=true) bool $markup If svg, output its markup instead of a base64 ? (default=false) Hooks
      Please have a look at the source code for more details about the hookable functions.
      Examples
      $wire->addHookAfter("FieldtypeQRCode::getQRText", function($event) { $page = $event->arguments("page"); $event->return = $page->title; // or could be: $event->return = "Your custom text"; }) $wire->addHookAfter("FieldtypeQRCode::generateQRCodes", function($event) { $qrcodes = $event->return; // keep everything except the QR codes generated from editUrl foreach($qrcodes as $key => &$qrcode) { if($qrcode["source"] === "editUrl") { unset($qrcodes[$key]); } } unset($qrcode); $event->return = $qrcodes; })
    • By Sebi
      AppApiFile adds the /file endpoint to the AppApi routes definition. Makes it possible to query files via the api. 
      This module relies on the base module AppApi, which must be installed before AppApiFile can do its work.
      Features
      You can access all files that are uploaded at any ProcessWire page. Call api/file/route/in/pagetree?file=test.jpg to access a page via its route in the page tree. Alternatively you can call api/file/4242?file=test.jpg (e.g.,) to access a page by its id. The module will make sure that the page is accessible by the active user.
      The GET-param "file" defines the basename of the file which you want to get.
      The following GET-params (optional) can be used to manipulate an image:
      width height maxwidth maxheight cropX cropY Use GET-Param format=base64 to receive the file in base64 format.
    • By MarkE
      This fieldtype and inputfield bundle was built for storing measurement values within a field, rendering them in a variety of formats and converting them to other units or otherwise modifying them via the API.
      The API consists of a number of predefined functions, some of which include...
      render() for rendering the measurement object, valueAs() for converting the value to another unit value, convertTo() for converting the whole measurement object to different units, and add() and subtract() for for modifying the stored value by the value (converted as required) in another measurement. In the admin the inputfield includes a checkbox (which can be optionally disabled) for converting values on page save. For an example if a value was typed in as centimeters, the unit was changed to metres, and the page saved with this checkbox selected, said value would be automatically converted so that e.g. 170 cm becomes 1.7 m.

      A simple length field using Fieldtype Measurement and Inputfield Measurement.
      Combination units (e.g. feet and inches) are also supported.
      Please note that this module is 'proof of concept' at the moment - there are limited units available and quite a lot of code tidying to do. More units will be added shortly.
      See the GitHub at https://github.com/MetaTunes/FieldtypeMeasurement for full details and updates.
    • By tcnet
      File Manager for ProcessWire is a module to manager files and folders from the CMS backend. It supports creating, deleting, renaming, packing, unpacking, uploading, downloading and editing of files and folders. The integrated code editor ACE supports highlighting of all common programming languages.
      https://github.com/techcnet/ProcessFileManager

      Warning
      This module is probably the most powerful module. You might destroy your processwire installation if you don't exactly know what you doing. Be careful and use it at your own risk!
      ACE code editor
      This module uses ACE code editor available from: https://github.com/ajaxorg/ace

      Dragscroll
      This module uses the JavaScript dragscroll available from: http://github.com/asvd/dragscroll. Dragscroll adds the ability to drag the table horizontally with the mouse pointer.
      PHP File Manager
      This module uses a modified version of PHP File Manager available from: https://github.com/alexantr/filemanager
       
×
×
  • Create New...