ميدياويكي:Common.js
من Sudan Memory
ملاحظة: بعد الحفظ، قد تحتاج إلى إفراغ كاش متصفحك لرؤية التغييرات.
- فايرفوكس / سفاري: اضغط Shift أثناء ضغط Reload، أو اضغط أيا من Ctrl-F5 أو Ctrl-R (⌘-R على ماك)
- جوجل كروم: اضغط Ctrl-Shift-R (⌘-Shift-R على ماك)
- إنترنت إكسبلورر: اضغط Ctrl أثناء ضغط Refresh، أو اضغط Ctrl-F5
- كنكرر: اضغط Reload أو اضغط F5
- أوبرا: أفرغ الكاش في Tools → Preferences
/* الجافاسكريبت الموضوع هنا سيتم تحميله لكل المستخدمين مع كل تحميل للصفحة. */ // ============================================================================= // Formate a poem // 2024-02-27: Created by Abdalla G. M. Ahmed // ============================================================================= // ----------------------------------------------------------------------------- // Measure displayed width of an HTML text // ----------------------------------------------------------------------------- function measureTextWidth(text, font) { var tmpSpan = document.createElement("span"); tmpSpan.style.font = font; // Apply the font style tmpSpan.style.position = "absolute"; tmpSpan.style.visibility = "hidden"; tmpSpan.style.whiteSpace = "nowrap"; tmpSpan.innerHTML = text; document.body.appendChild(tmpSpan); var textWidth = tmpSpan.offsetWidth; document.body.removeChild(tmpSpan); return textWidth; } // ----------------------------------------------------------------------------- // Retrieve font specs of an element // ----------------------------------------------------------------------------- function getFontStyle(node) { var computedStyle = window.getComputedStyle(node); var fontSize = computedStyle.fontSize; var fontFamily = computedStyle.fontFamily; var fontWeight = computedStyle.fontWeight; var fontStyle = computedStyle.fontStyle; var fontVariant = computedStyle.fontVariant; return ( fontStyle + " " + fontVariant + " " + fontWeight + " " + fontSize + " " + fontFamily ); } // ----------------------------------------------------------------------------- // Trim empty leading and trailing entries of an array // ----------------------------------------------------------------------------- function arrayTrim(arr) { var result = arr.slice(); // Clone the array to avoid modifying the original array while (result.length > 0 && !result[0]) { result.shift(); } // Remove empty elements from the beginning while (result.length > 0 && !result[result.length - 1]) { result.pop(); } // Remove empty elements from the end return result; } // ----------------------------------------------------------------------------- // Format contents of a container (e.g., div) as a poem // ----------------------------------------------------------------------------- function poemFormat(poem) { var bWidth = parseFloat(poem.getAttribute('data-bWidth') || 0); // Overall with of beit var bGap = parseFloat(poem.getAttribute('data-bGap') || 50); var pWidth = [0, 0, 0, 0, 0]; // Widths of part for different number of parts, index 0 is used for centered verses var nGaps = [2, 0, 1, 2, 3]; // Number of gaps for different number of parts, initially assuming no leading gaps var fontStyle = getFontStyle(poem); var lines = ( poem .innerHTML // We get the HTML to retain some tags like <a,i,b> .replace(/\s*(<p[^>]*>|<div[^>]*>|<pre[^>]*>)/gi, '') // Remove whitespace before opening container tags and the tags .replace(/<\/p>|<\/div>|<\/pre>/gi, '') // Remove closing tags .replace(/\s*<hr[^>]*>\s*/gi, '\n----\n') .split('\n') // Break into lines, assuming one beit per line ); lines = arrayTrim(lines); // Remove leading and trailing empty lines so that the enclosing <div> tag may be placed in separate lines var formattedLines = []; var tagPlaceholder = '<a><i></i></a>'; // Unlikely to be present and does not affect text size var tags = []; // To store extracted tags for (var i = 0; i < lines.length; i++) { var line = lines[i]; var leadingSpace = ( /^ {2,}/.test(line) ? // Starts with two or more spaces? '<span class="bGap" style="width:'+bGap+'px"> </span>' : // Will be placed at the being '' // Default to none ); line = line.trim(); // Remove leading and trailing spaces if (line === "" || /<br>/.test(line)) { // Empty line formattedLines.push('<br>'); // is replaced by a line break continue; // Done with this line } if (line === "----") { // Separator line formattedLines.push('<hr style="width:%bWidth%px">'); continue; // Done with this line } if (/^!/.test(line)) { // A line starting with an exclamation mark is a comment formattedLines.push( '<p class="bComment" style="width:%cWidth%px">' // "cWidth" is a placeholder until line widths are computed + line.substring(1) + // Remove the exclamation mark '</p>' ); continue; // Done with this line } var closingHalf = false; /*if (line.startsWith('..') && line.endsWith('..')) { // Lines delimited by two dots are treated as closing halves. line = line.substring(2, line.length - 2).trim(); // Remove delimiters and any white space line = '* ' + line.replace(/(\s+)/g, ' '); // Insert a minimal-width dummy half, and remove gaps, if any, to process as two halves closingHalf = true; }*/ if (line.startsWith('.') && line.endsWith('.')) { // Lines delimited by dots are centered. line = line.substring(1, line.length - 1).trim(); // Remove delimiters and any white space pWidth[0] = Math.max(pWidth[0], measureTextWidth(line)); formattedLines.push( '<p class="bMid" style="width:%bWidth%px">' + line + '</p>' ); continue; // Done with this line } // --------------------------------------------------------------------- // From here we assume a regular classic column poem // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Distribute tags over words so that they can be split into parts, // then save tags and replace them with no-space placeholders // --------------------------------------------------------------------- line = line.replace( /(<([abi]+)(?:\s[^>]*)?>)(.*?)<\/\2>/gi, // Match the <a/i/b> tags and capture parameters into positional variables function(match, openingTag, tagName, content) { // Compute replacements based on captured parameters return content // Content inside tag .split(/(\s+)/) // Split at white space and include white spaces in the list .map(function(item) { if (/\S/.test(item)) { // If an item is non-white space tags.push(openingTag, '</' + tagName + '>'); // Save opening and closing tags item = tagPlaceholder + item + tagPlaceholder; // Enclose text item in a dummy tag placeholder } return item; // Whitespace is returned as is }).join(''); // Join all items back together } ); // --------------------------------------------------------- // Extract trailing symbols to align at "قافية" // --------------------------------------------------------- var trailingSymbols = ''; // Default to none line = line.replace( /^(.*?[\u0620-\u064Aa-zA-Z])([^\u0620-\u064Aa-zA-Z]*)$/, // Match trailing non-letter symbols and capture parameters function(match, alphabeticPart, nonAlphabeticPart) { // A function to handle parameters if (match.endsWith(tagPlaceholder)) return match; // Too complex to handle, may consider later trailingSymbols = ( // Extract trailing symbols, if any '<span class="bTrailingSymbols">' // Enclose in a span element to enable separate formatting, if desirable + nonAlphabeticPart + '</span>' ); return alphabeticPart; // Return alphabetic part to replace the original line } ); // --------------------------------------------------------------------- // Split parts // --------------------------------------------------------------------- var nParts = 0; // Number of parts var partWidth = 0; // Maximum part length var parts = ( line .split(/(\s{2,})/) // Split at two or more spaces and include white spaces in the list .map(function(item) { if (/\S/.test(item)) { // An item containing non-space contents is treated as a part nParts++; // Increment number of parts to count this one // --------------------------------------------------------- // Enclose words in spans to enable justification // --------------------------------------------------------- item = ( item .split(/(\s+)/) // Split at white space and include white spaces in the list .map(function(item) { if ( /\S/.test(item) && !item.startsWith(tagPlaceholder) ) { // If an item is non-white space and not already in a tag return '<span>' + item + '</span>'; // Enclose in a span to enable justification } return item; // Return whitespace and tagged items as is }) .join('') // Join all items back together ); // --------------------------------------------------------- partWidth = Math.max( partWidth, measureTextWidth(item, fontStyle) // Update longest part length ); return ( '<span class="bJustified" style="width:%pWidth%px">' + item + '</span>' ); } else { // White space separating parts return '<span class="bGap"> </span>'; // Enclose in a span, typically stylized to preserve spaces } }) ); //if (closingHalf) { parts.shift(); } // Dispense with dummy line = parts.join('').replace(/%pWidth%/g, '%pWidth' + nParts + '%'); // The number of parts is known now pWidth[nParts] = Math.max(pWidth[nParts], partWidth); /*if (closingHalf) { formattedLines.push( '<p class="bMid" style="width:%bWidth%px">' + line + '</p>' ); }*/ //else { formattedLines.push( '<p class="beit">' + leadingSpace + '<span class="bJustified" style="width:%bWidth%px">' + line + '</span>' + trailingSymbols + '</p>' ); //} } for (var i = 0; i < pWidth.length; i++) { var bWidth_i = pWidth[i] ? pWidth[i] * i + nGaps[i] * bGap : 0; // Width to accommodate this number/width of parts bWidth = Math.max(bWidth, bWidth_i); // Accommodate the widest } pWidth = pWidth.map(function(w, i) { return (bWidth - nGaps[i] * bGap) / (i ? i : 1); }); var tagIndex = 0; // To track the current tag being replaced return ( formattedLines .join('') // Concatenate .replace(new RegExp(tagPlaceholder, "g"), function() { // Restore saved tags return tags[tagIndex++]; }) .replace(/%pWidth(\d+)%/g, function(match, i) { // Replace computed part widths return pWidth[i].toFixed(1); }) .replace(/%bWidth%/g, bWidth) // Replace computed overall beit width .replace(/%cWidth%/g, (0.9 * bWidth).toFixed(1)) // Replace width of comments ); } $(function () { document.querySelectorAll('.abyat').forEach(function(poem) { poem.innerHTML = poemFormat(poem); }); var toggler = document.getElementsByClassName("treeBranch"); var i; for (i = 0; i < toggler.length; i++) { toggler[i].addEventListener("click", function() { this.parentElement.querySelector(".treeBranch-nested").classList.toggle("treeBranch-active"); this.classList.toggle("treeBranch-down"); }); } }());