Autor Zpráva
pavelrejha
Profil
Zdravím,
potřeboval bych script, který vezme název souboru například 2500.html k číslu přidá +1 (eventuelně -1) a ve výsledku bude odkazovat na 2501.html (2499.html).
Bohužel se mi nedaří sloučit dva scripty, neboť script na přidání čísla, nemá kde ty data vzít neboť "ještě neexistují"...

<script type="text/javascript">
var url = window.location.pathname.replace(/\/+$/, "");
document.write('<a href="' + url.substr(url.lastIndexOf('/') + 1, url.lastIndexOf('.') - 1) + '">Odkaz</a>');
</script>

<span id="vem" style="display:none">2500</span><span id="pridej"></span>

<script type="text/javascript">
window.addEventListener("load",function(){
x = parseFloat(document.getElementById("vem").innerHTML);
document.getElementById("pridej").innerHTML = ((x + 1).toFixed(0))*1;
},false);
</script>

Předem děkuji za pomoc.
anonym_
Profil *
pavelrejha:
Co je cílem, co chceš udělat?
CZghost
Profil
Asi vím, o co se jedná. Soubor 2500.html má odkazovat na předchozí soubor 2499.html a další 2501.html (něco jako stránkování).

Zfušoval jsem menší ukázku: Živá ukázka

Snad jsem něco nepopletl, nicméně to funguje.
anonym_
Profil *
CZghost:
Takto se stránkování opravdu nedělá.
CZghost
Profil
No jistě, stránkování se dá dělat mnohem efektivněji a lépe. Ale funguje to. Většinou se to dělá na stejné webové stránce, nebo se stránkování generuje pomocí PHP či jiného preprocesoru. Smysl to dává maximálně ale u nějakého rozsáhlého návodu. Jinak nedává moc smysl rozdělovat jedno téma na několik samostatných podstránek a odkazovat na předchozí či další kapitoly. Pokud si dělám portfolio, tak většinou se to všechno dává na jednu stránku, případně dám na další stránky nějaké dodatečné funkce. V takovém případě určitě souhlasím s tím, že takto se to opravdu nedělá.
anonym_
Profil *
CZghost:
Ne, nikdy se to takhle nedělá.

Až budu chtít stránku 2000 vyhodit, tak co? Nebo nějakou někam dovnitř vložit. Všechny ostatní budu přejmenovávat?
CZghost
Profil
Proto říkám, že se to dá dělat mnohem efektivněji a lépe. Nikde jsem neříkal, že protože to tak funguje, mělo by se to tak používat.
N71
Profil *
No je to naprd, nalijme si čistého vína.

Skript předpokládám bude chtít být stejný (externí?) na všech stránkách, jinak to celé postrádá smysl. Tím pádem by měl řešit i první a poslední stránku.
No a jak anonym zmínil, pokud by se ta řada měla někdy změnit, tak spánembohem.

Čistě v rovině javascriptu bych asi zvolil načtení nějakého rejstříku (JSON nebo klidně i nativní XML sitemap) a zkusil bych pracovat s ním.
weroro
Profil
Možno iba nemá možnosť generovať to serverovo, alebo to chce podobne ako pri SSG spúšťať si to lokálne dvojklikom na html súbor.

Ak sa jedná naozaj o pagination, tak niečo podobné som dostal pred pár mesiacmi ako zadanie na pohovor.

- Akceptuje to aj číselné názvy, ktoré začínajú nulami (napr. 007.html, 008.html). [na prípone nezáleží, takže tam môže byť aj .php a pod.]
- Je možné nastaviť minimálnu hodnotu (first page) a maximálnu hodnotu (last page), kde sa tieto hodnoty používajú ako hranica po ktorú sa budú generovať next a previous.
- Súbory, ktoré nenasledujú priamo za sebou to rieši pomocou nastavenia zoznamu exclude v konfigurácii, čo je zoznam čísiel, ktoré majú byť preskočené pri generovaní next/prev.

