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 MoritzLost
      Hello there,
      I'm working on a tiny textformatter module that searches the text for titles of other pages on your site and creates hyperlinks to them. I'm not sure if something like this exists already, but I haven't found anything in the module directory, so I wrote my own solution 🙂
      It's not properly tested yet and is still missing some functionality I would like to implement, so at the moment it should be considered in BETA. Features include limiting the pages that will get searched by template, and adding a custom CSS class to the generated hyperlinks. As I'm writing this I noticed that it will probably include unpublished and hidden pages at the moment, so yeah ... it's still in development alright 😅
      You can download the module from Github:
      https://github.com/MoritzLost/TextformatterPageTitleLinks
      There's some more information in the readme as well.
      Anyway, let me know what you think! I'm happy about any feedback, possible improvements or ideas on how to improve the module. Cheers.
    • By adrian
      This module provides a way to rapidly generate Page fields and the required templates and pages for use as a drop down select (or any other Page field type).
      This module will let you create a full page field setup in literally a few seconds 
      To use, run Page Field Select Creator from the Setup Menu
      Enter a Field Title, eg: Room Types Select Options - These will become the child pages that will populate the page field select options. There are two different options.
       
      Option 1. TITLE FIELD ONLY - enter one option per line, eg:
       
      Single
      Double
      Suite
       
       
      Option 2. MULTIPLE FIELDS - the first line is used for the field names and the first field must be 'Title'. Subsequent lines are the values for the fields, eg:
       
      Title, Number of Beds, Number of People, Kitchen Facilities
      Single, 1, 1, Fridge Only
      Double, 2, 2, Fridge Only
      Suite, 3, 6, Full Kitchen
        Choose the parent where the page tree of options will be created, eg a hidden "Options" parent page Select a "Deference in API as" option depending on your needs Choose the input field type Check whether "Allow new pages to be created from field?" should be enabled. As an example, if you entered "Room Types" as the field title, you would end up with all of the following automatically created:
      a fully configured page field called: room_types MULTIPLE FIELDS OPTION - 3 additional fields - number_of_beds, number_of_people, kitchen a parent template called: room_types a child template called: room_types_items (with either just a title field, or with the 3 additional fields as well) a parent page called: Room Types a series of child pages named and titled based on the per line entries in the Select Options textarea The templates are configured such that the "room_types_items" child template can only have the main "room_types" template as a parent, and vice versa.

      Then all you have to do is add the newly created page field to any template you want and you're ready to go!
       
      You can grab it from:
       
      Modules directory: http://modules.processwire.com/modules/process-page-field-select-creator/
      Github: https://github.com/adrianbj/ProcessPageFieldSelectCreator
       

    • By bernhard
      WHY?
      This module was built to fill the gap between simple $pages->find() operations and complex SQL queries.
      The problem with $pages->find() is that it loads all pages into memory and that can be a problem when querying multiple thousands of pages. Even $pages->findMany() loads all pages into memory and therefore is a lot slower than regular SQL.
      The problem with SQL on the other hand is, that the queries are quite complex to build. All fields are separate tables, some repeatable fields use multiple rows for their content that belong to only one single page, you always need to check for the page status (which is not necessary on regular find() operations and therefore nobody is used to that).
      In short: It is far too much work to efficiently and easily get an array of data based on PW pages and fields and I need that a lot for my RockGrid module to build all kinds of tabular data.

      Basic Usage

       
      Docs & Download
      https://modules.processwire.com/modules/rock-finder/
      https://github.com/BernhardBaumrock/RockFinder
       
      Changelog
      180817, v1.0.6, support for joining multiple finders 180810, v1.0.5, basic support for options fields 180528, v1.0.4, add custom select statement option 180516, change sql query method, bump version to 1.0.0 180515, multilang bugfix 180513, beta release <180513, preview/discussion took place here: https://processwire.com/talk/topic/18983-rocksqlfinder-highly-efficient-and-flexible-sql-finder-module/
    • By BitPoet
      MediaLibrary
      Update: MediaLibrary can now be found in the official module list.
      Out of necessity, I've started to implement a simple media library module.
      The basic mechanism is that it adds a MediaLibrary template with file and image fields. Pages of this type can be added anywhere in the page tree.
      The link and image pickers in CKEditor are extended to allow quick selection of library pages from dropdowns. In the link picker this happens in the MediaLibrary tab, where you can also see a preview of the selected image. In the image picker, simply select a library from the dropdown at the top, everything else is handled by standard functionality.
      I've put the code onto github. This module is compatible with ProcessWire 3.
      Steps to usage:
      Download the module's zip from github (switch to the pw3 branche beforehand if you want to test on PW 3.x) and unpack it into site/modules Click "Modules" -> "Refresh" in the admin Click "Install" for MediaLibrary For testing, create a page with the MediaLibrary template under home (give it an expressive title like 'Global Media') and add some images and files Edit a differnt page with a CKEditor field and add a link and an image to see the MediaLibrary features in action (see the screencap for details) Optionally, go into the module settings for MediaLibrary Note: this module is far from being as elaborate as Kongondo's Media Manager (and doesn't plan to be). If you need a feature-rich solution for integrated media management, give it a look.
      Feel free to change the settings for MediaFiles and MediaImages fields, just keep the type as multiple.
      There are some not-so-pretty hacks for creating and inserting the correct markup, which could probably be changed to use standard input fields, though I'm a bit at a loss right now how to get it to work. I've also still got to take a look at error handling before I can call it fit for production. All feedback and pointers are appreciated (that's also why I post this in the development section).

      Edit 09.03.2016 / version 0.0.4: there's now also a "Media" admin page with a shortcut to quickly add a new library.

      Edit 01.05.2016:
      Version 0.0.8:
      - The module now supports nested media libraries (all descendants of eligible media libraries are also selectable in link/image picker).
      - There's a MediaLibrary::getPageMediaLibraries method you can hook after to modify the array of available libraries.
      - You can switch between (default) select dropdowns or radio boxes in the module configuration of MediaLIbrary to choose libraries.
      Edit 10.10.2018:
      Version 0.1.3:
      - Dropped compatibility for ProcessWire legacy versions by adding namespaces
      - Allow deletion of libraries from the Media overview admin page
      - Added an option to hide media libraries from the page tree (optionally also for superusers)
    • By Robin S
      This module corrects a few things that I find awkward about the "Add New Template" workflow in the PW admin. I opened a wishlist topic a while back because it would good to resolve some of these things in the core, but this module is a stopgap for now.
      Originally I was going to share these as a few standalone hooks, but decided to bundle them together in a configurable module instead.
      Add Template Enhancements
      A module for ProcessWire CMS/CMF. Adds some efficiency enhancements when adding or cloning templates via admin.

      Features
      Derive label from name when new template added: if you like to give each of your templates a label then this feature can save some time. The label can be added automatically when templates are added in admin, in admin/API, or not at all. There are options for underscore/hyphen replacement and capitalisation of the label. Edit template after add: when adding only a single template, the template is automatically opened for editing after it is added. Copy field contexts when cloning: this copies the field contexts (a.k.a. overrides such as column width, label and description) from the source template to the new template when using the "Duplicate/clone this template?" feature on the Advanced tab. Copy field contexts when duplicating fields: this copies the field contexts if you select the "Duplicate fields used by another template" option when adding a new template. Usage
      Install the Add Template Enhancements module.
      Configure the module settings according to what suits you.
       
      https://github.com/Toutouwai/AddTemplateEnhancements
      https://modules.processwire.com/modules/add-template-enhancements/