2015年12月19日 星期六

jQuery AJAX

jQuery AJAX Methods

AJAX is the art of exchanging data with a server, and update parts of a web page - without reloading the whole page.
The following table lists all the jQuery AJAX methods:
MethodDescription
$.ajax()Performs an async AJAX request
$.ajaxPrefilter()Handle custom Ajax options or modify existing options before each request is sent and before they are processed by $.ajax()
$.ajaxSetup()Sets the default values for future AJAX requests
$.ajaxTransport()Creates an object that handles the actual transmission of Ajax data
$.get()Loads data from a server using an AJAX HTTP GET request
$.getJSON()Loads JSON-encoded data from a server using a HTTP GET request
$.getScript()Loads (and executes) a JavaScript from a server using an AJAX HTTP GET request
$.param()Creates a serialized representation of an array or object (can be used as URL query string for AJAX requests)
$.post()Loads data from a server using an AJAX HTTP POST request
ajaxComplete()Specifies a function to run when the AJAX request completes
ajaxError()Specifies a function to run when the AJAX request completes with an error
ajaxSend()Specifies a function to run before the AJAX request is sent
ajaxStart()Specifies a function to run when the first AJAX request begins
ajaxStop()Specifies a function to run when all AJAX requests have completed
ajaxSuccess()Specifies a function to run when an AJAX request completes successfully
load()Loads data from a server and puts the returned data into the selected element
serialize()Encodes a set of form elements as a string for submission
serializeArray()Encodes a set of form elements as an array of names and values

AJAX

AJAX 概念:

AJAX




Create an XMLHttpRequest Object



var xhttp;
if (window.XMLHttpRequest) {
    xhttp = new XMLHttpRequest();
    } else {
    // code for IE6, IE5    xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}


Send a Request To a Server






Server Response






The onreadystatechange Event








<!DOCTYPE html>
<html>
<body>

<h3>Start typing a name in the input field below:</h3>

<form action=""> 
First name: <input type="text" id="txt1" onkeyup="showHint(this.value)">
</form>

<p>Suggestions: <span id="txtHint"></span></p> 

<script>
function showHint(str) {
  var xhttp;
  if (str.length == 0) { 
    document.getElementById("txtHint").innerHTML = "";
    return;
  }
  xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (xhttp.readyState == 4 && xhttp.status == 200) {
      document.getElementById("txtHint").innerHTML = xhttp.responseText;
    }
  };
  xhttp.open("GET", "gethint.php?q="+str, true);
  xhttp.send();   
}
</script>

</body>
</html>



showCustomer

function showCustomer(str) {
  var xhttp; 
  if (str == "") {
    document.getElementById("txtHint").innerHTML = "";
    return;
  }
  xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (xhttp.readyState == 4 && xhttp.status == 200) {
    document.getElementById("txtHint").innerHTML = xhttp.responseText;
    }
  };
  xhttp.open("GET""getcustomer.asp?q="+str, true);
  xhttp.send();
}




2015年12月9日 星期三

DataSource->Where

如果 在 Design Type 下,該筆  Record 的 DataSource 裡面的 WHERE 有設定值
則 Run Time 時,似乎無法改變 DataSource->Where 的值

如果 在 Design Mode 裡, Record 的 DataSource 沒有設 Where
Run time ,在 BeforeBuildSelect Event 就可以設定 Where 值!

2015年12月7日 星期一

快速訂單設計記錄

這篇是寄給我自己看的,讀者看不懂就算了!

在資料庫中讀取相同的介紹會員,且還沒有完成的快速訂單中,找出最近的一筆,亦即是 id 最大的那筆,然後,設定一個 Session 給他。

在 STEP1 Page 中的 PageBeforeInitialize 中,寫:
$db = new clsDBmysql_conn(); 
$SQL = "SELECT max(qf_id) as maxid FROM quick_form WHERE refer_mem_extid='" .$_SESSION["mem_id"]."' AND finished='0';";
$db->query($SQL);
$Result = $db->next_record(); 
if ($Result) {$_SESSION["qf_id"] = $db->f("maxid");} else {$_SESSION["qf_id"] = 0;}

然後,在 Page 的 Record 中,DataSource 中,要設定該 Table ,Where 設定為:qf_id=$_SESSION["qf_id"];

這樣就可以搞定。

STEP 2, STEP 3....之後的步驟網頁,也都是一樣的設定,這樣就可以確保處裡的都是相同的一筆資料了!

上一步、下一步,都可以指稱到相同的一筆。縱使是 user 直接在 url 輸入 step2網址,也可以指到我們希望的那一筆資料。(相同會員最後未完成的那一筆記錄)。

注意:當最後一個步驟完成時,記得必需將 Finished 欄位設為"1",且將 Session 清空!表示已經完成,不會被重複處理!


DataSource->Where

DataSource->Where Run-Time Property (PHP)

Syntax

object->DataSource->Where [=value]

This property stores all conditions that are eventually used in the WHERE clause of a query that selects, updates or deletes data from the database. Programmers can add their own conditions (preserving the SQL syntax) in one of the events triggered before the final query is built and executed (i.e. BeforeBuildSelect, BeforeBuildDelete, BeforeBuildUpdate).

