Jump to content

The G

  • Posts

  • Joined

  • Last visited

Everything posted by The G

  1. The module's output uses the same function (renderHeadContent) : <script defer src='{$this->wire('modules')->get('ProCache')->js($this->getJsFile())}'></script> One way to insert just the JavaScript URL in your array would be to check "Render Banner and Header Content Manually" and to use $modules->get('PrivacyWire')->getInlineJs() and $modules->get('PrivacyWire')->getJsFile() instead of $modules->get('PrivacyWire')->renderHeadContent().
  2. I don't think that the file you see requested comes from the module. Pro Cache should automatically merge and minify PrivacyWireUnstyled.js. Did you took out the code you added in the templates and cleared the cache afterwards? Try uninstalling the module and see if you still have PrivacyWireUnstyled.js requested. Don't forget to clear the cache after any change.
  3. Hmm, I think you didn't read the instructions carefully enough. Did you notice a "Use ProCache JS Minification (if available)" checkbox near the end of the settings? Not tried it myself, but AFAIK you don't need to mess with other settings if what you want is just ProCache minification. Try this: uncheck "Render Banner and Header Content Manually", take out the code you manually inserted into the templates and check "Use ProCache JS Minification (if available)". Regarding CSS: styles are inserted by JavaScript (PrivacyWire.js), so no module CSS file is needed. If you choose the unstyled version, the module will load PrivacyWireUnstyled.js instead leaving the styling up to you (I chose to use the unstyled version and insert the needed styles into my main CSS file, since it will be loaded on every page. Either way seem good solutions to me - the styles are only needed together with the JavaScript. Off-topic: I'd love an inline code plugin for the forum's editor.
  4. You have the "Render Banner and Header Content Manually" option in the module settings. After checking it you can insert the module generated code wherever you'd like. The script tags are generated by the folowing snippet: $modules->get('PrivacyWire')->renderHeadContent() Disclaimer: didn't tested my suggestion, this is just what I saw in the module's code. Why would you want to include both PrivacyWire.js and PrivacyWireUnstyled.js? AFAIK they only differ in including or not the module's CSS for the frontend. Including PrivacyWireUnstyled.js would only waste resources if PrivacyWire.js is included.
  5. I tried to disable or hide a "Remember me" checkbox. My HTML is <div class="field has-text-right"> <label class="checkbox"> <input type="checkbox" name="rememberme" value="<?=(int) input()->cookie->rememberme?>"> <?=__('Remember me')?> </label> </div> The code I'd prefer would be (notice the two "disabled" attributes on the label and the input) <div class="field has-text-right"> <label class="checkbox" disabled> <input type="checkbox" name="rememberme" value="<?=(int) input()->cookie->rememberme?>" disabled> <?=__('Remember me')?> </label> </div> Although I could live with only hiding it, which is what I've tried by adding data-category="functional" data-ask-consent="0" data-ask-consent-rendered="1" to the div, the label or the checkbox. And it hides them all right. The issue is that PrivacyWire does not care about innerHTML of my poor div, or about its class. I changed o.innerText=e.innerText with o.innerHTML=e.innerHTML directly into js/PrivacyWireUnstyled.js and I got my checkbox back, but without its initial class. I think it is the code at line 231 in src/js/PrivacyWire.js. I know almost no JavaScript, so start throwing tomatoes - in the priw_updateAllowedElement there is no way to let the old element live instead of copy into a new one > insert the new one in the DOM > delete the old one? Also, it feels to me that flipping between two attributes or two CSS classes should be all PrivacyWire needs to do in regard to the elements that need consent. LATER: hmm, maybe not in regard to scripts. Leaving for the coffee machine...
  6. So, excited to use the updated version as I was, there was no time for RTFM - even if there was clearly written without leading slash , I merrily entered /site/templates/modules/PrivacyWire/PrivacyWireBanner.php and BANG!, ProcessWire shouted at me for wanting to use a not allowed path (because of the resulting double slash). I'm still trembling! Since it breaks so hard, I'm wondering if the input could be somehow forced to loose the leading slashes forgotten by irresponsible people like yours truly. Sadly, I'm not well versed (yet!) in module configuration input validation/modification. Or at least, write "without leading slash" in bold letters πŸ˜…
  7. Nice work! Question: I'm finding myself in need of many changes in the banner template, so I had to hook-replace the module's 'render' method. Would be useful to isolate the path retrieving code in separate hookable functions? Like this: /** * checks for a banner template alternate path * @return string the path of the banner template file */ public function ___getBannerTemplate() { return $this->wire('config')->paths->$this . 'PrivacyWireBanner.php'; } /** * checks for a javascript file alternate path * @return string the path of the banner template file */ public function ___getJsFile() { return ($this->add_basic_css_styling) ? $this->wire('config')->urls->$this . "js/PrivacyWire.js" : $this->wire('config')->urls->$this . "js/PrivacyWireUnstyled.js"; } Then, I could use it (I am using it, actually) like this (in /site/ready.php): // my front pages are all extending a FrontPage class // see https://processwire.com/blog/posts/pw-3.0.152/#new-ability-to-specify-custom-page-classes if (page() instanceof FrontPage) { $wire->addHookAfter('PrivacyWire::getBannerTemplate', function ($event) { $event->replace = true; $default_path = $event->return; $filename = pathinfo($default_path, PATHINFO_BASENAME); // my override is in /site/templates/modules/PrivacyWire/PrivacyWireBanner.php $override_path = paths()->templates.'modules/PrivacyWire/'.$filename; $event->return = is_readable($override_path) ? $override_path : $default_path; }); } Or even simpler (for me πŸ˜‚), those could be two new config keys, like 'alternateBannerTemplate' and 'alternateJsFile'. This would also cover the case of needing to change the header tag, so it could be dropped (just a thought, don't hit me in the head, you valiant head tag config defenders 😁).
  8. In my case the Warning: Illegal offset type in /var/www/html/site/modules/ProcessBlog/ProcessBlog.module on line 917 Warning: Illegal offset type in /var/www/html/site/modules/ProcessBlog/ProcessBlog.module on line 918 messages were probably caused by the page()->outputFormatting setting being "Off", and were fixed by casting (string) on the array keys: 915 $list = array( 916 (string) $posts->title => array('published' => $qn['blog-post'], 'unpublished' => $qn['unpublished'] ), 917 (string) $comments->title => array('approved' => $numApproved, 'pending' => $numPending, 'spam' => $numSpam ), $categories->title . ' & ' . $tags->title => array('categories' => $qn['blog-category'], 'tags' => $qn['blog-tag'] ), 918 );
  9. Nice, it works beautifully. The duration. I'd like to let the user read the message for a little longer: Off-topic question: how does one make posted videos to not extend to the full container width? I used the annoying GIF above because I didn't find a way to display posted videos at their real size.
  10. After the user saves his/her choices, a confirmation message is shown for 1.5 seconds, then is removed. My contact page uses Google Recaptcha and thus it needs Google's marketing cookies to work. So, in the beginning, instead of the contact form, the page shows only a message explaining that if one wishes to use the contact form, one needs to consent to the marketing cookies. Only after/if the user consents is the form shown. I wanted to have the page refreshed after saving the choices, so the user would not need to do a manual refresh to see the changes. I did it by adding a 74 window.location.reload(true); line after 73 priw_wrapper.classList.remove('show-message'); which is the one where the confirmation message is removed (priw_showMessage(), line 73 in src/js/PrivacyWire.js) and re-rollup-ing. I could make a pull request if it seems useful. Another suggestion would be make the setTimeout delay configurable. This one is not something I needed, but it just feels right to have it configurable 😁
  11. I 've done a pull request against the v2 branch, only three underscores added πŸ˜„ This is how I hooked it in ready.php (these are theme specific overrides, so I want to keep them in the /site/ folder somewhere): // If I want to do something with front pages (old code) //if (strpos($_SERVER['REQUEST_URI'], $config->urls->admin) !== 0) { // my front pages are all extending a FrontPage class // see https://processwire.com/blog/posts/pw-3.0.152/#new-ability-to-specify-custom-page-classes if (is_subclass_of(page(), 'Processwire\FrontPage')) { // [...] $wire->addHookBefore('PrivacyWire::render', function($event) { $event->replace = true; $privacywire = $event->object; $isProCache = modules()->isInstalled('ProCache') && modules()->get('ProCache'); $jsFilePath = getModuleFile($privacywire, 'js/PrivacyWire.js', true); if ($isProCache && $privacywire->use_procache_minification) { $jsFilePath = modules()->get('ProCache')->js($jsFilePath); } $output = wireRenderFile(getModuleFile($privacywire, 'PrivacyWireBanner.php'), [ 'module' => $privacywire ]); $output .= "\n<script>var PrivacyWireSettings={version:'{$privacywire->version}',dnt:'" . ((int) $privacywire->respectDNT) . "'};</script>"; $output .= "\n<script defer src='{$jsFilePath}'></script>"; $event->arguments(0)->return = str_replace("</body>", "{$output}</body>", $event->arguments(0)->return); }); // [...] } /** * checks for a module file override in the path defined * @param object $module the module needing a file overriden * @param string $file_path the override file path, from the module folder, i.e. "js/PrivacyWire.js" * @param boolean $is_url switch for outputting a path or an URL, by default the function outputs a path * @return string the override path is it's readable or the initial file path if it's not */ function getModuleFile($module, $file_path, $is_url = false) { // we're putting module overrides in /site/templates/modules/ $override_dir = 'modules/' . $module->className() .'/'; $override_path = paths()->templates . $override_dir . $file_path; // we're overriding files in the module's folder $default_path = paths()->$module . $file_path; if (is_readable($override_path)) { return $is_url ? urls()->templates . $override_dir . $file_path : $override_path; } return $is_url ? urls()->$module . $file_path : $default_path; }
  12. Ah, but of course! How could I forget about hooks! Thank you, @horst! I realize now that I could probably keep all my overrides in a single place, depending on the presence of the hooks, of course. @joshua, please make the render() function hookable. Sometimes I wish ProcessWire could be more restrictive, my /site/ folder is a frankensteinish patchwork of code snippets, because I used whatever the search cat dragged in first 🀣
  13. Hello gentlemen and thank you for your fine module, Joshua! Is there a way to preserve the changes to the HTML/CSS of the banner after updates? Maybe there is a generic processwirish way to override module markup? Right now I added a method to the module that allows me to replace the module's markup by placing the modified files in /site/templates/MODULE_DIR/: protected function getFile($file, $is_url = false) { // we're putting module overrides in /site/templates/modules $override_dir = 'modules/' . basename(dirname(__FILE__)) .'/'; $override_path = $this->wire('config')->paths->templates . $override_dir . $file; // we're overriding files in the module's folder $default_path = $this->wire('config')->paths->$this . $file; if (is_readable($override_path)) { return $is_url ? $this->wire('config')->urls->templates . $override_dir . $file : $override_path; } return $is_url ? $this->wire('config')->urls->$this . $file : $default_path; } and using it like this: $jsFilePath = $this->getFile('js/PrivacyWire.js', true); and $output = wireRenderFile($this->getFile('PrivacyWireBanner.php'), [ 'module' => $this ]); This way I only have to add the above code into the module after the update, while keeping my changes in /site/templates/PrivacyWire/, to preserve the look of the banner, from the default to a Bulma version
  14. Disclaimer: please note that this is how I am doing it, it may or may not suit you, so take it with a grain of salt. Also, I apologize for not obeying ProcessWire's code style, I'm just too old and it feels alien to me. Thing I'm trying to get: not having to input the 'Custom Editor CSS File ...' and 'Custom Editor JS Styles Set ....' for each of the fields using CKEditor. Yeah, I know, call me lazy or sloppy or whatever, it is what it is πŸ˜„ . having the front end styles in the editor container, so the one editing the page would be able to eyeball the styling of the content while stayin in the editor For the first objective I tried to find a way in the CKEditor configuration options, like config.js, or at least a single point to set my options. In the end, what worked for me was hooking the Inputfield in ready.php: if (strpos($_SERVER['REQUEST_URI'], $config->urls->admin) !== 0) { // things I do to frontend pages, believe me, you don't want to know :D } else { $wire->addHookBefore('InputfieldWrapper::renderInputfield', function($event) { // process further if it is an InputfieldCKEditor if (strpos($event->arguments(0)->className(), 'InputfieldCKEditor') === 0) { // store the Inputfield $inputfield = $event->arguments(0); // my custom CKEditor options $my_settings = [ 'contentsCss' => '/site/assets/css/cke.css', 'contentsInlineCss' => '/site/assets/css/cke_inline.css', 'stylesSet' => 'mystyles:/site/modules/InputfieldCKEditor/mystyles.js', 'extraAllowedContent' => '*[id](*); audio[src,controls,preload]; source[src,type]; button[title]; script; i[data-feather]; svg[xmlns,height,width]; path[d,fill,stroke]', ]; // for each option, check if it's empty and if it is set it to the custom value foreach ($my_settings as $key => $value) { if (empty($inputfield->get($key))) { $inputfield->set($key, $value); } } // get the changes into $event $event->arguments(0, $inputfield); } }); } Now, my CSS files are generated by Sass in the /site/assets/css/ directory, because of the second objective. Thus, I'm including the frontend CSS in three places: the two custom CSS files used by CKeditor in regular/inline mode and defined above ('contentsCss' and 'contentsInlineCss' options), and my custom CSS file used by admin.php. The regular mode CSS files contains: // cke.sass - Sass syntax @import "main" where main.sass is my frontend Sass file (I have a real talent for names, I know). So it includes all the frontend styles in the regular CKEditor iframe. The inline mode CSS file contains: // cke_inline.sass .cke_editable_inline @import "main" This way the frontend styles are applied only to elements inside the CKEditor inline container. I know I'm tying myself to the CKEditor markup, but as you may have noticed by now, I'm quite eager to sell myself in slavery for a bit of convenience πŸ˜„ . The admin styles are built the same, changing only the container class and adding some styles to increase readability: // admin.sass /* force a min width for CKEditor combo, so I can read the text */ .cke_combopanel min-height: 21rem min-width: 25rem > iframe height: 100% !important .cke @import "main" The resulting /site/assets/css/admin.css file is loaded by /site/templates/admin.php by adding $config->styles->add($config->urls->assets.'css/admin.css'); before the require($config->paths->adminTemplates . 'controller.php'); line. Lo and behold, Bulma styles available in the editor toolbar and container (there's a short clip attached). Well, this should be it. I hope it helps someone. If you know a better way to do this or if you notice a mistake/omission, by all means, let me know. Thank you for following me until now - here's the medal you rightly deserve: πŸ₯‡ LATER EDIT: sorry about the video size, I swear it's just a little 578x472px video. ckeditor-2020-04-10-161245.mp4
  15. Thank you! Dude, you really have patience 😁 The source of the problem was the Media Widget plugin , which wraps another figure element on the image element, although now there is an outer figure has the correct class πŸ€·β€β™‚οΈ. I could swear it wasn't there before... Oh well... Didn't need the plugin, so I uninstalled it. To summarize, to have it noted down and to pick the brains of the experts, this is what I did to get the styles working: 1. created /site/assets/css/ckeditor_contents.css (my choice of path) containing some of the framework's styles, like .has-text-danger { color: hsl(348, 100%, 61%); } .is-pulled-left { float: left; } 2. created /site/assets/css/admin.css containing my custom admin styles like /* custom CKEditor styles to have in PW admin interface */ @import url("../../assets/css/ckeditor_contents.css"); /* force a min width for CKEditor combo, so I can read the text */ .cke_combopanel { min-width: 25rem; } 3. imported the same /site/assets/css/ckeditor_contents.css on top of /site/modules/InputfieldCKEditor/contents.css /* custom CKEditor styles to have in PW admin interface */ @import url("../../assets/css/ckeditor_contents.css"); 4. linked /site/assets/css/admin.css on top of /site/templates/admin.php, right at the beginning of the file, before the line requiring the controller $config->styles->add($config->urls->assets.'css/admin.css'); 5. changed classes in the Page Edit Image module settings (the link is /ADMIN_FOLDER/module/edit?name=ProcessPageEditImageSelect) aaaand... I got this (with Bulma classes) 😁 As you see, I have even the kitchen sink in there, it's because of my condition called what-if-I-ever-need-it-osis πŸ˜‚ Thank you!
  16. Thank you for taking the time to answer, Robin. That setting is changing the class of the image inside the figure element, unfortunately. This is the code generated for a right aligned image: <figure class="image"> <img class="align_right" src="/path/to/image/" width="160" /> </figure> I'd like to change the class of the most outer (is that an expression?) container, so I can move it as a block.
  17. Hi, I'm working on a Bulma based site. I'd like to have an experience that's closer to WYSIWYG, so I added some of Bulma classes into mystyles.js and in contents.css. And it works, except when I'm trying to float an image inside CKEditor, using the PWImage plugin. I tried adding { name: 'Image Float Left', element: 'figure', attributes: { 'class': 'is-pulled-left' } }, { name: 'Image Float Right', element: 'figure', attributes: { 'class': 'is-pulled-right' } }, into mystyles.js, but it just ignores me, no class is added to the default "image" class of the wrapping figure element. What am I missing? Thank you πŸ˜€
  18. OK, found the culprit, is the static variable $alreadyFormatted which is set to true at line 527 (module version 106): 525 public function formatExtraValue(HookEvent $event) { 526 if (!self::$alreadyFormatted) { 527 self::$alreadyFormatted = true; I don't know its purpose, but in my case (a loop retrieving captions for an image from every blog post) it stops the text formatter from processing any item after the first one. So I commented it out, I'll see if anything goes wrong.
  19. If it was me editing the pages, I could live with it, but for regular users is confusing. Not to mention paying customers .
  20. Thank you for the module! I'm using it to add a Markdown enhanced captions for some blog images. I have a problem - the text is processed by the Mardown module only for the first image (in ProcessWire 3.0.72 multi language). Could someone give me a hint about where to look, please? I'm stumped. I'm retrieving them like this: <?php foreach (pages('parent=8888') as $item) { ?> <div> <div class="uk-card uk-card-default"> <?php if (count($item->images)) { $item_image = $item->images->getRandom(); ?> <div class="uk-card-media-top"> <figure> <img src="<?=$item_image->size(580, 384, ['quality' => 75])->url?>" title="<?=$item_image->description?>" alt="<?=$item_image->description?>"> <figcaption class="uk-text-meta uk-padding uk-padding-remove-vertical"><?=$item_image->caption?></figcaption> </figure> </div> <?php } ?> <div class="uk-card-body"> <h3 class="uk-card-title"><a href="<?=$item->url?>" title=""><?=$item->title?></a></h3> <p><?=$item->summary?></p> </div> </div> </div> <?php } ?>
  21. My bad, i should've not added that render comment. Sure, I could check the fields to see if they are empty and a 404 is needed. The other languages don't need this check, though. They can be disabled and that's enough. My real question is about the editing interface: how can I hide the default language fields? Thanks for the link to Adrian's module. Unfortunately, as I said in the first post, I'd very much prefer not to separate the translation interface for all pages just because a few of them might not use a language. Also, it appears that the request Adrian made for hooking the Languages class remained unanswered and so, his module cannot currently select the supported languages - it's all or default only. IMO, the dificulty springs from the fact that the "name" and "title" mandatory fields are being used as translations. I'd rather duplicate "default" as English and treat "name" as an ID, but then again, Ryan knows much better than me.
  22. Hello everyone , I searched the forums, but could not find any simple way to take the default language out of one page (or a few pages), like this Homepage en page1 page2 de seite1 (page1 content translated in German) seite2 (page2 content translated in German) seite4 (only in German, no English version - this is what I don't know to do) The way it is now, the default language cannot be disabled, so "seite4" would have the English translation fields in the editing form and would render in the front end. I thought about creating a second English (en) language and hiding the default one, but it won't work because the way ProcessWire treats the "name" field. Another way would be separate trees for each language. That would work for languages with content that is different enough. But for one or a few pages that would not be translated to the default language, I would loose the integrated interface and big image would become more difficult to see. So I'd much prefer not to use it. The last way that crossed my mind was to modify the LanguageSupportPageNames module to update behind the curtain the default language with something while keeping it hidden. That's probably what I'll try given enough time. What do you say? What do I miss? LATER EDIT: I totally don't know any German, used it just as an example.
  23. Hi, I have a bunch of pages and I want to search for words or word parts in their "title" and "tags" field. The "tags" field is a textarea containing a comma separated list. It's a long story, I tried first using pages for tags, but text search was slow and I don't need them to have their own URL anyway, because I'm using query strings to bundle together all the search+filters+sort+pagination parts. Anyways... let me give an example: for instance somebody searches for "rome city". I need to get the results in this specific order: all full words in the title (i.e. both "rome" and "city in the title) all full words in the title or tags all word parts in the title (i.e. parts of both "rome" and "city in the title) all word parts in the title or tags Right now, I'm using merged PageArrays and it's quite a PITA: $results = new PageArray(); // this is computed, but to simplify I'm defining it here directly $searches = array ( 'title~=rome city', 'title|tags~=rome city', 'title%=rome,title%=city', 'title|tags%=rome,title|tags%=city', ); // the 'filter' part comes from a filter form via the whitelist // I'm leaving it in place to show that is precomputed // I took out the sorting and pagination parts $base_selector = array( 'base' => 'parent=1025', 'search' => '', 'filter' => implode(',', filterToSelector($filter)), ); foreach ($searches as $search_lap) { // $search_lap_selector is a temporary array of selectors for this round of search $search_lap_selector = $base_selector; // the current search is inserted into the selectors array $search_lap_selector['search'] = $search_lap; // this gets the ids of the pages already in $results PageArray $cids = array_flip($results->explode('id')); // implodeSelector implodes the selector parts in the correct order during conversion to and from the whitelist // this loop tests if $clip it's already present in $results PageArray and skips it if so, // to preserve the order // I tried with import, but every $results->import messes the results order foreach ($pages->find(implodeSelector($search_lap_selector)) as $clip) if (!isset($cids[$clip->id])) $results->add($clip); } This gets me the results, but, as I said, it's a PITA and somehow it doesn't look right. It would have been very nice if I could use selector groups and attach somehow the results count to the selector, so I could use the results count for sorting. Something like parent=1025, ('title~=rome city'), ('title|tags~=rome city'), ('title%=rome,title%=city'), ('title|tags%=rome,title|tags%=city'), sort=-title_full_matches_count, sort=-title_tags_full_matches_count, sort=-title_part_matches_count, sort=-title_tags_part_matches_count Does anything like this exists?
  24. Hi, Is there a way to use ProcessWire to convert ProcessWire selectors to SQL queries, i.e. like PageFinder does, but using the API?
  • Create New...