2016年3月17日 星期四

Javascript Sort

有時需要在前端進行排序時,可透過String.localeCompare()來進行比對。

var v1 "abc";
var v2 "def";
console.log(v1.localeCompare(v2));// -1
console.log(v2.localeCompare(v1));// 1
console.log(v1.localeCompare(v1));// 0

所以當有一個ObjectArray需要進行排序時,可寫成如下

var objectAry = [
    {userName:'John Doe',age:20}
    ,{userName:'Peter Hancock',age:42}
    ,{userName:'May J.',age:16}
   ];
var compareAttr 'userName';
    objectAry.sort(function (o1,o2) {
    return o1[compareAttr].localeCompare(o2[compareAttr]);
    }).forEach(function(row,index){
    console.log("row:" + index, row);
    });
 
row:0 Object {userName: "John Doe", age: 20}
row:1 Object {userName: "May J.", age: 16}
row:2 Object {userName: "Peter Hancock", age: 42}

由於localeCompare只有String才有,所以若直接用Number的資料以localeCompare的方式排序會出現錯誤。

compareAttr 'age';
    objectAry.sort(function (o1,o2) {
    return o1[compareAttr].localeCompare(o2[compareAttr]);
    }).forEach(function(row,index){
    console.log("row:" + index, row);
    });

Uncaught TypeErroro1[compareAttr].localeCompare is not a function

所以可透過prototype的方式將Number資料型態增加localeComparefunction來處理。

Number.prototype.localeCompare = function (compare) {
    if (isNaN(compare)) {//用於資料為String and Number混合比對的時候
        
return (this + "").localeCompare(compare);
    } else if (this > compare) {
        return 1;
    } else if (this < compare) {
        return -1;
    } else {
        return 0;
    }
    };
 
再次執行
 
compareAttr 'age';
    objectAry.sort(function (o1,o2) {
    return o1[compareAttr].localeCompare(o2[compareAttr]);
    }).forEach(function(row,index){
    console.log("row:" + index, row);
    });

row:0 Object {userName: "May J.", age: 16}
row:1 Object {userName: "John Doe", age: 20}
row:2 Object {userName: "Peter Hancock", age: 42}

Javascript Number

蒐集整理一下最近用Javascript計算數字的心得,以免日後每次用都要重新再搞一次….orz

·   Javascript浮點數計算

由於浮點數的誤差(詳細請參閱),因此簡單的數學計算常會在Javascript出現出乎意料之外的結果。

var n1 0.1;
var n2 0.2;
console.log(n1 n2);//0.30000000000000004
console.log(n1 n2);//0.020000000000000004
console.log(n1 n2);//0.5
console.log(n1 n2);//-0.1

0.30000000000000004
0.020000000000000004
0.5
-0.1


因此建議不要透過javascript來進行運算,或透過javascriptlibmathjs來使用。
但若只是單純的運算,不涉及一些重要資訊如金錢或有嚴重影響的資訊,也不想再額外包入相關的javascript lib,則可透過簡單的使用方式如下。

console.log(Math.round((n1 n2) * 100) / 100);
console.log(Math.round((n1 n2) * 100) / 100);
console.log(Math.round((n1 n2) * 100) / 100);
console.log(Math.round((n1 n2) * 100) / 100);

0.3
0.02
0.5
-0.1

或是增加一個Numberprototype function如下

Number.prototype.toCorrectFloat function () {
    return Math.round(this 100) / 100;
};

console.log((n1 n2).toCorrectFloat());
console.log((n1 n2).toCorrectFloat());
console.log((n1 n2).toCorrectFloat());
console.log((n1 n2).toCorrectFloat());

0.3
0.02
0.5
-0.1


· Javascript科學符號  toExponential(x)

將數字以科學符號表示,並取小數點後x字數,不足的字數以0補上。(無條件捨去)

console.log((0.00011235).toExponential());//1.1235e-4console.log((0.00011235).toExponential(3));//1.123e-4console.log((0.00011235).toExponential(7));//1.1235000e-4

· Javascript Number Format  toPrecision(x)

大於0則會取x字數(包含0不含小數點且無條件捨去)

console.log((1.0025).toPrecision(2));//1.0
console.log((1.0025).toPrecision(4));//1.003

大於0且字數大於x則會變為科學記號並只取由前數來共x數字(四捨五入)

console.log((9861.0001).toPrecision(2));//9.9e+3
console.log((9841.0001).toPrecision(2));//9.8e+3
console.log((9811.0001).toPrecision(6));//9811.00

小於0則取小數點第一個非0的數字後x字數(四捨五入)

console.log((0.00011634).toPrecision(1));//0.0001
console.log((0.00011634).toPrecision(2));//0.00012
console.log((0.00011634).toPrecision(3));//0.000116

·Javascript Number Format  toFixed(x)

取小數點後x字數(四捨五入),不足的字數量會以0補上

console.log((0.00011634).toFixed(1));//0.0001
console.log((13333.00511634).toFixed(2));//13333.01
console.log((0.103).toFixed(6));//0.103000

2016年1月12日 星期二

Ajax上傳檔案Sample

早期的瀏覽器並不支援透過Ajax上傳檔案的作法,因此常都需要透過Flash的元件來做到一些有互動性的檔案上傳。

