kongondo

Module: RuntimeMarkup Fieldtype & Inputfield

Recommended Posts

FieldtypeRuntimeMarkup and InputfieldRuntimeMarkup
 
Modules Directory: http://modules.processwire.com/modules/fieldtype-runtime-markup/
GitHub: https://github.com/kongondo/FieldtypeRuntimeMarkup
 
This module allows for custom markup to be dynamically (PHP) generated and output within a page's edit screen (in Admin).
 
The value for the fieldtype is generated at runtime. No data is saved in the database. The accompanying InputfieldRuntimeMarkup is only used to render/display the markup in the page edit screen.
 
The field's value is accessible from the ProcessWire API in the frontend like any other field, i.e. it has access to $page and $pages.
 
The module was commissioned/sponsored by @Valan. Although there's certainly other ways to achieve what this module does, it offers a dynamic and flexible alternative to generating your own markup in a page's edit screen whilst also allowing access to that markup in the frontend. Thanks Valan!
 
Warning/Consideration

  • Although access to ProcessWire's Fields' admin pages is only available to Superusers, this Fieldtype will evaluate and run the custom PHP Code entered and saved in the field's settings (Details tab). Utmost care should therefore be taken in making sure your code does not perform any CRUD operations!! (unless of course that's intentional)
  • The value for this fieldtype is generated at runtime and thus no data is stored in the database. This means that you cannot directly query a RuntimeMarkup field from $pages->find().

Usage and API

 
Backend

Enter your custom PHP snippet in the Details tab of your field (it is RECOMMENDED though that you use wireRenderFile() instead. See example below). Your code can be as simple or as complicated as you want as long as in the end you return a value that is not an array or an object or anything other than a string/integer.
 
FieldtypeRuntimeMarkup has access to $page (the current page being edited/viewed) and $pages. 
 
A very simple example.

return 'Hello';

Simple example.

return $page->title;

Simple example with markup.

return '<h2>' . $page->title . '</h2>';

Another simple example with markup.

$out = '<h1>hello ';
$out .= $page->title;
$out .= '</h1>';
return $out;

A more advanced example.

$p = $pages->get('/about-us/')->child('sort=random');
return '<p>' . $p->title . '</p>';

An even more complex example.

$str ='';
if($page->name == 'about-us') {
  $p = $page->children->last();
  $str = "<h2><a href='{$p->url}'>{$p->title}</a></h2>";
}

else {
  $str = "<h2><a href='{$page->url}'>{$page->title}</a></h2>";
}

return $str;

Rather than type your code directly in the Details tab of the field, it is highly recommended that you placed all your code in an external file and call that file using the core wireRenderFile() method. Taking this approach means you will be able to edit your code in your favourite text editor. It also means you will be able to type more text without having to scroll. Editing the file is also easier than editing the field. To use this approach, simply do:

return wireRenderFile('name-of-file');// file will be in /site/templates/

If using ProcessWire 3.x, you will need to use namespace as follows:

return ProcessWire\wireRenderFile('name-of-file');

How to access the value of RuntimeMarkup in the frontend (our field is called 'runtime_markup')
 
Access the field on the current page (just like any other field)

echo $page->runtime_markup;

Access the field on another page

echo $pages->get('/about-us/')->runtime_markup;

Screenshots
 
Backend
 
screenshot1.png
 
screenshot2.png
 
Frontend
 
screenshot3.png

  • Like 23
  • Thanks 1

Share this post


Link to post
Share on other sites

I think I understand what this module does but I'm having trouble grasping the situations in which it would be useful based on the examples you've given.

Is it just a convenience thing, so the editor doesn't have to look elsewhere for some information that might affect the content they decide to add to the page?

Share this post


Link to post
Share on other sites

There are many usefull situations like:

1. If you have a page for settings or tools with general entries/items and you use them on other pages like in a contactform you use the email field from the /settings/ page you could show this general fields on several places/templates

2. more advanced example could be to render statistic like content from subpages - imagine if you have a ad system that is counting views and clicks you could render a little stat with some html and some css/js at the rootpage of the ad's...