Config je voliteľný a default-ne má nastavený first page na hodnotu 1 a last page na hodnotu null (nekonečne), pole exclude je prázdne.


/**
 * Configuration object for StaticPaging class.
 *
 * @typedef {Object} StaticPagingConfig
 * @property {number[]} exclude - An array of numbers representing excluded page numbers.
 * @property {number} first - The number of the first page.
 * @property {number|null} last - The number of the last page, or null if there is no last page.
 */

/**
 * Represents paging information.
 *
 * @typedef {Object} PageInfo
 * @property {number} current - The current page number.
 * @property {number|null} prev - The number of the previous page, or null if there is no previous page.
 * @property {number|null} next - The number of the next page, or null if there is no next page.
 * @property {string} currentStr - The current page number as string with original zero padding.
 * @property {string|null} prevStr - The number of the previous page as string with original zero padding, or null if there is no previous page.
 * @property {string|null} nextStr - The number of the next page as string with original zero padding, or null if there is no next page.
 * @property {string} ext - The file extension, or empty string if not applicable.
 */

/**
 *
 */
class StaticPaging {
    /**
     * Configuration object for static paging.
     *
     * @type {StaticPagingConfig}
     * @private
     * @readonly
     */
    #_config = {
        exclude: [],
        first: 1,
        last: null
    };

    /**
     * Creates an instance of StaticPaging.
     * @param {StaticPagingConfig} [config] - Optional configuration object.
     * @public
     */
    constructor(config) {
        if (config !== null && typeof config === 'object' && !Array.isArray(config) && Object.keys(config).length > 0) {
            this.#_config = {...this.#_config, ...config};
        }
    }

    /**
     * Gets paging information based on the provided filename or current URL.
     *
     * @param {string} [filename] - The filename or URL from which to extract page information.
     * @returns {PageInfo | null} An object containing current, previous, and next page numbers, along with file extension.
     * @public
     * @example
     * const staticPaging = new StaticPaging({ first: 1, last: 10, exclude: [3, 6, 9] });
     * const pageInfo = staticPaging.getPages('/5.html');
     */
    getPages(filename) {
        /** @type {RegExpMatchArray} */
        const filenameSegments = (
            filename || globalThis.location?.pathname.replace(/\/$/, '').replace(/.*\//, '')
        ).match(/^\/?(\d+)(\.[^.]+)?$/);

        /** @type {string|number} */
        let current = filenameSegments?.[1] || '';
        const currentLength = current.length;
        /** @type {string} */
        const ext = filenameSegments?.[2] || '';

        if (isNaN((current = +current))) {
            return null;
        }

        const prev = this._getStep(current, false);
        const next = this._getStep(current, true);

        return {
            current,
            currentStr: current.toString().padStart(currentLength, '0'),
            prev,
            prevStr: prev?.toString().padStart(currentLength, '0') || null,
            next,
            nextStr: next?.toString().padStart(currentLength, '0') || null,
            ext
        };
    }

    /**
     * Gets the next or previous page number based on the current page number and direction.
     *
     * @param {number} current - The current page number.
     * @param {boolean} dir - The direction (true for next, false for previous).
     * @returns {number | null} The next or previous page number, or null if it's out of range or excluded.
     * @private
     */
    _getStep(current, dir) {
        const step = dir ? 1 : -1;
        let value = current + step;

        while (this.#_config.exclude.includes(value)) {
            value += step;
        }

        if ((!dir && value < this.#_config.first)
            || (dir && (this.#_config.last !== null && value > this.#_config.last))) {
            return null;
        }

        return value;
    }
}

Použitie:

const staticPaging = new StaticPaging();

const pageInfo = staticPaging.getPages();
pageInfo obsahuje objekt v obsahujúci:
{
    current: number, // aktuálne číslo stránky
    currentStr: string, // aktuálne číslo stránky s nulami na začiatku (ak ich pôvodný názov obsahoval)
    prev: number, // predošlé číslo stránky
    prevStr: string | null, // predošlé číslo stránky s nulami na začiatku (ak ich pôvodný názov obsahoval)
    next: number, // nasledujúce aktuálne číslo stránky
    nextStr: string | null, // nasledujúce číslo stránky s nulami na začiatku (ak ich pôvodný názov obsahoval)
    ext: string // prípona súboru s bodkou na začiatku (e.g. '.html')
}

Použitie konfigurácie:
const staticPaging = new StaticPaging({
    first: 1, // prvá stránka
    last: 10, // posledná stránka
    exclude: [3, 6, 9] // vylúčené stránky (aj keby mal súbor názov 6.html alebo 006.html, tak ho to bude ignorovať)
});

Ešte sa to dá mierne vylepšiť (alebo pokaziť - záleží na uhle pohľadu) a to pridaním nejakého fetch requestu, ktorý by kontroloval existenciu naledujúceho alebo predošlého súboru.


Vykreslenie tých buttonov sa môže urobiť nejak takto (použijem ten originálny renderer, čo som mal urobiť ku tomu zadaniu)

class Renderer {
    /**
     * Templates mapping object.
     *
     * @type {{[key: string]: (data: unknown) => string}}
     * @private
     * @readonly
     */
    _templates;

    /**
     * Creates an instance of Renderer.
     *
     * @param {{[key: string]: (data: unknown) => string}} templates - An object containing template functions.
     * @throws {Error} Throws an error if no templates are provided or if templates is not a non-empty object.
     * @public
     */
    constructor(templates) {
        if (!templates || typeof templates !== 'object' || Array.isArray(templates) || !Object.keys(templates).length) {
            throw new Error('No templates provided');
        }
        this._templates = templates;
    }

    /**
     * Renders the specified template into the given container with the provided data.
     *
     * @param {HTMLElement} container - The container element where the template will be rendered.
     * @param {string} templateId - The identifier of the template to render.
     * @param {{[key: string]: unknown}} [data] - Optional data object to be passed to the template function.
     * @returns {void}
     * @public
     */
    render(container, templateId, data) {
        /** @type {string|undefined} */
        const html = this._templates[templateId]?.(data);
        if (!html) {
            return;
        }
        let containerLastChild;
        /** @type {HTMLTemplateElement} */
        const template = document.createElement('template');
        container ||= document.body;
        template.innerHTML = html;
        while ((containerLastChild = container.lastChild)) {
            container.removeChild(containerLastChild);
        }
        container.append(template.content);
    }
}

Potom samotný HTML template:

const TEMPLATES = {
    /**
     * @param {PageInfo} data
     * @returns {string}
     */
    'paging-component': (data) => {
        if (!data) {
            return `<h3>No pages available</h3>`;
        }
        const {currentStr, nextStr, prevStr, ext} = data;
        return `
                <style>
                    .paging {
                        display: flex;
                        gap: .25rem;

                        a, span {
                            padding: 1em;
                            border: .1em solid #3e7ba1;
                            border-radius: 5px;
                            text-decoration: none;
                            user-select: none;
                            -moz-user-select: none;
                            -webkit-user-select: none
                        }
                        a {
                            color: #fff;
                            background: #215575;

                            &:hover {
                                background: #3e7ba1
                            }
                        }
                    }
                </style>

                <div class="paging">
                    ${prevStr !== null ? `<a href="${prevStr}${ext}" title="Previous page">← ${prevStr}${ext}</a>` : ''}
                    <span title="Current page">${currentStr}${ext}</span>
                    ${nextStr !== null ? `<a href="${nextStr}${ext}" title="Next page">${nextStr}${ext} →</a>` : ''}
                </div>
            `;
    },
}

A už to iba celé zavoláme:

const staticPaging = new StaticPaging();
const renderer = new Renderer(TEMPLATES);

document.addEventListener('DOMContentLoaded', () => {
    const container = document.querySelector('#view');
    const pagingData = staticPaging.getPages(); // test staticPaging.getPages('/123.html');

    renderer.render(container, 'paging-component', pagingData);
});



Živá ukázka

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0