Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 10/17/2014 in all areas

  1. MarkupAdaptive This module aims to be a helper for developing an adaptive site. MarkupAdaptive is a module that injects classnames representing 'media queries'. Fire events after the browser is resized and fires an event when a media query is changed. Optionally it can write a cookie with the ‘media query’ classname of the current viewport size. The main purpose of this module is about syncing media queries with javascript. Say I want to have a slider on the iPad but don't want that slider on the phone I could now destroy the slider exactly on the right time. You could respond server side with this cookie, but keep in mind that you then need a workaround for the default caching solutions. (template cache or ProCache) The module script works with injected media queries and a HTML element tested against those. This javascript process starts real early in the load process and is extremely fast. It starts even before the body tag is parsed. In Explorer 7 and 8 clientWidth is used to pinpoint the “classname of the viewport size”. To support Explorer 7 and 8 your media queries should be specified in pixels. In the wild An working example of the module is hosted on hosted on lightning.pw Instant ProcessWire Hosting from conclurer.com. Please don't forget to view the console.log(). The site doesn't use any media query in the stylesheet. Not that I recommend building adaptive sites without media queries. . How to install Install the module At least open the Module configuration, optionally save it. Insert the below code in the HEAD of your html file <script><?php echo $modules->get('MarkupAdaptive'); ?></script> Javascript methods available when using MarkupAdaptive. ( More instructions like Event support IE7 & 8 are available in the 'example template' packed in the module folder ) /** * Getting information with Javascript. * */ // How to catch the end of a resize (with jQuery) $('html').on('resized', function(e) { console.log('Browser window is resized'); }); // Respond on a media query change $('html').on('mediaquerychange', function(e) { // Get the old class name before the “mediaquery” change has occurred var oldClass = MarkupAdaptive.getOldClass(); // Get the new class belonging to the current “mediaquery” var newClass = MarkupAdaptive.getClass(); console.log('mediaquerychange, from: “' + oldClass + '” to: “' + newClass + '”'); }); // Get the current class var current = MarkupAdaptive.getClass() // Get the old class, the class before the current var old_class = MarkupAdaptive.getOldClass() // Mediaquery JSON object which originates from your Modules config var sizes_object = MarkupAdaptive.getJson() // Mediaquery JSON object which originates from your Modules config' var array_with_classnames =MarkupAdaptive.getArray(); // Is the current browser IE8 (returns true/false) MarkupAdaptive.isIE() // (bool) // Is the current browser IE8 MarkupAdaptive.isIE(8) // (bool) // Is the current browser less then or equal to IE9 (lt, lte, gt, gte) MarkupAdaptive.isIE(9, 'lte') // (bool) // get the cookie, when checked in the module configuration function getCookie(name) { var match = document.cookie.match(RegExp('(?:^|;\\s*)' + name + '=([^;]*)')); return match ? match[1] : null; } console.log('Classname cookie value: ' + getCookie('MarkupAdaptive')); Special thanks to all the people from conclurer who made it possible to host MarkupAdaptive. When you're searching a lightning fast hoster. You should consider lightning.pw. View on GitHub Download GitHub
    10 points
  2. It's made 100% in PW and sent directly from this server using PW's WireMail interface with either Teppo's WireMailSwiftMailer or Horst's WireMailSMTP.
    8 points
  3. I think the issue is that the image is by default an inline element. Inline elements do not respond the same as block elements. Verticaly you can't set paddings to 0 You could float the image to make it a inline-block automagicly or you could make it a block element. img { display:block; margin: 0; } // center image with class .center img.center { display:block; margin: 0 auto; } img.left { float: left; } img.right { float: right; }
    5 points
  4. Adrian, that's a valid sequence when using SSL (Port 465 is required). Port 587 requires TLS. The first link I posted explains what normally works, according to Gmail themselves. I host with Dreamhost and when I was using ActiveCollab, I could use either or both within that application. Gmail has other relay addresses that also work. Here's Dreamhost's take on SMTP/SSL/TLS http://wiki.dreamhost.com/Secure_E-mail I'm no Gmail or SMTP expert, so I usually just play around with the settings until I get one that reliably works. I don't think there is a default right answer to getting your mail to send reliably, because we are dealing with different email vendors, Operating Systems, Webhosts and other factors we don't even know about.
    5 points
  5. Ok, as promised, here's my solution. public function init() { wire()->addHookAfter("ProcessPageEdit::execute", $this, "tryThis"); } public function tryThis(HookEvent $event) { $render = $event->return; $template_name = "xyz"; // Change this to match the exact template name of pages you want to apply tab-renaming to. if (false !== strpos($render, "template_{$template_name} ")) { $render = str_replace("Content</a>", "New Title</a>", $render); $event->return = $render; } } I'm not totally satisfied with it as it makes no allowance for possible changes to the default string or the internationalisation of it - but it is still relatively easy in PW. I've raised an issue about this over on the home repo as I think PW should be able to solve this more elegantly. It will do for this current site as I only expect to use the English default string for the content tab.
    4 points
  6. @bbeer that is a lot of fields to have in one template. I also see that it's not just a lot of fields, but most of them are also multi-language, which takes your quantity of fields and multiplies that by the number of languages (4 in your case). Plus take your quantity of individual files and multiply that by 4 as well. It's possible you could be hitting 800+ inputs here. While I don't think this quantity of fields is necessarily a problem, I do think that you should expect some overhead in trying to render and save that many fields at once. It's not just going to be server side, as that's a lot of markup for your browser to process, and a lot of DOM elements for the Javascript client side as well. So you will likely see both server-side and client-side overhead at this scale of fields. I also see some third party modules involved here, and I don't know to what extent they also add overhead. For instance, I see you've got Teppo's awesome version control module on most of your fields. I also use that on my sites. But I've always assumed there must be some significant overhead with it given all the great things it does, so I typically limit usage of it to only 1-2 fields on a template. Unless Teppo says otherwise, I would suggest doing a test and remove the version control from those fields just to see what difference it makes. In fact, the same goes for any 3rd party modules that you've got involved here (I see one active in your files). Remove or change them to non-third party temporarily just to see if you an find any bottlenecks. Sometimes certain bottlenecks only become apparent at larger scale like you have here. One thing that could make a potentially huge difference here would be use of the Textareas ProField field. This is the perfect case for it, since you have so many similarly configured Text and Textarea fields. It looks to me like you could potentially reduce your quantity of fields by a factor of 10 or more, which may solve the overhead issues completely on their own. However, you may lose the version control (which I'm assuming either doesn't work with the Textareas ProField, or treats all the components of it as one block), and you would have to change your multi-language approach slightly by using the language alternate approach with separate language-specific Textareas field. But it would still drastically cut down on the field quantity and thus overhead. Another thing to consider is that it's possible you may be trying to accomplish too much with one page/template here. If you look at it from a database design perspective, it's kind of like having one giant god table that holds everything, rather than splitting it out into specific, more dedicated parts. However, if each of the pages like this is completely different in content (i.e. little to no repetition of what gets populated in the fields), then it may be completely fine. I can't really evaluate much from looking at the screenshots because it's just one page and I don't read the language. So I'd be inclined to see how you can reduce overhead with what you've got before you re-think the structure of it. Lastly, you may have to consider the PHP max_input_vars limit. With ~150 fields multiplied 4 languages, plus quantity of individual files multiplied by 4 languages, you could hit the default limit already. You will likely need your system administrator to bump that limit up from 1000 to 3000 to play it safe. Otherwise you could experience data loss when saving a page.
    4 points
  7. Overview Mobile Detect uses a lightweight PHP class Mobile_Detect for detecting mobile devices (including tablets). Installation 1a. Clone the module and place MobileDetect in your site/modules/ directory. [OR] 1b. Download it. git clone https://github.com/justonestep/processwire-mobiledetect.git your/path/site/modules/MobileDetect 2. Login to ProcessWire admin and click Modules. 3. Click "Check for new modules". 4. Click "install" next to the new SimpleContactForm module. Usage This Module extends $config and sets the following parameters: $config->mobileDetect = array( 'deviceType' => 'deviceType (phone, tablet or desktop)', 'browser' => 'mobile browser', 'operatingsystem' => 'mobile operatingsystem', 'device' => 'mobile device' ); You can access them where ever you want. See the example below: <body class="devicetype--<?php echo $config->mobileDetect->deviceType?>"> <body class="devicetype--{{config.mobileDetect.deviceType}}"> // twig Results in: <body class="devicetype--phone"> OR<body class="devicetype--tablet"> OR<body class="devicetype--desktop">
    3 points
  8. First of all, you really shouldn't try to do an import via phpMyAdmin. Using ProcessWire's API is always a better (and easier) way. Direct SQL import is going to be a lot of work and might cause all sorts of unexpected issues, some of which you might not notice until it's too late. Import scripts are easy to write -- usually the hardest part is getting data out of the other system and, of course, planning your new data structure. I'm not familiar enough with MODX to know how easy or hard it's going to get data from there, though, but I've done my fair share of import scripts for other systems. Usually the easiest method is exporting data from original system as CSV, JSON or something else that's "machine readable" and then writing a simple import script using the bootstrap method, but there are other methods too. You might want to check out this case story -- and perhaps ask some questions in that thread too -- as it seems to have some similarities with your case. Also, if you can get your data out in CSV format and it's not too complex in structure, Import Pages CSV just might do most of the work for you. Migrator tool built by Adrian is somewhat related too, though that's not exactly off-the-shelf solution for this particular situation (there's a WordPress migrator available, but not one for MODX yet, at least as far as I know). Hope this helps a bit.
    3 points
  9. I think your PHP version is not sufficient enough. It need to be > 5.3.8.
    3 points
  10. Can't speak for everyone here, but I won't be using them anytime soon. Short opening tags depend on a PHP settings in all PHP versions, so they're never guaranteed to work. While short echo (<?= $whatever ?>) is generally speaking more acceptable -- after all it's always enabled in PHP 5.4+ -- it might not work in all setups using earlier PHP versions. By the way, the accepted answer to this Programmers Stack Exchange question has a simple chart about using the short echo tag. Since ProcessWire officially supports PHP 5.3.8, I would suggest avoiding them in your modules, even if just to be consistent with the core system itself.
    3 points
  11. Just to add to Craig's post, if you needed to style each item differently for any reason, you could do something like this: <?php $newsItems = $pages->find("template=widgetNews"); $i = 1; foreach($newsItems as $newsItem) { ?> <article class="newsItem newsItem<?php echo $i ?>"> <h3><?php echo $newsItem->title; ?></h3> <h4><?php echo $newsItem->newsDate; ?></h4> <?php echo $newsItem->newsSummary; ?> </article> <?php $i++; } ?> That would give you the shared newsItem class as well as a unique newsItem# class with the number of the iteration (i.e. newsItem1, newsItem2, newsItem3). Similarly, you could use the page's name instead of a number by tacking that on to the end of the class.
    3 points
  12. From the source code it looks like the title of the first tab is set by adding the title attribute to the form in buildFormContent. I can successfully overwrite that attribute with this code... wire()->addHookAfter("ProcessPageEdit::buildFormContent", $this, "tryThis"); public function tryThis(HookEvent $event) { $form = $event->return; $new_title = $this->_("Personal Info"); $title = $form->attr('title'); $this->message("Updating form title [$title -> $new_title]"); $form->attr('title', $new_title); } And I've verified (by single stepping the code) that the attribute gets overwritten and returned and even makes it through several stages of hook return. Despite this, as Martijn mentioned, it seems to be protected as it still gets rendered as "Content" even with the change. I have no idea why at the moment. Update 1: Ok, it is getting saved in an instance variable ($this->tabs[$id] = $title) and it is that variable that's being used to render the tab via WireTabs. Will need to look at hooking execute() and doing a replace on the rendered output. Not a pretty way to do it - but at least I know it should work. Update 2: Just to confirm, I have succeeded in doing this using an after hook on ProcessPageEdit::execute - but it's not a particularly elegant solution.
    3 points
  13. Having a nasty bug in Explorer 9 and higher. Please wait using this one till this is fixed. Sorry Huge rewrite & now polyfilled with the matchMedia polyfill from Scott Jehl, Paul Irish, Nicholas Zakas, David Knight.
    2 points
  14. You should know I'm not very familiar with CSS / JS. I run into an issue when I have developed a responsive site that should show different designs for phones, tablets and desktops. Also the site uses infinite scrolling, loading image thumbs. The number of loaded images at once and the dimensions of the requested images needs to be very different regarding to the device type a visitor uses. (for phones it should load 2 thumbs at once, for tablets 12 and for desktops 36) I have used a serverside UA-Sniffer (PHP) and have set a class in the body tag to represent the found devicetype "<body class='tablet' ..", This way all the CSS for the different device types could be derived from there. After the site was nearly finished, one of the last things to implement was ProCache. This was planned from the beginning, but I haven't used it before. After installing and configuring ProCache, the first device-type entering an URL was written into the cached page-version. Uhh! It is very important to build the caching strategy at an early point. (Now I know this too) I came around my issue with the caching with changing from the serverside UA-Sniffer to a JS-UA-Sniffer and adding a JS snippet right after the body tag that adds the relevant device-type-class to the body. var md = new MobileDetect(window.navigator.userAgent); if(md.phone()) { document.body.className += (' phone'); } if(md.tablet()) { document.body.className += (' tablet'); } The code is called directly after the opening body-tag. Also the small JS-lib does not depend on jQuery, it is the only one that needs to be called in the head. All other JS files can be called after the body content. I used this PHP UA-Sniffer: https://github.com/serbanghita/Mobile-Detect and this JS-Port of the above: http://hgoebl.github.io/mobile-detect.js/
    2 points
  15. @Martijn, I've unmarked this as solved as it's not quite the whole story. If I put a breakpoint in my hook routine I can examine the $event object and I can see all the information I need to be able to make a rename decision as the $event object's page's template has a title that I want to compare against - but it doesn't seem possible for me to access that information via the API using $event->object->page->template->title which always gives a blank, despite me being able to inspect the data in the debugger. I suspect that some of these fields are protected or private members of the $event->object. If I do find a full solution I'll post it.
    2 points
  16. Hey owzim. I'm glad you like the module. We're still using it in all of our projects (but as I've already mentioned combined with TemplateTwigReplace) so it has to be maintained further even if it's only for our own projects. I'll look into this issue and try to do my best in the next days. Sadly marco (who is a great software engineer - a lot better than me) isn't working for neuwaerts anymore but if I can't resolve this issue by myself I'm sure he'll help us fix it.
    2 points
  17. Not a direct response to your question but I have never liked the PHP short tags (just a matter of preference). Even on personal sites where I am sure short tags feature is enabled, I never use them. I don't think there is a general consensus about their use (or not) in modules but I would urge all module developers to stay clear of them just to ensure compatibility..
    2 points
  18. + Use: https://github.com/typekit/webfontloader if you're using webfonts (this is important especially on mobile with slow connections)! + Use the "Picture" Element where applicable + Use dns-prefetch if you're loading external ressources (i.e. cloud hosted javascript librarys) This Article has some more stuff to look at.
    2 points
  19. Something like this <?php $newsItems = $pages->find("template=widgetNews"); foreach($newsItems as $newsItem) { ?> <article class="newsItem"> <h3><?php echo $newsItem->title; ?></h3> <h4><?php echo $newsItem->newsDate; ?></h4> <?php echo $newsItem->newsSummary; ?> </article> <?php } ?> Wrap each post's content in another tag which you can style separately. Here I used the article tag, but a div would work just as well.
    2 points
  20. @jordanlev Sure, but be warned, my code currently does it across all pages you edit as I've not added anything to restrict it to just the template I'm after. In fact, I'm now worried that I won't be able to do it on a per-template basis this way. But the day is late and I'll worry about that tomorrow. In the meantime, here it is... public function init() { wire()->addHookAfter("ProcessPageEdit::execute", $this, "tryThis"); } public function tryThis(HookEvent $event) { $render = $event->return; $event->return = str_replace("Content</a>", "New Title</a>", $render); } That's part of a little auto-loaded module. Oh, yeah, it also currently updates any links that end with the word "Content" but that's fixable with a more complex match.
    2 points
  21. I don't know why but when I use my work email address which is managed by Gmail, but is not a @gmail address, I need to use: Nothing else seems to work for me except this. Hopefully that might be a useful addition to @cstevensjr's excellent post.
    2 points
  22. I just want to drop a note here to publicly thank jlahijani and muzzer for lots of recent help getting several more bugs identified and fixed and at the same time mention that you should all grab the most recent version on Github (https://github.com/adrianbj/ProcessMigrator). Thanks again guys!
    2 points
  23. The emails themselves are pages in ProcessWire as well, so all the content managed just like any other ProcessWire page, i.e. https://processwire.com/about/newsletters/processwire-weekly-22/
    2 points
  24. You can detect whether the current page was loaded from ajax by checking the value of $config->ajax from your template file: <?php if($config->ajax) { // page was requested from ajax } Following that, you will likely want to render the page differently to accommodate whatever you are doing from the javascript side. For instance, you might want do one of these: 1. Deliver alternate or reduced markup when loaded from ajax 2. Deliver a JSON or XML string for parsing from javascript Below are examples of each of these scenarios. 1. Deliver alternate or reduced markup when loaded from ajax You might find checking for ajax helpful when you want portions of pages to load in your site without re-rendering the entire page for each request. As a simple example, we'll use the default ProcessWire site and make it repopulate it's #bodycopy area when you click a page in the top navigation. (To use this example, you'll need the default ProcessWire site templates, though you can easily adapt the example to another situation.) To accomplish this, we'll update our main page template to only include the header and footer markup if the page is NOT being loaded from ajax: /site/templates/page.php <?php if(!$config->ajax) include("./head.inc"); echo $page->body; if(!$config->ajax) include("./foot.inc"); Next we'll update the top navigation to do ajax loads of the pages when the client has javascript (and leave as-is when they don't). Paste this javascript snippet before the closing </head> tag in the header markup file: /site/templates/head.inc: <script type="text/javascript"> $(document).ready(function() { $("#topnav a").click(function() { $("#topnav a.on").removeClass('on'); // unhighlight selected nav item... $(this).addClass('on'); // ...and highlight new nav item $("#bodycopy").html("<p>Loading...</p>"); $.get($(this).attr('href'), function(data) { $("#bodycopy").html(data); }); return false; }); }); </script> Now when you click on any page in the top navigation, it pops into the bodycopy area without a page load visible from your browser. And all pages remain accessible from their URL as well. Note that this is just a test scenario, and I probably wouldn't use this approach for the entire bodycopy area on a production site (it would make bookmarking difficult). But this approach can be very useful in the right places. 2. Deliver a JSON or XML string for parsing from javascript Lets say that you want pages in your site to return a JSON string with the page's id, title, and number of children when it is requested from ajax. When not requested from ajax, they will return their content as normal. To handle the ajax requests, you'd want to add something like this at the top of your template file before any other output. <?php if($config->ajax) { // this is an ajax request, return basic page information in a JSON string $json = array( 'id' => $page->id, 'title' => $page->title, 'numChildren' => $page->numChildren ); echo json_encode($json); return; } // not ajax, continue with regular page output And here is some markup and inline javascript you might use to test the ajax call on some other page (or the same one if you prefer). You would paste this snippet right in your site's markup where you want that info to appear. <ul id='info'></ul> <script type='text/javascript'> var url = '/'; // this is homepage, so replace '/' with page URL you want to load JSON from $(document).ready(function() { $.getJSON(url, function(data) { $.each(data, function(key, value) { $("#info").append("<li>" + key + ": " + value + "</li>"); }); }); }); </script> The above snippet would output something like this: • id: 1 • title: Home • numChildren: 5 To take this example further, you could build an ajax-driven sitemap or any number of web services. Conclusion Hope this helps you to see how simple it is to use ProcessWire to deliver output for ajax. These are just contrived examples, but hopefully examples that might lead to more ideas. In addition, much of what you see in these examples is also applicable to building web services in ProcessWire.
    1 point
  25. Hi all, I just released my first module on github called Template Data Providers. This module lets you create simple data provider classes for templates and chunks (a.k.a. partials, blocks, includes, ...) to gather and prepare data for templates and/or handling form data and other actions outside of the templates ("separation of concerns"). But even if you've installed the module the usage of the new functionality is merely optional. You may define your simple templates and chunks as usuals, adding custom classes (PageDataProvider for pages/templates, ChunkDataProvider for chunks) for more complex data handling on demand. I provided detailed instructions in the README.md and encourage you to read it for further information. Just some sample code here: Defining a data provider for a home template: class HomePage extends \nw\DataProviders\PageDataProvider { public function populate() { $this->foo = 'bar'; // definevariable $foo to use within the page's template $this->page->foo = 'baz'; // provides page member $page->foo to use within the page's template } } Calling a chunk from within a template: $page->renderChunk('path/to/primary-navigation.php'); // relative to site/templates/ Calling a chunk providing contextual data: $news = $pages->get('template=news'); foreach ($news as $newsItem) { $page->renderChunk('path/to/news-item.php', $newsItem); // additional arguments provided will be avaiable within the chunk in a closed scope } Defining an example chunk data provider: class ExampleChunk extends \nw\DataProviders\ChunkDataProvider { public function setContext(array $context = array()) { // store first context argument in $this->foo $this->foo = isset($context[0]) ? $context[0] : null; // store second context argument in $this->bar if instance of \Page $this->bar = null; if (isset($context[1]) && $context[1] instanceof \Page) { $this->bar = $context[1]; } } public function populate() { $this->foo = 'bar'; // provides variable $foo to use within the chunk } } Please leave your questions, remarks, error reports here in the forum or at github and I'll try to answer as soon as possible. This module is a preparation for another module coming soon. This will be an alternative Twig template engine module that will interact with Template Data Providers or could be used as stonde-alone module. Regards from Hanover/Germany, Marco
    1 point
  26. 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
  27. This module is obsolete and will not be developed any further. Please use the ImageExtra Module instead. Overview This module allows you to add additional informations to an image (for example: title, description, link, orientation and any field you may need). If you want to, you can install FieldtypeImageExtraLanguage to get multi-language support. For more informations have a look at the readme. Installation 1a. Clone the module and place FieldtypeImageExtra in your site/modules/ directory. [OR] 1b. Download and unzip it from the module page. git clone https://github.com/justonestep/processwire-fieldtypeimageextra.git your/path/site/modules/FieldtypeImageExtra 2. Login to ProcessWire admin and click Modules. 3. Click "Check for new modules". 4. Click "install" next to the new FieldtypeImageExtra module. If you need multi-language support, you have to install the FieldtypeImageExtraLanguage module. 5. That's all - no settings are required but possible. Define your custom fields 1. Login to ProcessWire admin and click Modules. 2. Open `Images Extra Inputfield` Settings. The following fields are available by default: orientation - image orientation orientation values - values to use as classnames or identifiers for different image orientations title - image title to use for title/alt tag or/and caption, if empty, the content will be generated from the applications filename description - image description link - image link to internal pages If these fields are not enough for you, you can add any other field (for example _author_ and _location_) by writing it (separated by comma) in the field otherField. If you don't need all custom fields, you can easily disable them. One more exception is orientationValues. Here you can insert identifiers for classnames or similar separated by comma. This values will be available in a dropdown list. Usage 1. Under Setup and Fields create a new field using type `ImageExtra` or `ImageExtraLanguage`. 2. After entering the new field name and label, click Save. 3. Configure it depending on your own needs. 4. Save. 5. Add your new field to one or more Templates. Accessing the value This is no different than accessing the value of any other field. $image = $page->image->getRandom(); echo $image->title; echo $pages->get($image->link)->url For use with TemplateTwigReplace {% set image = page.images.getRandom() %} {{image.title}} {{pages.get(image.link).url}} Screenshots Here is a litte example how to access the new fields: // if there are images, lets choose one to output in the sidebar if (count($page->images)) { // if the page has images on it, grab one of them randomly... $image = $page->images->getRandom(); // resize it to 400 pixels wide $image = $image->width(400); // output the image at the top of the sidebar $sidebar = "<img src='$image->url' alt='$image->description' />" . "<h3>$image->title</h3>" . "<blockquote>$image->description</blockquote>" . "<p>$image->author ($image->location)</p>" . $page->sidebar; }
    1 point
  28. I was just wondering if there are any future plans to extend the comments field slightly? Obviously I know it should remain lightweight as it's a part of the core, but I'll chip in with my personal wishlist for it. Basically my number one wish is for the ability to link comments to member accounts. This would enable us to output their profile picture next to their comments, link their name to their profile, and basically output any information stored within their profile page (gender, age, location) alongside their comment, if desired. The ability to use permissions, roles / dynamic roles to determine who can can edit / post / delete their comments. An option to enable comment quoting on reply (like you can do with this forum). We could then use our own markup to style it etc. Finally, an easy way to determine what page comments are connected to. This would allow us to create a new page and loop through all the pages with comments, thus creating a very basic forum-style page. The latest version of muut follows along those lines by utilising comments to create a central hub or basic forum. Personally I reckon with these additions we will be able to use PW to easily create something like you see on the Muut page above. Thanks.
    1 point
  29. We've recently rebrushed/relaunched our agencys website and took the opportunity to build it using processwire (as we're currently using it for almost all of our projects). http://www.neuwaerts.de Modules used: Modules Manager Page Link Abstractor Database Backups Redirects Revision History For Text Fields Template Data Providers Template Decorator Template Twig Replace There currently are 6(!) more websites using processwire in the making (more or less parallel) so stay tuned for some more showcase entrys in the next weeks
    1 point
  30. Some more bug fixes - thanks again to muzzer! More interestingly though, during import you now have the option to automatically download and install any required missing fieldtypes/inputfields from the PW modules directory. This is optional and I have noted that if you don't trust the source of the data you are importing, then you might want not want to enable this option. It is off by default, in which case you'll receive notifications of what's missing so you can install manually before re-starting the import.
    1 point
  31. 1 point
  32. Tuomas, thanks for your post and welcome to forums! Does that work universally, since there is another salt at filesystem (site/config.php)? https://github.com/ryancramerdesign/ProcessWire/blob/master/install.php#L610
    1 point
  33. For me this Module is the best approach for organizing logic and views without being too much in your face with restrictions. I tested it yesterday, and like it very much and discovered the same problem as @marcus without knowing it has been posted here. I created an issue: https://github.com/marcostoll/processwire-template-data-providers/issues/2 What's the status of this module? Will it be maintained further?
    1 point
  34. Hi pwired, Correct, mod_security in CPanel. I'm still looking into the issue but so far it looks like there was a false positive in some encoded third-party cookie data. Can't share the settings/config atm. Mod_security made the decision to 404 these requests.
    1 point
  35. Update: I traced the problem back to mod_security and it's fixed now. Marc
    1 point
  36. @Jordan, Some useful links: https://github.com/ryancramerdesign/ProcessHello http://wiki.processwire.com/index.php/Module_Creation http://processwire.com/api/modules/ https://processwire.com/talk/topic/741-a-guideline-for-module-naming/?p=6267 https://processwire.com/talk/topic/2394-how-to-present-your-module/ https://processwire.com/talk/topic/1313-modules-process-and-the-difference/
    1 point
  37. You can load a process module on the front end if you need to access a method or property from it. Usually Process modules are not autoloading because they are called from a page under setup or as a helper from another module. But if you have it already doing something in the admin, you could load it on the front-end: $modules->get("ModuleClassName"); and then call the required method/property. I would suggest limiting most parts of the module's functionality to just the admin template so when you load it on the front end, only the relevant method/property is instantiated and processed - the rest of the code should be excluded. It looks like Craig might have detailed what you need as far as setting things up.
    1 point
  38. Probably the simplest way to do this is to create a hook method or property on pages - rather than "injecting" variables into templates. The Helloworld.module file is a basic example of how to do this - example3 and example4 functions, but here is how it might look (completely untested - guide only!) Module init: $this->addHookProperty('Page::hello_world', $this, 'helloWorld'); Module function: function helloWorld($event) { $page = $event->object; if ($page->template->name !== 'my_template') return; $event->return = "Hello, world. The ID of this current page is " . $page->id; } Template: <h1><?php echo $page->title ?></h1> <p><?php echo $page->hello_world ?></p>
    1 point
  39. Jordan, I am not sure whether this would help: https://processwire.com/talk/topic/4647-best-hook-for-replacing-page-rendering/?p=45968 but I am failing to understand how a Process Module (modules that run in the backend/admin) has anything to do with something that will be rendered in the front-end (basically a page's template)...
    1 point
  40. Swab the decks, ye mutinous architect. We'll plunder yer blueprints and use 'em as underpants.
    1 point
  41. On Goldfinger... Trivia: it was actually Ian Fleming's dislike for the architect, Ernő Goldfinger, that lead to the James Bond villain being named after him [Wikipedia]
    1 point
  42. This is a very good newsletter I think https://serversforhackers.com/
    1 point
  43. could you try this: $this->addHookAfter("ProcessPageEdit::buildForm", $this, "tryThis"); public function tryThis(HookEvent $event) { $form = $event->return; $content = $form->find("id=ProcessPageEditContent")->first(); $content->label = 'steve'; } sitting on the livin' room giving the baby milk, so no time to test what I wrote.
    1 point
  44. Javascript performance is very good when you keep one thing in mind. Don't trigger repaints when you can avoids those. I can imagine all the needed data you send to the browser is in JSON. Then build the whole needed HTML structure with Javascript before attaching it to the DOM. After inserting the HTML structure fire the plug-in. When you change the viewport size (with orientation change for example) You now can Destroy what you've build with Javascript, and use the original JSON data to build the other structure. The JSON data can easily hold the data for multiple sizes of images or what ever you wish.
    1 point
  45. some other links Rating Pages https://processwire.com/talk/topic/7871-page-ratings/#entry76186 Flagpages https://processwire.com/talk/topic/7044-release-flagpages/ Bookmark pages https://processwire.com/talk/topic/7886-page-bookmarks/ Add remember - all are pages so Users are pages, too. This means that if i "bookmark" a users page -> i'm a follower of this "page=user". If i remeber right the user bwakad builds some kind of social powered website, may you send him a message. regards mr-fan
    1 point
  46. Here's how it worked for me in CKEditor (in case you persist on this route - but I would go for Hanna Code as Adrian suggested. As usual, the "culprit" is our friend HTML Purifier (read from here up to and including Ryan's comment here about its pros and cons before deciding whether to implement #5 below!) For iframes, the Extra allowed content seems to have no effect - btw, the correct syntax here is for example, div(*) not div[*] Add 'Iframe' (note the spelling) to your CKEditor Toolbar Leave ACF on No need to switch the field's "Content Type" from "Markup/HTML" to "Unknown" Turn HTML Purifier off (gasp! ) Enjoy your embedded video
    1 point
  47. That's the exact thing I try to avoid @Marvin: Here goes: https://github.com/sforsman/SessionLdapAuth I even added an example for the group mapper and did a modification to the code (well, I fixed a spelling error in the description of the module)! If you have any questions about some parts of it, just ask away. I've published it as a Proof of Concept. (see Nico, I'm learning!) No but really, the main point here is to give you something to think against regarding your own implementation. The group mapper configuration string for an example is parsed in a very quick and dirty (=error prone) way and shouldn't be given directly to clients.
    1 point
  48. hi isag, welcome to the forum! your templates include what you tell them they should include... an easy example: template1.php includes style1.css <!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" media="screen" href="<?= $config->urls->templates ?>css/style1.css" /> </head> <body> <?= $page->body ?> </body> </html> template2.php includes style2.css <!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" media="screen" href="<?= $config->urls->templates ?>css/style2.css" /> </head> <body> <?= $page->body ?> </body> </html> ----------------------- or you can use a _main.php file and populate just the variable blocks/styles/values in your template: _main.php <!DOCTYPE html> <html> <head> <link rel="stylesheet" type="text/css" media="screen" href="<?= $stylesheet ?>" /> </head> <body> <?= $content ?> </body> </html> tempate1.php $stylesheet = $config->urls->templates . "css/style1.css"; $content = $page->body; include("_main.php"); template2.php $stylesheet = $config->urls->templates . "css/style2.css"; $content = $page->body; include("_main.php"); hope that helps remark: no correct code - just to clarify the principle!
    1 point
  49. Hi marco, unfortunately the example for a home page template, mentioned above, doesn't work in my case. I installed the module, left the default setting dataproviders, created this very folder in site/templates/ (checked its permissions), placed a HomePage.php with your example code in it, opened home.php and tried to echo $foo. With no result. Am I misunderstanding the concept, or did I forget a neccessary step to make this work? Thanks in advance! marcus PS: PW 2.4, Module version 1.0.2
    1 point
  50. Thanks Apeisa! When configuring mailchimp it was annoying me that it was sending way to many confirmation and thank you emails for a simple email subscription, I designed and customized all the messages though. The reason why I gave up on from it, was that, apparently, you can't customize the error messages, and they are automatically translated and full of errors. I will try madmimi later. For now I'm quite happy with my efforts to collect the emails, here is what I have: <?php echo $pages->get(1011)->text; if($input->post->submit){ $email = $sanitizer->email($input->post->email); if(!$email) { echo "<p>" .$input->post->email . " is not a valid email</p>"; } elseif($pages->get("title=$email") instanceof NullPage) { $p = new Page(); $p->template = $templates->get("person"); $p->parent = $pages->get(1015); $p->title = $email; $p->save(); echo "<p>your email was saved </p>"; } else { echo "<p>" . $email . " exists already in our database</p>"; } } else { ?> <?php echo $pages->get(1011)->emailform; ?> <!-- Begin Signup Form --> <form action="<?php echo $page->url; ?>" method="post" id="signup"> <input type="text" name="email" class="email" id="email" /> <br /> <input type="submit" value="senden" name="submit" class="send" /> </form> <!--End signup form--> <?php }; ?> Besides this I'm validating the email with jquery before submiting. It's working, but am I doing something unsafe or it's ok?
    1 point
×
×
  • Create New...