3. special for overview pages/rootpages it provides options to put some extra information/logic in such pages without the use of pagetable or something other complex..

4....

you get the idea

regards mr-fan

  • Like 3

Share this post


Link to post
Share on other sites

Simple answer is that @Valan had a need and commissioned me to develop this :biggrin: . 

Seriously though, mr-fan already covered it brilliantly. When I get some time, I'll post some other examples.

  • Like 2

Share this post


Link to post
Share on other sites

I have used a homemade solution to display information of related pages in the editor, which are needed to know how to handle the page (essentially user requests).

  • Like 2

Share this post


Link to post
Share on other sites

This is such a great module; recently I used it to create custom action buttons on my calendar/futuremail app;

Send or preview the email message for the future mail:

post-136-0-22253700-1443749172_thumb.png

send or preview a calendar event, which is typed by a chosen template (e.g. event, lesson reminder, etc.)

post-136-0-31179600-1443749173_thumb.png

  • Like 12

Share this post


Link to post
Share on other sites

Macrura - very cool - I hadn't thought of using it that way and will actually need similar buttons in an upcoming project so might just consider using this module to do it!

The trouble I am having with PW lately is that there are so many great new ways of doing things and it's hard to keep track of them all :)

  • Like 4

Share this post


Link to post
Share on other sites

In my case i only have 1 field and then my code checks for which template it's on, then outputs various buttons and messages; the buttons themselves just link to templates that read the url parameters and run some process. Eventually i'll probably have a generic module to process the buttons..

i think I'm going to be using this a lot!

  • Like 3

Share this post


Link to post
Share on other sites

Thank you Kongondo & @Valan for this great little helper!

For me as a non real dev...it is much more easy to get some special admin magic working with this!

This is one of the real big things i like with PW - there are tools that helps and can used by non experienced PHP users without to force them to do risky things within the backend...in other systems the level of complexity always grows and grows...with PW it seems it always get easier ;)

I'm on a hard deadline this days so less time to contribute but this little snippet may helps others - easy to use and very helpful.

It works as a kind of shortcut navigation to prev next siblings - like Kongondo showed off in his video to the notorious V.P.S.

I saw the raw links and thought hey i've a version of this running with UI buttons so here we go:

$out ='';
$siblings = $page->siblings;
//generate next & prev links output
if (count($siblings)) {
	$prev = $siblings->getPrev($page);
	if ($prev) {	
		$out .= '<a href="'.$prev->editUrl.'">';
		$out .= '<button type="button" name="button" class="ui-button ui-widget ui-corner-all ui-state-default">';
		$out .= '<span class="ui-button-text"><i class="fa fa-angle-double-left"></i> '.$prev->title.'</span></button>';
		$out .= '</a>';
	}
	$next = $siblings->getNext($page);
	if ($next) {
		$out .= '<a href="'.$next->editUrl.'">';
		$out .= '<button type="button" name="button" class="ui-button ui-widget ui-corner-all ui-state-default">';
		$out .= '<span class="ui-button-text">'.$next->title.' <i class="fa fa-angle-double-right"></i></span></button>';
		$out .= '</a>';
	}
if ($out <> "") $out = "<div class='NextPrevLinks'>".$out."</div>";
return "<div class='NextPrevLinks'>".$out."</div>";
}

Output of the field is:

post-2327-0-97972400-1443878534_thumb.jp

Have fun and best regards mr-fan

  • Like 4

Share this post


Link to post
Share on other sites

is it possible to use the value of this field for field dependency selectors? that would be really great but i didn't get it to work...

i created a field "testruntime"

post-2137-0-26897500-1445185352_thumb.pn

i set visibility for field "headline2"

post-2137-0-19718400-1445185351_thumb.pn

but the field does not show up...

post-2137-0-31086500-1445185353_thumb.pn

post-2137-0-84136000-1445185431_thumb.pn