在CodeCharge 的 help 裡面有這一段,他說設定了DataSource->Where 是儲存了  Select, update, delete  的 WHERE 子句。
程式設計師可以分別在 BeforeBuildSelect, BeforeBuildDelete, BeforeBuildUpdate 裡面,去設定 WHERE 子句。

結果,我一開始以為,只要在 BeforeBuildSelect 中設定了 WHERE 子句,就已經設定了所有的 WHERE 子句,結果一執行的結果,Select 出來的是我要的結果沒錯,但是,一執行 Update 就整個資料庫都被 Update ,就相當於沒有 Where 一樣。(  我在 Record 的定義中,並沒有設定 WHERE)。這並不是我要的結果。

後來經過測試的結果是:原來,我必須個別去設定 BeforeBuildUpdate  的 Where,以及 BeforeBuildDelete 的 Where 才會被正確的執行。

 CodeCharge的SELECT, UPDATE, DELETE 的 WHERE 子句是個別設定的!

2015年11月25日 星期三

SCriptcase 在 buttom 之後的 error_message

Scriptcase的error handling 提供了內定的 macro 函數:

sc_error_message();
sc_error_exit();

然而,此 sc_Error_message() 函數似乎僅限於在 on_xxx events 中
放在 on_validate 等都work
但是,放到 自訂的 buttom 之後,似乎不work

於是,只好改用

echo "Error: Error message!!!";
sc_error_message("Error: Error Message!!!");
sc_error_exit();

這樣可以出現 echo 視窗。

但是如果只有 
echo "Error: Error message!!!";
sc_error_exit();
 這樣,出現echo 視窗後,還是會繼續執行,不會停止程式。

必需完整的

echo "Error: Error message!!!";
sc_error_message("Error: Error Message!!!");
sc_error_exit();

三段都有才可以。

記錄之,備查!


註:使用 echo "";  可以顯示一個 Output 小視窗。




2015年11月22日 星期日

將經營規則 business rule 寫在 mysql 中

資料庫系統,一定牽涉到資料庫本身,以及應用程式所處理的功能。
這些功能的規則,稱為 Business Rule. 有人翻譯為"商業規則",我認為這個翻譯不大妥當,應該為 "經營規則"。

這些經營規則,以前通常都是在 APP 應用程式中去設計執行,但如果有不同的程式給不同的人使用,而要遵守同一個 business rule ,那就變成必需在各個 AP 中個別去撰寫程式碼,這樣就會有不一致以及浪費時間的現象。

所以,關於這些資料的經營規則 business rule 最好是直接在  mysql 中執行即可,以方便保持資料的一致性,規則的一致性。

使用 mysql 的 STORED ROUTINE(Procedure/Function)及 Trigger Routine 以及Table 間的Foreign Key 規則、Index 唯一或可重複等工具,即可以達到一定的一致性規則。

而畫面的新增/更改/刪除/查詢,則可以很簡單的運用如 Scriptcase 等畫面產生器,就可以輕鬆的完成輸出入界面。


某些技巧:

如果有些程式碼是在特定的情況下才需要被執行,可以設計一個欄位值來控制他。
例如:field: execute_it char(1), Default:"0"
在 update_trigger中的程式可以寫:

IF NEW.execute_it = "1" THEN
    -- Execute some code...
    SET NEW.execute_it = "0";
ELSE
    -- Execute the other code......
END IF;

記得最後必須將 execute_it 的值設回來"0"
    SET NEW.execute_it = "0";



2015年9月28日 星期一

SC error handling


if({password} != {repassword})
{
sc_error_message("ERROR: ERROR ERROR MEssage!!!!");
sc_error_exit();
} else {
{password} = md5({password});
}

2015年9月14日 星期一

運用MySQL的Trigger 來設計鎖單功能

一個商業上資料表單,經常應該經過審核過後,即會希望把單據鎖定,不再被修改或刪除。例如:訂單、進貨單、出貨單、請假單......
如果經過Approve過的單據,還可以隨意被修改,那不是很糟糕嗎!

如此的商業邏輯 Business Rule,應該由MySQL 來做就好,以輕鬆維持資料庫的完整性。
運用 MySQL的 Trigger 就可以輕鬆的做到。

方法是:在該表單的欄位裡面,增加一個 lock bit(1)的欄位。

然後,建立一個 Trigger BEFORE_UPDATE:

BEGIN
IF OLD.lock THEN
    SET NEW = 'ERROR: 本單已經鎖定,無法更改。如欲更改,請先解除鎖定狀態。';
END IF;
END

BEFORE_DELETE:
BEGIN
IF OLD.lock THEN
    SET NEW = 'ERROR: 本單已經鎖定,無法刪除。如欲刪除,請先解除鎖定狀態。';
END IF;
END

這樣就ok了!

2015年9月10日 星期四

Scriptcase 上傳到伺服主機時,要注意可讀寫

當Scriptcase發佈到服務主機時,要注意一下,某些資料夾的權限是需要開啟可讀寫的。

/_lib/tmp 是要可讀寫

2015年9月6日 星期日

MySQL SUM with LIMIT records

