From 2a9521b862a2050e5d53761e79c74cf3092d2216 Mon Sep 17 00:00:00 2001 From: Du Date: Wed, 27 Mar 2019 14:07:05 +0700 Subject: [PATCH] Release v3.4.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Thay đổi lại cách thức thực hiện truy vấn SQL -> hạn chế lỗi SQL Injection ✓ - Fix lỗi bị lag khi thực hiện thêm, sửa, xóa với các mục có nhiều dữ liệu ✓ - Fix lỗi không cài đặt được ở 1 số máy ✓ - Fix lỗi không hiện công thức toán khi làm bài ✓ - Rewrite URL ✓ - Thêm upload ảnh cho nội dung câu hỏi ✓ - Tối ưu lại một số code ✓ --- CHANGELOG.md | 3 +- GUIDE.md | 1 + resource/config/config.php | 1 + resource/controllers/controller_admin.php | 20 +- resource/controllers/controller_student.php | 2 +- resource/controllers/controller_teacher.php | 2 +- resource/core/Base.php | 46 + resource/install.php | 1 + resource/res/img/image_btn.png | Bin 0 -> 498 bytes resource/res/js/add_question.js | 41 + resource/res/js/admins_panel.js | 2 +- resource/res/js/edit_question.js | 41 + resource/res/js/questions_panel.js | 8 +- resource/res/js/students_panel.js | 8 +- resource/res/js/teachers_panel.js | 2 +- resource/res/libs/ckeditor/config.js | 3 +- .../ckeditor/plugins/image/dialogs/image.js | 1257 +++++++++++++++++ .../plugins/image/icons/hidpi/image.png | Bin 0 -> 905 bytes .../ckeditor/plugins/image/icons/image.png | Bin 0 -> 498 bytes .../ckeditor/plugins/image/images/noimage.png | Bin 0 -> 1610 bytes .../libs/ckeditor/plugins/image/lang/af.js | 25 + .../libs/ckeditor/plugins/image/lang/ar.js | 25 + .../libs/ckeditor/plugins/image/lang/az.js | 25 + .../libs/ckeditor/plugins/image/lang/bg.js | 25 + .../libs/ckeditor/plugins/image/lang/bn.js | 25 + .../libs/ckeditor/plugins/image/lang/bs.js | 25 + .../libs/ckeditor/plugins/image/lang/ca.js | 25 + .../libs/ckeditor/plugins/image/lang/cs.js | 25 + .../libs/ckeditor/plugins/image/lang/cy.js | 25 + .../libs/ckeditor/plugins/image/lang/da.js | 25 + .../libs/ckeditor/plugins/image/lang/de-ch.js | 25 + .../libs/ckeditor/plugins/image/lang/de.js | 25 + .../libs/ckeditor/plugins/image/lang/el.js | 25 + .../libs/ckeditor/plugins/image/lang/en-au.js | 25 + .../libs/ckeditor/plugins/image/lang/en-ca.js | 25 + .../libs/ckeditor/plugins/image/lang/en-gb.js | 25 + .../libs/ckeditor/plugins/image/lang/en.js | 25 + .../libs/ckeditor/plugins/image/lang/eo.js | 25 + .../libs/ckeditor/plugins/image/lang/es-mx.js | 25 + .../libs/ckeditor/plugins/image/lang/es.js | 25 + .../libs/ckeditor/plugins/image/lang/et.js | 25 + .../libs/ckeditor/plugins/image/lang/eu.js | 25 + .../libs/ckeditor/plugins/image/lang/fa.js | 25 + .../libs/ckeditor/plugins/image/lang/fi.js | 25 + .../libs/ckeditor/plugins/image/lang/fo.js | 25 + .../libs/ckeditor/plugins/image/lang/fr-ca.js | 25 + .../libs/ckeditor/plugins/image/lang/fr.js | 25 + .../libs/ckeditor/plugins/image/lang/gl.js | 25 + .../libs/ckeditor/plugins/image/lang/gu.js | 25 + .../libs/ckeditor/plugins/image/lang/he.js | 25 + .../libs/ckeditor/plugins/image/lang/hi.js | 25 + .../libs/ckeditor/plugins/image/lang/hr.js | 25 + .../libs/ckeditor/plugins/image/lang/hu.js | 25 + .../libs/ckeditor/plugins/image/lang/id.js | 25 + .../libs/ckeditor/plugins/image/lang/is.js | 25 + .../libs/ckeditor/plugins/image/lang/it.js | 25 + .../libs/ckeditor/plugins/image/lang/ja.js | 25 + .../libs/ckeditor/plugins/image/lang/ka.js | 25 + .../libs/ckeditor/plugins/image/lang/km.js | 25 + .../libs/ckeditor/plugins/image/lang/ko.js | 25 + .../libs/ckeditor/plugins/image/lang/ku.js | 25 + .../libs/ckeditor/plugins/image/lang/lt.js | 25 + .../libs/ckeditor/plugins/image/lang/lv.js | 25 + .../libs/ckeditor/plugins/image/lang/mk.js | 25 + .../libs/ckeditor/plugins/image/lang/mn.js | 25 + .../libs/ckeditor/plugins/image/lang/ms.js | 25 + .../libs/ckeditor/plugins/image/lang/nb.js | 25 + .../libs/ckeditor/plugins/image/lang/nl.js | 25 + .../libs/ckeditor/plugins/image/lang/no.js | 25 + .../libs/ckeditor/plugins/image/lang/oc.js | 25 + .../libs/ckeditor/plugins/image/lang/pl.js | 25 + .../libs/ckeditor/plugins/image/lang/pt-br.js | 25 + .../libs/ckeditor/plugins/image/lang/pt.js | 25 + .../libs/ckeditor/plugins/image/lang/ro.js | 25 + .../libs/ckeditor/plugins/image/lang/ru.js | 25 + .../libs/ckeditor/plugins/image/lang/si.js | 25 + .../libs/ckeditor/plugins/image/lang/sk.js | 25 + .../libs/ckeditor/plugins/image/lang/sl.js | 25 + .../libs/ckeditor/plugins/image/lang/sq.js | 25 + .../ckeditor/plugins/image/lang/sr-latn.js | 25 + .../libs/ckeditor/plugins/image/lang/sr.js | 25 + .../libs/ckeditor/plugins/image/lang/sv.js | 25 + .../libs/ckeditor/plugins/image/lang/th.js | 25 + .../libs/ckeditor/plugins/image/lang/tr.js | 25 + .../libs/ckeditor/plugins/image/lang/tt.js | 25 + .../libs/ckeditor/plugins/image/lang/ug.js | 25 + .../libs/ckeditor/plugins/image/lang/uk.js | 25 + .../libs/ckeditor/plugins/image/lang/vi.js | 25 + .../libs/ckeditor/plugins/image/lang/zh-cn.js | 25 + .../libs/ckeditor/plugins/image/lang/zh.js | 25 + .../res/libs/ckeditor/plugins/image/plugin.js | 184 +++ .../res/templates/admin/add_question.html | 41 +- .../res/templates/admin/edit_question.php | 28 +- resource/res/templates/admin/head_left.php | 2 +- resource/res/templates/shared/profiles.php | 2 +- resource/res/templates/student/head_left.php | 2 +- resource/res/templates/teacher/head_left.php | 2 +- .../img => upload}/avatar/avatar-default.jpg | Bin 98 files changed, 3419 insertions(+), 30 deletions(-) create mode 100644 resource/core/Base.php create mode 100644 resource/res/img/image_btn.png create mode 100644 resource/res/libs/ckeditor/plugins/image/dialogs/image.js create mode 100644 resource/res/libs/ckeditor/plugins/image/icons/hidpi/image.png create mode 100644 resource/res/libs/ckeditor/plugins/image/icons/image.png create mode 100644 resource/res/libs/ckeditor/plugins/image/images/noimage.png create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/af.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ar.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/az.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/bg.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/bn.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/bs.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ca.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/cs.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/cy.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/da.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/de-ch.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/de.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/el.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/en-au.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/en-ca.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/en-gb.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/en.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/eo.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/es-mx.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/es.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/et.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/eu.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/fa.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/fi.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/fo.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/fr-ca.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/fr.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/gl.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/gu.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/he.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/hi.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/hr.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/hu.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/id.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/is.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/it.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ja.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ka.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/km.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ko.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ku.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/lt.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/lv.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/mk.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/mn.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ms.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/nb.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/nl.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/no.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/oc.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/pl.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/pt-br.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/pt.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ro.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ru.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/si.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/sk.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/sl.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/sq.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/sr-latn.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/sr.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/sv.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/th.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/tr.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/tt.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/ug.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/uk.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/vi.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/zh-cn.js create mode 100644 resource/res/libs/ckeditor/plugins/image/lang/zh.js create mode 100644 resource/res/libs/ckeditor/plugins/image/plugin.js rename resource/{res/img => upload}/avatar/avatar-default.jpg (100%) mode change 100755 => 100644 diff --git a/CHANGELOG.md b/CHANGELOG.md index bb4883ab..47f02e75 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ v3.4.2 (27/03/2019) - Fix lỗi không cài đặt được ở 1 số máy ✓ - Fix lỗi không hiện công thức toán khi làm bài ✓ - Rewrite URL ✓ - - Tối ưu lại một số code ✗ + - Thêm upload ảnh trong nội dung câu hỏi ✓ + - Tối ưu lại một số code ✓ - Thêm comment cho các hàm phục vụ cho việc bảo trì, nâng cấp ✗ v3.4.1 (17/03/2019) diff --git a/GUIDE.md b/GUIDE.md index 34423b6a..4e6d96bb 100755 --- a/GUIDE.md +++ b/GUIDE.md @@ -9,6 +9,7 @@ Nếu đã kiểm tra lại và vẫn lỗi, bạn có thể mở file config/connect.php sửa trực tiếp kết nối trong đó, hoặc liên hệ báo lỗi tới email: dzu6996@gmail.com +- Sửa URL trang web trong config/config.php - Sửa tài khoản gửi email quên mật khẩu tại /controllers/controller_login.php dòng 127, 128 - Tài khoản mặc định: diff --git a/resource/config/config.php b/resource/config/config.php index 7ec20549..2c7b894a 100755 --- a/resource/config/config.php +++ b/resource/config/config.php @@ -16,4 +16,5 @@ class Config const EMAIL = "dzu6996@gmail.com"; const RELEASE = "27/03/2019"; const TIMEZONE = "Asia/Bangkok"; + const APP_URL = "http://localhost/"; } diff --git a/resource/controllers/controller_admin.php b/resource/controllers/controller_admin.php index 9dda62fc..76d2a818 100755 --- a/resource/controllers/controller_admin.php +++ b/resource/controllers/controller_admin.php @@ -6,6 +6,8 @@ * Mail: dzu6996@gmail.com **/ +require_once('core/Base.php'); +require_once('config/config.php'); require_once('models/model_admin.php'); require_once('views/view_admin.php'); //load thư viện PhpSpreadSheet @@ -1001,13 +1003,29 @@ public function submit_update_avatar() $duoi = explode('.', $_FILES['file']['name']); $duoi = $duoi[(count($duoi)-1)]; if ($duoi === 'jpg' || $duoi === 'png') { - if (move_uploaded_file($_FILES['file']['tmp_name'], 'res/img/avatar/'.$this->info['username'].'_' . $_FILES['file']['name'])) { + if (move_uploaded_file($_FILES['file']['tmp_name'], 'upload/avatar/'.$this->info['username'].'_' . $_FILES['file']['name'])) { $avatar = $this->info['username'] .'_' . $_FILES['file']['name']; $update = $this->update_avatar($avatar, $this->info['username']); } } } } + public function uploadImage() + { + if (isset($_FILES['file'])) { + $base = new Base(); + $res = array(); + $path = 'upload/question_images/'; + $upload = $base->uploadImage($_FILES['file'],$path); + if($upload != false) { + $res['url'] = Config::APP_URL . $path . $upload; + $res['stt'] = true; + } + else + $res['stt'] = false; + echo json_encode($res); + } + } public function delete_check_students() { $result = array(); diff --git a/resource/controllers/controller_student.php b/resource/controllers/controller_student.php index c764212d..0b85f131 100755 --- a/resource/controllers/controller_student.php +++ b/resource/controllers/controller_student.php @@ -119,7 +119,7 @@ public function submit_update_avatar() $duoi = explode('.', $_FILES['file']['name']); $duoi = $duoi[(count($duoi)-1)]; if ($duoi === 'jpg' || $duoi === 'png') { - if (move_uploaded_file($_FILES['file']['tmp_name'], 'res/img/avatar/'.$this->info['username'].'_' . $_FILES['file']['name'])) { + if (move_uploaded_file($_FILES['file']['tmp_name'], 'upload/avatar/'.$this->info['username'].'_' . $_FILES['file']['name'])) { $avatar = $this->info['username'] .'_' . $_FILES['file']['name']; $update = $this->update_avatar($avatar, $this->info['username']); } diff --git a/resource/controllers/controller_teacher.php b/resource/controllers/controller_teacher.php index c477602a..0e181bbf 100755 --- a/resource/controllers/controller_teacher.php +++ b/resource/controllers/controller_teacher.php @@ -68,7 +68,7 @@ public function submit_update_avatar() $duoi = explode('.', $_FILES['file']['name']); $duoi = $duoi[(count($duoi)-1)]; if ($duoi === 'jpg' || $duoi === 'png') { - if (move_uploaded_file($_FILES['file']['tmp_name'], 'res/img/avatar/'.$this->info['username'].'_' . $_FILES['file']['name'])) { + if (move_uploaded_file($_FILES['file']['tmp_name'], 'upload/avatar/'.$this->info['username'].'_' . $_FILES['file']['name'])) { $avatar = $this->info['username'] .'_' . $_FILES['file']['name']; $update = $this->update_avatar($avatar, $this->info['username']); } diff --git a/resource/core/Base.php b/resource/core/Base.php new file mode 100644 index 00000000..5663eef2 --- /dev/null +++ b/resource/core/Base.php @@ -0,0 +1,46 @@ +convertString($expl[0]); + $hash = md5(time()); + if ($ext === 'jpg' || $ext === 'png' || $ext === 'jpeg') { + $new_name = $hash .'_' . $name . '.' . $ext; + if (move_uploaded_file($file['tmp_name'], $path . $new_name)) { + return $new_name; + } else { + return false; + } + } + + } + public function convertString($str) { + $str = trim(mb_strtolower($str)); + $str = preg_replace('/(à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ)/', 'a', $str); + $str = preg_replace('/(è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ)/', 'e', $str); + $str = preg_replace('/(ì|í|ị|ỉ|ĩ)/', 'i', $str); + $str = preg_replace('/(ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ)/', 'o', $str); + $str = preg_replace('/(ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ)/', 'u', $str); + $str = preg_replace('/(ỳ|ý|ỵ|ỷ|ỹ)/', 'y', $str); + $str = preg_replace('/(đ)/', 'd', $str); + $str = preg_replace('/[^a-z0-9-\s]/', '', $str); + $str = preg_replace('/([\s]+)/', '-', $str); + return $str; + } +} + +?> \ No newline at end of file diff --git a/resource/install.php b/resource/install.php index 89432c68..691cee83 100755 --- a/resource/install.php +++ b/resource/install.php @@ -161,6 +161,7 @@ function step_error() echo "Tài khoản mặc định: admin
"; echo "Mật khẩu: 123456
"; echo "Vui lòng đăng nhập và đổi mật khẩu ngay sau khi đăng nhập.
"; + echo "Sửa URL trang web trong config/config.php
"; echo 'Mọi thông tin chi tiết, hỗ trợ, góp ý, báo lỗi,
'; echo"vui lòng liên hệ dzu6996@gmail.com hoặc trực tiếp trang chính thức sản phẩm TẠI ĐÂY

