kongondo Posted September 2, 2015 Share Posted September 2, 2015 (edited) FieldtypeRuntimeMarkup and InputfieldRuntimeMarkup Modules Directory: http://modules.processwire.com/modules/fieldtype-runtime-markup/GitHub: https://github.com/kongondo/FieldtypeRuntimeMarkup As of 11 May 2019 ProcessWire versions earlier than 3.x are not supported 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 Frontend Edited May 11, 2019 by kongondo ProcessWire 3.x support only. 25 1 Link to comment Share on other sites More sharing options...
Robin S Posted September 6, 2015 Share Posted September 6, 2015 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? Link to comment Share on other sites More sharing options...
mr-fan Posted September 6, 2015 Share Posted September 6, 2015 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 3 Link to comment Share on other sites More sharing options...
kongondo Posted September 6, 2015 Author Share Posted September 6, 2015 Simple answer is that @Valan had a need and commissioned me to develop this . Seriously though, mr-fan already covered it brilliantly. When I get some time, I'll post some other examples. 3 Link to comment Share on other sites More sharing options...
LostKobrakai Posted September 6, 2015 Share Posted September 6, 2015 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). 2 Link to comment Share on other sites More sharing options...
Macrura Posted October 2, 2015 Share Posted October 2, 2015 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: send or preview a calendar event, which is typed by a chosen template (e.g. event, lesson reminder, etc.) 12 Link to comment Share on other sites More sharing options...
adrian Posted October 2, 2015 Share Posted October 2, 2015 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 4 Link to comment Share on other sites More sharing options...
Macrura Posted October 2, 2015 Share Posted October 2, 2015 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! 3 Link to comment Share on other sites More sharing options...
mr-fan Posted October 3, 2015 Share Posted October 3, 2015 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: Have fun and best regards mr-fan 4 Link to comment Share on other sites More sharing options...
bernhard Posted October 18, 2015 Share Posted October 18, 2015 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" i set visibility for field "headline2" but the field does not show up... 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 Link to comment Share on other sites More sharing options...
adrian Posted November 1, 2015 Share Posted November 1, 2015 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! 1 Link to comment Share on other sites More sharing options...
kongondo Posted November 1, 2015 Author Share Posted November 1, 2015 <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> 4 Link to comment Share on other sites More sharing options...
tpr Posted November 2, 2015 Share Posted November 2, 2015 That would surely convert many users from other CMSes - so please don't go that cinematic 1 Link to comment Share on other sites More sharing options...
naldrocks98 Posted November 5, 2015 Share Posted November 5, 2015 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? Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 5, 2015 Share Posted November 5, 2015 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'). 2 Link to comment Share on other sites More sharing options...
naldrocks98 Posted November 5, 2015 Share Posted November 5, 2015 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 Link to comment Share on other sites More sharing options...
LostKobrakai Posted November 5, 2015 Share Posted November 5, 2015 Also did not work on url variables... i tried this but can't get to work... Speedy people here. Read my edited post above. Link to comment Share on other sites More sharing options...
naldrocks98 Posted November 5, 2015 Share Posted November 5, 2015 you'r edit post work.. thanks by the way... LostKobrakai Link to comment Share on other sites More sharing options...
kongondo Posted November 5, 2015 Author Share Posted November 5, 2015 (edited) @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 November 5, 2015 by kongondo Link to comment Share on other sites More sharing options...
diogo Posted December 3, 2015 Share Posted December 3, 2015 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 3 Link to comment Share on other sites More sharing options...
LostKobrakai Posted December 3, 2015 Share Posted December 3, 2015 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. 3 Link to comment Share on other sites More sharing options...
kongondo Posted December 3, 2015 Author Share Posted December 3, 2015 Maybe even a very tiny 'prettifier' would do....hmmm Link to comment Share on other sites More sharing options...
diogo Posted December 3, 2015 Share Posted December 3, 2015 Or check if Ace is installed, and if not add from a cdn http://cdnjs.com/libraries/ace/ 1 Link to comment Share on other sites More sharing options...
Macrura Posted December 4, 2015 Share Posted December 4, 2015 @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; Link to comment Share on other sites More sharing options...
kongondo Posted December 4, 2015 Author Share Posted December 4, 2015 (edited) @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 December 8, 2015 by kongondo 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now