當使用 SUM() 做加總函數時,MySQL是針對所有的WHERE 條件的,如果有 LIMIT 現制筆數時,他並不會只針對現制筆數部分做部分加總。

SELECT sum(quantity) 
FROM stock_card
LIMIT 0,2;
以上,這樣會得到所有記錄的總加總,而不是只有兩筆;

SELECT sum(quantity) 
FROM (SELECT quantity
      FROM stock_card
      LIMIT 0,2
) AS subquery;
以上,這樣就可以僅僅兩筆的加總。

2015年8月27日 星期四

MySQL: Trigger not activated on delete cascade

MySQL 在delete cascade時,並未啟動 Trigger

解決方法:將Delete Cascade 的 Delete 改為自己做 Delete Trigger


2015年8月22日 星期六

ScriptCase 的 Radio option 如果直接是文字,可能有問題

如題。

我設計了一個訂單選項,A/B/C,僅能讓使用者三選一,所以,自然是使用 Radio option 來讓使用者選擇。

這可能可以兩種設計方式:一個是直接在資料庫中記錄  "A"/或"B"/或"C"的文字內容,或是另外建一個資料表,一個ID+一個選項說明的欄位 desc ,來選。

Scriptcase 的Radio 的選項資料來源 ,即 lookup method ,可以有(1) Manual 或(2)Automatic

Manual 即是自行輸入選項內容來選;而 Automatic 則是從資料表中擷取。

實驗結果發現,如果是  Manual 方式,可能會有一些問題。
顯示沒問題,使用者選擇也沒有問題,儲存鍵以後,也可以直接將該文字值存入資料庫中。然而是在於 其 Default 選項出現時會有問題。他完全不理會 Default 的設定,也不管了之前選擇儲存在資料庫中讀取出來的現有值!顯示出來的並不是資料庫儲存的值!

而如果將之改為 Automatic  另外一個資料表的時候,就完全正確了!

這應該也是一個 Scriptcase 的bug 吧!

2015年8月18日 星期二

Scriptcase 的 button 如何改變label?

上網找了一下Scriptcase如何程式中,改變顯現的Label。

在程式中,經常會有"鎖定/解鎖"按鈕的需求,當開放時,按鈕顯現的是"鎖定",而當鎖定以後,按鈕顯現的是"解鎖"。也就是兩個不同的狀態,可以隨著狀態不同而交替顯示按鈕名稱。

Scriptcase 裡面並沒有提供 可以直接控制物件屬性的方法,希望以後可以有,這樣可以更有彈性的滿足更多的不同需求。

可是,這會兒還沒有怎麼辦?

找了Scriptcase 的 論壇,找到一個網友提供的方法,就是製做兩個 Button,然後使用 sc_btn_display("button_name",on/off),來控制。

可以設計一個資料表中的欄位,其值只有兩個狀態:1/0。

當 1 時,顯示 button_1, on,而button_2, off
當 0 時,相反。

將這程式寫在 Events -> OnLoad 中,即可。

2015年8月16日 星期日

Scriptcase 的 SQL ERROR!

當訪問數據庫時發生錯誤:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3

View SQL


昨天發生了這個ERROR,查了好久,查不到!

原先一直以為是 trigger 裡面的SQL Statement 的問題,一行一行的查,每個函數也都花了時間查了!結果,找不到Error!

最後,才一直回憶,我最近一次修改了什麼?

原來,我將一個欄位設為 Disabled Field,我不希望讓使用者可以點擊那個欄位,結果就出現了這個 SQL syntax error 的問題。
將之改回 Enable ,就沒問題了!

後來,我發現有個屬性:SQL Type:Text,這個屬性我過去幾乎沒有去管他,也沒有發生過什麼錯誤。這次,因為這個欄位的型態應該是 Number,而不是 Text,所以,我將之改為 Number,一樣設 Disabled Field,結果就OK了!

原來問題發生在這裡:SQL Type不符合上面!

mysql trigger error handle

DELIMITER $$
DROP TRIGGER IF EXISTS before_tblinventoryexceptionreasons_delete $$
CREATE TRIGGER before_tblinventoryexceptionreasons_delete
BEFORE DELETE ON tblinventoryexceptionreasons
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblinventoryexceptionreasons = old.idtblinventoryexceptionreasons) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exception reasons table with this item.';
  END IF;
END$$
DELIMITER ;

DELIMITER $$
DROP TRIGGER IF EXISTS before_storesalesconfig_delete $$
CREATE TRIGGER before_storesalesconfig_delete
BEFORE DELETE ON tblstoresalesconfig
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblstoresales WHERE tblstoresales.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the sales table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventory WHERE tblinventory.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exceptions table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$$
DELIMITER ;

DELIMITER $$
DROP TRIGGER IF EXISTS before_tblinvoice_delete $$
CREATE TRIGGER before_tblinvoice_delete
BEFORE DELETE ON tblinvoice
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblinvoice = old.idtblinvoice) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$$
DELIMITER ;

2015年8月13日 星期四

Scriptcase 開發有感:Business Rule 設計在mysql

應該盡量把  Business Rule 設計在 mysql 裡面,也就是 Stored Procedure / Trigger 等

Scriptcase 只要單純的做 FORM的 IO/AUDI就好。

