Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"data-poster" and "data-thumbnail-src" do not recognize placeholders ("poster" and "thumbnail-src" also) #2807

Open
KogucikPL opened this issue Jul 31, 2024 · 1 comment

Comments

@KogucikPL
Copy link

I have a script that replaces placeholders with the corresponding values ​​from a JSON array. In general, the replacement works fine everywhere, but for some reason it doesn't want to work with these attributes.
For example:

<span>I like {{activity}}</span
<img src="/assets/images/{{file}} />

gives

<span> I like reading books</span>
<img src="/assets/images/book.png" />

Expected behaviour:

I would like
<video class="plyyr" playsinline controls data-poster="/assets/video/{{folder}}/thumb.png" data-thumbnail-src="/assets/video/{{folder}}/preview.vtt">
to change to
<video class="plyyr" playsinline controls data-poster="/assets/video/book/thumb.png" data-thumbnail-src="/assets/video/book/preview.vtt">
and then work as "intended", i.e. add a video poster and display thumbnails in the progress bar.

Actual behaviour:

Currently the replacement works. The console and browser see the change. Theoretically, the placeholders change, but despite this, neither the poster nor the preview works.
When it comes to lines like this one, after replacing everything works:
<source src="/assets/video/{{folder}}/1080p.mp4" type="video/mp4" size="1080" />
When I replace the placeholder manually (i.e. I simply enter the path myself), then everything works perfectly, but with the placeholder it does not want to work, even though the browser and console see the change correctly.

Steps to reproduce:

  1. Create a basic player:
<div class="plyr-player">
            <video class="plyyr" playsinline controls data-poster="/assets/video/book/thumb.png" data-thumbnail-src="/assets/video/book/preview.vtt">
              <source src="/assets/video/book/1080p.mp4" type="video/mp4" size="1080" />
              <source src="/assets/video/book/720p.mp4" type="video/mp4" size="720" />
              <source src="/assets/video/book/480p.mp4" type="video/mp4" size="480" />
              <source src="/assets/video/book/360p.mp4" type="video/mp4" size="360" />
            </video>
</div>
  1. Add placeholders:
<div class="plyr-player">
            <video class="plyyr" playsinline controls data-poster="/assets/video/{{folder}}/thumb.png" data-thumbnail-src="/assets/video/{{folder}}/preview.vtt">
              <source src="/assets/video/{{folder}}/1080p.mp4" type="video/mp4" size="1080" />
              <source src="/assets/video/{{folder}}/720p.mp4" type="video/mp4" size="720" />
              <source src="/assets/video/{{folder}}/480p.mp4" type="video/mp4" size="480" />
              <source src="/assets/video/{{folder}}/360p.mp4" type="video/mp4" size="360" />
            </video>
</div>
  1. Add this script:
document.addEventListener('DOMContentLoaded', () => {
    const jsonUrl = `/assets/file.json?v=${new Date().getTime()}`;

    fetch(jsonUrl)
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            return response.json();
        })
        .then(data => {
            function replacePlaceholders(template, values) {
                return template.replace(/{{(.*?)}}/g, (match, key) => {
                    return values[key.trim()] || match;
                });
            }

            function replacePlaceholdersInElement(element, values) {
                if (element.childNodes.length) {
                    element.childNodes.forEach(child => {
                        if (child.nodeType === Node.TEXT_NODE) {
                            child.textContent = replacePlaceholders(child.textContent, values);
                        } else if (child.nodeType === Node.ELEMENT_NODE) {
                            replacePlaceholdersInElement(child, values);
                            replacePlaceholdersInAttributes(child, values);
                        }
                    });
                }
            }

            function replacePlaceholdersInAttributes(element, values) {
                Array.from(element.attributes).forEach(attr => {
                    if (attr.name === 'src') {
                        const newSrc = replacePlaceholders(attr.value, values);
                        console.log(`Setting src attribute to: ${newSrc}`); // Debugging line
                        element.setAttribute('src', newSrc);
                    } else {
                        attr.value = replacePlaceholders(attr.value, values);
                    }
                });
            }

            function replacePlaceholdersInDocument(values) {
                Array.from(document.body.childNodes).forEach(node => {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        replacePlaceholdersInElement(node, values);
                    }
                });
            }

            const values = {};
            data.forEach(item => {
                values[`order${item.order}`] = item.order;
                values[`folder${item.order}`] = item.folder;
                values[`title${item.order}`] = item["title"];
                values[`artist${item.order}`] = item["artist"];
            });

            replacePlaceholdersInDocument(values);

            document.querySelectorAll('img').forEach(img => {
                const srcPlaceholder = img.getAttribute('src');
                const newSrc = replacePlaceholders(srcPlaceholder, values);
                img.setAttribute('src', newSrc);
            });
        })
        .catch(error => {
            console.error('Error loading JSON data:', error);
        });
});
  1. Add a table like this:
[
  {
    "id": 1,
    "order": 1,
    "folder": "book1",
    "title": "Title1",
    "artist": "Artist1"
  },
  {
    "id": 2,
    "order": 2,
    "folder": "book2",
    "title": "Title2",
    "artist": "Artist2"
  }
]

Environment:

  • Browser: Opera GX
  • Version: LVL 5 (core: 109.0.5097.142)
  • Operating System: Windows 11 Pro
  • Version: 23H2 (22631.3880)

Console errors (if any):

None.

Thank you in advance for any help.

@KogucikPL
Copy link
Author

I solved the problem using simple php, more specifically:

<?php
$jsonFile = 'path/to/file.json';

$jsonData = file_get_contents($jsonFile);
$dataArray = json_decode($jsonData, true);

function replacePlaceholders($template, $dataArray) {
    foreach ($dataArray as $data) {
        $order = $data['order'];
        foreach ($data as $key => $value) {
            $placeholder = "{{{$key}{$order}}}";
            if (strpos($template, $placeholder) !== false) {
                $template = str_replace($placeholder, $value, $template);
            }
        }
    }
    return $template;
}

ob_start();
?>

<!-- Some HTML code -->
<div class="plyr-player">
            <video class="plyyr" playsinline controls data-poster="/assets/video/{{folder100}}/thumb.png" data-thumbnail-src="/assets/video/{{folder100}}/preview.vtt">
              <source src="/assets/video/{{folder100}}/1080p.mp4" type="video/mp4" size="1080" />
              <source src="/assets/video/{{folder100}}/720p.mp4" type="video/mp4" size="720" />
              <source src="/assets/video/{{folder100}}/480p.mp4" type="video/mp4" size="480" />
              <source src="/assets/video/{{folder100}}/360p.mp4" type="video/mp4" size="360" />
            </video>
          </div>
<!-- Some HTML code -->

<?php
$htmlContent = ob_get_clean();

$replacedContent = replacePlaceholders($htmlContent, $dataArray);

echo $replacedContent;
?>

Maybe it will be useful to someone in the future. I thank myself for helping lol

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant