Leaderboard
Popular Content
Showing content with the highest reputation on 03/14/2019 in all areas
-
I've just upgraded the forums to the latest version 4.4.x as there was a critical security patch that warranted it. As usual, there is some pain in upgrading from a 4.x to 4.x branch due to template changes and feature changes/additions so you may find things have moved around a bit. There is still work to do on the template as this was a little rushed (security update forced my hand) but it should be functional at the very least. If you spot anything drastically broken that I may have missed, please let me know here. Minor template tweaks (fonts, alignment etc) will be updated in the next few days.11 points
-
5 points
-
@jploch AFAIK, you can turn off PCRE JIT compilation if needed. Some info in the discussion here.3 points
-
Thanks @adrian, I was really missing these features (search and recents list). It was a challenge to set up FilterBox to fit in here but fortunately everything fell into place.3 points
-
Hi @louisstephens, <link rel="icon" type="image/png" href="<?php echo $config->urls->templates?>favicon.png" /> There is no need to add a splash before favicon.png. Gideon3 points
-
I'm glad lots of you like this tip. In the meantime I found more to read: https://codequs.com/ has lost of recent articles on web development. About pure JavaScript I found these one to be interesting: Do we still need JavaScript frameworks? Quote: "That said, much of what frameworks do will probably become easier to do with smaller libraries and/or native code as time goes on. Take my application as an example. At the same time, if the large frameworks and libraries remain versatile they may morph, adapt, and stick around. If not, they may end up like jQuery — a tool of the past for the most part." https://codequs.com/p/r1Jzty4S4/do-we-still-need-javascript-frameworks Design Patterns: The Comprehensive Guide to JavaScript Design Patterns https://codequs.com/p/B1lboCPS4/the-comprehensive-guide-to-javascript-design-patterns A guide to prototype-based class inheritance in JavaScript https://codequs.com/p/HyiztJFH4/a-guide-to-prototype-based-class-inheritance-in-javascript Prototype-based Inheritance and Prototype chain in JavaScript (ES5) https://codequs.com/p/Hy6_WgCI4/prototype-based-inheritance-and-prototype-chain-in-javascript-es5 JavaScript ES6 Classes https://codequs.com/p/H1poPtiS4/javascript-es6-classes Javascript and Functional Programming: An Introduction https://codequs.com/p/BJL08ThSV/javascript-and-functional-programming-an-introduction State management patterns in JavaScript: Sharing data across components https://codequs.com/p/HkD3mZ9LE/state-management-patterns-in-javascript-sharing-data-across-components "Tips" JavaScript naming conventions: do’s and don’ts https://codequs.com/p/B1-VWxRIN/javascript-naming-conventions-do-s-and-don-ts 12 Concepts That Will Level Up Your JavaScript Skills https://codequs.com/p/BkdaLTnS4/12-concepts-that-will-level-up-your-javascript-skills Understanding the Spread Operator in JavaScript https://codequs.com/p/ByL0qvXUV/understanding-the-spread-operator-in-javascript The Complete Guide to Loops in JavaScript https://codequs.com/p/S1dZcv7LN/the-complete-guide-to-loops-in-javascript Memoization is an optimization technique that speeds up applications by cached result https://codequs.com/p/H1XlyssUE/understanding-memoization-in-javascript Arrays: How to Sort an Array of Objects in JavaScript https://codequs.com/p/BysEP63SV/how-to-sort-an-array-of-objects-in-javascript 2 Ways to Merge Arrays in JavaScript https://codequs.com/p/H1jReV-IN/2-ways-to-merge-arrays-in-javascript How to Deep Clone an Array in JavaScript https://codequs.com/p/rynJIss84/how-to-deep-clone-an-array-in-javascript 4 Uses of JavaScript's Array.map() You Should Know https://codequs.com/p/B13x_ZqLE/4-uses-of-javascript-s-array-map-you-should-know Asynchronous tasks: Understanding Promises in JavaScript https://codequs.com/p/Sy3hiPP8N/understanding-promises-in-javascript JavaScript Promises: The Definitive Guide, Part 1 https://codequs.com/p/BkToHnnU4/javascript-promises-the-definitive-guide-part-1 Introduction to fetch() https://developers.google.com/web/updates/2015/03/introduction-to-fetch How to Use the JavaScript Fetch API to Get Data https://scotch.io/tutorials/how-to-use-the-javascript-fetch-api-to-get-data3 points
-
Don't shoot the messenger – I know this is from WordCamp, not ProcessCamp, but there's plenty of quality material there not strictly tied to WordPress ? https://wpwoofi.com/wordcamp-nordic-paneelit-2019/ Sadly the recording misses the beginning of the UX for everyone talk by Piccia Neri. This was my absolute favourite in the whole event, there were so many good points there. She has the ability to explain scary-sounding concepts and processes in a way that makes them really easy to grasp, and actually makes them seem attainable even in relatively low-budget projects ? "Lessons from WordPress core on how to (not) write code" has some good pointers for anyone designing dev tools, "Cache is keeping you from reaching your full potential as a developer" contains valid arguments, and although "Continuous integration and deployment with WordPress" is definitely WP-specific, the basic principles can be easily applied to other platforms as well. Just to mention a few. Anyhow, I hope someone finds these interesting ?2 points
-
2 points
-
2 points
-
Back here with... quite an amount of shame... I'm sorry I have taken time from you all. Here's the thing : my site/ready.php which I thought did not have access to bd() because I couldn't even see a simple bd('ok'); was not at the right place. A bell just rang in my head a few minutes ago after making a fresh re-install of a blank profile ! I came back to my original local site and thought : "No way, Fred ! site/ready.php NOT your-website-root/ready.php !!!!" I moved ready.php and.... tada ! (Of course...). What a nerd... So again, SORRY for having taken some of your time, but thanks for your helpful answers. I still have learned quite a lot from our exchange and that is the most important thing. I'm glad I posted in 'Getting started' ;)2 points
-
I remember falling into the same trap. I didn't modify the generated config.php but simply moved the contents from the unzipped subdirectory one up before I submit the database information.2 points
-
2 points
-
Thanks Pete! Avatars are also stretched in the Notifications panel. Another thing I noticed is that all out locations have "Location" prepended - eg: "LocationBuckley, Wales"2 points
-
2 points
-
Something looks wrong here. The avatars in the Latest Topics column are stretched out vertically. Also the whole Latest Topics column has moved upwards out of line with the Welcome to Processwire column.2 points
-
2 points
-
@SamC: Exactly @happywire: You are completely right except the last point: The snippet performs the boolean evaluation of Math.random() some thousend of times: var YesIfTrue = !!~~(Math.random() * 2); // Boolean result 50/50 You either get a boolean true or boolean false for each iteration. YesIfTrue is set, if the truncation of (Math.random() * 2) is equal or above 1.0 (or Math.random() returns a value equal or above 0.5). The less obfuscated version of that line would be: var YesIfTrue = Math.random() >= 0.5; Which can be unrolled to: var YesIfTrue; if(Math.random() >= 0.5) YesIfTrue = true; else YesIfTrue = false; which is what actually happens behind the scenese: A numerical comparison on two floats along with a "jump" to either assignment statement. While there still is some "jumps are bad" in many minds, that's not necessarily true for JavaScript. In fact the version using the comparison may effectively execute faster than the obfuscated "true boolean" version, but the unrolled version is slowest (10Mio iterations, Firefox 65): True Boolean: Yes: 4999123 No: 5000877 in 54ms Logical: Yes: 9997660 No: 10002340 in 51ms Comparison: Yes: 14996131 No: 15003869 in 39ms Unrolled: Yes: 19995907 No: 20004093 in 98ms Floor: Yes: 24996634 No: 25003366 in 57ms var i, cntYes=0, cntNo=0; var tStart, tEnd; tStart = window.performance.now(); for(i=0; i<10000000; ++i) { var YesIfTrue = !!~~(Math.random() * 2); cntYes += YesIfTrue; cntNo += !YesIfTrue; } tEnd = window.performance.now(); console.log('True Boolean: Yes: '+cntYes+' No: '+cntNo+' in '+(tEnd-tStart)+'ms'); tStart = window.performance.now(); for(i=0; i<10000000; ++i) { var YesIfTrue = ~~(Math.random() * 2); cntYes += YesIfTrue; cntNo += !YesIfTrue; } tEnd = window.performance.now(); console.log('Logical: Yes: '+cntYes+' No: '+cntNo+' in '+(tEnd-tStart)+'ms'); tStart = window.performance.now(); for(i=0; i<10000000; ++i) { var YesIfTrue = Math.random() >= 0.5; cntYes += YesIfTrue; cntNo += !YesIfTrue; } tEnd = window.performance.now(); console.log('Comparison: Yes: '+cntYes+' No: '+cntNo+' in '+(tEnd-tStart)+'ms'); tStart = window.performance.now(); for(i=0; i<10000000; ++i) { var YesIfTrue; if(Math.random() >= 0.5) YesIfTrue = true; else YesIfTrue = false; cntYes += YesIfTrue; cntNo += !YesIfTrue; } tEnd = window.performance.now(); console.log('Unrolled: Yes: '+cntYes+' No: '+cntNo+' in '+(tEnd-tStart)+'ms'); tStart = window.performance.now(); for(i=0; i<10000000; ++i) { var YesIfTrue = Math.floor(Math.random() * 2); cntYes += YesIfTrue; cntNo += !YesIfTrue; } tEnd = window.performance.now(); console.log('Floor: Yes: '+cntYes+' No: '+cntNo+' in '+(tEnd-tStart)+'ms');2 points
-
Wow, there's some really great replies here, thanks everyone ? For clarity, the context is 'this' (quite literally): http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/ That line came from this section on the page: 3. Fix this when method is assigned to a variable So what I've read previously in this thread and about bitwise OR, is this what happens? // Let's forget about the + 1 -1 stuff for now // Math random returns a float between 0-1 (not inclusive of 1) var randomNum = ((Math.random() * 2 | 0); // Once this float is multiplied by two (keeping the decimal places shorter) var randomNum = (1.6 | 0); // After forced type coercion to int and trucation (because of bitwise OR) var randomNum = (1 | 0); // Binary values are compared // Bitwise OR: 1 compared to 0 = 1 var randomNum = 1; // OR var randomNum = (0.7 | 0) // After forced type coercion to int and trucation (because of bitwise OR) var randomNum = (0 | 0); // Binary values are compared // Bitwise OR: 0 compared to 0 = 0 var randomNum = 0; Just did a super quick demo to try and solidify this in my head, if you don't use vscode and quokka plugin, try it, it's awesome ? @happywire if you're just starting out with JS, I can highly recommend this course: https://www.udemy.com/understand-javascript/ Anthony is an incredible teacher. This isn't just your usual "make a project with me" i.e. just code along, finish the project, learn next to nothing and not be able to implement anything you've learned in different scenarios kind of course. This is much more about the theory of how JS works.2 points
-
Ha, thx heaps for the detailed reply. As you can see I understood it wrong and thank you for getting back about it. Much appreciated! So, I am just learning JS basics (doing this course at the moment udemyDOTcom/javascript-bootcamp-2016/ ), and to clarify/repeat, what is happening here is called type coercion as explained here for example https://eloquentjavascript.net/01_values.html#h_AY+YGu6qyM , right? Integer is a full number, so no comma behind it, in this case either 0 or 1. Since Math.random outputs floating numbers, meaning with comma and lots of numbers behind the comma, then those numbers, the decimals, are just cut off, truncated, like you say. Then you say this and I think this is highly important to understand because no method is called. So instead of converting the floating result with Math.floor one can just use the logical operator to get an integer, right? The snippet shows how many times from 10'000 runs Math.random() outputs a true integer without type coercion and how many times it outputs a floating number, right?2 points
-
2 points
-
sorry: No! Any logical operation like OR '|', AND '&', EXOR '^', Bitwise complement '~' or even shift can only be processed on integers. Using one of these operators enforce JavaScript to typecast any other type into integer. If one of the operators is a float (like return value of Math.random), then decimals are just truncated (a 1.99999 gets 1), if its a string, JS tries to convert it into an integer first. The logical OR (in contrast to the boolean OR '||') is executed in any case. Even if '| 0' does not seem to make any sense, its just there to enforce the type conversion, so the result is an integer. Using a logical operator in contrast to Math.floor basically optimizes for performance (no method call). And if you need a true boolean result and love obfuscated code, try this: var randomNum = !!~~(Math.random() * 2); Maybe this snippet helps to clarify it: var i, cntYes=0, cntNo=0; for(i=0; i<10000; ++i) { var YesIfTrue = !!~~(Math.random() * 2); // Boolean result 50/50 cntYes += YesIfTrue; // Count only true results cntNo += !YesIfTrue; // Count only not true results } console.log('Yes: '+cntYes+' No: '+cntNo);2 points
-
The hook code definitely needs to be in /site/ready.php or /site/init.php. It won't work in your template-prepended _init.php file - the page is already rendering by the time that code executes.2 points
-
We have a fairly simple website: www.labsphere.com It was developed in 2015/2016 by a contractor who did a great job of capturing what we needed. We are happy with his work and the site has been great, though we are also looking at replacing the site within the next year just to keep our brand fresh. The problem is, we have no one on staff that can manage the site beyond very basic Processwire CMS (add pages, add images, add text, etc). The original contractor who developed our site is available when we need him to make changes, but for business integrity purposes we need to have a second person or agency with access to our site as a backup. If the original developer wins the lottery and no longer wants to work on websites, we need someone on staff who could assist with issues. My goal would be to find someone who can act as a backup for when the original developer may be too busy to assist with issues. Maybe a monthly retainer could be paid for someone to "be on call" for times when we want to change something? Let me know if you are interested or have any questions. Thanks, Darlene Delano 603-731-4916 ddelano@labsphere.com2 points
-
You are right. I am not referring to the website. However, you might need certain aspects of your products to be multilingual, for instance, their categories/collections, descriptions, etc. Padloper needs to make sure that the developer/shop owner has inputs corresponding to the languages they have installed for entering information. In my example above, if you had a product "Trousers" and your shop is in Canada, you probably have an English and a French version of the site. Padloper needs to give you inputs for both when you are creating product categories, tags, or inputting product titles, descriptions, etc. Maybe you are thinking about old Padloper ? :-). Exactly.2 points
-
@louisstephens In that thread you linked I found and since I cannot edit my above post I meant that in fact the source from the later , "srcset, sizes and picture support" uses art direction instead of sizes and dpi, however I also read through the MarkupSrcSet thread and it does not seem correct to me at least, however I might be able to look into that repo to learn how image variations are created server-side so that I can have an image array to work with without affecting the frontend. If you are unsure, test the output with https://ausi.github.io/respimagelint/ it is the definite answer to having correct syntax when it comes to responsive images, be this using art direction or sizes.1 point
-
Thats fine with me. If I use Mamp with PHP 5.6 this issue is solved. No worries! Keep up the good work! Looking forward to use this one day ? I still have no clue what stops the markup regions from working though.1 point
-
Sorry dude, I am aware of this issue but forgot to update the first post and the github doc. So yes, basically, In the last version of Duplicator, its necessary (but unwanted) to move the unzipped data to the parent dir.. And about your last issue, try what its said in the github issue linked by @netcarver and more precisely this one : https://github.com/composer/composer/issues/7836#issuecomment-452341683 And just saying, I have not tested the module with PHP 7.x and it might have some issues on this version. sorry for the inconveniences, I hope to get the time to finally work on the V2 ? but I promise you guys to take a look at the actual version and make a revision in the last 10 days or ask to moderators to ban me from the forum ! ? ?1 point
-
Hi. Please PM @Pete, the forum admin. Maybe some settings got mucked up. Sorry.1 point
-
I changed the PHP version to 5.6 and these errors are gone now. However my markup regions seem not to be working. But when logged into the admin everything on the frontend works fine. When logged out I get an error saying "no regions" and the site is messed up. Iam about to give up on this and just use the site profile exporter for now ?1 point
-
The installation worked that way. But Iam still getting errors on the frontend saying Warning: preg_replace(): JIT compilation failed: no more memory Any Ideas, what is causing this? When I use the site profile exporter and install the profile everything is working fine.1 point
-
You mean something like this? $content = $page->images; if (count($page->images)) { // the page has one or more images foreach ($page->images as $image => $value) { $content .= $value; $content .= "picture markup to follow.."; } }1 point
-
I had the same problem a couple of times now. For example when I try to install a backup of a live site on my localhost (Running on Mamp) or an a web server I always get the error config file cannot be found. The issue happened in the installation process after entering the database data and proceed. Maybe this is happening when the website is in another subdirectory and not the web root? The duplicator always makes a subdirectory when unzipping the files and then looks for the config in the root folder. After I manually change the config file, the site was showing up and I could see all the content in the admin, but had some strange errors on the frontend.1 point
-
1 point
-
Looking nice even in its unfinished state :-). One thing now that we have you here (I think I might have asked this before), you know when one is browsing list of unread posts/content, we used to be able to hover on a topic's title in the list and click a button/link to mark that AND ONLY that post as read. That was a time saver! There are times when you just want to mark A FEW/SOME posts as read without actually opening them (?). Are you able to look into this please? Thanks!1 point
-
Edge (still same machine): True Boolean: Yes: 4998588 No: 5001412 in 3542.50002880837ms Logical: Yes: 9999775 No: 10000225 in 3009.699778367602ms Comparison: Yes: 14999604 No: 15000396 in 3001.5002759201707ms Unrolled: Yes: 19998134 No: 20001866 in 3037.500176051153ms Floor: Yes: 25002010 No: 24997990 in 4482.999860439448ms1 point
-
The thread finally switched into Browser Benchmarking now. My numbers were taken from Firefox, which returns now as an integer only. On Vivaldi (Chromium) this is a float and execution times are generally longer (same machine) and Logical indeed is fastest: True Boolean: Yes: 5001949 No: 4998051 in 201.30000000062864ms Logical: Yes: 10001446 No: 9998554 in 173.00000000250293ms Comparison: Yes: 15001053 No: 14998947 in 177.5999999990745ms Unrolled: Yes: 20000397 No: 19999603 in 240.49999999988358ms Floor: Yes: 24999139 No: 25000861 in 186.0999999989872ms So watch your step when optimizing for performance in JS.1 point
-
I get different results: So for me the logical was the fastest ? Second try:1 point
-
1 point
-
1 point
-
Sorry, I wasn't suggesting setting everything up again - just a clean PW install with no modules, pages, templates etc just to see if it works. I imagine it will, but thought it might be a good sanity check in case there is some weird server setting somehow interfering - although I can't imagine what and you mentioned that you tried on your local dev as well and it still doesn't work.1 point
-
https://flaviocopes.com/page/ebooks/ I am in the middle of reading his The JavaScript Handbook which is great to get up to speed in the additions of the language added in the last few years. This is a no-nonsense, easy to understand, from-a-programmer-to-programmers book, highly recommended ? All six titles: The JavaScript Handbook (171 pages) JavaScript from ES5 to ESNext (84 pages) The React Handbook (220 pages) The Node.js Handbook (189 pages) The Express.js Handbook (61 pages) The Vue.js Handbook (122 pages) Happy coding ?1 point
-
Just a thought: could there be a before hook on Page::render (perhaps from a 3rd party module) that replaces the original function and prevents after hooks from running? You can see all active hooks with trace with that little snippet: $allHooks = $hooks->getHooks($page, 'render'); bd($allHooks); Make sure to visit a page on the frontend, otherwise ProcessPageRender won't be invoked and Page::render won't even exist (at least that's the case here when testing on 3.0.96.1 point
-
Hello, I support this: In other words I think supporting multilingual stores is a must and doing it the PW way is the easiest to use by those who will build stores based on Padloper 2. Regarding performance, custom db tables might have an advantage but – I guess – most Padloper 2 sites will never reach the point when it matters.1 point
-
To see all the places where a particular method is called by the core you would need to search the core code. In the case of Fieldtype::getInputfield the most significant places are in Field::getInputfield, which returns the inputfield according to the fieldtype of that field, which in turn is called by Fieldgroup::getPageInputfields, which loops through all the fields that belong to a fieldgroup (you can think of a fieldgroup as being sort of the same as the template) to get and populate their inputfields so they can be displayed in Page Edit (for instance). But you probably don't need to spend time working through all of that in order to successfully create a Fieldtype module. An important thing to understand if you don't already is that your Fieldtype module extends the Fieldtype class. This is called Object Inheritance: http://php.net/manual/en/language.oop5.inheritance.php So all the methods in the Fieldtype class also belong to your module, and the code for those methods is what you see in Fieldtype.php unless you override the method by including it in your module. To illustrate with an example, we can see that Fieldtype::getBlankValue returns an empty string: https://github.com/processwire/processwire/blob/cbfe97de207e3166451f16865429c02c081791e8/wire/core/Fieldtype.php#L494 If we look at FieldtypeText we see that it doesn't include a getBlankValue() method - it doesn't need to because the getBlankValue() method of Fieldtype already returns the right value for a blank text field. But if we look at FieldtypeCheckbox we see it does include a getBlankValue() method - that's because an empty string isn't the right type of value for a blank (unchecked) checkbox, so it implements its own method to return 0.1 point
-
@tiefenbacher_bluetomato Here is an example script from my migration. Note that I did not use MarkupSeo, in my case I had two fields "seoTitle" and "seoDescription". I highly recommend using the migrations module to execute such logic. $pages = $this->wire('pages')->findMany("seoTitle|seoDescription!='',include=all"); foreach ($pages as $page) { if (!$page->hasField('seo')) { continue; } $page->of(false); foreach ($this->wire('languages') as $language) { $this->wire('user')->language = $language; $title = $page->seoTitle->getLanguageValue($language); $desc = $page->seoDescription->getLanguageValue($language); $page->seo->meta->title = $title ?: 'inherit'; $page->seo->meta->description = $desc ?: 'inherit'; } $page->save(); }1 point
-
I agree. Let's put it in the meta group. ? There is also no need to setup default values for the canonical url, it always equals the page's url unless overridden.1 point
-
Here's something to chew on. Start with this tutorial: https://processwire.com/blog/posts/building-custom-admin-pages-with-process-modules/ Some code to play with. This creates a paginated ProcessWire-rendered HTML table. Create a module as per above tutorial. Use the following code in your Process module's execute() method. You need to create some people pages. In this example, they use the template 'people'. Edit functionality not included. Have a look at Blog module for that, here. For CSV upload (not included), have a look at Matrix module here for uploading CSV file and here for reading CSV file. /** * Display, Add and Edit People. * * Called when the URL is peoples's page URL + "/people/" i.e. URL Segment. * Renders a table with People information. People can be edited via modal. * * @access protected * @return mixed $form rendered form * */ public function ___execute() { $modules = $this->wire('modules'); $input = $this->wire('input')->post; $pages = $this->wire('pages'); // CREATE A NEW FORM $form = $modules->get('InputfieldForm'); $form->attr('id', 'people'); $form->action = './'; $form->method = 'post'; // CREATE AN INPUTFIELD MARKUP: Will hold list of people table $m = $modules->get('InputfieldMarkup'); $m->textFormat = Inputfield::textFormatNone;// make sure ProcessWire renders custom HTML // $m->label = $this->_('Edit'); // $m->description = $this->_('Click on a title to edit the item.'); // CREATE A NEW TABLE: for people $t = $modules->get('MarkupAdminDataTable'); $t->setEncodeEntities(false); $t->setClass('peopleTable'); // set header rows $peopleTableHeaders = array( '<input type="checkbox" class="toggle_all">', $this->_('Title'), $this->_('Name'), $this->_('Surname'), $this->_('Another Column'), $this->_('One More Column'), $this->_('Published'), #$this->_('Date'), ); $t->headerRow($peopleTableHeaders); // grab a limited number of people to show in people dashboard. Limit is hardcoded in this example $people = $pages->find("template=people, include=all, sort=-created, parent!=7, limit=10"); foreach ($people as $p) { if (!count($people)) break;// if no people found, break early // check if person page is published or not $p->is(Page::statusUnpublished) ? $status = '<span class="unpublished">' . $this->_('No') . '</span>' : $status = $this->_('Yes'); // set table rows $peopleTable = array( "<input type='checkbox' name='posts_action[]' value='{$p->id}' class='toggle'>",// disabled sorting on this in .js file "<a href='{$this->wire('config')->urls->admin}page/edit/?id={$p->id}&modal=1' class='editPeople pw-modal pw-modal-medium'>$p->title</a>", $p->title, $p->person_name, $p->person_surname, $p->another_column, $p->one_more_column, $status ); // render the table rows with variables set above $t->row($peopleTable); }// end foreach $people as $p // display a headline indicating quantities. We'll add this to people dashboard $start = $people->getStart()+1; $end = $start + count($people)-1; $total = $people->getTotal(); if($total) $peopleCount = "<h4>" . sprintf(__('People %1$d to %2$d of %3$d'), $start, $end, $total) . "</h4>"; // add a description to people dashboard {postsCount, limitSelect and instruction OR no people found status} $m->description = $total == 0 ? $this->_('No items found.') : $peopleCount . $this->_('Click on a title to edit the item.'); $m->notes = "People table notes"; $currentUrl = $this->wire('page')->url . $this->wire('input')->urlSegmentsStr."/";// get the url segment string. In this case it is "people" $pagination = $people->renderPager(array('baseUrl' => $currentUrl)); $m->attr('value', $pagination . $t->render() . $pagination);// wrap our table with pagination $form->add($m); $post = $this->wire('input')->post; // render the final form return $form->render(); }1 point
-
a simple way of caching (nearly) everything using wirecache and 2 page render hooks in site/ready.php // the next ensures that the following code will only run on front end (otherwise back end would get cached, too which results in problems) // make sure to place anything you need in the backend before this line or change it to your needs.. if ((strpos($page->url, wire('config')->urls->admin) !== false) || ($page->id && $page->is('parent|has_parent=2'))) return; $cacheName = "prefix__$page->id-$page->template-{$user->language->name}"; if ($urlSegment1) $cacheName .= "-$urlSegment1"; if ($urlSegment2) $cacheName .= "-$urlSegment2"; if ($urlSegment3) $cacheName .= "-$urlSegment3"; if ($input->pageNum > 1) $cacheName .= "-page$input->pageNum"; // if already cached exit here printing cached content (only 1 db query) $wire->addHookBefore('Page::render', function() use($cache, $cacheName) { $cached = $cache->get($cacheName); if ($cached) { exit($cached); } }); // not cached so far, continue as usual but save generated content to cache $wire->addHookAfter('Page::render', function($event) use($cache, $cacheName) { $cached = $cache->get($cacheName); if (!$cached) { $cache->save($cacheName, $event->return); } unset($cached); }); of course not the same as a proper flat file cache like procache but at least saving many database queries make sure to adjust the $cacheName as needed, you can even cache query strings, almost everything you'd like and you could wrap everything in a condition to only run if no incoming post or query strings so form submits keep working example if (!count($input->get) && !count($input->post) && !$config->ajax) { // cache logic from above } have fun1 point
-
Another way you can go is to use page reference fields. Add two new 'Page' reference fields: topnav and footnav. Make them support multiple pages. Don't restrict it to a parent or template. Select 'PageListSelectMultiple' as the Inputfield for them. Save, and add them to your Homepage template. Now edit your homepage. For the 'topnav' field, select all the pages you want as part of your top navigation, and for the 'footnav' field select all the pages that should appear in your footer navigation. Drag to sort them in the order you want. Edit your main markup file (or head/foot includes) and use the following code to output that navigation: <?php foreach($pages->get("/")->topnav as $item) { echo "<li><a href='{$item->url}'>{$item->title}</a></li>"; } …repeat the same for the footer nav, except iterate the footnav (rather than topnav) field. In the sites that I develop, I almost always have the footer nav hard coded in the main markup file (I don't usually need it to be dynamic). For when I need the topnav dynamic, I'm usually sticking to the site's root level structure for the navigation (iterating the non-hidden children of the homepage). You may need all this stuff to be dynamic, in which case there are a lot of options. But I just wanted to mention that you should only make stuff dynamic that needs to be. When stuff can be hard coded in a template file, it consumes fewer resources. So if you stick to a policy of hard coding stuff that changes rarely and doesn't need to be dynamic, then you'll benefit from better performance, use less energy, save more trees, etc.1 point