舉一些例子:

會員編號的產生,auto_increment 是一個自動產生數字序號的方法
如果是要產生文字的編碼,就得自己製作。這應該直接由 trigger 來做即可,不用 AP 來做。


WRITE ONCE:只能寫一次的資料。

2015年8月12日 星期三

Scriptcase:如何設定一個欄位的初始值

當有需要在新增一筆資料時,有些欄位需要給予一個初始值。
在Scriptcase 裡面,Fields -> Initial Value (type) ->Defined Value,底下 Initial Value:可以設入一個初始值。
如果該初始值,是一個常數,如:數字、字母,那簡單,輸入就好。而如果是一個變數,就可以用 [variable] 。
那可以是函數嗎? 一個自訂函數可以嗎?
好像不行ㄟ!

只好試試看其他方法。

後來想了,將函數寫在 Form Event -> OnApplicationInit 中,將結果寫在一個變數中, 例如[v_result],然後,將此變數填在該欄位的 Initial Value裡面。

同時,記得到 Application -> Global Variable 中去找到這個變數,並將之設定為"OUT"


2015年8月8日 星期六

Scriptcase 控制欄位鎖住/開鎖的方法

會有需要鎖單功能,也就是將表單鎖住,不讓使用者修改。
需要經過開鎖,才可以編修。

ScriptCase 有提供對欄位 設為 readonly, disabled 等 macro

sc_block_display (Block_Name, on/off)
sc_field_disabled ("Field_Name = True/False", "Parameter")
sc_field_display ({My_Field}, on/off)
sc_field_readonly ({Field}, on/off)
sc_form_show 'on' or 'off

以上這些 Macro,可以對  form / block / field 做各種顯示不顯示,等設定。

而對於 Master / Detail 裡的 Detail 就不能了。因為 Detail 是另一個 Application 不是一個 field 或 block!

如果設了兩個 Block,分別設為 detail ,一個有IUD功能,另一個沒有,結果還是沒有!

最後,試了一個變通的方法:

製作兩個 Detail  Application,一個可以準備可以允許編輯用的;另一個準備來只准讀取 Read Only 的。幸好,使用 Scriptcase 複製 Application 還蠻方便。一下子就好了,名稱上一個叫做 xxxxxx_detail ;另一個叫做 xxxxx_detail_readonly,其內容,其實都一模一樣。

就在 Master application中,分別建立兩個 Master/Detail,一個在聯結中設定允許INSERT/UPDATE/DELETE、另一個不允許INSERT/UPDATE/DELETE,然後,分別放在兩個不同的Block中,而用 sc_block_display()來控制顯示哪一個block,就可以了!

註:2015/08/17 今天終於找到了,讓上面所講的鎖定/結鎖,能自動儲存起來,存在一個欄位中,然後,往前、往後以後,回到這一筆資料,依然是鎖定/解鎖 的狀態。
那就是:

if ({lock_field}=='1') {
   {lock_field}='0';
   enable_all_fields();
} else {
    {lock_field}='1';
    disable_all_fields();
}
sc_ajax_javascript( 'nm_atualiza', array('alterar'));


註:自己另行設計一個 button,TYPE:JavaScript,可以自訂 LABEL、還有 CONFIRM Message等。
在下面的 JavaScript 裡面輸入:

nm_atualiza('alterar');

這是執行"SAVE"的意思。



另一個應用場景是:如果希望自動執行SAVE,而不要讓使用者再按一次SAVE,就可以在程式中自己加入這段程式碼。

下面這一段程式:
執行SAVE,然後等一秒鐘,然後自動下一筆(nm_move('avanca');)

nm_atualiza('alterar'); setTimeout(function() {nm_move('avanca');},1000); //you need a delay (1000 = 1s) here to wait for the update to finish, otherwise the form would lock up. You might need to adjust the time. Just try what works best for your system.

Parameters for nm_move():
first = ‘inicio’
previous = ‘retorna’
next = ‘avanca’
last = ‘final’








2015年8月7日 星期五

Scriptcase 的 pdf 轉出

在 FORM 中的 PDF Export ,如果直接是 表單內容,可以依據表單格式輸出,然而,如果內含有 Master/Detail 的細項內容,就產生錯誤了。

看了 help 教學 Video,似乎要另外用 PDF Application來做才可以。

2015年8月6日 星期四

scriptcase 的 bugs

今天使用 ScriptCase 設計表單,表單日期欄位原本都是正常顯示的,但是當新增一個狀態欄位時,表單日期的顯現出現錯誤了!
原本日期顯示應該是: yyyy/mm/dd
增加一狀態欄位以後,變成: yyyy mm d
該狀態欄位為空白時,日期欄就是正常的;狀態欄位有值時,就變成錯誤格式!

將狀態欄位刪除,日期顯示格式就一切正常!

查看表單日期的資料庫內容,並沒有改變,沒有錯誤。顯示是 Scriptcase 在顯示該表單欄位資料時,由於Scriptcase內部程式的錯誤,某些變數或...相衝,導致顯示格式錯誤!

後來將狀態欄位加回去,將狀態欄位的型態改為 <select>,日期也就好了!
原本狀態欄位型態是 <integer>