any help for this? thanks for the great module - it was on my wishlist https://processwire.com/talk/topic/10555-using-pw-variables-in-descriptions-and-notes/   :)   ;)

edit: i was on the wrong track with this one... field dependencies work on the client side with JS and won't take care of the field value when the field is hidden

Share this post


Link to post
Share on other sites

Kongondo - just wanted to send a big thanks for this - just used it for the first time as a way to provide a preview of content from a hidden page tree and a modal edit link to edit that content - really very handy!

  • Like 1

Share this post


Link to post
Share on other sites

<silliness>I've been meaning to do a video demo of a list of silly thinks/pranks you can do with RunTimeMarkup...you know, a countdown to lunch break, a thing that shouts "peekaboo" every time you type a certain letter on your keyboard, a (not-so-silly) live spell-checker, etc....But then again, I have been meaning a lot of things... ;) </silliness>

  • Like 4

Share this post


Link to post
Share on other sites

That would surely convert many users from other CMSes - so please don't go that cinematic :)

  • Like 1

Share this post


Link to post
Share on other sites

Hi there?

is this possible?

if ($page->url=='/search/') {
  $title = $input->get['keyword']." ";
}
return $title;

I cannot return the value of $input->get['keyword'] even though it exist in the url?

Share this post


Link to post
Share on other sites

I'm not sure if you can access these items with the array notation, try $input->get('keyword') or $input->get->keyword.

Edit: And just as I thought, only $pages and $page are available as local variables. All the other api variables need to be accessed as $this->input or wire('input').

  • Like 2

Share this post


Link to post
Share on other sites

I'm not sure if you can access these items with the array notation, try $input->get('keyword') or $input->get->keyword.

Also did not work on url variables... i tried this but can't get to work...

Here's my url output

thefilipinodoctor/search/?keyword=Supranueron

Share this post


Link to post
Share on other sites

Also did not work on url variables... i tried this but can't get to work...

Speedy people here. Read my edited post above.

Share this post


Link to post
Share on other sites

@naldrocks98, 

Yes, @LostKobrakai is right about variable scope; RM only knows $page and $pages :-). So, this with your 'array notation', works:

$title = '';

if ($page->url=='/search/') {
  $title = $this->wire('input')->get['keyword'] ." ";
}
return $title;

If you had debug turned on, you could have seen the errors and fixed it :-). You also need to instantiate $title, otherwise, you will get an error for pages that don't match.

Edit

Btw, just curious, how are you using this?

Edited by kongondo

Share this post


Link to post
Share on other sites

Greatly useful module guys, thanks!

Just used it to provide a list of collected emails for simple copy/paste into send field

return $page->children->implode(', ', 'email');

Couldn't get any simpler than this!

PS: of course it would be great to have ACE on the code field like i Hanna Code ;)

  • Like 3

Share this post


Link to post
Share on other sites

PS: of course it would be great to have ACE on the code field like i Hanna Code ;)

The module could just check if Inputfield Ace Extended is installed and use it if so. That would prevent the big filesize like it's the case for hanna code and leave the code editor optional.

  • Like 3

Share this post


Link to post
Share on other sites

@kongondo - wondering if there might be an issue with renaming fields using this fieldtype;

i tried renaming an existing field but got a sql error;

Share this post


Link to post
Share on other sites

@Macrura,
 
Thanks for catching this. You will notice the same error if you tried to rename a FieldtypeConcat field. The error occurs because these Fieldtypes do not create a database table, i.e. there is no field_my_runtime_field table. MySQL throws the error since it can't find such a table on file, i.e. there is no field_my_runtime_field.frm file (every MySQL table is represented on disk by a .frm file that describes the table's format). It throws the error in Fields.php, in the __save() method, here. Although the method is hookable, I'll have a talk with Ryan to see what's the best way to handle this.

Edit: Forgot to provide a temporary solution:

As we know, the names of fields themselves are stored in the 'fields' table. As we wait to resolve this, we can always change a fields name there. Not ideal, I know, but we will get to the bottom of this.

