-
Posts
17,122 -
Joined
-
Days Won
1,652
Everything posted by ryan
-
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();
- 237 replies
-
- 23
-
-
To make it even shorter, you can also do this (specify path to category): $posts = $pages->find("parent=/posts/, category=/category/events/"); Or this (specify title of category): $posts = $pages->find("parent=/posts/, category.title=Events"); To take it further, you could replace "title" above with any field present on the category template and match based on that. But I think 'title' or 'name' are probably the most common ones. If your 'category' field only exists on your posts, then technically, you could leave out the "parent=" part. Though a more specific selector tends to scale better than a less specific one (like if you re-use your category field in another template). So I do think it's worthwhile to keep it, or use $pages->get('/posts/')->children('...') like in your example. In PW 2.3 (dev branch), you can now do this as well, which would be the shortest possible alternative: $posts = $pages->find("category=events"); The above is matching the page's name field. Since there is no slash in the value "events", it assumes you are talking about the page's name rather than path or ID.
-
This is the most likely case. My memory has never been great... I'm almost as old as VI itself, heh. But I'm looking forward to giving this debug combo a try.
-
Hacking the core to have no trail slash as default
ryan replied to Adam Kiss's topic in General Support
This has been kept as a per-template setting. I opted not to make it a system wide setting because I thought it would create some support burden and make it more difficult for people to use. Every time we post an example that includes some kind of link, we'd have to qualify it with "depending on your slashes setting". I recommend sticking to slashes with your pages (defined pages) and optionally omitting slashes with non-defined pages: URL segments or page numbers. Another thing to mention is that Process modules actually require use of trailing slashes for defined pages, so don't disable trailing slashes on your 'admin' template. -
How about: $page->images->removeAll(); $page->save();
-
I didn't realize you were a VIM user too. That makes at least two of us here. I need to get setup with this debugger plugin too.
-
Thanks for getting Form Builder! You should have access to the Form Builder support board now. It doesn't actually create pages for each form, as they are all handled via URL segments. I'm not aware of any major downsides to using embed method A or B, and there are whole lot of upsides. I much prefer these iframe based embed methods because it makes the forms bulletproof -- they are fully isolated and immune to any unwanted effects from other stylesheets or scripts. The only [minor] downside I can think of is that if someone uses it without javascript, they will either see some extra whitespace at the bottom of the form, or have to use a scroll bar, depending on the form length.
-
Like you found, that function only operates on one comments field. But you can search multiple comments field using the PW 2.3 dev branch with this syntax, where a, b, c are the names of different comments fields: $pages->find("a|b|c%=some text"); This isn't supported in the current 2.2.9 stable branch. But you could always take the wire/modules/FieldtypeComments/* files from the 2.3 dev branch, to avoid moving the whole system to it yet.
-
"git clone" takes about 3 seconds from the GitHub to whatever server I install it to. No idea how it can be that fast, but it always amazes me. Doing an rsync from my localhost to a web server usually takes 20 seconds or so. And that's with all the files (not an archive). With regular old FTP, I have seen it take a long time, but it was always due to a slow FTP client or host.
-
I think we are very lucky here to have the maintainer of Textile [Netcarver] using ProcessWire. I started using Textile late in the game, but now that I use it regularly, I like it so much better than Markdown. I wish that I had bundled Textile in the PW core in addition to (or rather than) Markdown. Though if I do it now, then it'll conflict with the /site/modules/ version that anyone already has installed, so would have to come up with a different name for the TextformatterTextile modules. @netcarver, are you interested in managing the TextformatterTextile and TextformatterTextileRestricted modules? These modules basically consist of 1 function all, so there isn't really anything to maintain in them except for the classTextile.php version. If you would like to, let me know and I'll just change the ownership of the modules.processwire.com listing to you so that you can re-point it to your own repo. I'm guessing this would ensure the best consistency between the PW module and classTextile versions. Otherwise, I'm happy to keep them in my GitHub account, but figured I should offer it since you are the maintainer of Textile itself, not to mention a great PW module developer.
-
Definitely, I think this would be a good thing to do. I'd like to see (and create) more profiles (whether free or commercial). This is one area where we don't have much to offer yet, but it's so easy to do, so I think I'm going to have to dedicate some time to this once 2.3 is out.
-
Michael, the status checkboxes actually can't be moved to the content tab. But you can add your own checkbox to perform a similar function. If you create a new field called 'toggle_hidden' (or whatever you want to call it) then you would just include "toggle_hidden!=1" in all of your $pages->find() calls.
-
I agree this does seem really useful, thanks for posting it. I can think of a lot of situations where I really should be using this rather than the existing getRandom(). Rather than adding to PageArray, it seems like the value could extend further than just pages and perhaps it belongs in WireArray instead? (which would be inherited by PageArray) I'm thinking name should be: getRandomInterval(), getRandomTimed() ... or some name that alludes to what differentiates it from getRandom()?
-
Great module Teppo! Love the output and the whole idea of having this log. I will definitely keep this one installed and look forward to using it. I also like all the details you thought of, like automatic pruning of logs with LazyCron, and keeping track of non-existent users. Very nicely put together. The only thing I might like in some future version is the IP address for each login, just to help for those times when something looks suspicious. Thanks for your work in putting together this module.
-
Instead of moving these things, why not teach the client how to use the 'settings' tab? These things are kept out of the 'content' tab for a few good reasons: First is that they are things that are less likely to change after the page is created, so keeping them out of the content tab reduces the possibility of mistakes. Second is that these are fields where changes are potentially costly. You change any one of the things on this page and you could affect navigation or site structure. This differentiates them from just about any custom field, which affect the content of the page, rather than the type or structure. Third is that the fields in 'settings' are common among all pages, so it's a means of establishing a baseline consistency among all pages. Rather than the client having to figure out where 'name' or 'hidden' are, they know that no matter where they go, 'name' and 'hidden' are always in the same place. I like to tell clients: "If you know how to edit one page, you know how to edit any page", and they find a lot of comfort in that. Since ProcessWire is driven by custom fields, it's possible for the editing scenario to change a lot from template to template. As a result, it's preferable (IMO) to have the page fundamentals (the things that are always there) kept together for consistency.
-
Already Impressed, but a Bit of Trouble...
ryan replied to MatthewSchenker's topic in Getting Started
Thanks for finding it. I am correcting the master copy here. -
Trying to implement a frontend batch deleting process for editor
ryan replied to onjegolders's topic in General Support
Your if() statements will always execute since a PageArray (returned by find) would never resolve to false. The find() could be replaced with a get(), assuming there is only one page with template=student per student. Also there are some out of scope variables, and what looks to be unnecessary foreach() loops. Lastly, the 'name' could use sanitization. I rewrite it like this: if($input->post->submit) foreach($input->post->delete as $s) { $name = wire('sanitizer')->pageName($s); if(!$name || $name !== $s) continue; $dp = $pages->get("template=student, name=$name"); $du = $users->get($name); foreach(array($dp, $du) as $item) { if(!$item->id) continue; $pages->delete($item); echo "<p>$item->path has been deleted!</p>"; } } -
Btw, I just now added a replace() method to WireArray so that we'll have the above contained in 1 function for PW 2.3
-
You might try something like this for replacing an image. You add the new image (which places it at the end) then grab it and insert it before or after the old image. Then you delete the old image. $oldFile = 'myimage.jpg'; $newFile = '/some/path/or/url/myimage2.jpg'; $oldItem = $page->images->get($oldFile); $page->images->add($newFile); $newItem = $page->images->last(); // get the item just added $page->images->insertAfter($newItem, $oldItem); $page->images->delete($oldItem); $page->save();
-
This one is correct, if I'm understanding what you are trying to do correctly. If you go and uninstall module B, that is actually okay -- it won't stay uninstalled for long. Whenever you request a module via $modules->get('module name'); it goes ahead and re-installs it (if it's not installed). Here is the key: If module A installs module B and actually uses it for something or another, then module A will continue to work because module B will be installed again as soon as module A executes. This behavior is part of this dependency ecosystem. If module A requires module B, that means module B must be installed before it will let you install module A. In the above, you've got both modules requiring each other, which would prevent installation of either. This is a circular reference. I'm not surprised it timed out. Maybe I should account for that situation, but this is the first I've seen someone making a module require itself. This also seems like another kind of circular reference where the behavior would be undefined. If I'm understanding all correctly, I'm guessing you would suggest this: If module A installs module B, then module B should not be un-installable except by module A? I think this probably makes sense. Currently it does not do that, but I don't see any drawbacks in implementing that behavior.
-
I'm at gym reading tweets between sets so will read/reply better later. But have you looked at the LanguageSupport module that installs/uninstalls its own related modules?
-
ProcessWire modules are by nature meant to save time. There are 3 modules that I think can be big time savers on almost every project: The MarkupPagerNav module included with ProcessWire is hard to imagine being without. Yet, I was doing pagination without this for a long time before making it, and... things get done a lot quicker now. The MarkupSimpleNavigation module can be a big time saver when it comes to many common navigation scenarios. The FormBuilder module is a big time saver when it comes to creating forms. It's turned the most annoying and consuming part of development (for me at least) into one of the quickest and easiest. When it comes to front-end development, I'll admit that I've always preferred starting from scratch. But lately I've been enjoying what some of the CSS frameworks like Skeleton, Foundation and HTML Kickstart bring to the plate (and Twitter Bootstrap I'm guessing, but have not used it). With the appropriate project, these are huge time savers. The project I'm working on now (for a boarding school) needed to be responsive and very unique in design, and I found Skeleton to be the perfect balance there. It provides just enough to make things responsive, and very little else. That left little room for the design to be influenced by the framework (which was desirable in this case). If I didn't need responsive on a particular project, and could let the design benefit from some framework influence, I'd go straight to HTML Kickstart as the biggest time saving framework. Lastly, I'd say that using the Basic Profile as a starting point has always been a big time saver for me. Almost every site I build needs the core framework of fields and templates included with the basic profile. While all the markup and CSS ultimately get replaced, it saves a lot of time having these things there ready to implement.
-
I don't want to make assumptions about what people are using the text field for. If you are planning to use HTML, Textile, Markdown, BBCode, etc., then you don't want this Textformatter on. I usually make most of my text fields use Textile or Markdown (rather than HTML Entities) so that I can still have the ability to insert links and have basic formatting when I need it (even for single line text fields like 'title'). If the fields will contain untrusted user input, then I would choose TextileRestricted or BBCode (Markdown is not safe here, as it still allows HTML). Though if you don't need them to have any formatting ability, then I would just stick with HTML Entities, to exclude that possibility. There are just so many legitimate uses of tags in a field that I'd rather someone decide what they plan to use it for rather than us assuming what they will use it for. Still, I can see someone skipping over this not really understanding the security risks, so what may be warranted is for me to have it show a warning when no Textformatter is selected. There are plenty of cases where you actually don't want any Textformatters, but something containing untrusted user input is not one of them.
-
The main reason why name isn't on the content tab by default is because you could be breaking links (internal or external) every time you change it. It's one of those things that ideally should never change after its been created. But if you do expect changes, I suggest installing the Page Path History module, which will keep track of those changes and setup 301 redirects.