註:2015/08/16 剛才又發生一次類似的錯誤。
錯誤的狀況是:一個 integer 欄位型態, 然後用 Lookup Setting 設定為另外顯示該ID的名稱值。但是這樣一來,日期欄位的格式就變了!
將該欄位型態由  Integer 改為 Select ,一樣用Lookup Setting,而 加Where 設定,這樣就只有單一值可以顯示,不會有選項可以選。這樣那個日期顯示就正常了!

2015年8月5日 星期三

ScriptCase master/detail,當Master的一個選項值改變,Detail 要跟著變動,怎麼做?

Master/Detail 是關聯式資料庫概念裡面,經常有的資料庫結構關係。例如:訂單及訂單明細。訂單是 MAster ,訂單明細是 Details
如果由於 訂單的 某個欄位(field1)改變時,而Detail 裡面的選項也要跟著改,那就使用 field1 改變時,整個Form Reload 選項,即可達成目的了。

如果反過來,是 Detail 裡面的值改變時,要更新 Master 的欄位值,則使用 sc_master_value('Object', Value) 

2015年8月1日 星期六

Scriptcase 不能編修了!

經過調查,原來是我的欄位中設了一個 radio 欄位,而其值必須由另一個table產生,只要把這個欄位改成 text 就可以了。
可見,是此欄位的問題。

看來,必需另想辦法了!

使用這種產生器的缺點,就是你最好使用他的功能就好,她畢竟不是萬事都能做的!

2015年7月24日 星期五

scriptcase upload file

中文檔名,不行!
英文檔名,size較小,可以成功,但檔案較大,就不行!
將 php.ini 裡面的
upload_max_filesize = 64M ==> 512M
upload_max_filesize, 
memory_limit, 
post_max_size
max_execution_time

放大後,就可以成功了!

上傳的位置放在 /_lib/file/ 裡面 docnn  nn為id,設定在該form裡面。
他並沒有依照 form 裡面的 Application -> Settings->Document Path 裡的設定放置

如果選擇的是 field datatype -> images(file name),也不會放在 application -> settings -> Image Directory 裡面!

Scriptcase 裡面還是一堆 Bugs!

唉!究竟是我誤解了呢?還是 Bugs!


==============================

multi-upload 功能似乎僅能適用在 Document(database),也就是儲存在 mysql BLOB裡面才可以。用Filename 似乎不行ㄟ!

但是,我不想把附加的檔案文件放到BLOB中,那樣會讓 database太大,以後會麻煩的。






2015年7月22日 星期三

用MySQL的Trigger 自動產生會員編號

想要自己編會員編號,不想用mysql 的 auto-increment自動編號功能。
而這個編號,可能會在不同的 AP 開放輸入,所以,最好的產生方式,是放在資料庫裡面自動產生,所以,就動了 Trigger 的念頭。

經過研究,寫了下面這段:


CREATE TRIGGER `get_ext_id` BEFORE INSERT ON `members`
 FOR EACH ROW BEGIN

    DECLARE v_last_id , v_new_id INT;

    SELECT members_last_id INTO v_last_id FROM members_last_id;
    SET v_new_id = v_last_id + 1;
    UPDATE members_last_id SET members_last_id = v_new_id;
    SET NEW.members_ext_id = LPAD(v_new_id,10,'0');

END


members_last_id 是另外建立的一個 table,裡面只有一個欄位,也叫做:members_last_id,而且只有一筆記錄,就是記錄著欲產生的會員編號的最後一號。

就這樣,可以自動從資料庫裡面,每當有新增時,就會自動產生會員編號。

2015年7月21日 星期二

Scriptcase 建立文字的會員編號

$tmp_str_id = str_pad({members_id}, 10, '0', STR_PAD_LEFT);
// SQL statement parameters
$update_table  = 'members';      // Table name
$update_where  = "members_id = {members_id}"; // Where clause
$update_fields = array(   // Field list, add as many as needed
     "members_ext_id = '$tmp_str_id'"
 );
// Update record
$update_sql = 'UPDATE ' . $update_table
    . ' SET '   . implode(', ', $update_fields)
    . ' WHERE ' . $update_where;
sc_exec_sql($update_sql);

2015年4月24日 星期五

Scriptcase 裡面,如何取得上層ap的欄位值

如題

只能透過 [session variable]做了。

ScriptCase 的 Form 裡面 --> Fields --> 要的欄位 --> Save Variable:yes --> Variable Name: [xxxxxx]

這樣,就可以在 detail 中使用 該 Session Variable了。


而 sc_master_value('Object', Value) 這個 macro 則是可以 更新 上層ap 欄位的值

Update a data in the Master application in real time according to changes made in a given field of the Detail application.

2015年4月23日 星期四

php 加減

有些數字必須這樣處理,才能加減!
floatval(preg_replace("/[^-0-9\.]/","",$orders_shipment_id));
$total2 = floatval(preg_replace("/[^-0-9\.]/","",$total)) + floatval(preg_replace("/[^-0-9\.]/","",$ship_fees));

2015年4月22日 星期三

Scriptcase裡Form的 master/detail

