Leaderboard
Popular Content
Showing content with the highest reputation on 07/04/2013 in all areas
-
I recently completed a website that had a very large gallery requiring multiple albums (categories) and 100+ images per album with pagination. The solution I developed accomplishes this with just 2 templates (gallery-index and gallery-album) and a single multi-image field for each album, allowing for quick, mass upload of images*. One of the great things about ProcessWire is that you can custom build something like an image gallery with just the tools that the template system and API provide out of the box, without going in search of modules. Once we have the basic templates set up, we will use the excellent FancyBox jQuery script/plugin to add some slick Javascript "lightbox" functionality on top of it. The gallery will still work without FancyBox or with Javascript disabled; it will simply fall back to opening each image in a blank page. So, without further ado... 1. Create a file named gallery-index.php in your site/templates/ folder with the following code. This will be the main page of your gallery. The code simply loops through all of the photo albums that are children of your main gallery page and uses the first image in the album as the cover photo: <? include("./head.inc") ?> <? // Configure thumbnail width/height $thumbWidth = 250; $thumbHeight = 250; // Create an array of the child pages that use the gallery-album template $albums = $page->children('template=gallery-album'); ?> <h2><?= $page->title ?></h2> <div class="gallery"> <ul class="gallery-row row"> <? if(count($albums) > 0) { foreach($albums as $album) { // Grab the first image from the album and create a thumbnail of it $thumb = $album->images->first()->size($thumbWidth, $thumbHeight); ?> <li class="col span4"> <div class="gallery-album photoShadow"> <a href="<?= $album->url ?>" class="gallery-albumThumb" title="<?= $album->title ?>"> <img src="<?= $thumb->url ?>" alt="<?= $thumb->description ?>" /> <h4 class="gallery-albumTitle"><?= $album->title ?></h4> </a> </div><!-- /gallery-album --> </li><!-- /col --> <? } } ?> </ul><!-- /gallery-row --> </div><!-- /gallery --> <? include("./foot.inc") ?> 2. Add the gallery-index template in the ProcessWire admin under Setup->Templates. This template does not require any fields, although you may want to add a body field for outputting additional content to the page. 3. Create a file named gallery-album.php in your site/templates/ folder. This template will be used to both hold and display the images in your albums. Here we will be loading the fancybox plugin as well, so make sure you've downloaded it here: http://fancyapps.com/fancybox/ and uploaded the /fancybox/ folder to your site/templates/scripts/ folder. We are appending the fancybox files to the $config->scripts and $config->styles array before outputting them in our head.inc file so that we're only loading that code on the album pages. So make sure you are outputting those arrays in the <head></head> section of your head.inc file along with your other scripts & styles, like so: <? foreach($config->scripts as $file) { ?><script type="text/javascript" src="<?= $file ?>"></script> <? } ?> <? foreach($config->styles as $file) { ?><link rel="stylesheet" type="text/css" href="<?= $file ?>" /> <? } ?> Please note that you will also have to include jQuery in your head.inc file before your other scripts, if you're not already including it. So here is our gallery-album.php. Notice also that we are calling the FancyBox script and customizing some of its options at the bottom of the file: <? $config->styles->append($config->urls->templates . "scripts/fancybox/jquery.fancybox.css"); $config->styles->append($config->urls->templates . "scripts/fancybox/helpers/jquery.fancybox-thumbs.css?v=1.0.7"); $config->scripts->append($config->urls->templates . "scripts/fancybox/jquery.fancybox.pack.js"); $config->scripts->append($config->urls->templates . "scripts/fancybox/helpers/jquery.fancybox-thumbs.js?v=1.0.7"); // Configure thumbnail width/height & number of photos to display per page $thumbWidth = 150; $thumbHeight = 150; $imagesPerPage = 32; // Make ProcessWire pagination work on the images field (see for full explanation of this) $start = ($input->pageNum - 1) * $imagesPerPage; $total = count($page->images); $images = $page->images->slice($start, $imagesPerPage); // Create a new pageArray to give MarkupPagerNav what it needs $a = new PageArray(); // Add in some generic placeholder pages foreach($images as $unused) $a->add(new Page()); // Tell the PageArray some details it needs for pagination $a->setTotal($total); $a->setLimit($imagesPerPage); $a->setStart($start); include("./head.inc") ?> <?= $a->renderPager() ?> <div class="upOneLevel"><a href="<?= $page->parent->url ?>">← Albums</a></div> <h2><?= $page->title ?></h2> <div class="album"> <ul class="album-row row"> <? if(count($images) > 0) { foreach($images as $image) { $thumb = $image->size($thumbWidth, $thumbHeight); ?> <li class="album-photo darkenOnHover col span3"> <a href="<?= $image->url ?>" rel="fancybox-gallery" class="fancybox" title="<?= $image->description ?>"> <img src="<?= $thumb->url ?>" alt="<?= $thumb->description ?>" /> <!-- Uncomment this line if you want descriptions under images <p class="album-photoDescription"><?= $image->description ?></p>--> </a> </li> <? } } ?> </ul><!-- /album-row --> </div><!-- /album --> <div class="group"><?= $a->renderPager() ?></div> <script type="text/javascript"> $(document).ready(function() { $(".fancybox").fancybox({ prevEffect : 'elastic', nextEffect : 'elastic', loop : false, mouseWheel: true, helpers : { title : { type: 'outside' }, thumbs : { width : 100, height : 60 } } }); }); </script> <? include("./foot.inc") ?> 4. As we did before, add the gallery-album template in the ProcessWire admin. Assign the images field to it, and go into the URLs tab and make sure Page Numbers are allowed. 5. Create a page in the ProcessWire admin for the gallery index using the gallery-index template. You'll probably want to give it a title like "Gallery". 6. Underneath your Gallery page, create child pages that use the gallery-album template, one page for each album you want to create. Name them however you'd like. 7. Go into each album page you created and populate the Images field with your images. Just drag-and-drop. It's as simple as that! If you want to add a description for each image, you can also add it here. If you have more than 32 images (or whatever value you set the $imagesPerPage variable to), the pagination will kick in and split the album into multiple pages. 8. Finally, add in the CSS. The CSS is really up to you, but I'm including a good starting point below. This includes a handy responsive grid system I built for my sites, as well as a .photoShadow class I developed which gives your album covers a cool 3D Polaroid look using pure CSS. /********* Helper Classes **********/ .row:after, .group:after { content: ""; display: block; height: 0; clear: both; visibility: hidden; } .row { ; /* Remove left gutter */ margin-top: 0; margin-right: 0; margin-bottom: 0; padding: 0; zoom: 1; /* IE7 */ position: relative; } .col { display: block; float:left; margin-left: 2%; /* Gutter size */ margin-top: 0; margin-right: 0; margin-bottom: 0; padding: 0; zoom: 1; width: 95.99999999996%; } .span1 {width: 6.33333333333%;} .span2 {width: 14.66666666666%;} .span3 {width: 22.99999999999%;} .span4 {width: 31.33333333332%;} .span5 {width: 39.66666666665%;} .span6 {width: 47.99999999998%;} .span7 {width: 56.33333333331%;} .span8 {width: 64.66666666664%;} .span9 {width: 72.99999999997%;} .span10 {width: 81.3333333333%;} .span11 {width: 89.66666666663%;} .span12 {width: 97.99999999996%;} .photoShadow { position: relative; border: 5px solid #fff; background: #fff; -moz-box-shadow: 0px 0px 2px #ccc; -o-box-shadow: 0px 0px 2px #ccc; -webkit-box-shadow: 0px 0px 2px #ccc; -ms-box-shadow: 0px 0px 2px #ccc; box-shadow: 0px 0px 2px #ccc; } .photoShadow:before { z-index: -1; content: ""; display: block; position: absolute; width: 104%; height: 16px; bottom: -5%; left: -2%; overflow: hidden; border-radius: 50% 50% 0 0; box-shadow: inset 0px 8px 5px #999; } .darkenOnHover { opacity: .8; -webkit-transition: opacity .2s; -moz-transition: opacity .2s; -ms-transition: opacity .2s; -o-transition: opacity .2s; transition: opacity .2s; } .darkenOnHover:hover { opacity: 1; -webkit-transition: opacity .1s; -moz-transition: opacity .1s; -ms-transition: opacity .1s; -o-transition: opacity .1s; transition: opacity .1s; } /********** Blocks **********/ .gallery { } .gallery-album a:hover { text-decoration: none; } .gallery-albumTitle { font-size: 1.1em; text-align: center; margin: .2em ; } .gallery-album { -webkit-transition: all .2s; -moz-transition: all .2s; -ms-transition: all .2s; -o-transition: all .2s; transition: all .2s; } .gallery-album:hover { -webkit-transition: all .2s; -moz-transition: all .2s; -ms-transition: all .2s; -o-transition: all .2s; transition: all .2s; -webkit-box-shadow: 0 0 3px #555; -moz-box-shadow: 0 0 3px #555; -ms-box-shadow: 0 0 3px #555; -o-box-shadow: 0 0 3px #555; box-shadow: 0 0 3px #555; } .album-photo img { margin-bottom: 6px; border: 1px solid #ddd; } .upOneLevel { font-size: 1.1em; margin-bottom: .4em; } .upOneLevel .icon-circle-arrow-left { font-size: 1.5em; margin-right: .4em; } .upOneLevel a:hover { text-decoration: none; } .MarkupPagerNav { margin: 1em 0; font-family: Arial, sans-serif; float: right; } .MarkupPagerNav li { float: left; list-style: none; margin: 0; } .MarkupPagerNav li a, .MarkupPagerNav li.MarkupPagerNavSeparator { display: block; float: left; padding: 2px 9px; color: #fff; background: #2f4248; margin-left: 3px; font-size: 10px; font-weight: bold; text-transform: uppercase; } .MarkupPagerNav li.MarkupPagerNavOn a, .MarkupPagerNav li a:hover { color: #fff; background: #db1174; text-decoration: none; } .MarkupPagerNav li.MarkupPagerNavSeparator { display: inline; color: #777; background: #d2e4ea; padding-left: 3px; padding-right: 3px; } I think that's it! Just make sure you're including the CSS file in your head.inc inside the <head></head> tags and you should be all set. If you come across any issues trying to implement the above (or find any of it confusing) please let me know below. Everyone is coming from different backgrounds and different experience levels. And if you find this tutorial useful, please feel free to let me know as well * I should mention that although it is possible to create galleries in Processwire where each image is represented by its own page (and, as Ryan has mentioned, is often preferable since it is ultimately more scalable), sometimes the ease of using a single image field (which can upload and decompress zip files of images in mass) simply outweighs any drawbacks. If I had to create this gallery with the 1-image-per-page method, it would have taken hours to upload all of the images one-by-one without some sort of additional programming to automate the process.6 points
-
Hi all, I want to present a preview of my new Portfolio. Actually I'm unsure with some points and the images aren't the final ones and other pieces aren't finished too. But the look is ready and maybe it would be good to get some feedback from the critics here ;-) The site actually runs on PW 2.3 stable, the used modules are: ImagesManager ImageMinSize Thumbnails FieldtypeTextUnique Minify I have disabled direct access via .htaccess to portfolio-images that resides in the files folder. Thumbnails and images related to infos and news can be accessed directly, all others have to use a proxy page I have build as PW-template. With the ImagesManager I initially have created my six categories (albums) and manage all uploads. Via a hook into ImagesManager on upload I'm able to rename the original images and create 3 variations (600px, 900px, 1200px). Also I stripp all Exif and IPTC data from them but populate them with the minimal needed IPTC data. That way I never have custom related infos in the images, neither in filename nor in metadata. I use serverside mobiledetection and also JS to detect viewport dimensions. This should be used to serve images that fit best to devices and viewport dimensions. But it isn't ready now. The layout / design is done from HTML5 boilerplate. There are no frameworks or thatlike used / needed. But there is heavy use of Javascript (jQuery-Libs: Swipe, Stapel, Flexslider), but the site also runs completly in noscript mode. Also the single-image-view in NoScriptMode lets you loop through the gallery and displays the content scrolled down to the image if needed. (That's one of the advantages of old veterans that have build html-pages during browser war 1995/98 ) All critic, suggestions etc is welcome: http://pw4.nogajski.de/5 points
-
Ohh I just got an idea for a module. What if you have a gallery type page you upload the images as usual to an images field. Then when saving the page there would be children created for each image and the ones removed from the gallery page. This would be very simple few lines of code. Sorry to hijack your thread. Nothing against the method to have one images field you store a gallery. If theres no metadata needed with no multilang and so on it is a pretty good and simple way to a simple gallery. I use it myself too.3 points
-
If the action of the form is without trailing slash and PW redirects to the url with a trailing slash, you'll get no GET. This is a feature3 points
-
Simplest solution: Use GET To make it automagically work with the pager, you need to add the variable to Pw's whitelist. Pw does append your get variables to the paging. if ($input->get->mysearchlocation) { $county = $sanitizer->selectorValue($input->get->mysearchlocation); $input->whitelist('country', $country); // Do your search and render the pager }2 points
-
From your code, you don't seem to be using that $post variable anywhere other than in the if(), but I'm assuming that you use it to set $country. (Correct me if I'm wrong.) Suggestions- Use $input->post["mysearchlocation"] rather than accessing $post directly (not essential) Run the result through $sanitizer (essential) Save the result in $session and access it from there on subsequent page loads.2 points
-
In case you missed it, Sublime Text 3 is now open to non-registred users http://www.sublimetext.com/32 points
-
Actually $modules->get("MarkupBox") will install the module if it's not2 points
-
Check settings for the field "genres": in the details what's the options selected for "Dereference in API as"? To support multiple selections this should be "Multiple pages" but it sounds like you've got either of those "Single page" options selected at the moment. This is how it should *not* look like: (Edit: added "*not*" above the screen shot )2 points
-
You're very close actually . This is how it works: if($modules->isInstalled("MarkupBox")) { // do something }2 points
-
Hi, Thanks for this tutorial! Thanks for taking the time to write it. I haven't finished reading it yet, but it looks very comprehensive, thanks . The question about image galleries has been coming up more often recently... Edit: Quick comment as I read...the term "single image field" might confuse some since you are not referring to an image field that only accepts one image (yet you state you uploaded multiple images), but you are stating you used one image field (that accepts multiple images), no? Maybe good to clarify that Finished reading: you give very clear, straightforward instructions. Many thanks!2 points
-
It's working now, I had to set the rewrite base (uncomment) Rewritebase / But as I said already in the PM, the permission on those accounts for apache and ftp user seem to create problem with not allowing to delete files over ftp created by php. Common problem with shared hostings. I deleted the files on server then with a php script, and installed a fresh install 2.3 stable. It seems all working with image upload. There's seems to be some limitations with that hosting in terms of memory and so on and the sftp is slow as hell. A little more infos seem to be found here: https://sourceforge.net/apps/trac/sourceforge/wiki/Project%20web%20and%20developer%20web%20platform2 points
-
You've been using MODX but now you've found ProcessWire. It’s totally amazed you and you can’t wait to get started. But…you are wondering where everything is. If this is you, read on… This guide is primarily aimed at those who are coming in from MODX and wish to know how to accomplish “MODX things” the “ProcessWire (PW) way”. This is not meant to be a full blown PW tutorial. It will focus on some key MODX concepts/tasks and how to accomplish those in PW. It will cover, whenever possible, both versions of MODX - Evolution and Revolution. The guide assumes that you’ve at least logged into a PW site and/or viewed a demo. The Table of Contents mostly reflects MODX terminology. Table of Contents 1. Manager 2. File System 3. Resources 4. Templates 5. Template Variables (TVs) 6. Template Files 7. Snippets 8. Modules 9. Plugins 10. Chunks 11. Miscellaneous 12. Examples - the PW way… a. Template Variables b. Snippets c. Modules d. Plugins e. Chunks 1. Manager In PW, the “manager” is referred to as the “Admin”. The default location of the Admin is www.yoursite.com/processwire. As of PW 2.3, you can rename the Admin to anything you wish during install. Just be careful to remember the name you use or you will be locked out! (If that happens, there are ways to get around it though). Logging into Admin, you will notice a tree just like in MODX. The Admin runs on jQuery UI and as you’ve seen, it is insanely fast! Don’t be fooled by its simple facade. PW is a really powerful CMS, highly extensible and very easy to use. Customising the PW admin is very easy. There are a number of custom themes available. It is also trivial to make yours. Custom Admin themes go into the folder site/templates-admin/. You can have only one theme at a time. On a related matter, if you wish to create a custom Admin page, it is easy to do so. See this thread for more info. 2. File System After installing PW, you will see two main folders; “site” and “wire” in your file system. Site is where all things related to your site reside. This is your playground and will survive an upgrade. Wire houses the Core. You will never have to go into that folder. 3. Resources In MODX, Resources can be many things (documents, etc.). There is no such term in PW. However, the most important “resources” you need to know about in PW are page and pages. Pages are a very powerful concept in PW. Page can refer to your website’s frontend pages, i.e. what can be viewable by your website users. I say can be for a reason. There are many uses for Pages in PW. This can be confusing to newbies but once you get the concept, you will appreciate the power of the system. Just because something is a Page does not mean it has to be viewable. It can have other uses such as a container that holds data for use by other Pages - in this case the Pages do not have to be displayed on the frontend. In fact, everything you see on the PW tree is a Page. That’s right; even the Admin and its components (Users, Roles, etc.) are all Pages! Still confused by Pages? Have a read here. Pages reside in the PW tree - you may have noticed . You can drag and drop pages to move them around. If drag and drop doesn’t work you probably have MySQL 5.0.5.1 installed. Upgrade your MySQL and you are sorted. The root of your site is the uppermost Page in the tree. In the default PW install this is called Home. You can change the name to something else. The default PW install comes with a number of Pages pre-installed. Try editing a Page. All those Fields you see on that Page when under the “CONTENT” tab? They are not default Fields. They are all Custom Fields! Yes, not even the Title! The only required Field for a Page is “name”. You find this under the “SETTINGS” tab on the page edit screen. More about Fields below… Other related stuff: Menuindex: As an aside, if outputting something like a menu, unless you state otherwise, it will reflect the tree hierarchy. Show in Menu: This functionality is covered by the Page status, whether hidden or not. Hidden pages do not get output on menus (more about menus later) unless explicitly stated so using PW API selectors (see below). Menu Title: No such term in PW. You can name your menu items what you wish to name them. Very important: All Pages must be assigned a Template. 4. Templates In PW, Templates mean something slightly different compared to MODX and many other CMS. MODX describes templates as: That is not entirely true of PW Templates. In PW, the term Template is used in the sense of the English definition of the term: PW Templates serve as a pattern for the foundation of your Pages. By foundation, I do not mean the HTML or CSS. Rather, the Template servers as blueprint for your Pages. What is available to the Template is available to the Page that uses it. Templates establish a pattern for the Pages by the inclusion of Fields to the Template. A Template can have as many or as few Fields as you wish. You can create as many or as few Templates as you wish. You can easily change the Template a Page uses when editing the Page. See under SETTINGS. Note that if you have Fields on that Page that are not in the Template you are switching to, those Page Fields will be lost! PW will warn you about this when switching Templates though. OK, so how do you show “Resources to the world”? That will be the work of Template Files which we’ll look at in section 6. 5. Template Variables A powerful feature of MODX is Template Variables (TVs). If you loved MODX TVs you will absolutely adore the PW equivalent. In PW, TVs are known as Fields. You can define your own Custom Fields. In fact, you will need to create your own in most cases. This is because PW does not have any required Field except for “name”. It is perfectly reasonable to have a Page with only the name Field! Many people do add at least a Title Field for such Pages. In the default PW install, the reason you see the Title Field in all Templates is because it has been set as a “Global” Field under the ADVANCED settings of the Field (edit the Field to see this setting). There are many types of Fields to hold all sorts of data - images, texts, urls, passwords, reference to Pages, etc. You can call your Fields anything you wish. You can call the Field for your main content “body”, or “stuff”, or “content” or whatever you wish as long as you follow the naming convention, i.e. “[a-z], numbers [0-9], or underscores (no dashes or spaces)”. Fields are reusable across different Templates. The order in which they appear on your Page follows the order in which they are arranged on your Template. However, it is important to note that: The order in which Fields appear on your page and/or the inclusion of a Field on your Page does not mean that: The Field will be output on the Frontend. The inclusion of a Field on a Page does not automatically mean it will be output; PW does not make that decision for you. It only makes the Field available to you to use as you require. You can output all or none or few of the Fields on your Page. The order in which Fields appear on a Page does not mean the same order will be reflected when you output the Page. You make that decision. Also note that you are able to arrange Fields side-by-side on your Page (via settings on the Page’s Template) to mimic your site’s layout or for other visual/ease-of-use purposes as you edit the Page in the Admin. You can also give each Field a label and a description. These will appear above each Field when editing a Page. In most cases, the content of Fields will be saved directly to the database. In the case of file related Fields, the path to the file will be stored in the database. There are no direct equivalents of MODX TVs “@Bindings” (data sources). These are inherently built into the different types of Fields. Note that you cannot run PHP code within Fields (so no @Eval). This is by design. Fields are a very powerful and much loved concept in PW. Just Google "custom fields cms" and you’ll see what comes up tops. 6. Template Files So far, we've seen that you create Fields, add them to a Template you've created and edit a Page using that Template to input your content into that Page’s Fields. So far so good but how do you output the content to the world? You do this via Template Files. Template Files live in /site/templates/. You have to create your own Template Files. In MODX, a Template will have both system fields, e.g. body, title, etc. and custom fields (TVs). Rendering a Template is achieved by adding MODX tags to your Template. In PW, in order for the content of your Page to be seen by the world, its Template must have a Template File (or there must be some other Template File associated with a different Template that is dynamically pulling and outputting elsewhere the content of a Page whose Template does not have a Template File). This does not mean that all content within a Page will be automatically output by the Template File. No; in the Template File you can choose to render all or some Fields present in the Pages using that Template or none at all! You tell the Template about the associated Template File when you create/edit the Template. PW assumes that there is a Template File with the same name as the Template in /site/templates/ and will tell you if it does not find one. However, you have two other choices. You can either enter an alternative name for your Template File or tell PW you do not wish to have a Template File for that Template. This means that a Template does not require a Template File. Obviously, in such a case, you will not be able to directly output the content of the Pages using that Template. In some cases, that is exactly what you want . As you get to know more about the system, you will find out how powerful and flexible the PW Template system can be. For instance, you can use your Template as a controller. That’s beyond this guide but feel free to search the forums for more info. Template Files are typically PHP files with logic to dynamically output your content. In most cases, Template Files are HTML with PHP tags inserted to output your content. The PHP in the Template File will in most cases be PW API. Hence, you will see things like $page and $pages in Template Files. The former always refers to the current Page and the latter to any other Pages in the system. These are very powerful variables in PW and give you access to ALL information about ALL pages including their Fields and whether those are empty or not, etc. See below for more info about these variables and have a look the docs too. Note that Templates do not care about what’s in your Template Files. In fact, they won’t even check. All they want is for you to tell them if and how you wish your Pages' contents to be rendered. Your Template Files can even contain pure HTML (although that won’t be dynamic!)! Your Template Files can have references to other things related (or not related!) to the Page using that Template File. For instance, within your Template File, you can pull in the 10 latest “posts” from your Blog or the Children Pages of that Page. There are just too many possibilities to list them all here. Don’t let the PHP in Template Files scare you if you are no coder. I am no coder but I am able to use PW. You will only need to know at least some very basic PHP to use PW. The most important are: echo; foreach; and if… Anything else is a bonus in most cases. In addition, you will need to know how to use the two most important PW variables - $page and $pages. With these two, most of what you would have done in vanilla PHP is covered. They are easy to use and to understand and very much follow the jQuery concept. Check out the docs to learn more. 7. Snippets In MODX, Snippets are the method by which MODX allows you to run dynamic PHP code in any of your pages. In PW, the term Snippets does not exist. What!?! Not to worry; in PW MODX-like Snippet functionality can be achieved in two ways: Template Files: Most PW Template Files are essentially dynamic PHP code. That’s Snippets for you right there. PW Modules: PW Modules do what MODX Snippets do and more (see below). It’s just an issue of terminology. For instance, the popular MODX Snippet WayFinder has a Module counterpart in PW. This is the Module Markup Simple Navigation. However, you do not need to use the Module to create a menu in PW. You can do the same thing using PHP in your Template File. See the default PW install for a simple example. Check out section 12 of this guide for example “popular-MODX-Snippets-to-PW-how-tos”. 8. Modules MODX Evolution defines Modules as “a program that can only be executed from within the manager.” There are PW Modules that fit this definition, for instance, the Module Batcher which is equivalent to the MODX Revolution add-on Batcher. However, there are other PW Modules that are executed in the frontend, e.g. Markup Simple Navigation previously mentioned. In fact, in PW, a Module is PHP that extends the functionality of PW. Modules contain PHP classes that adhere to PW’s Module interface. 9. Plugins In MODX Plugins are PHP code that are set to execute during certain system events. In PW, although the term Plugin does not exist (except maybe in reference to Modules), MODX Plugin functionality is easily doable in PW. This is achieved via Hooks. There is one difference though. In MODX, Plugins are standalone code you can download and install. You cannot download and install PW Hooks. Instead, PW contains many methods that you may hook into in order to modify the behaviour of the method. In other words, PW offers the ability to hook into its processes/events and manipulate them before or after the event or even replace them, etc. Hooks are usually invoked inside Modules. However, Hooks may be attached from anywhere that you use PW's API, for instance in Template Files. The average PW user will not need to use Hooks. For more info about Hooks check the documentation. 10. Chunks MODX defines Chunks as “bits of static text which you can reuse across your site”. There is no equivalent term in PW. You can, however, easily create Chunks in PW. You can create Chunks as a Page that contains various Fields each of which can act as a Chunk. This means you can have Chunks of all sorts of data. You can then set the Page you create to hold your Chunks as hidden (not available to searches). The Page can also be assigned a Template without a Template File to further limit frontend access. It can also be created as a child/grandchild of the page Admin. That will limit access by User (e.g. login required to view it in Admin). Accessing the Fields of that Page as your Chunks using PW API is quite trivial really. Since you can use labels and descriptions to further define each of your Pages’ Fields, this makes it quite easy to describe what each Chunk is for and/or give instructions on how to use the Chunks. See this example for more info. You can also simply use text files to pull into your content as Chunks. Personally I prefer using Pages as Chunks when I need to. In MODX, it is usual for many Snippets to use Chunks (HTML + placeholders) to structure their output (i.e. tpl Chunks). You do not need to do this in PW. Code output can be wrapped in HTML right within the Template File. The important thing to remember is that any Field in any PW Page is available to any other Page and any Template File. Cross-referencing Fields and Pages is child’s play. Seriously; it is that easy. 11. Miscellaneous Tag Syntax: PW does not use a templating language (tagging syntax) like MODX does. See this article why this decision was taken. I agree 100% with the approach and have come to realise its many benefits over using a templating language. However, there are two Modules that allow you to use template language tags in PW. I have never used them so cannot comment further. They are here and here. Settings Page: PW has no settings page like MODX. Many settings are set in the /site/config.php. Other MODX settings equivalents are interspersed in various places including caching content on a Template by Template basis and in Modules. You can also store custom settings needed for your site in the /site/config.php. You can even use Pages to store your settings as mentioned in section 10 (Chunks). Modularity: PW is a very modular system. The whole of PW is made up of Modules (Core Modules) that accomplish different tasks. 12. Examples - the PW way… In this section I will show you equivalent MODX versus PW add-ons as well as how to accomplish various task using PW “Snippets” equivalent. a. Template Variables As previously mentioned, MODX TVs are PW Fields (although PW Fields are more versatile). Outputting the contents of your Fields is very simple. echo $page->name_of_your_field; This gives you the contents of the Field in the current page. Works slightly different for image fields though. For other pages echo: One page $pages->get(ID or PATH or NAME, etc.)->name_of_your_field; //note replace ID with ID of the Page you want, etc. Many pages $pages->find("selectors"); //this will return an array. You can then go through the array using foreach as shown in the examples below to output the field(s) contents MODX - output main content of Page //MODX Evolution[*content*] //MODX Revolution[[*content]] ProcessWire - output main content of Page //ProcessWire echo $page->content;//note; this assumes you have a Field called content in the Template of the current page. In ProcessWire you can find Fields of other pages like so $fruits = $pages->find("template=yumyum, limit=10"); foreach($fruits as $fruit) { echo "<li><a href='{$fruit->url}'>{$fruit->title}</a></li>"; } //find 10 Pages that use the Template yumyum and echo their url and titles in a list. From these examples, you can see the elegance and flexibility of TVs done the PW way. Since there is separation between a Template and a Template File, you can conditionally echo out the contents of Fields found in Pages. b. Snippets Common MODX Snippets and PW equivalent Modules 1. WayFinder: Markup Simple Navigation or code in Template File (see head.inc in default PW installation for a simple menu). 2. Ditto (Evolution) and getResources (Revolution): Functionality inbuilt in PW. Use $page and $pages variables + selectors to find anything, anywhere. 3. Jot (Evolution) and Quip (Revolution): Comments Module is part of the PW Core. It is not enabled by default. You will have to enable it in the Admin. See also the related Comments Manager Module. 4. eForm (Evolution) and FormIt and FormItBuilder (Revolution): There are various Form parser codes in the Forums. There is also a commercial Form Builder Module. It’s not expensive, is developed by PW’s lead developer and proceeds support the PW project. 5. MaxiGallery (Evolution) and Gallery (Revolution): Presently, there is no equivalent. However, it is quite easy to build a photo album. See this tutorial in the wiki. There is also an Images Manager Module (still in alpha though). 6. AjaxSearch: Ajax Page Search Module. 7. Breadcrumbs: Quite easy to accomplish using PW API. See default PW install for an example. 8. FirstChildRedirect: Very easy to do using PW API like this: $session->redirect($page->children->first()->url); in a Template File. 9. getField (Evolution) and getResourceField (Revolution): Inbuilt in PW $page and $pages variables as shown above. 10. GetParent: Inbuilt in PW $page and $pages variables. E.g. $page->parent. 11. getPage: PW has inbuilt pagination as part of the Core (Pagination Markup Module). See this article for a quick tutorial. 12. UltimateParent: Inbuilt in PW API as rootParent. 13. if (Revolution): Use vanilla PHP with PW variable and selectors in Template Files. 14. VersionX (Revolution): Versioning for text-based fields is coming in PW 2.4 (release date summer 2013). Support for maintaining separate draft and live versions coming in PW 2.5 (Winter 2013/2014). Currently, there is also the Module Version Control for Text Fields. 15. getRelated (Revolution): No out-of-the-box Module for this. Has been previously accomplished using PW API in various ways. Have a look in the forums. 16. importX (Revolution): Import Pages CSV Module. 17. phpThumbOf: Thumbnail functionality is inbuilt in PW. There is also the Module Thumbnails that further extends this functionality. 18. getValue and getValues (Revolution): Inbuilt in PW. You can get the value of any Page using PW API - $page and $pages. 19. getFeed (Revolution): RSS Feed Loader Module. 20. MIGX (Revolution): Repeater Module which is part of the PW Core. It is not installed by default. You will need to do that yourself. For more info see this tutorial. 21. Articles (Revolution): See the Blog Profile Module. 22. NewsPublisher (Revolution): See below under Plugins. Examples MODX Ditto [!Ditto? &parents=`5`&extenders=`summary` &tpl=`tplBlog` &orderBy=`createdon ASC`&display=`6` &truncText=`Continue Reading This Article` !] PW equivalent $items = $pages->get(5)->children("sort=date,limit=6"); foreach ($items as $item) { echo $item->title; echo $item->summary;//etc. } //this assumes you have a Field called summary on that Page The first line in the above gives you all information about the 6 child Pages of the Page with ID #5. It returns an array. In other words, a basket of various documents containing all the info about those documents. Next, you traverse the array using foreach. In layman terms, you rummage through the basket picking goodies! In order to wrap HTML around the code output, we do it like this instead (there’s other ways to do it as well!) echo "<ul class='articles'>"; foreach($pages->get(5)->children("sort=date,limit=6") as $item) { echo "<li><p><a href='{$item->url}'>{$item->title}</a><br /> <span class='summary'>{$item->summary}</span></p></li>"; } echo "</ul>"; In this example, we have asked PW to grab the child Pages directly within the foreach rather than creating a variable $items first. MODX getResources // Output a list of child Resources of the current Resource, using the 'myRowTpl' chunk: [[!getResources? &parents=`[[*id]]` &tpl=`myRowTpl`]] PW equivalent echo "<ul>"; foreach ($page->children as $child) { echo "<li><a href='{$child->url}'>{$child->title}</a></li>"; } echo "</ul>"; //You might want to limit the number of child Pages you are getting if they are many! MODX getResources // Output the top 5 latest published Resources beneath the Resource with ID '5', with tpl 'blogPost': [[!getResources? &parents=`5` &limit=`5` &tpl=`blogPost` &includeContent=`1`]] PW equivalent echo "<h3>Latest Posts</h3>"; $posts = $pages->get(5)->children("limit=5"); foreach ($posts as $post) { echo $post->body; } c. Modules 1. Batcher and Docmanager (Revolution): Batcher Module (covers most equivalent functions). 2. DocFinder (Evolution): Inbuilt in PW default install. d. Plugins 1. QuickManager (Evolution): Several Modules can do this, i.e., Fredi, Page Frontend Edit and Inline Editor Modules. 2. ManagerManager (Evolution): Same functionality can be achieved using Templates, Access Control and the Modules Page Edit Field Permission, Page Edit Per User and Page Edit Per Role. e. Chunks See this example. Btw, the PW Cheat Sheet is you best friend... Hope this has been helpful! /kongondo1 point
-
Nice site thanks for sharing. Really cool photos. But what is very annoying on mobile is you can't zoom them. Or didi I miss something? What did you use now for the image scaling? Does the min size plugin work with ImageManager?1 point
-
Very beautiful! I love it! Two minor issues: 1. On info pages, on the right side (featured content), when viewing one of those pages, e.g. http://pw4.nogajski.de/de/news/greenscreen/, I see no english flag on the left to choose my language... 2. Is it possible, to dynamically change the HTML language declaration to match the selected language? So, if viewing the page in English, dynamically change this: <html lang="de" class="no-js"> to this: <html lang="en" class="no-js"> Only reason I ask is to stop my Google Translate Extension from automatically trying to translate (or asking me if it should translate) the page from German to English even though I have already selected English on your website. It's just a minor niggle from Google, but just wondering...1 point
-
Cool gallery website! Some critique: The main menu is a catastrophe in my opinion. The rounded corners on the left and right bottom side plus the margin between the links doesn't look good. The gallery loader.gif has a black background, which doesn't work with the blue background of the site. I would switch the keyboard arrow navigation. Right for next img, left for prev. More intuitive that way.1 point
-
1 point
-
No, my reply was in regard to your first paragraph about being able to identify and delete/edit images easily when using one page per image. Having a grid instaed of just a single column in the admin could be very helpful, I agree.1 point
-
1 point
-
+1 for DaveP's suggestion. See this also about input variable: http://processwire.com/api/variables/input/ How does the blog profile do it, btw? I'm looking at the code but can't see how it renders pagination on search results...Sessions?1 point
-
Is there a way in PW's Form Builder to convert hours from am/pm to proper 24h system? Now I get funny output, like this for example: 13:30 pm. BTW: while messing around with module I made a Form Builder themes preview (v. 0.2.2) to avoid switching and saving settings. Maybe someone who wants to use the preset form styles will find it usefull. Here is the link to screen shots: http://bit.ly/123dcpZ1 point
-
https://www.contentful.com/ This is still in beta and I just asked for an invitation, so I don't know how it is. But the concept sounds good. Edit: just want to add that something like this would be really easy to do with a PW site1 point
-
Are you talking about a multiple pages reference field? Could you confirm that under the INPUT tab, in the input field type* that you have selected a multiple page selection type? Version of PW you are using? Forget above...it seems you have in the DETAILS tab selected a single page? Edit Nik was faster1 point
-
Thanks for writing a new tuto. If you want to have image pages without creating every page manually one by one, you can also use ImagesManager which has upload tool to directly create the pages. So the argument doesnt count ;-)1 point
-
I use Feng Office, and have been using it for a few years; seems to be a really decent choice, but the community support and documentation are negligible; Upgrading is a hassle; Latest version is really nice, faster than previous version, and more customization options BTW i have tried most of them...1 point
-
Yo dude, where do you find all that time to set all that up (plus the tutos) ? Amazing. We'll actually I am jealous I don't have that time my self that I would love to spend on pw. Ryan, I think it is time to make kongondo a tutorial pw ambassador !1 point
-
Pagination is now fixed on the dev branch. Also you can now translate the the prefix segment (i.e. "page[n]") used for pagination in URLs. By default it is "page" for "page2", "page3", etc. But if you want to translate that on a per-language basis, you now can in the LanguageSupportPageNames module configuration screen. For instance, in Spanish you might want to make it "pagina" for "/path/to/page/pagina2", "/path/to/page/pagina3", etc.1 point
-
I agree, I think export/import methods like this on Fields and templates would be nice. There's a lot of considerations though, especially on import. Like whether individual fields already exist or not, whether those field definitions reference external things (like page IDs). That's not to say it isn't doable, but just that there is potential for it to get quite a bit more complex than it first appears. But I would like to implement some API level expor/import functions for this soon, to at least get things moving forward. I've already been working on similar export/import functions for Page objects (which you see in the latest dev branch, though they aren't yet active).1 point
-
Here's one more, 2038 + 1. Helpful and supporting pw (and probably coding) pro's like you deserve it.1 point
-
1 point
-
I'm in the process of building a complicated module and was thinking that being able to create the fields in the admin quickly, then export as a JSON string to use in the installer function would be much quicker than what I'm faced with at the moment - manually typing out the code for all the fields I need to add is taking a long time, so aside from the uses when copying fields/templates to other PW installations it would be fantastic to be able to generate the JSON and in a module's installer just do something like this if we wanted to change some template details or add some additional fields: $templatedata = json_decode($jsonstring); $fieldgroup = new Fieldgroup($templatedata->fields); $template = new Template(); $template->name = "template-name"; $template->fieldgroup = $fieldgroup; $template->save(); Or if we were happy with the template name we'd exported and all the fields, then this: // Adding template "template name" $templatedata = json_decode($jsonstring); $template = new Template($templatedata); // $templatedata contains template and field information $template->save(); The second option means you won't even know what the template is called unless you know how to read a JSON string, but I like its simplicity, and we can just put a comment above it as in my example Just a thought.1 point
-
The strtotime call isn't technically necessary. You could also just do this: foreach($programs->find("program_start_date<04/01/$year") as $program) {1 point
-
Every find will return a PageArray already, no need to explode to get the page id as array you already got them... My guess is that most people try to echo $p, and see that there's something like "1002|1230|2130" ... but that's not what's really behind $p and seems a common misunderstanding of non-coders. It's the magic toString() method of PageArray that returns the id's in that way. See https://github.com/ryancramerdesign/ProcessWire/blob/master/wire/core/PageArray.php#L407. So what you trying to do an extra step to explode something that PW implodes. This stringification is handy if you want to use the result $p in a selector. "id!=$p" will result in "id!=1002|1230|2130". But in your case you already have an PageArray and simply can loop the pages inside $p. $p = $pages->find("images.tags~=$tag") foreach($p as $onepage) { echo $onepage->title; }1 point
-
I feel like a padawan learning from Yoda.. ;P #lamestarwarsreferenceforthewin1 point
-
Hi, I am just getting started with Processwire. I'm a keen newbie - I've gone through the great tutorials by Ryan and Joss but feel like I could do with a few more to get up and running. I know good tutorials take a lot of time and effort to create, so I was thinking if it would be possible to fund a pro to make a video? I'm not talking http://drupalize.me Maybe 2-4 hour long video just to get new users working with the interface and api. Funding could go something like this: http://kck.st/WLZpDG1 point
-
I have to admit that I like learning from videos and books. They help to get across bigger picture concepts much better than copying and pasting. They build a foundation. So when it does come time to writing code (or copying pasting it), you've got the understanding of it. The problem with copying/pasting is that it's like building without a foundation, which can be dangerous. When you've got the foundation, all the other pieces just kind of fall into place. I think this is especially true of ProcessWire. If you understand the big picture and how simple it is, the rest of it becomes simple as well. And there's no reason not to learn the foundation, because it's so darn simple. It seems like a lot of people start working with ProcessWire while thinking of it in the context of some other CMS. So there is inevitable "un-learning" that has to take place, as people are looking for complexity where there isn't. This is a recurring theme. What I think would do an even better job of establishing the foundation would be two printable PDF documents that are maximum 1-printed page each: ProcessWire in a nutshell, a cheat-sheet – Covers everything you need to know to understand a typical site profile. Pages, Fields, Templates, then $page, $pages, and PageArray. All you need to know about PHP to use ProcessWire – This one would focus on the general PHP concepts necessary to use it like a template engine with ProcessWire. Covers things like PHP tags, double-vs-single quotes, echo, if(), foreach(), and comparison vs. assignment.1 point
-
1 point
-
1 point
-
When possible, use IDs (integers) for referring to pages in forms. Then your sanitization is as simple as this: $area_alias = (int) $input->get->area; There's a problem with this code segment: $area_alias = $sanitizer->text($input->get->area); Someone could inject more selectors into the string by specifying it in the URL for area_alias. The text() sanitizer isn't meant to sanitize strings for use in a selector. Instead, you'd want to use the selectorValue sanitizer: $area_alias = $sanitizer->selectorValue($input->get->area); But like mentioned at the beginning, I prefer to use integers (IDs) for anything referencing pages, since it makes the sanitization simple and bulletproof.1 point
-
$area_alias = $sanitizer->text($input->get->area); $area_page = $pages->get("alias=$area_alias"); $matches = $pages->find("title|body|sidebar*=$q, parent=/catalogo/produtos/, arealimit=50, id!=1, area=$area_page"); I think this is what you want, but I'm not sure. Tell me if I misunderstood everything. EDIT: See Ryan's corrections to my code some posts below1 point
-
I started building responsive sites more than a year ago, and like everyone else I quickly realized that the weakness of that new method / philosophy is serving the same image to all devices, from mobile to desktop. Matt Wilcox's Adaptive Images (server-side resizing) works great, but like JeffS above, I'm interested in optimizing content for device groups, i.e. content optimized for mobiles, tablets, desktop and even smart TVs. I've come to the conclusion that to do this efficiently, device detection has to be done on the server. There's even a buzzword for this new technique: RESS, or Responsive Design + Server Side Components as coined by Luke Wroblewski. WURLF is the most famous device detection database, and there are some good tutorials to get you started such as NetMagazine's, but it seems to me way too complicated for simple projects, and WURLF has turned into a commercial project anyway. I've been looking at two recent projects that seem very promising: Detector Categorizr Categorizr is by far the simpler approach, and I like how it turns the traditional and much-decried User-Agent sniffing on its head: it assumes that whatever is not detected as desktop and TV (which are relatively easy and safe to detect) is a mobile device. In other words, it's a mobile-first based device detection. Clever. Here's a test page I created using Categorizr and that you can check on your mobile, tablet, or computer that will show different content according to the device used (disclaimer: not fully tested): http://www.arqyestud.../categorizr.php Combining this server-side detection technique with the versatility and power of PW could make for very powerful and easily-maintainable 'hybrid' responsive sites. What do you guys think?1 point
-
The new user system will provide better support for developing your own user registration functions. But it's probably still a month or so before I'll have that ready. In the new user system, users are actually pages, so you can interact with them, add fields to them, and so on, in the same way.1 point