"; diff --git a/resource/res/img/image_btn.png b/resource/res/img/image_btn.png new file mode 100644 index 0000000000000000000000000000000000000000..8ea97259df1e428333b1dad62e48f94faa666a0d GIT binary patch literal 498 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CDO3=9p;3=BX21L>Cx45bDP46hOx7_4S6Fo@?*ia+WGRLhp+?e4|M(0zkpReK;%1Ag@`=X>@@dRb;faPyOW+kl=`Epd$~Nl7e8wMs5Z1yT$~28L$32IjhkmLZ15 uR>lTaCPvx@Mpgy}5);ZRP&DM`r(~v8;?|IP_WTi`1_n=8KbLh*2~7Z{n5wb> literal 0 HcmV?d00001 diff --git a/resource/res/js/add_question.js b/resource/res/js/add_question.js index 38439205..c0ccf0de 100644 --- a/resource/res/js/add_question.js +++ b/resource/res/js/add_question.js @@ -30,6 +30,47 @@ $(function() { }); }); +function upload_image() { + $('#uploading').removeClass('hidden'); + var file_data = $('#file').prop('files')[0]; + var type = file_data.type; + var size = file_data.size; + var match = ["image/png", "image/jpg", "image/jpeg"]; + if ((type == match[0] && size < 2048000) || (type == match[1] && size < 2048000) || (type == match[2] && size < 2048000)) { + var form_data = new FormData(); + form_data.append('file', file_data); + $.ajax({ + url: 'index.php?action=uploadImage', + dataType: 'text', + cache: false, + contentType: false, + processData: false, + data: form_data, + type: 'post', + success: function(result) { + var json_data = jQuery.parseJSON(result); + if(json_data.stt) { + $('#div-url').removeClass('hidden'); + $('.help').css('color', 'green').text("Thành công"); + $('#file').val(''); + $('#url').val(json_data.url); + $('#uploading').addClass('hidden'); + } else { + $('#div-url').addClass('hidden'); + $('.help').css('color', 'red').text("Thất bại"); + $('#file').val(''); + $('#url').val(''); + $('#uploading').addClass('hidden'); + } + } + }); + } else { + $('.help').css('color', 'red').text('Chỉ được upload file JPG, PNG nhỏ hơn 2mb'); + $('#file').val(''); + $('#uploading').addClass('hidden'); + } +} + function submit_add_question(data) { data[0]['value'] = CKEDITOR.instances.question_detail.getData(); data[1]['value'] = CKEDITOR.instances.answer_a.getData(); diff --git a/resource/res/js/admins_panel.js b/resource/res/js/admins_panel.js index a7d621c3..0e47b354 100755 --- a/resource/res/js/admins_panel.js +++ b/resource/res/js/admins_panel.js @@ -89,7 +89,7 @@ function show_list_admins(data) { var tr = $(''); tr.append('