ScriptCase 的 Form 裡面的 Master/ Detail 是建立一對多的關聯資料,detail 部分,可以連結到 Grid 或是 Form 都可以。

Grid 當然就是只有可以看,不能編輯、修改;而要期待能編輯、新增、修改、刪除,就必須使用 Form 裡面的 Multiple Records / Editable Grid / Editable Grid view ,咦?好像也可以使用 Single Record喔!就是出現時是一筆一筆出來的。

2015年4月20日 星期一

ScriptCase 裡面的 Link

如果Application 是 Form,允許的 Link 有:Application 、 Capture 兩種

Application Link :
  • Application - Used to link our form to any other type of application. This linking type is associated to events of Inclusion and/or alteration, when occurs one of those events the navigation will be effected to the application that we are calling.
Capture Link :
  • Capture - Will be created an icon  beside the field inside the form, when being selected it opens other window showing a search application. In this application that will be opened can do searches and return a value to text field.
  • 選了 Capture 以後,會出現一個欄位選擇,然後選擇一個 Grid 的 Application,此 Grid Application,即是產生來讓使用者選擇欄位值的。
  • 注意:選擇連結Capture 的欄位型態不能是<Select>,能夠是 <text>/<integer>等開放輸入欄位,不能是選擇式的,因為,那功能是一樣的,列出來選擇。我試了,如果是<select>,縱使再建立此 Capture Link 也一樣沒有連結東西,將<select>改成<integer> 就有聯結了!

Form 裡面的 fields 如果是 <select> type 的話,在此欄位旁邊可以加上一個 Link到form的連結,這個Link 就只是 Link 過去 edit 一個Form而已,沒有傳參數過去,同時顯示"EDIT"(中文"更改")的一個button。可以打開該欄位內容的 Form 去更改數值。


如果 Application 是 Grid的話,允許的 Link 有:Application 、 Field、Capture 三種

Application Link :

Field Link :

Capture Link :




2015年4月19日 星期日

scriptcase 的bug

好像還蠻多bugs的


  • master/detail 的 detail (用form做的) 設定沒有AUDI,但 Deploy之後就有!

在 master/detail 的欄位裡, 設定 detail 沒有新增,但一deploy以後,就一定有"新增"/修改/刪除,奇怪

後來,只好改用 grid 來做 detail ,那也可以啦

註:我今天是(20150810)卻發生 Master/Detail裡的Detail設定有AUDI,在開發環境跑都正常,depoly以後,AUDI不見了!太奇怪了!

  • master/detail-->update_master
建立一個訂單,以及訂單明細,兩個Forms,並在訂單中建立了 master/detail。設計了一個update_master() php程式,更改了 orders table 裡面的 total 欄位,並 呼叫 sc_master_value() 更新 master form裡面的  field ,然後,在 Events  裡面設定,onAfterInsert/onAfterUpdate/onAfterDelete 都呼叫 update_master()函數,結果發現為何資料庫有更新而 master fields沒有更新呢?原來發現,detail form 裡面的  "Form Formats"->"Editable Grid view"-> "Use modal form to edit"->要選擇"No",如果選擇 "yes" ,那麼,onAfterUpdate並不會被執行!
這應該是一個 bug 吧!



使用心得:
如果希望 Master/Detail 裡的Detail 需要可以新增刪除修改,那就用 FORM Application來做Detail,而如果希望Detail只需要查詢顯示,不希望可以被編輯,那就使用 GRID Application 來做Detail。

因為,試了很多次,Scriptcase裡面的 Detail 使用Form來製作的話,經常出現問題!
原本在開發環境有AUDI 的,Deploye以後,變不行了!反之亦然!不知道為什麼!




2015年4月12日 星期日

ScriptCase 的Application 管理

由於在 ScriptCase 裡面,要建立一個 Application 非常容易,所以,很容易就建立了一堆的 Application,然後,久而久之,你就忘了,當初建立它的作用是什麼?亂了!

許多Application 會是另一個 app 的master/detail 裡面的 detail,是他的一部分。此部分,也可以另外單獨執行,可是不一定適合使用。
也有可能被共用!所以,很容易亂掉。
所以,規畫就很重要。
另外,運用 Folder 來分類。

例如:屬於 member的部分app,都放在這個folder裡面,使用到的 detail app ,也放到這裡來,較不會亂。

2015年4月11日 星期六

ScriptCase 裡配合Javascript製作一個button的方法範例

很好的參考範例:

http://www.scriptcase.net/forum/showthread.php?7633-Best-way-to-do-this-in-Scriptcase-Display-Nicely-as-one-field-edit-as-multiple


Block1: 2 Label fields ({myaddress}, {mybtn}).

Block2: Address fields.

Create a javascript method (switchBlocks) with a variable (vswitch) to be passed in.

