Skip to content
Guides4 min read

قوالب HTML المخصصة في Potato

إنشاء واجهات توسيم مخصصة باستخدام قوالب HTML وتنسيق CSS وتفاعلية JavaScript.

Potato Team·

قوالب HTML المخصصة في Potato

بينما يوفر Potato أنواع توسيم مدمجة، تتيح لك قوالب HTML المخصصة إنشاء واجهات متخصصة لاحتياجات التوسيم الفريدة. يغطي هذا الدليل إنشاء القوالب والتنسيق ودمج JavaScript.

متى تستخدم القوالب المخصصة

القوالب المخصصة مفيدة لـ:

  • التخطيطات المعقدة غير المدعومة بالأنواع المدمجة
  • الواجهات الخاصة بالمجال (الطبية، القانونية، إلخ.)
  • التصورات التفاعلية
  • عناصر الإدخال المخصصة
  • تجارب التوسيم ذات العلامة التجارية

هيكل القالب الأساسي

تكوين القالب

yaml
annotation_task_name: "Custom Template Annotation"
 
html_layout: "templates/my_template.html"

ملف القالب

html
<!-- templates/my_template.html -->
<div class="custom-annotation-container">
  <!-- Display the text -->
  <div class="content-display">
    <div class="text-content">
      {{text}}
    </div>
  </div>
 
  <!-- Custom annotation interface -->
  <div class="annotation-area">
    <!-- Potato will inject annotation schemes here -->
    {{annotation_schemes}}
  </div>
</div>

متغيرات القالب

المتغيرات المتاحة

html
<!-- Item data -->
{{id}}           <!-- Item ID -->
{{text}}         <!-- Main text content -->
{{image_url}}    <!-- Image URL if present -->
{{audio_url}}    <!-- Audio URL if present -->
 
<!-- Metadata -->
{{metadata.field_name}}  <!-- Any metadata field -->

تنسيق القوالب المخصصة

CSS مضمن

html
<style>
  .custom-annotation-container {
    max-width: 800px;
    margin: 0 auto;
    padding: 20px;
    font-family: -apple-system, BlinkMacSystemFont, sans-serif;
  }
 
  .task-header {
    background: linear-gradient(135deg, #6E56CF, #9F7AEA);
    color: white;
    padding: 15px 20px;
    border-radius: 8px;
    margin-bottom: 20px;
  }
 
  .content-display {
    background: #F8FAFC;
    border: 1px solid #E2E8F0;
    border-radius: 8px;
    padding: 20px;
    margin-bottom: 20px;
  }
 
  .text-content {
    font-size: 16px;
    line-height: 1.6;
    color: #1E293B;
  }
 
  .metadata {
    margin-top: 15px;
    padding-top: 15px;
    border-top: 1px solid #E2E8F0;
    font-size: 14px;
    color: #64748B;
  }
 
  .annotation-area {
    background: white;
    border: 1px solid #E2E8F0;
    border-radius: 8px;
    padding: 20px;
  }
 
  /* Custom highlight styles */
  .highlight-positive {
    background-color: #D1FAE5;
    padding: 2px 4px;
    border-radius: 3px;
  }
 
  .highlight-negative {
    background-color: #FEE2E2;
    padding: 2px 4px;
    border-radius: 3px;
  }
</style>

دمج JavaScript

التفاعل الأساسي

html
<script>
  document.addEventListener('DOMContentLoaded', function() {
    // Get the text content element
    const textContent = document.querySelector('.text-content');
 
    // Add click-to-highlight functionality
    textContent.addEventListener('mouseup', function() {
      const selection = window.getSelection();
      if (selection.toString().trim()) {
        highlightSelection(selection);
      }
    });
 
    function highlightSelection(selection) {
      const range = selection.getRangeAt(0);
      const span = document.createElement('span');
      span.className = 'user-highlight';
      range.surroundContents(span);
    }
  });
</script>

قوالب متقدمة

المقارنة جنباً إلى جنب

html
<div class="comparison-container">
  <style>
    .comparison-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 20px;
    }
 
    .comparison-item {
      border: 1px solid #E2E8F0;
      border-radius: 8px;
      padding: 15px;
    }
 
    .comparison-item.selected {
      border-color: #6E56CF;
      box-shadow: 0 0 0 2px rgba(110, 86, 207, 0.2);
    }
 
    .item-label {
      font-weight: 600;
      margin-bottom: 10px;
      color: #6E56CF;
    }
  </style>
 
  <div class="comparison-item" data-option="A" onclick="selectOption('A')">
    <div class="item-label">Option A</div>
    <div class="item-content">{{option_a}}</div>
  </div>
 
  <div class="comparison-item" data-option="B" onclick="selectOption('B')">
    <div class="item-label">Option B</div>
    <div class="item-content">{{option_b}}</div>
  </div>
 
  <script>
    function selectOption(option) {
      // Update visual selection
      document.querySelectorAll('.comparison-item').forEach(el => {
        el.classList.remove('selected');
      });
      document.querySelector(`[data-option="${option}"]`).classList.add('selected');
    }
  </script>