'); tr.append('' + data[i].admin_id + ''); - tr.append('avatar'); + tr.append('avatar'); tr.append('' + data[i].name + ''); tr.append('' + data[i].username + ''); tr.append('' + data[i].email + ''); diff --git a/resource/res/js/edit_question.js b/resource/res/js/edit_question.js index 8fbbcf11..5240647c 100755 --- a/resource/res/js/edit_question.js +++ b/resource/res/js/edit_question.js @@ -24,4 +24,45 @@ function submit_edit_question(data) { $('#preload').addClass('hidden'); }; $.post(url, data, success); +} + +function upload_image() { + $('#uploading').removeClass('hidden'); + var file_data = $('#file').prop('files')[0]; + var type = file_data.type; + var size = file_data.size; + var match = ["image/png", "image/jpg", "image/jpeg"]; + if ((type == match[0] && size < 2048000) || (type == match[1] && size < 2048000) || (type == match[2] && size < 2048000)) { + var form_data = new FormData(); + form_data.append('file', file_data); + $.ajax({ + url: 'index.php?action=uploadImage', + dataType: 'text', + cache: false, + contentType: false, + processData: false, + data: form_data, + type: 'post', + success: function(result) { + var json_data = jQuery.parseJSON(result); + if(json_data.stt) { + $('#div-url').removeClass('hidden'); + $('.help').css('color', 'green').text("Thành công"); + $('#file').val(''); + $('#url').val(json_data.url); + $('#uploading').addClass('hidden'); + } else { + $('#div-url').addClass('hidden'); + $('.help').css('color', 'red').text("Thất bại"); + $('#file').val(''); + $('#url').val(''); + $('#uploading').addClass('hidden'); + } + } + }); + } else { + $('.help').css('color', 'red').text('Chỉ được upload file JPG, PNG nhỏ hơn 2mb'); + $('#file').val(''); + $('#uploading').addClass('hidden'); + } } \ No newline at end of file diff --git a/resource/res/js/questions_panel.js b/resource/res/js/questions_panel.js index 61c0f2fb..d2a9f4b8 100644 --- a/resource/res/js/questions_panel.js +++ b/resource/res/js/questions_panel.js @@ -20,6 +20,9 @@ $(function() { var instance = M.Modal.getInstance(elem); instance.open(); }); + $("form").on('submit', function(event) { + event.preventDefault(); + }); }); function check_box() { @@ -167,6 +170,9 @@ function get_list_questions() { $('.modal').modal(); $('select').select(); $('body').attr('style', 'overflow: auto;'); + $("form").on('submit', function(event) { + event.preventDefault(); + }); } function question_edit_button(data) { @@ -196,4 +202,4 @@ function submit_del_question(data) { $('#preload').addClass('hidden'); }; $.post(url, data, success); -} \ No newline at end of file +} diff --git a/resource/res/js/students_panel.js b/resource/res/js/students_panel.js index 555ab1a4..9c878ca2 100755 --- a/resource/res/js/students_panel.js +++ b/resource/res/js/students_panel.js @@ -36,6 +36,9 @@ $(function() { var instance = M.Modal.getInstance(elem); instance.open(); }); + $("form").on('submit', function(event) { + event.preventDefault(); + }); }); function check_box() { @@ -142,7 +145,7 @@ function get_list_students() { "targets":2, "render": function(data) { - return 'avatar'; + return 'avatar'; } }, { @@ -204,6 +207,9 @@ function get_list_students() { $('.modal').modal(); $('select').select(); $('body').attr('style', 'overflow: auto;'); + $("form").on('submit', function(event) { + event.preventDefault(); + }); } function student_edit_button(data) { diff --git a/resource/res/js/teachers_panel.js b/resource/res/js/teachers_panel.js index e7a8e310..1e0d8912 100755 --- a/resource/res/js/teachers_panel.js +++ b/resource/res/js/teachers_panel.js @@ -89,7 +89,7 @@ function show_list_teachers(data) { var tr = $(''); tr.append('

