Jump to content

Robin S

Members
  • Posts

    5,039
  • Joined

  • Days Won

    340

Everything posted by Robin S

  1. Often I want to limit the placement of pages with a particular template to a particular parent page in the tree. Many times this parent page doesn't need to have it's own unique template, but I end up duplicating one of my existing templates (lets say it is "basic-page") just to make sure editors don't have the ability to mess up the placement of pages, and so I can make make use of the "Add New" shortcut. So I end up with "basic-page" and duplicates "basic-page-2", "basic-page-3", etc (naming is just for argument's sake). When templates are duplicated the problem isn't so much the template files, because it's easy to manually assign the file of basic-page to basic-page-2 and basic-page-3. The problem is maintenance - if I want to add a field to basic-page, change a label or field width override, etc, I now have to repeat these changes on multiple templates. It becomes difficult to keep the duplicated templates in sync. Having a template setting "Allowed page id(s) for parent" would avoid the need to duplicate templates in this situation. An alternative possibility is some system of template inheritance, but that's another kettle of fish.
  2. Got it sorted, and complete plugin code is: // Keyboard shortcuts for headings 1-6, p ( function() { CKEDITOR.plugins.add( 'keystrokes', { init: function( editor ) { editor.addCommand( 'h1', { exec: function( editor ) { var format = { element: 'h1' }; var style = new CKEDITOR.style(format); style.apply(editor.document); } } ); editor.addCommand( 'h2', { exec: function( editor ) { var format = { element: 'h2' }; var style = new CKEDITOR.style(format); style.apply(editor.document); } } ); editor.addCommand( 'h3', { exec: function( editor ) { var format = { element: 'h3' }; var style = new CKEDITOR.style(format); style.apply(editor.document); } } ); editor.addCommand( 'h4', { exec: function( editor ) { var format = { element: 'h4' }; var style = new CKEDITOR.style(format); style.apply(editor.document); } } ); editor.addCommand( 'h5', { exec: function( editor ) { var format = { element: 'h5' }; var style = new CKEDITOR.style(format); style.apply(editor.document); } } ); editor.addCommand( 'h6', { exec: function( editor ) { var format = { element: 'h6' }; var style = new CKEDITOR.style(format); style.apply(editor.document); } } ); editor.addCommand( 'p', { exec: function( editor ) { var format = { element: 'p' }; var style = new CKEDITOR.style(format); style.apply(editor.document); } } ); editor.setKeystroke( CKEDITOR.ALT + 49 , 'h1' ); // ALT + 1 editor.setKeystroke( CKEDITOR.ALT + 50 , 'h2' ); // ALT + 2 editor.setKeystroke( CKEDITOR.ALT + 51 , 'h3' ); // ALT + 3 editor.setKeystroke( CKEDITOR.ALT + 52 , 'h4' ); // ALT + 4 editor.setKeystroke( CKEDITOR.ALT + 53 , 'h5' ); // ALT + 5 editor.setKeystroke( CKEDITOR.ALT + 54 , 'h6' ); // ALT + 6 editor.setKeystroke( CKEDITOR.ALT + 55 , 'p' ); // ALT + 7 } }); } )(); After adding the plugin it needs to be activated in the field settings > Input > Extra Plugins keystrokes.zip
  3. Thanks! That plugin code works perfectly for all the basic commands. Unfortunately I'm having trouble finding the names of commands for items in the Format dropdown (headings 1-6, paragraph, etc). That's really a CKEditor problem rather than a PW problem. Will post the solution here if I can find one.
  4. The code above is from the docs for CKEditor v3, so that's not applicable. The v4 docs give the following example... editor.setKeystroke( CKEDITOR.CTRL + 115, 'save' ); // Assigned Ctrl+S to the "save" command. editor.setKeystroke( CKEDITOR.CTRL + 115, false ); // Disabled Ctrl+S keystroke assignment. editor.setKeystroke( [ [ CKEDITOR.ALT + 122, false ], [ CKEDITOR.CTRL + 121, 'link' ], [ CKEDITOR.SHIFT + 120, 'bold' ] ] ); ...but I'm still not sure where this should be added to be applied in PW's CKEditor module.
  5. CKEditor doesn't provide shortcut keys for applying headings 1-6 and this makes text formatting slower than it needs to be. I'd like to add shortcuts for headings but I'm not sure where the config code should go. The CKEditor docs for shortcut keys give the following example: Edit: wrong version, see next post // This is actually the default value. config.keystrokes = [ [ CKEDITOR.ALT + 121 /*F10*/, 'toolbarFocus' ], [ CKEDITOR.ALT + 122 /*F11*/, 'elementsPathFocus' ], [ CKEDITOR.SHIFT + 121 /*F10*/, 'contextMenu' ], [ CKEDITOR.CTRL + 90 /*Z*/, 'undo' ], [ CKEDITOR.CTRL + 89 /*Y*/, 'redo' ], [ CKEDITOR.CTRL + CKEDITOR.SHIFT + 90 /*Z*/, 'redo' ], [ CKEDITOR.CTRL + 76 /*L*/, 'link' ], [ CKEDITOR.CTRL + 66 /*B*/, 'bold' ], [ CKEDITOR.CTRL + 73 /*I*/, 'italic' ], [ CKEDITOR.CTRL + 85 /*U*/, 'underline' ], [ CKEDITOR.ALT + 109 /*-*/, 'toolbarCollapse' ] ]; And the advice is that the code belongs in "plugins/keystrokes/plugin.js", but I suspect that isn't correct for PW because this file doesn't exist in the CKEditor module yet the normal keyboard shortcuts are available in PW. Which makes me think the keyboard shortcuts are defined somewhere else. The other place I thought of adding the config code is in the Custom Config Options textarea in the field settings, but the example code looks like it doesn't conform to property: value format for this field.
  6. Thanks for the ideas. @mr-fan: I think this might be the sort of thing you're hinting at - at the top of the widget templates... <?php if( empty($options['pageStack']) ) throw new Wire404Exception(); ?> Good info in this post from Jonathan Lahijani here and some info on pageStack from Ryan here. I like this solution. @LostKobrakai: Sounds like this would work, but it seems to me there are downsides to using wireRenderFile() over $page->render(). I have a lot of different widget templates and widgets are selected by editors via a page field, so using $page->render() keeps the rendering code really simple and maintenance-free. foreach($page->widgets as $widget) { echo $widget->render(); } But if I use wireRenderFile() I need a whole chain of logic to check the template of each widget and render it with the correct file for that type of widget. Besides avoiding partial pages being directly viewable, are there other benefits of wireRenderFile() that make it preferable to $page->render()?
  7. I have some pages that are used only as partials, to be rendered as part of other pages using $page->render() I have them inside a /widgets/ branch in my page tree. The problem is that they are viewable from the front-end: if someone visits mydomain.com/widgets/my-widget/ they see the partial HTML. Is there a way I can keep my widgets accessible to editors in the back-end and capable of being rendered in other pages but without them being directly viewable?
  8. You are right of course, don't know what I was thinking there... So I think we can safely say that of the two, ->has() definitely performs better
  9. Which of the following is the better way to test if a PageArray contains a particular id? $my_page_array->has("id=1234") or $my_page_array = 1234 Does one perform better than the other?
  10. Yes please!
  11. This can be set in My Settings > Notification Options...
  12. I think you're right, but it's more a case of "will be solved" rather than "can be solved" because the module isn't available yet. Eagerly looking forward...
  13. You could check with your host to see if they are running mod_security. I just struck the same 404 problem when I use an include in my Hanna PHP code. My host lets me disable mod_security via htaccess, and sure enough when I disable it the 404 problem is gone.
  14. Perhaps try the Dynamic Roles module.
  15. It occurred to me that a good addition to the forums would be some way for PW users to indicate support for a module idea. Similar to the Wishlist subforum but for functionality that belongs in a module rather than in the core. I'm thinking mainly of commercial modules, although if someone wanted to take up a module request and release it freely that would be cool. So users could propose a module idea, then others would vote for it (using likes or some special voting option) so that a vote means "I'd buy that", with the expectation of pricing in the general ballpark of Ryan's pro modules and Apeisa's PadLoper. As a beginner-intermediate developer I'm really enjoying working with PW and learning as I go - the API is so intuitive that I've been able to build my own solutions to things that in another CMS I would have been reliant on someone else's module to achieve. But there are things that I know are beyond my current skills, and for those things I look to third-party modules. My clients are non-profits and small businesses so I'm never likely to have the budget to commission a custom module alone. But there might be other PW users out there with similar needs and maybe that demand would make it worthwhile for an experienced developer to take on a proposal and release it as a commercial module. Currently there isn't a way to measure the demand for modules apart from occasional forum posts like "Is there a module that...?" Any thoughts on this? Here's a module request to start off with: I would be happy to buy a full-featured event calendar module. I've searched the module directory and the forums and Lindquist's module is the most feature-rich I've seen, but it's in an alpha proof-of-concept state and some important functions aren't implemented. Features I would be looking for are: Calendar grid interface in admin, allowing for easy addition and editing of events. (Nice but non-essential) Week and day views in admin, in addition to month view, with drag editing for event date and duration (I'm dreaming of something awesome like the dhtmlxScheduler interface or Fullcalendar interface). Although drag operations would really need an undo to correct accidental edits, so this may be more trouble than it's worth. Events are edited in a modal window, to avoid losing one's place in the calendar. Recurring events, with user-friendly selection of recurrence options. The ability to individually edit or remove an event that is a child of a recurring event (i.e. make an exception for that individual event). (Nice but non-essential) A couple of out-of-the-box minimal rendering options for the frontend (read-only calendar view, list view). This is the kind of module I need frequently. I've been lucky that I haven't had a client request a full event calendar since I've been using PW, but it's only a matter of time. I'm sure there are other PW users who need this and who would, like me, be happy to pay for such a module.
  16. No solution currently (other than switch from Repeater to PageTable). But issues logged at GitHub: #1567, #1616
  17. Thanks, I've taken that advice and everything works great. Sanitizing to an image object means I avoid having to check for object vs. string in the sleepValue method. For novice developers like myself I think it's a bit hard to grasp the sanitizeValue method because it's not obvious where the method is called. With some debugging it looks to me like sanitizeValue is called twice, with the flow being: inputfield > sanitizeValue > sleepValue > database and database > wakeupValue > sanitizeValue > page Is that correct? It's the first call that puzzles me a bit because the comment in Fieldtype.php for sanitizeValue says: And I can't see where the "Page instance" comes into inputfield > sanitizeValue > sleepValue > database @kixe Thanks for directing me to your module - I haven't tried it before and it looks like it's very flexible. It's not quite suitable for my purposes for a few reasons: I want my select dropdown to include the images from all the image fields assigned to the template. Because each image field is a separate table in the database I don't think Fieldtype Select External Option will allow this. I want to customise the select inputfield so it shows a thumbnail of the selected image (so it's easier for the user to select the image they want). I'm doing this by setting a thumbnail data attribute for each option in the options array. So my module needs to be something specific to images rather than Fieldtype Select External Option which has a broader application. When used for image fields, it seems that the value saved by Fieldtype Select External Option is quite fragile. Because the option value has to be an integer you have to use the Sort column for the value. This means that if the images are reordered in the image field the image referenced by Fieldtype Select External Option is changed. For an image reference you really want the image name to be the value that is stored. Also, I got some errors when attempting to install Fieldtype Select External Option. They are caused by the strings that are marked as translatable. I think lines like... $f->label = _('Usage'); ...need to be... $f->label = $this->_('Usage');
  18. I'm working on a simple fieldtype module and trying to understand the wakeupValue, sleepValue and sanitizeValue methods a bit better. This and this have been helpful but I still have a few questions. My module is for storing a reference to an image that is contained in one of the image fields in a page. I'm using a customised select inputfield to choose from the available images, and the reference to the image is stored in the database as a string in the form: field_name|image_name In the wakeupValue method I convert the reference string to an image object. public function ___wakeupValue(Page $page, Field $field, $value) { list($field_name, $image_name) = explode("|", $value); $image = $page->$field_name->get("name=$image_name"); return $image; } This is working fine, but at the moment I'm not doing anything in the sanitizeValue method. To get an idea of when sanitizeValue is called I have this... public function sanitizeValue(Page $page, Field $field, $value) { $type = gettype($value); $log = wire("log"); $log->save("debug", "Sanitized: $value, Type: $type"); return $value; } ...and it shows that for every Edit Page save in admin the sanitizeValue method receives both the image reference string and the image object. Sanitized: photoxpress_8083749.jpg, Type: object Sanitized: images_two|photoxpress_8083749.jpg, Type: string Why does sanitizeValue get both these types? I can understand why the image object goes through sanitizeValue because I am setting that to the page, but why does the string go through sanitizeValue? I'm not setting the string to the page, just saving it to the database. For modules like this that store data in a different type than they send to the page, will the sanitizeValue method always need to account for both variable types? That is, the method can't expect $value to always be a string or always an object - it will need to test the type of $value and apply different sanitizing checks accordingly? And is this true for sleepValue also? Ryan said in another post: That makes sense if I was saving to my field via the API and set an image object to the field - sleepValue needs to convert the object to a reference string for storage in the database. But at the moment I'm only saving to the field via the admin, and so the $value received by sleepValue is a string coming from the inputfield, not an object. So to cover both bases I will need to test for the type of $value at the start of the sleepValue method? I guess I'm asking if this is the normal/right way for such a module to work or if there is some better way to set it up so that sanitizeValue and sleepValue only have to handle one variable type.
  19. Just to expand on this a bit: unlike the standard CKEditor image plugin, the PW image plugin does not provide a text field where you can type in a class for the image. So you would need to add "img-responsive" to a custom JS styles set and apply the class to the image using the styles dropdown. Info on how to load a custom style set is here. If you want the "img-responsive" class to be applied to every image in your CKEditor field (so you don't have to manually add it to every inserted image) there are a couple of options: 1. Add the class client-side with jQuery. This is a nice easy option. For example if your body text is inside a div with the class "body"... $(".body img").addClass("img-responsive"); 2. A little more challenging but no big deal if you're comfortable with PHP... create your own text formatter module that adds the class at runtime.
  20. +1 for this. As LostKobrakai pointed out, this wouldn't be an extension of FieldTypeImage. Maybe just an InputField like that used for Image, but storing a reference similar to a Page fieldtype. One case where this would be very useful is for selecting the image that will be used in the og:image meta tag. You want a single-image inputfield that selects from the images that have been already loaded to Image fields on the page. I'd love a field that has a setting for which page(s) images would be selectable from. So you could fix a page or pages (e.g. current page) in the settings, or allow the selection of a page from the inputfield (like what is possible in an RTE field). I think a field like this would be a great asset in PW - if there are use cases for selecting images from external Image fields within an RTE field then there are bound to be use cases for selecting them in a dedicated "image reference" field.
  21. +1 for a class/ID on the "maintenance mode" badge so it's position and appearance can be overridden. Would be cool if there were controls to set the text of the badge and the native PW message. Also, site editors who are not given permission to view the site in maintenance mode are put into an infinite redirect loop if they attempt to log in.
  22. Perfect, thanks!
  23. I have a page "go" using template "go" that I use for adding/updating pages via the API - I visit mysite.com/go and my code executes. It's convenient to keep this page in the tree so it's there when I need it but I worry about it being accidentally accessed (by me!), so I want a way to disable the page when I'm not using it. I thought unpublishing the page would do it, but it seems that the template code executes on visiting mysite.com/go even when the "go" page is unpublished. Is there a way to disable a page so it's template code does not execute? I'm also interested to learn other techniques that can be used to execute API code besides putting it in a template and accessing it from the frontend.
  24. I think it is in the systemIDs array: /processwire/ is the page titled "Admin", aka adminRootPageID Thanks for the link to the other thread - that answers the question of how the /processwire/ branch is hidden.
×
×
  • Create New...