Edit 2: Issue fixed in this commit in ProcessWire 2.7.2 (dev)

Edited by kongondo
  • Like 1

Share this post


Link to post
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 Mike Rockett
      As I mentioned in this issue, I've create a new textformatter for ParsedownExtraPlugin, which adds some oomph to your markdown.
      Repo: Parsedown Extra Plugin
      Unlike the built-in textformatter for Parsedown and Parsedown Extra, this should be used when you want to use Extra with additional configuration/customisation.
      Some examples:
      ### Test {.heading} - A [external link](https://google.com/){.google} with `google` as a class that opens in a new tab if the config property is set. - [Another link](/page){target=_blank} that opens in a new tab even though it isn't external. ```html .html <p>Test</p> ``` There's some config options available to you, such as setting attributes on all/external images and links, setting table and table-cell alignment classes, adjusting footnote classes and IDs, adding <code> attributes to their parent <pre> elements, and changing the <code> class if your syntax highlighter does not use language-*.
      I was thinking about adding the ability to make links open in a new tab by appending a plus to the link syntax, but only external links should be opening in a new tab anyway. Further, this would add extra, unnecessary processing time.
      Please let me know if you bump into any problems. ☺️
    • By Mike Rockett
      TextformatterTypographer (0.4.0 Beta)
      A ProcessWire wrapper for the awesome PHP Typography class, originally authored by KINGdesk LLC and enhanced by Peter Putzer in wp-Typography. Like Smartypants, it supercharges text fields with enhanced typography and typesetting, such as smart quotations, hyphenation in 59 languages, ellipses, copyright-, trade-, and service-marks, math symbols, and more.
      Learn more on my blog
      It's based on the PHP-Typography library found over at wp-Typography, which is more frequently updated and feature rich that its original by KINGdesk LLC.
      The module itself is fully configurable. I haven't done extensive testing, but there is nothing complex about this, and so I only envisage a typographical bug here and there, if any.
      Please do test it out and let me know what you think.
      Also note that I have indicated support for PW 2.8, but I haven't tested there as yet. This was built on PW 3.0.42/62.
    • By Mike Rockett
      Jumplinks for ProcessWire
      Release: 1.5.50
      Jumplinks is an enhanced version of the original ProcessRedirects by Antti Peisa.
      The Process module manages your permanent and temporary redirects (we'll call these "jumplinks" from now on, unless in reference to redirects from another module), useful for when you're migrating over to ProcessWire from another system/platform. Each jumplink supports wildcards, shortening the time needed to create them.
      Unlike similar modules for other platforms, wildcards in Jumplinks are much easier to work with, as Regular Expressions are not fully exposed. Instead, parameters wrapped in curly braces are used - these are described in the documentation.
      Under Development: 2.0, to be powered by FastRoute
      As of version 1.5.0, Jumplinks requires at least ProcessWire 2.6.1 to run.
      View on GitLab
      Download via the Modules Directory
      Read the docs
      Features
      The most prominent features include:
      Basic jumplinks (from one fixed route to another) Parameter-based wildcards with "Smart" equivalents Mapping Collections (for converting ID-based routes to their named-equivalents without the need to create multiple jumplinks) Destination Selectors (for finding and redirecting to pages containing legacy location information) Timed Activation (activate and/or deactivate jumplinks at specific times) 404-Monitor (for creating jumplinks based on 404 hits) Additionally, the following features may come in handy:
      Stale jumplink management Legacy domain support for slow migrations An importer (from CSV or ProcessRedirects) Feedback & Feature Requests
      I’d love to know what you think of this module. Please provide some feedback on the module as a whole, or even regarding smaller things that make it whole. Also, please feel free to submit feature requests and their use-cases.
      Note: Features requested so far have been added to the to-do list, and will be added to 2.0, and not the current dev/master branches.
      Open Source

      Jumplinks is an open-source project, and is free to use. In fact, Jumplinks will always be open-source, and will always remain free to use. Forever. If you would like to support the development of Jumplinks, please consider making a small donation via PayPal.
      Enjoy! 
    • By bernhard
      Some of you might have followed the development of this module here: https://processwire.com/talk/topic/15524-previewdiscussion-rockdatatables/ . It is the successor of "RockDataTables" and requires RockFinder to get the data for the grid easily and efficiently. It uses the open source part of agGrid for grid rendering.
       
      WHY?
      ProcessWire is awesome for creating all kinds of custom backend applications, but where it is not so awesome in my opinion is when it comes to listing this data. Of course we have the built in page lister and we have ListerPro, but none of that solutions is capable of properly displaying large amounts of data, for example lists of revenues, aggregations, quick and easy sorts by the user, instant filter and those kind of features. RockGrid to the rescue 😉 
       
      Features/Highlights:
      100k+ rows Instant (client side) filter, search, sort (different sort based on data type, eg "lower/greater than" for numbers, "contains" for strings) extendable via plugins (available plugins at the moment: fullscreen, csv export, reload, batch-processing of data, column sum/statistics, row selection) all the agGrid features (cell renderers, cell styling, pagination, column grouping etc) vanilla javascript, backend and frontend support (though not all plugins are working on the frontend yet and I don't plan to support it as long as I don't need it myself)  
      Limitations:
      While there is an option to retrieve data via AJAX the actual processing of the grid (displaying, filtering, sorting) is done on the client side, meaning that you can get into troubles when handling really large datasets of several thousands of rows. agGrid should be one of the most performant grid options in the world (see the official example page with a 100k row example) and does a lot to prevent problems (such as virtual row rendering), but you should always have this limitation in mind as this is a major difference to the available lister options that do not have this limitation.
      Currently it only supports AdminThemeUikit and I don't plan to support any other admin theme.
       
      Download: https://gitlab.com/baumrock/FieldtypeRockGrid
      Installation: https://gitlab.com/baumrock/RockGrid/wikis/Installation
      Quikckstart: https://gitlab.com/baumrock/RockGrid/wikis/quickstart
      Further instructions: https://gitlab.com/baumrock/RockGrid/wikis/quickstart#further-instructions
      German Translation File: site--modules--fieldtyperockgrid--fieldtyperockgrid-module-php.json
      Changelog: https://gitlab.com/baumrock/FieldtypeRockGrid/raw/master/changelog.md
       
      Module status: alpha, License: MIT
      Note that every installation and uninstallation sends an anonymous google analytics event to my google analytics account. If you don't want that feel free to remove the appropriate lines of code before installation/uninstallation.
       
      Contribute:
      You can contribute to the development of this and other modules or just say thank you by
      testing, reporting issues and making PRs at gitlab liking this post buying me a drink: paypal.me/baumrock/5 liking my facebook page: facebook.com/baumrock hiring me for pw work: baumrock.com  
      Support: Please note that this module might not be as easy and plug&play as many other modules. It needs a good understanding of agGrid (and JavaScript in general) and it likely needs some looks into the code to get all the options. Please understand that I can not provide free support for every request here in the forum. I try to answer all questions that might also help others or that might improve the module but for individual requests I offer paid support for 60€ per hour (excl vat).
       
      Use Cases / Examples:
      Colored grid cells, Icons, Links etc. The Grid also has a "batcher" feature built in that helps communicating with the server via AJAX and managing resource intensive tasks in batches:

      Filters, PW panel links and instant reload on panel close:

      You can combine the grid with a chart library like I did with the (outdated) RockDataTables module:

    • By thomasaull
      Some time ago I created a site profile for creation of a REST API with ProcessWire. Since I kept struggeling with updating stuff between different projects which use this, I decided to convert it into a module. It is now ready for testing: https://github.com/thomasaull/RestApi
      Additionally I added a few small features:
      automatic creation of JWT Secret at module install routes can be flagged as auth: false, which makes them publicly accessible even though JWT Auth is activated in module settings To check things out, download and install the module and check the folder /site/api for examples.
      If you find any bugs or can think of improvements, please let me know!