星期二, 12月 17, 2013

[JSP] IE8 無法下載檔案


最近客戶遇到在IE8不能下載檔案的問題,需要加了一些cache的header即可解決。
請參考微軟的說明:http://support.microsoft.com/kb/316431 範例如下:



String ua = request.getHeader("User-Agent");
         if(ua != null){
          //System.out.println("user-agent:" + ua);
          if(ua.indexOf("MSIE 8.0") > 0){
           response.setHeader("Cache-Control","private");
                    response.setHeader("Pragma","private");
          }
         }

星期一, 12月 02, 2013

[Java] 如何將上傳streaming透過Http Client再上傳到另外一個Server

目前有一個需求是要將上傳api拿到的Stream再透過REST API上傳至另一個儲存空間。
採用的架構是透過Java Jersey + Apache HttpClient 4.3

測試範例如下:

[Java] 下載檔案的中文編碼錯誤如何解決

當透過瀏覽器下載檔案時,需要處理不同瀏覽器對檔案名稱該如何正確編碼的問題。
可以參考[2]的實驗結果。

目前針對IE採用UrlEncode,chrome與firefox採用Mimetype base64編碼,其他未偵到的也都採用base64 :D,base64編碼可直接使用 MimeUtility.encodeText(fileName, "UTF-8", "B");即可。

範例碼如下:
String userBrowser = request.getHeader(HEADER_USER_AGENT);
       
       if(userBrowser != null){
        
        log.debug(String.format("User agent: %s", userBrowser));
        if(userBrowser.toLowerCase().indexOf("mozilla") > -1
          && userBrowser.toLowerCase().indexOf("msie") < 0 
          && userBrowser.toLowerCase().indexOf("chrome") < 0){
         
         log.debug("Detect 'FireFox' browser");
//         Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0

         fileName = MimeUtility.encodeText(fileName, "UTF-8", "B");
         
        }else if(userBrowser.toLowerCase().indexOf("msie") > -1){
        
         log.debug("Detect 'IE' browser");
//         Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; MATP)
         //cosa url encoder

         fileName = URLEncoder.encode(fileName);  
         
        }else{
        
//         Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
         log.debug("Common attachment");
         
         fileName = MimeUtility.encodeText(fileName, "UTF-8", "B");
        }
       }
       else{
        
        log.debug("Cannot find User-Agent header");
        
//        encoding - the encoding to be used. Currently supported values are "B" and "Q".
//        If this parameter is null, then the "Q" encoding is used if most of characters to be encoded are in the ASCII charset, otherwise "B" encoding is used.
        fileName = MimeUtility.encodeText(fileName, "UTF-8", "B");

       }
       
       log.debug("Filename encoded:" + fileName);
       String contentDisposition = String.format("%s ;filename=\"%s\"", valOfDisposition, fileName);

       log.debug("Content diposition:" + contentDisposition);
       builder.header(HEADER_CONTENT_DISPOSITION,contentDisposition);


測試檔案:
ライセンス期限切中文中文kumokura_010507.exe

Base64編碼:

=?UTF-8?B?44Op44Kk44K744Oz44K55pyf6ZmQ5YiH5Lit5paH5Lit5paHa3Vt?= =?UTF-8?B?b2t1cmFfMDEwNTA3LmV4ZQ==?=



參考:
[1] 錯誤訊息:「Internet Explorer cannot download a file (Internet Explorer 無法下載檔案)」

[2] Unicode网页中上传下载文件时发生文件名乱码的问题

星期六, 11月 30, 2013

[jQuery plugin] jQuery validatation 文件

寫網站如果使用jquery的話,一定對jquery validation這個外掛很熟。 今天寫一些功能的時候,找到了一個介紹如何使用的網站:D 有興趣的人可以參考: http://jqueryvalidation.org/

星期三, 11月 27, 2013

[jQuery API] 如何使用$ajax進行 multiple-part/form-data 傳輸

這幾天整合summernote編輯器的上傳,
順便記錄一下如何使用jquery $ajax進行multiple-part的上傳方式
var formdata = new FormData();
//指定欄位的name與binary string
    formdata.append("fileToUpload", file);
    $.ajax({
        data: formdata,
        type: "POST",
        url: "your_api/upload_imgur/" + uid,
        // cache: false,
        contentType: false,
        // dataType: "json",//用這個叫api會404
        processData: false,
        success: function(rJSON) {
            $.console("send file callback:");
}
});
參考https://github.com/HackerWins/summernote/issues/72

