Leaderboard
Popular Content
Showing content with the highest reputation on 08/20/2015 in all areas
-
Hi Guys, A new launch from us. Ensoul.co.uk - Interior Design, Architecture & Project Management, London. Background Based in London, Ensoul are Interior Architects specialising in high-end / luxury interiors, basement conversions, extensions, and residential renovations etc. We based the site on ProcessWire because it's agile, scalable and a pleasure to work with. Given that the Ensoul team will shortly be updating the site and blog in-house we needed a CMS that would also be intuitive for them to use. Overall the nature of the site is very visual and relies heavily on photography. It was essential the CMS had solid image management built in and this was another factor in choosing to run it on ProcessWire. More on that shortly. The plan This is Phase 1 (design and launch) of a multi phase project. Phase 2 consists of optimisation, refinement and a comprehensive SEO project. In particular we'll be redesigning the homepage, building a blog and looking to speed up page loads. With ProCache due to be installed very shortly, we plan to dramatically increase the site speed, minify a lot of the JS and gain points on Googles mobile speed test tool. Image Management I just wanted to highlight some of the nice image management features which ProcessWire brought to the table. 1. Background images Most of the pages have a large background image and we wanted the freedom to swap and change these on a page by page basis and test a lot of different photos. Given 80% of the page and background image is covered by content, not every image was going to work. We solved this simply by creating an image filed called Background Image into which we (or client) can drag and drop a photo of their choice. Any background photos are integrated into the jQuery Backstretch plugin In the case of the homepage where three background images are used, PW and Backstretch will create a slideshow instead. <?php // if Background_Image field contains more than 1 photo, echo the images in a slideshow // Mainly for Homepage if($page->Background_Image->count > 1 ) { $bgimage = $page->Background_Image; echo '<script>$.backstretch(["'; echo $bgimage->implode('", "', "url"); // results in url", "url", "url echo '"], {duration: 5000, fade: 1000});</script>'; } else // otherwise echo a single image on its own // Mainly for all other pages if($page->Background_Image->count == 1 ) { $bgimage = $page->Background_Image; foreach ($bgimage as $image) { echo" <script> $.backstretch('$image->url'); </script> "; } } ?> 2. Portfolio The Portfolio page is image heavy and features a masonry grid of photos which are then filtered by project type. On the front end, I was able to restrict each thumbnail and pop-up image to the size of my choice without having to crop each individual photo. To achieve this, I used a $thumb and $large variable and PW automagically handled the cropping. foreach($page->Images as $image) { $large = $image->width(800); $thumb = $image->size(340); echo ".... Creating the filters which toggle the display of rooms by type was surprisingly easy with ProcessWire. I used the image tag field which I hadn't really used before and quickly allowed me to tag a photo as a kitchen, bedroom or basement etc. It really was an eye opener into the power of PW: <div class="portfolioFilter"> <strong>View:</strong> <a href="#" data-filter="*" class="current">All</a> <a href="#" data-filter=".Kitchen">Kitchen</a> <a href="#" data-filter=".Bedroom">Bedroom</a> <a href="#" data-filter=".Bathroom">Bathroom</a> <a href="#" data-filter=".Sitting-Room">Sitting Room</a> <a href="#" data-filter=".Gym">Gym</a> <a href="#" data-filter=".Basement">Basement</a> <a href="#" data-filter=".Home-Office">Home Office</a> <a href="#" data-filter=".Kids">Kids</a> <a href="#" data-filter=".Garden">Garden</a> </div> <div class="portfolioContainer"> <?php foreach($page->Images as $image) { $large = $image->width(800); $thumb = $image->size(340); echo " <a class='fancybox-portfolio port-item {$image->tags}' href='$image->url' rel='gallery1'> <img src='$thumb->url' alt='$thumb->description' class='portfolio-thumb'> </a>"; } ?> </div> 3. Coverage Thumbs The client is receiving regular coverage in leading interior design magazines and at the end of the project I required a way to differentiate between Features and Opinion pieces. Again, PW made this very easy for me. I knew I could easily create a field called Coverage Type and select the type of coverage a publication should belong to. Traditionally I would have relied on the Page field to achieve this but I didn't need the initial more involved setup which that would require. Instead I opted for the new, simpler Options field instead. Featured Modules RenoTheme CoreConfig Upgrade Markup Simple Navigation CroppableImage FormBuilder ProCache (shortly) SEO Page Path History Redirects SiteMap XML ListerPro WireMail SMTP Conclusion That's pretty much it. I know some of the techniques here won't set the PW world on fire and probably are pretty basic but hopefully seeing the screengrabs and examples will help other beginners understand PW a little better. Thanks as always to the PW community who helped build this with their advice and answers along the way.13 points
-
Quick note about this site, it's just been re-launched as a 'V2' after an additional 90 hrs of work on it... http://ohmspeaker.com/ mostly a lot of refactoring of code, finding better, more efficient ways of doing things, both in frontend and admin...I had about 2 years of good reading–the forum–between the initial launch and when the refactor started... Thanks to pro modules like Table and Lister Pro, the management interface is fast, and easy for the company management to maintain. With 4 separate product lines to manage (Speakers, Legacy Products, B-Stock and Home Theater), Lister pro has streamlined this–the agile ajax interface is truly unparalleled amongst ecommercce systems for adding and editing hundreds of products. The news system has been expanded and enhanced with xml feeds, category/tag/archive filters, author profile, and other enhancements. The product search was converted from a server side search to a completely Javascript based filter, using html5 pushstate, and graphical sliders. The category overview pages filter the products as opposed to being separate pages, reducing page loads. Product pages are more intuitive, with better veneer picker, and other javascript enhancements.6 points
-
That's a better description...Like @tpr has suggested, this would be better managed on the admin side rather than in an include file for at least two reasons: 1. Your images will have a description - no need to type that text in some template file where your client/editors will not be able to change it 2. Dynamism...in case needed in the future. Here are some options: Option 1: Create an image field (e.g. call it content_header). Attach this image to the template used by your parent pages (Whale, Guppie, etc). I am assuming all these parent pages have a single shared template (please note, I am talking about a template here; not a template file). Image fields have a description text area. Use that for your 'brief descriptions'. content_header->description will give you access to those descriptions. More here on image fields. Then on the children pages' template file(s) call on their parents' image field and description...e.g. $page->parent->content_header->description Option 2: Create a dedicated page to hold all the content headers and their descriptions. Let's call it 'Content Headers'. Add one image field to it that accepts multiple images. Add your '25' images named similar to your parent pages, e.g. whale.jpg, guppie.jpg, etc (if practical, or use some other naming format). I can't remember if you can use the API to find an image using its name (i.e. $image->basename). Anyway, you can activate the 'tag' text area of an image field (in the field's settings). In that case, no need to give your images any specific name. Then, give each image a tag that is identical to your parent pages names or titles. You can find each specific image using their tag, i.e., $page->images->getTag('mytag'); Or, in your case you refer to the dedicated page, e.g. $p = $pages->get('name=content-headers'); $chImage = $p->content_header->getTag("$page->parent->name"); If you gave the whale header image a tag called 'whale', then, when viewing Whale's child pages, this image will be retrieved. The advantage here is that you can edit all your content headers in one place. Option 3: If your descriptions are quite long, then, create a dedicated text field(s) and a separate image field using either of the above options Option 4: I think you could also use repeaters or PageTable(?) Haven't tested the above code and I have been away a while, so, there could be other better ways to accomplish what you are after.3 points
-
hi all, new PW site launch: http://www.ohmspeaker.com/ some of the modules that were helpful or essential for this: cropimage formbuilder fredi importcsv minify piwik analytics procache batcher redirects version control template decorator modules manager page link abstractor sitemap xml admin custom pages markup simple navigation (for the sitemap) forum topics related to this site dev: Legacy Site URL redirects: http://processwire.com/talk/topic/3641-redirect-legacy-url-to-new-pw-page/ Clean up spelling: http://processwire.com/talk/topic/3519-use-api-to-spellcheck-whole-siteclean-up-spacing/ hashes in URLs on change selected product http://processwire.com/talk/topic/3496-help-with-url-param-change/ FormBuilder http://processwire.com/talk/topic/2904-how-to-redirect-by-id/ http://processwire.com/talk/topic/2821-3rd-party-send-conditionally/ http://processwire.com/talk/topic/2820-use-session-to-remember-form-selections/ Custom Menus http://processwire.com/talk/topic/2787-custom-menu-not-related-to-page-tree/ other notes: The skyscraper profile provided the example for how to get started with the advanced product search, a.k.a. the speaker finder. The standard search has been extended to show results in different categories. there is some use of Soma's word limiter for the news teaser text, and for making meta descriptions out of body fields, from this topic: http://processwire.com/talk/topic/3429-how-to-set-text-linecharacter-limits-in-templates/ the design is built on twitter bootstrap framework Fredi proved to be totally essential for the client, in being able to rapidly edit things without having to find things in the admin. This site is going to replace an existing site on a different domain (ohmspeakers.com). At some point we weren't sure if/how we would be able to handle the shopping cart element, and then found foxycart, which proved to be the best choice, very flexible, and easy to implement for this type of site. FC is hands down the simplest and easiest way (imho) we could achieve things like the legacy product pages, where there are various parts and upgrades displayed on 1 page. this version is sort of a "v1", and will be expanded/improved a lot for a v2, which would happen in about 4 months.. BTW - these speakers are really good; i now own 3 pairs ... they look great and do sound totally amazing...! -marc2 points
-
They are actually not using anything other than the stock Foxycart admin; Though i did setup Orderdesk and it looks great, but i don't think they ever used it. @BernhardB - thanks for checking it out! The filter is really dead simple.. 1.) jQuery Datatable with custom filters, using PW page IDs as data attributes on the cells, e.g. data-filter="1234" 2.) when you change any of the filters, there is an onchange trigger to redraw the table with the filter; 3.) change some numerical inputs to the sliders 4.) empty divs above the table, one for each filter type, and those are populated at the same time when the filters change2 points
-
Ok, just pushed a new version to dev that adds support for choosing an alternate Parent. This allows you to bring in child pages from any other parent in the page tree (like I mentioned in my previous post above). It's a new option under the Content / Deletion / Protection tab - obviously only available for page specific config settings. Also added an option to determine whether Filters/Columns/Actions are available in Lister mode - checkbox under the Lister mode settings tab. This version might require a little extra testing regarding allowed templates for editing/adding pages. Please let me know how it goes.2 points
-
I'm not exactly sure what you're thinking "combine" means here, but this field does exactly what the description says; it grabs data from other fields, mashes it all together into one big blob of (JSON) content -- and that's just about it. One very simple (yet sometimes very practical) use case is if you've got, say, 15 different text fields and you need to find pages that contain value "john doe" in any of those. Instead of doing this: $john_does = $pages->find('field1|field2|field3|field4|field5|...|field15%="john doe"'); .. you can create a cache field, select all of those fields to be cached in it, and then do this: $john_does = $pages->find('my_cache_field%="john doe"'); Not only does this look clean, in certain situations it can wildly improve query performance.2 points
-
A ProcessWire Fieldtype storing files in a customized location, outside the web root. This module is primarily useful if you need to store sensitive data which should not be accessible directly from the web. Normally, ProcessWire stores all files under /site/assets/files. Direct URL access to these files can be restriced by setting $config->pagefileSecure = true. Still you need to make sure that your template permissions are setup correctly. If something goes wrong, those files could be accessed from outside. GitHub: https://github.com/wanze/FieldtypeSecureFile Modules Directory: http://modules.processwire.com/modules/fieldtype-secure-file/ How does it work? After installing this module, you can create a new field of type SecureFile. Enter your configuration under the "Details" section when editing the field: Storage Location Enter a path outside the web root where the files are stored. You need to create the directory manually. Also make sure that the user running the web server has write permission. Roles allowing to download a secure file Users with a role selected here are able to download the files if a download is requested via the API. Allow Download in Admin If checked, users having a role selected above can download the files when editing a page. I needed this functionality for a recent project, so I created this module and thought to share it, mabye this is useful for someone else Consider it beta, I'm using it on one site but I'm sure it could be improved here and there. Feel free to suggest additional features! Cheers1 point
-
Here is a simple tutorial how to enable the Justify capability in CKEditor First, download the plugin at http://ckeditor.com/addon/justify . Copy the "justify" folder to the "plugins" folder under ckeditor in your modules directory and upload to server. Edit the field that is using the ckeditor and go to the input tab.. Under CKEditor Setting > CKEditor Toolbar insert the following line where you want the icons to appear: JustifyLeft, JustifyCenter, JustifyRight, JustifyBlock Use ACF? choose "No" Under Extra Plugins insert: justify1 point
-
Official Announcement: http://blog.getbootstrap.com/2015/08/19/bootstrap-4-alpha/ Hacker News Discussion: https://news.ycombinator.com/item?id=100866511 point
-
if you have an options selectfield eg "demo_select" 1=value|title 2=value2|title 2 3=value3|title 3 and want to have a visibility dependency for "show this field only if..." this works: demo_select=1|2 but this doesn't: demo_select=value|value2 i think the labeled version is better because it's better readable and labels don't change if you change the order of your options (if you create new ones or delete old ones the ids are newly created and therefore changed...)1 point
-
1 point
-
Yes - good find, that was the model i used for setting up the range filtering.. $.fn.dataTable.ext.search.push( function( settings, data, dataIndex ) { var distance = parseInt( $('#search_distance').val(), 10 ); var distmax = parseFloat( data[3] ) || 0; // use data for the distance column if( isNaN( distance ) || distance <= distmax ) { return true; } return false; } ); and i'm using the ion rangeslider, which after testing a few different ones seemed to work best1 point
-
<?php // First, confirm that a submission has been made if($input->post->contactname) { // Set a temporary upload location where the submitted files are stored during form processing $upload_path = $config->paths->assets . "files/contact_files/"; // New wire upload $contact_photo = new WireUpload('contact_photo'); // Reference field name in HTML form that uploads photos $contact_photo->setMaxFiles(5); $contact_photo->setOverwrite(false); $contact_photo->setDestinationPath($upload_path); $contact_photo->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif')); // Second wire upload (other_photos) [NEW CODE] $other_photos = new WireUpload('other_photos'); // Reference field name in HTML form that uploads photos $other_photos->setMaxFiles(10); // Allow 10 other photos $other_photos->setOverwrite(false); // Use the temporary location set above $other_photos->setDestinationPath($upload_path); $other_photos->setValidExtensions(array('jpg', 'jpeg', 'png', 'gif')); // execute upload and check for errors $files = $contact_photo->execute(); $other_files = $other_photos->execute(); // [NEW CODE] // Run a count($files) test to make sure there are actually files; if so, proceed; if not, generate getErrors() if(!count($files)) { $contact_photo->error("Sorry, but you need to add a photo!"); return false; } // Set up submissions in the ProcessWire page tree $np = new Page(); // create new page object $np->template = $templates->get("data"); // Set template for pages created from form submissions $np->parent = $pages->get("/test/"); // Set parent for pages created from form submissions // Send form submissions through ProcessWire sanitization and apply each to a template field for the new page $np->of(false); $np->title = $sanitizer->text($input->post->contactname); $np->name = $np->title; $np->contactname = $sanitizer->text($input->post->contactname); $np->email = $sanitizer->email($input->post->email); $np->comments = $sanitizer->textarea($input->post->comments); $np->save(); // Run photo upload for "contact_photo" foreach($files as $filename) { $pathname = $upload_path . $filename; $np->contact_photo->add($pathname); $np->message("Added file: $filename"); unlink($pathname); } // Run photo upload for "other_photos" [NEW CODE] foreach($other_files as $other_file) { $pathname = $upload_path . $other_file; $np->other_photos->add($pathname); $np->message("Added file: $other_file"); unlink($pathname); } // Save page again $np->save(); echo "<p>Thank you for your contact information.</p>"; return true; }else { echo "<p>Sorry, your photo upload was not successful...</P>"; } I've just gone though it and prettified the code. Also for line one: Do never put things right after "<?php". Not even comments. There has to be at least a space.1 point
-
You have two options for the dropdown: Page Field or Select Options Fieldtype1 point
-
Nice one, looks like you are getting the hang of PW and that is beneficial for you and your clients/visitors too! I see some glitches on mobile, eg: - menu doesn't show up on click (z-index?) - parallax images ruin the UX - I would disable on mobile entirely - portfolio images are wider than the page - the main logo looks jagged If you're before phase 2 than some of these could be added to the todo list1 point
-
Fantastic! Excellent finish all round, and thanks for highlighting a few of the PW methods used1 point
-
I am currently working on a project where Android apps connect to a PW DB to put and get data. For data exchange I decided to create a REStful service with PW. There is a REST helper class for PW from clsource which is working great. The Android apps also display HTML that is rendered by PW and sent as JSON to the Android app. I am not in charge of the JAVA part so I can't tell you what is needed on the Android side to render that JSON. There is the Ionic framework that helps in developing android apps based on web technologies without using JAVA.1 point
-
We are now at > 420 issues and ~ 80 PRs. I did a short analysis and the total amount of issues with labels fixed fixed! please confirm already fixed can be closed not a bug can’t reproduce feature not a bug completed (aka tickets which could very probably be closed) is around 130. I always try to comment such issues ("can this be closed?"). I will try to continue to do so. Edit: by the way, 26 PRs are marked as "completed".1 point
-
Hey, so after having used the Fieldtype Select for a few project I had some customers that wanted a radio version of this so I decided to modify it (not heavily) and make it work with radio buttons instead. I have it hosted up on github here so check it out and let me know if you have question or comments.1 point
-
@teppo I read your post a while ago but could not remember where to find it again so thanks for that, very nice writeup on caching and also good info there on hooks too for anyone looking for a clear explanation on this. Nice. I'll look into fieldtype caching. There does not seem to be much mention of it anywhere - googling it only returns a few vague bit and pieces (expect your own post here, which gives a pretty good overview of it I think). I'll give it a tryout anyway, sounds like it might be an option. @wanze Thanks for this suggestion. You are right, I'm calling find twice which is stupid so I'll definately alter this. The timing tests I did showed the sluggishness was due to the actual retrieval of individual field data rather than the fetching of the page objects (which was fast) so I don't expect it to make a huge difference, but any parts which can be optimized I'll look at, so this is a helpful suggestion.1 point
-
1 point
-
I think you mean something like this: function wordLimiter($str, $limit = 120, $endstr = '…'){ $str = strip_tags($str); if(strlen($str) <= $limit) return $str; $out = substr($str, 0, $limit); $pos = strrpos($out, " "); if ($pos>0) { $out = substr($out, 0, $pos); } return $out .= $endstr; } echo wordLimiter($page->body);1 point