Download: Tại đây
Thứ Năm, 27 tháng 8, 2026
Thứ Năm, 20 tháng 8, 2026
smooth scroll
Smooth Scroll
<button class="smooth-scroll">
Liên hệ với nhà cung cấp
</button>
// +---------------------+
// | Click div.smooth-scroll chạy xuống div.inquiry-msg-wrapper
// +---------------------+
<div class="inquiry-msg-wrapper">
Content suppliers
</div>
**** CSS
html {
scroll-behavior: smooth;
}
.btn-inquiry {
cursor: pointer;
transition: transform 0.2s ease, opacity 0.2s ease;
}
.btn-inquiry:hover {
opacity: 0.9;
transform: translateY(-2px);
/* Hiệu ứng nhích nhẹ nút khi di chuột */
}
**** JavaScript
$(document).ready(function() {
$('.smooth-scroll').on('click', function(e) {
e.preventDefault();
// Lấy vị trí top của phần tử mục tiêu
var targetOffset = $('.inquiry-msg-wrapper').offset().top;
// Nếu menu của bạn là menu cố định (fixed header), hãy trừ đi chiều cao menu tại đây (ví dụ: - 70)
var headerHeight = 0;
// Thực hiện hiệu ứng cuộn mượt trong 800ms
$('html, body').animate({
scrollTop: targetOffset - headerHeight
}, 800);
});
});
360° Virtual Tour
Để làm hình ảnh panorama 360 độ và tích hợp trình xem tương tác (360° Virtual Tour) giống trong ảnh lên website, bạn cần thực hiện theo 2 bước chính dưới đây.
Bước 1: Chụp và chuẩn bị ảnh 360 độ (Equirectangular)
Chụp bằng điện thoại/máy ảnh: Sử dụng ứng dụng chụp Panorama 360 (Google Street View, Polycam, Google Camera) hoặc chụp từ flycam/máy ảnh panorama chuyên dụng (Insta360, Ricoh Theta).
Định dạng ảnh: Xuất ảnh dưới dạng panorama toàn cảnh góc nhìn 360° × 180° (thường có tỉ lệ 2:1, định dạng
.jpghoặc.png).
Bước 2: Nhúng tính năng tương tác 360° vào Website
Bạn có thể chọn 1 trong 2 cách triển khai tùy thuộc vào nền tảng website của bạn:
Cách 1: Sử dụng thư viện JavaScript (Dành cho mã nguồn tự viết / HTML-JS) Dùng thư viện mã nguồn mở Pannellum (miễn phí, siêu nhẹ và phổ biến nhất).
Thêm thư viện vào tệp HTML của bạn:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pannellum@2.5.6/build/pannellum.css"/>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/pannellum@2.5.6/build/pannellum.js"></script>
Tạo thẻ
divchứa khung nhìn và thêm đoạn script cấu hình:
<div id="panorama" style="width: 100%; height: 400px;"></div>
<script>
pannellum.viewer('panorama', {
"type": "equirectangular",
"panorama": "duong-dan-den-anh-360.jpg",
"autoLoad": true,
"autoRotate": -2
});
</script>
Cách 2: Sử dụng Plugin hoặc Nền tảng có sẵn (Không cần viết code)
Website WordPress: Cài đặt các plugin như WP VR - 360 Panorama Tour hoặc iPanorama 360. Bạn chỉ cần tải ảnh 360 lên, plugin sẽ tự tạo trình xem tương tác và cung cấp Shortcode để chèn vào bất kỳ đâu trên trang.
Nền tảng nhúng đám mây: Tải ảnh lên các dịch vụ như Kuula.co hoặc Momento360, sau đó sao chép đoạn mã
<iframe>được tạo tự động và dán vào website.
Chủ Nhật, 9 tháng 8, 2026
Fancybox - Swiper - Zoomin
- Demo : ketsathalan
<!DOCTYPE html>
Thứ Hai, 3 tháng 8, 2026
Day - Date - Month - Year PHP
$thoigian = $value["thoigian"]; ("2026-07-31 14:41:39")
$timestamp = strtotime($thoigian);
$days = array(
'Sunday' => 'Chủ nhật',
'Monday' => 'Thứ Hai',
'Tuesday' => 'Thứ Ba',
'Wednesday' => 'Thứ Tư',
'Thursday' => 'Thứ Năm',
'Friday' => 'Thứ Sáu',
'Saturday' => 'Thứ Bảy'
);
$day = $days[date('l', $timestamp)];
<div class="pdnews-times">
<span><img src="/themes/'.$ThemeSel.'/images/icon-blog2.png"> '.$day.',</span>
<span class="news_home_content_short_time">
'.date('d/m/Y', $timestamp).'
</span>
</div>
Thứ Ba, 28 tháng 7, 2026
Chọn vị trí để IN (print) ra nội dung của div
** HTML
<div id="printArea">
<div class="no-print">Nội dung left</div>
<div class="content-right">Nội dung phải</div>
<!--Nội dung phải được in ra-->
</div>
** CSS
<style type="text/css">
@media print{
.certificate-container{
margin:0 !important;
padding:8mm !important;
height:auto !important;
min-height:auto !important;
}
.certificate-inner-border{
padding:6mm !important;
}
p,h1,h2,h3,h4,h5,h6{
margin-top:2px !important;
margin-bottom:2px !important;
}
.no-print{
display:none!important;
}
body *{
visibility:hidden;
}
#printArea,
#printArea *{
visibility:visible;
}
#printArea{
position:absolute;
left:0;
top:0;
width:100%;
}
}
</style>
** JS
<script type="text/javascript">
function printDiv(){
window.print();
}
</script>
Thứ Hai, 20 tháng 7, 2026
Nhập số tự chuyển thành "period / dot" và "comma"
** HTML
<input type='text' name='currency' id='currency' class='form-control'>
Nhập 25500 -> thành 25.500
** PHP
Code php lấy lại giá trị: 25500
$currency = str_replace('.', '', $_POST['currency']);
** JS
<script type="text/javascript">
$("#currency").on("input", function () {
// Chỉ giữ lại số
let value = $(this).val().replace(/\D/g, "");
// Format 25.500
if (value !== "") {
value = Number(value).toLocaleString("vi-VN");
}
$(this).val(value);
});
</script>
Thứ Ba, 14 tháng 7, 2026
explode - implode - uploads Images code php
##┌────────────────────────────────────────────────┐
## Implode
##└────────────────────────────────────────────────┘
function ConvertImplode($post){
if(empty($post) || !is_array($post)){
return '';
}
$post = array_map('trim', $post);
$post = array_filter($post);
return implode('**', $post);
}
$maymoc1 = ConvertImplode($_POST['maymoc1']);
$maymoc2 = ConvertImplode($_POST['maymoc2']);
$maymoc3 = ConvertImplode($_POST['maymoc3']);
$maymoc4 = ConvertImplode($_POST['maymoc4']);
##┌────────────────────────────────────────────────┐
## upload-image
##└────────────────────────────────────────────────┘
function uploadVerifiedImage($file, $path){
if (!isset($file['tmp_name']) || $file['error'] != 0) {
return '';
}
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
$allow = array('jpg','jpeg','png','gif','webp');
if (!in_array($ext, $allow)) {
return '';
}
$filename = time().'_'.mt_rand(1000,9999).'.'.$ext;
if (move_uploaded_file($file['tmp_name'], $path.$filename)) {
return $filename;
}
return '';
}
$path = "uploads/verified/";
if (!is_dir($path)) {
mkdir($path, 0777, true);
}
$gate_image = uploadVerifiedImage($_FILES['gate_image'], $path);
$production_image = uploadVerifiedImage($_FILES['production_image'], $path);
$machinery_image = uploadVerifiedImage($_FILES['machinery_image'], $path);
$certificate_file = uploadVerifiedImage($_FILES['certificate_file'], $path);
$video_file = uploadVerifiedImage($_FILES['video_file'], $path);
if($gate_image != ''){
$input_data['gate_image'] = $gate_image;
}
if($production_image != ''){
$input_data['production_image'] = $production_image;
}
if($machinery_image != ''){
$input_data['machinery_image'] = $machinery_image;
}
if($certificate_file != ''){
$input_data['certificate_file'] = $certificate_file;
}
if($video_file != ''){
$input_data['video_file'] = $video_file;
}
##┌────────────────────────────────────────────────┐
## Note: RESULT
##└────────────────────────────────────────────────┘
$input_data = array(
'bangke1' => $bangke1,
'bangke2' => $bangke2,
);
$xsql = "SELECT id FROM api_Vfactory WHERE shopid=".$shopid;
$rs = $db->sql_query($xsql);
if($db->sql_numrows($rs)){
// UPDATE
$sql = "UPDATE api_Vfactory SET "
.$db->sql_build_array('UPDATE', $input_data)
." WHERE shopid=".$shopid;
}else{
// INSERT
$input_data['shopid'] = $shopid;
$input_data['created_at'] = time();
$sql = "INSERT INTO api_Vfactory "
.$db->sql_build_array('INSERT', $input_data);
}
##┌────────────────────────────────────────────────┐
## Note: explode
##└────────────────────────────────────────────────┘
function parseData($value){
return !empty($value) ? explode('**', $value) : array();
}
$data = data__Vfactory($shopid);
extract($data[0]);
$bangke1 = parseData($bangke1);
$bangke2 = parseData($bangke2);
foreach ($bangke1 as $key => $value) {
<tr>
<td>'.$value.'</td>
<td>'.$bangke2[$key].'</td>
</tr>
}
Thứ Hai, 13 tháng 7, 2026
Thứ Tư, 8 tháng 7, 2026
Hiệu ứng Popup - Detail Product
Thứ Hai, 6 tháng 7, 2026
Hover Button css đẹp
## HTML
<div class="box-send-contact">
<button class="button dark">Gửi thông tin</button>
</div>
## CSS
.button.dark {
color: #fff;
border-color: #0d2445;
}
.box-send-contact button {
display: block;
margin: 2rem auto 3rem auto;
}
.button:before {
position: absolute;
content: '';
display: block;
left: -2px;
top: 0;
right: -2px;
bottom: 0;
transform: scale(1, 1);
transform-origin: left center;
z-index: -1;
background-color: #ffffff;
transition: transform 0.45s cubic-bezier(0.785, 0.135, 0.15, 0.86);
}
.button.dark:before {
background-color: #0d2445;
}
.button {
font-weight: 600;
position: relative;
display: inline-block;
padding: 1rem 2.8rem;
line-height: normal;
border: 1px solid #ffffff;
border-radius: 50px;
text-transform: uppercase;
font-size: 1.2rem;
text-align: center;
letter-spacing: 1px;
background-color: transparent;
transition: color 0.45s cubic-bezier(0.785, 0.135, 0.15, 0.86), border 0.45s cubic-bezier(0.785, 0.135, 0.15, 0.86);
z-index: 1;
color: #0d2445;
overflow: hidden;
}
.button:hover:before {
transform-origin: right center;
transform: scale(0, 1);
}
button:focus:not(:focus-visible) {
outline: 0;
}
button.dark:hover {
color: #0d2445;
}
Thứ Tư, 1 tháng 7, 2026
CSS clamp
height: clamp(280px, 23vw, 450px);
có nghĩa là chiều cao sẽ tự co giãn theo kích thước màn hình nhưng luôn nằm trong khoảng từ 280px đến 450px.
Cú pháp của clamp() là:
clamp(MIN, PREFERRED, MAX)
- 280px → Giá trị nhỏ nhất (không bao giờ thấp hơn).
- 23vw → Giá trị mong muốn (23% chiều rộng của cửa sổ trình duyệt).
- 450px → Giá trị lớn nhất (không bao giờ vượt quá).
Ví dụ
| Chiều rộng màn hình | 23vw | Kết quả |
|---|---|---|
| 320px | 73.6px | 280px (vì nhỏ hơn min) |
| 768px | 176.6px | 280px |
| 1200px | 276px | 280px |
| 1400px | 322px | 322px |
| 1600px | 368px | 368px |
| 2200px | 506px | 450px (vì vượt max) |
Khi nào dùng?
Ví dụ cho ảnh sản phẩm:
.dmsp-image {
height: clamp(280px, 23vw, 450px);
}
- Điện thoại → cao 280px.
- Tablet → khoảng 280–320px.
- Desktop → khoảng 320–450px.
- Màn hình siêu rộng → tối đa 450px, không bị quá cao.
Một số giá trị thường dùng
/* Luôn từ 250px đến 400px */
height: clamp(250px, 20vw, 400px);
/* Phù hợp card sản phẩm */
height: clamp(280px, 25vw, 420px);
/* Banner */
height: clamp(300px, 35vw, 700px);
clamp() rất hữu ích vì bạn không cần viết nhiều @media để thay đổi chiều cao theo từng kích thước màn hình.
Thứ Hai, 15 tháng 6, 2026
Click More - Less HTML+JS+CSS
Thứ Tư, 10 tháng 6, 2026
Icon trong select css đẹp
**** HTML
<div class="select-wrap">
<select name="customer_shipping_phuongxa" id="customer_shipping_phuongxa">
<option value="">Chọn Phường / Xã</option>
</select>
</div>
**** CSS
.appline .select-wrap{
position:relative;
width:100%;
}
.appline .select-wrap select{
-webkit-appearance:none;
-moz-appearance:none;
appearance:none;
background:#fff;
border:1px solid #d9d9d9;
box-sizing:border-box;
border-radius:16px !important;
height:40px !important;
width:100%;
padding:5px 45px 5px 20px !important;
transition:all .2s;
font-size:14px;
cursor:pointer;
}
.appline .select-wrap select::-ms-expand{
display:none;
}
.appline .select-wrap:after{
content:"";
position:absolute;
top:50%;
right:18px;
margin-top:-2px;
width:0;
height:0;
border-style:solid;
border-width:5px 4px 0 4px;
border-color:#888 transparent transparent transparent;
pointer-events:none;
}
Thứ Tư, 27 tháng 5, 2026
htmlspecialchars show hết lỗi dấu nháy - bird" s
$title_en="bird's nest products";
<input class="form-control" id="txt_name_en" name="txt_name_en" placeholder="Tên sản phẩm - Tiếng anh (*)" value="bird" s="" nest="" products'="" maxlength="80" required="">
và sử dụng hàm htmlspecialchars là OK.
htmlspecialchars($title_en, ENT_QUOTES)
Thứ Hai, 11 tháng 5, 2026
Thứ Năm, 16 tháng 4, 2026
lấy giá trị form - code php ajax
<form id="#send-supplier-fast">
<a id="tensanpham" href="'.$link.'" target="_blank" class="link">'.$title.'</a>
<input type="text" placeholder="Số lượng" name="soluong" oninput="this.value = this.value.replace(/[^0-9]/g, \'\')" required>
<textarea class="input-textarea" id="content" name="content" required></textarea>
<button type="submit" id="inquirySend"></button>
</form>
$(document).on('submit', '#send-supplier-fast', function (e) {
e.preventDefault();
const form = $(this);
const btn = $('#inquirySend');
let formData = new FormData();
// lấy data thường
formData.append('soluong', $('input[name=soluong]').val());
formData.append('donvitinh', $('select[name=donvitinh]').val());
formData.append('content', $('#content').val());
formData.append('senderMail', $('#senderMail').val());
formData.append('pid', $('input[name=pid]').val());
// formData.append('title', $('input[name=title]').val());
formData.append('title', $('#tensanpham').text().trim());
formData.append('userid', $('input[name=userid]').val());
// chỉ append file từ selectedFiles
selectedFiles.forEach(function(file) {
if (file && file.size > 0) {
formData.append('files[]', file);
}
});
btn.prop('disabled', true).text('Đang gửi...');
$.ajax({
url: '/send-supplier-product',
type: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: 'json',
success: function (res) {
// console.log(res);
if (res && res.status === 'success') {
showNotify('✅ Gửi yêu cầu thành công!');
form[0].reset();
window.location.href = '/?sendmail=' + res.mail_data.mail_id+ '&token=' + res.mail_data.token;
} else {
showNotify('❌ ' + (res.message || 'Có lỗi xảy ra'), 'error');
}
},
error: function () {
showNotify('❌ Lỗi server', 'error');
},
complete: function () {
btn.prop('disabled', false).text('Gửi yêu cầu');
}
});
});
Chỉ cho nhập số vào - code php
<input type="text" name="khoahoc" class="form-control" oninput="this.value = this.value.replace(/[^0-9]/g, \'\')" required>
Thứ Ba, 14 tháng 4, 2026
SEND EMAIL SMTP - KEIEIJUKU - send supplier
require_once 'classes/class.phpmailer.php';
require_once 'classes/class.smtp.php';
<!-- take include/data/mail_config.php
$SuppEmail = email_mail
$mailHost
$mailUsername
$mailPassword
$mailsetFrom
-->
===== MAIL GỬI CHO SUPPLIER =====
$mail = new PHPMailer();
$mail->CharSet = 'UTF-8';
$mail->isSMTP();
$mail->SMTPKeepAlive = true;
$mail->SMTPDebug = 0;
// $mail->Timeout = 10;
$mail->Host = $mailHost;
$mail->SMTPAuth = true;
$mail->Username = $mailUsername;
$mail->Password = $mailPassword;
$mail->SMTPSecure = 'ssl';
$mail->Port = 465;
$mail->setFrom($mailsetFrom, 'KEIEIJUKU KBN');
$mail->addAddress($supplier);
$mail->addReplyTo($customer);
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $body;
// ===== MAIL GỬI CHO KHÁCH (NGAY LẬP TỨC) =====
$mail2 = new PHPMailer();
$mail2->CharSet = 'UTF-8';
$mail2->isSMTP();
$mail2->SMTPKeepAlive = true;
$mail2->SMTPDebug = 0;
// $mail2->Timeout = 3;
$mail2->Host = $mailHost;
$mail2->SMTPAuth = true;
$mail2->Username = $mailUsername;
$mail2->Password = $mailPassword;
$mail2->SMTPSecure = 'ssl';
$mail2->Port = 465;
$mail2->setFrom($mailsetFrom, 'KEIEIJUKU KBN');
$mail2->addAddress($customer);
$mail2->isHTML(true);
$mail2->Subject = 'Xác nhận đã gửi yêu cầu từ website KEIEIJUKU KBN';
$mail2->Body = $body;
## Send-Mail
$start = microtime(true);
// gửi mail supplier trước
$ok1 = $mail->send();
$time1 = microtime(true);
// chỉ gửi mail khách nếu mail 1 OK
$ok2 = false;
if($ok1){
$ok2 = $mail2->send();
}
$time2 = microtime(true);
## ------------------------- ##
// tính thời gian
$time_supplier = round($time1 - $start, 3);
$time_customer = round($time2 - $time1, 3);
$total_time = round($time2 - $start, 3);
// ghi log
file_put_contents('debug_time.txt',
"Supplier: {$time_supplier}s\n" .
"Customer: {$time_customer}s\n" .
"Total: {$total_time}s\n\n",
FILE_APPEND
);
Thứ Sáu, 10 tháng 4, 2026
Accept - nhận đuôi file trong upload-file-input
<input type="file" name="pic_ncc" accept=".jpeg,.jpg,.png">
OR
<input type="file" name="pic_ncc" accept="image/*">
--> post - action - save
$image_nlh = null;
if (isset($_FILES['pic_ncc']) && $_FILES['pic_ncc']['error'] == 0) {
$ext = strtolower(pathinfo($_FILES['pic_ncc']['name'], PATHINFO_EXTENSION));
$allow_ext = array('jpg','png','jpeg');
if (in_array($ext, $allow_ext)) {
$new_name = 'picncc_'.time().'.'.$ext;
if (move_uploaded_file($_FILES['pic_ncc']['tmp_name'], $upload_dir . $new_name)) {
$image_nlh = $new_name;
}
}
}
/**************************/
<input type="file" id="images-file" accept=".jpeg,.jpg,.png" name="images_file[]" multiple>
--> post - action - save
if (isset($_FILES['images_file']) && !empty($_FILES['images_file']['name'][0])) {
for ($i = 0; $i < count($_FILES['images_file']['name']); $i++) {
if ($_FILES['images_file']['error'][$i] == 0) {
$name = $_FILES['images_file']['name'][$i];
$tmp = $_FILES['images_file']['tmp_name'][$i];
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
$allow_ext = array('jpg','png');
if (!in_array($ext, $allow_ext)) continue;
$new_name = 'img_' . time() . '_' . $i . '.' . $ext;
if (move_uploaded_file($tmp, $upload_banner . $new_name)) {
$images_saved[] = $new_name;
}
}
}
}
$images_db = !empty($images_saved) ? implode('**', $images_saved) : null;