星期二, 10月 01, 2013

[jQuery] beforeunload 踩到雷

由於在處理某個議題了,加入監聽beforeunload事件,目前由於有透過window.location.href進行檔案下載的動作,好死不死在chrome,也會因為這個指令而跑到beforeunload的事件。
google找到了對岸的實驗結果(http://www.w3help.org/zh-cn/causes/BX2047),如下表,不過應該在這瀏覽器會更新的時代只能僅供參考,要自已實驗XD
执行结果汇总入表:
IEFirefoxChrome SafariOpera
关闭当前浏览器窗口事件被触发事件被触发事件被触发不支持该事件
导航到另一个进入一个新的地址或选择一个喜欢的位置事件被触发事件被触发事件被触发不支持该事件
单击后退,前进,刷新,或主页按钮事件被触发事件被触发事件被触发不支持该事件
点击一个链接到新页面事件被触发事件被触发事件被触发不支持该事件
调用 anchor.click方法事件被触发不支持此方法1不支持此方法1不支持该事件
调用 document.write方法事件被触发事件被触发事件未触发不支持该事件
调用 document.open方法事件被触发事件被触发事件未触发不支持该事件
调用 document.close方法事件未触发事件未触发事件未触发不支持该事件
调用 window.open方法,窗口名称设置值为 _self事件被触发事件被触发事件被触发不支持该事件
调用 window.navigate事件被触发不支持此方法2不支持此方法2不支持该事件
调用 NavigateAndFind方法事件被触发不支持此方法3不支持此方法3不支持此方法3
调用 location.replace 方法事件被触发事件被触发事件被触发不支持该事件
调用 location.reload 方法事件被触发事件被触发事件被触发不支持该事件
指定一个 location.href 属性的新值事件被触发事件被触发事件被触发不支持该事件
使用 submit 按键提交表单事件被触发事件被触发事件被触发不支持该事件
调用 form.submit 方法事件被触发事件被触发事件被触发不支持该事件
调用 javascipt: 伪协议事件被触发事件未触发事件未触发不支持该事件
调用 mailto: 伪协议事件未触发事件未触发事件被触发不支持该事件
调用自定义伪协议事件被触发事件被触发事件被触发不支持该事件

星期四, 9月 26, 2013

[Shell] 監控JVM使用狀態

為了測試目前記憶體佔用的狀態所寫的shell。


cosa-memory.sh


#!/bin/sh

#author: ken tsai
#date: 2013/7/11

TOMCAT_PID=$(ps aux | grep /bin/java |grep -v grep | grep 'logging' |awk '{print $2}') 

echo "tomcat pid :$TOMCAT_PID"
echo "######################memory monitor##################"
jstat -gcutil -h 10 $TOMCAT_PID 1000

-gcutil Option


Summary of Garbage Collection Statistics
列名描述
S0survivor 0区利用率。
Survivor space 0 utilization as a percentage of
the space’s current capacity.
S1survivor 1区利用率。
Survivor space 1 utilization as a percentage of
the space’s current capacity.
Eeden区利用率。
Eden space utilization as a percentage of
the space’s current capacity.
O年老代空间利用率。
Old space utilization as a percentage of
the space’s current capacity.
P永生代空间利用率。Permanent space utilization as a percentage of
the space’s current capacity.
YGCyoung gc次数。
Number of young generation GC events.
YGCTyoung gc耗时。
Young generation garbage collection time.
FGCfull gc次数。
Number of full GC events.
FGCTfull gc耗时。
Full garbage collection time.
GCTGC总耗时。
Total garbage collection time.
參考資料
http://itzoo.info/?p=256

星期二, 9月 24, 2013

[Mongodb] child process failed, exited with error number 100 無法啟動monogo

在做硬碟塞爆測試的時候,為了將新的build丟上去機器後重開機,
結果會死在monogo無法啟動。

錯誤訊息如下

kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
about to fork child process, waiting until server is ready for connections.
forked process: 11871
all output going to: //storage/COSA//Mongo//log/mongodb.log
ERROR: child process failed, exited with error number 100

追了一下Monog噴的log


死在Insufficient free space for journal files 的錯誤,不過也是噴child process failed, exited with error number 100,這個錯誤的產生說是不正常的mongo db關機所造成。

星期一, 9月 23, 2013

[ShellScript] 用dd指令做硬碟塞爆測試

最近需要透過塞爆硬碟測試一些API,找到了網路上dd指令的介紹。
順便寫了一個簡單的shell script做測試。

of:檔案要存放的位置

//做1G
dd if=/dev/zero of=/tmp/1gb count=1024 bs=1M

//做10G
dd if=/dev/zero of=/tmp/10gb count=10240 bs=1M

//做100G
dd if=/dev/zero of=/tmp/100gb count=102400 bs=1M


//做100G
dd if=/dev/zero of=/tmp/100gb count=100 bs=1G


包裝成shell script使用

目前先都將產生的檔案產生在tmp的目錄下

#!/bin/bash

dummy_path="/tmp/"
count=$1
block_size=$2
block_count=$3

if [ -z "$count" ] || [ -z "$block_size"] || [ -z "$block_count"]
then
echo "Please input paramters for creating dummy file"
else

for ((index=0;index<$count;index++))
do
#echo "file index: $index"
now=$(date +"%m-%d-%Y-%H-%M-%S")
filename="dummyfile_no_${index}_${now}"
echo "create dummy file($index):$filename"
dd if=/dev/zero of="$dummy_path/$filename" count=$block_count bs=$block_size
done
fi

exit 0

$>./dummy_creator 10 1M 1024 # 產生十個1G的檔案

星期三, 9月 18, 2013

[jQuery] 如何控制textbox按enter後往下一個textbox移動

在提供使用者使用表單填寫資料時,如果欄位爆多的時候,
通常使用者會習慣打完資料按enter鍵後能自動往下一個欄位移動。
如果你有這個需求可以參考以下這個範例。
http://jquerybyexample.blogspot.com/2011/05/how-to-set-focus-on-next-textbox-on.html

實作方法透過偵測現在有多少input textbox,再透過遞增textbox index方式即可簡單做到
$('input:text')[nextIndex].focus();

把它改成外掛會更好使用。


星期三, 9月 11, 2013

[AngularJS] 如何重設表單

最近透過Angular在送出表單時,想要清除表單資料,於是將綁定欄位的model重設時,
會造成表單欄位有設require屬性,會丟出相對應的錯誤訊息。
因為在1.0.x版本時,這樣並沒有將整個表單的狀態重設

可以參考這篇
http://stackoverflow.com/questions/12603914/reset-form-to-pristine-state-angularjs-1-0-x

不過在1.1.x版提供一行簡單的指令可以解決重設表單的問題

 $scope.你的表單id.$setPristine();

範例
                             
 $scope.signup_form.$setPristine();
                             

星期日, 9月 01, 2013

[jQuery] IE8踩雷: 使用$('element')建立元素未加入結尾

最近寫了一個dropbox like breadcrumbs的外掛,
結果在IE8測試下有個地方沒反應,
查了一下是建立元素的時候沒有結尾

//會爆掉!!
//  var $anchor = $("<a data-id='" + nodeData.id + "'>");
  var $anchor = $("<a data-id='" + nodeData.id + "'></a>");

星期一, 8月 05, 2013

[jQuery] 如何新增plugin的 public method

寫了很多外掛用了很多外掛,一直再找覺得看起來順利的寫作pattern,Stackoverflow也有人提到jQuery官方如何擴充公用方法的實踐方法!!

統一整理到以下這篇:D

[jQuery Plugin] 撰寫jQuery plugin的一些寫作樣式

[jQuery] 搞懂 jquery plugin 與 jquery widget

對於jquery plugin與widget字義上有不清楚可以看一下stackoverflow解釋可以有助理解xd

jQuery plugins vs widgets

You can either write a jQuery plugin or a jQuery UI widget.
Depends on what you want to do. Neither of these is outdated. If you write a widget, it will depend on jQuery UI (and jQuery of course), if you write a plugin, it will only depend on jQuery. Really, it depends on what you want to achieve.

Jquery Widget vs Jquery Plugin, Differences, When to use which?

I've never heard of a jQuery widget. I imagine some people might use the term to describe a... widget... that has been made with jQuery. Certainly there are widgets in jQuery UI, for example. It's an odd question.
A widget is a widget (always includes a visual element, sometimes includes reusable functionality), and can be a subset of a plugin or a plugin in and of itself.
A plugin extends jQuery directly and may or may not have a visual component.

星期日, 7月 28, 2013

[PHP] Assetic 初探

Assetic是一個Asset的管理工具,可以把網站的靜態資源(js.css)打包在一起。

前置工具:
要獲得這個工具,請安裝composer,方便又快速

1.在你的專案下面建立一個composer.json
{
        "require":{
                "kriswallsmith/assetic": "1.1.*"
        }
}


2.安裝套件
$>composer install

裝完會在目錄下看到一個vendor的資料夾:
                                                                                                                          
vendor下面放的東西

3.建立一個測試頁面


  include_once 'vendor/autoload.php'; //記得要呼叫autoload.php

  use Assetic\Asset\AssetCollection;
  use Assetic\Asset\FileAsset;
  use Assetic\Asset\GlobAsset;
  use Assetic\Filter\GoogleClosure\CompilerApiFilter;

  $APP_FOLDER = dirname(dirname(__FILE__)) . "/flicklinkr";


  $js = new AssetCollection(array(
       // new GlobAsset($APP_FOLDER '/js/*'),
       new FileAsset($APP_FOLDER . '/js/plugins/jquery.logger.js'),
  ), array(
    new CompilerApiFilter()
  ));
 
  //the code is merged when the asset is dumped
  header("Content-Type: text/javascript");
  echo $js->dump();
?>

4.輸出結果

(function(a){a.console=function(a){"undefined"!=typeof window.console&&console.log(a)}})(jQuery);

[PHP] 安裝 composer套件


    記錄一下composer的安裝步驟

    安裝流程


  1. Change into a directory in your path like cd /usr/local/bin 
  2. Get Composersudo curl -sS https://getcomposer.org/installer | sudo php
  3. Make the phar executable sudo chmod a+x composer.phar 
  4. Change into a project directory cd /path/to/my/project 
  5. Use Composer as you normally would composer.phar install 
  6. Optionally you can rename the composer.phar to composer to make it easier
    1. sudo mv composer.phar composer

星期六, 7月 27, 2013

星期六, 7月 20, 2013

[Mac] 砍掉MAC網路磁碟產生的暫存檔"._"


掛載網路硬碟時,不小心把一些噁心的finder產生的暫存檔 ._ 丟到git上XD,
可參考這篇教學:How to remove all Mac "._" files from a Network Drive

可以透過find的指令把相關檔案找出來

$>find <路徑> -name "._*"

然後就會看到相關的暫存檔

要砍掉的話就加個 -delete 參數即可


$>find <路徑> -name "._*" -delete


好用的Effeckt css動畫效果


為了強調良好的UX,
透過一些動畫效果讓使用者清楚的知道頁面有哪些元素變動是非常重要的。現在除了Animation CSS之外又多了一個 Effeckt CSS,
可以適需求導入自已的專案中喔XD

http://h5bp.github.io/Effeckt.css/dist/


星期二, 7月 16, 2013

bootstrap

火紅很久的BootstrapUI框架,看來工程師要靠這個救一下自已了XD

英文
http://twitter.github.io/bootstrap/

繁體中文
http://kkbruce.tw/

星期一, 7月 15, 2013

[Java] Jersey 自動轉址

今天測試透過Jersey轉址到另一個下載連結,記錄一下操作方法。
主要透過Response.setOther這個方法就可以簡單達到,
不過要注意使用URI.create下載的連結時,
避免不合法的URI格式,可用URLEncode.encode解決。 
不過會遇到空白檔案下載變+號的編碼,記得取代一下+為%20即可

 (謎之聲:The URLEncoder implements the HTML Specifications for how to encode URLs in HTML forms.)。 URLEncoder.encode(obj_name).replace("+", "%20")

 如果炸掉可以將回傳結果轉換成json輸出,請看exception的程式範例

@GET
@Path("/download/{store_type}/{store_id}/{uuid}/{obj_name}")
public Response downloadObject(@Context HttpServletRequest request,
   @Context HttpServletResponse response,
   @PathParam(value = "store_type") String store_type,
   @PathParam(value = "store_id") String store_id,
   @PathParam(value = "uuid") String uuid,
   @PathParam(value = "obj_name") String obj_name,
   @QueryParam(value = "alf_ticket") String alf_ticket){
 
//...省略很多

String downloadlink = "http://test.jpg";
URI reidrectURI = null;
  
  try{
   
   reidrectURI = URI.create(downloadlink );
   
   return Response.seeOther(reidrectURI).build();
   
  }catch(IllegalArgumentException illaEx){
  
   illaEx.printStackTrace();
 JSONObject resp = new JSONObject();
   resp.put("statuscode", 500);
   resp.put("link", originalAlfDownloadLink);
  
   ResponseBuilder builder = 
     Response.status(Response.Status.INTERNAL_SERVER_ERROR).type(MediaType.APPLICATION_JSON);
   builder.entity(resp.toString());
   Response respBuilder = builder.build();
   
   return respBuilder;
  }
}

星期一, 7月 08, 2013

[Java] 監看誰呼叫了目前的程式

今天要找一個奇怪的bug,需要追踨整個Java Class呼叫的Stack

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace()
According to the Javadocs:
The last element of the array represents the bottom of the stack, which is the least recent method invocation in the sequence.
StackTraceElement has getClassName()getFileName()getLineNumber() andgetMethodName().
You will have to experiment to determine which index you want (probably stackTraceElements[1] or[2]).

星期三, 6月 26, 2013

[Java] 計算Concurrent User

客戶希望能看到網站目前的在線人數有哪些,
網路上大家都使用HttpSessionListener與HttpSessionBindingListener
二者的用法有點不一樣,但都可以達到一樣的效果。


細節的說明可以參考這篇:

這次的測試用HttpSessionBindingListener的示範:

星期四, 5月 30, 2013

[Javascript] 透過prototype的方法存取private member

記錄一下先前遇到的事情,
某一天在寫類別的時候,遇到想要用prototype去存取private member的成員,
就偷懶直接把private member改為public member XD,
查了一下Stackflow javascript - accessing private member variables from prototype-defined functions

No, there's no way to do it. That would essentially be scoping in reverse.
Methods defined inside the constructor have access to private variables because all functions have access to the scope in which they were defined.
Methods defined on a prototype are not defined within the scope of the constructor, and will not have access to the constructor's local variables.
You can still have private variables, but if you want methods defined on the prototype to have access to them, you should define getters and setters on the this object, which the prototype methods (along with everything else)will have access to.

function Dog(_dogName){
    var that = this;
    
    var dogname = _dogName || "dog" ;//default setting
  
    that._getName = function(){
       return dogname;
    };
    
    that._setName = function(newName){
         dogname = newName;
    };

};
//use getName to access private member
Dog.prototype.getName = function(){
    return  this._getName();
};
Dog.prototype.setName = function(newName){
    return  this._setName(newName);
};
    
var myDog = new Dog();
console.log("mydog:" + myDog.getName());

var tomDog = new Dog("tom");
console.log("tomDog:" + tomDog.getName());
tomDog.setName("mary");
console.log("tomDog2:" + tomDog.getName());


Fiddle看範例: Go

Reference:
Private Members in JavaScript

星期五, 5月 24, 2013

[jQuery plugins] 超激推 qtip plugin,讓錯誤訊息的位置不會撐爆XD

jquery validate是一個幾乎每個網站都會採用的外掛,
但是常常會因為錯誤訊息讓版面整個錯亂,
最近為了這個問題,找到了qtip2這個外掛,
強力的支援各種jquery plugin的tooptip外掛。

http://craigsworks.com/projects/qtip2/

為了方便使用就支接寫了一個擴充的方法,避免專案太多地方引用重覆的程式碼
原則上只是把範例的程式包起來而已...XD

//移除qtip2
 $.validator.prototype.qtipDestory = function(element){
      if( $(element).valid()){
       $(element).filter(".valid").qtip("destroy"); 
      }
    };
//顯示qtip2
$.validator.prototype.qtip = function(error,element,my,at){
  // Set positioning based on the elements position in the form
  var elem = $(element),  
  corners = ["right center", "bottom left"],
  flipIt = elem.parents("span.right").length > 0;

  if(my == "undefined" && at != "undefined"){
   corners = [my,at];
  }
  
  // Check we have a valid error message
  if(!error.is(":empty")) {
    // Apply the tooltip only if it isn"t valid
    elem.filter(":not(.valid)").qtip({
     overwrite: false,
     content: error,
     position: {
      my: corners[ flipIt ? 0 : 1 ],
      at: corners[ flipIt ? 1 : 0 ],
      viewport: $(window)
     },
     show: {
      event: false,
      ready: true
     },
     hide: false,
     style: {
      classes: "qtip-red" // Make it red... the classic error colour!
     }
    })

    // If we have a tooltip on this element already, just update its content
    .qtip("option", "content.text", error);
  } 
  // If the error is empty, remove the qTip
  else { elem.qtip("destroy"); }
 }

接著就照老樣子在errorPlacement補上一刀
...省略
errorPlacement:function(error,element){  
  $your_validated.qtip(error,element);
},
//驗證成功會把qtip消除
success:$.noop,

有時候你需要手動清除qtip(自已遇到關掉dialog要手動清除qtip)
//別忘了reset
$your_validated.resetForm();
$(".qtip").each(function(){
   $(this).data("qtip").destroy();
})

星期一, 5月 13, 2013

[Eclipse] bitbucket not authorized

先前把flicklinkr的原始碼改放在bitbucket,
今天要checkout的時候遇到not authorized錯誤
原來使用HTTPS將專案拉回的時候,要輸入你bitbucket上的帳號密碼XD

星期四, 5月 09, 2013

[jQuery Plugins] jquery form ajaxsubmit前修正欄位的名稱或值

jquery form是一個很常用的外掛,
能讓我們簡單做到ajax form的效果,
今天有一個需求想要在送出的時候多加一個欄位時該怎麼處理
只要在beforeSubmit的callback event下,
擴充form欄位的array就可以了。

參考stackoverflow
http://stackoverflow.com/questions/247284/modifying-form-values-with-beforesubmit-with-jquery-ajaxsubmit

範例如下

$(form).ajaxSubmit({
       url: apiEndpoint,
       type: "post",
//       data: postData,
       dataType:  "json", 
       beforeSubmit: function(arr, $form, options){
        

       //The array of form data takes the following form: 
       //$.console(arr);
       arr[arr.length] = { name:"draft", value:draft};
}
});

不過在測試multiform/data post的時候似乎不管用,殘念!!

[jQuery API] removeData 一直都拿不掉資料 WTF

今天發生一很怪的bug,想要用removeData移除先前暫存的資料一直移不掉(某些特別的key:user_jmeter-slave1-user1),如果像是簡單一點的ken,jack倒是沒問題。
想說是不是這個key,對$data方法會有bug發生。

結果寫了測試的方法也沒問題!!,範例如下

http://jsfiddle.net/e92s6/2/

但是在 瀏覽器下的console執行js code也不行。

最後發現jquery官方找到了另一條思路的解法(http://jsfiddle.net/rwaldron/AvqeW/9/),
就是再把資料設成null就好了

範例如下:
//清掉資料
$.data("your_key",null)

//判斷資料還存不存在,如果沒存過第一次是會找到undefined!!
var queryUserData = $.data("your_key",null)
if(typeof (queryUserData) == "undefined" || queryUserData == null){
      //做你要幹的事
  //.....
}



星期三, 5月 08, 2013

[Eclispe] 設定utf-8



開發專案前請記得請大家的環境統一設定UTF-8編碼,避免一些中文註解爆了XD
General/WorkSpace/Other: UTF-8


星期三, 4月 24, 2013

[jQuery plugin] 實作Shift + Click多選行為

如果要模擬window shift鍵多選的行為,可以參考以下這篇文章。
Snippet: Shift + Click List Items with jQuery
主要的邏輯是記錄最後一個選擇的項目
$parentNode.delegate("li","click",function(event){
    
    var $currLI = $(this);
   
    if($currLI.hasClass("select_this")){
     
     //unselected
     $.console("[UserList.render] delegate:unselected user");
     
     if(event.shiftKey){
      //just unselected
      $currLI.removeClass("select_this");
     }else{
      //re-locate last selected/unselected
      $currLI.removeClass("select_this");
      $currLI.addClass("last_selected");
      
      $lastSelected.removeClass("last_selected");
      
      //change last selected
      $lastSelected = $currLI;
     }
    }else{
     
     //selected 
     $.console("[UserList.render] delegate:selected user");
    
     //
     // SHIFT + CLICK
     //
     
     var $shiftSelected = [];//record seleted items by shfit key
     if(event.shiftKey){
      
      //shift + click logic 
      if($lastSelected.length > 0){//first click
       
       if($lastSelected == $currLI){
        $.console("[UserList.render] same selection");
        
        return false;
        
       }else{
        
        //detect foward or back
        direction = $currLI.nextAll(".last_selected").length > 0 ? "forward" : "back";
        $.console("[UserList.render] last_selected count:" + $currLI.nextAll(".last_selected").length);
        $.console("[UserList.render] direction:" + direction);
        
        if(direction == "forward"){
         $shiftSelected = $currLI.nextUntil($lastSelected);
        }else{
         //back
         $shiftSelected = $lastSelected.nextUntil($currLI);
        }
        
//        $.console("$shiftSelected:" + $shiftSelected.length);
        $LICollection.removeClass("select_this");//reset pre selected
        
        //final selected items
        $shiftSelected.addClass("select_this");//highlight shift selected
        $lastSelected.addClass("select_this");//highlight last selected
                 $currLI.addClass("select_this");//highlight current selected
                 
       }
       
      }else{
       
       $lastSelected = $currLI;
       $currLI.addClass("select_this last_selected");
      }
      
     }else{
      
      //record last selected
      $lastSelected = $currLI;
      $currLI.addClass("select_this last_selected");
  
     }
     
    }
    
    //for debug
//    $.console("lastselected username:" + $lastSelected.find(".usr_name").html());
    
    if(userlist.selecteEventHandler && typeof(userlist.selecteEventHandler) === "function"){
     userlist.selecteEventHandler($currLI,userlist.getSelectedItems());
    }
   });

星期五, 4月 19, 2013

[jQuery API] append加上fadeIn的效果

今天要遇到想要在append新元素時,加入fadein的效果。
筆記一下..
//userElem為html tag
$(userElem).hide().appendTo($parentNode).fadeIn(1000);

星期日, 4月 14, 2013

[Alfresco] 如何取得webscript的參數

這篇記錄如何從webscript取得QueryString、Path parameter of URL與Post body

QueryString
<url>/people/search/email?filter={email}</url>
function main()
{
   var filter = args["filter"];
}


Path parameter
<url>/person/{userName}</url>
function main()
{
   // Get the user name of the person to get
   var userName = url.extension;
}

Post Body
function main(){
 
//invalid input
if(!json.has("users")){
    status.setCode(status.STATUS_BAD_REQUEST, "The request body format is error.");
    return;
}

var usersIndex ;
var users = json.get("users");//json array
for (usersIndex = 0; usersIndex < users.length(); usersIndex++){
 //Get user val 
 var currentUser = users.get(usersIndex);
    

}

其他補充

url

A host object providing access to the URL (or parts of the URL) that triggered the web script.
context
Alfresco context path, for example /alfresco
serviceContext
Alfresco service context path, for example /alfresco/service
service
Web script path, for example /alfresco/service/blog/search
full
Web script URL, for example /alfresco/service/blog/search?q=tutorial
templateArgs
a map of substituted token values (within the URI path) indexed by token name
args
Web script URL arguments, for example q=tutorial
match
The part of the web script URL that matched the web script URL template
extension
The part of the web script URL that extends beyond the match path (if there is no extension, an empty string is returned)

For example, imagine a web script URL template of
/user/{userid}
and a web script request URL of
/alfresco/service/user/fred?profile=full&format=html
The url root object will respond as follows:
  • url.context => /alfresco
  • url.serviceContext => /alfresco/service
  • url.service => /alfresco/service/user/fred
  • url.full => /alfresco/service/user/fred?profile=full&format=html
  • url.args => profile=full&format=html
  • url.templateArgs['userid'] => fred
  • url.match => /user/
  • url.extension => fred
Reference:
http://wiki.alfresco.com/wiki/Web_Scripts_Examples#URL_Argument_Handling

其他你感興趣的文章

Related Posts with Thumbnails