Leaderboard
Popular Content
Showing content with the highest reputation on 02/11/2024 in all areas
-
I've always enjoyed PHP, but never really enjoyed Javascript until I started using jQuery. I continue to enjoy using jQuery much more than vanilla Javascript. Using jQuery has not always been about filling in a gap of Javascript so much as it has been about preferring and even enjoying the interface. It’s fun to use, and Vanilla JS not as much, at least to me. PW has some of its API inspired by jQuery, and together they have always felt just right. When it comes to open source stuff, I like to focus on tools that I enjoy using, as that's what keeps me interested and keeps me going. If we were to take jQuery out of the admin, it would be a huge amount of work, and then leave something that would be less interesting to maintain. So I’m not so enthusiastic about taking jQuery out of the admin. Where I would be enthusiastic about it is with front-end modules that might currently be using on jQuery and don’t necessarily need to. Take FormBuilder and LoginRegisterPro as examples (though there are many more). Perhaps those modules don’t need to require jQuery unless one of the Inputfield modules in use requires it. That way, modules like that aren’t introducing jQuery in an environment where it might not otherwise be in use. And maybe there are some Inputfield modules that currently use jQuery and don't need to. Since Inputfield modules can be either admin or front-end, it makes sense to use vanilla JS when possible with those. So yes, I'm all for reducing or removing the use of jQuery in spots, but not so interested in removing it from the admin.11 points
-
If I was the vendor of a product that currently has 77% market penetration I think I would keep going on. It is the most popular JavaScript library by a staggering margin: With so many happy customers it's fantastic news that jQuery continues to be updated and supported, and I don't see how its use in the PW core disadvantages users in any way.5 points
-
I've gone ahead and added this to the DEV branch! Please see2 points
-
2 points
-
Yeah, I've noticed that too and I think it's a bug. I normally select the "except when superuser" option and it does work then but this shouldn't be necessary. I opened an issue here: https://github.com/processwire/processwire-issues/issues/18792 points
-
Makes sense to update to jQuery 4 once it's available and stable, but I must admit that when I read that article my first thought was "holy crap, they are still going on?" ? Serious question to @ryan: what's your take on jQuery these days, do you still see it as something we will be, or should be, relying going forward? I'm not trying to push any agenda here, but I am wondering if you'd be open to perhaps starting to migrate more of ProcessWire's core code to vanilla JavaScript. I'm also not going to go into the "but what about Vue / React / Alpine / HTMX / insert-name-of-any-other-library-or-framework-here" topic at this point; that's a whole different subject. Also: all modern libraries are advocating the use of native JavaScript API's instead of "framework specific magic" anyway, so vanilla JS would be a good first step towards something new. In my opinion (which I've probably voiced here on the forums a few times already) jQuery is now largely obsolete. And I'm saying this as a former fan — it was amazing back in the days when native JS API's were very crude and lacking. Today it's more of a problem. For those that don't know what I'm speaking about, one example is the way jQuery handles events: the API is nice, but also hacky and non-standard, leading to the fact that in order to combine (standard) JS events with jQuery events you essentially need yet another library. (And vendor lock-in, intentional or not, is not a good thing.) Personally I find myself reaching for jQuery in pretty much one specific case: many third party plugins/libraries still rely on jQuery. This is less of an issue every year as devs keep moving forward, but there are still many popular plugins that do require jQuery. For every need there is a non-jQuery solution, but it can take a bit of work to find / migrate to. Some things are admittedly more difficult to replace, and one of those is jQuery UI. But since jQuery UI is already in "maintenace updates only" mode, replacing it is likely something that has to be done at some point. (Also... form serialization. That is something they did really well. And no, vanilla JS FormData is not a direct replacement ?) Sorry for the long rant, but I just felt that this needed a bit of context. I for one would be happy to submit PR's etc. that would move us towards fewer dependencies for jQuery if that's something that'd be beneficial for the project. I believe it would be, but that's just me ?2 points
-
Hello folks! ? First of all... I'm not a PHP developer, so this project is quite challenging. Please don't be too hard on me. ? Over the last weeks i was working on my very first module, which should provide an appointment booking function including a calendar in the frontend and create all the necessary pages. You can manage locations, employees, services and bookings. Currently the dependencies for the frontend are jQuery, jQuery validate, Bootstrap 5 (only design and error toast) and twig template. This is how it currently looks like. Frontend: Backend: It's actually only meant to be a fun project and i am not sure if i will ever finish it. However maybe at some point i will just make a public github repository. As far as I know, there is no such module yet and I think it could be very helpful for some. If i have the time and motivation... this is still on my to do list: Frontend: Functionality to select "any" employee and show free timeslots accordingly Day not selectable / blocked if no timeslots available Check if timeslot is still free on form submit (to avoid double bookings) Backend: Add working times in backend (currently static array in the code) Add selection for holidays (for location or in general and for employees, currently as static array in the code) Functionality to send email to the user if the booking is rejected or accepted Selection of weekdays that should always be blocked1 point
-
Like last week, this week the focus has been on adding feature requests from our processwire-requests repository. Though I'd like to give it another week before bumping up the version number. Rather than repeating all that was added here, please see the dev branch commit log, which covers them all, several with more detailed notes in the commits. The biggest added feature request was likely the API updates for getting/setting multi-language values, but there are several others as well. I was excited to see the new jQuery 4.0.0 release this week, which we'll no doubt be upgrading soon (or once out of beta). Here's a quote from the intro of their new post: Some parts of ProcessWire's API were originally inspired by jQuery. It's always nice to see progress there with new versions, especially a new major version. Thanks for reading and have a great weekend!1 point
-
RockMigrations now has a feature to easily make sure to fire certain migrations only once: $rm->once( "2024-02-11: Simple demo of the new once() feature", function() { bd('I will be executed only once!'); } ); Extensive docs are already in place: https://github.com/baumrock/RockMigrations/tree/dev/docs/once1 point
-
FieldtypeGrapick The FieldtypeGrapick module for ProcessWire wraps the Grapick vanilla javascript gradient creation UI and extends the feature set to include settings beyond what the original library allowed for. The original javascript library was written by Artur Arseniev. Aside from requiring ProcessWire 3, the requirements are: PHP >= 7.2 or >= PHP 8.0 This module makes use of the Spectrum colorpicker library. Repeater and RepeaterMatrix items are supported. There is a gremlin in RepeaterPageArray iteration that causes warnings. I've created an issue for it. It does not impact performance. CssGradient Object The FieldtypeGrapick field value is a CssGradient object. $gradient = new CssGradient( $options=[] ); where $options is a list of properties: $options = [ 'style' => 'linear', 'stops' => 'FFFFFFFF^0|FF000000^100', 'angle' => '180', 'origin' => '', 'size' => '', ]; Properties The CssGradient style by default is linear, 180deg, with a white opaque stop at 0% and a black opaque stop at 100%. style $gradient->style: gives you the dropdown value of the style of gradient. Setting this automatically uses the correct settings for the css function and shape parameter as required. Possible values: 'linear' = Linear 'radial-circle' = Radial Circle 'radial-ellipse' = Radial Ellipse 'repeating-linear' = Repeating Linear 'repeating-radial-circle' = Repeating Circle 'repeating-radial-ellipse' = Repeating Ellipse 'conical' = Conical 'repeating-conical' = Repeating Conical Any other value defaults to linear. Depending on the type of gradient selected, origin, angle, and/or size will come into play. The stops are always used to determine the order of colors and their relative locations according to the limitations of each style. origin $gradient->origin: gives you the dropdown value of the origin of the gradient as it applies to radial and conical gradients. The format is X%_Y% if for some reason you want to set a custom X/Y origin. The dropdown values are typically what I find useful for most applications, but I am open to adding other presets. '-100%_-100%' = Far Top Left '50%_-100%' = Far Top Center '200%_-100%' = Far Top Right '-50%_-50%' = Near Top Left '50%_-50%' = Near Top Center '150%_-50%' = Near Top Right 'top_left' = Top Left 'top_center' = Top Center 'top_right' = Top Right '-100%_50%' = Far Middle Left '-50%_50%' = Near Middle Left 'center_left' = Middle Left 'center_center' = Center 'center_right' = Middle Right '150%_50%' = Near Middle Right '200%_50%' = Far Middle Right 'bottom_left' = Bottom Left 'bottom_center' = Bottom Center 'bottom_right' = Bottom Right '-50%_150%' = Near Bottom Left '50%_150%' = Near Bottom Center '150%_150%' = Near Bottom Right '-100%_200%' = Far Bottom Left '50%_200%' = Far Bottom Center '200%_200%' = Far Bottom Right angle $gradient->angle: gives you the angle in degrees of the gradient as it applies to conical and linear gradients. Should be a value between -360 and 360. Measured in degrees. size $gradient->size: gives you the size - of what depends on the type of gradient. For radial ellipse gradients, at applies a size of XX% YY% using the value. So 25 would represent a size of 25% width, 25% height of the container. For repeating linear, conical and radial gradients, the repeating gradient will apply the percentage stops as a percentage of this value. In the case of repeating linear gradients, if you have your stops at 0%, 10%, 50% and 100% and your size is 200, the stops in the calculated rule will be at 0px, 20px, 100px and 200px. For repeating ellipse and conical gradients, a similar calculation is performed, but the units are %, not px. You can get some crazy tartan backgrounds out of this if you stack your gradients up and are creative with transparencies. stops $gradient->stops: gives you the current stop settings in a AARRGGBB^%% format, with each stop separated by a '|' character on a single line. You can role your own gradient ruleset by modiying this property prior to getting the rule. When using the UI you can also reveal the Stops inputfield and change the stops manually, however you will need to save to see the changes in the UI. rule $gradient->rule: gives you the stored rule that is calculated prior to the field value being saved to the database from the UI. Of course, if you are ignoring the UI altogether and just using the class, you will probably ALWAYS want to call getRule() rather than use this property. If you render the field, it will return the rule as a string. Methods The CssGradient has a single public method that is mostly useful when manipulating an instance of the CssGradient class. getRule(string $delimiter) $gradient->getRule(): calculates the rule based on the properties or options you have set for the field. This automatically runs if you have set an $options array and populate the rule property, but if you decide later that you need to change the properties of the object, you'll want to manually call it again to recalculate it. For example, if you programmatically change the stops, you will want to run the getRule() method rather than just grab the rule property. If you pass a string, the first character will be used as an ending delimiter. If you pass an empty string, no ending delimited will appear. By default, the rule is output with a semicolon. Grapick UI The Grapick UI is relatively straightforward. Clicking the (x) handle above a gradient stop removes the stop from the gradient calculation. If you remove all the stops, the bar is transparent. Clicking on the gradient bar sets a stop conveniently set to the color you click on. Clicking on the colorpicker box below the stop line allows you to select the color and transparency of the stop. Click and drag the stop line itself to modify the gradient. Making changes to any of the controls on the field will update the preview and the calculated rule in real-time. You can always cut and paste this rule and use it in your designs elsewhere if you want. Likewise, if you open the Stops inputfield area (which is collapsed by default) you can directly alter the colors and code using a color in an AARRGGBB format and adjust the stop with a number from 0-100. It's fun to play with - experiment with hard and soft lines, size and origin - many interesting effects are possible. Do not forget that the alpha slider is also available. Examples $grk = new CssGradient($options=[ 'style' => 'linear', 'origin' => '', 'angle' => 270, 'stops' => 'FF8345E4^0|FF5A08DB^25|FF2C046B^97|FF000000^100', 'size' => '', ]); echo $grk->getRule(); will give you: linear-gradient(270deg, rgba(131, 69, 228, 1) 0%, rgba(90, 8, 219, 1) 25%, rgba(44, 4, 107, 1) 97%, rgba(0, 0, 0, 1) 100%); while echo $grk->getRule(''); will give you linear-gradient(270deg, rgba(131, 69, 228, 1) 0%, rgba(90, 8, 219, 1) 25%, rgba(44, 4, 107, 1) 97%, rgba(0, 0, 0, 1) 100%) and echo $grk->gerRule(','); will give you linear-gradient(270deg, rgba(131, 69, 228, 1) 0%, rgba(90, 8, 219, 1) 25%, rgba(44, 4, 107, 1) 97%, rgba(0, 0, 0, 1) 100%),1 point
-
1 point
-
So I tried this method but it still puts in the parameter if it's empty: I think the solution is to use the notes to convey what the default value will be if empty, but also have a way not to add it into the markup if it's empty - perhaps some sort of __omit_empty override, so default_term__omit_empty parameter since we don't want to make assumptions for everyone else using this already? That way for these specific cases I can also add a note warning them that if it's left empty it will defer to the defaults that can change over time so the content editor has had fair warning. EDIT again - my brain is not in gear today because I can simply do this myself and check for an empty value ? So this is a non-issue now - I can work with this easily by doing: if(strlen($default_term) === 0) { // use the default value in the PHP code } And using strlen because the value might actually be a zero of course. Edit #237: Here's my solution: Attributes: default_amount default_amount__notes=Leave blank to default to 150000 - default may be changed in future default_term default_term__notes=Leave blank to default to 25 years - default may be changed in future default_type default_type__type=select default_type__options=Repayment|Interest Only default_type__notes=Leave blank to default to Repayment default_rate default_rate__notes=Leave blank to default to 4% - default may be changed in future And defaults are now set in the PHP code, overridden with the HannaCode selections if any values are set <?php namespace ProcessWire; $types = ['Repayment' => 'repayment', 'Interest Only' => 'interest']; $default_amount = strlen($default_amount) > 0 ? $default_amount : 150000; $default_term = strlen($default_term) > 0 ? $default_term : 25; $default_type = strlen($default_type) > 0 ? $types[$default_type] : 'repayment'; $default_rate = strlen($default_rate) > 0 ? $default_rate : 4; echo $files->render('partials/calculators/mortgage', ['default_amount' => $default_amount, 'default_term' => $default_term, 'default_type' => $default_type, 'default_rate' => $default_rate]);1 point
-
Yeah I think that would be a great solution! It would be there if needed and does not take up space if not. If you added the "uk-tooltip" attribute it would instantly show as a https://getuikit.com/docs/tooltip which appears instantly and looks nicer. This would only work if someone has uikit on the frontend, but if not, it does not hurt again, as it will fallback to the regular "title" attribute of the browser. <span title="Enable Tracy | 160.1ms" uk-tooltip>icon</span>1 point
-
I didn't mind the boilerplate required to add a new panel (especially since there is an example HelloWorld panel available), and it is definitely nice to have essentially unhindered access to native Tracy extensions, but it also wouldn't hurt to have a hookable method as suggested by Bernhard (if feasible). If adding new panels was that easy, it could be more tempting to add site-specific panels etc. ? (Of course this should be an addition / alternative to current approach, not a replacement.) Just for context, here's the discussion that led to what we currently have:1 point
-
Hey All, I thought I'd jump on here and share my first 3 ProcessWire sites! LatticeWork (https://www.latticeworkinc.com/) - This one is live but still being actively developed in preparation for targeting an international audience (so current translations need auditing and it's not yet GDPR-compliant). The multilingual capabilities offered by ProcessWire, in contrast to WordPress, were the catalyst for starting my PW journey. The added performance that will be necessary as we deprecate some international sites and push everyone here was another decision driver for choosing PW. Obviously many thanks to @ryan and other core contributors for such an incredibly refined core product that regularly surprises me with features and functionality that I didn't know I was missing. Additional thanks go to @FireWire for the Fluency add-on, @Mike Rockett for Jumplinks, @Wanze for SEO Maestro, @teppo for Search Engine, and again Ryan for Pro Fields. These were invaluable. The Mart Group (https://www.martgroup.com/) - This site was my second to build with ProcessWire, though it was completed first due to its smaller size. In addition to all the prior thanks, I really appreciated RockFrontend by @bernhard while working on this one. Lori H. Cole (https://www.editsbylori.com/) - I probably wouldn't mention this single-page site I built as a favor, except to point out that PW is so lean and easy to work with I was able to give the client the ability to edit their own site without much server overhead or added development time. I did the front-end development work on these, which as a designer/animator hasn't historically been an area I'm comfortable in. ProcessWire has been such a delight to use that it has re-kindled my interest in working more with code. So, in time I hope to get more creative with the front-end coding as well. Thanks!1 point
-
Thx! I've updated the link. It was working for me so I would have not realised! Github changed something with embedding images from issue comments ?1 point
-
1 point
-
I just pushed an update to the DEV branch that I really believe should be part of the core: That means you can still edit all settings on the module config screen, but you can override any setting in config.php like this: <?php $config->rockmigrations = [ 'syncSnippets' => true, ]; My module now shows that changes in a nice and easy way (bubble 2) and it also comes with links to edit a setting directly (1), which will scroll to the field in question ? What do you think, would this be helpful for your modules as well? Should this be part of the core?1 point
-
Looks like now is a great time to dive back in!1 point
-
This week I was wrapping up the client project I mentioned last week (just launched today here), but did get some updates added to the core as well. Primarily the addition of some smaller feature requests. One of the features added is a README.md and CHANGELOG.md viewer to each module's configuration/info screen. When a module has one of those files in it, it is now viewable from within the admin. You'll see the links them at the bottom of the "Module information" section of any module's config/info screen in the admin. Other requested features added were: Support for OPTIONS, CONNECT and TRACE methods in WireHttp. And, A new hookable method in ImageSizerEngineIMagick added via a PR from Robin S. Support for <hr> elements has been added in InputfieldSelect and InputfieldSelectMultiple. It was news to me, but apparently <hr> (horizontal rule) elements are now supported by browsers between <option> tags in <select> elements, rendering a nice separator between options when you want them. So our Select inputfields now support that. To add a horizontal rule/separator, just add an option with 3 or more dashes/hyphens. Programmatically you would do a call like this when you are between options where you want the <hr> to appear: $inputfield->addOption('---'); Or, if specifying options as text (as you would with Options fields, or several other Fieldtypes), you would just enter a line with 3 or more dashes on it, and nothing else. So if we had an select where you could select a color, and we wanted to separate RGB from the other colors, we could do this on its configuration screen: R=Red G=Green B=Blue --- O=Orange P=Pink C=Cyan Thanks for reading and have a great weekend!1 point
-
I want to show a new website that I made at the beginning of this year using @bernhard's RockPageBuilder module: https://www.kurrat-terrassendaecher.de/ The client: Kurrat Terrassendächer (which translates to "Kurrat Terrace Roofs") is a dealer from germany that is specialized in building custom made terrace roofings, awnings and solar protection. The goal: The customer had a old website that was used as a basis for the new design. The new website should offer a more "catalogue-like" look with lots of information for the customer. Fortunately the client had access to high quality images of the products that really make the whole website shine. The page features three main categories: 1. Terrace Roofs 3. Solar Protection 3. Winter Gardens Each category subpage is made of modular content blocks: The user is able to make custom page layouts using these blocks directly in the frontend. With the RockPageBuilder module it is super fun an super straight forward to work with these content blocks. If you don't know this module yet I highly recommend to check it out! If you like the RepaterMatrix you will love this module. It is far superior IMHO! Inserting a content block looks like this: It is also possible to edit content on-the-fly in the frontend: As with the RepeaterMatrix each content block an also be added end edited in the backend of the page: Here you see the list of content blocks used on the home page. To edit a block, just click on it and you can edit it just like using the RepaterMatrix. Screenshots from the website: Modules used for this page: - RockFrontend (for asset bundling, minifying, etc.) - RockPageBuilder (instead of RepeaterMatrix! For building and editing all content in the frontend) - WireMailSMTP - PageImageSource (for creating webp image variations) - PrivacyWire (for cookie consent banner) - SEO Maestro - Redirects The frontend framework is UIKit1 point
-
Happy to announce the launch of the completely rebuilt San Francisco Contemporary Music Players website, using ProcessWire. https://sfcmp.org/ The previous website was a hornet's nest of disorganized content, dozens of 3rd party plugins, duct taped together within WordPress... difficult to use, time consuming and confusing to manage. And didn't look so good either. Lot of fun to rebuild this, though took several months. YOOtheme Pro and UiKit were a dream for me to work with, just love those. Made it so possible to create all of the custom sections, widgets, sliders, cards, mega menus, and so on. Don't consider myself a front-end focused web dev, so have a deep appreciation for the time, care and effort that Yoo has put into both UiKit and YOOtheme Pro. Almost no additonal CSS was needed to be written for this; the stock UiKit classes and attributes make it possible to just build things in HTML and not have to fiddle with CSS. Ryan's commercial modules played a major role in the build. ProFields, ListerPro, ProCache, and FormBuilder were all important. FormBuilder+Stripe allowed me to confidently migrate their need for a stripe checkout from some WP plugin to the clean and simple setup now using FB. ( https://sfcmp.org/donate/print-for-sale-dirge-by-hung-liu/ ) Some libraries also were of great use and value, namely PLYR for audio, and tabulator for some table display type of stuff. As always, the API was a dream to work with, many custom import scripts were created along the way to import legacy Press, Albums, Repertoire works, Program Booklets library, Players etc.. The image API is doing wonders with SRC sets, and webp images. The PW documentation site was a daily companion. This forum likewise was always a most valuable and enjoyable resource to search and rely on for solving the occasional conundrum. There is such a wealth of info here that i never found it necessary to post a question. Lastly, to underscore just how unparalleled, flexible and user-friendly the PW backend is, we had the backend training session a couple of weeks after the site was launched, and within 30 minutes, the person who will be managing the content was able to know how to create and manage concerts, blog posts, albums, press articles and more.1 point
-
Hi all, Here is one of the latest website we created for a french company renting construction machines and trucks with specialized drivers, based in Le Mans. It’s a rather simple showcase/informational website, but we aimed at making clear (and visually attractive) what is available, what is the skillset and various ways to quickly get in touch. We produced everything, from the design, pictures, illustrations down to the development (ofc). There wasn’t any website before except for social media presence and this task was a follow-up to the update of the visual identity we did. Behind the scene, on the front-end, everything is custom made: we don’t use any frameworks. On the back-end we used the usual suspects and some: TracyDebugger ❤️ FormBuilder ProCache ProFields (RepeaterMatrix, Table) Dynamic options / Select images Our own flavor of “components” Thanks for having a look!1 point
-
1 point
-
Just wanted to share what I recently used to create forms in modules and in frontend using the API and Inputfield modules PW provides and uses on its own. I think many newcomers or also advanced user aren't aware what is already possible in templates with some simple and flexible code. Learning this can greatly help in any aspect when you develop with PW. It's not as easy and powerful as FormBuilder but a great example of what can be archieved within PW. Really? Tell me more The output markup generated with something like echo $form->render(); will be a like the one you get with FormBuilder or admin forms in backend. It's what PW is made of. Now since 2.2.5~ somewhere, the "required" option is possible for all fields (previous not) and that makes it easier a lot for validation and also it renders inline errors already nicely (due to Ryan FormBuilder yah!). For example the Password inputfield already provides two field to confirm the password and will validate it. De- and encryption method also exists. Or you can also use columns width setting for a field, which was added not so long ago. Some fields like Asm MultiSelect would require to also include their css and js to work but haven't tried. Also file uploads isn't there, but maybe at some point there will be more options. It would be still possible to code your own uploader when the form is submitted. Validation? If you understand a little more how PW works with forms and inputfields you can simply add you own validation, do hooks and lots of magic with very easy code to read and maintain. You can also use the processInput($input->post) method of a form that PW uses itself to validate a form. So getting to see if there was any errors is simply checking for $form->getErrors();. Also the $form->processInput($input->post) will prevent CSRF attacks and the form will append a hidden field automaticly. It's also worth noting that processInput() will work also with an array (key=>value) of data it doesn't have to be the one from $input->post. Styling? It works well if you take your own CSS or just pick the inputfields.css from the templates-admin folder as a start. Also the CSS file from the wire/modules/InputfieldRadios module can be helpful to add. And that's it. It's not very hard to get it display nicely. Here an code example of a simple form. <?php $out = ''; // create a new form field (also field wrapper) $form = $modules->get("InputfieldForm"); $form->action = "./"; $form->method = "post"; $form->attr("id+name",'subscribe-form'); // create a text input $field = $modules->get("InputfieldText"); $field->label = "Name"; $field->attr('id+name','name'); $field->required = 1; $form->append($field); // append the field to the form // create email field $field = $modules->get("InputfieldEmail"); $field->label = "E-Mail"; $field->attr('id+name','email'); $field->required = 1; $form->append($field); // append the field // you get the idea $field = $modules->get("InputfieldPassword"); $field->label = "Passwort"; $field->attr("id+name","pass"); $field->required = 1; $form->append($field); // oh a submit button! $submit = $modules->get("InputfieldSubmit"); $submit->attr("value","Subscribe"); $submit->attr("id+name","submit"); $form->append($submit); // form was submitted so we process the form if($input->post->submit) { // user submitted the form, process it and check for errors $form->processInput($input->post); // here is a good point for extra/custom validation and manipulate fields $email = $form->get("email"); if($email && (strpos($email->value,'@hotmail') !== FALSE)){ // attach an error to the field // and it will get displayed along the field $email->error("Sorry we don't accept hotmail addresses for now."); } if($form->getErrors()) { // the form is processed and populated // but contains errors $out .= $form->render(); } else { // do with the form what you like, create and save it as page // or send emails. to get the values you can use // $email = $form->get("email")->value; // $name = $form->get("name")->value; // $pass = $form->get("pass")->value; // // to sanitize input // $name = $sanitizer->text($input->post->name); // $email = $sanitizer->email($form->get("email")->value); $out .= "<p>Thanks! Your submission was successful."; } } else { // render out form without processing $out .= $form->render(); } include("./head.inc"); echo $out; include("./foot.inc"); Here the code snippet as gist github: https://gist.github.com/4027908 Maybe there's something I'm not aware of yet, so if there something to still care about just let me know. Maybe some example of hooks could be appended here too. Thanks Edit March 2017: This code still works in PW2.8 and PW3.1 point
-
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
-
[quotamos]This is really interesting stuff and I'm learning so much from it. I've already tested Soma's code and it works very well. Is there a way of configuring $form->render() so that it outputs different html (divs for ul/li etc.)? [/quotamos] you.can usage. $form->setMarkup(); und $form->setClasses(); two.set markups und html caresses. see.eliamos /wire/core/InputfieldWrapper.php1 point
-
Great tutorial Soma! This is the best summary of using PW's Inputfields that I've seen. I noticed you did $field->attr('id+name', 'email') so just wanted to explain what that is for those that may be unsure of the syntax. That syntax is basically saying to set the 'id' and 'name' attribute to have the 'email'. While every field needs a 'name' attribute (like in HTML) the 'id' attribute is optional… if you don't assign an id attribute, PW will make one up. If you intend to custom style a field with CSS or target it from javascript, then it's best to assign your own 'id' attribute. Otherwise, it doesn't matter. // this… $field->attr('id+name', 'email'); // …is the same as: $field->attr('id', 'email'); $field->attr('name', 'email'); // …as is this (direct reference): $field->id = 'email'; $field->name = 'email'; The advantage of using the attr() function over direct reference is that attr() can't ever collide with other Inputfield properties that might have the same name as a field attribute. It's basically your way of saying "this should definitely be an HTML attribute and not anything else." For recognized attributes like 'name' or 'value' it doesn't matter what syntax you use because an Inputfield already knows 'name' and 'value' are standard HTML attributes. But if you needed to add a custom attribute like "data-something", well then you'd definitely want to use the attr() method of setting. That attr() method should only be used for things that would actually be HTML attributes of the <input>, because they will literally end up there. So if you do an $field->attr('label', 'Hello'); you'll end up with an <input label='Hello'> in the markup, which is obviously not something that you want. That's why you assign a non-attribute property like 'label' or 'description' directly, like: $field->label = 'Something'; Last note about $attr() is that it can be used for both setting and getting attributes: $field->attr('value', 'something'); echo "The field's value is: " . $field->attr('value'); // same as: $field->value = 'something'; echo "The field's value is $field->value"; To extend your example, lets say that you wanted the 'email' and 'password' fields in a fieldset titled "About You". You would create the fieldset, and then add/append the fields to the $fieldset rather than the $form. Then you'd add the $fieldset to the $form: $fieldset = $modules->get('InputfieldFieldset'); $fieldset->label = 'About You'; $field = $modules->get("InputfieldEmail"); $field->label = "E-Mail"; $field->attr('id+name','email'); $field->required = 1; $fieldset->append($field); // append the field $field = $modules->get("InputfieldPassword"); $field->label = "Password"; $field->attr("id+name","pass"); $field->required = 1; $fieldset->append($field); $form->append($fieldset); Or lets say that you wanted those 'email' and 'password' fields to be each in their own column so that are next to each other horizontally rather than vertically. You would assign the 'columnWidth' property to both the email and password fields. In this case, we'd give them both a value of 50 to say that we want them to be a 50% width column: $field->columnWidth = 50; To jump out of tutorial mode and into idea mode: lately I've been thinking that PW should have a YAML to Inputfields conversion tool in the core (something that would be pretty easy to build), so that one could define a form like this: And create it like this (where $yaml is the string above above): $form = $modules->get('InputfieldForm'); $form->load($yaml); echo $form->render();1 point