'); tr.append('' + data[i].teacher_id + ''); - tr.append('avatar'); + tr.append('avatar'); tr.append('' + data[i].name + ''); tr.append('' + data[i].username + ''); tr.append('' + data[i].email + ''); diff --git a/resource/res/libs/ckeditor/config.js b/resource/res/libs/ckeditor/config.js index 89db121a..929bcb37 100644 --- a/resource/res/libs/ckeditor/config.js +++ b/resource/res/libs/ckeditor/config.js @@ -57,7 +57,7 @@ CKEDITOR.editorConfig = function(config) { // The default plugins included in the basic setup define some buttons that // are not needed in a basic editor. They are removed here. - config.removeButtons = 'Cut,Copy,Paste,Undo,Redo,Anchor,Underline,Strike,Subscript,Superscript'; + config.removeButtons = 'Anchor,Link,Unlink'; // Dialog windows are also simplified. config.removeDialogTabs = 'link:advanced'; @@ -74,6 +74,7 @@ CKEDITOR.editorConfig = function(config) { config.extraPlugins = 'floatpanel'; config.extraPlugins = 'panel'; config.extraPlugins = 'listblock'; + config.extraPlugins = 'image'; config.entities_latin = false; config.basicEntities = false; config.entities = false; diff --git a/resource/res/libs/ckeditor/plugins/image/dialogs/image.js b/resource/res/libs/ckeditor/plugins/image/dialogs/image.js new file mode 100644 index 00000000..8ee58c6c --- /dev/null +++ b/resource/res/libs/ckeditor/plugins/image/dialogs/image.js @@ -0,0 +1,1257 @@ +/** + * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +( function() { + var imageDialog = function( editor, dialogType ) { + // Load image preview. + var IMAGE = 1, + LINK = 2, + PREVIEW = 4, + CLEANUP = 8, + regexGetSize = /^\s*(\d+)((px)|\%)?\s*$/i, + regexGetSizeOrEmpty = /(^\s*(\d+)((px)|\%)?\s*$)|^$/i, + pxLengthRegex = /^\d+px$/; + + var onSizeChange = function() { + var value = this.getValue(), + // This = input element. + dialog = this.getDialog(), + aMatch = value.match( regexGetSize ); // Check value + if ( aMatch ) { + if ( aMatch[ 2 ] == '%' ) // % is allowed - > unlock ratio. + switchLockRatio( dialog, false ); // Unlock. + value = aMatch[ 1 ]; + } + + // Only if ratio is locked + if ( dialog.lockRatio ) { + var oImageOriginal = dialog.originalElement; + if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) { + if ( this.id == 'txtHeight' ) { + if ( value && value != '0' ) + value = Math.round( oImageOriginal.$.width * ( value / oImageOriginal.$.height ) ); + if ( !isNaN( value ) ) + dialog.setValueOf( 'info', 'txtWidth', value ); + } + // this.id = txtWidth. + else { + if ( value && value != '0' ) + value = Math.round( oImageOriginal.$.height * ( value / oImageOriginal.$.width ) ); + if ( !isNaN( value ) ) + dialog.setValueOf( 'info', 'txtHeight', value ); + } + } + } + updatePreview( dialog ); + }; + + var updatePreview = function( dialog ) { + //Don't load before onShow. + if ( !dialog.originalElement || !dialog.preview ) + return 1; + + // Read attributes and update imagePreview; + dialog.commitContent( PREVIEW, dialog.preview ); + return 0; + }; + + // Custom commit dialog logic, where we're intended to give inline style + // field (txtdlgGenStyle) higher priority to avoid overwriting styles contribute + // by other fields. + function commitContent() { + var args = arguments; + var inlineStyleField = this.getContentElement( 'advanced', 'txtdlgGenStyle' ); + inlineStyleField && inlineStyleField.commit.apply( inlineStyleField, args ); + + this.foreach( function( widget ) { + if ( widget.commit && widget.id != 'txtdlgGenStyle' ) + widget.commit.apply( widget, args ); + } ); + } + + // Avoid recursions. + var incommit; + + // Synchronous field values to other impacted fields is required, e.g. border + // size change should alter inline-style text as well. + function commitInternally( targetFields ) { + if ( incommit ) + return; + + incommit = 1; + + var dialog = this.getDialog(), + element = dialog.imageElement; + if ( element ) { + // Commit this field and broadcast to target fields. + this.commit( IMAGE, element ); + + targetFields = [].concat( targetFields ); + var length = targetFields.length, + field; + for ( var i = 0; i < length; i++ ) { + field = dialog.getContentElement.apply( dialog, targetFields[ i ].split( ':' ) ); + // May cause recursion. + field && field.setup( IMAGE, element ); + } + } + + incommit = 0; + } + + var switchLockRatio = function( dialog, value ) { + if ( !dialog.getContentElement( 'info', 'ratioLock' ) ) + return null; + + var oImageOriginal = dialog.originalElement; + + // Dialog may already closed. (https://dev.ckeditor.com/ticket/5505) + if ( !oImageOriginal ) + return null; + + // Check image ratio and original image ratio, but respecting user's preference. + if ( value == 'check' ) { + if ( !dialog.userlockRatio && oImageOriginal.getCustomData( 'isReady' ) == 'true' ) { + var width = dialog.getValueOf( 'info', 'txtWidth' ), + height = dialog.getValueOf( 'info', 'txtHeight' ), + originalRatio = oImageOriginal.$.width / oImageOriginal.$.height, + thisRatio = width / height; + + dialog.lockRatio = false; // Default: unlock ratio + + if ( !width && !height ) { + dialog.lockRatio = true; + } else { + // Round ratio to two decimal places so ratio locking will be less precise (#2254). + var ratioComparison = Math.round( ( originalRatio / thisRatio ) * 100 ) / 100; + + if ( ratioComparison == 1 ) { + dialog.lockRatio = true; + } + } + } + } else if ( value !== undefined ) { + dialog.lockRatio = value; + } else { + dialog.userlockRatio = 1; + dialog.lockRatio = !dialog.lockRatio; + } + + var ratioButton = CKEDITOR.document.getById( btnLockSizesId ); + if ( dialog.lockRatio ) + ratioButton.removeClass( 'cke_btn_unlocked' ); + else + ratioButton.addClass( 'cke_btn_unlocked' ); + + ratioButton.setAttribute( 'aria-checked', dialog.lockRatio ); + + // Ratio button hc presentation - WHITE SQUARE / BLACK SQUARE + if ( CKEDITOR.env.hc ) { + var icon = ratioButton.getChild( 0 ); + icon.setHtml( dialog.lockRatio ? CKEDITOR.env.ie ? '\u25A0' : '\u25A3' : CKEDITOR.env.ie ? '\u25A1' : '\u25A2' ); + } + + return dialog.lockRatio; + }; + + var resetSize = function( dialog, emptyValues ) { + var oImageOriginal = dialog.originalElement, + ready = oImageOriginal.getCustomData( 'isReady' ) == 'true'; + + if ( ready ) { + var widthField = dialog.getContentElement( 'info', 'txtWidth' ), + heightField = dialog.getContentElement( 'info', 'txtHeight' ), + widthValue, heightValue; + + if ( emptyValues ) { + widthValue = 0; + heightValue = 0; + } else { + widthValue = oImageOriginal.$.width; + heightValue = oImageOriginal.$.height; + } + + widthField && widthField.setValue( widthValue ); + heightField && heightField.setValue( heightValue ); + } + updatePreview( dialog ); + }; + + var setupDimension = function( type, element ) { + if ( type != IMAGE ) + return; + + function checkDimension( size, defaultValue ) { + var aMatch = size.match( regexGetSize ); + if ( aMatch ) { + // % is allowed. + if ( aMatch[ 2 ] == '%' ) { + aMatch[ 1 ] += '%'; + switchLockRatio( dialog, false ); // Unlock ratio + } + return aMatch[ 1 ]; + } + return defaultValue; + } + + var dialog = this.getDialog(), + value = '', + dimension = this.id == 'txtWidth' ? 'width' : 'height', + size = element.getAttribute( dimension ); + + if ( size ) + value = checkDimension( size, value ); + value = checkDimension( element.getStyle( dimension ), value ); + + this.setValue( value ); + }; + + var previewPreloader; + + var onImgLoadEvent = function() { + // Image is ready. + var original = this.originalElement, + loader = CKEDITOR.document.getById( imagePreviewLoaderId ); + + original.setCustomData( 'isReady', 'true' ); + original.removeListener( 'load', onImgLoadEvent ); + original.removeListener( 'error', onImgLoadErrorEvent ); + original.removeListener( 'abort', onImgLoadErrorEvent ); + + // Hide loader. + if ( loader ) + loader.setStyle( 'display', 'none' ); + + // New image -> new dimensions + if ( !this.dontResetSize ) { + resetSize( this, editor.config.image_prefillDimensions === false ); + } + + if ( this.firstLoad ) { + CKEDITOR.tools.setTimeout( function() { + switchLockRatio( this, 'check' ); + }, 0, this ); + } + + this.firstLoad = false; + this.dontResetSize = false; + + // Possible fix for https://dev.ckeditor.com/ticket/12818. + updatePreview( this ); + }; + + var onImgLoadErrorEvent = function() { + // Error. Image is not loaded. + var original = this.originalElement, + loader = CKEDITOR.document.getById( imagePreviewLoaderId ); + + original.removeListener( 'load', onImgLoadEvent ); + original.removeListener( 'error', onImgLoadErrorEvent ); + original.removeListener( 'abort', onImgLoadErrorEvent ); + + // Set Error image. + var noimage = CKEDITOR.getUrl( CKEDITOR.plugins.get( 'image' ).path + 'images/noimage.png' ); + + if ( this.preview ) + this.preview.setAttribute( 'src', noimage ); + + // Hide loader. + if ( loader ) + loader.setStyle( 'display', 'none' ); + + switchLockRatio( this, false ); // Unlock. + }; + + var numbering = function( id ) { + return CKEDITOR.tools.getNextId() + '_' + id; + }, + btnLockSizesId = numbering( 'btnLockSizes' ), + btnResetSizeId = numbering( 'btnResetSize' ), + imagePreviewLoaderId = numbering( 'ImagePreviewLoader' ), + previewLinkId = numbering( 'previewLink' ), + previewImageId = numbering( 'previewImage' ); + + return { + title: editor.lang.image[ dialogType == 'image' ? 'title' : 'titleButton' ], + minWidth: ( CKEDITOR.skinName || editor.config.skin ) == 'moono-lisa' ? 500 : 420, + minHeight: 360, + onShow: function() { + this.imageElement = false; + this.linkElement = false; + + // Default: create a new element. + this.imageEditMode = false; + this.linkEditMode = false; + + this.lockRatio = true; + this.userlockRatio = 0; + this.dontResetSize = false; + this.firstLoad = true; + this.addLink = false; + + var editor = this.getParentEditor(), + sel = editor.getSelection(), + element = sel && sel.getSelectedElement(), + link = element && editor.elementPath( element ).contains( 'a', 1 ), + loader = CKEDITOR.document.getById( imagePreviewLoaderId ); + + // Hide loader. + if ( loader ) + loader.setStyle( 'display', 'none' ); + + // Create the preview before setup the dialog contents. + previewPreloader = new CKEDITOR.dom.element( 'img', editor.document ); + this.preview = CKEDITOR.document.getById( previewImageId ); + + // Copy of the image + this.originalElement = editor.document.createElement( 'img' ); + this.originalElement.setAttribute( 'alt', '' ); + this.originalElement.setCustomData( 'isReady', 'false' ); + + if ( link ) { + this.linkElement = link; + this.linkEditMode = true; + + // If there is an existing link, by default keep it (true). + // It will be removed if certain conditions are met and Link tab is enabled. (https://dev.ckeditor.com/ticket/13351) + this.addLink = true; + + // Look for Image element. + var linkChildren = link.getChildren(); + if ( linkChildren.count() == 1 ) { + var childTag = linkChildren.getItem( 0 ); + + if ( childTag.type == CKEDITOR.NODE_ELEMENT ) { + if ( childTag.is( 'img' ) || childTag.is( 'input' ) ) { + this.imageElement = linkChildren.getItem( 0 ); + if ( this.imageElement.is( 'img' ) ) + this.imageEditMode = 'img'; + else if ( this.imageElement.is( 'input' ) ) + this.imageEditMode = 'input'; + } + } + } + // Fill out all fields. + if ( dialogType == 'image' ) + this.setupContent( LINK, link ); + } + + // Edit given image element instead the one from selection. + if ( this.customImageElement ) { + this.imageEditMode = 'img'; + this.imageElement = this.customImageElement; + delete this.customImageElement; + } + else if ( element && element.getName() == 'img' && !element.data( 'cke-realelement' ) || + element && element.getName() == 'input' && element.getAttribute( 'type' ) == 'image' ) { + this.imageEditMode = element.getName(); + this.imageElement = element; + } + + if ( this.imageEditMode ) { + // Use the original element as a buffer from since we don't want + // temporary changes to be committed, e.g. if the dialog is canceled. + this.cleanImageElement = this.imageElement; + this.imageElement = this.cleanImageElement.clone( true, true ); + + // Fill out all fields. + this.setupContent( IMAGE, this.imageElement ); + } + + // Refresh LockRatio button + switchLockRatio( this, true ); + + // Dont show preview if no URL given. + if ( !CKEDITOR.tools.trim( this.getValueOf( 'info', 'txtUrl' ) ) ) { + this.preview.removeAttribute( 'src' ); + this.preview.setStyle( 'display', 'none' ); + } + }, + onOk: function() { + // Edit existing Image. + if ( this.imageEditMode ) { + var imgTagName = this.imageEditMode; + + // Image dialog and Input element. + if ( dialogType == 'image' && imgTagName == 'input' && confirm( editor.lang.image.button2Img ) ) { // jshint ignore:line + // Replace INPUT-> IMG + imgTagName = 'img'; + this.imageElement = editor.document.createElement( 'img' ); + this.imageElement.setAttribute( 'alt', '' ); + editor.insertElement( this.imageElement ); + } + // ImageButton dialog and Image element. + else if ( dialogType != 'image' && imgTagName == 'img' && confirm( editor.lang.image.img2Button ) ) { // jshint ignore:line + // Replace IMG -> INPUT + imgTagName = 'input'; + this.imageElement = editor.document.createElement( 'input' ); + this.imageElement.setAttributes( { + type: 'image', + alt: '' + } ); + editor.insertElement( this.imageElement ); + } else { + // Restore the original element before all commits. + this.imageElement = this.cleanImageElement; + delete this.cleanImageElement; + } + } + // Create a new image. + else { + // Image dialog -> create IMG element. + if ( dialogType == 'image' ) + this.imageElement = editor.document.createElement( 'img' ); + else { + this.imageElement = editor.document.createElement( 'input' ); + this.imageElement.setAttribute( 'type', 'image' ); + } + this.imageElement.setAttribute( 'alt', '' ); + } + + // Create a new link. + if ( !this.linkEditMode ) + this.linkElement = editor.document.createElement( 'a' ); + + // Set attributes. + this.commitContent( IMAGE, this.imageElement ); + this.commitContent( LINK, this.linkElement ); + + // Remove empty style attribute. + if ( !this.imageElement.getAttribute( 'style' ) ) + this.imageElement.removeAttribute( 'style' ); + + // Insert a new Image. + if ( !this.imageEditMode ) { + if ( this.addLink ) { + if ( !this.linkEditMode ) { + // Insert a new link. + editor.insertElement( this.linkElement ); + this.linkElement.append( this.imageElement, false ); + } else { + // We already have a link in editor. + if ( this.linkElement.equals( editor.getSelection().getSelectedElement() ) ) { + // If the link is selected outside, replace it's content rather than the link itself. ([foo]) + this.linkElement.setHtml( '' ); + this.linkElement.append( this.imageElement, false ); + } else { + // Only inside of the link is selected, so replace it with image. ([foo], [f]oo) + editor.insertElement( this.imageElement ); + } + } + } else { + editor.insertElement( this.imageElement ); + } + } + // Image already exists. + else { + // Add a new link element. + if ( !this.linkEditMode && this.addLink ) { + editor.insertElement( this.linkElement ); + this.imageElement.appendTo( this.linkElement ); + } + // Remove Link, Image exists. + else if ( this.linkEditMode && !this.addLink ) { + editor.getSelection().selectElement( this.linkElement ); + editor.insertElement( this.imageElement ); + } + } + }, + onLoad: function() { + if ( dialogType != 'image' ) + this.hidePage( 'Link' ); //Hide Link tab. + var doc = this._.element.getDocument(); + + if ( this.getContentElement( 'info', 'ratioLock' ) ) { + this.addFocusable( doc.getById( btnResetSizeId ), 5 ); + this.addFocusable( doc.getById( btnLockSizesId ), 5 ); + } + + this.commitContent = commitContent; + }, + onHide: function() { + if ( this.preview ) + this.commitContent( CLEANUP, this.preview ); + + if ( this.originalElement ) { + this.originalElement.removeListener( 'load', onImgLoadEvent ); + this.originalElement.removeListener( 'error', onImgLoadErrorEvent ); + this.originalElement.removeListener( 'abort', onImgLoadErrorEvent ); + this.originalElement.remove(); + this.originalElement = false; // Dialog is closed. + } + + delete this.imageElement; + }, + contents: [ { + id: 'info', + label: editor.lang.image.infoTab, + accessKey: 'I', + elements: [ { + type: 'vbox', + padding: 0, + children: [ { + type: 'hbox', + widths: [ '280px', '110px' ], + align: 'right', + className: 'cke_dialog_image_url', + children: [ { + id: 'txtUrl', + type: 'text', + label: editor.lang.common.url, + required: true, + onChange: function() { + var dialog = this.getDialog(), + newUrl = this.getValue(); + + // Update original image. + // Prevent from load before onShow. + if ( newUrl.length > 0 ) { + dialog = this.getDialog(); + var original = dialog.originalElement; + + if ( dialog.preview ) { + dialog.preview.removeStyle( 'display' ); + } + + original.setCustomData( 'isReady', 'false' ); + // Show loader. + var loader = CKEDITOR.document.getById( imagePreviewLoaderId ); + if ( loader ) + loader.setStyle( 'display', '' ); + + original.on( 'load', onImgLoadEvent, dialog ); + original.on( 'error', onImgLoadErrorEvent, dialog ); + original.on( 'abort', onImgLoadErrorEvent, dialog ); + original.setAttribute( 'src', newUrl ); + + if ( dialog.preview ) { + // Query the preloader to figure out the url impacted by based href. + previewPreloader.setAttribute( 'src', newUrl ); + dialog.preview.setAttribute( 'src', previewPreloader.$.src ); + updatePreview( dialog ); + } + } + // Dont show preview if no URL given. + else if ( dialog.preview ) { + dialog.preview.removeAttribute( 'src' ); + dialog.preview.setStyle( 'display', 'none' ); + } + }, + setup: function( type, element ) { + if ( type == IMAGE ) { + var url = element.data( 'cke-saved-src' ) || element.getAttribute( 'src' ); + var field = this; + + this.getDialog().dontResetSize = true; + + field.setValue( url ); // And call this.onChange() + // Manually set the initial value.(https://dev.ckeditor.com/ticket/4191) + field.setInitValue(); + } + }, + commit: function( type, element ) { + if ( type == IMAGE && ( this.getValue() || this.isChanged() ) ) { + element.data( 'cke-saved-src', this.getValue() ); + element.setAttribute( 'src', this.getValue() ); + } else if ( type == CLEANUP ) { + element.setAttribute( 'src', '' ); // If removeAttribute doesn't work. + element.removeAttribute( 'src' ); + } + }, + validate: CKEDITOR.dialog.validate.notEmpty( editor.lang.image.urlMissing ) + }, + { + type: 'button', + id: 'browse', + // v-align with the 'txtUrl' field. + // TODO: We need something better than a fixed size here. + style: 'display:inline-block;margin-top:14px;', + align: 'center', + label: editor.lang.common.browseServer, + hidden: true, + filebrowser: 'info:txtUrl' + } ] + } ] + }, + { + id: 'txtAlt', + type: 'text', + label: editor.lang.image.alt, + accessKey: 'T', + 'default': '', + onChange: function() { + updatePreview( this.getDialog() ); + }, + setup: function( type, element ) { + if ( type == IMAGE ) + this.setValue( element.getAttribute( 'alt' ) ); + }, + commit: function( type, element ) { + if ( type == IMAGE ) { + if ( this.getValue() || this.isChanged() ) + element.setAttribute( 'alt', this.getValue() ); + } else if ( type == PREVIEW ) + element.setAttribute( 'alt', this.getValue() ); + else if ( type == CLEANUP ) { + element.removeAttribute( 'alt' ); + } + + } + }, + { + type: 'hbox', + children: [ { + id: 'basic', + type: 'vbox', + children: [ { + type: 'hbox', + requiredContent: 'img{width,height}', + widths: [ '50%', '50%' ], + children: [ { + type: 'vbox', + padding: 1, + children: [ { + type: 'text', + width: '45px', + id: 'txtWidth', + label: editor.lang.common.width, + onKeyUp: onSizeChange, + onChange: function() { + commitInternally.call( this, 'advanced:txtdlgGenStyle' ); + }, + validate: function() { + var aMatch = this.getValue().match( regexGetSizeOrEmpty ), + isValid = !!( aMatch && parseInt( aMatch[ 1 ], 10 ) !== 0 ); + if ( !isValid ) + alert( editor.lang.common.invalidLength.replace( '%1', editor.lang.common.width ).replace( '%2', 'px, %' ) ); // jshint ignore:line + return isValid; + }, + setup: setupDimension, + commit: function( type, element ) { + var value = this.getValue(); + if ( type == IMAGE ) { + if ( value && editor.activeFilter.check( 'img{width,height}' ) ) + element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) ); + else + element.removeStyle( 'width' ); + + element.removeAttribute( 'width' ); + } else if ( type == PREVIEW ) { + var aMatch = value.match( regexGetSize ); + if ( !aMatch ) { + var oImageOriginal = this.getDialog().originalElement; + if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) + element.setStyle( 'width', oImageOriginal.$.width + 'px' ); + } else { + element.setStyle( 'width', CKEDITOR.tools.cssLength( value ) ); + } + } else if ( type == CLEANUP ) { + element.removeAttribute( 'width' ); + element.removeStyle( 'width' ); + } + } + }, + { + type: 'text', + id: 'txtHeight', + width: '45px', + label: editor.lang.common.height, + onKeyUp: onSizeChange, + onChange: function() { + commitInternally.call( this, 'advanced:txtdlgGenStyle' ); + }, + validate: function() { + var aMatch = this.getValue().match( regexGetSizeOrEmpty ), + isValid = !!( aMatch && parseInt( aMatch[ 1 ], 10 ) !== 0 ); + if ( !isValid ) + alert( editor.lang.common.invalidLength.replace( '%1', editor.lang.common.height ).replace( '%2', 'px, %' ) ); // jshint ignore:line + return isValid; + }, + setup: setupDimension, + commit: function( type, element ) { + var value = this.getValue(); + if ( type == IMAGE ) { + if ( value && editor.activeFilter.check( 'img{width,height}' ) ) + element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) ); + else + element.removeStyle( 'height' ); + + element.removeAttribute( 'height' ); + } else if ( type == PREVIEW ) { + var aMatch = value.match( regexGetSize ); + if ( !aMatch ) { + var oImageOriginal = this.getDialog().originalElement; + if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' ) + element.setStyle( 'height', oImageOriginal.$.height + 'px' ); + } else { + element.setStyle( 'height', CKEDITOR.tools.cssLength( value ) ); + } + } else if ( type == CLEANUP ) { + element.removeAttribute( 'height' ); + element.removeStyle( 'height' ); + } + } + } ] + }, + { + id: 'ratioLock', + type: 'html', + className: 'cke_dialog_image_ratiolock', + style: 'margin-top:30px;width:40px;height:40px;', + onLoad: function() { + // Activate Reset button + var resetButton = CKEDITOR.document.getById( btnResetSizeId ), + ratioButton = CKEDITOR.document.getById( btnLockSizesId ); + if ( resetButton ) { + resetButton.on( 'click', function( evt ) { + resetSize( this ); + evt.data && evt.data.preventDefault(); + }, this.getDialog() ); + resetButton.on( 'mouseover', function() { + this.addClass( 'cke_btn_over' ); + }, resetButton ); + resetButton.on( 'mouseout', function() { + this.removeClass( 'cke_btn_over' ); + }, resetButton ); + } + // Activate (Un)LockRatio button + if ( ratioButton ) { + ratioButton.on( 'click', function( evt ) { + switchLockRatio( this ); + + var oImageOriginal = this.originalElement, + width = this.getValueOf( 'info', 'txtWidth' ); + + if ( oImageOriginal.getCustomData( 'isReady' ) == 'true' && width ) { + var height = oImageOriginal.$.height / oImageOriginal.$.width * width; + if ( !isNaN( height ) ) { + this.setValueOf( 'info', 'txtHeight', Math.round( height ) ); + updatePreview( this ); + } + } + evt.data && evt.data.preventDefault(); + }, this.getDialog() ); + ratioButton.on( 'mouseover', function() { + this.addClass( 'cke_btn_over' ); + }, ratioButton ); + ratioButton.on( 'mouseout', function() { + this.removeClass( 'cke_btn_over' ); + }, ratioButton ); + } + }, + html: '
' + + '' + editor.lang.image.lockRatio + '' + + '' + editor.lang.image.resetSize + '' + + '
' + } ] + }, + { + type: 'vbox', + padding: 1, + children: [ { + type: 'text', + id: 'txtBorder', + requiredContent: 'img{border-width}', + width: '60px', + label: editor.lang.image.border, + 'default': '', + onKeyUp: function() { + updatePreview( this.getDialog() ); + }, + onChange: function() { + commitInternally.call( this, 'advanced:txtdlgGenStyle' ); + }, + validate: CKEDITOR.dialog.validate.integer( editor.lang.image.validateBorder ), + setup: function( type, element ) { + if ( type == IMAGE ) { + var value, + borderStyle = element.getStyle( 'border-width' ); + borderStyle = borderStyle && borderStyle.match( /^(\d+px)(?: \1 \1 \1)?$/ ); + value = borderStyle && parseInt( borderStyle[ 1 ], 10 ); + isNaN( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'border' ) ); + this.setValue( value ); + } + }, + commit: function( type, element ) { + var value = parseInt( this.getValue(), 10 ); + if ( type == IMAGE || type == PREVIEW ) { + if ( !isNaN( value ) ) { + element.setStyle( 'border-width', CKEDITOR.tools.cssLength( value ) ); + element.setStyle( 'border-style', 'solid' ); + } else if ( !value && this.isChanged() ) { + element.removeStyle( 'border' ); + } + + if ( type == IMAGE ) + element.removeAttribute( 'border' ); + } else if ( type == CLEANUP ) { + element.removeAttribute( 'border' ); + element.removeStyle( 'border-width' ); + element.removeStyle( 'border-style' ); + element.removeStyle( 'border-color' ); + } + } + }, + { + type: 'text', + id: 'txtHSpace', + requiredContent: 'img{margin-left,margin-right}', + width: '60px', + label: editor.lang.image.hSpace, + 'default': '', + onKeyUp: function() { + updatePreview( this.getDialog() ); + }, + onChange: function() { + commitInternally.call( this, 'advanced:txtdlgGenStyle' ); + }, + validate: CKEDITOR.dialog.validate.integer( editor.lang.image.validateHSpace ), + setup: function( type, element ) { + if ( type == IMAGE ) { + var value, marginLeftPx, marginRightPx, + marginLeftStyle = element.getStyle( 'margin-left' ), + marginRightStyle = element.getStyle( 'margin-right' ); + + marginLeftStyle = marginLeftStyle && marginLeftStyle.match( pxLengthRegex ); + marginRightStyle = marginRightStyle && marginRightStyle.match( pxLengthRegex ); + marginLeftPx = parseInt( marginLeftStyle, 10 ); + marginRightPx = parseInt( marginRightStyle, 10 ); + + value = ( marginLeftPx == marginRightPx ) && marginLeftPx; + isNaN( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'hspace' ) ); + + this.setValue( value ); + } + }, + commit: function( type, element ) { + var value = parseInt( this.getValue(), 10 ); + if ( type == IMAGE || type == PREVIEW ) { + if ( !isNaN( value ) ) { + element.setStyle( 'margin-left', CKEDITOR.tools.cssLength( value ) ); + element.setStyle( 'margin-right', CKEDITOR.tools.cssLength( value ) ); + } else if ( !value && this.isChanged() ) { + element.removeStyle( 'margin-left' ); + element.removeStyle( 'margin-right' ); + } + + if ( type == IMAGE ) + element.removeAttribute( 'hspace' ); + } else if ( type == CLEANUP ) { + element.removeAttribute( 'hspace' ); + element.removeStyle( 'margin-left' ); + element.removeStyle( 'margin-right' ); + } + } + }, + { + type: 'text', + id: 'txtVSpace', + requiredContent: 'img{margin-top,margin-bottom}', + width: '60px', + label: editor.lang.image.vSpace, + 'default': '', + onKeyUp: function() { + updatePreview( this.getDialog() ); + }, + onChange: function() { + commitInternally.call( this, 'advanced:txtdlgGenStyle' ); + }, + validate: CKEDITOR.dialog.validate.integer( editor.lang.image.validateVSpace ), + setup: function( type, element ) { + if ( type == IMAGE ) { + var value, marginTopPx, marginBottomPx, + marginTopStyle = element.getStyle( 'margin-top' ), + marginBottomStyle = element.getStyle( 'margin-bottom' ); + + marginTopStyle = marginTopStyle && marginTopStyle.match( pxLengthRegex ); + marginBottomStyle = marginBottomStyle && marginBottomStyle.match( pxLengthRegex ); + marginTopPx = parseInt( marginTopStyle, 10 ); + marginBottomPx = parseInt( marginBottomStyle, 10 ); + + value = ( marginTopPx == marginBottomPx ) && marginTopPx; + isNaN( parseInt( value, 10 ) ) && ( value = element.getAttribute( 'vspace' ) ); + this.setValue( value ); + } + }, + commit: function( type, element ) { + var value = parseInt( this.getValue(), 10 ); + if ( type == IMAGE || type == PREVIEW ) { + if ( !isNaN( value ) ) { + element.setStyle( 'margin-top', CKEDITOR.tools.cssLength( value ) ); + element.setStyle( 'margin-bottom', CKEDITOR.tools.cssLength( value ) ); + } else if ( !value && this.isChanged() ) { + element.removeStyle( 'margin-top' ); + element.removeStyle( 'margin-bottom' ); + } + + if ( type == IMAGE ) + element.removeAttribute( 'vspace' ); + } else if ( type == CLEANUP ) { + element.removeAttribute( 'vspace' ); + element.removeStyle( 'margin-top' ); + element.removeStyle( 'margin-bottom' ); + } + } + }, + { + id: 'cmbAlign', + requiredContent: 'img{float}', + type: 'select', + widths: [ '35%', '65%' ], + style: 'width:90px', + label: editor.lang.common.align, + 'default': '', + items: [ + [ editor.lang.common.notSet, '' ], + [ editor.lang.common.left, 'left' ], + [ editor.lang.common.right, 'right' ] + // Backward compatible with v2 on setup when specified as attribute value, + // while these values are no more available as select options. + // [ editor.lang.image.alignAbsBottom , 'absBottom'], + // [ editor.lang.image.alignAbsMiddle , 'absMiddle'], + // [ editor.lang.image.alignBaseline , 'baseline'], + // [ editor.lang.image.alignTextTop , 'text-top'], + // [ editor.lang.image.alignBottom , 'bottom'], + // [ editor.lang.image.alignMiddle , 'middle'], + // [ editor.lang.image.alignTop , 'top'] + ], + onChange: function() { + updatePreview( this.getDialog() ); + commitInternally.call( this, 'advanced:txtdlgGenStyle' ); + }, + setup: function( type, element ) { + if ( type == IMAGE ) { + var value = element.getStyle( 'float' ); + switch ( value ) { + // Ignore those unrelated values. + case 'inherit': + case 'none': + value = ''; + } + + !value && ( value = ( element.getAttribute( 'align' ) || '' ).toLowerCase() ); + this.setValue( value ); + } + }, + commit: function( type, element ) { + var value = this.getValue(); + if ( type == IMAGE || type == PREVIEW ) { + if ( value ) + element.setStyle( 'float', value ); + else + element.removeStyle( 'float' ); + + if ( type == IMAGE ) { + value = ( element.getAttribute( 'align' ) || '' ).toLowerCase(); + switch ( value ) { + // we should remove it only if it matches "left" or "right", + // otherwise leave it intact. + case 'left': + case 'right': + element.removeAttribute( 'align' ); + } + } + } else if ( type == CLEANUP ) { + element.removeStyle( 'float' ); + } + } + } ] + } ] + }, + { + type: 'vbox', + height: '250px', + children: [ { + type: 'html', + id: 'htmlPreview', + style: 'width:95%;', + html: '
' + CKEDITOR.tools.htmlEncode( editor.lang.common.preview ) + '
' + + '' + + '
' + + '' + + '' + + // jscs:disable maximumLineLength + ( editor.config.image_previewText || '' ) + + // jscs:enable maximumLineLength + '
' + } ] + } ] + } ] + }, + { + id: 'Link', + requiredContent: 'a[href]', + label: editor.lang.image.linkTab, + padding: 0, + elements: [ { + id: 'txtUrl', + type: 'text', + label: editor.lang.common.url, + style: 'width: 100%', + 'default': '', + setup: function( type, element ) { + if ( type == LINK ) { + var href = element.data( 'cke-saved-href' ); + if ( !href ) + href = element.getAttribute( 'href' ); + this.setValue( href ); + } + }, + commit: function( type, element ) { + if ( type == LINK ) { + if ( this.getValue() || this.isChanged() ) { + var url = this.getValue(); + element.data( 'cke-saved-href', url ); + element.setAttribute( 'href', url ); + + if ( this.getValue() || !editor.config.image_removeLinkByEmptyURL ) + this.getDialog().addLink = true; + else + this.getDialog().addLink = false; + } + } + } + }, + { + type: 'button', + id: 'browse', + className: 'cke_dialog_image_browse', + filebrowser: { + action: 'Browse', + target: 'Link:txtUrl', + url: editor.config.filebrowserImageBrowseLinkUrl + }, + style: 'float:right', + hidden: true, + label: editor.lang.common.browseServer + }, + { + id: 'cmbTarget', + type: 'select', + requiredContent: 'a[target]', + label: editor.lang.common.target, + 'default': '', + items: [ + [ editor.lang.common.notSet, '' ], + [ editor.lang.common.targetNew, '_blank' ], + [ editor.lang.common.targetTop, '_top' ], + [ editor.lang.common.targetSelf, '_self' ], + [ editor.lang.common.targetParent, '_parent' ] + ], + setup: function( type, element ) { + if ( type == LINK ) + this.setValue( element.getAttribute( 'target' ) || '' ); + }, + commit: function( type, element ) { + if ( type == LINK ) { + if ( this.getValue() || this.isChanged() ) + element.setAttribute( 'target', this.getValue() ); + } + } + } ] + }, + { + id: 'Upload', + hidden: true, + filebrowser: 'uploadButton', + label: editor.lang.image.upload, + elements: [ { + type: 'file', + id: 'upload', + label: editor.lang.image.btnUpload, + style: 'height:40px', + size: 38 + }, + { + type: 'fileButton', + id: 'uploadButton', + filebrowser: 'info:txtUrl', + label: editor.lang.image.btnUpload, + 'for': [ 'Upload', 'upload' ] + } ] + }, + { + id: 'advanced', + label: editor.lang.common.advancedTab, + elements: [ { + type: 'hbox', + widths: [ '50%', '25%', '25%' ], + children: [ { + type: 'text', + id: 'linkId', + requiredContent: 'img[id]', + label: editor.lang.common.id, + setup: function( type, element ) { + if ( type == IMAGE ) + this.setValue( element.getAttribute( 'id' ) ); + }, + commit: function( type, element ) { + if ( type == IMAGE ) { + if ( this.getValue() || this.isChanged() ) + element.setAttribute( 'id', this.getValue() ); + } + } + }, + { + id: 'cmbLangDir', + type: 'select', + requiredContent: 'img[dir]', + style: 'width : 100px;', + label: editor.lang.common.langDir, + 'default': '', + items: [ + [ editor.lang.common.notSet, '' ], + [ editor.lang.common.langDirLtr, 'ltr' ], + [ editor.lang.common.langDirRtl, 'rtl' ] + ], + setup: function( type, element ) { + if ( type == IMAGE ) + this.setValue( element.getAttribute( 'dir' ) ); + }, + commit: function( type, element ) { + if ( type == IMAGE ) { + if ( this.getValue() || this.isChanged() ) + element.setAttribute( 'dir', this.getValue() ); + } + } + }, + { + type: 'text', + id: 'txtLangCode', + requiredContent: 'img[lang]', + label: editor.lang.common.langCode, + 'default': '', + setup: function( type, element ) { + if ( type == IMAGE ) + this.setValue( element.getAttribute( 'lang' ) ); + }, + commit: function( type, element ) { + if ( type == IMAGE ) { + if ( this.getValue() || this.isChanged() ) + element.setAttribute( 'lang', this.getValue() ); + } + } + } ] + }, + { + type: 'text', + id: 'txtGenLongDescr', + requiredContent: 'img[longdesc]', + label: editor.lang.common.longDescr, + setup: function( type, element ) { + if ( type == IMAGE ) + this.setValue( element.getAttribute( 'longDesc' ) ); + }, + commit: function( type, element ) { + if ( type == IMAGE ) { + if ( this.getValue() || this.isChanged() ) + element.setAttribute( 'longDesc', this.getValue() ); + } + } + }, + { + type: 'hbox', + widths: [ '50%', '50%' ], + children: [ { + type: 'text', + id: 'txtGenClass', + requiredContent: 'img(cke-xyz)', // Random text like 'xyz' will check if all are allowed. + label: editor.lang.common.cssClass, + 'default': '', + setup: function( type, element ) { + if ( type == IMAGE ) + this.setValue( element.getAttribute( 'class' ) ); + }, + commit: function( type, element ) { + if ( type == IMAGE ) { + if ( this.getValue() || this.isChanged() ) + element.setAttribute( 'class', this.getValue() ); + } + } + }, + { + type: 'text', + id: 'txtGenTitle', + requiredContent: 'img[title]', + label: editor.lang.common.advisoryTitle, + 'default': '', + onChange: function() { + updatePreview( this.getDialog() ); + }, + setup: function( type, element ) { + if ( type == IMAGE ) + this.setValue( element.getAttribute( 'title' ) ); + }, + commit: function( type, element ) { + if ( type == IMAGE ) { + if ( this.getValue() || this.isChanged() ) + element.setAttribute( 'title', this.getValue() ); + } else if ( type == PREVIEW ) + element.setAttribute( 'title', this.getValue() ); + else if ( type == CLEANUP ) { + element.removeAttribute( 'title' ); + } + } + } ] + }, + { + type: 'text', + id: 'txtdlgGenStyle', + requiredContent: 'img{cke-xyz}', // Random text like 'xyz' will check if all are allowed. + label: editor.lang.common.cssStyle, + validate: CKEDITOR.dialog.validate.inlineStyle( editor.lang.common.invalidInlineStyle ), + 'default': '', + setup: function( type, element ) { + if ( type == IMAGE ) { + var genStyle = element.getAttribute( 'style' ); + if ( !genStyle && element.$.style.cssText ) + genStyle = element.$.style.cssText; + this.setValue( genStyle ); + + var height = element.$.style.height, + width = element.$.style.width, + aMatchH = ( height ? height : '' ).match( regexGetSize ), + aMatchW = ( width ? width : '' ).match( regexGetSize ); + + this.attributesInStyle = { + height: !!aMatchH, + width: !!aMatchW + }; + } + }, + onChange: function() { + commitInternally.call( + this, [ + 'info:cmbFloat', + 'info:cmbAlign', + 'info:txtVSpace', + 'info:txtHSpace', + 'info:txtBorder', + 'info:txtWidth', + 'info:txtHeight' + ] + ); + updatePreview( this ); + }, + commit: function( type, element ) { + if ( type == IMAGE && ( this.getValue() || this.isChanged() ) ) + element.setAttribute( 'style', this.getValue() ); + + } + } ] + } ] + }; + }; + + CKEDITOR.dialog.add( 'image', function( editor ) { + return imageDialog( editor, 'image' ); + } ); + + CKEDITOR.dialog.add( 'imagebutton', function( editor ) { + return imageDialog( editor, 'imagebutton' ); + } ); +} )(); diff --git a/resource/res/libs/ckeditor/plugins/image/icons/hidpi/image.png b/resource/res/libs/ckeditor/plugins/image/icons/hidpi/image.png new file mode 100644 index 0000000000000000000000000000000000000000..d0f21aeec2061dd27fc335d91509001bf040b394 GIT binary patch literal 905 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmUKs7M+SzC{oH>NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!ItFh?!xdN1Q+aGJ{c&& zUgGKN%Km_xiC2-KneQA20|Qg9r;B4q#NngiyYsF(2-t2e&*?U+aq!am(IlcN?C9;< z{gag|it8W4%Sn^E#JWl}Kd}Y`K4bRiPI~{2hc(K$eEr^Sp9Pd7Z+)LrT=qut^2w8& z$9zJ|f4OYQ+LuzcK6=mV#y8g(t{KGfDop>b*t_=roJ6Kcw>r1x_Mg=^VPcq<6dj~! zd5ZC_o28uO?Zt-2^Ok;|+q$RXdR1q4x@vK-up$e?4WWrb6Pa#Qy?<}(P@Z&vP1ra; zbgSuSU1Q;fYi!S>j$QK)WMt44JZPCdckj9D^XJc3UaP!FHei+2su{A{#~iF2T-X#W zKVQCl*>%nGHD6T!nCSdkekgKZ#^#%EEMgv62nL5*+}_B&=X<_ON`Zz_`n}&~`@hG0 z+G@6v!T7M{^+)f^8|M`38uR;I-g{i)yGX{YXPgbEHLrKyph5&u=G= z9XogaT)E2K z49!|DUsk`~75L4SbyGq%V@&0H^+v?M?{*5U zy=iiG^Ii#!yQQI__tl>Dz1kI)X1C_`FXe_)=bm#d*|_ih{^cJZzWS76qEP(Kwddnc zkpmLSNj>42^K179^W0eC>cVUgeWFLJpthEmAwJh=)6N8+wT8!9XUsU)rqtBj+^l!Z z;>%~|=VzMcDQ_^33cYI0@HHu4InD98zucPYmliD_>UyCK+H_RV{IiC`m~yNwrEY zN(E93Mh1pvx`u|j21X%<##YA0Rt5&z28KZLI^&wRC>nC}Q!>*kacfu>BN7PIz~JfX K=d#Wzp$PzE&Ulgl literal 0 HcmV?d00001 diff --git a/resource/res/libs/ckeditor/plugins/image/icons/image.png b/resource/res/libs/ckeditor/plugins/image/icons/image.png new file mode 100644 index 0000000000000000000000000000000000000000..8ea97259df1e428333b1dad62e48f94faa666a0d GIT binary patch literal 498 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6-E$sR$z z3=CDO3=9p;3=BX21L>Cx45bDP46hOx7_4S6Fo@?*ia+WGRLhp+?e4|M(0zkpReK;%1Ag@`=X>@@dRb;faPyOW+kl=`Epd$~Nl7e8wMs5Z1yT$~28L$32IjhkmLZ15 uR>lTaCPvx@Mpgy}5);ZRP&DM`r(~v8;?|IP_WTi`1_n=8KbLh*2~7Z{n5wb> literal 0 HcmV?d00001 diff --git a/resource/res/libs/ckeditor/plugins/image/images/noimage.png b/resource/res/libs/ckeditor/plugins/image/images/noimage.png new file mode 100644 index 0000000000000000000000000000000000000000..74c6ee9262bbd0d379738c63f673dca93b34f08b GIT binary patch literal 1610 zcmV-Q2DSN#P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 zVoOIv0RI600RN!9r;`8x1z|} z6>qo$Lwtz}p)D$?NhyhX&n36q%7-zr7k~vN5ebP==s7!&7xS_+d-l`|dJ;}jc6Vm} z^Ze(T=WPc0nZ-8*u7fP`T>W(0z!|y4;%^7%4=f!&dW@>*f%pLeD1xA93oM}O#)=zB z)b?!nr^6k#?%v_A$B(x&kfq~Ck5U%Bl)q~0&v$^T@$zjScFbPkt6s@#uN(tpsQ~EZ zJwP!UmV$`bNkxOeMmT<;6E29br}(O86;=QkHGUq{ZH_UvLHuqA7(-|?#y%}Zr-m<@ zRoEWEtt5Vr%*!uc0W}1hn+851CqKZLnhZ1~FHGN8W z7iZW_`!w)@VC{_~GJ^5&5H@I+F?)+owiqIS5`fJl+7cotCTW`nJ|WnwMx6I)(gvpE zogiSZ@hL$c5ByM#wg_fj2Lj-3cKGL8;e6SKr2;8oC;}xJb)Wcy|`{2E|0OjG@W+(p8#u@`h z4&doO|5A@eWLahx?NW+DCmta4now1Ynx-?3XDDh6igNqobspTf8IfG(;Ku40{?OGm zw*dQlaN{PwoH@^MIJ7n&3Wdq?6DKi7UBdQ>J`D>Zf*Ql1-{;;JR{%JCdIf;Fm1R`n z;o1g9mBnk9#>j1*TV-K>o}wtI>)OrN%-t=&6=v)pv4ax#w_d9bJU=%#MsolA%fU0} zR+c--Rb?5;a$CHs{ElM58>&glCPhVDBDco8e=uNsjO5$IKTmFcZjQ1nA;Nni#A3(f zdna+L(cnmq7!4pvo8rzJ5Ch02EAjV+d zKJq-H>o+$T(ChW6eVFRN$Ar7&w^Ch_EtB`SPa+S0>4$GP@WDG{+|BXDNz;yPthMPEwWoj$|nB zqIlOSpU8_Hf+U6bwov*CM}E4}Np5y#hP)_Hl&UPb^XXS9$q!GWz&+>nAqThSZ_7_L zm<)8^Nxcq49vjG26-AymX-b5us>Vo~C{u($m*muze7fqv_$Zc~8LbI#eRPpmM>RSc zv2|{hsw~O#JiS?P__8dy{mCUeRZ;Nk*$d28l?_Wa_@TySjV}3s+~P$&^1@90S!@b@478QGv}WD;>Ej><0| z-Ls6MEJKp_wcI3pp66s)MwVrmD5v}9Bz)o|P2$Ghog_Q#`%L(blYUHo65e7OyqCEf ze#}YK*?>RtHNK;+gl|q=W4I~c13_?AwL9G-&EWW)>ML)9Nrc(TWD0m%aWG8a9VCiA z?k)gv_F>c>awO8gp5uwDnQ$O*gM*pdwonhcj48C!)im(I1{;;9Hv+hSorA=;q0)VW zu$TCVAmJPvAC#J1YHAGiVq39%TKEEBWNLf7iz~?p>>=Sh6m)U*se6hy4ME+0GTd33 z>Gi@bXS1qg@yR`NvmWn>ah39HcopTz&JfV;LgDPFuCM=Ho9FVsA^rnywRP1%iheNw z001R)MObuXVRU6WV{&C-bY%cCFflbPFgPtRH&ih*IyE>tH8v|SGCD9Y2Grjq0000b zbVXQnWMOn=I&E)cX=Zr
- Hỗ trợ nhập công thức bằng LaTeX +
+
+ Thêm ảnh + +
+
+ + +
+ Ảnh JPG,PNG nhỏ hơn 2mb +
+
- Nhập Câu Hỏi: + Nhập Câu Hỏi (Hỗ trợ nhập bằng LaTeX):
- Đáp Án A: + Đáp Án A:
- Đáp Án B: + Đáp Án B:
- Đáp Án C: + Đáp Án C:
- Đáp Án D: + Đáp Án D:

