-
Posts
17,254 -
Joined
-
Days Won
1,708
Everything posted by ryan
-
PW2 admin browser support is currently built around recent Webkit and Mozilla browsers (Firefox 3.5+, Chrome 7+, Safari 4+). IE8+ also works just fine, though not running on a PC I haven't spent as much time in that browser... though I consider supporting it always of major importance. I believe the only place where IE8 is a little strange right now is in the TinyMCE image editing functions. It works, but there's some strange overlay issues getting confuse between the windows. Opera support is also on the to-do list. I like the idea of these file upload widgets, and the one you posted seemed to work well when I tested it. I'm particularly interested in an HTML5 widget option where one could drag files into it. But I think the best solution will be to make these options something that the user can select what upload widget they want. For instance, they can use the basic HTML one, or they can choose an alternate via a plugin module, kind of like how they can select "TinyMCE" (and likely others, in the future) with the Textarea fieldtype.
-
Apeisa, thanks I think that's a great summary and order of things. I agree with everything you've said here. I already have this one partially done and working. I'll be happy to post it before it's done if anyone wants to play with it. I just posted a guide this morning in the forums. At least it's a start for the real documentation. Thanks, Ryan
-
Regarding the image cleanup. I need to create a "clear image cache" function at some point (perhaps as a button in the FieldtypeImage module configuration). That would just go through and wipe out all the cached images. Since ProcessWire doesn't know which size variations you are actually using, it would have to wipe them all. But of course, any of the ones that were being used would just get re-create automatically the next time the page is viewed. On a big site, this might mean pages take longer to render than usual, but only temporarily.
-
Sinnut is right. This was a bug! It has been fixed in the latest commit. Thanks Sinnut! https://github.com/ryancramerdesign/ProcessWire/commit/fbb5db8ac46cc94676221a8fe06c058e3ee4e76f
-
How do you call data from a page or pages into another page?
ryan replied to a topic in API & Templates
Apeisa's examples are great. You may also sometimes want to pull pages based on their location rather than what template they use. For example, lets say you were on the homepage (or some other page) and wanted to pull the 3 most recent news items from the /company/news/ page. I'm going to assume that the news page is already set to sort it's children by date descending. <?php $latestNews = $pages->get("/company/news/")->children("limit=3"); foreach($latestNews as $item) { echo "<p><a href='{$item->url}'>{$item->title}</a><br />{$item->summary}</a></p>"; } -
That's a good question. It is feasible to do this, but I see possible security implications with making this sort of functionality accessible from the front end. When you've got something like this on the front end, you really want to be storing files they add in a non-web accessible location, and you want to make sure they aren't posting hundreds of giant files to fill up your hard drive, and using image resize functions as DDOS entry points, and so on. Lots of implications like that when you consider completely anonymous users. The current file/image tool isn't designed for anonymous/guest users. That's not to say that it's not plenty secure, but that I'm very paranoid about such functions (in any CMS) unless they are specifically designed for guest/anonymous use (like the one included in these forums). Once we have a more thorough users system in place, I think we should make these fieldtypes more accessible outside administrative use.
-
I wanted to mention that there is something sort of like this. I use it mostly for quick prototyping pages and stuff, but take a look at the Admin > Modules > MarkupPageFields, and click install if it's not already. Then in your template(s), you would do something like this, probably in your main content column: <?php echo $page->renderFields(); ?> That will render all of your fields and values on the page in an HTML definition list. It's a quick way to get a look at all your data in context before you produce your real templates. But I see this as a tool to help with development and prototyping, and not something to use for production sites (though you certainly could if you wanted to).
-
Here is a quick guide to using the comments system. We start from the simplest usage, and get down into more configuration options further in the post. Making use of the Comments fieldtype 1. Make sure that Comments fieldtype (FieldtypeComments) is installed from the Admin > Modules menu. 2. Now go to Admin > Setup > Fields and create a new field. Select "Comments" as the fieldtype and give it whatever name you wish (I usually call it just "comments", and code snippets here assume it's called that). 3. On the next screen, you'll have several options to configure the comments field. Make sure that you enter a Notification email. This is the email address that gets notified when new comments are submitted. Currently it is the only way you will know when new comments are posted (short of checking the admin page yourself), so using this is important. 4. Now edit the template where you want your comments to appear. Enter this: <?php echo $page->comments->render(); 5. Likewise, in your template, enter this where you want the comments entry form to appear: <?php echo $page->comments->renderForm(); 6. Your comments are now ready to use. Note that any templates that use comments for posting should not use Template caching unless you configure the comments to post to another template/page. You'll see an option for this in the renderForm() options shown further down on this post. Adding the Akismet Spam Filter I highly recommend that you use the Akismet spam filter with your comments. To do so, you'll need an Akismet or Wordpress API key (http://en.wordpress.com/api-keys/). Once you have it, click to Admin > Modules > Akismet (CommentFilterAkismet). Enter your API key in the space provided and Save. Then go to Setup > Fields > and edit the comments field you added. Check the box for "Use Akismet". You'll also see a field that says how many days it will keep spam before deleting it. I usually set this at 1 or 2 days, just in case Akismet identifies something as spam that isn't (though it's yet to happen!). Hit Save, and your comments are now hooked into Akismet. Styling the Comments See the file attached to this message (at the bottom). It is a starting point for styling the comments. It's just pulled from the comments styling at processwire.com, so it should be seen as an optional starting point rather than as a ready-to-go stylesheet. Or, you may prefer to start from scratch on styling the comments, depending on your need. OPTIONAL: Customizing the Comments Output You may want to change some of the basics of the comments output. You can do this by passing arguments to the functions you called above to render the comments list and comments form. Included below are examples with all options. You may specify any one or more of the options -- only specify the ones you want to change: <?php // comments list with all options specified (these are the defaults) echo $page->comments->render(array( 'headline' => '<h3>Comments</h3>', 'commentHeader' => 'Posted by {cite} on {created}', 'dateFormat' => 'm/d/y g:ia', 'encoding' => 'UTF-8', 'admin' => false, // shows unapproved comments if true )); // comments form with all options specified (these are the defaults) echo $page->comments->renderForm(array( 'headline' => "<h3>Post Comment</h3>", 'successMessage' => "<p class='success'>Thank you, your submission has been saved.</p>", 'errorMessage' => "<p class='error'>Your submission was not saved due to one or more errors. Please check that you have completed all fields before submitting again.</p>", 'processInput' => true, 'encoding' => 'UTF-8', 'attrs' => array( 'id' => 'CommentForm', 'action' => './', 'method' => 'post', 'class' => '', 'rows' => 5, 'cols' => 50, ), 'labels' => array( 'cite' => 'Your Name', 'email' => 'Your E-Mail', 'text' => 'Comments', 'submit' => 'Submit', ), // the name of a field that must be set (and have any non-blank value), typically set in Javascript to keep out spammers // to use it, YOU must set this with a <input hidden> field from your own javascript, somewhere in the form 'requireSecurityField' => '', // not used by default )); Lets say that you just wanted to change the headlines for the comments list and comments form. You'd do this: <?php echo $page->comments->render(array( 'headline' => '<h2>Read Comments</h2>', )); echo $page->comments->renderForm(array( 'headline' => '<h2>Join The Discussion</h2>', )); OPTIONAL: Generating your own output If you wanted to generate your own output (rather than use the built in render() methods), you can iterate the $page->comments field: <?php foreach($page->comments as $comment) { if($comment->status < 1) continue; // skip unapproved or spam comments $cite = htmlentities($comment->cite); // make sure output is entity encoded $text = htmlentities($comment->text); $date = date('m/d/y g:ia', $comment->created); // format the date echo "<p><strong>Posted by $cite on $date</strong><br />$text</p>"; } You can likewise do the same for the comment form. But I don't want to get too far into this level yet since this is supposed to be a quick guide. Whats on the Comments roadmap? In my mind the biggest missing part is a central place to manage all your comments. Currently you manage them on a page-by-page basis, consistent with where the comment was posted. This is fine for simple uses, but becomes more challenging on larger sites, where you have to rely upon the notification emails to let you know where comments are posted. I would like to expand this so that comments can optionally be managed in a central place. In addition, I would like to make them as easily API accessible as pages. The comments are also not hooked into the user system. Every time you post, you are essentially posting as a guest. While the comments fieldtype will recognize your email address if you have posted an approved comment before, I would like to make it recognize the user system, and also recognize other user systems (like Twitter, Facebook and Gravatar). There is more needed too, like comments pagination and support for basic markup (comments can only contain text at present). If your needs are relatively simple, the Comments fieldtype is a good way to go. If your needs are more advanced, systems like Disqus and Intense Debate are excellent options to consider. The only issue I would have with those options is that they are javascript-based by default, so comments don't become part of your site's indexable content (to search engines like Google). comments.css.zip
-
Great! Glad that worked. Like I say it's just a start, but a good proof of concept hopefully.
-
Any chance of a quick guide to comments system?
ryan replied to martinluff's topic in API & Templates
I'm going to post a guide for this after the weekend. Lots more planned for the comments system, but it gets the job done as it is... And it hooks into akismet so that you don't get a spamstorm. NOTE: Comments Guide was posted to the Tutorials section in the forum. -
Can you check at the bottom of the modules screen, there should be a "check for new modules" button (just added last week, so it wasn't there before). This was so that we could cache modules (faster) but you need to click the button for it to find them.
-
You are right, that is a typo it should be $form not $contactForm. Do you still get the error after that correction? The error message seems to indicate that typo may be the problem. if not, can you double check that FormTemplateProcessor is installed in Admin > Modules? Thanks -Ryan
-
I worked to make a module early this AM before everyone woke up, and have been banned from the computer since. But got a minute to post it so figured I would, and then I'll post a live example tomorrow. This is just a start on this module... lots more to cover obviously, but just wanted to get the momentum going. And it is fully functional even in this state, if anyone wants to try it out. I just experimented with simple forms having "name, email and message" text fields, so far. Here are usage instructions below (pulled from the module file), and the .module file is attached if anyone wants to try it or work with it. Just place it in: /site/modules/FormTemplateProcessor.module /** * Module to let you use templates as web contact forms. * * Can send you email and/or save the submission to a page in your site. * * Usage: * * 1. In admin, create the fields you want to be part of the form. * 2. Create a new template and assign your fields to this template. * 3. Create another template for your contact form page (if you don't already have one). * 4. Use the example below as a starting point for this contact form page: * * $form = $modules->get('FormTemplateProcessor'); * $form->template = $templates->get('my_contact_form_template'); // required * $form->requiredFields = array('fullname', 'email'); * $form->email = 'your@email.com'; // optional, sends form as email * $form->parent = $page; // optional, saves form as page * echo $form->render(); // draw form or process submitted form * * 5. Use CSS to style the fields. See the bottom of this file for suggestions. * */ Download at GitHub: https://github.com/ryancramerdesign/FormTemplateProcessor
-
Adam, sounds like you have some good ideas. I have to build a contact form for a site that's going up tomorrow and think I'm going to use the Inputfield modules to do it (manually) just to see how it might work. I'll post the template and result here tomorrow if you guys want to see it. I think it'll lead to some more thoughts on a form builder.
-
I would like something like that too, though don't know how it could be done without being something that generates markup. But this is one of the cases where markup generation is probably desirable. I am thinking the best bet will be to base it on ProcessWire's Inputfield modules, since they are already used for this purpose in the page editor (and throughout ProcessWire). And they already generate their own markup and retrieve and sanitize their own values. The main thing will be to write an editor to construct the form (similar to the template editor) and then something to save submitted entries to the DB (or optionally, page records). I haven't actually tried Drupal's form builder yet, I need to get a look at that. Edit: I see Adam is thinking the same thing (and typing at the same time as me). It may be that the existing Templates system can be used for creating these forms as you mentioned.
-
Congrats to you guys on writing the first 3rd party ProcessWire module! I've added a Modules section on the download page. This will be built out more in the future, but just wanted to get something there for now.
-
Tried tried it out, and it's looking good! Only thing I noticed is that in your getModuleConfigInputfields function, you need to add "$field->value = 1;" to both showModal and initCollapsed, so that there is a value for the checkbox when it is checked. Also, in your README.txt I recommend a note to tell people that they need to name the module dir "AdminBar". This reason is that if you download the ZIP from GitHub, it's named apeisa-AdminBar-39820zvosomethingorother.zip, and when you it extract it, the dir has that name as well... so I had to rename that dir to be AdminBar in order to get it to work (ProcessWire requires that the dir and module name are the same, though maybe I should change that).
-
The Modules configuration stuff is fixed, and I also added some optimizations to the Modules loader while I was at it. Grab the latest master and upgrade before proceeding with the following. For AdminBar.module here is what I would recommend. Add a getDefaultData() function to the AdminBar class to store your defaults. This isn't part of a PW2 interface, this is just for your use, but it prevents you from having to name the defaults twice. <?php /** * Default configuration for our module * * The point of putting this in it's own function is so that you don't have to specify * these defaults more than once. * * However, there is no requirement for you to do this (it was just my preferred style). * If you preferred, you could just check $this->showModal and if it was null, then you * would know it had not yet been configured (and likewise for the other vars). * */ static public function getDefaultData() { return array( 'showModal' => 1, 'initCollapsed' => 0, 'administration' => wire('config')->adminRootPageID ); } Now setup your constructor to populate that default configuration data in your class. You want to do this just in case your module is running "unconfigured" (i.e. the admin has never gone in and tried to make any settings). <?php /** * Populate the default config data * * ProcessWire will automatically overwrite it with anything the user has specifically configured. * This is done in construct() rather than init() because ProcessWire populates config data after * construct(), but before init(). * */ public function __construct() { foreach(self::getDefaultData() as $key => $value) { $this->$key = $value; } } Next is your function that handles the config data. I changed it so that it pulls the defaults from that function we added above. Also, the checkbox fields need a value, so I just set that as "1". That's the value that gets used if it's checked. Lastly, since we're using HTML5 with XHTML tags, I set the 'checked' attribute to have a value of 'checked' rather than boolean true. Not sure that it matters, but this seems to be XHTML syntax best practice. <?php static public function getModuleConfigInputfields(array $data) { // this is a container for fields, basically like a fieldset $fields = new InputfieldWrapper(); // since this is a static function, we can't use $this->modules, so get them from the global wire() function $modules = wire('modules'); // Populate $data with the default config, because if they've never configured this module before, // the $data provided to this function will be empty. Or, if you add new config items in a new version, // $data won't have it until they configure it. Best bet is to merge defaults with custom, where // custom overwrites the defaults (array_merge). $data = array_merge(self::getDefaultData(), $data); // showModal field $field = $modules->get("InputfieldCheckbox"); $field->name = "showModal"; $field->label = "Show modal box?"; $field->description = "Whether edit opens modal box or goes to administration."; $field->value = 1; // providing a "checked" value for the checkbox is necessary $field->attr('checked', empty($data['showModal']) ? '' : 'checked'); $fields->add($field); // initCollapsed field $field = $modules->get("InputfieldCheckbox"); $field->name = "initCollapsed"; $field->label = "Init collapsed?"; $field->value = 1; $field->attr('checked', empty($data['initCollapsed']) ? '' : 'checked'); $fields->add($field); // administration field $field = $modules->get("InputfieldPageListSelect"); $field->name = "administration"; $field->label = "Where to go after clicking on 'administration'"; $field->value = $data['administration']; $fields->add($field); return $fields; } Lastly, your pageRender() method is currently checking $this->showModal with an isset() function. That's not going to be the right approach here because it's always going to be set once it's configured (it will be set with a value of either 0 or 1). So the thing to do is: <?php if($this->showModal) { // draw the modal link } else { // draw the regular link } ...and likewise with any other configuration options. None of the configuration options will ever be unset since in this class instance we're now setting them in the constructor. I tested it here using your module, and all appears to work from this end. Let me know how this works for you. I'm really enjoying using this module!
-
Any pointers on creating a mobile version of a site?
ryan replied to martinluff's topic in API & Templates
There is $config->httpHost, but it's exactly the same thing as $_SERVER['HTTP_HOST'] except that it's been sanitized. But in this case, it wouldn't matter which one you check. Edit: Also $config->httpHost wouldn't have worked in the database selection because it's set by the ProcessWire bootstrap class (which hasn't yet been instantiated when /site/config.php is loaded. -
I just tried out AdminBar and it works great! I love it. It seems like there is a need to have a save button that doesn't need to be scrolled to. Can buttons be added to the modal window? Or, I was thinking I should just add it to ProcessPageEdit (right next to the page ID at the top right), as it would be useful with or without the AdminBar. I'm working on the Modules.php update/fix right now and should have it posted to the master branch shortly. Nice work with AdminBar!!
-
Any pointers on creating a mobile version of a site?
ryan replied to martinluff's topic in API & Templates
Another possible approach would be to point m.domain.com to just domain.com. Then your head and foot templates (or main template if you are using that), would check $config->httpHost to see if it's at the m.domain.com, i.e. /site/templates/head.inc <?php if($config->httpHost == 'm.domain.com') include('./head-mobile.inc'); else include('./head-normal.inc'); Your head-mobile.inc would contain your mobile specific markup, stylesheet links, javascript links, etc. Likewise, your head-normal.inc would contain the same for the non-mobile version of the site. That way you wouldn't have to do anything on a page-by-page basis, and the mobile version of the site would just happen automatically depending on the hostname. What you would have to be aware of is that any markup created in your page-specific templates should be compatible with the mobile or regular version of the site. However, I think this would often be the case even if you weren't trying to do it that way. Though if there were instances where you needed them to be different, you would just check that $config->httpHost again from inside your template. If you are concerned about duplicate content at the m.domain.com, then using a canonical tag may be a good option to add to your head-mobile.inc: <link rel="canonical" href="http://domain.com<?php echo $page->url; ?>" /> -
Thanks, I can't wait to check this out! We are headed to dinner, so I'm going to check when I get back. If you are still around and want to try it, here is a fixed /wire/core/Modules.php that corrects the bug (attached). I am going to go over it in more detail tomorrow. Also, I may have told you the wrong thing on setting the defaults in the getModuleConfigInputfields... you may be able to remove that part at the top. I'll double check on the proper syntax either tonight or tomorrow, and then get started on the module documentation! Modules_php.zip
-
Looks like you've found a bug! I will work to get this fixed for tomorrow. Sorry for the inconvenience. Turns out this is the first configurable module of it's type, so it's not come up before. But I think it will be an easy fix.
-
You are right. I'm figuring it out now... you the first person to develop a module, and this is only the 3rd or 4th configurable module ever, so I'm getting up to speed myself. I'll reply shortly.
-
It's getting near the end of the work day and I'm forgetting crucial details. To read this values, they will be automatically set in your AdminBar instance. So anywhere in that class, you should be able to just reference it like: $this->showModal, and so on. If the value is not set or doesn't exist, it will just be null. If that's the case, then you should use some default value, because it means the module has never been configured. Or you could set them up in a __construct method. The constructor is of course executed before PW2 sets any values to the module. Whereas the init() method is called after PW2 sets values to the module. So you might setup your defaults like this: public function __construct() { $this->showModal = true; } No need to define a separate showModal var in your class, because WireData is already handling that for you behind the scenes...