Leaderboard
Popular Content
Showing content with the highest reputation on 09/08/2017 in all areas
-
Wrapping up the fieldset trilogy comes part 3: Fieldset Group, which is now released. In the post we take a closer look at it and compare it to the other fieldset types. Then we wrap up with some hints about more coming up in the weeks ahead. https://processwire.com/blog/posts/fieldsetgroup-module-released/8 points
-
hi and welcome deceleration quite easy: <?php // overview for($i=1; $i<??; $i++) { echo "<a href='./$i'>"; // create a link with that url segment echo "ZIP $i... [" . $pages->count("template=yourtemplate, zipcode^=$i") . "]"; echo "</a><br>"; } // details $zip = $sanitizer->int($input->urlSegment1); if($zip) { $items = $pages->find("template=yourtemplate, zipcode^=$zip"); foreach($items as $item) { echo "<a href='{$item->url}'>{$item->title}</a><br>"; } }3 points
-
sagol, yuvarlanıp gidiyoruz iste. means for the non-turkish members: thanks, this is really a great community and i learned a lot of interesting stuff. god bless ryan.2 points
-
Ok, in my test setup `country` field may include spaces, so urlSegments is out of question. In these situations you can use query strings and send encoded parameters with urls. If user goes to a nonexistent url, it redirects back to summary list <?php namespace ProcessWire; $detailMode = false; // show people in a country? $grouped = []; if ($input->get->country) { // always sanitize user input $country = $sanitizer->selectorValue($input->get->country); $persons = $pages->find("template=person, country=$country"); $detailMode = true; if (!$persons->count) $session->redirect('./'); } else { // summary mode $persons = $pages->find('template=person'); foreach ($persons as $person) { $country = $person->country; if (isset($grouped[$country])) { $grouped[$country][] = $person; } else { $grouped[$country] = [$person]; } } } ?> <?php if($detailMode): // showing single country ?> <h1><?= $persons->first->country ?></h1> <?php foreach ($persons as $person): ?> <?= $person->title ?><br> <?php endforeach; ?> <?php else: // showing all countries ?> <?php foreach ($grouped as $country => $people): ?> <?php $encoded = "./?" . http_build_query(['country' => $country]) ?> <?= $country ?> <a href="<?= $encoded ?>">[<?= count($people) ?>]</a><br> <?php endforeach; ?> <?php endif; ?> Result looks like this One drawback of using query parameters is that the url looks like mysite.com/url?param=value, instead of mysite.com/url/value.2 points
-
You're welcome. I'm glad your problem got solved. You're right, thanks for pointing that. I was reading the source for urlSegments just today. Gotta love @ryan's humor // ProcessPageView.module /** * Get the requested page and populate it with identified urlSegments or page numbers * * @return Page|null * */ protected function getPage() { $config = $this->wire('config'); $shit = isset($_GET['it']) ? trim($_GET['it']) : "/"; // dirty $it = preg_replace('{[^-_./a-zA-Z0-9]}', '', $shit); // clean unset($_GET['it']); if($shit !== $it && $config->pageNameCharset == 'UTF8') { $it = $this->wire('sanitizer')->pagePathNameUTF8($shit); } // ... while((!$page || !$page->id) && $cnt < $maxSegments) { $it = rtrim($it, '/'); $pos = strrpos($it, '/')+1; $urlSegment = substr($it, $pos); $urlSegments[$cnt] = $urlSegment; $it = substr($it, 0, $pos); // $it no longer includes the urlSegment $selector = "path=" . $this->wire('sanitizer')->selectorValue($it, 2048) . ", status<" . Page::statusMax; $page = $this->pages->get($selector); $cnt++; } // ... }2 points
-
datatable connected to the pagefield updating the pageautocomplete field seemed a little tricky in the beginning but the final approach was quite easy: // handle buttonclicks $('#addcompetences').click(function(e) { e.preventDefault(); var table = $table.DataTable(); // datatable instance var $field = $('#wrap_Inputfield_competences'); // asm select field var $template = $field.find('li.itemTemplate'); // selected page template var $ol = $template.closest('ol'); // get selected competences from table var selectedtable = $.map( table.rows({selected:true}).data(), function(val, i) { return [[ val.id.sort, val.title + ' (' + val.cluster.filter + ')' ]]; } ); // update ASM // clone template and populate values $.each(selectedtable, function(i,val) { // check double if($ol.find('.itemValue:contains("' + val[0] + '")').length) return; // add clone var $new = $template.clone().appendTo($template.parent()); $new.find('.itemValue').text(val[0]); $new.find('.itemLabel').text(val[1]); $new.removeClass('itemTemplate'); }); // add state changed class $field.addClass('InputfieldStateChanged'); // update original input InputfieldPageAutocomplete.rebuildInput($ol); return false; });2 points
-
I've made a few CSS changes, now preview buttons look the same in all 3 image grid modes and I've fixed some other glitches too. The CSS file was a bit overcomplicated, I could eliminate large blocks so I hope I haven't broken anything I also checked the preview images with more than one crop setting (multiple buttons) and it's working fine here. All is in the PR.2 points
-
Others may come up with different suggestions, but intercooler.js (there is a module, but I haven't used it, even though I have used intercooler) can do infinite scrolling and history.pushstate. (And a load of other clever stuff, but they're your main two.)2 points
-
During boot, inside /site/config.php $page is not yet determined, so I am limited in determining what to prepend/append. For this reason I disable $config->prependTemplateFile (& append) and use a 'controller' hook like this. wire()->addHookBefore('TemplateFile::render', function (HookEvent $event) { // skip if AJAX if ($event->config->ajax) return; /** @var TemplateFile $templateFile */ $templateFile = $event->object; // Skip admin pages if (strpos($event->input->url, $event->config->urls->admin) === 0) return; // check if this is a partial template, if so, stop $fileDir = pathinfo($templateFile->get('filename'), PATHINFO_DIRNAME); $templatesPath = $event->config->paths->templates; if (realpath($fileDir) !== realpath($templatesPath)) return; $templateName = $templateFile->page->template->name; $prepends = [ 'routes' => $templatesPath . "{$templateName}.routes.php", 'before' => $templatesPath . "_before.php" // like your _init.php ]; // then comes the actual template file $appends = [ 'view' => $templatesPath . "views/{$templateName}.php", 'after' => $templatesPath . "_after.php", 'layout' => $templatesPath . "layouts/main.php" ]; foreach ($prepends as $name => $file) { if (file_exists($file)) $templateFile->setPrependFilename($file); } foreach ($appends as $name => $file) { if (file_exists($file)) $templateFile->setAppendFilename($file); } }); So to adapt this to your setup, you can define your urlSegments inside template.routes.php, and stop further appends with return $this->halt(). This way only template.routes.php is loaded and remaining appends are skipped while still allowing PW to complete its shutdown.2 points
-
Thank you Ryan! Both modules look awesome! And I see use cases for both of them on sites I am working on right now. It is especially nice to see these developed in response to a community feedback made through a PW weekly poll. And this is the first reason I hope both fill be released in the core. The second is that that FieldsetGroup is such a natural and kind of even expected extension of the regular fieldset it must be valuable to many. I got my ProFields subscription anyways, but still...1 point
-
Optionally, you can create a select field, or better, a page field and select flavors for each post while editing and render items depending on that https://processwire.com/blog/posts/making-efficient-use-of-fields-in-processwire/#use-page-fields-rather-than-individual-checkboxes if($item->flavors->get("name=hoverable")) { // this page has the "hoverable" flavor set }1 point
-
Here are two ways: <?php namespace ProcessWire; /** @var $pages Pages */ $posts = $pages->find('template=post, sort=-published'); $latest = $posts->shift(); // removes first item off of $posts ?> <ul class="post-list"> <li class="item--latest item"> <?= $latest->title ?> </li> <?php if ($posts->count): ?> <?php foreach ($posts as $i => $p): ?> <?php $itemClass = ($i % 3 == 0) ? "item--hoverable" : ''; ?> <li class="<?= $itemClass ?> item"><?= $p->title ?></li> <?php endforeach; ?> <?php endif; ?> </ul> <!-- OR --> <?php if ($posts->count): ?> <ul class="post-list"> <?php foreach ($posts as $i => $post): ?> <?php if ($i === 0): // LATEST POST ?> <li class="item--latest item"> Latest: <?= $post->title ?> </li> <?php elseif ($i === 1): // BASIC ?> <li class="item--basic item"> Basic: <?= $post->title ?> </li> <?php elseif ($i % 3 === 0): // HOVERABLE ?> <li class="item--hoverable item"> Hover Me: <?= $post->title ?> </li> <?php endif; ?> <?php endforeach; ?> </ul> <?php else: ?> <p>No posts found</p> <?php endif; ?>1 point
-
I was just typing something along those lines when you posted. It's either that, or fix Spex, or refactor the whole site not to need Spex. (I figured out where the live site is, and I'm guessing that refactoring isn't actually an option.) You might find that the core PW stuff in the working version is still covered in the docs, since stuff is rarely (never?) deprecated completely, just new stuff added, and there isn't the imperative with PW to upgrade like you might be used to with WP. You can always come back here for advice - we usually try to help when we can.1 point
-
Interesting. I replaced some of those functions with their new counterparts, and now the page is loading without errors, but it is not loading properly... http://dev.delucaswpg.webfactional.com I may have to just "leave well enough alone" and stick with my 2.3 installation... and muddle my way through making the changes — with documentation that is not correct for the version I'm using. Fun times. I really do appreciate you guys taking the time to try to help me figure this out though! Definitely a big help. Thank you.1 point
-
I updated Spex — from 0.2 (!) to 0.99 — and still get this error: Error: Exception: Method ProcessWire::getArray does not exist or is not callable in this context (in /home/delucaswpg/webapps/delucas_dev/wire/core/Wire.php line 519) #0 /home/delucaswpg/webapps/delucas_dev/wire/core/Wire.php(386): Wire->___callUnknown('getArray', Array) #1 /home/delucaswpg/webapps/delucas_dev/wire/core/WireHooks.php(698): Wire->_callMethod('___callUnknown', Array) #2 /home/delucaswpg/webapps/delucas_dev/wire/core/Wire.php(442): WireHooks->runHooks(Object(ProcessWire), 'callUnknown', Array) #3 /home/delucaswpg/webapps/delucas_dev/wire/core/ProcessWire.php(587): Wire->__call('callUnknown', Array) #4 /home/delucaswpg/webapps/delucas_dev/wire/core/Wire.php(445): ProcessWire->__call('callUnknown', Array) #5 /home/delucaswpg/webapps/delucas_dev/wire/core/Wire.php(445): ProcessWire->callUnknown('getArray', Array) #6 /home/delucaswpg/webapps/delucas_dev/wire/core/ProcessWire.php(590): Wire->__call('getArray', Array) #7 /home/delucaswpg/webapps/delucas_dev/site/modules/Spex/Spex.module(250): ProcessWire->_ This error message was shown because: you are logged in as a Superuser. Error has been logged. When I removed Spex I got loads of "function doesn't exist" errors for the page templates, so it looks like this template is relying on it pretty heavily.1 point
-
1 point
-
sorry my solution only works if you have zip-codes like 1... 2... 3... 10... and 19... would be listed under 1... you could replace the for(...) with this $zipcodes = [11, 15, 80, 99]; foreach($zipcodes as $zip) { ... } always depends what your initial data looks like (if you know the zip-code-categories or if they are dynamic). 1 question, so many answers1 point
-
1 point
-
You can group pages depending on a field and output them like this. I used `country` field, instead of `zipcode` but it doesnt change anything <?php namespace ProcessWire; $persons = $pages->find('template=person'); $grouped = []; foreach ($persons as $person) { $country = $person->country; if (isset($grouped[$country])) { $grouped[$country][] = $person; } else { $grouped[$country] = [$person]; } } ?> <?php foreach ($grouped as $country => $people): ?> <h2><?= $country ?></h2> <?php foreach ($people as $p): ?> <p><?= $p->title ?></p> <?php endforeach; ?> <?php endforeach; ?> Which outputs something like this1 point
-
I strongly suggest creating a template for the child pages as well. You might not have an issue at the moment, but a month from now, a year from now, when you need to change something, it won't be where you expect it to be. It'll be harder to maintain. I had to do a number of complete rewrites in the past because I was only complicating things for myself for no reason.1 point
-
Never said that I would recommend reading my second link carefully and trying out markup regions (... And building your site with a template for your child pages instead of URL segments)1 point
-
very nice - a good alternative to other page select options out there, and intuitive for the user;1 point
-
thanks a lot. I wouldnt have got it by now. Must have taken another night without you guys!!!!!!!!!!!!!1 point
-
if($page->template == "contact" || $page->template == "course" || $page->template == "holiday" || $page->template == "newsletter") { if(!$page->is(Page::statusHidden)) include ("contact.inc.php"); } Check contact.inc.php Might be a field on the homepage.1 point
-
1 point
-
Thanks, @abdus for so quick response. You are right, I don't get "category" page because of missed "echo"; And this return $this->halt(); prevents render of "categories" page. From your code: $name = sanitizer()->pageName(input()->urlSegment1); https://processwire.com/api/ref/input/url-segment/ Docs say that urlSegments are already sanitized as page names. Thanks once again!1 point
-
I'm not getting that behavior. I tired to replicate your setup. This is what I have ended up with (I use jobs instead of categories but it shouldnt matter) <?php namespace ProcessWire; // categories.routes.php if (input()->urlSegment2) throw new Wire404Exception(); if (input()->urlSegment1) { /** @var Pages $pages */ $name = sanitizer()->pageName(input()->urlSegment1); $match = $pages->findOne("template=profession, name=$name"); if (!$match->id) throw new Wire404Exception(); echo $match->render(); return $this->halt(); } This is my _init.php. It gets included to every template (after its routes, if exists) <?php namespace ProcessWire; require_once '_func.php'; $testPages = $pages->find('template=profession, limit=5'); And I use it inside actual page template that renders `category` page <?php namespace ProcessWire; ?> This is: <?= $page->title ?> <p>Other Pages:</p> <?php foreach ($testPages as $p): ?> <?= $p->title ?><br> <?php endforeach; ?> And both pages render correctly So, to me the only thing that seems missing is echo statement before $p->render() and return $this->halt(); after that EDIT: This is the backend structure, I am guessing you have a similar one. You get categories from another parent1 point
-
1 point
-
there's https://www.adminer.org/#download Put it in your root directory and access it from mysite.com/adminer.php You can find database credentials in /site/config.php1 point
-
Hmm that looks quite outdated. My suggestions may not even exists in your version. Also the module list seem to include only core modules. Since you have the sources, can you download /site/templates and /site/modules folders and search all files for @ symbol?1 point
-
Hello, this module has been updated and it is now compatible with Graph API version 2.10. Parameters 'description' and 'name' are not supported by the new Graph API version. Therefore, fields for description and name cannot be provided anymore.1 point
-
URLs are generated from page names by default. What I'm trying to show is that you dont have to use IDs for page names, otherwise when generating URLs you'd get /codes/123 instead of /codes/wall-mounted-light. Below is a sample template that should work in your case <?php namespace ProcessWire; /** @var Pages $pages */ /** @var Sanitizer $sanitizer */ /** @var Page $child */ $child = null; if ($input->urlSegment1) { $codeChildName = "code--{$input->urlSegment1}"; $codeChildName = $sanitizer->pageName($codeChildName); $child = $pages("parent=$page, name=$codeChildName"); if (!$child->id) throw new Wire404Exception(); } ?> <div class="code-page"> <?php if ($child): ?> <!-- RENDER CHILD PAGE --> <h1>Child: <?= $child->title ?></h1> <?= $child->body ?> <?php else: ?> <!-- RENDER CODE PAGE WITH CHILDREN --> <h1><?= $page->title ?></h1> <?= $page->body ?> <h2>List of children:</h2> <ul class="chilren"> <?php foreach ($page->children as $c): ?> <?php $childUrl = "./$c->name"; // generate urls for the child ?> <li class="child"> <a href="<?= $childUrl ?>"><?= $c->title ?></a> </li> <?php endforeach; ?> </ul> <?php endif; ?> </div> I also concur with @bernhard. If you're modifying the core behavior and rendering child page at the url that matches the child's, then I'd say you should reconsider your approach. You're only complicating it for yourself. Also, thanks, I'm doing what I can. These questions are like quizzes that I enjoy solving, and get to practice coding with PW.1 point
-
If pages are not public, then you wouldnt need to worry about SEO. Page name format works for pages created in the future, but for the current pages you can do: $codes = wire()->pages('template=code'); foreach ($codes as $c) { // wall-mount-mini-split becomes code--wall-mount-mini-split $replacement = "code--{$c->name}"; $c->of(false); $c->setName($replacement); $c->save(); } And in your template, where you check urlSegments: if($input->urlSegment1) { if ($input->urlSegment2) throw new Wire404Exception(); $codeName = "code--{$input->urlSegment1}"; $codeName = $sanitizer->pageName($codeName); $code = $pages("template=code, name=$codeName"); if(!$code->id) throw new Wire404Exception(); // do sth with the code page }1 point
-
What you need to do is basically: Get a list of pages with limit for pagination $pages->find('template=post, limit=10, sort=-published'); Render a list of items Render the pagination at the bottom of the page Using JS listen to scroll event, and trigger AJAX request Get the response, filter the list of elements, replace the container that holds the old items Repeat As a different approach, you can implement barba.js for PJAX (ajax with history support) (and limit it to only pagination links, if you prefer), and trigger click() on the next pagination link when it gets closer to viewport. For that you can use scrollMonitor.js. Total weight of these two scripts are under 15KB, they don't add much load on the page. One bonus is that you can enable barba.js on all (internal) links (it's enabled by default) to make transitions between pages feel more responsive.1 point
-
@cjx2240, I'm not sure if this is the best way, but hey it works. Put this in your /site/ready.php wire()->addHookBefore('Page::render', function (HookEvent $e) { // requested page (not the one being rendered) $page = $e->page; // skip admin pages if (strpos($e->input->url, $e->config->urls->admin) === 0) return; // force redirect to homepage if ($page->id != 1) { $e->session->redirect('/'); } }); And in your home template, put this at the beginning <?php namespace ProcessWire; $splashPage = $pages->get(1353); echo $splashPage->render(); return $this->halt();1 point
-
https://moz.com/blog/structured-data-for-seo-1 Seems to me that one of the huge advantages we have with PW is that it's fairly straightforward to include 'extra' stuff as part of our rendered markup, without necessarily waiting for someone else to develop a plugin of some kind, as is so often the case with other CMSs. This blog post (and Pt 2 when it comes out I expect) not only goes into some depth on its subject, but links to loads of other resources on the topic.1 point
-
Just a word of caution. Do not use this in high traffic pages, because it holds a race condition, where people might be assigned the same number.1 point
-
Just updated the module to version 0.1. Almost everything in it has changed so reading the docs is a must The module does less "magic" as before, eg. doesn't add the "lazyload" class and data-sizes automatically. These should be added manually or you can write a wrapper function if you would like to simplify things (please notify me if you think you wrote one that should be part of the module). Also all the module settings are gone except the "Load scripts" checkbox because all other settings became useless after the rewrite. The new syntax looks like this (here with a helper to add a noscript tag for no-js fallback): <?php $img = $page->featured_image; ?> <img data-srcset="<?php echo $img->srcset('200x300,*2,*3'); ?>" class="lazyload" data-sizes="auto" alt="" /> <noscript> <img src="<?php echo $img->srcsetUrls[0]; ?>" /> </noscript> The main change is that you can easily tell what image sizes (sets) you need ("200x300,*2,*3" in the above example). Of course you can use WxH values for each set or use divisors too. What's more you don't have to start with the lowest image size, eg. "1200x900, /2, /4" is perfectly fine.1 point