Jump to content

Stefanowitsch

Members
  • Posts

    293
  • Joined

  • Last visited

  • Days Won

    5

Posts posted by Stefanowitsch

  1. 5 hours ago, nbcommunication said:

    Hi @Stefanowitsch,

    Is the module itself logging anything?

    You've got your username in the working example - does adding it to the ajax one change anything?

    Cheers,

    Chris

    No it does not change anything.
    This logs "false" (when executed in the header of the template in the if $config->ajax statment.

     bd($instagram->getMedia('myusername'))

     

  2. 4 hours ago, nbcommunication said:

    Hi @Stefanowitsch,

    I'd start removing layers of complexity - does getMedia() return something outwith the ajax context?

    Is anything being logged by the module in Logs? Does the default user account appear in the module config?

    Cheers,

    Chris

    Yes I have a working instance of the InstagramBasicDisplayApi on my Page. The media is fetched from my account and displayed in a carousel:

    image.thumb.png.739abc068b86603aea7b601ad7e872ad.png

    This is the code, as I mentioned it works fine:

    <ul class="uk-slider-items uk-child-width-1-2 uk-child-width-1-5@m uk-grid">
    
      <?php
    
      // Get the 12 most recent items and render them based on type
    
      foreach($instagram->getMedia('thumann.media',12) as $item) {
    
        switch($item->type) {
          case 'VIDEO':
            $media_src = $item->poster;
            $media_icon = '<i class="fas fa-film"></i>';
            break;
          case 'CAROUSEL_ALBUM':
            // Just get the first item
            $media_src = $item->children->first->src;
            $media_icon = '<i class="far fa-images"></i>';
            break;
          default:
            $media_src = $item->src;
            $media_icon = '<i class="far fa-images"></i>';
            break;
        }
    
      ?>
    
      <li>
        <a href="<?=$item->link?>" target="_blank" rel="noopener">
          <img class="lazyload img-fluid" src="<?=$media_src?>" alt="<?=$item->alt?>"/>
          <?=$media_icon?>
        </a>
      </li>
      <?
    
        }
    
      ?>
    
    </ul>

    Right now only 12 items are fetched. I want to go the next step and load the content of my Instagram channel in batches and append them when scrolling through the carousel.

    So I went to the documentation on the PW modules pages under "Pagination":

    https://processwire.com/modules/instagram-basic-display-api/

    Lazy loading of items can be achieved using getMedia(). The following example shows how to return batches of items using AJAX requests:
    $instagram = $modules->get('InstagramBasicDisplayApi'); // The pagination cursor is reset if the request is not AJAX, e.g. when the page is loaded.
    
    if($config->ajax) {
    	header('Content-Type: application/json');
    	echo $instagram->getMedia(); // ['json' => true] is inferred by $config->ajax
    	die();
    }

    But when I include a Tracy Debugger bardump on the $instagram->getMedia() function here it returns nothing. 

  3. @nbcommunication thanks for your input!

    It seems the problem lies somewhere else. I am trying to get the most basic output but all I am receiving is an empty data object.

    On my home.php template I have this code at the very top:

    <?php
    
    $instagram = $modules->get('InstagramBasicDisplayApi'); // The pagination cursor is reset if the request is not AJAX, e.g. when the page is loaded.
    
    if($config->ajax) {
        header('Content-Type: application/json');
        echo $instagram->getMedia(); // ['json' => true] is inferred by $config->ajax
        bd($instagram->getMedia());
        die();
    }
    ?>

    Then inside my template I have this code below which should do nothing else than send an AJAX request to the page itself to execute the code shown above. Also to make tracy debugger log the WireArray that is returned by the $instagram->getMedia() function.

    <script>
        (async () => {
    
            console.log('try to fetch data');
            try {
                const response = await fetch(window.location.href, {
                    method: 'GET',
                    headers: {
                        'X-Requested-With': 'XMLHttpRequest'
                    },
                    responseType: 'json'
                });
    
                if (response.status === 200) {
                    const data = await response.text();
                    console.log(data);
                }
                else {
                    console.log(response.status);
                    console.log(response.statusText);
                }
    
            } catch (error) {
                console.error(error);
            }
        })();
    </script>

    Wenn viewing the homepage this script is executed but the console.log(data) prints out an empty string.

    The bd($instagram->getMedia()) instruction in the header also logs nothing.

  4. @nbcommunication For my new project I want to make use of the lazy loading function. So I followed the steps in the documentation.

    My main question is: where do I have to put this code?

    $instagram = $modules->get('InstagramBasicDisplayApi'); // The pagination cursor is reset if the request is not AJAX, e.g. when the page is loaded.
    
    if($config->ajax) {
        header('Content-Type: application/json');
        echo $instagram->getMedia(); // ['json' => true] is inferred by $config->ajax
        die();
    }
    
    echo '<div id=instagram class="uk-grid-small uk-child-width-1-2 uk-child-width-1-3@s uk-child-width-1-4@l" data-uk-grid data-uk-lightbox data-uk-scrollspy="target: > div; cls: uk-animation-slide-bottom-small; delay: 128;"></div>';

    It it necessary to enter the user name in the getMedia() function? 

    $instagram->getMedia('my.account');

    When viewing the page I receive the following error in the console. I guess that has to do with the placement of the code above.

    (Index):403 SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

    When placing the code at the top of my template (before the <!DOCTYPE is declared) I receive the following error:

    SyntaxError: Unexpected end of JSON input

     

  5. I can reproduce this behaviour.

    It seems if you copy a text from a website and paste it into the frontend editor all the formatting (this means all HTML tags and elements) are also copied. This works fine on regular body fields that allow HTML tags. For example you can just copy & paste entire HTML tables without creating them in the editor from scratch.

    But when you then copy this text into a field that is set to not allow html tags it results in this kind of mess in the frontend:

    image.png.e2fc51d21c0125a2bd47a5cf28f8ecf9.png

    In the Backend it looks like this:

    image.png.f8dbe20db0b217a9146900ff30ffca1e.png

    This is because of the Textformatter settings for this headline field. HTML Tags are just rendered as plain text.

    image.png.ba1392aad8b0d7a373feeda6f990b32a.png

    • Thanks 1
  6. 6 hours ago, Boost said:

    Hei @Stefanowitschjust one question. For the FieldsetPage approach, do you create specific fields for it? For example, I have a single image field that I use in multiple templates, but for use on my FieldsetPage, I would like that the single image field have a fixed image height and width (which is specific only to one template). So, how do you work on this case? Do you create another image field, or is there a way to customise field properties inside the Fieldset page?

    I like to re-use most of the fields. For example in most projects i have one body field, one headline field and one (single) image field. With fieldsets I can reuse these fields as often an as much on a single template as I want. As long as the field settings not differ that much there is no use to create a "body2" or "body3" field.

    BUT if you need to alter the field settings in one case it is possible to override these changes on a fieldset-basis.

    For example I have this fieldset here with two generic input fields: A single image field and a body copy field.

    image.thumb.png.e465e8952d588687c06e8fc306115ac1.png

    These are generic fields that I use all over the place.

    If I want to make slight changes to those fields in the context of the fieldset I can edit the fieldset and then click on the name of one of the fields inside it.
    This will open a dialogue where you can override very basic field settings.

    It is in most cases not possible to customize a field very much this way. For example you can't change the width and height cropping properties on an image field.

     

    • Like 1
  7. After upgrading the PW Version to the latest master version 3.0.227 I get the message that there are two versions of the TinyMCE installed:

    image.png.8711dda1136033bfccc0df00ad2455c0.png

    This is because before the TinyMCE was officially a part of the PW core I installed it manually. 

    My question is: Is it "safe" to just delete the module folder of the manually installed version that lives in the /site/modules folder? I want to make use of the core version from now on.

  8. 1 hour ago, Ivan Gretsky said:

    @bernhardis so productive I must have missed the RockPageBuilder thing. Can't find it on github. @Stefanowitsch, where did you get it?))

    Ahh. Should've read it from the start) It is explained earlier in this thread.

    Yeah I had the pleasure to be one of the earliest customers who uses this module and already made a few websites with it. Once it's released I will give some insight here in the board how I created this and that with it. It's a really powerful tool!

    • Like 1
  9. Hello!

    I know exactly what you are meaning. Well you have at least three possibilites:

    1. Use the Fieldset Page in ProcessWire. With this you can combine fields into one Fieldset. I don't use this Fielset anmyore but if I remember correct you have to install it from the "Core Modules Tab" (under: /processwire/module/).
    You create a new field (name it for example fieldset_introduction) and then you add fields to it that you want to make use of (cool thing: you can reuse this fields in all other fieldset page fields and don't have to create a "body copy field" for each and everyone of them separetely!)

    image.png.33e2b58e25c7f2e16c76848980c9c79d.png

    And here is what it looks like on a page template. The fields shown above are aligned in a fieldset named "Introduction". You can add several Fieldsets this way and just put them in any order on your page template. 

    image.thumb.png.f42aede2ec59121f2b507548f1d41904.png

    2. Use the Repeater Matrix Pro Field. This ones commercial but it makes handling and editing Sections on your pages much easier and more flexible! 

    Cool thing is that you can define your content blocks in the field settngs and add the needed fields right there. Then on your page template you can select the type of content block (or name it section):

    image.thumb.png.fd5f5be943da86c469dbc8d5ae914511.png

    After that it's super easy and comfortable to edit these sections and also change their order!

    image.thumb.png.6c380619a988c10ce2218336a34f60c5.png

    3. Use a third party page builder module like the RockPageBuilder from @bernhard. This module even beats the popular Repeater Matrix module in my opinion as it accelerates the creation and editing (and managing!) of content massively! Even better, it kind of combines the Repeater Matrix block-buidling functions with frontend editing which is a massive leap forward in terms of workflow optimization and customer happiness (cause it is also very easy to use for non-technically experienced users!).

    image.thumb.png.61476f3f899b4ac132d15b0eda64117e.png

    image.thumb.png.a60f2d7595b34bd489a8835bc8c0eaf6.png

    • Like 6
  10. I now changed Line 322 in InputfieldImageMarker.module from

    $addInfoPages = $modules->get('InputfieldAsmSelect');
    
    foreach($opts as $opt) $addInfoPages->addOption($opt->id, $opt->title);

    to:

    $addInfoPages = $modules->get('InputfieldAsmSelect');
    
    foreach($opts as $opt) $addInfoPages->addOption($opt->id, $opt->headline);

    Now the headline is shown as title in the select field:

    image.png.679285be19bcaa66f784c5da89649cee.png

    But the bummer is: It turns out that this field does not work properly inside a repeater matrix. The table with the marker coordinates never shows up after saving 😞

  11. 2 hours ago, bernhard said:

     

    Ah sorry, my bad! This is not what I meant.

    I want to make the headline field of the repeater item pages shown in my screenshot to be listed in the AsmSelect Inputfield of the Image Marker Field.

    Right now this AsmSelect Field is only showing the page ID's of the repeater item pages:

    image.png.97d67e8911e9cddaef37b394005d490e.png

    I don't know if this is even possible via hook.

  12. On 9/9/2023 at 10:39 AM, bernhard said:

    I guess the module uses something like $page->get('title|id') for the labels and since your page has no title field it falls back to the id.

    You can easily overwrite the "title" property of your page via hook! In this example I overwrite it for the "repeater_rpb_textgrid_items" template and set it to display the field "rpb_textgrid_headline" instead of "title":

    <?php
    $wire->addHookProperty("Page(template=repeater_rpb_textgrid_items)::title", function ($event) {
      $event->return = $event->object->rpb_textgrid_headline;
    });

     

    That's an interesting approach. The repeater items are located here in this case (rep_stories), how would I hook into the title rendering function in this case?
    image.thumb.png.93c26dae547d8ad12c991cc4fe08b5b7.png

  13. I am in the need of using this module in a current project 🙂

    Turns out it works just as fine as I could ever wish! Except one thing:

    I want to make use of Repater Field Items as selectable pages only.

    So I added this line of code in the field settings. The page ID in this case is my repeater field that contains the child elements (=pages) that I want to be able to select.

    image.png.5196a4e7f46f1bca610224451b9bb71c.png

    This works but unfortunately I see only the page IDs in the AsmSelect Inputfield as labels:

    image.png.1b6a84bc3556b141ac402184c9bc2cdb.png

    I know that there is a setting for the AsmSelect to tell which field to use for the label:

    image.png.b3e46800a646e1dbba33b4c71d7c6763.png

    BUT since the AsmSelect in the ImageMarker module is generated via API code it is not possible to adjust this setting.

    @kongondo can you help me out on this one? it is somehow possible to tell the AsmSelect which field to use as a label?

     

  14. 8 minutes ago, cpx3 said:

    Actually, the answer is much simpler. I had the same problem with another script. When I call the page with "url: '/ajax/captcha-verify'", the data gets deleted, with url: '/ajax/captcha-verify/' it works. Thanks to everybody!

    Ah that is a classic mistake I also made in the past. Page paths always have to end with a backslash in ProcessWire (but that is adjustable in the template settings!).

    When you call up an URL you can leave the backslash - this will work - but in that case theres a redirect going on that leads to the data-loss when submitting form data.

    • Like 1
  15. On 1/6/2019 at 10:46 PM, Robin S said:

    I tested it too, and the problem occurs when the paragraph is longer than the truncate length, causing there to be no closing </p> tag present in the truncated string.

    There is an option for the fixUnclosedTags() method used by truncate, to close instead of remove unclosed tags...

    * Fix/close unclosed tags:
    * ------------------------
    * When the remove option is false, it will attempt to close unclosed tags rather than 
    * remove them. It doesn't know exactly where they should be closed, so it appends the 
    * close tags to the end of the string. 

    ...but the truncate method calls fixUnclosedTags() with remove = true and doesn't provide a way to do otherwise. I guess you could use WireTextTools::fixUnclosedTags() before calling $sanitizer->truncate but it would be nice to have the option built into the truncate method. Maybe an oversight by Ryan?
    Edit: request opened here: https://github.com/processwire/processwire-requests/issues/253

     

    @bibsch, because your truncate length is short and will only contain a single paragraph you can achieve your objective by adding <p> tags around your truncated text:

    echo '<p>' . $sanitizer->truncate($child->body, 200) . '</p>';

     

    I am stumbling over and over again over this issue and I really think this should be fixed, or at least the 'remove' option of the fixUnclosedTags() Function should be adjustable in the $sanitizer->truncate() method. @ryan

  16. 15 hours ago, elabx said:

    A bit offtopic: Specifically in UIkit I've overcome most some of these issues adding the classes along the attributes of the components, for example if you have a uk-dropdown or uk-drop components, add the uk-drop class too. See how the uk-drop class is the one with the display:none property, hence the issue of seeing it when the js hasn't added the class to the component.

    .uk-drop {
        display: none;
        position: absolute;
        z-index: 1020;
        --uk-position-offset: 0px;
        --uk-position-viewport-offset: 0;
        box-sizing: border-box;
        width: 300px;
    }

    All assuming you load the CSS before the document.

    Ah! That did the trick. Thank you!

    I now went from this:

    return "<div class='uk-navbar-dropdown'><ul class='uk-nav uk-navbar-dropdown-nav'>$output</ul></div>";

    To this (also added the 'uk-drop' class as you mentioned).

    return "<div class='uk-navbar-dropdown uk-drop'><ul class='uk-nav uk-navbar-dropdown-nav'>$output</ul></div>";

    Now I can use "defer" without having the flashy dropdown menus on page load. This is a trick I bet I want to try on some other UIkit components aswell, if they behave a little bit clunky.

    • Like 3
  17. It seems you have more and more options nowadays to use everyday things.

    One thing I don't like about using the "defer" method (even it seems as the go-to method today) is that when you make use of frontend frameworks that manipulate the look of elements on your website this results in some ugly "jumping around of elements that are not aligned/styled yet because the script is waiting to be executed".

    I am using UIkit and when using "defer" on the uikit.min.js file it will execute after the HTML is parsed. So for a few milliseconds on page load you can see some of the  dropdown menus visible in the main navigation for example. That is because I make use of the uk-navbar component, which relies on the uikit.min.js file:

    uk-navbar="align: center; animation: uk-animation-slide-top-small; animate-out: true"

    When loading the script the normal way (no defer or async) you see no dropdown menu at all when the page is loaded. Because then the script is executed before all of the page is loaded.

    I think even when there are best-practices how to to stuff you always should check what is more important for your project. Having a consistent look or save a few fractions of some milliseconds on loading time.

    • Like 1
  18. For me personally I see RockFrontend as a tool for development. Not a frontend framework. 

    The main reasons why I am using RockFrontend are:

    - Auto Refresh
    - Make use of the rfGrow Feature for fluid font sizes
    & Handling Assets:
    - Auto compile LESS to CSS
    - Minify CSS and JS Files

    I know that there are already some JS-Snippets included (like rf-scrollclass) but I it's too tempting to start in including more and more Frontend Framework features. I personally use only a fraction of what RockFrontend offers and it's hard keeping track because new features arrive continuously 🙂 

    If more and more frontend framework features will be included at some point in the future you have to decide wether RockFrontend will evolve into it's own frontend framework, shipping scripts and styles for everyday usages.

    • Like 4
  19. 6 hours ago, protro said:

    Hi @bernhard is it possible to load a <script> tag or to load specific javascript file for only a specific page and/or template using Rockfrontend ? Right now _main.php is handling all scripts site-wide. Was wondering how granular this can go.

    Thanks for such a great module.

    As far as I know (and I haven't used this feature yet!) this should be possible (found here: https://processwire.com/modules/rock-frontend/)

    You can make use of the addIf() function to load a script only under special circumstances.

    Adding assets to your site (JS or CSS)


    While you can always add custom <script> or <link> tags to your site's markup it is recommended that you use RockFrontend's AssetsArray feature:

    $rockfrontend->scripts()
      ->add('/path/to/your/script.js')
      // you can add any custom flags to your $rockfrontend variable at runtime!
      ->addIf('/path/to/foo.js', $rockfrontend->needsFooScript)
      ->addIf('/path/to/slider.js', $page instanceof HomePage)
      ->addIf('/path/to/blogscript.js', $page->template == 'blogitem')
      ;
    $rockfrontend->styles()
      ->add(...)
      ->addIf(...)
      ;

    There are several reasons why this is preferable over adding custom script/style tags:

    • addIf() keeps your markup file cleaner than using if / echo / endif
    • It automatically adds timestamps of files for cache busting
    • You can inject scripts/styles from within other files (eg PW modules)

    RockFrontend itself uses this technique to inject the styles and scripts necessary for frontend editing (ALFRED). Have a look at the module's init() method!

    • Like 1
    • Thanks 1
×
×
  • Create New...