Leaderboard
Popular Content
Showing content with the highest reputation on 12/28/2014 in all areas
-
I have been spending some long evenings building PadLoper. It is my personal project to challenge myself as a developer, but also something I believe ProcessWire really misses: a solid eCommerce platform. I am happy to announce, that I am not very far away from public release, so I did create a little teaser site and email list for all of you that are interested: https://www.padloper.pw/ As many of you now, I also have bunch of eCommerce modules called "shop for processwire". Those remain open source modules, but I am not actively maintaining them (like I really haven't since 2012). All the code in PadLoper is new and it's totally build from ground up. If someone wants to maintain or develop shop for processwire further, I am more than happy for that. There will be some open source components coming from PadLoper also: at least payment modules, but I might also open source the shopping cart module. Padloper released 4th October, 2015: https://www.padloper.pw/12 points
-
Hello community, This is a tiny command line node app, to print out the latest ProcessWire forum posts to your terminal. Installation Following command requires nodejs sudo npm install -g processwire-forum-posts Usage The global installation will symlink an executable script and place it in your PATH. To use processwire-forum-posts type `pwforum` on your terminal or command prompt: $ pwforum More information please refer following: NPM Directory: https://www.npmjs.com/package/processwire-forum-posts Source: https://github.com/gayanvirajith/node-processwire-forum-posts Thanks5 points
-
Getting closer to the release: please all you that are interested, subscribe into PadLoper newsletter to get early access invite and discount: http://www.padloper.pw/4 points
-
Finally, thanks to various advices I found that for me the easiest way to accomplish this was to use MarkupLoadRSS module and retrieve the youtube ID from the link. I post here the code for future reference: $rss = $modules->get("MarkupLoadRSS"); $rss->load("https://url_to_my_feed"); foreach($rss as $item) { $url = $item->link; // link to youtube video provided by MarkupLoadRSS parse_str( parse_url( $url, PHP_URL_QUERY ), $my_array ); //create a array with values contained in the URL $youtubeID= $my_array['v']; //$youtubeID is the youtube ID echo "<img src='http://i.ytimg.com/vi/".$youtubeID."/mqdefault.jpg' alt='".$item->title."'/>";// img url reconstruction }//foreach end4 points
-
This is a very basic guide on how to optimize a ProcessWire page for speed. It doesn’t go into the depths of optimization and perfect render paths but will provide you with some proven ProcessWire methods for faster websites. The big problems that are easy to fix are what we aim for. You want quick improvements? Then read on… First let's have a look ath the following graph. Those are the areas, we want to improve. Source: http://httparchive.org/interesting.php?a=All&l=Oct%201%202014 Clean up your HTML Look at your HTML source code. Are there any unnecessary parts? Remove anything that might not be needed and try to keep your markup as clean as possible. Avoid using too many external JS libraries or other tools. It is okay to include jQuery from a CDN, because most visitors will already have cached the file. Too many of those external requests will slow down the page. If possible, try to avoid render-blocking Javascripts and move your script tags to the end of the page, right before the body. In most cases, your Javascript will enhance your content but doesn’t need to fire before the site is rendered. Always think if you need to include another library or the fourth webfont on your site. Minify Markup The next step to save some bytes is to remove all whitespaces from your markup. It doesn’t have to look nice, it has to be loaded fast. We perform this trick with our new super-weapon: The AllInOneMinify module for ProcessWire. Install it like every other module for ProcessWire. Once activated, go to the module settings and tick the checkbox for “Minify HTML” and look at your sites source code. It should be minified. AIOM can handle conditional browser comments. If your layout depends on whitespaces you could “force” them by putting an into the markup. Optimize the CSS Now we’re heading for the next larger part of a usual website. We will combine all CSS files and then remove anything not needed (whitespace,comments) from it. Before we start, make sure your CSS files only contain rules that you really use. Especially if you’re using a framework like Bootstrap, most of the selectors are never used. Remove them carefully. We need the AllIneOneMinify module from the previous step again. After installation, open the template file where your HTML header is generated. We will now replace all stylesheet tags with a single file. AIOM needs to know all CSS (or even LESS) files, relative to your template folder. It will then output a link to a single, compressed CSS file. You might have this in your HTML head: <link href="<? echo $config->urls->templates;?>/css/grid.css "rel="stylesheet" /> <link href="<? echo $config->urls->templates;?>/css/style.css“ rel="stylesheet" /> Replace all links to Stylesheets with the single tag like this: <link href=”<? echo AIOM::CSS(array(‘css/grid.css’,’css/style.css’)));?>” rel=”stylesheet”/> You pass an array with the file names to the AIOM method CSS. It will return a link to the file. AIOM takes care of image urls inside CSS. It will detect changes in the source file and only generate a new file if necessary. While developing, you might want to turn on the “Development” checkbox in the module settings. Make JavaScript tiny Do the same as you do to the CSS to your Javascript files. First, clean up the code. Then install AIOM and compress all JS files into a single file using the AIOM::JS method that works as the AIOM::CSS method. For best results, think about including scripts like jQuery from a CDN and put your scripts below the content, before you close the body tag. Also note that the order on how your throw your JS files into AIOM might be important, depending on the code inside. Get the right image size. ProcessWire comes with great image tools. Use them, to make images exactly the size you need them. You don’t have to serve that little thumbnail with over 3000px length just because the editor wasn’t able to reduce the size. Example: Your designer wants to have a slider image with a maximum size of 600x320 pixel. To output the image with that exact dimensions, use the API accordingly: $sliderImage->size(600,320)->url; An even better way would be to use adaptive images or the new srcset attribute combined with a JS fallback. Then your site only delivers the image size as needed. Hint: Play around with the image quality setting in the config.php. Maybe you don’t need images with a JPG quality of 90+. Compress the images further with minimize.pw To make images even smaller, we can use the minimize.pw service. This service will compress images nearly lossless by using more complicated tools to reduce the size of PNGs and JPEGs. By doing this, you remove bytes from the largest chunk of your website weight. minimize.pw is free for 2000 images. Just enter your E-Mailadress and receive a free key Then you have to install the ProcessImageMinimize module and enter they key. You can now activate the option to automatically compress every image uploaded. It is fail-safe and will compress images in the background. Please note, the automatic mode only works with images uploaded AFTER you have activated the module. You can manually select image fields with the ->mz() API method. Just include it before you output the image in your template file: $myImage->width(300,300)->mz()->url; We've closed the service. You could use something similar like Imgix ( https://www.imgix.com/ ). Activate GZip compression on your site Another method to speed up your site is to activate GZip compression. The server will then send all files compressed to the client. This works with nearly all browsers and the CPU power required is minimal. You can tell your server to do this, by adding those lines to your .htaccess file in your root directory. Please take care, that you do not overwrite the ProcessWire rules in the file! For best results add them on the top of the .htaccess file: <IfModule mod_deflate.c> AddOutputFilter DEFLATE js css AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html </IfModule> This was taken from another forum post. Tell the client to cache stuff To make repeating visits faster, we can tell the browser to cache special files for a longer period of time. Again, add this on top of your .htaccess file: <IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 seconds" ExpiresByType image/x-icon "access plus 1 year" ExpiresByType image/jpeg "access plus 1 year" ExpiresByType image/png "access plus 1 year" ExpiresByType image/gif "access plus 1 year" ExpiresByType text/css "access plus 1 month" ExpiresByType text/javascript "access plus 1 month" ExpiresByType application/octet-stream "access plus 1 month" ExpiresByType application/x-javascript "access plus 1 month" </IfModule> <IfModule mod_headers.c> <FilesMatch "\\.(ico|jpe?g|png|gif|swf|woff)$"> Header set Cache-Control "max-age=31536000, public" </FilesMatch> <FilesMatch "\\.(css)$"> Header set Cache-Control "max-age=2692000, public" </FilesMatch> <FilesMatch "\\.(js)$"> Header set Cache-Control "max-age=2692000, private" </FilesMatch> <FilesMatch "\.(js|css|xml|gz)$"> Header append Vary: Accept-Encoding </FilesMatch> Header unset ETag Header append Cache-Control "public" </IfModule> Remember, that this caching might be annoying while developing the site. Use the internal cache (or ProCache) Another trick to make the site faster is to use a caching system. This will “store” your rendered site so you don’t have to query the database that often. We can either do this with the internal cache of ProcessWire or use the commercial, official ProCache module. Using the build-in system, you go the the setting page of a template and open the “Cache” register. You can now set the Cache time and what happens if something changes. The settings depend on the content of the site. Mostly static content can be cached longer and you might not need to reset the cache every time. Dynamic sites will need shorter cache times. ProCache (buy here) is even faster because it will bypass PHP and the database. Files are served directly as HTML. Please note, that caching might make the site faster but it can create new problems. Use with care. Summary Keep your code as clean as possible. Remove anything unnecessary and then compress HTML,CSS and JS using the AIOM module. The largest part of your page weight are images. Keep them small by using the appropriate dimensions and consider services like minimize.pw. In the end, use intelligent caching and buy ProCache. Following this guide takes not more than an hour but can speed up your site and make your visitors happy. This was just a quick overview of techniques to optimize your page speed. There is plenty of stuff you can do but the steps above are a good first step. Maybe you can share your favorite methods (or links) to start the discussion.1 point
-
Keep up the good work @apesia, I'm absolutely sure PadLoper will be the e-commerce solution of choice for everyone in here using Pw!1 point
-
I was making a point about letting the unwinding of nested function calls help with your tag closures but you don't have to take it to extremes. Take your example of HTML that works and indent it to see structure/repetition much more easily (see below). Where there is a lot of repetition there is more of a case for using a function. Looking at the indented code, I'd start with two functions. You get the stuff to display as a PageArray using: $children=$pages->find("template=product,product_cat=1014,show_main>0"); The thing I see being repeated a lot is for each product-block. Markup to display one product's attributes. Each grouping of those has a simple wrapper surrounding it which is a couple nested divs (item and row). Make a function to do the item and row divs. Pass it $children and since you want to do products in groups of four pass it an index and a quantity (4). It can test that to tell whether it should use the "active" class and it can use the index and quantity to pick pages to be displayed from of the $children PageArray. It will use another function multiple times to produce the items and then it will close the item and row divs it started. Make a second function for the first function to pass a product page to. This will make the markup for that one product, starting with div class="span3 product-block" inserting the data from the product page, and closing the divs for the product block before returning. Your foreach loop can then call the first function, incrementing the index, until it runs out of pages. You could have the first function help out by returning either the next index to use or false if there are no more products and it's time to stop. I left out making the "carousel" markup around each "row" but it's just more of the same idea. <div class="carousel-inner "> <!-- repeat --> <div class="item active"> <div class="row-fluid box-product"> <div class="span3 product-block"><div class="product-inner"> <div class="image"> <a href="#"><img alt="Loves or pursues" src="products/image-4.jpg"></a> </div> <div class="wrap-infor"> <div class="name"><a href="#">Loves or pursues</a></div> <div class="description">Samsung Galaxy Tab 10.1, is the world's thinnest tablet, m...</div> </div> </div> </div> <div class="span3 product-block"><div class="product-inner"> <div class="image"> <a href="#"><img alt="Loves or pursues" src="products/image-5.jpg"></a> </div> <div class="wrap-infor"> <div class="name"><a href="#">Loves or pursues</a></div> <div class="description">Samsung Galaxy Tab 10.1, is the world's thinnest tablet, m...</div> </div> </div> </div> <div class="span3 product-block"><div class="product-inner"> <div class="image"> <a href="#"><img alt="Loves or pursues" src="products/image-6.jpg"></a> </div> <div class="wrap-infor"> <div class="name"><a href="#">Loves or pursues</a></div> <div class="description">Samsung Galaxy Tab 10.1, is the world's thinnest tablet, m...</div> </div> </div> </div> <div class="span3 product-block"><div class="product-inner"> <div class="image"> <a href="#"><img alt="Loves or pursues" src="products/image-7.jpg"></a> </div> <div class="wrap-infor"> <div class="name"><a href="#">Loves or pursues</a></div> <div class="description">Samsung Galaxy Tab 10.1, is the world's thinnest tablet, m...</div> </div> </div> </div> </div> </div> <!-- repeat --> </div>1 point
-
You're right. Depending on what you want to allow you should use the $sanitizer options, for html maybe the purifier, which can be used via the module, or your own stuff. http://cheatsheet.processwire.com/#sanitizer http://modules.processwire.com/modules/markup-htmlpurifier/1 point
-
Thanks now i am more encourage knowing it works on your end. I will do as specified and debug it and monitor the variables. I wanted to be sure I wasn't an exception thanks alot andrian.1 point
-
I think the feature Nico is talking about was added in the dev branch a while back? IIRC...can't find a link atm... . To be clear parent::init() has been there for a while...what I am referring to is the 'uninstall' feature Nico is talking about...if memory serves me right!1 point
-
1 point
-
Hi BernhardB - awesome and thanks so much for joining in on this.. i really like your approach to the widgets also; the InputfieldSelector field isn't that new, i can't remember when it was announced - i think this past summer; but in terms of the CMS, it is pretty new and it was conceived by Antti Peisa, coded by Ryan Cramer and sponsored by Avoine; it is in the core, so you just need to install it. The field is used in the listers; as a standalone field i haven't seen many posts about day-to-day use of it and i kept thinking of when and where it might come in handy.. then while i was setting up this one site I came across this situation where i wanted a certain widget only to show up on the child pages of another page; so first i did a plain field and typed in the selector and sort of moved on... but something kept nagging at me and then it suddenly dawned on me that there is already this field that could make setting up the selector more user friendly and reliable, and it works great; It provides feedback to tell you how many pages match your selector; for some clients who have a little technical knowledge and skill, this is a really simple and easy way to specify a selector for pages, and then be able to test against that selector in conditionals.. i think in some instances it is probably too technical to be of use; i wonder if you could use the new selector field in your setup, as you can add additional lines to the selector, which would be like your repeaters... i haven't done extensive testing or experimenting yet with this, but i have 3 more sites to launch and i'm sure this selector field will get more use in situations like this..1 point
-
You can do a check to see if the product_type is the same as it was during the last loop. Something like this: $last_product_type = ''; $sid=$pages->find("template=product, sort=product_type"); foreach($sid as $product){ if($product->product_type != $last_product_type) echo $product->product_type ."<br>"; echo $product->product_name ."<br>"; echo $product->product_image->url ."<br>"; echo $product->desc ."<br>"; $last_product_type = $product->product_type; }1 point
-
The PW image API allows you to create different sized, cached versions of images for use in different situations. For instance an original image might be 1000 x 700 px, but we can can crop and resize using: $newsize = $page->myimage->size(300,300); And produce a square, cropped and resized image 300 x 300 px. But how can we make this work in a responsive environment so that we choose an image varient created using the API based on viewport size? There are several ways to do this, but in this case, a bit of script called Response.js can be rather useful. Reponse.js allows you to set up a set of parameters for exchanging data on the fly. (Please note that this is NOT an ajax based system, for that, please look up enquire.js) So, you can tell it to look for a certain sized view port by setting breakpoints and then use that to choose what data you want to call in. So, for instance, on their website they give this example: <img src="lo-fi.png" data-src481="medium.png" data-src1025="hi-fi.png" alt="example" /> The default image is the smallest (thinking mobile first) and then there are two further images called depending on the viewport size. The "data-src481" bit relates to the set up code made for this page or site. You can see that it would be fairly easy to add the PW image api to that bit of html. So, onto a real world example I am using in a client's blog. I had two imediate problems - firstly the site uses EMs and by default, response.js uses px. Secondly, I wanted nice memorable names for my various breakpoints. The developer of response.js is a helpful fellow and he wrote me a nice bit of script to do exactly what I want: !function(Response) { var names = ['basic', 'phoneportrait', 'phonelandscape','smalltablet','largetablet','laptop','desktop']; var values = { phoneportrait: '(min-width:20em)', phonelandscape: '(min-width:30.063em)', smalltablet: '(min-width:33.125em)', largetablet: '(min-width:48.000em)', laptop: '(min-width:64.063em)', desktop: '(min-width:80.063em)' }; Response.addTest('view', function(breakpoint) { var query = values.hasOwnProperty(breakpoint) && values[breakpoint]; return !query || Response.media(values[breakpoint]).matches; }).create({prefix: 'view-', prop: 'view', breakpoints: names, dynamic: true}); }(Response); This script is in my sitewide javascript file so that it is available for anything I am doing. All this script is doing is setting my em min-width values against names and then using those to create the calls. So, I would call a breakpoint with: data-view-phoneportrait Just for interest, this reproduces a set of breakpoints I have using sass-mq for my sass development set up. Now all I have to do is mix that up with my images, In the example below, which is for a list of articles in responsive blocks (using the easy to use pocketgrid system) I just swap the image depending on the view port: $smallimage = $article->image_single->size(256,256); $mediumimage = $article->image_single->size(300,300); $largeimage = $article->image_single->size(371,371); echo "<a href='{$article->url}'><img src='{$smallimage->url}' data-view-smalltablet='{$largeimage->url}' data-view-largetablet='{$mediumimage->url}' data-view-laptop='{$mediumimage->url}' data-view-desktop='{$largeimage->url}'></a>"; Response JS can also swap data within a div, though as I said earlier, this does not use ajax, so is best for small bits and pieces. I am finding that with the huge versatility of Processwire, this plays very nicely not just with more complete systems like Foundation, but perfectly with far more versatile system made up of small utilities rather than one big do-everything solution. My tool box now consists of responsejs, enquire, boubon mixins (but I don't use NEAT), various cross browser helpers like respond.js and html5shiv, a very good media query mixin call sass-mq and then my own bits and pieces. So, the lesson here is that the PW api does not just output data, but is part of your toolset for creating powerful and capable dynamic, responsive, mobile first websites.1 point
-
This will do what you are looking for. You need to get the page array for the page you are adding: $pageitem and also use "add" to add it to the array of pages held by the page field. $p = $pages->get(1234); $pageitem = $pages->get(4321); $p->of(false); $p->foo->add($pageitem); $p->save(); Hope that makes sense.1 point
-
Thank you Adrian, You guys are so awesome! I will give a look to simplepie. Merry Christmas and and all the best in 2015!1 point
-
1 point
-
What about if you use this link: http://gdata.youtube.com/feeds/api/users/disney/uploads?orderby=updated&v=2&client=ytapi-youtube-rss-redirect&alt=rss That actually contains the thumbnail url. Note the "api", rather than "base"1 point
-
The node that contains an image is not there. The images are in a blob of HTML so it's hard to get those out. If you really want to get those out you could build the url to the image your self. The easiest way I see now is: Filter the video id out of the: // 76UvX8EKNZ8 is the ID <guid ispermalink='false'> tag:youtube.com,2008:video:76UvX8EKNZ8 </guid> Then use that id to build the url with: // Default image (small) http://img.youtube.com/vi/<insert-youtube-video-id-here>/default.jpg // high quality http://img.youtube.com/vi/<insert-youtube-video-id-here>/hqdefault.jpg // medium quality http://img.youtube.com/vi/<insert-youtube-video-id-here>/mqdefault.jpg // standard definition http://img.youtube.com/vi/<insert-youtube-video-id-here>/sddefault.jpg // max resolution http://img.youtube.com/vi/<insert-youtube-video-id-here>/maxresdefault.jpg Keep in mind that not all images are available so propably you'll need a loop till you have an image and use a fallback if nothing is found. Second way: A second way I see is to search the <description> with PHP DOMDocument.1 point
-
My initial need is to support different local vat classes. I will take a look into this vatmess, but I wouldn't hold my breath for full support (although it probably isn't that big stretch from that) . It seems the technical hurdle is the smallest one for dealer. If I understood correctly, you need to register into each eu country as seller. Do you need to report those taxes also into each country?1 point