اذهب إلى المحتوى

علي الكاسر

الأعضاء
  • المساهمات

    190
  • تاريخ الانضمام

  • تاريخ آخر زيارة

أجوبة بواسطة علي الكاسر

  1. لقد حصلت على كو د جافا سكربت لعمل تاريخ هجري، ولكنني لم افهم اي شي من الكود. 

    اتمى احد يقوم بشرح الكود بالتفصيل لنستفيد جميعا 

    الكود

    <script language="JavaScript">
      var fixd;
    function isGregLeapYear(year)
    {
      return year%4 == 0 && year%100 != 0 || year%400 == 0;
    }
    
    function gregToFixed(year, month, day)
    {
      var a = Math.floor((year - 1) / 4);
      var b = Math.floor((year - 1) / 100);
      var c = Math.floor((year - 1) / 400);
      var d = Math.floor((367 * month - 362) / 12);
      if (month <= 2)
        e = 0;
      else if (month > 2 && isGregLeapYear(year))
        e = -1;
      else
        e = -2;
      return 1 - 1 + 365 * (year - 1) + a - b + c + d + e + day;
    }
    function Hijri(year, month, day)
    {
      this.year = year;
      this.month = month;
      this.day = day;
      this.toFixed = hijriToFixed;
      this.toString = hijriToString;
    }
    function hijriToFixed()
    {
      return this.day + Math.ceil(29.5 * (this.month - 1)) + (this.year - 1) * 354 +
        Math.floor((3 + 11 * this.year) / 30) + 227015 - 1;
    }
    function hijriToString()
    {
      var months = new Array("محرم","صفر","ربيع أول","ربيع ثانى","جمادى أول","جمادى ثانى","رجب","شعبان","رمضان","شوال","ذو القعدة","ذو الحجة");
      return this.day + " " + months[this.month - 1]+ " " + this.year;
    }
    function fixedToHijri(f)
    {
      var i=new Hijri(1100, 1, 1);
      i.year = Math.floor((30 * (f - 227015) + 10646) / 10631);
      var i2=new Hijri(i.year, 1, 1);
      var m = Math.ceil((f - 29 - i2.toFixed()) / 29.5) + 1;
      i.month = Math.min(m, 12);
      i2.year = i.year;
      i2.month = i.month;
      i2.day = 1;
      i.day = f - i2.toFixed() + 1;
      return i;
    }
    var tod=new Date();
    var weekday=new Array("الأحد","الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت");
    var monthname=new Array("1","2","4","3","5","6","7","8","سبتمبر","12","11","10");
    var y = tod.getFullYear();
    var m = tod.getMonth();
    var d = tod.getDate();
    var dow = tod.getDay();
    document.write(weekday[dow] + " " + d + " " + monthname[m] + " " + y);
    m++;
    fixd=gregToFixed(y, m, d);
    var h=new Hijri(1421, 11, 28) ;
    h = fixedToHijri(fixd);
    document.write(" م || " + h.toString() + "هـ");
    </script>

     

    • أعجبني 1
  2. بتاريخ 2 ساعة قال Mustafa Suleiman:

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

    مكتبة prism توفر لك تلوين الأكواد أي عمل Highlighting وليس توفير موقع لتحرير الأكواد، أي سيتعين عليك التخصيص وبناء الموقع وفقًا لما تراه مناسبًا.

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

    وإذا أردت الأسهل فعليك استخدام Ace Editor حيث يمكنك تضمين المكتبة مباشرًة واستخدام المحرر من خلال نسخة جاهزة كالتالي:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>ACE Code Lens demo</title>
        <style type="text/css" media="screen">
          body {
            overflow: hidden;
          }
    
          #editor {
            margin: 0;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
          }
        </style>
      </head>
      <body>
        <pre id="editor"></pre>
    
        <!-- load ace -->
        <script
          src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.24.2/ace.js"
          integrity="sha512-4gOhBb0ynE9P/pWgzXZA8AaPsS49vQpZI/AlBpUDKXH+AVZjEq6usVtcbrygkQkM0ztBvCt5AyLPZpN1Fcwnvg=="
          crossorigin="anonymous"
          referrerpolicy="no-referrer"
        ></script>
        <!-- load ace code_lens extension -->
        <script
          src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.24.2/ext-code_lens.min.js"
          integrity="sha512-81QPqjkXeCVN8i0OfBEGy3Ix+IwfmHwQ7D103quJuOs18KwgO6ra7L//1ZBU1LVMelSMweA0cAQSPAhXVa9zYQ=="
          crossorigin="anonymous"
          referrerpolicy="no-referrer"
        ></script>
        <script>
          var editor = ace.edit('editor');
          editor.session.setMode('ace/mode/html');
    
          var commandId = 'describeCodeLens';
          editor.commands.addCommand({
            name: commandId,
            exec: function (editor, args) {
              // services available in `ctx`
              alert('CodeLens command called with arguments ' + args);
            },
          });
          editor.commands.addCommand({
            name: 'clearCodeLenses',
            exec: function (editor, args) {
              editor.setOption('enableCodeLens', false);
              codeLens.clear(editor.session);
            },
          });
          editor.setOption('enableCodeLens', true);
    
          codeLens.registerCodeLensProvider(editor, {
            provideCodeLenses: function (session, callback) {
              var p = [
                {
                  start: { row: 0 },
                  command: {
                    id: 'clearCodeLenses',
                    title: 'Clear all code lenses',
                    arguments: [],
                  },
                },
              ];
              var l = session.getLength();
    
              for (var row = 2; row < l; row++) {
                var line = session.getLine(row);
                var endColumn = line.length;
    
                var m = /[{>]\s*$/.exec(line);
                if (!m) continue;
    
                p.push({
                  start: {
                    row: row,
                    column: m.index,
                  },
                  command: {
                    id: commandId,
                    title: 'Line ' + (row + 1),
                    arguments: ['line', row],
                  },
                });
    
                if (m.index < 10) continue;
                p.push({
                  start: {
                    row: row,
                    column: m.index,
                  },
                  end: {
                    row: row,
                    column: m.index + 1,
                  },
                  command: {
                    id: commandId,
                    title: 'column ' + endColumn,
                    arguments: ['column', endColumn],
                  },
                });
    
                if (m.index < 30) continue;
                p.push({
                  start: {
                    row: row,
                    column: m.index,
                  },
                  command: {
                    id: commandId,
                    title: 'Third Link',
                    arguments: ['3', row],
                  },
                });
              }
              callback(null, p);
            },
          });
    
          window.editor = editor;
          window.codeLens = codeLens;
        </script>
    
        <!-- <script src="./show_own_source.js"></script> -->
      </body>
    </html>

     

    شكرا اخي هذا المحرر ممتاز ولكن هل يمكن استخدامه داخل form في حق ادخال textarea حيث قد يكون textarea اكثر من حقل واحد 

    • أعجبني 1
  3. لقد سألت نفس السؤال واجاب احد الاخوه وارشدني إلى مكتبة prism-live.js وجربتها ونجحت ولكن بها عيوب حيث ان نص الكود لا يظهر بشكل كامل عندما يكون السطر طويل ولا ينزل المحرر سطر جديد للاسفل عندما يصل السطر إلى اخر صندوق الادخال كما في الصورة المرفقه، ناهيك انها لا تلون الاكواد التي داخل حاويات مثل div. 

    هل يوجد مكتبه اخرى لفعل محرر اكواد بشكل اقوى واحترافي 

    Screenshot_20230912-080038.png

    • أعجبني 1
  4. بتاريخ 12 ساعة قال Mustafa Suleiman:

    من المفترض أن يعمل معك في حال قمت بإتباع الخطوات في النقاش الذي أرفقته.

    وعلي أي حال إليك نموذج بسيط قمت بتنفيذه من قبل لشرح النقاش المذكور:

     

    prism-js.rar 8.27 kB · 1 تنزيل

    اخي  يوحد مشكله في هذا المحرر حيث لا يمكنني رؤية باقي الكود اذا كان نص السطر طويل وهذا امر غير مرغوب فمن الصعب التعامل معه. هل يوجد مكتبه اخرى تعمل محرر بشكل افضل واقوى

    Screenshot_20230912-080038.png

  5. بتاريخ 29 دقائق مضت قال Mustafa Suleiman:

    من المفترض أن يعمل معك في حال قمت بإتباع الخطوات في النقاش الذي أرفقته.

    وعلي أي حال إليك نموذج بسيط قمت بتنفيذه من قبل لشرح النقاش المذكور:

     

    prism-js.rar 8.27 kB · 0 تنزيلات

    شكرا اخي الان اشتغل 

  6. بتاريخ 4 ساعة قال Mustafa Suleiman:

    أولاً عليك باستيراد الملفات المطلوبة وهي:

    • prism.js
    • prism.css
    • prism-live.css
    • prism-live.js

    ويمكنك استيرادها من خلال الروابط التالية:

      <link
          rel="stylesheet"
          href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism-tomorrow.min.css"
        />
        <script src="
        https://cdn.jsdelivr.net/npm/prismjs@1.29.0/prism.min.js
        "></script>
        <script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>

    ثم استيراد ملف prism-live.js كالتالي:

        <script src="prism-live.js?load=css,html,javascript"></script>

     حيث أن prism-live.js تعتمد على prism.js وتسمح بتلوين الأكواد داخل عنصر <textarea>.

    وبعد ذلك عليك بحقن الأكواد من خلال جافاسكريبت في iframe  وضع له id وليكن باسم code كالتالي:

     <iframe id="code"></iframe>

    وقد شرحت الأمر بالتفصيل في سؤال من قبل عن كيفية إنشاء محرر أكواد بسيط مثل CodePen هنا:

    لم يشتغل اخي 

  7. بتاريخ 29 دقائق مضت قال Hessen Nasser:

    إليك شرح لكل خصائص العنصر الذي ارسلته :

    autocomplete="on":  عندما يتحقق المتصفح من أن هذا الخيار مفعل (on)، فإنه سيقترح تلقائيًا قيم مماثلة لهذا الحقل استنادًا إلى البيانات التي قد تكون قد أدخلتها في وقت سابق على سبيل المثال، عند إدخال اسم مستخدم في هذا الحقل قد تظهر قائمة من الأسماء المقترحة تلقائيًا.

    username-field: هذه الخاصية يبدو أنها مخصصة وربما تستخدم في مكان آخر في الكود أو في الجافا سكريبت يبدو أنها تمثل معلومة إضافية حول نوع الحقل وقد تكون مفيدة للأغراض البرمجية الخاصه بالمشروع نفسه.

    improve-input: هذه الخاصية تظهر أنها تمثل إجراءات إضافية لتحسين إدخال البيانات في الحقل يمكن أن تشمل هذه الإجراءات تصحيح الأخطاء الإملائية أو تنسيق البيانات ولكنها ايضامخصصة داخل المشروع.

    rm-white-spaces: هذه الخاصية تشير إلى أن الحقل سيقوم بإزالة الفراغات البيضاء (المسافات) من النص المدخل تلقائيًا يعني ذلك أن أي مسافات بيضاء في البداية أو النهاية أو بين الكلمات سيتم حذفها مع العلم هذه ليست خاصيه في html بل هي مخصصه ويتم التعامل معها من خلال جافاسكريبت.

    to-arabic-numbers: من الواضح ان هذه الخاصية تقوم بتحويل الأرقام في النص المدخل إلى أرقام عربية إذا كانت الأرقام بالأصل بالأحرف اللاتينية مع العلم هذه ليست خاصيه في html بل هي مخصصه ويتم التعامل معها من خلال جافاسكريبت.

    to-lower: هذه الخاصية تقوم بتحويل الأحرف في النص المدخل إلى أحرف صغيرة (حالة صغيرة) مع العلم هذه ليست خاصيه في html بل هي مخصصه ويتم التعامل معها من خلال جافاسكريبت.

    في المواقعالكبيره او المتوسطهه يقوم المطورين بانشاء او اضافة attributes مخصصه لكي يتمكنوا من التعامل مع حالات معينه اثناء تجرة المستخدم المختلفه.

    لمعرفة المزيد عن خصائص عناصر HTML يمكنك زيارة التوثيق الخاص ب HTML .

    لقد فهمت الان يعني انها خصائص خاصن وليست خصائص تبع اللغه

    شكرا لك اخي

    • أعجبني 1
  8. هذا حقل الادخال في احد المواقع وجدت فيه خصائص جديده لم اسمع بها من قبل ما فائدتها 

    <input type="text" name="username" class="login-input name" placeholder="ادخل رمز الكرت هنا" required autocomplete="on" username-field improve-input rm-white-spaces to-arabic-numbers to-lower/>

    هذه هي تحديدا

    autocomplete="on" username-field improve-input rm-white-spaces to-arabic-numbers to-lower

    اتمنى شرح هذه الخصائص واين يمكنني تعلم جميع خصائص عناصر html 

    • أعجبني 1
  9. بتاريخ 2 ساعة قال بلال زيادة:

    إذا كنت ترغب في عرض جميع المنشورات مع ثلاثة تعليقات فقط من كل منشور، يمكنك تحقيق ذلك باستخدام الدالة النافذة ROW_NUMBER() المتاحة في MySQL. هذا سيسمح لك بترقيم التعليقات داخل كل منشور ومن ثم اختيار الثلاثة التعليقات الأولى فقط.

    SELECT *
    FROM (
        SELECT 
            posts.*,
            comments.*,
            ROW_NUMBER() OVER (PARTITION BY posts.id ORDER BY comments.comment_id) AS comment_rank
        FROM posts
        LEFT JOIN comments ON posts.id = comments.post_id
    ) ranked_comments
    WHERE comment_rank <= 3;

     

    اخي جربت هذا الكود ولم يعمل وماذا تعني هذه الجمله ranked_comments لم افهم وجودها هنا ولماذا وضعتها، ارجو منك اخي اعادة كتابة الكود بما يتناسب مع بنية الجداول التاليه 

    جدول المستخدمين user 

    الاعمده

    id لتخزين اي دي المستخدم 

    name لتخزين اسم المستخدم

    جدول المنشورات posts

    الاعمده 

    post_id  لتخزين اي دي المنشور وربطه مع جدول التعليقات

    post_user لتخزين اي دي المستخدم مرسل المنشور والربط مع جدول المستخدمين مع العمود id

    post_msg لتخزين نص المنشور

    الجدول الثالث جدول التعليقات comment

    الاعمده 

    com_id لتخزين اي دي التعليق 

    com_id_post لتخزين رقم اي دي المنشور والربط مع جدول المنشورات عبر العمود post_id

    com_user لتخزين اي دي مرسل التعليق والربط مع جدول المستخدمين عبر العمود id

    com_msg لتخزين نص التعليق 

     

    الان اريد صياغة الكود اعلاه ليتم عرض المنشورات واسماء مرسليها وتحت كل منشور يتم عرض ثلاثه تعليقات مع اسماء مرسليها. 

    اتمنى الرد وشكرا جزيلا 

  10. بتاريخ 3 دقائق مضت قال بلال زيادة:
    SELECT
        posts.post_id,
        posts.post_content,
        GROUP_CONCAT(comments.comment_content) AS post_comments
    FROM
        posts
    LEFT JOIN
        comments ON posts.post_id = comments.post_id
    GROUP BY
        posts.post_id, posts.post_content;

    شكرا اخي هذا ما اريد ولك كيف يمكن عرض الناتج في حلقة foreach وخاصه التعليقات  وايضا اريد عرض ثلاثه تعليقات من كل منشور وليست كلها

  11. بتاريخ 17 دقائق مضت قال Thaer Alhabbash:

    يمكنك تحقيق ذلك من خلال طريقتين :
    الأولى : باستخدام الـ
    mysql
    بما أن الـ post_id مفتاح اجنبي (foreign_key) في جدول التعليقات , اذا علينا استخدام الـ Left Join لجلب جميع التعليقات الخاصة بكل منشور كالتالي:
     

    SELECT posts.*, comments.*
    FROM posts
    LEFT JOIN comments ON posts.id = comments.post_id;

    ماذا لو اردت عرض جميع المنشورات وثلاثه تعليقات فقط من كل منشور 

    • أعجبني 1
  12. لدي جدولين جدول للمنشورات وجدول اخر للتعليقات على المنشورات وبينهما علاقه في عمود post_id، كيف يمكنني باستلام واحد عرض المنشورات وتحت كل منشور التعليقات الخاصه به. 

    طبعا يمكنني فعل ذلك باستعلامين منفصلين، لذلك أسأل هل يمكن عمل هذا باستعلام واحد 

    • أعجبني 2
  13. بتاريخ On ١١‏/٧‏/٢٠٢٣ at 19:19 قال Adnane Kadri:

    بما أنك تقوم بتجاوز عنصر audioBlob، فما عليك إلا ارسال الـ Blob الخاص بملف الأوديو وسيتم التعامل معه بشكل اعتيادي جدا، لنقم مثلا بإنشاء وظيفة جديدة هي وظيفة uploadAudio بحيث تقوم بـ:

    • إنشاء formData نقوم بإضافة عنصر الأوديو إليه. 
    • ارسال ملف الصورة إلى الخادم.
    function uploadAudio() {
          // إرسال الصوت إلى الخادم هنا
          var formData = new FormData();
          formData.append("audio", audioBlob, "recording.webm");
    
          fetch("URL_TO_SERVER_ENDPOINT", {
            method: "POST",
            body: formData
          })
            .then(response => response.json())
            .then(data => {
              console.log("تم رفع الصوت بنجاح!", data);
              // استجابة من الخادم تحتوي على معلومات الصوت المرفوع ومعالجتها وتخزينها في قاعدة البيانات هنا
            })
            .catch(error => {
              console.error("حدث خطأ أثناء رفع الصوت", error);
            });
        }

    بعد هذا سيمكنك التعامل مع الملف من خلال الباك اند بشكل عادي جدا.

    اخي لقد نجحت في رفع الملف للسيرفر ولكن الملف مافيه صوت يعني لما اشغل الملف مايطلع الصوت 

  14. بتاريخ 10 ساعة قال عبدالباسط ابراهيم:

    هناك طريقة وهي استخدام WebSockets بدلاً من إرسال الطلبات عبر Fetch API. ما يحدث هو:

     عند الضغط على زر التسجيل، نقوم بإنشاء WebSocket connection مع السيرفر.
     عندما تصبح أجزاء الصوت متاحة عبر dataavailable event، نرسلها مباشرة عبر الـ WebSocket connection دون الانتظار حتى يكتمل التسجيل.
    في السيرفر، نتلقى أجزاء الصوت من خلال نفس الـ WebSocket connection ونخزنها في قاعدة البيانات كما نتلقاها.

    هذه الطريقة أفضل لأن:

    • ترسل البيانات مباشرة كلما أصبحت متاحة، بدون انتظار حتى ينتهي التسجيل.  
    • تقلل من حجم البيانات المرسلة مرة واحدة لأنها ترسل جزءًا بعد آخر كما يتم إنتاجه.  
    • تستخدم الـ WebSocket الذي هو أفضل من Fetch API في مثل هذه الحالات لأنه يوفر اتصالًا مستمرًا.

    لذا سيكون الكود تقريبًا كالتالي:

    let ws;
    
    function samah() {  
      // إنشاء واير سوكات
      ws = new WebSocket("YOUR_WEBSOCKET_ENDPOINT");
      
      // ... باقي كود التسجيل نفسه
    }
    
    function stops() {
      mediaRecorder.addEventListener("dataavailable", event => {
        
        // إرسال الصوت عبر ذا واير سوكات
        ws.send(event.data); 
      });
        
      // ... بقية الكود نفسه
    }

     

    بس يا اخي الخوادم المحليه الخاصه للتجريب واغلب الاستضافات واخاصه الرخيصه ماتدعم الويب سوكيت، وانا استخدم php في الخلفيه وهذه اللغه لا تدعم الويب سوكيت بشكل جيد وليس هناك مصدر لتعلم الويب سوكيت فيها 

  15. السلام عليكم ورحمة الله وبركاته 

    لدي كود جافا سكربت يقوم بالوصول للميكرفون وتسجيل الصوت وارساله للسيرفر ولكن المشكله يتم رفع ملف الصوت ولكن عند تشغيل الملف لا يوجد هناك صوت 

    هذه مجلدات وملفات السكربت كامله اتمنى التعديل على الكود وحل المشكله 

    مجلد upload

    ملف audio.html

    ملف audio.php

    كود ملف audio.html

    <html>

    <body>
      <button onclick="samah();">تسجيل صوتي</button>
      <button onclick="stops();">stop</button>
      <br>
      <a id="a"></a>
      <br>
      <audio style="display:none" id="audi" controls="controls" src=""></audio>

      <script>
        var audioChunks = []; // بيانات الصوت
        var mediaRecorder = null;
        var audioBlob = null;
        var audioUrl = null;
        var mainStream = null;

        function samah() {
          navigator.mediaDevices.getUserMedia({audio: true})
            .then(stream => {
              mainStream = stream;
              mediaRecorder = new MediaRecorder(stream);
              mediaRecorder.start(); // بدء التسجيل
              mediaRecorder.addEventListener("dataavailable", event => {
                audioChunks.push(event.data);
              });
            });
        }
        
        function uploadAudio() {
          // إرسال الصوت إلى الخادم هنا
          var formData = new FormData();
          formData.append("audio", audioBlob, "recording.webm");

          fetch("audio.php", {
            method: "POST",
            body: formData
          })
            .then(response => response.json())
            .then(data => {
              if(data.aud){
                alert(data.url) ;
                let audi = document.getElementById("audi");
                audi.src = data.url;
                audi.style.display = 'block';
              }else{
                alert(data.error);
              }
              // استجابة من الخادم تحتوي على معلومات الصوت المرفوع ومعالجتها وتخزينها في قاعدة البيانات هنا
            })
            .catch(error => {
              console.error("حدث خطأ أثناء رفع الصوت", error);
            });
            
        }
        
        function stops() {
          mediaRecorder.addEventListener("stop", () => {
            audioBlob = new Blob(audioChunks, {type: mediaRecorder.mimeType});
            audioUrl = URL.createObjectURL(audioBlob);

            mainStream.getTracks() // get all tracks from the MediaStream
              .forEach(track => track.stop()); // stop each of them

            // تحميل ملف الصوت
            let a = document.getElementById("a");
            a.href = audioUrl;
            a.download = "recording.webm";
            a.innerText = 'click me to save file';
            uploadAudio();
            //document.body.appendChild(a);
            //a.click();
          });

          mediaRecorder.stop();


        }

      </script>

    </body>

    </html>

     

    كود ملف audio.php

    <?php
      function _file($file,$allowedExtension,$size,$folder){
        global $load_error ; 
        $rand = array('A','a','B','b','C','c', 'D','b','E','e','F','f','G','g','J','j','K','k','L','l','H','h','S','s','V','v', 'T','t','Q','q','W','w','Y', 'y','U','u','I','i', 'O','o','P','p', 'X', 'x','N','n','M','m','R','r','Z','z');
        $text = '';
        for($i = 0; $i < rand(10,20); $i++){
         $text = $text.$rand[rand(0,51)];
        } 
        $fileName = $_FILES[$file]['name'];
        $fileSize = $_FILES[$file]['size'];
        $fileTmp  = $_FILES[$file]['tmp_name'];
        $fileType = $_FILES[$file]['type'];
        $fileExtensions = end(explode('.',$fileName));
        if(isset($fileName) and $fileName!=''){
          if(in_array($fileExtensions,$allowedExtension)){
            if($fileSize > $size){
              $load_error = 2;
              return false;
            }else{
              //نقوم بتغيير اسم الملف وحفضه في المجلد
              $location = $folder."/".$fileName;
              $location_new = $folder."/".$text.'.'.$fileExtensions;
              move_uploaded_file($fileTmp,$location);
              rename($location,$location_new);
              return $location_new;
            }
          }else{
            $load_error = 1;
            return false;
          } 
        }else{
          $load_error = 0;
          return false;
        }
      }
       if($audio_url = _file('audio',['webm','png'],1000*1000*5,'upload')) {
         $arr['aud'] = true;
         $arr['url'] = $audio_url;
       }else{
         $errors[] = 'لا يوجد ملف ';
         $errors[] = 'الملف غير مدعوم';
         $errors[] = 'حجم الملف كبير';
         $arr['aud'] = false;
         $arr['error'] = $errors[$load_error];
       }
       
      echo json_encode($arr);

    ?>

  16. بتاريخ 7 دقائق مضت قال Adnane Kadri:

    بما أنك تقوم بتجاوز عنصر audioBlob، فما عليك إلا ارسال الـ Blob الخاص بملف الأوديو وسيتم التعامل معه بشكل اعتيادي جدا، لنقم مثلا بإنشاء وظيفة جد

    شكرا لك اخي 

    بتاريخ 5 دقائق مضت قال Mustafa Suleiman:

    ستحتاج إلى تعديل الكود كالتالي:

    <html>
    <body>
      <button onclick="samah();">تسجيل صوتي</button>
      <button onclick="stops();">stop</button>
      <a id="a"></a>
    
      <script>
        let audioChunks = [];
        let mediaRecorder = null;
        let audioBlob = null;
        let mainStream = null;
    
        function samah() {
          navigator.mediaDevices.getUserMedia({ audio: true })
            .then(stream => {
              mainStream = stream;
              mediaRecorder = new MediaRecorder(stream);
              mediaRecorder.start();
              mediaRecorder.addEventListener("dataavailable", event => {
                audioChunks.push(event.data);
              });
            });
        }
    
        async function stops() {
          mediaRecorder.addEventListener("stop", async () => {
            audioBlob = new Blob(audioChunks, { type: mediaRecorder.mimeType });
    
            mainStream.getTracks().forEach(track => track.stop());
    
            // إنشاء كائن FormData لإرسال البيانات إلى السيرفر
            const formData = new FormData();
            formData.append("audio", audioBlob, "recording.webm");
    
            try {
              // إرسال البيانات إلى السيرفر باستخدام Fetch API و async/await
              const response = await fetch("URL_TO_SERVER_ENDPOINT", {
                method: "POST",
                body: formData
              });
              const data = await response.json();
              console.log("تم رفع التسجيل الصوتي بنجاح!", data);
              // هنا يمكنك التحكم في البيانات المرتدة من السيرفر
            } catch (error) {
              console.error("حدث خطأ أثناء رفع التسجيل الصوتي:", error);
            }
          });
    
          mediaRecorder.addEventListener("stop", stops);
    
          mediaRecorder.stop();
        }
      </script>
    </body>
    </html>

    وآلية عمل الكود هي:

    1. عند النقر على زر "تسجيل صوتي"، يتم استدعاء الدالة samah().
    2. تتم مطالبة المستخدم بالإذن للوصول إلى الميكروفون باستخدام navigator.mediaDevices.getUserMedia().
    3. بمجرد الحصول على الإذن، يتم تشغيل التسجيل باستخدام MediaRecorder، وتبدأ المكونات الصوتية في الاحتفاظ بالبيانات المسجلة في المصفوفة audioChunks.
    4. عند النقر على زر "stop"، يتم استدعاء الدالة stops().
    5. استدعاء حدث "stop" على mediaRecorder باستخدام mediaRecorder.addEventListener("stop", stops) للتأكد من استدعاء الدالة عند إيقاف التسجيل.
    6. إنشاء كائن Blob من المكونات الصوتية المسجلة.
    7. يتم إيقاف جميع المسارات في mainStream باستخدام mainStream.getTracks().forEach(track => track.stop()).
    8. إنشاء كائن FormData لتكوين بيانات الصوت المراد إرسالها إلى السيرفر.
    9. استخدام fetch لإرسال بيانات الصوت إلى السيرفر بطريقة غير متزامنة باستخدام طريقة POST.
    10. التعامل مع الاستجابة من السيرفر باستخدام response.json() ومن ثم استخدام البيانات المرتجعة كما تحتاج.

    شكرا جزيلا لك اخي اصبح الكود مفهوم بعد شرحك المفصل تسلم

  17. السلام عليكم ورحمة الله وبركاته 

    لدي كود جافا سكربت يقوم بفتح الميكرفون والتسجيل الصوتي ولكن يقوم بعمل رابط لتحميل الصوت المسجل. 

    أنا اريد تعديل ذلك الكود ليقوم برفع وارسال الصوت الى السيرفر لاقوم بعد ذلك بتخزينه في قاعدة البيانات والتحكم فيه 

    الكود

    <html>
    
    <body>
      <button onclick="samah();">تسجيل صوتي</button>
      <button onclick="stops();">stop</button>
      <a id="a"></a>
    
      <script>
        var audioChunks = []; // بيانات الصوت
        var mediaRecorder = null;
        var audioBlob = null;
        var audioUrl = null;
        var mainStream = null;
    
        function samah() {
          navigator.mediaDevices.getUserMedia({audio: true})
            .then(stream => {
              mainStream = stream;
              mediaRecorder = new MediaRecorder(stream);
              mediaRecorder.start(); // بدء التسجيل
              mediaRecorder.addEventListener("dataavailable", event => {
                audioChunks.push(event.data);
              });
            });
        }
        function stops() {
          mediaRecorder.addEventListener("stop", () => {
            audioBlob = new Blob(audioChunks, {type: mediaRecorder.mimeType});
            audioUrl = URL.createObjectURL(audioBlob);
    
            mainStream.getTracks() // get all tracks from the MediaStream
              .forEach(track => track.stop()); // stop each of them
    
            // تحميل ملف الصوت
            let a = document.getElementById("a");
            a.href = audioUrl;
            a.download = "recording.webm";
            a.innerText = 'click me to save file';
            //document.body.appendChild(a);
            //a.click();
          });
    
          mediaRecorder.stop();
    
    
        }
    
      </script>
    
    </body>
    
    </html>

     

    • أعجبني 2
  18. بتاريخ 19 ساعة قال Sam Ahw:

    لم أفهم ما علاقة الهاتف بالضبط في سؤالك، كون التقنية التي نتحدث عنها في طرف خادم الويب ولا علاقة لها بمستخدم الموقع. ولكن بشكل عام معظم استضافات مواقع الويب توفّر دعم لـ Redis أو يمكنك التواصل مع الدعم الفني أو الاطلاع على التوثيق الخاص بالاستضافة التي لديك معرفة طرق التثبيت.

    استخدم هاتف الاندرويد كخادم محلي اختبر عليه الموقع ويوجد تطبيق تيرمكس وهو شبيه بنظام لينكس من خلاله يتم تحميل الحزم والخوادم

  19. بتاريخ 38 دقائق مضت قال Sam Ahw:

    من الأفضل استخدام Redis كذاكرة مؤقتة لحفظ عناوين IP المستخدمين دون التأثير على بنية الموقع لديك، ويمكنك استخدام الشيفرة التالية كمثال:

    <?php
    //الاتصال بخادم redis
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    $redis->auth('REDIS_PASSWORD');
    
    $max_calls_limit  = 3; // العدد الأعظمي للطلبات خلال وقت محدد
    $time_period      = 10; // نافذة الوقت (الوقت اللازم لإعادة الحساب)
    $total_user_calls = 0; // إجمالي عدد الطلبات من نفس المستخدم
    
    // للحصول على عنوان المستخدم من الممكن أن يكون ضمن 3 أماكن في الطلب الذي يتم استقباله
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $user_ip_address = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $user_ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $user_ip_address = $_SERVER['REMOTE_ADDR'];
    }
    
    //التحقق في حال كان عنوان  المستخدم جديد وغير موجود في الذاكرة
    if (!$redis->exists($user_ip_address)) {
        $redis->set($user_ip_address, 1);
        $redis->expire($user_ip_address, $time_period);
        $total_user_calls = 1;
    } else {
        $redis->INCR($user_ip_address);
        $total_user_calls = $redis->get($user_ip_address);
        if ($total_user_calls > $max_calls_limit) {
            echo "User " . $user_ip_address . " limit exceeded.";
            exit();
        }
    }

    يمكنك مراجعة التوثيق الرسمي لـ Redis وقراءة الأوامر وطرق التثبيت والمزيد من التفاصيل. أو البحث على الانترنت عن تثبيت Redis ضمن نظام التشغيل الموجود لديك في بيئة الاستضافة.

    يعني هذا $redis = new Redis(); مكتبه او اطار عمل او ماذا بالضبط 

  20. بتاريخ 13 ساعة قال Sam Ahw:

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

    لذا يفضّل اتباع بعض معايير الحماية من طرف خادم الويب، مثل استخدام مايعرف ب Rate Limiter والذي يعمل على حجب الطلبات HTTP القادمة إلى خادم الويب من نفس المستخدم أو عنوان ال IP لمدّة معيّنة من الزمن حسب العدد الأعظمي الذي تحدده أنت، ولها أيضاً العديد من التطبيقات والمزايا التي قد تكون مفيدة في هذه الحالات.

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

    اخي لقد بحثت كثيرا في قوقل عن Rate Limiter ولكن لم احد مصادر عربيه تتحدث عنه، جربت بعض الاكواد التي وجدتها في مصادر اجنبيه الا انها فاشله وغير مفهومه واغلبها لم تعمل، هل يمكن ان تشرح لي بالاكواد php لافهم الموضوع 

×
×
  • أضف...