@mhmttosun/dnd 0.0.0-stage → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +327 -2
- package/css/answer-key.css +200 -0
- package/css/editor.css +1797 -0
- package/css/player.css +782 -0
- package/css/stage.css +490 -0
- package/dist/dnd-player-element.js +1758 -0
- package/dist/dnd.js +2041 -0
- package/dist/editor.css +3278 -0
- package/dist/editor.d.ts +23 -0
- package/dist/editor.js +8506 -0
- package/dist/index.d.ts +102 -0
- package/dist/player.css +782 -0
- package/dist/player.d.ts +1 -0
- package/dist/player.js +2041 -0
- package/dist/player.umd.cjs +1758 -0
- package/index.html +203 -0
- package/js/app.js +188 -0
- package/js/core/AnswerKeyManager.js +494 -0
- package/js/core/EditorCore.js +220 -0
- package/js/core/HistoryManager.js +194 -0
- package/js/core/LayerManager.js +86 -0
- package/js/core/ObjectManager.js +468 -0
- package/js/core/SelectionManager.js +459 -0
- package/js/core/StageManager.js +295 -0
- package/js/data/SampleProjects.js +883 -0
- package/js/engine/TransformEngine.js +632 -0
- package/js/engine/ValidationEngine.js +147 -0
- package/js/player/ActivityEngine.js +1272 -0
- package/js/player/ExportManager.js +820 -0
- package/js/ui/MiniToolbar.js +1546 -0
- package/js/ui/PropertyPanel.js +776 -0
- package/js/ui/UIManager.js +596 -0
- package/js/utils/AudioSynthesizer.js +111 -0
- package/package.json +69 -4
- package/src/ActivityPlayer.js +309 -0
- package/src/DNDEditor.js +217 -0
- package/src/components/DNDPlayerElement.js +191 -0
- package/src/index.js +12 -0
- package/src/player.js +13 -0
package/index.html
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="tr">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>DND • Etkinlik Düzenleyicisi</title>
|
|
7
|
+
|
|
8
|
+
<!-- Google Font Inter -->
|
|
9
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
10
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
11
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
12
|
+
|
|
13
|
+
<!-- CSS Dosyaları -->
|
|
14
|
+
<link rel="stylesheet" href="css/editor.css">
|
|
15
|
+
<link rel="stylesheet" href="css/stage.css">
|
|
16
|
+
<link rel="stylesheet" href="css/answer-key.css">
|
|
17
|
+
<link rel="stylesheet" href="css/player.css">
|
|
18
|
+
</head>
|
|
19
|
+
<body>
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
<!-- ==========================================
|
|
24
|
+
2. İKİNCİL ARAÇ ÇUBUĞU (SECONDARY TOOLBAR)
|
|
25
|
+
========================================== -->
|
|
26
|
+
<nav class="app-sub-toolbar">
|
|
27
|
+
<!-- Sol Mod Kümesi -->
|
|
28
|
+
<div class="sub-toolbar-cluster cluster-left-group">
|
|
29
|
+
<div class="mode-pill-group">
|
|
30
|
+
<button type="button" class="mode-toggle-btn active" data-mode="design" title="Tasarım Modu">
|
|
31
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
|
32
|
+
</button>
|
|
33
|
+
<button type="button" class="mode-toggle-btn" data-mode="answer-key" title="Cevap Anahtarı Modu">
|
|
34
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/><path d="M9 16l2 2 4-4"/></svg>
|
|
35
|
+
</button>
|
|
36
|
+
<button type="button" class="mode-toggle-btn" data-mode="preview" title="Önizleme Modu">
|
|
37
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
|
38
|
+
</button>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<!-- Şablon Seçici Menü -->
|
|
42
|
+
<div class="template-dropdown-wrapper">
|
|
43
|
+
<button type="button" class="sub-tool-btn" id="btn-toggle-templates" title="Örnek Etkinlik Şablonları">
|
|
44
|
+
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
|
|
45
|
+
</button>
|
|
46
|
+
<div class="templates-menu" id="templates-menu" style="display: none;">
|
|
47
|
+
<div class="menu-title">Örnek Şablonlar</div>
|
|
48
|
+
<button type="button" class="template-menu-item" data-sample="matching">1. Eşleştirme (Kavram ve Tanım)</button>
|
|
49
|
+
<button type="button" class="template-menu-item" data-sample="image-labeling">2. Görsel Etiketleme (İnsan Anatomisi)</button>
|
|
50
|
+
<button type="button" class="template-menu-item" data-sample="categorization">3. Kategorilere Ayırma (Meyve/Sebze)</button>
|
|
51
|
+
<button type="button" class="template-menu-item" data-sample="sequencing">4. Sıralama (Kelebek Yaşam Döngüsü)</button>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<!-- Cevap Anahtarı Rehber Bloğu (Yalnızca Cevap Anahtarı Modunda) -->
|
|
56
|
+
<div class="answer-key-toolbar-guide" id="answer-key-guide-bar" style="display: none;">
|
|
57
|
+
<div class="ak-toolbar-divider"></div>
|
|
58
|
+
<div class="ak-toolbar-content">
|
|
59
|
+
<div class="ak-toolbar-title-row">
|
|
60
|
+
<span class="ak-toolbar-status-icon" id="ak-status-icon">
|
|
61
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
|
62
|
+
<circle cx="12" cy="12" r="10"/>
|
|
63
|
+
<polyline points="9 12 12 15 16 10"/>
|
|
64
|
+
</svg>
|
|
65
|
+
</span>
|
|
66
|
+
<span class="ak-guide-title" id="ak-guide-title">Eşleştirmeler tamamlandı</span>
|
|
67
|
+
</div>
|
|
68
|
+
<div class="ak-guide-instruction" id="ak-guide-instruction">4/4 eşleşme · Cevap anahtarını kontrol et</div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<!-- Orta Araç Kümesi (Nesne Ekleme) -->
|
|
74
|
+
<div class="sub-toolbar-cluster cluster-add-objects" id="cluster-add-objects">
|
|
75
|
+
<button type="button" class="sub-tool-btn" id="btn-add-text" title="Metin Kutusu Ekle">
|
|
76
|
+
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="4 7 4 4 20 4 20 7"/><line x1="12" y1="4" x2="12" y2="20"/><line x1="8" y1="20" x2="16" y2="20"/></svg>
|
|
77
|
+
</button>
|
|
78
|
+
|
|
79
|
+
<button type="button" class="sub-tool-btn" id="btn-add-rect" title="Kutu / Kart Ekle">
|
|
80
|
+
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="3"/></svg>
|
|
81
|
+
</button>
|
|
82
|
+
|
|
83
|
+
<button type="button" class="sub-tool-btn" id="btn-add-circle" title="Daire Şekli Ekle">
|
|
84
|
+
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/></svg>
|
|
85
|
+
</button>
|
|
86
|
+
|
|
87
|
+
<button type="button" class="sub-tool-btn" id="btn-add-image" title="Bilgisayardan Görsel Yükle">
|
|
88
|
+
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
|
|
89
|
+
</button>
|
|
90
|
+
<input type="file" id="file-input-image" accept="image/*" style="display: none;">
|
|
91
|
+
|
|
92
|
+
<button type="button" class="sub-tool-btn" id="btn-add-target" title="Çizgi Ekle">
|
|
93
|
+
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="4" y1="20" x2="20" y2="4"/></svg>
|
|
94
|
+
</button>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<!-- Sağ Küme (Geçmiş, Yakınlaştırma ve Daha Fazla Menüsü) -->
|
|
98
|
+
<div class="sub-toolbar-cluster cluster-right-group">
|
|
99
|
+
<div class="cluster-history-zoom" id="cluster-history-zoom">
|
|
100
|
+
<button type="button" class="sub-tool-btn" id="btn-undo" title="Geri Al (Ctrl+Z)" disabled>
|
|
101
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/></svg>
|
|
102
|
+
</button>
|
|
103
|
+
|
|
104
|
+
<button type="button" class="sub-tool-btn" id="btn-redo" title="İleri Al (Ctrl+Y)" disabled>
|
|
105
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7"/></svg>
|
|
106
|
+
</button>
|
|
107
|
+
|
|
108
|
+
<div class="sub-divider"></div>
|
|
109
|
+
|
|
110
|
+
<button type="button" class="sub-tool-btn" id="btn-zoom-out" title="Uzaklaştır">
|
|
111
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/><line x1="8" y1="11" x2="14" y2="11"/></svg>
|
|
112
|
+
</button>
|
|
113
|
+
|
|
114
|
+
<button type="button" class="sub-tool-btn" id="btn-zoom-reset" title="Ekrana Sığdır">
|
|
115
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>
|
|
116
|
+
</button>
|
|
117
|
+
|
|
118
|
+
<button type="button" class="sub-tool-btn" id="btn-zoom-in" title="Yakınlaştır">
|
|
119
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/><line x1="8" y1="11" x2="14" y2="11"/></svg>
|
|
120
|
+
</button>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<div class="sub-divider" id="more-menu-divider"></div>
|
|
124
|
+
|
|
125
|
+
<!-- Daha Fazla Seçenek Menüsü (Proje Aç, Çevrimdışı HTML İndir, Kaydet) -->
|
|
126
|
+
<div class="more-menu-wrapper" id="more-menu-wrapper">
|
|
127
|
+
<button type="button" class="sub-tool-btn" id="btn-more-menu" title="Daha Fazla Seçenek" aria-expanded="false" aria-haspopup="true">
|
|
128
|
+
<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
|
|
129
|
+
<circle cx="12" cy="12" r="1.5"/>
|
|
130
|
+
<circle cx="12" cy="5" r="1.5"/>
|
|
131
|
+
<circle cx="12" cy="19" r="1.5"/>
|
|
132
|
+
</svg>
|
|
133
|
+
</button>
|
|
134
|
+
<div class="more-dropdown-menu" id="more-dropdown-menu" style="display: none;">
|
|
135
|
+
<button type="button" class="more-menu-item" id="btn-open-project" title="Proje Aç (JSON)">
|
|
136
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
|
|
137
|
+
<span>Proje Aç</span>
|
|
138
|
+
</button>
|
|
139
|
+
<input type="file" id="file-input-project" accept=".json,application/json" style="display: none;">
|
|
140
|
+
|
|
141
|
+
<button type="button" class="more-menu-item" id="btn-export-html" title="Çevrimdışı HTML İndir">
|
|
142
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
|
143
|
+
<span>Çevrimdışı HTML İndir</span>
|
|
144
|
+
</button>
|
|
145
|
+
|
|
146
|
+
<button type="button" class="more-menu-item" id="btn-save-project" title="Kaydet (JSON)">
|
|
147
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>
|
|
148
|
+
<span>Kaydet</span>
|
|
149
|
+
</button>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
</nav>
|
|
154
|
+
|
|
155
|
+
<!-- ==========================================
|
|
156
|
+
3. ÇALIŞMA ALANI (FULL CANVAS WORKSPACE)
|
|
157
|
+
Sağ ve Sol Panel Yoktur.
|
|
158
|
+
========================================== -->
|
|
159
|
+
<main class="editor-workspace" id="editor-layout">
|
|
160
|
+
<div class="stage-viewport" id="stage-viewport">
|
|
161
|
+
<div class="stage-container" id="stage-container">
|
|
162
|
+
<div class="stage-scaler" id="stage-scaler">
|
|
163
|
+
<div class="stage grid-visible mode-design" id="stage">
|
|
164
|
+
<!-- SVG Bağlantı ve Çizim Katmanı -->
|
|
165
|
+
<svg class="stage-svg-overlay" id="svg-overlay">
|
|
166
|
+
<g id="svg-connections"></g>
|
|
167
|
+
</svg>
|
|
168
|
+
|
|
169
|
+
<!-- Sahne Nesneleri Katmanı -->
|
|
170
|
+
<div class="stage-objects" id="stage-objects"></div>
|
|
171
|
+
|
|
172
|
+
<!-- Seçim ve Boyutlandırma Çerçevesi -->
|
|
173
|
+
<div class="selection-box" id="selection-overlay"></div>
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
</main>
|
|
179
|
+
|
|
180
|
+
<!-- ==========================================
|
|
181
|
+
ÖNİZLEME ALANI (PREVIEW CONTAINER)
|
|
182
|
+
========================================== -->
|
|
183
|
+
<div id="preview-container"></div>
|
|
184
|
+
|
|
185
|
+
<!-- MODÜLER JAVASCRIPT DOSYALARI (Bağımlılık Sırasıyla) -->
|
|
186
|
+
<script src="js/utils/AudioSynthesizer.js"></script>
|
|
187
|
+
<script src="js/engine/ValidationEngine.js"></script>
|
|
188
|
+
<script src="js/core/EditorCore.js"></script>
|
|
189
|
+
<script src="js/core/StageManager.js"></script>
|
|
190
|
+
<script src="js/core/ObjectManager.js"></script>
|
|
191
|
+
<script src="js/core/SelectionManager.js"></script>
|
|
192
|
+
<script src="js/core/HistoryManager.js"></script>
|
|
193
|
+
<script src="js/core/LayerManager.js"></script>
|
|
194
|
+
<script src="js/core/AnswerKeyManager.js"></script>
|
|
195
|
+
<script src="js/engine/TransformEngine.js"></script>
|
|
196
|
+
<script src="js/player/ActivityEngine.js"></script>
|
|
197
|
+
<script src="js/player/ExportManager.js"></script>
|
|
198
|
+
<script src="js/ui/MiniToolbar.js"></script>
|
|
199
|
+
<script src="js/ui/UIManager.js"></script>
|
|
200
|
+
<script src="js/data/SampleProjects.js"></script>
|
|
201
|
+
<script src="js/app.js"></script>
|
|
202
|
+
</body>
|
|
203
|
+
</html>
|
package/js/app.js
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* app.js - Uygulama Başlatıcı (Bootstrapper).
|
|
3
|
+
* Bütün modülleri temiz bir bağımlılık sırasıyla birbirine bağlar ve çalıştırır.
|
|
4
|
+
* Yan paneller kaldırılmış, bağlamsal MiniToolbar entegre edilmiştir.
|
|
5
|
+
*/
|
|
6
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
7
|
+
try {
|
|
8
|
+
const stageViewport = document.getElementById('stage-viewport');
|
|
9
|
+
const stageEl = document.getElementById('stage');
|
|
10
|
+
|
|
11
|
+
// 1. Çekirdek Sistem
|
|
12
|
+
const core = new window.DND.EditorCore();
|
|
13
|
+
|
|
14
|
+
// 2. Sahne ve Koordinat Yönetimi
|
|
15
|
+
const stageManager = new window.DND.StageManager(core, stageViewport, stageEl);
|
|
16
|
+
|
|
17
|
+
// 3. Nesne Yönetimi
|
|
18
|
+
const objectManager = new window.DND.ObjectManager(core, stageEl);
|
|
19
|
+
|
|
20
|
+
// 4. Seçim ve Dönüşüm Yönetimi
|
|
21
|
+
const selectionManager = new window.DND.SelectionManager(core, stageManager, objectManager, stageEl);
|
|
22
|
+
const historyManager = new window.DND.HistoryManager(core);
|
|
23
|
+
const layerManager = new window.DND.LayerManager(core, objectManager);
|
|
24
|
+
|
|
25
|
+
// 5. Cevap Anahtarı ve Dönüşüm Motorları
|
|
26
|
+
const answerKeyManager = new window.DND.AnswerKeyManager(core, stageManager, objectManager, stageEl);
|
|
27
|
+
const transformEngine = new window.DND.TransformEngine(core, stageManager, objectManager, selectionManager, historyManager, stageEl);
|
|
28
|
+
|
|
29
|
+
// 6. Dışa Aktarma, MiniToolbar ve Arayüz
|
|
30
|
+
const exportManager = new window.DND.ExportManager(core);
|
|
31
|
+
const miniToolbar = new window.DND.MiniToolbar(core, objectManager, selectionManager, layerManager, stageManager);
|
|
32
|
+
const uiManager = new window.DND.UIManager(core, stageManager, objectManager, selectionManager, historyManager, exportManager);
|
|
33
|
+
|
|
34
|
+
// =========================================================================
|
|
35
|
+
// 7. GÖMÜLÜ MOD (EMBEDDING) VE DIŞA AKTARMA (JSON EXPORT) API'LERİ
|
|
36
|
+
// =========================================================================
|
|
37
|
+
|
|
38
|
+
// Header görünürlüğünü dinamik olarak kontrol etme fonksiyonu
|
|
39
|
+
const setHeaderVisible = (visible) => {
|
|
40
|
+
const isVisible = !!visible;
|
|
41
|
+
if (typeof document !== 'undefined' && document.body && document.body.classList) {
|
|
42
|
+
document.body.classList.toggle('is-embedded', !isVisible);
|
|
43
|
+
}
|
|
44
|
+
const topHeader = typeof document !== 'undefined' ? document.querySelector('.app-top-header') : null;
|
|
45
|
+
if (topHeader && topHeader.style) {
|
|
46
|
+
topHeader.style.display = isVisible ? 'flex' : 'none';
|
|
47
|
+
}
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
if (stageManager && typeof stageManager.updateScale === 'function') {
|
|
50
|
+
stageManager.updateScale();
|
|
51
|
+
}
|
|
52
|
+
}, 30);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Embedding Modu Tespiti:
|
|
56
|
+
// URL parametresi (?embedded=true, ?header=false, ?hideHeader=true) veya iframe içi
|
|
57
|
+
const searchStr = (typeof window !== 'undefined' && window.location && window.location.search) ? window.location.search : '';
|
|
58
|
+
let isEmbeddedQuery = false;
|
|
59
|
+
let headerExplicitTrue = false;
|
|
60
|
+
try {
|
|
61
|
+
if (typeof URLSearchParams !== 'undefined' && searchStr) {
|
|
62
|
+
const urlParams = new URLSearchParams(searchStr);
|
|
63
|
+
isEmbeddedQuery = urlParams.get('embedded') === 'true' ||
|
|
64
|
+
urlParams.get('embed') === 'true' ||
|
|
65
|
+
urlParams.get('header') === 'false' ||
|
|
66
|
+
urlParams.get('hideHeader') === 'true';
|
|
67
|
+
headerExplicitTrue = urlParams.get('header') === 'true';
|
|
68
|
+
}
|
|
69
|
+
} catch (e) {}
|
|
70
|
+
|
|
71
|
+
let isIframe = false;
|
|
72
|
+
try {
|
|
73
|
+
isIframe = typeof window !== 'undefined' && window.self !== window.top;
|
|
74
|
+
} catch (e) {
|
|
75
|
+
isIframe = true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// iframe içindeyse (ve açıkça header=true denmemişse) veya URL'de parametre varsa header'ı gizle
|
|
79
|
+
const shouldHideHeader = isEmbeddedQuery || (isIframe && !headerExplicitTrue);
|
|
80
|
+
if (shouldHideHeader) {
|
|
81
|
+
setHeaderVisible(false);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// JSON Dışa Aktarma Fonksiyonları (Ebeveyn uygulamanın tek çağrıyla JSON alabilmesi için)
|
|
85
|
+
const exportJSON = () => core.getProjectData();
|
|
86
|
+
const exportJSONString = (indent = 2) => JSON.stringify(core.getProjectData(), null, indent);
|
|
87
|
+
const loadJSON = (projectData) => {
|
|
88
|
+
core.loadProject(projectData);
|
|
89
|
+
uiManager.updateSaveStatus(true);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Global app nesnesi
|
|
93
|
+
window.app = {
|
|
94
|
+
core,
|
|
95
|
+
stageManager,
|
|
96
|
+
objectManager,
|
|
97
|
+
selectionManager,
|
|
98
|
+
historyManager,
|
|
99
|
+
layerManager,
|
|
100
|
+
answerKeyManager,
|
|
101
|
+
transformEngine,
|
|
102
|
+
exportManager,
|
|
103
|
+
miniToolbar,
|
|
104
|
+
uiManager,
|
|
105
|
+
|
|
106
|
+
// Dışa aktarma ve entegrasyon metotları
|
|
107
|
+
exportJSON,
|
|
108
|
+
exportJSONString,
|
|
109
|
+
getProjectData: exportJSON,
|
|
110
|
+
loadProject: loadJSON,
|
|
111
|
+
setHeaderVisible,
|
|
112
|
+
isEmbedded: () => {
|
|
113
|
+
return typeof document !== 'undefined' &&
|
|
114
|
+
document.body &&
|
|
115
|
+
document.body.classList &&
|
|
116
|
+
document.body.classList.contains('is-embedded');
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Global kısayollar (window.dndExport() veya iframe.contentWindow.dndExport())
|
|
121
|
+
window.dndExport = exportJSON;
|
|
122
|
+
window.dndExportString = exportJSONString;
|
|
123
|
+
window.dndLoad = loadJSON;
|
|
124
|
+
window.dndSetHeaderVisible = setHeaderVisible;
|
|
125
|
+
|
|
126
|
+
// PostMessage Desteği (iframe entegrasyonlarında ebeveyn uygulamanın JSON istemesi veya yüklemesi için)
|
|
127
|
+
if (typeof window !== 'undefined' && typeof window.addEventListener === 'function') {
|
|
128
|
+
window.addEventListener('message', (event) => {
|
|
129
|
+
const msg = event.data;
|
|
130
|
+
if (!msg || typeof msg !== 'object') return;
|
|
131
|
+
|
|
132
|
+
switch (msg.type) {
|
|
133
|
+
case 'DND_GET_DATA':
|
|
134
|
+
case 'GET_PROJECT_DATA': {
|
|
135
|
+
const data = exportJSON();
|
|
136
|
+
if (event.source && typeof event.source.postMessage === 'function') {
|
|
137
|
+
event.source.postMessage({
|
|
138
|
+
type: 'DND_DATA_RESPONSE',
|
|
139
|
+
requestId: msg.requestId,
|
|
140
|
+
data: data
|
|
141
|
+
}, '*');
|
|
142
|
+
}
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
case 'DND_LOAD_DATA':
|
|
146
|
+
case 'LOAD_PROJECT': {
|
|
147
|
+
if (msg.data) {
|
|
148
|
+
loadJSON(msg.data);
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
case 'DND_SET_HEADER': {
|
|
153
|
+
setHeaderVisible(msg.visible !== false);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case 'DND_SET_MODE': {
|
|
157
|
+
if (msg.mode) {
|
|
158
|
+
core.setMode(msg.mode);
|
|
159
|
+
}
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Sahne verisi her değiştiğinde ebeveyn uygulamaya canlı bildirim gönder (iframe içindeyse)
|
|
167
|
+
core.on('dataChanged', (e) => {
|
|
168
|
+
if (isIframe && typeof window !== 'undefined' && window.parent && window.parent !== window) {
|
|
169
|
+
try {
|
|
170
|
+
window.parent.postMessage({
|
|
171
|
+
type: 'DND_DATA_CHANGED',
|
|
172
|
+
source: e.source,
|
|
173
|
+
data: exportJSON()
|
|
174
|
+
}, '*');
|
|
175
|
+
} catch (err) {}
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Başlangıç Projesi: Ekteki görseldeki "Kavram ve Tanım" eşleştirme projesi
|
|
180
|
+
const defaultSample = window.DND.SAMPLE_PROJECTS['matching'] || window.DND.SAMPLE_PROJECTS['image-labeling'];
|
|
181
|
+
core.loadProject(defaultSample);
|
|
182
|
+
uiManager.updateSaveStatus(true);
|
|
183
|
+
|
|
184
|
+
} catch (err) {
|
|
185
|
+
console.error('Uygulama başlatılırken kritik hata:', err);
|
|
186
|
+
alert('Uygulama başlatılamadı: ' + err.message);
|
|
187
|
+
}
|
|
188
|
+
});
|