</div>

التمييز التفاعلي

html
<div class="highlight-annotation">
  <style>
    .highlight-toolbar {
      display: flex;
      gap: 10px;
      margin-bottom: 15px;
    }
 
    .highlight-btn {
      padding: 8px 16px;
      border: 1px solid #E2E8F0;
      border-radius: 6px;
      cursor: pointer;
      background: white;
    }
 
    .highlight-btn.active {
      background: #6E56CF;
      color: white;
      border-color: #6E56CF;
    }
 
    .highlightable-text {
      line-height: 1.8;
    }
 
    .highlight-positive { background: #D1FAE5; }
    .highlight-negative { background: #FEE2E2; }
    .highlight-neutral { background: #FEF3C7; }
  </style>
 
  <div class="highlight-toolbar">
    <button class="highlight-btn" data-color="positive" onclick="setHighlightMode('positive')">
      Positive
    </button>
    <button class="highlight-btn" data-color="negative" onclick="setHighlightMode('negative')">
      Negative
    </button>
    <button class="highlight-btn" data-color="neutral" onclick="setHighlightMode('neutral')">
      Neutral
    </button>
    <button class="highlight-btn" onclick="clearHighlights()">
      Clear All
    </button>
  </div>
 
  <div class="highlightable-text" id="textContent">
    {{text}}
  </div>
 
  <script>
    let currentMode = null;
    let highlights = [];
 
    function setHighlightMode(mode) {
      currentMode = mode;
      document.querySelectorAll('.highlight-btn').forEach(btn => {
        btn.classList.toggle('active', btn.dataset.color === mode);
      });
    }
 
    document.getElementById('textContent').addEventListener('mouseup', function() {
      if (!currentMode) return;
 
      const selection = window.getSelection();
      if (selection.toString().trim()) {
        const range = selection.getRangeAt(0);
        const span = document.createElement('span');
        span.className = `highlight-${currentMode}`;
 
        // Store highlight data
        highlights.push({
          text: selection.toString(),
          type: currentMode,
          start: range.startOffset,
          end: range.endOffset
        });
 
        range.surroundContents(span);
        selection.removeAllRanges();
      }
    });
 
    function clearHighlights() {
      highlights = [];
      document.getElementById('textContent').innerHTML = '{{text}}';
    }
  </script>
</div>

واجهة التبويبات

html
<div class="tabbed-interface">
  <style>
    .tab-buttons {
      display: flex;
      border-bottom: 2px solid #E2E8F0;
    }
 
    .tab-btn {
      padding: 12px 24px;
      border: none;
      background: none;
      cursor: pointer;
      font-size: 14px;
      font-weight: 500;
      color: #64748B;
      border-bottom: 2px solid transparent;
      margin-bottom: -2px;
    }
 
    .tab-btn.active {
      color: #6E56CF;
      border-bottom-color: #6E56CF;
    }
 
    .tab-content {
      display: none;
      padding: 20px 0;
    }
 
    .tab-content.active {
      display: block;
    }
  </style>
 
  <div class="tab-buttons">
    <button class="tab-btn active" onclick="showTab('text')">Text</button>
    <button class="tab-btn" onclick="showTab('metadata')">Metadata</button>
    <button class="tab-btn" onclick="showTab('context')">Context</button>
  </div>
 
  <div class="tab-content active" id="tab-text">
    <div class="text-content">{{text}}</div>
  </div>
 
  <div class="tab-content" id="tab-metadata">
    <pre>{{metadata | json}}</pre>
  </div>
 
  <div class="tab-content" id="tab-context">
    <p><strong>Source:</strong> {{metadata.source}}</p>
    <p><strong>Date:</strong> {{metadata.date}}</p>
    <p><strong>Author:</strong> {{metadata.author}}</p>
  </div>
 
  <script>
    function showTab(tabName) {
      document.querySelectorAll('.tab-btn').forEach(btn => {
        btn.classList.remove('active');
      });
      document.querySelectorAll('.tab-content').forEach(content => {
        content.classList.remove('active');
      });
 
      event.target.classList.add('active');
      document.getElementById(`tab-${tabName}`).classList.add('active');
    }
  </script>
</div>

أفضل الممارسات

  1. أبقِ القوالب بسيطة: المنطق المعقد يجب أن يكون في التكوين لا القوالب
  2. اختبر الاستجابة: تأكد من عمل القوالب على أحجام شاشات مختلفة
  3. تصميم قابل للوصول: استخدم تبايناً مناسباً وتسميات وتنقلاً بلوحة المفاتيح
  4. الأداء: قلل من JavaScript وحسّن الصور
  5. البدائل: وفر بدائل للبيانات المفقودة
  6. التوثيق: علّق على قوالبك لسهولة الصيانة

الوثائق الكاملة في /docs/core-concepts/annotation-types.