Code:
if(vswitch == 1)
{
document.getElementById('div_hidden_bloco_0').style.display = 'none'; //you need to determine the number of the block by inspecting the element in the browser
document.getElementById('div_hidden_bloco_1').style.display = 'block';
}
else
{
document.getElementById('div_hidden_bloco_0').style.display = 'block';
document.getElementById('div_hidden_bloco_1').style.display = 'none';
}
Create a php method (call_switchBlocks):
Code:
sc_ajax_javascript('switchBlocks',array(0)); //we need this because we can't call javascript from the onLoad event
onLoad:
Code:
{myaddress} = {name}.'<br>'.{address1}.'<br>'.{city};
{mybtn} =  "<button type='button' onclick='switchBlocks(1)'>Edit</button>"; //could be beefed up with some css
call_switchBlocks();
onAfterUpdate:
Code:
call_switchBlocks();
That should give you a start.

另一個案例:

自行建立欄位:{sam_addr_btn}

在 onLoad Event裡建立
{same_addr_btn1}="<button type='button' onclick='sameaddress1()'>Same Address</button>";
在 Javascript Methods建立一個 sameaddress
code:
$("select[name$='m_country_id']" ).val($("select[name$='country_id']").val()); 
$("input[name$='m_state']" ).val($("input[name$='state']").val()); 
$("input[name$='m_city']" ).val($("input[name$='city']").val()); 
$("input[name$='m_postcode']" ).val($("input[name$='postcode']").val()); 
$("input[name$='m_street1']" ).val($("input[name$='street1']").val());
$("input[name$='m_street2']" ).val($("input[name$='street2']").val());



2015年4月8日 星期三

ScriptCase 的 Radio

如果給 Radio 一個空值,結果 Radio 不會空白!

而,Select 會留在Title上面,Radio不會,唉!只好把 Radio 改為 Select

ScriptCase 裡 Select 對應資料欄位不可以使用 ZEROFILL

如題,
如果將欄位設為 ZEROFILL 在ScriptCase裡恐怕會是災難!因為,ScriptCase裡面好像不認得這種欄位設定!會搞得很慘!
我把 ZEROFILL屬性拿掉,就正常了!

呼!搞了半天!花費我好幾個小時的時間,以為撞鬼了!軟體不會撞鬼,只有自己不知道錯在哪裡而已,唉!

記下來,以後不要犯一樣的錯!

2015年4月5日 星期日

ScriptCase 的 Form 裡的 Checkbox 整列設定on/off

Form 有四種類型:
1. Single Record
2. Multiple Record
3. Editable Grid
4. Editable Grid View

這四種的 設定裡面,在 Setting 裡面,底下有個 Layout And Behavior
裡面,如果是第二個 Multiple Record 會有一個

Mark checkbox   Mark all the checkbox fields of the record.

這是用在,例如 ScriptCase 所附的 Security 模組中的 Groups/Apps 權限程式中,設定是否有權限,就有用到這個功能。
如果要在這一個 row 的前面多出現一個  Checkbox 以選擇這個 row 裡面所有的 checkbox on/off 就必須把以上這個選項打開。

其他三個form 類型沒有這個選項。

這是在 Script Case 的 HELP 裡面沒有寫到的!


2015年4月4日 星期六

ScriptCase 的內建Macro : sc_field_disabled_record()

很多軟體都會有一些未公布、未公開的......

ScriptCase 也是一樣的,真的是有點令人......討厭。

我覺得 ScriptCase 還有很多改進的空間,或者是像我另一位朋友說的:「他完全不考慮使用這種程式產生器、或是現成模組、套版等」,開發程式產生器、或套組的工程師,我們搞不清楚他的裡面寫什麼,Open Source的還好,可以看到原始程式碼,還可以知道他做了甚麼事,沒有開放原始碼的,就完全不知道它內部的做法,好像黑盒子一樣。

程式軟體工程的模組,黑盒子概念,物件概念,當然是為了不用蓋房子都必須從磚塊一個一個砌,可以用別人做好的模組來使用就好,節省時間與成本,然而,有一好,就沒兩好,模組也就成了黑盒子,他裡面搞什麼,我們無法掌控!

ScriptCase的Macro有許多讓人......的地方,再怎樣多的 Macro 恐怕也很難滿足所有的需求。

sc_field_disabled(),是一個鎖住欄位,不讓人編輯的函數,但是,如果到了Grid的時候,就不適用逐個記錄的欄位鎖住否。必需用另一個函數sc_field_disabled_record(),而這個函數在 Help 裡面沒有!但在, ScriptCase所附的 Security 模組裡面就有用到!

令人感到困惑的是:到底還有多少沒有被列出公告出來的函數?

碰到問題時,去哪裡找?

ScriptCase 要加強這部分的說明文件,以及服務管道。

ScriptCase 好像是巴西人開發的,使用的原始文字我看不懂,還好有英文,但英文對他們來說是第二語言,所以,並不是第一手的資訊。

有沒有我們中文自己開發類似的程式產生器呢?


2015年4月3日 星期五

Script Case使用有感

Script Case 是一個 php 的 應用程式產生器,可以產生 php+mysql 或其他資料庫的應用程式。

他有設計好許多現成的功能,優勢是:可以快速的產生程式,然而,缺點是:僅能做出他所提供的功能。

所以,如果要以 Script Case來做為一個AP 的開發工具,記得:僅能做出它能做的,不能做出它做不到的。

最好,先研究他能做的,然後,去適應它能做的。
不要妄想去做他做不到的。那會浪費很多時間。

