星期日, 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