Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/21/2014 in all areas

  1. Hi everybody, As much as we hate the CAPTCHA, it is still used. I decided to share my solution of using ProcessWire forms with CAPTCHA. My goals were quite simple: 1. Create a form and customize it. 2. Get an Inputfield for a page field and append this Inputfield to the form. 3. Display a CAPTCHA. 4. Process the form and check its fields for correctness. 5. Check the CAPTCHA. 6. If steps 4-5 fail, display the form back with the user input intact. What I found to be not quite easy was how to push a different CAPTCHA into an already submitted form. (A spoiler: this is done quite smoothly with the power of ProcessWire's Inputfields.) Let's start, then. My Form class has several methods: appendFields() accepts an array of field names, gets their Inputfields from a template and appends these to the form displayForm() adds a CAPTCHA and returns the form's HTML processForm() checks the CSRF session ID and user input and delegates CAPTCHA verification getCAPTCHA() returns the html for the CAPTCHA checkCAPTCHA() checks the user input against the CAPTCHA and sets the verification flag to true or false. That's mostly it. Now to the code itself. class Form { public $form; public $captchaVerificationResult; // captcha verification flag (bool) public function __construct () { // form is created upon class instantiation $form = wire('modules')->get("InputfieldForm"); $form->action = wire('page')->path; $form->method = 'post'; $form->attr("id+name", 'form'); $form->attr("class", 'pure form'); // I use PureCSS class name here as an example // how form items are displayed can be customized $form->setMarkup(array ( 'list' => "\n{out}\n", 'item' => "\n\t{out}\n\t", 'item_label' => "\n\t\t<label class='pure-form' for='{for}'>{out}</label>", 'item_content' => "\n\t{out}\n\t", 'item_error' => "\n<p><span class='ui-state-error'>{out}</span></p>", 'item_description' => "\n<p class='description'>{out}</p>", 'item_head' => "\n<h2>{out}</h2>", 'item_notes' => "\n<p class='notes'>{out}</p>", ) ); // form classes can also be customized $form->setClasses(array ( 'list' => 'Inputfields', 'list_clearfix' => 'ui-helper-clearfix', 'item' => '', 'item_required' => '', 'item_error' => 'ui-state-error InputfieldStateError', 'item_collapsed' => '', 'item_column_width' => '', 'item_column_width_first' => '', ) ); $this->form = $form; } public function appendFields ($fields) { /* * $fields is an array of field names * * for each field name a corresponding Inputfield is fetched from a page * and appended to the form * */ $page = wire('pages')->get("999999999"); // this is the page that has your fields foreach ($fields as $f_name) { $field = wire('fields')->get($f_name); $if = $field->getInputfield($page); // this page must have field name $f_name among its fields! $this->form->append($if); } /* * * CAPTCHA placeholder */ /* * create an InputfieldMarkup field, * give it an ID and append to the form * * Later this Inputfield can be easily found by its ID. * * */ $inputfield = new InputfieldMarkup; // inputfield markup is appendable to form! $inputfield->id = 'captcha1'; // id of the InputfieldMarkup with CAPTCHA $this->form->append($inputfield); /** * finally, the SUBMIT button * */ $submit = wire('modules')->get('InputfieldSubmit'); $submit->skipLabel = Inputfield::skipLabelBlank; // remove the label $submit->name = 'submit_save'; $submit->value = "Save"; $this->form->append($submit); } public function get () { return $this->form; } public function displayForm ($form) { /* * Each time the form is displayed, the CAPTCHA should be there * * So, behore doing $form->render() let's get an InputFieldMarkup field by ID * and pour some fresh CAPTCHA in it * * */ $form->children->findOne("id=captcha1")->value .= $this->getCAPTCHA(); return $form->render(); } public function processForm ($form) { try { $form->processInput(wire('input')->post); wire('session')->CSRF->validate(); } catch (WireCSRFException $e) { die ($this->displayForm($form)); } $this->checkCAPTCHA(); // sets class property $captcha_verification_result to false/true if (!$this->captcha_verification_result) { $form->children->findOne("id=captcha1")->value = "Wrong captcha, try again <br />"; // this will go before the CAPTCHA code die($this->displayForm($form)); } else { // let's do some simple checks // you can and should do more of yours, of course $email = $form->get("b_email"); if (filter_var($email->value, FILTER_VALIDATE_EMAIL)) { $email->error = "Incorrect email format"; } if ($form->getErrors()) { // the form contains errors, display it with user input die($this->displayForm($form)); } else { echo "Thanks for the submission!"; // everything is just right } } } public function getCAPTCHA () { /* * * $captcha_html = your CAPTCHA code * */ return $captcha_html; // have a lovely CAPTCHA } public function checkCAPTCHA () { /* * * get some response and check it * * */ if ($response->failed) { $this->captchaVerificationResult = false; } else { $this->captchaVerificationResult = true; } } } Here's how this can be used: $form = new Form(); $formFields = array ("name", "email"); $form->appendFields($formFields); $newForm = $form->get(); if ($input->post->submit_save) { // user submitted the form, process it and check for errors $form->processForm($newForm); // the form was processed successfully because nothing die()'d. Now it's time to play with what's been submitted. } else { echo $form->displayForm($newForm); // if it's not been submitted, just display it and the CAPTCHA } With this being just a generic idea on how to do form processing with CAPTCHA, I hope portions of this code will prove helpful in your development. Your comments, corrections and suggestions are very much welcome.
    4 points
  2. I normally just minimize both my pocketgrid and normalize and add them to the top of my style.css One call, does it all /*! PocketGrid 1.1.0 | MIT License | http://arnaudleray.github.io/pocketgrid/ ____ __ __ ______ _ __ / __ \____ _____/ /_____ / /_/ ____/____(_)___/ / / /_/ / __ \/ ___/ //_/ _ \/ __/ / __/ ___/ / __ / / ____/ /_/ / /__/ ,< / __/ /_/ /_/ / / / / /_/ / /_/ \____/\___/_/|_|\___/\__/\____/_/ /_/\__,_/ */ .block-group,.block,.block-group:after,.block:after,.block-group:before,.block:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.block-group{*zoom:1}.block-group:before,.block-group:after{display:table;content:"";line-height:0}.block-group:after{clear:both}.block-group{list-style-type:none;padding:0;margin:0}.block-group>.block-group{clear:none;float:left;margin:0 !important}.block{float:left;width:100%} /*! normalize.css v3.0.1 | MIT License | git.io/normalize _ __ ___ / | / /___ _________ ___ ____ _/ (_)___ ___ / |/ / __ \/ ___/ __ `__ \/ __ `/ / /_ / / _ \ / /| / /_/ / / / / / / / / /_/ / / / / /_/ __/ /_/ |_/\____/_/ /_/ /_/ /_/\__,_/_/_/ /___/\___/ */ html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}
    3 points
  3. It looks like ProcessDatabaseBackup is already on the way https://github.com/ryancramerdesign/ProcessWire/commit/52c09f5ef1980b7cad3876e8332254f3792e795d#commitcomment-7463067
    3 points
  4. Even if alternatives are not needed (sorry!) and though you've probably already evaluated it, when I used to develop on Windows, XAMPP was all the rage. Cross-platform, well maintained, free, etc. Just saying. Then again, it's way over 100MB package, so if that makes a difference (?), it's probably out of the equation too
    2 points
  5. WOW, that guy is totally taking parkour to a new level!
    2 points
  6. I do think you know this, but ones all data is stored in PW pages, it's quite easy to loop them and update those pages (clean process). On every loop you do little steps. recent: In the dev there's now $sanitizer->purify this can be used for cleaning HTML.
    2 points
  7. @pwired, I know this is the Pub forum... but the PW forums is a cozy place where I really enjoy being away from the wild internet.
    2 points
  8. Hi MidRo, Welcome to ProcessWire and the forums. I see your question has not been answered 7 days later! Apologies, we are normally not that slow RE spam, yes, a number of us (including Ryan) recommend using a 'honeypot' field to filter out spam. Read more here: https://processwire.com/talk/topic/960-comment-spam-filtering-alternatives/
    2 points
  9. Doesn't sound right . No need to duplicate pages. Where an item can belong to more than 1 category, the 'normal' way is to create categories as separate pages, make them selectable in the items pages using a page reference field....This guy explains it better, have a read here instead: https://processwire.com/talk/topic/3579-tutorial-approaches-to-categorising-site-content/
    2 points
  10. Well, I want to thank you all for the pointers - It does exist, but I was looking on wrong search terms in the forum and all. I have read a post from Ryan: Quote Actually, you can do this on the dev branch. Lets assume that cities are children of countries and that is reflected in your page structure (i.e. /countries/france/paris/). Create your 2 page fields (country and city), and configure 'country' as a single page field with "parent" set to "/countries/". Next, for the "city" field configuration, use the "Custom selector to find selectable pages", present on the "input" tab. In that field, enter "parent=page.country". Save and try it out. This works with select, selectMultiple and asmSelect fields (and possibly others), though not yet with checkboxes, radios or PageListSelect. - So, I have Skyscrapers - my pages are: provinces - province (drenthe) - - municipal (this) - - municipal (that) - - municipal (some) my templates are: provinces - province - - testing (added fields: province and municipal) my fields are: page field : province > single/null > required > parent selectable pages is Provinces page field : municipal > single/null > required > custom selector is parent=page.province Now it works thanks to you guys! If I select a province (which is required to choose) - I also get a select list for municipals in that province (and is also required to choose). And I do not have to use visibility because I need to choose a province and municipal. But I do wonder why a structure like this is not working? Provinces - a - b Municipal - a - b
    2 points
  11. Hi all This module was sponsored by Jason as per this topic: http://processwire.com/talk/topic/3566-email-image-module-development/ It's quite similar to horst & ryan's EmailImage module, but supports multiple email addresses for sending emails to different parts of your site, also allowing you to select different templates. There is also a delimiter option whereby you can split up the email's content and have text appear in the body or sidebar etc. Here's a video to show you what I mean. The video may well be of interest to other module authors as I used some Ajax to push what can normally be done in the module config - hope you like it There was the temptation to build on the EmailImage module with this one, but I already had code for my Helpdesk module (work in progress) that parsed emails using Flourishlib and wanted to use that code instead for this one. EDIT: Also worth noting is that unlike the EmailImage module, this doesn't come with a pre-built gallery template for the front-end. This is intentional as you could pipe emails into any part of a site you like, so I couldn't make assumptions as to usage of the content. You can download it via the modules directory.
    1 point
  12. The admin theme files are a combination of HTML/PHP, CSS, JS files and images. For the most part, it is no different from what you would create in your own site files (in /site/templates/). By default, the admin theme files are located in this directory: /wire/templates-admin/ STEP 1: To create a new admin theme, you would copy the default admin-templates directory (/wire/templates-admin/) to here: /site/templates-admin/ When ProcessWire sees /site/templates-admin/, it will use it instead of the default one. STEP 2: Now you can modify any of those files in /site/templates-admin/ and your changes should be reflected in the admin control panel. STEP 3: To distribute it to other people, you would just zip up the dir and then anyone else can unzip it to /site/templates-admin/ and have it work. I will be glad to setup a directory of admin themes on the site if anyone else decides to make one. That is all there is too it. But here are some other details and recommendations you may find helpful: MORE DETAILS: Why not just edit the files in /wire/templates-admin/ ? You certainly could do this, but you should consider everything in /wire/ specific to ProcessWire, and everything in /site/ specific to your installation. If you were to modify the files in /wire/templates-admin/, then your changes would get overwritten every time you upgraded ProcessWire. Whereas, /site/templates-admin/ is not overwritten during upgrades. What if I only want to change stylesheets and images? If you only need to change stylesheets and images, then I would recommend having your /site/templates-admin/default.php just include the one in /wire/templates-admin/, i.e. /site/templates/default.php: <?php include("/wire/templates-admin/default.php"); And likewise for any other files in there that have markup that you don't want to modify. This includes notices.inc and debug.inc. You'll also see a controller.php file there, but that is already just a placeholder so no need to make any changes to it. What are all the files in ProcessWire's admin theme and what do they do? Files you can edit: debug.inc - An HTML/PHP file that is included when $config->debug is true. It outputs general debugging information in the admin. default.php - The main HTML/PHP container template. All admin output goes through this file. notices.inc - Generates the markup for admin messages and error notices that appear at the top of the screen. scripts/ - Directory containing jQuery/javascript files. scripts/main.js - Main jQuery/javascript file that is run on all admin pages. All this does currently is setup a few minor form interactions. styles/ - Directory containing CSS files/stylesheets styles/main.css - Initial layout and styling for the admin control panel. styles/reset.css - Resets all browser styles styles/ui.css - User interface override styles. This is the last stylesheet loaded so it can more easily modify styles that came before it as needed. styles/JqueryUI/ Directory containing jQuery UI specific stylesheets and images. You can use jQuery UI's themeroller for these if you prefer. http://bit.ly/eTVbDC styles/ie.css - Styles specific to IE styles/ie7.css - Styles specific to IE7 and below. Because we don't support those, this basically just turns off IE7 support. styles/images/ - Images used by any of the above stylesheets. Files you shouldn't bother editing: controller.php - This is just a placeholder that includes a controller in /wire/core/. You should leave this file as-is. install-head.inc - These HTML files are used by the installer. You can edit them, but ProcessWire will still use the one in /wire/templates-admin/ since they are only used before installation. As a result, you can delete them from your /site/templates-admin/ if you prefer. install-foot.inc - See above. scripts/install.js - See above. styles/install.css - See above. Modifying form widgets with jQuery UI Most of the form inputs in ProcessWire are based on a jQuery UI theme. It is located in this file /wire/templates-admin/styles/JqueryUI/JqueryUI.css (and the images directory below it). Like the other CSS files, that can be edited directly. But since this was originally built using JQuery UI's Themeroller, you can continue to modify it with that if you'd prefer. Here is a link to it with ProcessWire's admin styles already pre-populated: http://bit.ly/eTVbDC Copyrights and Logo You should leave existing copyright notices, links to processwire.com and the name ProcessWire in place. You should also add a notice indicating "[Admin theme name] copyright [your name]", i.e. "Widget admin theme copyright Gonzo Deutschdeung". We also prefer that you keep a copy of the ProcessWire logo somewhere in your design, but it's up to you. A photoshop file of the logo at high resolution is attached to this message. pw2-logos.zip
    1 point
  13. Recently I got a brand new iMac so I needed to install PHP SQL and configure Apache. I'm using the same web develop environment for years and I'm really happy with it. Raymond is also using this and Arjen did the same recently. I love to share how I setup this environment in a step by step tutorial. Let's setup PHP, MYSQL and activate mail using gmail smtp for OSX 10.6 and up, perfectly suitable for ProcessWire. It doesn't install Apache, it uses the Apache installation, which comes with OS X. The PHP installer package is created by Liip and it is based on entropy's php package. For MYSQL we gonna install the DMG Archive (x86, 64-bit). After we installed PHP, we configure Apache & PHP so that we’re able to run the ProcessWire sites in our own ~/Sites directory. For El Capitan see Arjen's https://processwire.com/talk/topic/5797-setup-a-processwire-environment-on-a-fresh-macos-x-install/?p=103674 Install PHP We gonna use the PHP installer created by Liip. (more information) Go to: /Applications/Utilities/ Open: Terminal.app Type: curl -s http://php-osx.liip.ch/install.sh | bash -s 5.5 Press: RETURN Type: your admin password Press: RETURN ( download starts and continues with a the install ) note: If you want to have an older PHP version, replace 5.5 with 5.4. (PHP 5.5 is the current stable) After the install is completed Apache is restarted and complains about “Could not reliably determine the server's fully qualified domain name, using your-computer-name.local for ServerName”. This notice is not a problem, we only use this Mac for local website development. Setup Apache Open a new finder window. Press: shift + command + g ( Go to folder ) Type: /etc/apache2/ Press: go Open: httpd.conf Find the line: #Include /private/etc/apache2/extra/httpd-vhosts.conf Remove the # infront to enable. Press save and enter your password when asked. Enable the use of ~/Sites folder:Open the folder /etc/apache2/users/ * Duplicate the Guest.conf and name it martijn.conf Open the duplicated file that we created * Change: <Directory "/Users/Guest/Sites/"> to <Directory "/Users/martijn/Sites/"> Change: AllowOverride None, to AllowOverride All Save the file. The file should look like: <Directory "/Users/martijn/Sites/"> Options Indexes MultiViews AllowOverride All Order allow,deny Allow from all </Directory> Configure the vhosts includes Open /etc/apache2/extra/httpd-vhosts.conf Comment out the 2 VirtualHost examples by putting a # in front Be sure that NameVirtualHost *:80 doesn’t start with a # sign. * Add the include: include /Users/martijn/Sites/_vHosts/*.conf at the bottom of the file. Save the file, password will be asked. The file should at least have these two lines: NameVirtualHost *:80 include /Users/martijn/Sites/_vHosts/*.conf * ( Replace martijn with your short admin name ) The ~/Sites folder (Users/martijn/Sites) Goto your user Home folder. Create the Sites folder in your user home ( if not exist ) Create inside the Sites folder a folder called _vHosts Create the folder domains inside the ~/Sites folder Create a folder inside the domains folder called processwire ( processwire will be the domain name ) Inside the processwire folder create 2 directories: 1. htdocs 2. logs ( make this writeable by right click the folder and choose Get info ) Create inside the htdocs folder a file called index.html with some content. The folder structure should look like: ~/Sites |`-- _vHosts | `-- domains | `-- processwire | |-- htdocs | `-- index.html | `-- logs Configure PHP Open the file: /usr/local/php5/php.d/99-liip-developer.ini ( This file is the last ini file that gets loaded, so perfectly suitable for your personal settings ) Make your personal changes here. ( setting xdebug.max_nesting_level=1000 for example if needed ) Save the file ( password will be asked. ) Make an alias the this file by right click and choose: Make Alias Name the alias _settings.ini or what ever you want to name it. Move the alias to your ~/Sites folder Create a vHostIn our ~/Sites folder we created a folder named _vHosts. This folder we gonna use for the vHosts. All files ending with .conf in this folder will be loaded when we (re-)start Apache. Create a new file with your favourite text editor. Type the following in the file: ( Replace martijn with your short admin name ) <VirtualHost *:80> DocumentRoot /Users/martijn/Sites/domains/processwire/htdocs/ ServerName processwire ErrorLog /Users/martijn/Sites/domains/processwire/logs/error.log.txt CustomLog /Users/martijn/Sites/domains/processwire/logs/access.log.txt common </VirtualHost> Save the file with the filename processwire.conf in the folder _vHosts The hosts fileGo to the Finder Press: shift + command + g ( Go to folder ) Type: /etc/hosts & press return Open the hosts file with you favourite editor Type 127.0.0.1 processwire below 127.0.0.1 localhost but above 255.255.255.255 broadcasthost Save the file Right click the file & choose: Make Alias Move the alias that you created to your ~/Sites folder Rename it to _hosts The file should look like: ## # Host Database # # localhost is used to configure the loopback interface # when the system is booting. Do not change this entry. ## 127.0.0.1 localhost 127.0.0.1 processwire 255.255.255.255 broadcasthost ::1 localhost fe80::1%lo0 localhost Test the Apache & PHP setup Go to: /Applications/Utilities/ Open: Terminal.app Type: sudo apachectl restart Press: RETURN Type: your admin password Press: RETURN At this point Apache & PHP will be up and running.Go to a browser and type: processwire/ in the address bar and press enter. MYSQL For managing MySQL databases I use Sequel Pro it's a very handy tool and in this tutorial we set the root user password with it. For the SQL server we gonna use the MySQL DMG Archive (x86, 64-bit) Download the following: MySQL DMG Archive (x86, 64-bit) Sequel Pro Open the mysql-5.6.16-osx10.7-x86_64 image * install mysql-5.6.16-osx10.7-x86_64.pkg, MySQLStartupItem.pkg & install the prefPane * if MACOSX complains about: ( mysql-5.6.16-osx10.7-x86_64.pkg” can’t be opened because it is from an unidentified developer. ) You should open your System Preferences, go to Security & Privacy and Allow apps downloaded from: Anywhere Set the root user password Double click the sequel-pro-1.0.2.dmg. The disc image will mount Drag'n'drop the Sequel Pro.app to your /Applications/ folder. Open Sequel Pro Type by name: 127.0.0.1 Type by host: 127.0.0.1 Type by username: root Login Press command + u Select the root user on the left side Fill in the password Press apply We're Done ----- Todo how to use it after the setup is complete
    1 point
  14. Hey, The Form API has CSRF protection build in, but if you for some reason don't want to use the API you can however use the CSRF protection. Its very simple but it took some time for me to find out, so i figured i share my findings with the rest. What is CSRF? First you need to create a token and a token name you do that as following: $tokenName = $this->session->CSRF->getTokenName(); $tokenValue = $this->session->CSRF->getTokenValue(); Very simple. Now what you want to do is create a hidden input field like this: $html .= '<input type="hidden" id="_post_token" name="' . $tokenName . '" value="' . $tokenValue . '"/>'; Now this will generate something that will look like this: You are done on the form side. You can now go to the part where you are receiving the post. Then use: $session->CSRF->validate(); This will return true (1) on a valid request and an exception on a bad request. You can test this out to open up your Firebug/Chrome debug console and change the value of the textbox to something else. Basicly what this does is set a session variable with a name (getTokenName) and gives it a hashed value. If a request has a token in it it has to have the same value or it is not send from the correct form. Well I hope I helped someone.
    1 point
  15. Hi guys! I'm working on several processwire 3d wallpapers. Hope you like it. I will upload more soon. Wallpapers: Signatures:
    1 point
  16. This started off as an experiment - tweaking the existing Futura colour scheme using browser dev tools to find the places to edit. I was trying to create a less intimidating admin for my clients. So it's not ideal in that it's not a proper module, and it's not taking advantage of CSS preprocessors etc. But, I thought someone might like to try out this 'subtle' take on the admin theme. Like I said, it's just a hack - so just replace /wire/modules/AdminTheme/AdminThemeDefault/styles/main-futura.css with this version. Then in Modules > Core > AdminTheme choose "Futura". I've only tried it on the dev branch 2.4.13... If there's any interest, I might make a proper theme Module with it... -Brent Edit: added screenshots main-futura.css
    1 point
  17. I very frequently see people not finding stuff in the forums, I don't blame them, the forum search sucks bit time Then many times forum members suggest to use {searchterm} site:processwire.com/talk on Google. It's true, nine times out of ten I DON'T find what I am looking for using the standard forum search. Nine times out of ten I DO find what I am looking for using Google search. So perhaps there should be a hint on the search dialog/page to use Google instead (if that's even possible). New users would find stuff quicker, saves time for all.
    1 point
  18. Thanks Martijn for the great guide. Just wanted to point out that me and my team have used VirtualHostX for years to make managing multiple local hosts easier. It's a bit pricey, but if you work with a lot of local sites it's a huge time saver. https://clickontyler.com/virtualhostx/
    1 point
  19. It would be great to automatically add a tab to all templates (like you can do with fields). This is handy for the SEO tab for example.
    1 point
  20. Hmm... If you did a category/tagging system or based it on the existing tagging system, you wouldn't be able to customize the order of the fields in different templates. That said, I agree that the fieldset/fieldsetTab system right now is a little bit unintuitive, even if it is quite functional. A fieldset doesn't really "feel" like it should be a type of field itself, and having to setup each fieldset can get a little tiring. I think it would be nice if the fieldsets could just be created and added right from within the template's edit screen. I've recently started using fieldsetTabs to split off content into "Sidebar" and "Media" tabs, and it really helps to clean up the editor. It's a great feature that I'm surprised I haven't really used before now. Another thing that I've started to realize could be helpful in PW is some way of grouping fields into portable components that could be added to templates as a single unit (like repeater fields, except without the repeating part), instead of having to add each field one-by-one. Technically, templates ARE linked to "fieldgroups" (if you have advanced mode on, you'll see the option to use a fieldgroup from one template in another), but I don't believe you can have more than one fieldgroup per template. Anyway, it could end up adding more complexity and confusion to the system, but it could also be a big time saver in some cases. EDIT: I think if it was setup as new fieldtype similar to repeaters it wouldn't be too confusing. Maybe it's time for me to build a module...
    1 point
  21. : How much luck can you have ? Click on max screen: At the end the guy simply steps off the roof. Edit: link died out. http://www.telegraaf.nl/tv/opmerkelijk/22987318/__Ongeluk_loopt_bizar_af__.html Edit here is a better link with higher resolution This goes way beyond james bond. Speechless. http://www.youtube.com/watch?v=7vd_OuqUAaI
    1 point
  22. Hello Marek747 Welcome to the website developers world. You are not the first with exactly these questions. If you go through this forum history you will find real good answers for these questions given by talented coders and experienced web developers. Just look for them. One good thing is that you have found processwire that compared to the other big cms'es out there will save you time in quality and manageable website developing. But to answer some of your questions from my own experience. Becoming a webdeveloper and making money with that is simply not easy in the beginning. It takes time and studying the market. Besides a cms you need to be very good in html, php and css and prototyping a layout that reflects the look and feel for your client and communicate that clear with your client. Many times a client does not have a clear idea of what he wants but makes you responsible if he does not get what he wants. So prototyping until you know what your client exactly wants is important. Also to get payed in case a client decides to change what he wants during the process or in case he wants to cancel the project during the process. That takes time to learn with lots of practise. And that is only halve of it. The other halve is finding projects, planning your time with deadlines, good client communication, getting payed, etc. Don't go for reseller web hosting alone, too much good competition. Better combine making a website including web hosting for your client and make a price for that combination. A good tip is try to work together with an established designer/developer. They usually have lots of work and need a helping hand. It will speed up your learning process drastically. Good luck
    1 point
  23. Many years ago, I'm certain that many of you (and I) used the reset developed by Eric Meyer http://meyerweb.com/eric/tools/css/reset/ Sometime later, I switched to normalize https://github.com/necolas/normalize.css Are browser resets still used? Do you use them? If so, which do you use?
    1 point
  24. You only update something that needs updating . Eric Meyer's reset is still working fine for some people . Unlike CSS Frameworks, I doubt reset CSS change much over the years... Btw: http://www.cssreset.com/
    1 point
  25. It turned out to be a battle between 'normalizing' and 'resetting'. After reading up on (and testing) resetting versus normalizing (and because I am lazy), I decided to go with resetting (normalizing meant adding a few extra lines of code which I was not keen on ). I then decided to choose from what's popular out there and is HTML5 friendly. Ended up with html5doctor
    1 point
  26. Hey uprightbass360 I was literally about to post an update when your latest post apepared. After days of getting nowhere and a looming deadline, I wondered if perhaps my issues were a result of a local environment so I reinstalled PW on my www hosting, setup all the same fields, templates, pages etc (zzzz) and the same code worked beautifully. The only changes I actually made were to set a max of 1 image on the image field. I think there was something locally preventing me from using CropImage properly on my local install. I can tell now because when I crop an image on my remote site, the image in the "featured_image" field reflects the cropped image. On my local install, the image was allegdely cropped but always displayed the fullsize image with the image field. Whew! Anyway, I'm finally moving forward again and building my clients site. Thanks everyone for the help.
    1 point
  27. That will be a difficult one. I see that the two examples of artinfo you show are already different. In the first one the year is the 4th item, in the second example the 5th. Simply exporting to csv and expecting to be able to import it into Processwire is not going to work. Hope the differences are not too big over all the data..... So, the data shall have to be cleaned up first. The different ways of showing size can be overcome in the beginning by just using a textfield. How to deal with the data that has to be entered in pagefields I don't no yet. Maybe others can explain that. Btw....Maybe the cleaning up is faster to do in Excel. I've done it before in database migrations and having a good view over the columns and rows helps and also a little bit of formulas and Visual Basic afcourse.
    1 point
  28. Yes, I saw the video and was also impressed Just want to make sure that a youtube nonstop current of videos doesn't start Or at least that it has it's own place, like the programming (and not only) music thread.
    1 point
  29. not correct From the docs $options = array( 'quality' => 90, 'upscaling' => false, 'cropping' => 'southeast' ); $img = $image->size($x, $y, $options);
    1 point
  30. Hi everyone! I'd like to introduce PassiveCron - a module, which allows developers to schedule cronjobs - to you. This will be Conclurer's second Pro Module, following ProcessImageMinimize / minimize.pw. PassiveCron is available now as a beta version. What is it going to do? Have you ever been in a situation, in which ProcessWire ran out of PHP's max_execution_time, because you're doing cool tasks like resizing dozens of images using PIM? Or have you noticed site load performance issues when doing a lot of tasks simultaneously? PassiveCron will fix this by giving developers the ability to schedule tasks to future and / or repeating points in time run tasks asynchronously Isn't this exactly the same as LazyCron? No. LazyCron runs your tasks synchronously as your page loads. So running larger tasks will decrease your page's load performance. Instead of this, PassiveCron is able to run those tasks separately from your site loads, thanks to our new web service cron.pw, which will be released together with PassiveCron. How can I use this in my site / module? We will bundle PassiveCron with an easy-to-use API. Let's say you want to call a specific module action tomorrow at 8:00 am: $cron->tomorrow->at('8:00 am')->run('Class', 'Method'); Or do this specific cleanup task, every night at 3:00 am: $cron->every("day")->at("3:00 am")->run("Class", "Method"); Or just run this one large task asynchronously: $cron->run("Class", "Method"); How much will it cost? We are planning to give every ProcessWire site 200 task executions / day for free. For unlimited task executions per site, it'll be around 5€ (pay once, use forever). During the beta period, no payments will be available. Features overview Easy-to-use API for asynchronous task execution Integrable into existing modules for load time improvements No registration at cron.pw needed Pro Cache will be bypassed En- or disable PassiveCron per module Free minimize.pw background tasks Dashboard with reports per task So, what do you think? Is such a module what you need? Can you imagine additional features or do you have wishes for PassiveCron? Please tell us in the comments. Thank you very much!
    1 point
  31. On my new development I now use this tree structure: Parentpage - countries childpage hold "country"-name childpage of country-name hold province-name childpage of province-name hold city-name country field, 1st select, for country value = normal parent select > "countries" province field, 2nd select, for province name OF country selected value = custom selector > "parent=page.country' city field, 3rth select, for city name OF province selected value = custom selector > "parent=page.province'. Works great!
    1 point
  32. @djr - in case you haven't seen it yet, Ryan has added a WireDatabaseBackup class to the core: https://github.com/ryancramerdesign/ProcessWire/commit/52c09f5ef1980b7cad3876e8332254f3792e795d Maybe you can make use of this directly in your module once PW 2.5 is released.
    1 point
  33. A highly categorised site is a different beast then a textual 'animal' site. So what advanced is depends a lot from the context of your site. For a big news portal (mainly textual), I used the google search api to search the site. This way all textual content is searched, even in PDF,s. The results I get back from google (json) I store for 1 hour with markupCache to reduce requests to google. I use the urls from the results to get back to the page Objects. This way I let google do the search and ProcessWire the presentation of the results. ( showing thumbnails etc, headlines descriptions etc. ) But if you have a site with a lot of categories, highly structural. I could imagine you build a chain of selectboxes. This search is a Perfect fit for ProcessWire.
    1 point
  34. Martijn, I did not make that website and I could not open that site during the day. Flushing my dns resolver cache and changing my dns settings in my network connection to google, telefonica, or vodafone, and also resetting our router here: did not help. I read your post now and while trying again to my surprise I can open that site. That's too bad because now I will never know what really caused the problem. About cookies, yes I can see the slider now too ha ha good one Oh and did you know there is a "hollandse winkel" here and every now and then I go there to buy some "dropjes" - "stroopwafels" and "pindakaas" from holland
    1 point
  35. Maybe define it on the init and not ready. Bootstrap doesn't trigger ready as its not web context.
    1 point
  36. Hi everyone! It's been a little bit of time since the update - the last month was very busy, but we are on the track and planning to release the first public beta version of PassiveCron / cron.pw in the next week. Like the previous previews, I want to share with you two additional features of cron.pw. 1) Dashboard Just like minimize.pw, cron.pw comes with a Dashboard, on which you can control every background task and upgrade your plan. It looks a lot like minimize, although it's blue this time ;-) 2) Task Reports cron.pw lets you take a look at the history of every module's tasks and their executions. This allows you to check out - if necessary - if a certain task has been executed correctly. ... and to enhance your development abilities, cron.pw lets you also inspect every task in detail, including transmitted request parameters and response output. Thank you in advance for your feedback!
    1 point
  37. this is awesome! made something like this couple of weeks ago myself but it's really basic at the moment I made a little JS bookmarklet for sharing things to PW but jealous for your chrome app main thing why I stopped is because I need to have a simple sharing option from my mobile (android) was just looking for a wrapper app or something because I'm not going to start digging into app programming at the moment Probably I'll just use the bookmarklet on mobile as well Ah I made the sharer saving the bookmark directly when calling it, so the window is more for editing and deletion if needed thought it's faster, like pressing the star in Chrome
    1 point
  38. Hi again, just as promised: I'm going to give you a glance at two additional features of PassiveCron. 1. Pro Cache Bypass Unlike LazyCron, which is executed parallel to page loads, PassiveCron will be able to execute tasks even while Pro Cache is turned on. So you are able to execute tasks while having great load performance thanks to Pro Cache. 2. No registration needed Unlike ProcessImageMinimize / minimize.pw, there is no need to sign up at our web service. As you install PassiveCron, it will automatically register itself anonymously at cron.pw and just work. In the next weeks we will post more information about PassiveCron and cron.pw as we develop them, so stay tuned.
    1 point
  39. Yes I can see issues with auto upgrade, though a new version available module might be useful for some. Of course, one of the things about how I use PW is that I really don't have a huge need to upgrade since the site is built round whatever the version was at the time. There is also not the pressure to upgrade unlike certain other systems.....
    1 point
  40. Hi apeisa! Thanks for your great feedback. Such good thoughts really help us, creating just the service, developers want and need. I totally agree with you. Minimize.pw was our first step in the ProcessWire ecosystem. We learned a lot from it, especially creating performant web services, that just work. With things like replication and auto-failover, I think we can guarantee a 99% working service. In the coming days, I'll post more information about how the service is going to work. And opposite to ProcessImageMinimize / minimize.pw, PassiveCron / cron.pw will have an extended open beta period before the first final release. We want to help web developers creating the site with everything they imagine, so this is the way to go. On this one, I'm also right there with you. If everything works fine - and I do think so - we have great ideas to follow up for large projects' needs.
    1 point
  41. I recently completed a website that had a very large gallery requiring multiple albums (categories) and 100+ images per album with pagination. The solution I developed accomplishes this with just 2 templates (gallery-index and gallery-album) and a single multi-image field for each album, allowing for quick, mass upload of images*. One of the great things about ProcessWire is that you can custom build something like an image gallery with just the tools that the template system and API provide out of the box, without going in search of modules. Once we have the basic templates set up, we will use the excellent FancyBox jQuery script/plugin to add some slick Javascript "lightbox" functionality on top of it. The gallery will still work without FancyBox or with Javascript disabled; it will simply fall back to opening each image in a blank page. So, without further ado... 1. Create a file named gallery-index.php in your site/templates/ folder with the following code. This will be the main page of your gallery. The code simply loops through all of the photo albums that are children of your main gallery page and uses the first image in the album as the cover photo: <? include("./head.inc") ?> <? // Configure thumbnail width/height $thumbWidth = 250; $thumbHeight = 250; // Create an array of the child pages that use the gallery-album template $albums = $page->children('template=gallery-album'); ?> <h2><?= $page->title ?></h2> <div class="gallery"> <ul class="gallery-row row"> <? if(count($albums) > 0) { foreach($albums as $album) { // Grab the first image from the album and create a thumbnail of it $thumb = $album->images->first()->size($thumbWidth, $thumbHeight); ?> <li class="col span4"> <div class="gallery-album photoShadow"> <a href="<?= $album->url ?>" class="gallery-albumThumb" title="<?= $album->title ?>"> <img src="<?= $thumb->url ?>" alt="<?= $thumb->description ?>" /> <h4 class="gallery-albumTitle"><?= $album->title ?></h4> </a> </div><!-- /gallery-album --> </li><!-- /col --> <? } } ?> </ul><!-- /gallery-row --> </div><!-- /gallery --> <? include("./foot.inc") ?> 2. Add the gallery-index template in the ProcessWire admin under Setup->Templates. This template does not require any fields, although you may want to add a body field for outputting additional content to the page. 3. Create a file named gallery-album.php in your site/templates/ folder. This template will be used to both hold and display the images in your albums. Here we will be loading the fancybox plugin as well, so make sure you've downloaded it here: http://fancyapps.com/fancybox/ and uploaded the /fancybox/ folder to your site/templates/scripts/ folder. We are appending the fancybox files to the $config->scripts and $config->styles array before outputting them in our head.inc file so that we're only loading that code on the album pages. So make sure you are outputting those arrays in the <head></head> section of your head.inc file along with your other scripts & styles, like so: <? foreach($config->scripts as $file) { ?><script type="text/javascript" src="<?= $file ?>"></script> <? } ?> <? foreach($config->styles as $file) { ?><link rel="stylesheet" type="text/css" href="<?= $file ?>" /> <? } ?> Please note that you will also have to include jQuery in your head.inc file before your other scripts, if you're not already including it. So here is our gallery-album.php. Notice also that we are calling the FancyBox script and customizing some of its options at the bottom of the file: <? $config->styles->append($config->urls->templates . "scripts/fancybox/jquery.fancybox.css"); $config->styles->append($config->urls->templates . "scripts/fancybox/helpers/jquery.fancybox-thumbs.css?v=1.0.7"); $config->scripts->append($config->urls->templates . "scripts/fancybox/jquery.fancybox.pack.js"); $config->scripts->append($config->urls->templates . "scripts/fancybox/helpers/jquery.fancybox-thumbs.js?v=1.0.7"); // Configure thumbnail width/height & number of photos to display per page $thumbWidth = 150; $thumbHeight = 150; $imagesPerPage = 32; // Make ProcessWire pagination work on the images field (see for full explanation of this) $start = ($input->pageNum - 1) * $imagesPerPage; $total = count($page->images); $images = $page->images->slice($start, $imagesPerPage); // Create a new pageArray to give MarkupPagerNav what it needs $a = new PageArray(); // Add in some generic placeholder pages foreach($images as $unused) $a->add(new Page()); // Tell the PageArray some details it needs for pagination $a->setTotal($total); $a->setLimit($imagesPerPage); $a->setStart($start); include("./head.inc") ?> <?= $a->renderPager() ?> <div class="upOneLevel"><a href="<?= $page->parent->url ?>">← Albums</a></div> <h2><?= $page->title ?></h2> <div class="album"> <ul class="album-row row"> <? if(count($images) > 0) { foreach($images as $image) { $thumb = $image->size($thumbWidth, $thumbHeight); ?> <li class="album-photo darkenOnHover col span3"> <a href="<?= $image->url ?>" rel="fancybox-gallery" class="fancybox" title="<?= $image->description ?>"> <img src="<?= $thumb->url ?>" alt="<?= $thumb->description ?>" /> <!-- Uncomment this line if you want descriptions under images <p class="album-photoDescription"><?= $image->description ?></p>--> </a> </li> <? } } ?> </ul><!-- /album-row --> </div><!-- /album --> <div class="group"><?= $a->renderPager() ?></div> <script type="text/javascript"> $(document).ready(function() { $(".fancybox").fancybox({ prevEffect : 'elastic', nextEffect : 'elastic', loop : false, mouseWheel: true, helpers : { title : { type: 'outside' }, thumbs : { width : 100, height : 60 } } }); }); </script> <? include("./foot.inc") ?> 4. As we did before, add the gallery-album template in the ProcessWire admin. Assign the images field to it, and go into the URLs tab and make sure Page Numbers are allowed. 5. Create a page in the ProcessWire admin for the gallery index using the gallery-index template. You'll probably want to give it a title like "Gallery". 6. Underneath your Gallery page, create child pages that use the gallery-album template, one page for each album you want to create. Name them however you'd like. 7. Go into each album page you created and populate the Images field with your images. Just drag-and-drop. It's as simple as that! If you want to add a description for each image, you can also add it here. If you have more than 32 images (or whatever value you set the $imagesPerPage variable to), the pagination will kick in and split the album into multiple pages. 8. Finally, add in the CSS. The CSS is really up to you, but I'm including a good starting point below. This includes a handy responsive grid system I built for my sites, as well as a .photoShadow class I developed which gives your album covers a cool 3D Polaroid look using pure CSS. /********* Helper Classes **********/ .row:after, .group:after { content: ""; display: block; height: 0; clear: both; visibility: hidden; } .row { ; /* Remove left gutter */ margin-top: 0; margin-right: 0; margin-bottom: 0; padding: 0; zoom: 1; /* IE7 */ position: relative; } .col { display: block; float:left; margin-left: 2%; /* Gutter size */ margin-top: 0; margin-right: 0; margin-bottom: 0; padding: 0; zoom: 1; width: 95.99999999996%; } .span1 {width: 6.33333333333%;} .span2 {width: 14.66666666666%;} .span3 {width: 22.99999999999%;} .span4 {width: 31.33333333332%;} .span5 {width: 39.66666666665%;} .span6 {width: 47.99999999998%;} .span7 {width: 56.33333333331%;} .span8 {width: 64.66666666664%;} .span9 {width: 72.99999999997%;} .span10 {width: 81.3333333333%;} .span11 {width: 89.66666666663%;} .span12 {width: 97.99999999996%;} .photoShadow { position: relative; border: 5px solid #fff; background: #fff; -moz-box-shadow: 0px 0px 2px #ccc; -o-box-shadow: 0px 0px 2px #ccc; -webkit-box-shadow: 0px 0px 2px #ccc; -ms-box-shadow: 0px 0px 2px #ccc; box-shadow: 0px 0px 2px #ccc; } .photoShadow:before { z-index: -1; content: ""; display: block; position: absolute; width: 104%; height: 16px; bottom: -5%; left: -2%; overflow: hidden; border-radius: 50% 50% 0 0; box-shadow: inset 0px 8px 5px #999; } .darkenOnHover { opacity: .8; -webkit-transition: opacity .2s; -moz-transition: opacity .2s; -ms-transition: opacity .2s; -o-transition: opacity .2s; transition: opacity .2s; } .darkenOnHover:hover { opacity: 1; -webkit-transition: opacity .1s; -moz-transition: opacity .1s; -ms-transition: opacity .1s; -o-transition: opacity .1s; transition: opacity .1s; } /********** Blocks **********/ .gallery { } .gallery-album a:hover { text-decoration: none; } .gallery-albumTitle { font-size: 1.1em; text-align: center; margin: .2em ; } .gallery-album { -webkit-transition: all .2s; -moz-transition: all .2s; -ms-transition: all .2s; -o-transition: all .2s; transition: all .2s; } .gallery-album:hover { -webkit-transition: all .2s; -moz-transition: all .2s; -ms-transition: all .2s; -o-transition: all .2s; transition: all .2s; -webkit-box-shadow: 0 0 3px #555; -moz-box-shadow: 0 0 3px #555; -ms-box-shadow: 0 0 3px #555; -o-box-shadow: 0 0 3px #555; box-shadow: 0 0 3px #555; } .album-photo img { margin-bottom: 6px; border: 1px solid #ddd; } .upOneLevel { font-size: 1.1em; margin-bottom: .4em; } .upOneLevel .icon-circle-arrow-left { font-size: 1.5em; margin-right: .4em; } .upOneLevel a:hover { text-decoration: none; } .MarkupPagerNav { margin: 1em 0; font-family: Arial, sans-serif; float: right; } .MarkupPagerNav li { float: left; list-style: none; margin: 0; } .MarkupPagerNav li a, .MarkupPagerNav li.MarkupPagerNavSeparator { display: block; float: left; padding: 2px 9px; color: #fff; background: #2f4248; margin-left: 3px; font-size: 10px; font-weight: bold; text-transform: uppercase; } .MarkupPagerNav li.MarkupPagerNavOn a, .MarkupPagerNav li a:hover { color: #fff; background: #db1174; text-decoration: none; } .MarkupPagerNav li.MarkupPagerNavSeparator { display: inline; color: #777; background: #d2e4ea; padding-left: 3px; padding-right: 3px; } I think that's it! Just make sure you're including the CSS file in your head.inc inside the <head></head> tags and you should be all set. If you come across any issues trying to implement the above (or find any of it confusing) please let me know below. Everyone is coming from different backgrounds and different experience levels. And if you find this tutorial useful, please feel free to let me know as well * I should mention that although it is possible to create galleries in Processwire where each image is represented by its own page (and, as Ryan has mentioned, is often preferable since it is ultimately more scalable), sometimes the ease of using a single image field (which can upload and decompress zip files of images in mass) simply outweighs any drawbacks. If I had to create this gallery with the 1-image-per-page method, it would have taken hours to upload all of the images one-by-one without some sort of additional programming to automate the process.
    1 point
  42. I already built something kind of similar: http://processwire.com/talk/topic/4209-dark-business-10/
    1 point
  43. LanguageLocalizedURL module Localized URL generator and parser You can find the last version here: http://modules.proce...-localized-url/ Or from the repository on github: https://github.com/m...e-localized-URL This module is useful to generate localized url using the language code as first 'folder', and then the localized titles of the nested pages: (removed previous instructions to prevent double maintaining.) See more infos in readme of the module with instruction and informations. https://github.com/m...aster/README.md
    1 point
  44. Fancy Admin Mode Just had a little funwith fancybox iframes, and created a little module that opens all admin links (topnav links, edit, view, new, copy actions) except "Pages" screen and "Site", "Search" in a FancyBox, so you'll never leave the page tree. It even works with inherit editing child pages. Download: https://github.com/s.../FancyAdminMode Little screencast to se it in action:
    1 point
  45. Methinks this... 'url' => "./$event[id]", // event ID is the url segment ); return json_encode($json); // <<<< wrong data? } ...should be this... 'url' => "./$event[id]", // event ID is the url segment ); return json_encode($items); // <<<< right data? }
    1 point
×
×
  • Create New...