# PHP
[TOC]
## PHP 內建函數
### PHP str
1. strip_tags 清除html程式碼
```php=
<?php
$mystring="<a href='http://www.webtech.tw'>WebTech</a>";
echo strip_tags($mystring);
//輸出
WebTech
?>
```
2. rtrim 可以去除最右邊的
```php=
$date_search .= " data_date LIKE '".$item["data_date"]."' OR";
$date = rtrim($date_search, 'OR');
```
3. str_pad 補0輸出
```php=
$month = 3; // 例如,3月
$day = 5; // 例如,5日
// 补零并输出
$formattedMonth = str_pad($month, 2, "0", STR_PAD_LEFT);
$formattedDay = str_pad($day, 2, "0", STR_PAD_LEFT);
```
4. floor 小數捨去
```php=
<?php
floor(intval($buy_sell)/1000*100)/100,
```
5. round 四捨五入
```php=
<?php
round(intval($amount),2);
```
### PHP Array
1. array_push 陣列增加
```php=
<?php
$array = array();
array_push($array,"apple");
```
2. array_values 將索引重置
```php=
<?php
$data = array_values($data);
?>
```
3. array_search 尋找檔名在Array value的key
```php=
<?php
$tmp_img_sorts = explode(";",$request->tmp_img_sort);
foreach ($request->file('multiple_img') as $key=>$image) {
$originalName = $image->getClientOriginalName();
$filekey = array_search($originalName, $tmp_img_sorts);
$multiple_imgs[$filekey];
//這邊就是陣列去尋找原本檔名的在地幾個key後然後儲存
}
```
4. in_array 查看資料有沒有在Array的Value裡
```php=
<?php
$fruits = array("apple", "banana", "orange", "grape");
// 检查数组中是否存在某个值
$searchValue = "orange";
if (in_array($searchValue, $fruits)) {
echo "$searchValue 存在于数组中。";
} else {
echo "$searchValue 不存在于数组中。";
}
```
5. unset 刪除array指定key
```php=
<?php
unset($data[0]);
?>
```
6. array_slice array取出一段值
```php=
<?php
$a=array("red","green","blue","yellow","brown");
print_r(array_slice($a,1,2));
// 輸出
Array ( [0] => green [1] => blue )
?>
```
7. array_filter 陣列篩選,或是將空值過濾
```php=
<?php
$search_conditions = array_filter($search_conditions);
//也可以直接篩選
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// 過濾出偶數
$evenNumbers = array_filter($numbers, function($number) {
return $number % 2 === 0;
});
```
8. array_diff 找出兩組陣列不同差異
```php=
<?php
$array1 = [1, 2, 3, 4, 5];
$array2 = [3, 4, 5, 6, 7];
$onlyInArray1 = array_diff($array1, $array2);
$onlyInArray2 = array_diff($array2, $array1);
print_r("Values only in Array1: ");
print_r($onlyInArray1);
print_r("Values only in Array2: ");
print_r($onlyInArray2);
Values only in Array1: Array
(
[0] => 1
[1] => 2
)
Values only in Array2: Array
(
[0] => 6
[1] => 7
)
```
## PHP 作業系統判別
```php=
<?php
if (strtoupper(substr(PHP_OS, 0, 5)) === 'LINUX') {
//linux
}elseif(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'){
//windows
}
```
## PHP Json轉資料
```php=
<?php
// 轉成json資料
try {
} catch (\Exception $e) { // dd($e);
return json_encode([
'status' => 'fail',
'msg' => '查詢失敗',
'e' => $e
]);
}
// json轉回php array or object
json_decode();
```
## PHP查看版本
1. cmd指令
php -v
2. PHP裡輸出
```php=
<?php
phpinfo();
echo PHP_VERSION
```
## PHP 日期計算
```php=
<?php
給目前時間加一天、一小时
echo "今天:",date('Y-m-d H:i:s'),"<br>";
echo "明天:",date('Y-m-d H:i:s',strtotime('+1 day'));
同理,加一年、一個月、一小時、一分鐘…
echo "明天:",date('Y-m-d H:i:s',strtotime('+1 day'));
echo "明天:",date('Y-m-d H:i:s',strtotime('+1 hour'));
echo "明天:",date('Y-m-d H:i:s',strtotime('+1 minute'));
echo "明天:",date('Y-m-d H:i:s',strtotime('+1 mouth'));
//這裡+1 day可以修改參數1為任何想需要的數 day也可以改成year(年),month(月),hour(小時)minute(分),second(秒)如:
date('Y-m-d H:i:s',strtotime("+1 day +1 hour +1 minute");
//给指定時間加一天、一小時
echo date("Y-m-d",strtotime("+1 month",strtotime("2020-10-13")));
?>
```
### PHP 簡易日期區間判斷星期幾
```php=
<?php
$weekarray=array("日","一","二","三","四","五","六");
$start_date = "2023-07-01";
$start_strtotime = strtotime($start_date);
$end_date = "2023-08-04";
$end_strtotime = strtotime($end_date);
$days = round(($end_strtotime-$start_strtotime)/3600/24);
for ($i=0;$i<=$days;$i++){
$now_date = date('Y-m-d',strtotime("-$i day",$end_strtotime));
$week = $weekarray[date("w",strtotime($now_date))];
if($week == "六" || $week=="日"){
echo "$now_date 星期 $week 不開盤<br>";
}else{
echo "$now_date 星期 $week 開盤<br>";
}
}
?>
```
## PHP 計算執行程式多久
```php=
<?php
$start_time = microtime(true);
// 你的 PHP 程式碼
// 記錄結束時間
$end_time = microtime(true);
// 計算執行時間
$execution_time = ($end_time - $start_time);
// 顯示執行時間
echo "程式執行時間: {$execution_time} 秒";
?>
```
## PHP curl爬網頁
### PHP curl get
```php=
<?php
$PostData = "a=abc&b=def";
$curl = curl_init("https://test.com/test.php?$PostData");
//檢查 curl 有無作用
if (! $curl) {
die( "Cannot allocate a new PHP-CURL handle" );
}
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); //SSL
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//SSL
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//這個若是沒設 , curl_exec($curl) 會直接印出來
curl_setopt ($curl, CURLOPT_HEADER, 0); // 得到回傳的HTTP頁面.
$data = curl_exec($curl);
echo "&data=$data"; //輸出傳回值
curl_close($curl); //關閉連線
```
### PHP curl post
```php=
<?php
$PostData = "a=abc&b=def";
$curl = curl_init("https://test.com/test.php");
//檢查 curl 有無作用
if (! $curl) {
die( "Cannot allocate a new PHP-CURL handle" );
}
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); //SSL
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//SSL
//這邊是給Header 下面只是範例 可設可不設
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer {$channelAccessToken}", "Content-Type: application/json"));
curl_setopt($ch, CURLOPT_HEADER, 1);
//---------------------------
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//這個若是沒設 , curl_exec($curl) 會直接印出來
curl_setopt($curl, CURLOPT_POST,1);//設定CURLOPT_POST為1或true,表示用post傳送
curl_setopt($curl, CURLOPT_POSTFIELDS,$PostData)// PostData傳送的資料
curl_setopt ($curl, CURLOPT_HEADER, 0); // 得到回傳的HTTP頁面.
$data = curl_exec($curl);
echo "&data=$data"; //輸出傳回值
curl_close($curl); //關閉連線
```
### PHP file_get_contents
file_get_contents($url);
## PHP 瀏覽器清除緩存
```php=
<?php
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0", false);
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Pragma: no-cache");
```
## PHP 壓縮pdf ghostscript
1. 下載 ghostscript
```php=
<?php
$pdfPath = public_path('uploads/').$pdf_link;
$compressedPdfPath = public_path('uploads/').$compressed_pdf_link;
$ghostscriptPath = '"C:\\Program Files\\gs\\gs10.02.1\\bin\\gswin64c.exe"';
// $command = "$ghostscriptPath -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile={$compressedPdfPath} {$pdfPath}";
// $command = "gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile={$compressedPdfPath} {$pdfPath}";linux指令
$command = "$ghostscriptPath -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -r72 -sOutputFile={$compressedPdfPath} {$pdfPath}";
$output = shell_exec($command);
```
## PHP 正規式
### 抓取日期
```php=
<?php
$pattern = '/\b\d{4}\/\d{2}\/\d{2}\b/';
preg_match($pattern, $value, $matches);
if (!empty($matches)) {
$data_date = str_replace("/","-",$matches[0]);
break;
}
```
### 去除空白
```php=
<?php
$value = preg_replace('/\s+/', "", $value);
```
### 頭尾去除空白(特殊無法用其他" "取代掉的 )
```php=
<?php
$value = preg_replace('/^\p{Z}+|\p{Z}+$/u', '', $value);
?>
```
### 將括號內容移除
```php=
<?php
$string = "這是一個(含有括號的)字串。";
$pattern = '/\([^)]*\)/'; // 正規表達式,匹配括號及其內容
$cleanedString = preg_replace($pattern, '', $string);
echo $cleanedString;
```
### 基本匹配:檢查字串中包含是否某個特定的字詞或字符
```php=
<?php
$pattern = '/apple/';
$text = 'I like apples.';
if (preg_match($pattern, $text)) {
echo "Match found!";
} else {
echo "No match found.";
}
?>
```
### 案例不敏感匹配:執行不區分大小寫的模式匹配
```php=
<?php
$pattern = '/apple/i';
$text = 'I like Apples.';
if (preg_match($pattern, $text)) {
echo "Match found!";
} else {
echo "No match found.";
}
?>
```
### 提取匹配:從字符串中提取匹配的部分
```php=
<?php
$pattern = '/(\d{2})-(\d{2})-(\d{4})/';
$text = 'Date of birth: 05-20-1990';
if (preg_match($pattern, $text, $matches)) {
echo "Day: " . $matches[1] . ", Month: " . $matches[2] . ", Year: " . $matches[3];
} else {
echo "No match found.";
}
?>
```
### 替換:將匹配的部分替換為新的字符串 preg_replace
```php=
<?php
$pattern = '/apple/';
$text = 'I like apples.';
$replacement = 'oranges';
$new_text = preg_replace($pattern, $replacement, $text);
echo $new_text; // Output: I like oranges.
?>
```
### 字符範圍:匹配特定範圍的字符
```php=
<?php
$pattern = '/[0-9]/'; // 匹配任何數字字符
$text = 'The code is 12345.';
if (preg_match($pattern, $text)) {
echo "Match found!";
} else {
echo "No match found.";
}
?>
```
### 字串裡提取英文
```php=
<?php
$text = "Hello123World456";
$pattern = '/[A-Za-z]+/';
preg_match_all($pattern, $text, $matches);
$english_words = $matches[0];
print_r($english_words);
Array
(
[0] => Hello
[1] => World
)
?>
```
### 字串裡提取數字
```php=
<?php
$text = "Hello123World456";
$pattern = '/\d+/';
preg_match_all($pattern, $text, $matches);
$numbers = $matches[0];
print_r($numbers);
Array
(
[0] => 123
[1] => 456
)
?>
```
### 獲得輸出richMenuId
```php=
<?php
$pattern = '/"richMenuId":"(.*?)"/';
preg_match($pattern, $output, $matches);
if (isset($matches[1])) {
$richMenuId = $matches[1];
echo "成功獲得 Rich Menu ID:$richMenuId<br>";
} else {
echo "無法提取 Rich Menu ID。<br>";
}
?>
```
# PHP Laravel
(https://hackmd.io/NWZ9E6EQQ4yUVBFX-Je8hQ)
# .htaccess
## 檔案數量限制及size
```php=
php_value upload_max_filesize 50M
php_value post_max_size 52M
php_value max_file_uploads 100
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} ^public/(.+)$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ public/%1 [NC,R,L]
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
```
# phpmyadmin修改sql
https://hackmd.io/kORpcygzQuKxr0AqMUu-_g
# Mysql
## 大量資料減少查詢時間
原本
```sql=
select *
from `news`
where (`enabled`=1 or web_data_active=1) and
length(`subject`)>10 and
`newsid` != '20231221A001001' and
(`end_datetime` is null or `end_datetime` > '2024-01-09 10:39:00') and
`start_datetime` < '2023-12-21 13:49:01' and
`start_datetime` < '2024-01-09 10:39:00' and
`news`.`deleted_at` is null
order by start_datetime desc,newsid asc
LIMIT 0,1;
```
修改後
```sql=
SELECT `news`.*
FROM `news`
JOIN (
SELECT `newsid`
FROM `news`
WHERE (`enabled` = 1 OR `web_data_active` = 1) AND
LENGTH(`subject`) > 10 AND
`newsid` != '20231221A001001' AND
(`end_datetime` IS NULL OR `end_datetime` > '2024-01-09 10:39:00') AND
`start_datetime` < '2023-12-21 13:49:01' AND
`start_datetime` < '2024-01-09 10:39:00' AND
`news`.`deleted_at` IS NULL
ORDER BY `start_datetime` DESC, `newsid` ASC LIMIT 0, 1 ) AS subquery
ON `news`.`newsid` = subquery.`newsid`;
```
ORM方式
第一種
```php=
<?php
$result = News::join(
DB::raw('(SELECT newsid
FROM news
WHERE (enabled = 1 OR web_data_active = 1)
AND LENGTH(subject) > 10
AND newsid != "20231221A001001"
AND (end_datetime IS NULL OR end_datetime > "2024-01-09 10:39:00")
AND start_datetime < "2023-12-21 13:49:01"
AND start_datetime < "2024-01-09 10:39:00"
AND deleted_at IS NULL
ORDER BY start_datetime DESC, newsid ASC
LIMIT 0, 1) as subquery'),
function ($join) {
$join->on('news.newsid', '=', 'subquery.newsid');
}
)
->select('news.*')
->get();
```
第二種
```php=
<?php
$subquery = News::select('newsid')
->where(function ($query) {
$query->where('enabled', 1)
->orWhere('web_data_active', 1);
})
->where('subject', '>', 10)
->where('newsid', '!=', '20231221A001001')
->where(function ($query) {
$query->whereNull('end_datetime')
->orWhere('end_datetime', '>', '2024-01-09 10:39:00');
})
->where('start_datetime', '<', '2023-12-21 13:49:01')
->where('start_datetime', '<', '2024-01-09 10:39:00')
->whereNull('deleted_at')
->orderBy('start_datetime', 'desc')
->orderBy('newsid', 'asc')
->limit(1);
$result = News::whereIn('newsid', $subquery)
->get();
```
原理join的是原本where得資料但只搜尋newsid可以減少查詢時間後再去on id去等於抓取那比資料
## 大量減少查詢時間2(先抓id在where)
### 原生語法
```sql=
select * from `news` where `newsid` = (
select `newsid` from `news`
where (`enabled` = ? or `web_data_active` = ?) and
length(`subject`)>10 and
`newsid` != ? and
(`end_datetime` is null or `end_datetime` > ?) and
`start_datetime` < ? and `start_datetime` >= ? and
`start_datetime` < ? and `deleted_at` is null
order by `start_datetime` desc
limit 1
)
and `news`.`deleted_at` is null
```
### ORM
```php=
<?php
$news = News::where('newsid', function ($query) use($newsid,$start_datetime,$orm) {
$query->select('newsid')
->from('news')
->where(function ($subquery) {
$subquery->where('enabled', 1)
->orWhere('web_data_active', 1);
})
->whereRaw('length(`subject`)>10')
->where('newsid', '!=', $newsid)
->where(function ($subquery) {
$subquery->whereNull('end_datetime')
->orWhere('end_datetime', '>', date("Y-m-d H:i:00"));
})
->where('start_datetime', '<', date("Y-m-d H:i:00"))
->where('start_datetime', '>=', date("Y-m-d",strtotime("-2 day", strtotime($start_datetime))))
->where('start_datetime', '<', $start_datetime)
->whereNull('deleted_at')
->orderByDesc('start_datetime')
->first();
});
```
### 在php用if的orm
```php=
<?php
$conditions["whereraw"][] = "(`enabled`=1 or web_data_active=1) and length(`subject`)>10";
$conditions["where"][] = array("start_datetime","<=",date("Y-m-d H:i:00"));
$conditions["orwhere"][] = array(
array("end_datetime","=",null),
array("end_datetime",">",date("Y-m-d H:i:00")),
);
$conditions["wherehas"]["tags"] = array("id","=",$tag);
$news = News::select('news.*')
->whereHas('tags', function ($query) use ($tag) {
$query->where('id', $tag);
})
->joinSub(function ($query) use ($conditions) {
$query->select('newsid')
->from('news');
foreach($conditions as $sql_where => $sql_data){
switch ($sql_where){
case "where":
foreach ($sql_data as $item) {
$query->where($item[0],$item[1],$item[2]);
}
break;
case "whereraw":
foreach ($sql_data as $raw) {
$query->whereRaw($raw);
}
break;
case "orwhere":
foreach ($sql_data as $item) {
$query->where(function ($query)use($item) {
foreach($item as $sql_key=>$array){
if($sql_key==0){
$query->where($array[0],$array[1],$array[2]);
}else{
$query->orwhere($array[0],$array[1],$array[2]);
}
}
});
}
break;
}
}
$query->orderByDesc('start_datetime');
$query->limit(12);
}, 'subquery', function ($join) {
$join->on('news.newsid', '=', 'subquery.newsid');
});
```
## 搜尋重覆資料且多筆資料只留id最小資料其他列出來(可用於刪除)
```sql=
SELECT a.*
FROM stock_daily_price a
JOIN (
SELECT
stock_id,
stock_name,
closing_price,
stock_price_change,
opening_price,
highest_price,
lowest_price,
MIN(id) AS min_id
FROM stock_daily_price
WHERE updated_at LIKE '2023-12-01%'
GROUP BY
stock_id,
stock_name,
closing_price,
stock_price_change,
opening_price,
highest_price,
lowest_price
HAVING COUNT(*) >= 2
) b ON
a.stock_id = b.stock_id
AND a.stock_name = b.stock_name
AND a.closing_price = b.closing_price
AND a.stock_price_change = b.stock_price_change
AND a.opening_price = b.opening_price
AND a.highest_price = b.highest_price
AND a.lowest_price = b.lowest_price
AND a.id != b.min_id
WHERE a.updated_at LIKE '2023-12-01%';
```
## 搜尋重覆資料兩個相同條件
```sql=
SELECT *
FROM daily_tvstock
WHERE updated_at LIKE '2023-12-01%'
GROUP BY stock_id,hit_count -- 列出所有你想要檢查重複的欄位
HAVING COUNT(*) >= 2;
```
## 刪除相同重覆資料兩筆兩個相同條件且留id小的
```sql=
DELETE t1
FROM daily_tvstock t1
JOIN daily_tvstock t2
ON t1.stock_id = t2.stock_id
AND t1.hit_count = t2.hit_count
AND t1.id > t2.id
WHERE t1.updated_at LIKE '2023-12-01%'
AND t2.updated_at LIKE '2023-12-01%';
```
## CONCAT_WS 用來將多個字串值連接起來,並使用指定的分隔符進行分隔
```sql=
where用
concat_ws(\'\', name,city, sub_area, address) like "%'.$search_txt.'%" '
selesect用
CONCAT_WS(separator, string1, string2, string3, ...)
1. separator:分隔符,用來將不同的字串值分隔開來。
2. string1, string2, string3, ...:要連接的字串值。
SELECT CONCAT_WS(', ', first_name, last_name) AS full_name
FROM users;
+--------------+
| full_name |
+--------------+
| John, Doe |
| Jane, Smith |
| Alice, Brown |
+--------------+
```
### in,exists 适用于左边大表,右边小表。
https://www.zhihu.com/question/388019803/answer/3167172828
假如有order和user兩張表,其中order表有10000條數據,而user表有100條數據。
這時如果想查一下,所有有效的用戶下過的訂單清單。 可以使用in關鍵字實作:
select * from order
where user_id in (select id from user where status=1)
也可以使用exists關鍵字實作:
select * from order
where exists (select 1 from user where order.user_id = user.id and status=1)
前面提到的這種業務場景,使用in關鍵字去實現業務需求,更加適合。
為什麼呢?
因為如果sql語句中包含了in關鍵字,則它會優先執行in裡面的子查詢語句,
然後再執行in外面的語句。 如果in裡面的資料量很少,作為條件查詢速度更快。
而如果sql語句中包含了exists關鍵字,它優先執行exists左邊的語句(即主查詢語句)。
然後把它當作條件,去跟右邊的語句配對。 如果符合上,則可以查詢出資料。
如果匹配不上,資料就被過濾掉了。
這個需求中,order表有10000條數據,而user表有100個數據。
order表是大表,user表是小表。 如果order表在左邊,用in關鍵字表現較好。
exists 適用於左邊小表,右邊大表。
不管是用in,還是exists關鍵字,其核心想法都是用小表驅動大表。
# javascript
## <script defer src="{{ asset(mix('js/page/search_model.js'), true) }}" ></script>>
script defer:
這是一個 HTML <script> 標籤的屬性,defer 屬性的作用是告訴瀏覽器在解析完 HTML 文件後才執行這個 JavaScript 檔案,這樣可以確保 DOM(文件物件模型)已經建立完畢。
src="{{ asset(mix('js/page/search_model.js'), true) }}":
這部分是試圖動態生成 JavaScript 檔案的 URL。在 Laravel 框架中,asset 函式用於生成資源的 URL,而 mix 函式則通常用於為資源加上版本號(cache busting),以防止瀏覽器緩存舊版本。最後的 true 參數表示生成絕對 URL。
## history.replaceState 修改歷史標籤,但不會將瀏覽器重定向到新的URL
```javascript=
history.replaceState(stateObj, title, url);
```
這個方法用於修改歷史標籤,但不會將瀏覽器重定向到新的URL。
stateObj: 表示一個JavaScript對象,與新的狀態有關,可以是null。
title: 用於新的狀態的標題,現代瀏覽器通常忽略這個參數,因此可以傳入空字符串。
url: 新的URL。
在你的代碼中,你使用了 history.replaceState 來替換當前的URL,並且將URL設置為 {{url("/program-post/img")}} + "/" + extractedString。這樣的代碼片段看起來像是在修改URL,使其包含 "/program-post/img" 和 extractedString。
請確保 {{url("/program-post/img")}} 和 extractedString 的值都是正確的並且不包含空格或非法字符,以確保生成的URL是有效的。
## 擷取字串
```javascript=
var img_url_now = this.slides[index].dataset.url;
// 從後面尋找第一個斜線的索引
var lastIndex = img_url_now.lastIndexOf("/");
var dotIndex = img_url_now.lastIndexOf(".");
// 擷取字串
var extractedString = img_url_now.substring(lastIndex+1,dotIndex);
```
# jQuery
## 增加屬性attr
$('#search_choose_form').attr('action',search_route);
## 移除屬性removeAttr
$('#search_input').removeAttr('name');
## 增加css
$('#search_input').css('display','none');
## 從某個class底下去尋找index
```javascript=
$('.schedule').eq($('#week').val()-1).find('tbody tr').eq(index).addClass('highlight-row');
//查看name在第幾個index
$(document).on("change", 'input[name^="images"]', function (e) {
var inputIndex = $('input[name^="images"]').index(this);
var width = $("#rich_menu_select_block").find(".div_block:eq("+inputIndex+")").css('width');
var height = $("#rich_menu_select_block").find(".div_block:eq("+inputIndex+")").css('height')
});
```
## jQuery Laravel url 用在juqery
```javascript=
$("#submit").attr("data-refresh-url","{!! url('/liveendyoutubeschedule?week="+week+"') !!}");
```
## jQuery 程式觸發change事件
```javascript=
$('#data_key').val(key).trigger('change');
//觸發change事件
```
## jQuery name onchange
```javascript=
$('select[name^="rich_menu_type"]').change(function() {
var selectedIndex = $('select[name^="rich_menu_type"]').index(this);
console.log("Index: " + selectedIndex);
});
```
## jQuery id onchange
```javascript=
$('#data_key').on('change', function() {
$(this).find(":selected").val();
$.each( p_data["data"],function(key,array){
$('#list_id').append($('<option>', {value:array["id"], text:array["title"]}));
});
});
```
## jQuery
最後一行為清除url的get資料
```javascript=
localStorage.removeItem('countdownSeconds');
localStorage.setItem('countdownSeconds', 30);
history.replaceState({}, document.title, window.location.pathname);
```
## jQuery input file 修改檔案
```htmlembedded=
<input type="file" class="form-control" id="multiple_img" name="multiple_img[]" multiple>
<script>
$(document).ready(function() {
$('#multiple_img').change(function() {
var files = $('#multiple_img')[0].files;
var dataTransfer = new DataTransfer();
if (files.length > 0) {
var newFiles = [];
for (var i = 0; i < files.length; i++) {
if (i !== 0) {
dataTransfer.items.add(files[i]);
}
}
}
// $('#multiple_img_copy')[0].files = newFiles;
$('#multiple_img')[0].files = dataTransfer.files;
});
});
</script>
```
## jQuery input file兩邊同時傳
```javascript=
$('.container').on('click', '.select-save-block-image-trigger', function() {
var triggerType = $(this).data('trigger-type');
// 執行相關的邏輯,基於 triggerType(A 或 B)
if (triggerType === 'A') {
var fileInputs = $("input[name='images_a[]']");
var fileTemps = $("input[name='images_temp_a[]']");
} else if (triggerType === 'B') {
var fileInputs = $("input[name='images_b[]']");
var fileTemps = $("input[name='images_temp_b[]']")
}
console.log(fileInputs);
fileInputs.each(function(index, element) {
var fileValue = $(this).val();
if (fileValue) {
var fileInput = element; // 获取原生 DOM 元素
var file = fileInput.files[index]; // 获取文件
var fileList = new DataTransfer();
fileList.items.add(file);
// 设置到相应的目标文件输入元素(例如,fileTemps)
fileTemps.eq(index).prop('files', fileList.files);
}
});
});
```
## jQuery file預覽
```html=
<input type="file" class="form-control" id="multiple_img" name="multiple_img[]" multiple>
<table class="table table-bordered" id="imagePreviewContainer">
<tbody>
<tbody>
</table>
```
```javascript=
<script>
$(document).ready(function() {
$('#multiple_img').change(function() {
readURL(this);
});
});
function readURL(input) {
$('#imagePreviewContainer tbody').empty();
var table = `
<tr class="active">
<th style="width:10px;">排序</th>
<th style="width:40px;">圖片</th>
</tr>`;
if (input.files && input.files.length > 0) {
for (let i = 0; i < input.files.length; i++) {
const reader = new FileReader();
// reader.readAsDataURL(input.files[i]);
const objectURL = URL.createObjectURL(input.files[i]);
var sort = i+1;
table += `
<tr id="item-${i}">
<td>${sort}</td>
<td>
<div><img src = "${objectURL}" style="width:200px;"></img></div>
</td>
</tr>`;
}
$('#imagePreviewContainer tbody').append(table);
}
}
</script>
```
## jQuery input <0正規式
```javascript=
$("#skip_time").on("input", function() {
// 获取输入框的值
var inputValue = $(this).val();
// 使用正则表达式检查是否为负数
var regex = /^-\d+(\.\d+)?$/;
if (regex.test(inputValue)) {
// 如果是负数,将其改成0
$(this).val("0");
}
});
```
## jQuery checkbox 多個name使用
```javascript=
//if簡寫
id ? id = true : id = false;
//日期差
var date = new Date(checkin_date).getTime()-new Date(checkout_date).getTime();
var days = Math.abs(date)/(24*3600*1000);
// js 計算月日
var start_date = new Date(checkin_date).getTime()-new Date(order_date).getTime();
var start_day = Math.abs(start_date)/(24*3600*1000);
//指定日期加幾天
date = new Date (new Date(checkin_date).setDate(new Date(checkin_date).getDate() + i));
getYearMonthDay(date,'/');
//將年月日放進來進行字串整理
function getYearMonthDay(date,symbol){
year = date.getFullYear()
month = date.getMonth()+1;
day = date.getDate()
if (day < 10) {
day = '0' + day;
}
if (month < 10) {
month = '0' + month;
}
r
//判斷有沒有進行勾選
$('#' + id).is(":checked")
jQuery <1.9
$('#inputId').attr('readonly', true);
jQuery 1.9+
$('#inputId').prop('readonly', true);
存資料
$('#checkin_district').val( 123 );
// 多個id或name用相同的event事件用法
$(document).on('input', '#order_name, #order_phone_number, #order_email', function() {
});
//取得data-key的資料 多個name使用
<select name="time_of_room" data-key="{{ $key }}" style="width: 180px">
$(document).on('change', 'select[name="time_of_room"]', function(key,value) {
key = $(this).attr("data-key");
$('#time_of_room_'+key).prop('checked', true);
});
//name checked
$('input[name="time_of_meal_'+key+'"]')[key].checked = true
//選下拉選單第一個
$('select[name="time_of_restaurant"]').val($('select[name="time_of_restaurant"] option:first').val());
```
## jQuery 連點submit問題
```php=
<input type="hidden" class="form-control" id="lastClickTime" name="lastClickTime" value="0">
<button type="submit" class="btn btn-info pull-right _submit_" data-function="form_check();" data-form-id="form" data-refresh-url="{{ url('/analyster/video') }}">提交</button>
<script type="text/javascript">
function form_check() {
var lastClickTime = $("#lastClickTime").val();
var currentTime = new Date().getTime();
var clickInterval = 2000; // 1秒
$("#lastClickTime").val(new Date().getTime());
if (currentTime - lastClickTime > clickInterval) {
if (!analyster_yt_different()) {
return false;
}
return true;
}
return false;
}
</script>
```
## jQuery 按鈕開關
```php=
<style>
.tr-odd{background-color: #ccc;}
.tr-hover{background-color: #0fa;}
.btn-switch {
color: whitesmoke;
width: 6rem;
height: 2.5rem;
margin:.1rem;
padding: .1rem;
background: #555;
border: 2px solid #ccc;
border-radius: 2rem;
transition: .3s;
box-shadow: inset 1px 1px 5px #333, .1rem .2rem .5rem #999;
}
.btn-switch-ball {
color: whitesmoke;
width: 2rem;
height: 2rem;
background: #777;
border: inset .1rem rgba(153, 153, 153, 0.43);
border-radius: 50%;
box-sizing: border-box;
cursor: pointer;
transition: .3s;
box-shadow: 1px 1px 5px #000;
}
.on .btn-switch {
background: #777;
}
.on .btn-switch-ball {
background: #999;
/* outset .1rem rgba(153, 153, 153, 0.43) */
box-shadow: -1px 1px 5px #000;
margin-left: calc(100% - 2rem);
}
</style>
@foreach ($pager as $item)
@if($item['enable']==1)
<button class="btn-switch">
<div class="btn-switch-ball" data-id="{{ $item['id'] }}">開</div>
</button>
@else
<button class="btn-switch on">
<div class="btn-switch-ball" data-id="{{ $item['id'] }}">關</div>
</button>
@endif
@endforeach
<script>
$(document).ready(function () {
$('.btn-switch-ball').on('click', function () {
var $this = $(this);
var enable = 0;
var message = "";
var dataId = $this.data('id');
if ($this.parent().hasClass('on')) {
message = "確定要進行啟用嗎?";
enable = 1;
} else {
message = "確定要進行關閉嗎?";
enable = 0;
}
if(confirm(message)){
$this.parent().toggleClass('on');
if(enable==1){
$this.html("開");
}else{
$this.html("關");
}
$.ajax({
data: {
id: dataId,
enable: enable,
},
type: 'POST',
dataType: 'JSON',
url: "{{url('/analyster/analyster_enable')}}",
success: function (response) {
console.log(response);
alert(response.msg);
},error: function(response) {
alert(response.msg);
}
});
}
});
});
$('tr').hover(function() {
$(this).addClass('tr-hover');
}, function() {
$(this).removeClass('tr-hover');
});
});
```
ajax打的資料
```php=
<?php
public function analyster_enable(Request $request){
$AnalystVideo = AnalystVideo::find($request->id);
$AnalystVideoGcp = AnalystVideo::on('azure_mysql')->find($request->id);
switch ($request->enable){
case 0:
$AnalystVideo->enable = 0;
$AnalystVideoGcp->enable = 0;
break;
case 1:
$AnalystVideo->enable = 1;
$AnalystVideoGcp->enable = 1;
break;
default:
$AnalystVideo->enable = 0;
$AnalystVideoGcp->enable = 0;
}
if(!$AnalystVideo->save()){
return $this->retJson(503, '啟用修改失敗!');
}
$AnalystVideoGcp->save();
return $this->retJson(200, '操作成功!');
}
```
## jQuery 抓youtube 的影片長度
```html=
//這一塊用來隱藏iframe youtube的資料,因要抓影片長度資料就會顯示
<div id="player_div" hidden>
// player會進行刪除後再新增,若不這樣會影響抓資料的問題
<div id="player"></div>
</div>
<input type="text" class="form-control" name="video_id" id="video_id" value="@if(isset($item)){{ $item->video_id }}@endif">
<input type="hidden" class="form-control" id="video_duration" name="video_duration" value="0">
<button type="button" id="form_button" class="btn btn-info pull-right">提交</button>
<button type="submit" id="submit" style="display: none;">
```javascript=
<script src="https://www.youtube.com/iframe_api"></script>
$('#form_button').on('click', function() {
event.preventDefault(); // 阻止默认的提交行为
var videoId = extractYouTubeVideoId($('#video_id').val());
onYouTubeIframeAPIReady(videoId).then(function() {
onPlayerReady(function(videoDuration) {
// 手动触发表单提交
$("#submit").click();
});
});
});
$(document).ready(function() {
$('#youtube').on('input', function() {
$("#player_div").hide();
$("#player_div").html("");
$("#video_duration").val(0);
$("#player_div").append(`<div id="player"></div>`);
var videoId = extractYouTubeVideoId($('#youtube').val());
if(videoId){
onYouTubeIframeAPIReady(videoId);
setTimeout(function() {
console.log($("#video_duration").val());
if ($("#video_duration").val() > 0) {
console.log('影片有秒數,不進行移除');
} else {
console.log('影片沒有秒數,移除 iframe');
$("#player_div").show();
$("#player_div").html("");
$("#player_div").append(`<font color="red">影片不存在或未公開!</font>`);
}
}, 1000);
}
});
function onYouTubeIframeAPIReady(video_id) {
return new Promise(function(resolve, reject) {
player = new YT.Player('player', {
height: '360',
width: '640',
videoId: video_id,
events: {
'onReady': function() {
resolve();
onPlayerReady();
},
'onError': function(errEvent) {
console.log(errEvent);
var errCode = errEvent.data;
if(errCode == 100) {
alert('Video Not Found');
}
}
}
});
});
}
function onPlayerReady() {
try {
$("#player_div").show();
console.log(player);
var videoDuration = player.getDuration(); // 获取视频长度,单位为秒
var videoTitle = player.getVideoData().title;
console.log("视频標題:", videoTitle, "秒");
console.log("视频長度:", videoDuration, "秒");
$("#video_duration").val(videoDuration);
player.pauseVideo(); // 暂停播放
player.mute(); // 静音
player.setVolume(0); // 设置音量为 0
} catch (error) {
// 在這裡加入錯誤處理的邏輯
console.error("發生錯誤:", error);
// 在這裡加入其他處理錯誤的邏輯
$("#player_div").html(""); // 清空 player_div
}
}
function extractYouTubeVideoId(link) {
var videoId = '';
var regex = /(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?.*v=([a-zA-Z0-9_-]{11})/;
var match = link.match(regex);
if (match && match[1]) {
videoId = match[1];
return videoId;
} else {
return link;
}
}
});
```
## jQuery sortable 表格行拖曳
### 第一種圖片上傳或修改時調整順序
subject_item.blade.php
```php=
<?php
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
</head>
<input type="file" class="form-control" id="multiple_img" name="multiple_img[]" multiple>
<input type="hidden" class="form-control" id="tmp_img_sort" name="tmp_img_sort" value="@if(isset($item)){{ $item->multiple_img }}@endif" >
<table class="table table-bordered" id="imagePreviewContainer">
<p class="table-remark" @if(!isset($item))style="display: none;"@endif><font color="red">*拖曳圖片即可進行排序,拖曳排序完成後需按「提交」按鈕,才會進行儲存這次的排序內容。</font></p>
<tbody>
@if(isset($item->multiple_imgs))
<tr class="active">
<th style="width:50px;">排序</th>
<th>圖片</th>
</tr>
@foreach ($item->multiple_imgs as $key=>$url)
<tr id="item-{{$key}}" class="draggable">
<td>{{ $key+1 }}</td>
<td>
<div><a target="_blank" href="{{ asset("storage/{$url}?".date('YmdHis')) }}"><img src = "{{ asset("storage/{$url}?".date('YmdHis')) }}" style="width:200px;"></img></a></div>
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
```
js得部分
```javascirpt=
$(document).ready(function() {
$('#multiple_img').change(function() {
readURL(this);
var files = $('#multiple_img')[0].files;
$("#tmp_img_sort").val("");
if (files.length > 0) {
var array = [];
$.each(files, function(index, file) {
var fileName = file.name;
array.push(`${fileName}`);
});
$('#tmp_img_sort').val(array.join(';'));
}else{
$(".multiple-img-remark").show();
}
});
$( "tbody" ).sortable({
items: 'tr.draggable',
axis: 'y',
update: function (event, ui) {
var serializedString = $(this).sortable('serialize');
var idArray = serializedString.split('&').map(function(pair) {
return pair.split('=')[1];
});
// 使用分號拆分成每個鍵值對
var tmp_img_sort = $('#tmp_img_sort').val().split(';');
// 使用 map 方法創建包含索引和值的新陣列
var indexedArray = $.map(tmp_img_sort, function(value, index) {
return { index: idArray.indexOf(index.toString()), value: value };
});
// 使用 sort 方法,根據每個元素的索引進行排序
indexedArray.sort(function(a, b) {
return a.index - b.index;
});
// 提取排序後的值
var sortedValues = $.map(indexedArray, function(item) {
return item.value;
});
$("#tmp_img_sort").val(sortedValues.join(';'));
updateFirstColumn();
}
});
$( "#sortable" ).disableSelection();
)};
// 更新表格的第一列数据
function updateFirstColumn() {
// 获取所有行的第一列
var firstColumnCells = $("tbody tr td:first-child");
// 遍历排序后的索引,更新第一列的文本
$("tbody tr").each(function (index, row) {
var newIndex = $(row).index();
var newText = newIndex+1; // 你可以根据需要修改这里的逻辑
$(firstColumnCells[index]).text(newText);
if(index>0){
var newId = "item-" + (index-1);
$(row).attr("id", newId);
}
});
}
$( "#sortable" ).disableSelection();
function readURL(input) {
$(".table-remark").hide();
$('#imagePreviewContainer tbody').empty();
var table = `
<tr class="active">
<th style="width:50px;">排序</th>
<th>圖片</th>
</tr>`;
if (input.files && input.files.length > 0) {
$(".table-remark").show();
for (let i = 0; i < input.files.length; i++) {
const reader = new FileReader();
// reader.readAsDataURL(input.files[i]);
const objectURL = URL.createObjectURL(input.files[i]);
var sort = i+1;
table += `
<tr id="item-${i}" class="draggable">
<td>${sort}</td>
<td>
<div><img src = "${objectURL}" style="width:200px;"></img></div>
</td>
</tr>`;
}
$('#imagePreviewContainer tbody').append(table);
}
}
```
SubjectDateController.php
```php=
<?php
$tmp_img_sorts = explode(";",$request->tmp_img_sort);
$SubjectDate = SubjectDate::find($id);
if ($request->hasFile('multiple_img')) {
$multiple_imgs = array();
foreach ($request->file('multiple_img') as $key=>$image) {
$originalName = $image->getClientOriginalName();
$extension = $image->getClientOriginalExtension();
$size = $image->getSize();
$mime = $image->getMimeType();
$filekey = array_search($originalName, $tmp_img_sorts);
$fileName = $SubjectDate->id .'_img' .($filekey+1) .'.'.$extension;
$filePath_name = $image->storeAs(config('project.subject_date_dir'), $fileName, 'public');
$multiple_imgs[$filekey] = $filePath_name;
}
asort($multiple_imgs);
$data["multiple_img"] = implode(";",$multiple_imgs);
}else{
if($request->input('_method') == 'PUT'){
$data["multiple_img"] = $request->tmp_img_sort;
}
}
```
### 第二種直接拖曳修改sort的部分
subject_list.blade.php
```php=
<?php
<table class="table table-bordered">
<tbody>
<tr class="active">
<th style="width:50px;">ID</th>
<th style="width:200px;">日期</th>
<th style="width:400px;">主題</th>
<th>簡介</th>
<th style="width:200px;">上架日期</th>
<th style="width:200px;">操作</th>
</tr>
@foreach ($data as $item)
<tr id="item-{{$item->id}}" class="draggable">
<td>{{ $item->id }}</td>
<td>
<div>{{ $item->date }}</div>
</td>
<td>
<div>{{ $item->subject }}</div>
</td>
<td>
<div><pre>{!! $item->intro !!}</pre></div>
</td>
<td>
<div>{{ $item->start_date }}</div>
</td>
<td>
<!-- <button><a href="{{ url('/subjectdate')}}/{{$item['id']}}/editimgsort">圖片排序</a></button> -->
<a class="btn btn-primary" role="button" href="{{ url('/subjectdate')}}/{{$item->id}}/edit">編輯</a>
<a class="btn btn-secondary _delete_" role="button" href="#" class="_delete_" data-url="{{ url('/subjectdate')}}/{{$item->id}}" data-errmsg="確定要刪除 {{$item->subject}} 嗎?">刪除</a>
</td>
</tr>
@endforeach
</tbody>
</table>
```
js的部分
```javascirpt=
$(document).ready(function() {
$( "tbody" ).sortable({
items: 'tr.draggable',
axis: 'y',
update: function (event, ui) {
var data = $(this).sortable('serialize');
// POST to server using $.post or $.ajax
var csrfToken = "{{ csrf_token() }}";
$.ajax({
data: data,
type: 'POST',
url: '{{url('/subjectdate/group/saveorder')}}',
headers: {
'X-CSRF-TOKEN': csrfToken
},
success: function (response) {
// updateFirstColumn();
location.href = location.href;
}
});
}
});
$( "#sortable" ).disableSelection();
});
```
SubjectDateController.php
```php=
<?php
public function saveorder(Request $request){
// $data = SubjectDate::find($request->id);
// $multiple_imgs = explode(";",$data->multiple_img);
// // 重新排列数组
// $sortedArray = array_map(function ($index) use ($multiple_imgs) {
// return $multiple_imgs[$index];
// }, $request->item);
// SubjectDate::where('id', $request->id)->update(['multiple_img' => implode(";",$sortedArray)]);
// dd($request->item);
$i = 0;
foreach ($request->item as $index => $id) {
$item = SubjectDate::where('id', $id)->first();
$item->update(array('sort'=>$index));
$i++;
}
}
```
## jQuery 時間條
```javascript=
.time-bar {
width: 500px;
height: 20px;
border: 1px solid black;
position: relative;
}
.time-handle {
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
position: absolute;
bottom: -12px;
cursor: pointer;
}
.start-handle {
left: 0;
border-bottom: 10px solid blue;
}
.end-handle {
right: 0;
border-bottom: 10px solid blue;
}
.time-range {
position: absolute;
bottom: 0px;
height: 20px;
background-color: green;
transform-origin: left;
}
.time-prohibit {
position: absolute;
bottom: 0px;
height: 20px;
background-color: red;
transform-origin: left;
}
.time-display {
margin-top: 10px;
}
</style>
<div class="form-group">
<label for="week" class="col-sm-2 control-label">*星期:</label>
<div class="col-sm-3">
<select class="form-control" id="week" name="week">
<option value="1" @if(isset($item) && $item->week==1) selected="selected" @endif>一</option>
<option value="2" @if(isset($item) && $item->week==2) selected="selected" @endif>二</option>
<option value="3" @if(isset($item) && $item->week==3) selected="selected" @endif>三</option>
<option value="4" @if(isset($item) && $item->week==4) selected="selected" @endif>四</option>
<option value="5" @if(isset($item) && $item->week==5) selected="selected" @endif>五</option>
<option value="6" @if(isset($item) && $item->week==6) selected="selected" @endif>六</option>
<option value="7" @if(isset($item) && $item->week==7) selected="selected" @endif>日</option>
</select>
</div>
</div>
<div class="form-group">
<label for="time" class="col-sm-2 control-label">*節目時段:</label>
<div class="col-sm-10 time-display">
<input type="time" class="form-control" id="start-time" name="time" value="@if(isset($item)){{ $item->time }}@endif" style="width: 140px;display: inline-block;float: none;" >
<p style="display: inline-block;">~</p>
<input type="time" class="form-control" id="end-time" name="end_time" value="@if(isset($item)){{ $item->end_time }}@endif" style="width: 140px; display: inline-block;float: none;" >
</div>
</div>
<div class="form-group">
<div class="col-sm-2">
</div>
<div class="col-sm-10">
<div class="time-bar">
<div class="time-handle start-handle"></div>
<div class="time-handle end-handle"></div>
<div class="time-range"></div>
<!-- <div class="time-prohibit"></div> -->
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js"></script>
<script>
var item = {!! isset($item) ? json_encode($item) : "false" !!};
var week_times = {!! $week_times !!};
$(document).ready(function() {
var barWidth = $('.time-bar').width();
var minuteInterval = barWidth / (23 * 60 + 59); // Calculate the width of one minute
updateTimeBar();
$('#week').on('change', function() {
week = $(this).find(":selected").val();
updateTimeBar();
});
// Update the time display based on the handle position
function updateTimeDisplay(handle, timeField) {
var handlePosition = handle.position().left;
var minutes = Math.round(handlePosition / minuteInterval);
var hours = Math.floor(minutes / 60);
minutes = minutes % 60;
var timeString = hours.toString().padStart(2, '0') + ':' + minutes.toString().padStart(2, '0');
timeField.val(timeString);
}
function getHandlePosition(timeString){
var hours = parseInt(timeString.split(':')[0]);
var minutes = parseInt(timeString.split(':')[1]);
var totalMinutes = hours * 60 + minutes;
return totalMinutes * minuteInterval;
}
function updateTimeBar(){
$(".time-prohibit").remove();
$.each(week_times,function(key,array){
if (array["week"]==$('#week').val()){
var startTimeInterval = getHandlePosition(array["time"]);
var endTimeInterval = getHandlePosition(array["end_time"]);
var left_int =startTimeInterval +5 ;
var width_int= endTimeInterval - startTimeInterval;
var $newDiv = `<div class="time-prohibit" style="left:${left_int}px;width:${width_int}px;"></div>`; // creates a div element
$('.time-bar').append($newDiv);
}
});
}
// Update the handle position based on the time value
function updateHandlePosition(handle, timeField) {
var handlePosition = getHandlePosition(timeField.val());
handle.css('left', handlePosition + 'px');
$('.time-range').css('left', ($('.start-handle').position().left + 5) + 'px');
$('.time-range').css('width', ($('.end-handle').position().left - $('.start-handle').position().left) + 'px');
}
// Initialize the handle positions and time display
updateHandlePosition($('.start-handle'), $('#start-time'));
updateHandlePosition($('.end-handle'), $('#end-time'));
updateTimeDisplay($('.start-handle'), $('#start-time'));
updateTimeDisplay($('.end-handle'), $('#end-time'));
// Handle dragging of the start handle
$('.start-handle').draggable({
axis: 'x',
containment: 'parent',
drag: function() {
updateTimeDisplay($(this), $('#start-time'));
updateHandlePosition($('.start-handle'), $('#start-time'));
},
stop: function() {
updateTimeDisplay($(this), $('#start-time'));
}
});
// Handle dragging of the end handle
$('.end-handle').draggable({
axis: 'x',
containment: 'parent',
drag: function() {
updateTimeDisplay($(this), $('#end-time'));
updateHandlePosition($('.end-handle'), $('#end-time'));
},
stop: function() {
updateTimeDisplay($(this), $('#end-time'));
}
});
// Update start time field when its value changes
$('#start-time').on('input', function() {
updateHandlePosition($('.start-handle'), $(this));
});
// Update end time field when its value changes
$('#end-time').on('input', function() {
updateHandlePosition($('.end-handle'), $(this));
});
});
</script>
```
## jQuery遇到的問題
### jQuery submit onclick 事件觸發資料會直接送
這邊可以先利用button做onclick去觸發submit然後把submit隱藏起來就好
```php=
<button type="button" id="form_button" class="btn btn-info pull-right">提交</button>
<button type="submit" id="submit" style="display: none;">
$('#form_button').on('click', function() {
// 手动触发表单提交
$("#submit").click();
});
```
### jQuery Ajax送到controller的update 空值 create有資料
:::danger
錯誤訊息
Symfony\\Component\\HttpKernel\\Exception\\HttpException
CSRF token mismatch.
:::
:::danger
因Restful API修改用put但實則上ajax type只接受get和post
如果是要修改就要先type=post然後data裡面在上面_method=put就即可解決
:::
```php=
<?php
@if($method=="store")
<form id="form" action="{{ url('/subjectdate') }}" enctype="multipart/form-data">
@else
<form id="form" action="{{ url('/subjectdate/'.$item->id) }}" enctype="multipart/form-data">
@method('PUT')
@endif
@csrf
<input type="submit" class="btn btn-info" value="提交">
```
```javascript=
$(document).ready(function() {
$('#form').on('submit', function(e) {
e.preventDefault(); // 阻止表单默认提交行为
// 使用 .serializeArray() 获取表单字段
var formData = $(this).serializeArray();
form = $('#form')[0];
var formData = new FormData(form); // 获取表单字段
var formAction = $(this).attr('action');
var type = "POST";
// 发送 AJAX 请求
$.ajax({
type: type,
data: formData,
url: formAction, // 替换为实际的验证路由
processData: false,
contentType: false,
success: function(response) {
// 验证成功,执行相关操作
if(response.status=="success"){
Swal.fire({
title: '成功',
text: response.message,
icon: 'success',
confirmButtonText: '確認',
timer: 2000, // 設定計時器為 2000 毫秒(2 秒)
showConfirmButton: false // 隱藏確認按鈕
}).then((result) => {
// 使用 JavaScript 重新導向到新頁面
location.reload();
});
}
console.log(response);
},
error: function(xhr) {
if (xhr.status === 422) {
// 验证失败,显示错误消息
var errors = xhr.responseJSON;
var errorContainer = $('#errorContainer');
errorContainer.find('ul').empty(); // 清空之前的错误消息
// 构建错误消息并显示
$.each(errors.errors, function(key, value) {
errorContainer.find('ul').append('<li>' + value + '</li>');
});
errorContainer.show();
} else {
// 处理其他错误
console.log('An error occurred');
}
}
});
});
});
```
### jQuery 事件沒反應換成如下
```javascript=
$(document).on("change", 'select[name^="rich_menu_type"]', function () {
console.log(this);
});
```
# AJAX
## ajax包function return data
記得PHP 要將資料轉成JSON
json_encode()
```javascript=
function List(id){
var res = query();
console.log(res);
switch(res.status) {
case 'success':
alert(msg);
return false;
break;
case 'fail':
alert(res.msg);
return false;
break;
default:
alert('查詢空房失敗');
return false;
}
}
{{-- (done)查詢 --}}
function SearchRoomquery() {
var data = '';
$.ajax({
url: "{{ route('Front::Search') }}",
type: 'GET',
headers: {'X-CSRF-TOKEN': '{{ csrf_token() }}'},
async: false,
dataType: 'JSON',
data: {
checkin_date: $('#checkin_date').val(),
checkout_date: $('#checkout_date').val()
$('#order_data').serialize(),
},
success: function (e) {
data = e;
}, error: function(xhr, type) {
// do nothing
}
});
return data;
}
#jQuery onclick(product.edut())
var product = {
'insert': function() {
$('#save_button').text('新增');
$('#save_button').attr("onClick","product.save_insert();");
$('#order_data')[0].reset();
$('#checkin_date').attr({"min" : now_date});
$('#checkout_date').attr({"min" : now_date});
$('#checkin_date').val(now_date);
},'edit': function(id) {
$('h4.modal-title').html('訂單管理');
OrderListLoad(id);
$('#product_info').modal('show');
}
```
##
```php=
```
# CSS
如果col沒辦法同行有可能套件問題直接加style
```html=
<div style = "display:inline-block">
</div>
```
直接對子層下css
```html=
<style>
.table>tbody>tr>td>a{
color: #337ab7;
text-decoration: none;
}
</style>
```
# npm安裝(webpack.mix.js更改)
```php=
npm install
```
webpack.mix.js 更改
```php=
# 編譯開發資源
npm run dev
# 或者,啟動監視模式,當資源文件更改時自動重新編譯
npm run watch
```
在這兩個指令中,npm run dev 用於編譯開發版本,而 npm run watch 則會啟動監視模式,當檔案更改時自動重新編譯。
運行這些指令之後,Laravel Mix 將根據您的 webpack.mix.js 文件重新編譯前端資源。這樣的更改才會生效,並且生成的檔案將反映您對 webpack.mix.js 文件所做的更改。
請注意,有時可能需要清除瀏覽器緩存,或者在瀏覽器中強制刷新頁面,以確保您看到最新的前端資源。這通常可以通過在瀏覽器中按下 Ctrl + F5(Windows/Linux)或 Cmd + Shift + R(Mac)實現。