Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 10/24/2023 in all areas

  1. TinyMCE inherits this class names from the Page Edit Image module, you can change these classes in the: modules -> configure -> ProcessPageEditImageSelect module
    3 points
  2. FieldtypeListLinks If somehow found myself needing a means to associate items between two lists, and pages this time weren't the answer. So I started to develop this little Fieldtype/Inputfield. It lets you define two lists (let's call them "left" and "right") and declare a mapping between those. 1. Create your field and add options for the "left" and "right" select: 2. Set your labels and how many items it should show: 3. Edit your page and assign items: The module is still very much experimental and the API subject to change. However, I wanted to share what I have and maybe get some ideas and feedback before things get wired too tightly. The module and a little more documentation can be found in its GitHub repo.
    2 points
  3. Intro: Just to let you all know where this comes from... In the last few weeks I had a lot of tasks and projects in regards to SSG (static site generators), mainly some *.js frameworks. While those *.js frameworks weren't anything of my taste I started to love and enjoyed 11ty. I've already re-built some of my personal projects with it (11ty) just on static files (js/json data files), which worked really great. BUT... and this is my reason I post this here... this was hard work to move data into static files. Question: How Do You Do It? How do you handle ProcessWire as a Headless CMS for SSG projects? I tried the Pages2Json and GraphQL modules and even custom URL-Hooks for JSON output... but those solutions didn't fit any of my needs. Not even close. It could be me, but I thought about solutions that were more kind of ready-made for almost all purposes. (Yes, I know PW is more of a toolkit :D But most projects just don't have the budget to allow such custom exports of data.) As I wanted to build more complex sites (even as those are mostly only prototypes whatsoever) with way more data, as in posts, pages and such... I installed a basic Wordpress instance, used Custom Post Type UI for custom post types, I was able to get everything done within minutes. Yes, minutes. It took me 3 minutes to set everything up (5+ post types), while adding data took another 10 minutes for each post type. The result was, that I had specific JSON feeds for everything I needed. wp.domain/wp-json/wp/v2/posts ... /pages .../movies .../authors .../whatever - all in perfectly formatted JSON, even those fields that where references, like categories, topics, and other taxomonies. I'd love to see/hear about your solutions. I'm almost certain that PW should or might need an additional (instead of new) focus. As PW is able to do way more than any other Headless CMS out there... it might and should try to match up (in terms of marketing and onboard solutions). I tried Forestry CMS, DatoCMS, SanityCMS, NetlifyCMS and a lot more Headless CMS the last few weeks... all were nice but FAR away from what a basic PW instance can do. I was shocked how basic, yet praised they (other HeadlessCMS) were in the community. Even without ProModules ProcessWire is way ahead of any Headless CMS I tried/used so far. (SURE! It could be me, but I doubt it.) Maybe I'm missing something but I for sure don't wanna miss out on PW for an awesome solution as a Headless CMS. If there was a native JSON/RestAPI feed like in WordPress or any other like-minded (as in easy) solution in it... it could probably the one solution for all. So... Headless ProcessWire - How Do You Do It? Therefore, as this is way more complex than an average question, I tag some of you right here, as you may know much more about anything in terms of ProcessWire or ProcessWire Headless as me. @ryan @adrian @Robin S @horst @psy @Jonathan Lahijani @teppo @dadish@thomasaull
    1 point
  4. Hello friends, I was playing around with the clamp techniques used to provide progressive font sizing, and it has replaced flowtype.js in most projects. But one of the things that I really missed was the ability to scale based on container width - rather than full viewpoint width. I was also interested in trying to replace fittext.js and learned a very useful technique with reasonable browser support: https://codepen.io/solonmg/pen/ZEwGEay instead of using vw units, you can apply: container-type: size; container-type: inline-size; And then by dividing the character count of a line by 100 and applying the outcome to use cqw units instead of vw units, you get the same scaling type features. If you are trying to get that optimal character/word line length in a given column, this will certainly help! The same clamping limits that already exist based on viewport widths work for containers. I don't know if it makes sense to have separate clamping settings for display text (like headings) and body text, but this is just something I have been playing around with.
    1 point
  5. Look directly into the error log (via FTP): site/assets/logs/errors.txt You should find the error message there.
    1 point
  6. Thanks so much, @7Studio! This works. Now it makes sense, that I saw the placeholders {alignleft}, {aligncenter} and {alignright} in the JSON-file „wire/modules/Inputfield/InputfieldTinyMCE/defaults.json“. Thread-topic solved.? Yes, @AndZyks links are really helpful, but i still have to make friends with the syntax.? What are you trying to accomplish? Maybe me or someone more experienced can help.
    1 point
  7. Yeah, I'm still having issues. @JoseFrasher links helped, but I'm not yet able to get it fully working. Every time I fix something, another gets broken? However @7Studio post did the trick for the images ?
    1 point
  8. Hi, you'll probably find this a little funny but now i'm trying to reproduce your fieldtype abilities but saving data to the database to make it "indexxable" by teppo great search engine as it will allow me to get datas from any database i need even an external one and save it as a field content with or without formatting thanks again for this great module i porbably play a bit too much with ? have a nice day
    1 point
  9. As far as I can tell, this is a current limitation of the core. The default language cannot be deactivated and serves as fallback for non-translated versions.
    1 point
  10. @markus_blue_tomato I'm also thinking of adding support for alternative hashing methods, specifically ThumbHash. The colors with ThumbHash seem to be a bit closer to the original and it also supports alpha channels. Would you be willing to accept a PR for that? I'd love to avoid creating a separate module, as the core logic would just be duplicated. Adding a new setting is much more elegant and allows experimenting with both hashing methods more easily. If it helps and it's possible, I'd be willing to take over maintenance of the module and take it from there.
    1 point
  11. Hi @markus_blue_tomato I've finally come around to investigating the issue where newly uploaded images would keep the old blurhash. I have a working backward-compatible fix ready in a fork, but I see that the module itself has been marked as readonly for a while and I can't create any PRs against it. Would you accept this fix via some other means?
    1 point
  12. I played around and worked a lot with Astro in the last few months, and one thing I really liked was working with <Components />. Right now I try to move my experience from it towards my PW/Twig/Latte setup. Some parts work pretty well, while some things don't work out as expected. Splitting parts isn't that easy in PW, when using PW and Tailwind. Due to the missing build-step. But ok. I can live with it. When using plain CSS, this could be a totally different thing. Yet the CSS and JS isn't scoped. Boooh! I didn't use plain CSS for about 18 months now - which is wild, as I was a plain-CSS-advocate since always. But I am working on it again, which feels super awkward on its own right now, as PW is totally different compared to Astro or the tools I used in the last months. I could imagine using <Components /> in one way or another using Twig/Latte and some ProCache-magic... I could minimize CSS way more, yet I don't know if all that is really necessary. For what I can tell right now... each release with PW and JS/CSS is way bigger than in Astro, as PW has no real page-based build-step. That's fine for me, as most of my projects are super minimal right from the start and get 4x 100 in Google Pagespeed. To be really honest... I am at a point right now in which I really don't care about the last 100-500ms in a pagespeed tool anymore when I at leat get the 94 scores for each step. Addional note: Right now I work on a 11ty/Astro setup that loads all data, pages, and structure from PW in JSON-format. Loading all data (from https://www.restaurants-neumuenster.de/) takes about 1-2 seconds in total while building all pages, data entries, and everything else takes another 3-5 seconds. It works, yet I don't like the result somehow. There are things I really don't like and have to fix in JS/Nunjucks/Liquid or some other parts of the setup. Right now: I focus really on optimized PW Twig/Latte workflows and for minimals sites using JSON using 11ty/Astro as frontend layer.
    1 point
  13. Hello, I would really appreciate your comments on this blog post I am preparing for our site. =========== Creating a dynamic search with very little code in ProcessWire is easy. This search cannot compete with engines like Elasticsearch, Solr, and others. However, it is suitable for most "showcase" sites. Here is how we did it on the Spiria site using the small library htmx and its companion hyperscript. The goal The recipe Inclusion of libraries htmx and hyperscript (the latter is optional). A field of type textarea integrated to the page models that we want to index. A code for indexing the existing content in the file `ready.php` A search controller which we name here `api.php`. This controller will also be a page with the `api` template. A form placed in the pages requiring the search. Content indexing Before we can program, we need to index the content on which we want to apply our search. In my proof of concept, I have developed two strategies. This is probably overrated, because I am not sure of the gain in speed. Index for a single term search Indexing for a multiple term search To do this, we need to introduce two fields in each model where we want an indexation. The `search_text` field which will contain only one occurrence of each word on a page. The `search_text_long` field which will preserve all sentences without HTML tags. We place a hook in the `ready.php` page in this way: <?php namespace ProcessWire; pages()->addHookAfter("saveReady", function (HookEvent $event) { $p = $event->arguments[0]; switch ($p->template->name) { case "blog_article": $french = languages()->get('fr'); $english = languages()->get('default'); $txt_en = $p->page_content->getLanguageValue($english) . ' ' . $p->blog_summary->getLanguageValue($english); $txt_fr = $p->page_content->getLanguageValue($french) . ' ' . $p->blog_summary->getLanguageValue($french); $title_en = $p->title->getLanguageValue($english); $title_fr = $p->title->getLanguageValue($french); $resultEn = stripText($txt_en, $title_en); $resultFr = stripText($txt_fr, $title_fr); $p->setLanguageValue($english, "search_text", $resultEn[0]); $p->setLanguageValue($english, "search_text_long", $resultEn[1]); $p->setLanguageValue($french, "search_text", $resultFr[0]); $p->setLanguageValue($french, "search_text_long", $resultFr[1]); break; } }); And function stripText($t, $s) { $resultText = []; $t = strip_tags($t); $t .= " " . $s; $t = str_replace("\n", " ", $t); $t = str_replace(",", "", $t); $t = str_replace("“", "", $t); $t = str_replace("”", "", $t); $t = str_replace("'", "", $t); $t = str_replace("?", "", $t); $t = str_replace("!", "", $t); $t = str_replace(":", "", $t); $t = str_replace("«", "", $t); $t = str_replace("»", "", $t); $t = str_replace(",", "", $t); $t = str_replace(".", "", $t); $t = str_replace("l’", "", $t); $t = str_replace("d’", "", $t); $t = str_replace("&nbsp;", "", $t); $t = preg_replace('/\[\[.*\]\]/', '', $t); //$t = preg_replace('/\?|\[\[.*\]\]|“|”|«|»|\.|!|\&nbsp;|l’|d’|s’/','',$t); $arrayText = explode(" ", $t); foreach ($arrayText as $item) { if (strlen(trim($item)) > 3 && !in_array($item, $resultText)) { $resultText[] = $item; } } return [implode(" ", $resultText), $t]; } If you have the ListerPro module, it becomes easy to save all the pages to be indexed in batch and any new page will then be indexed as it is created. The `stripText()` function aims at cleaning up the text as we want. Note that, in my example, I distinguish between French and English. This little algorithm is entirely perfectible! I have commented a shorter way to clean up the text, but at the expense of comprehension. As mentioned before, it is probably unnecessary to create two search fields. The most important thing would be to optimize the text as much as possible, as many small words are useless. The current code restricts to words longer than three characters, which is tricky in a computing context like our site where names like `C#`, `C++`, `PHP` compete with `the`, `for`, `not`, etc. That said, perhaps this optimization is superfluous in the context of a simple content and not and limited in number. So now see the process and the research code. The structure structure.svg This scheme is classical and needs few explanations. The `htmx` library allows a simple Ajax call. The form code01.svg The form has a `get` method that returns to a conventional search page when the user presses the `enter` key. A hidden field with the secret key generated on the fly enhances security. The third field is the `input` of the dynamic search. It has a `htmx` syntax. The first command, `hx-post`, indicates the method of sending the data to the API. Here, it is a `post`. `htmx` allows to handle events on any DOM element. So we could have several calls on different elements of a form. The second line indicates where the API response will be sent when received, which is `div#searchResult` below the form. The `hx-trigger` command describes the context of sending to the API. Here, when the user releases a key, with a delay of 200 ms between each reading of the event. The `hx-indicator` command is optional. It tells the user that something is happening. In the example, the `#indexsearch` image is displayed. This is automatically handled by htmx. We have the possibility to pass other parameters to the search with the `hx-vals` command. The given example is simplified. We send the search language. The last command comes from the `hyperscript` syntax. It indicates that if you click anywhere outside the search field, you will make the contents of `#found` disappear, which will be described below. It is clear from this example that no javascript is called, except the [htmx] and [hyperscript] libraries. It is worth visiting the web site of these two libraries to understand their philosophy and possibilities. The Search API The API resides in a normal ProcessWire page. Although it is published, it remains "hidden" from CMS searches. This page allows requests to be answered and the correct functions to be called. Several requests to the CMS can be gathered in this type of page. <?php namespace ProcessWire; $secretsearch = session()->get('secretToken'); $request = input()->post(); $lang = sanitizer()->text($request["lang"]); if (isset($request['CSRFTokenBlog'])) { if (hash_equals($secretsearch, $request['CSRFTokenBlog'])) { if (!empty($request["search"])) { echo page()->querySite(sanitizer()->text($request["search"]),$lang); } } else { echo __("A problem occurred. We are sorry of the inconvenience."); } } exit; In this case : We extract the secret token of the session, token that will have been created in the search form page. We then process everything that is in the `post` query. Note that this is a simplified example. We compare the token with the one received in the query. If all goes well, we call the SQL query. Our example uses a class residing in `site/classes/ApiPage.php`; it can therefore be called directly by `page()`. Any other strategy is valid. The following code represents the core of the process. <?php namespace ProcessWire; public function querySite($q, $l) { $this->search = ""; $this->lang = $l == 'en' ? 'default' : 'fr'; user()->setLanguage($this->lang); $whatQuery = explode(" ", $q); $this->count = count($whatQuery); if ($this->count > 1) { $this->search = 'template=blog_article,has_parent!=1099,search_text_long~|*= "' . $q . '",sort=-created'; } elseif (strlen($q) > 1) { $this->search = 'template=blog_article,has_parent!=1099,search_text*=' . $q . ',sort=-created'; } if ($this->search !== "") { $this->result = pages()->find($this->search); return $this->formatResult(); } return ""; } protected function formatResult() { $html = '<ul id="found">'; if (count($this->result) > 0) { foreach ($this->result as $result) { $html .= '<li><a href="' . $result->url . '">' . $result->title . '</a></li>'; } } else { $html .= __('Nothing found'); } $html .= '</ul></div>'; return $html; } The `formatResult()` function is simple to understand and it is here that we see the `ul#found` tag appear which, remember, is deleted by the _hyperscript_ line of the form. _="on click from elsewhere remove #found" Actually, I've commented out this line in the production code so far. Instead of clicking anywhere, it would be better to add a background behind the form when doing a search in order to focus the `click` event. But again, all strategies are good! In the current code, it is not necessary to add CSS to display the result. It is placed in an empty `#searchResult` tag, so it is invisible at first. As soon as it is filled by the search result, everything becomes accessible, the CSS being targeted on the `ul#found` list and not on its parent. Conclusion The purpose of this article was to demonstrate htmx and the possibilities that this library allows. There is already an excellent search module for ProcessWire, SearchEngine, which can coexist very well with the code described here.
    1 point
×
×
  • Create New...