尤其是它有很多的 bugs ,我們只能去適應它!使用它的功能,不要妄想去改變它。


多想一想如何運用它擁有的功能,來達到程式的目的。畫面部分,就遷就他可以做的。



2015年3月31日 星期二

ScriptCase:強制開啟form application在新增模式

三個方法:

1. 在 ToolBar 裡面設計,只要保留 "Insert" 及 "Exit" ,其他 "Update"/"Delete"不要出現,就會開啟在新增記錄的模式。

2. 在 SQL 裡面的 "Where Condition" 故意放一個永遠不會 true 的判斷式,例如:1=2,就會進入 新增記錄模式。

3. 由別的Application啟動,使用
sc_apl_conf("my_form", "start", "new")
此能由別的 Application 來啟動
或是使用在 onApplicationInit event

參考網頁:
https://support.scriptcase.net/en-us/article/884-open-a-form-in-insert-mode




2015年3月9日 星期一

CodeCharge的多語系

<script type="text/javascript">
function insertParam(key, value) {
        key = escape(key); value = escape(value);
        var kvp = document.location.search.substr(1).split('&');
        if (kvp == '') {
            document.location.search = '?' + key + '=' + value;
        }
        else {
            var i = kvp.length; var x; while (i--) {
                x = kvp[i].split('=');
                if (x[0] == key) {
                    x[1] = value;
                    kvp[i] = x.join('=');
                    break;
                }
            }
            if (i < 0) { kvp[kvp.length] = [key, value].join('='); }
            //this will reload the page, it's likely better to store this until finished
            document.location.search = kvp.join('&');
        }
    }
</script>

<div class="top-bar">
  <div class="container">
    <div class="row">
      <div class="col-sm-6 col-xs-4">
        <div class="top-number">
          <p><i class="fa fa-phone-square"></i> {res:CallServiceLine} 0800 628 659</p>

        </div>

      </div>

      <div class="col-sm-6 col-xs-8">
        <div class="social">
          <ul class="social-share">
          <li><div onclick="insertParam('locale','zh-TW')">
            <a href="#"><img src="images/flags/flag_taiwan.png" height="25" width="25"></a>
            </div>
          </li>
            <li><div onclick="insertParam('locale','zh-CN')">
            <a href="#"><img src="images/flags/flag_china.png" height="25" width="25"></a>
            </div>
            </li>
            <li><div onclick="insertParam('locale','en')">
            <a href="#"><img src="images/flags/flag_usa.png" height="25" width="25"></a></div></li>

            <li><div onclick="insertParam('locale','en')">
            <a href="#"><img src="images/flags/flag_philippines.png" height="25" width="25"></a></div></li>

            <li><div onclick="insertParam('locale','en')">
            <a href="#"><img src="images/flags/flag_thailand.png" height="25" width="25"></a></div></li>

            <li class="divider"></li>

            <li><a href="https://www.facebook.com/richeverlight" target="_blank"><i class="fa fa-facebook"></i></a></li>

            <li><a href="https://plus.google.com/101449003530296505676/" rel="publisher" target="_blank"><i class="fa fa-google-plus"></i></a></li>

          </ul>

          <div class="search">
            <form role="form">
              <input type="text" class="search-form" autocomplete="off" placeholder="Search"><i class="fa fa-search"></i>
            </form>

          </div>

        </div>

      </div>

    </div>

  </div>

  <!--/.container-->
</div>
<!--/.top-bar-->

2015年3月4日 星期三

給你的網站設計一個行動版icon

在 html 裡加上這些:

<link rel="shortcut icon" type='image/x-icon' href="favicon.ico">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-144-precomposed.png" sizes="144x144">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-114-precomposed.png" sizes="114x114">
<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-72-precomposed.png" sizes="72x72">

<link rel="apple-touch-icon-precomposed" href="apple-touch-icon-57-precomposed.png">



Code Charge的Builder產生錯誤

在 Code Charge 裏使用 Application builder時,發生JS的錯誤。

經過一番研究後,終於了解,產生的錯誤是在run Builder時,會載入 masterpage,所有在masterpage的 js 都會載入,所以,如果這些 js 裡面有錯,就會在 builder 執行時產生錯誤。

找出是哪個 js 出的錯,然後改正,問題就沒了。

記錄一下。

2015年2月11日 星期三

Script Case Blank Application

SC 裡面的Blank Application

1.
onExecute
如果要放 html/javascript/css 等,要記得一開始、跟最後要鍵入:
 ?>
.....
<?php

中間才寫你的code

2. 如果沒有標明 <body>他會把內容都放在<head>
?>
<script src="../_lib/lib/js/d3.min.js"></script>
<script>d3.select("body").append("p").text("New paragraph!");</script>
<?php

這樣寫,什麼也不會被執行。

?>
<script src="../_lib/lib/js/d3.min.js"></script>
<body>
<script>d3.select("body").append("p").text("New paragraph!");</script>
</body>
<?php

像這樣,才會把d3等碼執行




如何判斷現在FORM是在 insert mode? 還是 update mode?

只要用  if (empty({primary_key})) 就可以知道是否為新增模式了。 如果 {promary_key} 是空白的,那麼就是在新增模式;反之,就是更新模式。 以上。