在瀏覽器開始支援後(對,我就是說IE!)Ajax上傳檔案的作法才開始應用,所以需要注意瀏覽器的版本。

瀏覽器版本資訊

IE
FIREFOX
CHROME
SAFARI
OPERA
10.0+
4.0+
7.0+
5+
12+


Sample Code


<!-- HTML -->

<input type='file' name='upload' id='file-select' />

<!-- Javascript -->

<script>

    var fileSelect = document.getElementById('file-select');

    // Get the selected files from the input.

    var files = fileSelect.files;//It’s an array.

    // Create a new FormData object.

    var formData = new FormData();

    // Loop through each of the selected files.

    for (var i = 0; i < files.length; i++) {
        var file = files[i];
        // Check the file type.可利用type屬性篩選,這裡只取圖片
        if (!file.type.match('image.*')) {
            continue;
        }

        // Add the file to the request.這裡的第一個參數等於QueryStringname,第二個參數等於Value
        formData.append('upload', file, file.name);

    }

    //接著可透過JQuery或是自己弄個XMLHttpRequest的方式Send Form

    //JQuery
    $.ajax({
        url: '/WebApp/uploadFile.action',//php,jsp and etc..
         type: 'POST',
        data: formdata,
        cache: false,
        dataType: 'json',
        processData: false, // Don't process the files
        contentType: false, // Set content type to false as jQuery will tell the server its a query string request
        success: function(data, textStatus, jqXHR) {
            // Handle errors here
            console.log('Success: ' + textStatus);
            //STOP LOADING SPINNER

        },

        error: function(jqXHR, textStatus, errorThrown) {
            // Handle errors here
            console.log('Errors: ' + textStatus);
            // STOP LOADING SPINNER
        }

    });



    //XMLHttpRequest
    // Set up the request.
    var xhr = new XMLHttpRequest();

    // Open the connection.
    xhr.open('POST', 'handler.php', true);

    // Set up a handler for when the request finishes.
    xhr.onload = function () {

        if (xhr.status === 200) {
            // File(s) uploaded.
             //uploadButton.innerHTML = 'Upload';
            alert('Upload Success!');
        } else {             alert('An error occurred!');         }     };     // Send the Data.     xhr.send(formData); </script>


參考資料


2016年1月10日 星期日

檢查文字檔案編碼

最近做了針對純文字檔案(.txt)的Parse工作,由於取得的txt檔案有可能是utf-16編碼

因此若用一般IO方式讀檔案

new BufferedReader(fileReader);

會出現多餘的空白導致判斷有問題,因此需要先判斷檔案的格式是什麼再改成

new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-16"));

以下是找到的java lib Sample Code,做個紀錄...

https://code.google.com/p/juniversalchardet/

import org.mozilla.universalchardet.UniversalDetector;
public class TestDetector {
  public static void main(String[] args) throws java.io.IOException {
    byte[] buf = new byte[4096];
    String fileName = args[0];
    java.io.FileInputStream fis = new java.io.FileInputStream(fileName);

    // (1)
    UniversalDetector detector = new UniversalDetector(null);

    // (2)
    int nread;
    while ((nread = fis.read(buf)) > 0 && !detector.isDone()) {
      detector.handleData(buf, 0, nread);
    }
    // (3)
    detector.dataEnd();

    // (4)
    String encoding = detector.getDetectedCharset();
    if (encoding != null) {
      System.out.println("Detected encoding = " + encoding);
    } else {
      System.out.println("No encoding detected.");
    }

    // (5)
    detector.reset();
  }
}


2015年12月31日 星期四

CSS省略文字及JavaScript判斷是否有省略

有時候為了版面美觀,會將過長的文字敘述隱藏而使用ToolTip的方式顯示,但當文字並沒有被隱藏卻顯示ToolTip則顯得有點多餘,因此分享以下的判斷方式做為參考。

<style>
   
table{
       
margin: 1em;
    }
    .
row div {
       
padding: 5px;
    }
   
/** 透過CSS設定將長度大於100px的內容隱藏 **/
   
.shortern div{
       
width: 100px;
       
overflow: hidden;
       
text-overflow: ellipsis;
       
white-space: nowrap;
    }
    .
tip{
       
background: black;
       
color: white;
       
font-weight: bold;
       
padding: 5px;
    }
</
style>

<div class="row">

    <table class="shortern" border="1">

        <tr>

            <td>

                <div>Something is very looooong</div>

            </td>

        </tr>

        <tr>

            <td>

                <div>Short</div>

            </td>

        </tr>

    </table>

</div>

<div class="row tip" style="position: absolute">

    <!--I am tooltip;-->

</div>


<script>

    $(document).ready(function(){

        var $tooltip=$(".tip");

        $tooltip.hide();

        $("table div").hover(function(e){

            var targetEle = e.target;

            var $target = $(targetEle);

            /**

             * 判斷ElementscrollWidth是否大於offsetWidth

             * 較大則代表有被隱藏的文字

             * **/

            if(targetEle.scrollWidth > targetEle.offsetWidth){

                var offset = $target.offset();

                offset.left = offset.left + $(targetEle).parent().width() + 30;

                offset.top = offset.top;

                $tooltip.css(offset);

                $tooltip.text($(this).text());

                $tooltip.show();

            }

        },function(e){

            $tooltip.hide();

        })

    });

</script>