1. Chokri.Z

    Chokri.Z مشرف موقع أكتب كود

    مـــقـــدمـــة
    في الكثير من المواقف في مجال برمجة و تطوير المواقع و خاصة منها التعليمية، و سعيا وراء تسهيل الأمر على المستخدمين، قد نجد من بين الخيارات المعروضة بعض الإضافات و ذلك حسب الحاجة.
    سنتكلم اليوم على خيار مهم جدا للمواقع التعليمية خاصة، و هو نسخ محتوى أكواد أو رموز توضيحية إلى لوحة المفاتيح، لكي يتم لصقها في مرحلة ثانية.

    الفــكــرة
    سنقوم بإذن الله، في مرحلة أولى بإنشاء محتوى داخل عنصر HTML .
    ثم في مرحلة ثانية سنقوم بإضافة زر يمكننا من القيام بعملية نسخه ( المحتوى ) عند الضغط على الزر .
    سيكون الزر إن شاء الله مخفي و لا يظهر إلا في حالة مرور الفأرة "mouse" فوق المحتوى.

    أخيرا و ليس آخرا، سنضيف زر ثاني للسماح بالتنقل بين خيار ثيمات اللون ( themes ).
    سنحدد عدد الثيمات إلى إثنان و هما الشائعان وضع الإضاءة والوضع المظلم نسبيا. (Light and Dark modes ).

    هذه الإضافة هي من باب التسهيل على المستخدم أيضا و هي لا تقل أهمية عن الأولى.

    يــتــبــع

     
  2. Chokri.Z

    Chokri.Z مشرف موقع أكتب كود

    تــهـيـئــة الــبيـئـة

    الطريقة المستعملة
    هناك أكثر من طريقة لفعل ذلك. الشائع منها:
    واجهة برمجة تطبيقات الحافظة (The Clipboard API)
    طريقة الإستعمال : navigator.clipboard
    لمزيد من المعلومات، MDN

    في هذا المثال سنستعمل "clipboard js" و هي عبارة عن مكتبة خفيفة تمكن من نسخ النص إلى الحافظة بأقل خطوات، و يمكن تحميلها من هـنا. (هي المفضلة لدي :) )
    بعد التحميل، سنحتاج فقط مجلد "dist" الذي بداخله ملفنا المنشود "clipboard.min.js".

    المكتبة بها العديد من الميزات سنحتاج في مثالنا إثنان منها فقط.
    الميزة الأولي هي عملية النسخ و هي ضرورية. أما الثانية، فهي تضليل النص و هي إختيارية.


    نبدأ على بركة الله بإنشاء ملف بامتداد "html." وسميه ما تشاء.
    كنت قد ذكرت في مشاركة السابقة بأننا سنقوم بإنشاء محتوى داخل عنصر HTML.
    سنأخذ هذا المحتوى من هذه المشاركة و نعمل علية، ليصبح:​
    كود HTML:
    <pre id="contToCopy" aria-label=""><code>
        <span class="html">&lt;!doctype <span class="attr">html</span>></span>
        <span class="html">&lt;html</span> <span class="attr">lang</span>=<span class="text">"en"</span><span class="html">></span>
            <span class="html">&lt;head></span>
                <span class="html">&lt;meta</span> <span class="attr">charset</span>=<span class="text">"utf-8"</span><span class="html">></span>
                <span class="html">&lt;meta</span> <span class="attr">name</span>=<span class="text">"viewport" content="width=device-width"</span><span class="html">></span>
                <span class="html">&lt;title></span>The "pre" html element<span class="html">&lt;/title></span>
            <span class="html">&lt;/head></span>
            <span class="html">&lt;body</span>
                <span class="comm">&lt;!-- I am an HTML body content --></span>
                <span class="html">&lt;div</span> <span class="attr">class</span>=<span class="text">"navbar"</span><span class="html">></span>
                    <span class="html">&lt;a</span> <span class="attr">href</span>=<span class="text">"!#home"</span><span class="html">></span>Home<span class="html">&lt;/a></span>
                    <span class="html">&lt;a</span> <span class="attr">href</span>=<span class="text">"!#news"</span><span class="html">></span>News<span class="html">&lt;/a></span>
                    <span class="html">&lt;a</span> <span class="attr">href</span>=<span class="text">"!#contact"</span><span class="html">></span>Contact<span class="html">&lt;/a></span>
                <span class="html">&lt;/div></span>
    
                <span class="php">&lt;?php</span>
                    <span class="comm">// I am a PHP body content</span>
                    <span class="text"><span class="key-word">echo</span> 'Hello World'</span>;
                <span class="php">?></span>
    
                <span class="html">&lt;script></span>
                    <span class="comm">// I am a JavaScript body content</span>
                    <span class="key-word">const</span> <span class="var">btn</span> = <span class="js-key-word">document</span>.<span class="js-comm-txt">querySelector</span>(<span class="text">'#get-code'</span>);
                <span class="html">&lt;/script></span>
            <span class="html">&lt;/body></span>
        <span class="html">&lt;/html></span>
    </code></pre>


    كما لحظنا، أدخلنا العديد من التغييرات على جل العناصر بإسنادها فئة "class"
    كما أسندنا للعنصر "pre" معرف وحيد "id". هذا سيفيد في التنسيق و التعريف لدي الجفا سكريبت.

    عل ذكر التنسيق، سنحتاج بعض الأيقونات و أنا اخترت مكتبة "fontawesome" الموجودة بالمرفقات.
    سنحتاج أيضا ملف صورة و الذي سيكون خلفية زر النسخ و أنا اخترت بامتداد "svg." و الموجود أيضا بالمرفقات.

    المرحلة القادمة بإذن الله، ستكون مرحلة التطبيق.

    يــتـــبـــع
     
  3. Chokri.Z

    Chokri.Z مشرف موقع أكتب كود

    قبل أن نشرع في العمل ينقصنا ملف الـ "JQuery" الذي لا غنا عنه إذا أردنا استعمال حدث النقر "click event" في الجفا سكريبت.
    الملف سيكون في المرفقات إن شاء الله. و لمن أراد تحميله من جديد فمن هنا.

    إذا، لدينا ملف HTML يحتوي على عنصر "pre"، مع جميع الملفات الأخرى المطلوبة.​
    كود:
    <!doctype html>
    <html lang="en">
    
        <head>
    
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width">
            <title>The HTML element "pre"</title>
     
        </head>
    
        <body class="light-theme">
            <main class="content">
          
                <div class="pre-content">
                  <pre id="contToCopy" aria-label=""><code>
                    <span class="html">&lt;!doctype <span class="attr">html</span>></span>
                    <span class="html">&lt;html</span> <span class="attr">lang</span>=<span class="text">"en"</span><span class="html">></span>
                      <span class="html">&lt;head></span>
                        <span class="html">&lt;meta</span> <span class="attr">charset</span>=<span class="text">"utf-8"</span><span class="html">></span>
                        <span class="html">&lt;meta</span> <span class="attr">name</span>=<span class="text">"viewport" content="width=device-width"</span><span class="html">></span>
                        <span class="html">&lt;title></span>The "pre" html element<span class="html">&lt;/title></span>
                      <span class="html">&lt;/head></span>
                      <span class="html">&lt;body</span>
                        <span class="comm">&lt;!-- I am an HTML body content --></span>
                        <span class="html">&lt;div</span> <span class="attr">class</span>=<span class="text">"navbar"</span><span class="html">></span>
                          <span class="html">&lt;a</span> <span class="attr">href</span>=<span class="text">"!#home"</span><span class="html">></span>Home<span class="html">&lt;/a></span>
                          <span class="html">&lt;a</span> <span class="attr">href</span>=<span class="text">"!#news"</span><span class="html">></span>News<span class="html">&lt;/a></span>
                          <span class="html">&lt;a</span> <span class="attr">href</span>=<span class="text">"!#contact"</span><span class="html">></span>Contact<span class="html">&lt;/a></span>
                        <span class="html">&lt;/div></span>
    
                          <span class="php">&lt;?php</span>
                            <span class="comm">// I am a PHP body content</span>
                            <span class="text"><span class="key-word">echo</span> 'Hello World'</span>;
                          <span class="php">?></span>
    
                        <span class="html">&lt;script></span>
                          <span class="comm">// I am a JavaScript body content</span>
                         <span class="key-word">const</span> <span class="var">btn</span> = <span class="js-key-word">document</span>.<span class="js-comm-txt">querySelector</span>(<span class="text">'#get-code'</span>);
                        <span class="html">&lt;/script></span>
    
                      <span class="html">&lt;/body></span>
                    <span class="html">&lt;/html></span>
                  </code></pre>
                </div>
            </main>
        </body>
    </html>
    


    كما لحظنا، اعتمدنا الثيمة "theme" الإفتراضية "light mode" و ذلك عندما اسندنا للهيكل "body" فئة "light-theme".
    كما سبق الذكر، سنعتمد ثمتان فقط. و سيكون الإنتقال من نمط لآخر عبر النقر على زر.​
    كود HTML:
    <button type="button" class="theme-btn" title="Click to switch theme">
        <i class="fa-duotone fa-2x fa-moon-stars"></i>
    </button>

    نلاحظ في الكود أن الزر يحتوي على أيقونة.
    سيتم تغييرها تلقائيا عند الإنتقال من ثمة أو نمط لآخر. و ذلك عند عملية النقر.

    ملف النمط "CSS"
    كود PHP:
    @charset "UTF-8";
    :
    root{
        
    font-size16px;
    }
    .
    light-theme{
        --
    pre-content-bg-color#f8f8f8;
        
    --pre-color#141414;
        
    --pre-content-border-colorrgb(1247154);
     
        --
    btns-bg-colortransparent;
     
        --
    text-colorrgb(19315570);
        --
    comment-colorrgb(180180180);
        --
    html-colorrgb(99236);
        --
    attr-colorrgb(561077);
        --
    key-word-colorrgb(27070255);
        --
    key-word-php-colorrgb(250816);
        --var-
    colorrgb(1008193);
        --
    js-key-wordrgb(149597);
        --
    js-comm-txtrgb(120120120);
    }
    .
    dark-theme{
        --
    pre-content-bg-colorrgb(385056);
        --
    pre-color#d4d4d4;
        
    --pre-content-border-colorrgb(195232121);
     
        --
    btns-bg-colortransparent;
     
        --
    text-colorrgb(195232141);
        --
    comment-colorrgba(180180180.3);
        --
    html-colorrgb(1605872);
        --
    attr-colorrgb(24115963);
        --
    key-word-colorrgb(153134234);
        --
    key-word-php-colorrgb(1783356);
        --var-
    colorrgba(38110226);
        --
    js-key-wordrgb(15010025);
        --
    js-comm-txtrgb(180180180);
    }

    *, :
    before, :after {
        
    padding0;
        
    margin:0;
        -
    webkit-box-sizingborder-box;
        -
    moz-box-sizingborder-box;
        
    box-sizingborder-box;
    }

    .
    content::after {
      
    clearboth;
      
    content"";
      
    displayblock;
      
    height0;
      
    visibilityhidden;
    }

    .
    theme-btn{
        
    positionabsolute;
        
    top25px;
        
    left170px;
        
    background-color: var(--btns-bg-color);
        
    font-sizecalc(100% - 3px);
        
    text-aligncenter;
        
    bordernone;
        
    cursorhelp;
        
    box-shadownone;
        
    z-index:999;
    }
    .
    theme-btn:focus i{
        -
    webkit-transition.3s;
        -
    moz-transition.3s;
        
    transition.3s;
    }

    .
    light-theme .theme-btn i{
        
    colorrgb(385056);
    }
    .
    dark-theme .theme-btn {
        
    color#f8f8f8;
    }

    .
    pre-content {
        
    positionrelative;
        
    displaytable;
        
    width700px;
        
    margin16px auto;
        
    background-color: var(--pre-content-bg-color);
        
    border-radius4px;
        
    border1px solid var(--pre-content-border-color);
        
    clearboth;
        
    overflowauto;
    }

    @
    media screen and (max-width768px) {
        .
    pre-content {
            
    width600px;
            
    padding0;
        }
    }
    .
    pre-content:hover .copy-button,
    .
    pre-content:focus .copy-button {
        -
    moz-opacity1;
        
    opacity1;
        -
    webkit-animationfade-out .5s;
        -
    moz-animationfade-out .5s;
        
    animationfade-out .5s;
    }

    pre {
        
    displaytable-cell;
        
    color: var(--pre-color);
        
    overflowauto;
    }

    pre,
    code {
        
    background-color: var(--pre-content-bg-color);
        
    font100%/20px Consolas,Lucida Console,Menlo,Monaco,monospace;
        
    margin0;
        
    padding0;
        
    text-shadownone;
        
    z-index0;
    }

    pre,
    pre code {
        
    directionltr;
        
    white-spacepre-wrap;
        
    word-spacingnormal;
        -
    moz-tab-size4;
        
    tab-size4;
        -
    webkit-hyphensnone;
        -
    ms-hyphensnone;
        
    hyphensnone;
    }

    pre code span.html {
        
    color: var(--html-color);
    }

    pre code span.php {
        
    color: var(--key-word-php-color);
    }
    pre code span.text{
        
    color: var(--text-color);
    }

    pre code span.js-key-word {
        
    color: var(--js-key-word);
    }

    pre code span.js-comm-txt {
        
    color: var(--js-comm-txt);
    }

    pre code span.attr {
        
    color: var(--attr-color);
    }

    pre code span.comm{
        
    color: var(--comment-color);
    }
    pre code span.var{
        
    color: var(--var-color);
    }
    pre code span.key-word{
        
    color: var(--key-word-color);
    }

    button{
      
    font-weight300;
      
    line-height1.6;
      
    font-size100%;
    }

    .
    copy-button /****/
        
    width22px;
        
    height22px;
        
    displayblock;
        
    positionabsolute;
        
    top2%;
        
    leftcalc(100% - 27px);
        
    background#f8f8f8 url("clippy.svg");
        
    background-size60auto;
        
    background-positioncenter center;
        
    background-repeatno-repeat;
        
    border1px solid rgba(0000.29);
        
    cursorcopy;
        
    border-radius3px;
     
        -
    moz-opacity0;
        
    opacity0;
        
    overflowvisible;
     
        -
    webkit-transformtranslateY(-2%);
        -
    moz-transformtranslateY(-2%);
        
    transformtranslateY(-2%);
     
        -
    webkit-transitionopacity 0.3s;
        -
    moz-transitionopacity 0.3s;
        -
    o-transitionopacity 0.3s;
        
    transitionopacity 0.3s;
     
    }
    @
    media screen and (max-width768px) {
        .
    copy-button {
            -
    moz-opacity1;
            
    opacity1;
        }
    }

    .
    copy-button:hover,
    .
    copy-button:focus {
        
    background-color#eaeaea;
        
    box-shadow0 1px 1px rgba(0000.12);
    }

    .
    copy-button::before {
        
    displaynone;
        
    width0;
        
    height0;
        
    positionabsolute;
        
    top25%;
        
    left: -11px;
        
    content"";
        
    border-top5px solid transparent;
        
    border-bottom5px solid transparent;
        
    z-index999;
    }

    .
    copy-button::after {
        
    displaynone;
        
    width80px;
        
    height34px;
        
    positionabsolute;
        
    top13px;
        
    left: -90px;
        
    contentattr(data-tooltip);
        
    font-size14px;
        
    font-weightbold;
        
    line-height34px;
        
    text-aligncenter;
        
    border-radius3px;
        
    z-index999;
     
        -
    webkit-transformtranslate(0, -50%);
        -
    moz-transformtranslate(0, -50%);
        
    transformtranslate(0, -50%);
    }

    .
    light-theme .copy-button::before {
        
    border-left7px solid var(--pre-content-border-color);
    }

    .
    light-theme .copy-button::after {
        
    background-color: var(--pre-content-border-color);
        
    color#fff;
    }

    .
    dark-theme .copy-button::before {
        
    border-left7px solid var(--pre-content-border-color);
    }

    .
    dark-theme .copy-button::after {
        
    background-color: var(--pre-content-border-color);
        
    color#1a1a1a;
    }

    .
    copy-button:focus::before,
    .
    copy-button:focus::after,
    .
    copy-button:hover::before,
    .
    copy-button:hover::after {
        
    displayblock;
        -
    moz-animationfade-out .3s;
        -
    webkit-animationfade-out .3s;
        
    animationfade-out .3s;
    }

    @-
    moz-keyframes fade-out {
        
    0%{ -moz-opacity0; }
        
    100%{ opacity1; }
    }
    @
    keyframes fade-out {
        
    0%{ opacity0; }
        
    100%{ opacity1; }
    }

    ملف الجفا سكريبت
    كود PHP:
    'use strict';

    $(function () {
     
        const 
    copy_btns document.querySelectorAll('.copy-button');
        if(
    copy_btns){
            var 
    clipboard = new ClipboardJS('.copy-button');
            
    clipboard.on('success', (e) => {
                for (
    let i 0copy_btns.lengthi++) {
                    
    copy_btns[i].addEventListener('mouseleave'clearTooltip);
                    
    copy_btns[i].addEventListener('blur'clearTooltip);
                }
                
    e.clearSelection();
                
    // clipboard.destroy();
            
    }).on('error', (e) => {
                
    console.info('Action:'e.action);
                
    console.info('Text:'e.text);
                
    console.info('Trigger:'e.trigger);
                
    clipboard.destroy();
            });
      
            
    copy_btns.forEach(btn => {
                
    btn.onclick = (e) => {
                    
    showTooltip(btnbtn.dataset.sucess);
                };
            });
        }
     
     
        const 
    theme_btn document.querySelector('.theme-btn');
        if(
    theme_btn){
            
    theme_btn.addEventListener('click', (e) => {
                
    let btn e.currentTarget;
                $(
    'body').toggleClass('light-theme dark-theme');
                $(
    btn).find('i').toggleClass('fa-moon-stars fa-sun-bright');
            });
        }
     


        function 
    clearTooltip(even) {
            
    //even.currentTarget.setAttribute('class', 'copy-button');
            //even.currentTarget.removeAttribute('aria-label');
            
    even.currentTarget.dataset.tooltip 'Copy';
        }
     
        function 
    showTooltip(elmsg) {
            
    el.dataset.tooltip msg;
        }
    });

    نلاحظ الأمر "e.clearSelection();"

    هو أمر يخص عملية تظليل النص المراد نسخه.
    بما أنه اختياري، اخترت هنا عدم التظليل. لمن أراد عكس ذلك، عليه أن يضع علامة "//" أما الأمر كي يصبح على شكل تعليق و لن يتم تنفيذه، أو يزيله تماما.

    كما أن الأمر "clipboard.destroy();" مسؤول على إعادة كل العملية عند كل ضغطة زر.
    أنا اخترت هذاا الخيار. لمن أراد غير ذلك، ماعليه إلا جعل السطر على شكل تعليق، أو حذفه تماما.


    ملف الـ HTML كاملا بعد التعديل
    كود HTML:
    <!doctype html>
    <html lang="en">
    
        <head>
    
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width">
            <title>The HTML element "pre"</title>
      
            <link href="./fontawesome/css/all.min.css" rel="stylesheet">
            <link href="./pre.css" rel="stylesheet">
    
        </head>
    
        <body class="light-theme">
            <main class="content">
                <button type="button" class="theme-btn" title="Click to switch theme">
                    <i class="fa-duotone fa-2x fa-moon-stars"></i>
                </button>
                <div class="pre-content">
                  <button type="button" class="copy-button" data-clipboard-snippet=""
                  data-clipboard-target="#contToCopy" data-tooltip="Copy"
                  data-sucess="&check; Copied" aria-label="Copy">
                  </button>
                  <pre id="contToCopy" aria-label=""><code>
                    <span class="html">&lt;!doctype <span class="attr">html</span>></span>
                    <span class="html">&lt;html</span> <span class="attr">lang</span>=<span class="text">"en"</span><span class="html">></span>
                      <span class="html">&lt;head></span>
                        <span class="html">&lt;meta</span> <span class="attr">charset</span>=<span class="text">"utf-8"</span><span class="html">></span>
                        <span class="html">&lt;meta</span> <span class="attr">name</span>=<span class="text">"viewport" content="width=device-width"</span><span class="html">></span>
                        <span class="html">&lt;title></span>The "pre" html element<span class="html">&lt;/title></span>
                      <span class="html">&lt;/head></span>
                      <span class="html">&lt;body</span>
                        <span class="comm">&lt;!-- I am an HTML body content --></span>
                        <span class="html">&lt;div</span> <span class="attr">class</span>=<span class="text">"navbar"</span><span class="html">></span>
                          <span class="html">&lt;a</span> <span class="attr">href</span>=<span class="text">"!#home"</span><span class="html">></span>Home<span class="html">&lt;/a></span>
                          <span class="html">&lt;a</span> <span class="attr">href</span>=<span class="text">"!#news"</span><span class="html">></span>News<span class="html">&lt;/a></span>
                          <span class="html">&lt;a</span> <span class="attr">href</span>=<span class="text">"!#contact"</span><span class="html">></span>Contact<span class="html">&lt;/a></span>
                        <span class="html">&lt;/div></span>
    
                          <span class="php">&lt;?php</span>
                            <span class="comm">// I am a PHP body content</span>
                            <span class="text"><span class="key-word">echo</span> 'Hello World'</span>;
                          <span class="php">?></span>
    
                        <span class="html">&lt;script></span>
                          <span class="comm">// I am a JavaScript body content</span>
                         <span class="key-word">const</span> <span class="var">btn</span> = <span class="js-key-word">document</span>.<span class="js-comm-txt">querySelector</span>(<span class="text">'#get-code'</span>);
                        <span class="html">&lt;/script></span>
    
                      <span class="html">&lt;/body></span>
                    <span class="html">&lt;/html></span>
                  </code></pre>
                </div>
            </main>
      
            <script src="./jquery.min.js"></script>
            <script src="./clipboard.min.js"></script>
            <script src="./main.js"></script>
        </body>
    </html>
    

    [​IMG]

    [​IMG]


    جميع الملفات المستعملة في هذا التوضيح، تم إدراجها بالمرفقات.
    أهلا و مرحبا بكل تساؤل


    مــتــابــعــة طــيــبــة
     
    آخر تعديل: ‏26/8/2022
جاري تحميل الصفحة...