@@ -80,7 +97,7 @@ Hỗ trợ nhập công thức bằng LaTeX
Lưu Ý:
1, Không sửa file mẫu tránh gây lỗi khi nhập dữ liệu.

- 2, Hiện tại chưa hỗ trợ thêm nội dung hình ảnh, âm thanh,... vào câu hỏi. + 2, Nếu nội dung câu hỏi hoặc đáp án có sử dụng ảnh, vui lòng sử dụng chức năng thêm từng câu để đạt hiểu quả tốt nhất.
@@ -112,23 +129,23 @@ \ No newline at end of file diff --git a/resource/res/templates/admin/edit_question.php b/resource/res/templates/admin/edit_question.php index af40edd3..ee15402e 100644 --- a/resource/res/templates/admin/edit_question.php +++ b/resource/res/templates/admin/edit_question.php @@ -7,6 +7,24 @@
+
+
+ Thêm ảnh + +
+
+ + +
+ Ảnh JPG,PNG nhỏ hơn 2mb +
+
Nội Dung Câu Hỏi:
@@ -119,19 +137,19 @@ diff --git a/resource/res/templates/admin/head_left.php b/resource/res/templates/admin/head_left.php index a680cf42..317a72a0 100755 --- a/resource/res/templates/admin/head_left.php +++ b/resource/res/templates/admin/head_left.php @@ -31,7 +31,7 @@