2016年10月24日 星期一

Context 的 openFileOutput/openFileInput、SharedPreferences (Android)

※Context的openFileOutput/openFileInput

從data/data/com.example~~~/files資料夾裡,讀或寫
其中com.example~~~是getApplicationContext().getPackageName()


※strings.xml

<resources>
    <string name="login_practice">登入練習</string>
    <string name="enter_account">請輸入帳號</string>
    <string name="enter_password">請輸入密碼</string>
    <string name="remember_account_and_password">記住帳號密碼</string>
    <string name="login">登錄</string>
    <string name="account_and_password_require">帳號密碼必須輸入</string>
</resources>

※需要用到的字串,集中在這個檔案管理


※activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.bruce_java.myapplication.MainActivity">
    
    <EditText
        android:id="@+id/account"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/enter_account"
        android:layout_marginTop="80dp"/>
    
    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword"
        android:hint="@string/enter_password"
        android:layout_marginBottom="10dp"/>
    
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <CheckBox
            android:id="@+id/cb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/remember_account_and_password"
            android:layout_alignParentLeft="true"/>
    
        <Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/login"
            android:layout_alignParentRight="true"
            android:onClick="login"/>
    </RelativeLayout>
</LinearLayout>

※模擬一個登入頁面


※AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bruce_java.myapplication20161022">
    
    <!--<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>-->
    <!--<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>-->
    
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/login_practice"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivityButton">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

※注意android:label本來是@string/app_name,我改了,要對應到strings.xml

※如果需要加權限,就打開註解的部分,當然還有很多


※MainActivity.java

public class MainActivity extends AppCompatActivity {
    EditText accText = null;
    EditText passText = null;
    CheckBox cb = null;
    final String fileName = "login.txt";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_button);
    
        accText = (EditText) findViewById(R.id.account);
        passText = (EditText) findViewById(R.id.password);
        cb = (CheckBox) findViewById(R.id.cb);
    
        Map<String, String> map = this.readAccountAndPassword();
        if (!map.isEmpty()) {
            accText.setText(map.get("account"));
            passText.setText(map.get("password"));
            cb.setChecked(true);
        } else {
            cb.setChecked(false);
        }
    }
    
    private Map<String, String> readAccountAndPassword() {
        Map<String, String> map = new HashMap<>();
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(super.getApplicationContext().openFileInput(fileName)));
            map.put("account", in.readLine());
            map.put("password", in.readLine());
        } catch (FileNotFoundException fnfe) {
            fnfe.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return map;
    }
    
    public void login(View view){
        String account = accText.getText().toString().trim();
        String password = passText.getText().toString().trim();
    
        if(TextUtils.isEmpty(account) || TextUtils.isEmpty(password)){
            Toast.makeText(getApplicationContext(), R.string.account_and_password_require, Toast.LENGTH_SHORT).show();
            return;
        } else {
            if(cb.isChecked()) {
                OutputStream out = null;
                try {
                    //data/data/com.example~~~/files
                    out = super.getApplicationContext().openFileOutput(fileName, super.MODE_PRIVATE);
                    out.write((account + "\r\n" + password).getBytes());
                } catch (FileNotFoundException fnfe) {
                    fnfe.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (out != null) {
                            out.close();
                            Toast.makeText(getApplicationContext(), "已儲存帳號和密碼", Toast.LENGTH_SHORT).show();
                        }
                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                    }
                }
            }
        }
    }
}

※MODE_PRIVATE會寫入檔案,如果發現已有檔案會覆蓋,
如果改成MODE_APPEND,會附加資料在最後面

※readAccountAndPassword方法是讀;login方法是寫



※SharedPreferences 讀寫XML

從data/data/com.example~~~/shared_prefs資料夾裡,讀或寫
會自動加副檔名xml(不管你有沒有加xml,都會在後面多個.xml)
只有MainActivity.java和openFileOutput/openFileInput不一樣

※MainActivity.java

public class MainActivity extends AppCompatActivity {
    EditText accText = null;
    EditText passText = null;
    CheckBox cb = null;
    final String fileName = "login";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_button);
    
        accText = (EditText) findViewById(R.id.account);
        passText = (EditText) findViewById(R.id.password);
        cb = (CheckBox) findViewById(R.id.cb);
    
        Map<String, String> map = this.readAccountAndPassword();
        if (map.get("account") != null && map.get("password") != null) {
            accText.setText(map.get("account"));
            passText.setText(map.get("password"));
            cb.setChecked(true);
        } else {
            cb.setChecked(false);
        }
    }
    
    public void login(View view){
        String account = accText.getText().toString().trim();
        String password = passText.getText().toString().trim();
    
        if(TextUtils.isEmpty(account) || TextUtils.isEmpty(password)){
            Toast.makeText(getApplicationContext(), R.string.account_and_password_require, Toast.LENGTH_SHORT).show();
            return;
        } else {
            if(cb.isChecked()) {
                // data/data/com.example~~~/shared_prefs/login.xml
                // fileName後會自動加副檔名xml
                SharedPreferences sp = super.getSharedPreferences(fileName, super.MODE_PRIVATE);
                SharedPreferences.Editor editor = sp.edit();
                editor.putString("account", account);
                editor.putString("password", password);
                editor.commit();
                Toast.makeText(getApplicationContext(), "已儲存帳號和密碼", Toast.LENGTH_SHORT).show();
            }
        }
    }
    
    private Map<String, String> readAccountAndPassword() {
        Map<String, String> map = new HashMap<>();
        SharedPreferences sp = super.getSharedPreferences(fileName, super.MODE_PRIVATE);
        // 第二個參數是取不到時的預設值
        map.put("account", sp.getString("account", null));
        map.put("password", sp.getString("password", null));
        return map;
    }
}

※readAccountAndPassword方法是讀;login方法是寫

2016年10月23日 星期日

Button的兩種方式 (Android)

官網連結
有兩種方式可以使按鈕起作用,View.OnClickListener 和 XML layout,其中View.OnClickListener有三種方法


※一、View.OnClickListener

※activity_main.xml

<Button
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test button"/>

※View.OnClickListener的三種方法都是用這個xml


※1.MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_button);
    
        Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new MyOnClickListener());
    }
    
    private class MyOnClickListener implements View.OnClickListener{
        @Override
        public void onClick(View v) {
            Toast.makeText(getApplicationContext(), "extends Listener button", Toast.LENGTH_SHORT).show();
        }
    }
}

※寫一支class繼承View.OnClickListener,然後實作onClick方法


※2.MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_button);
    
        Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Toast.makeText(getApplicationContext(), "Listener button", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

※和第一種方法一樣,只是變成匿名類別


※3.MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_button);
    
        Button btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(this);
    }
    
    @Override
    public void onClick(View view) {
        Toast.makeText(getApplicationContext(), "class Listener button", Toast.LENGTH_SHORT).show();
    }
}

※不寫class繼承View.OnClickListener,直接繼承View.OnClickListener,一樣實作onClick方法



※二、XML layout 

這種方式是用設定的方式來達成,較常用


※activity_main.xml

<Button
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="test button"
    android:onClick="xxx"/>

※xxx是要實限的方法名稱,當然也可以叫onClick


※MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_button);
    }
    
    public void xxx(View view) {
        Button btn = (Button) view;
        String[] display = {"別按我", "按屁啊", "按一次五元", "誰叫你亂按的", "林老師咧"};
        btn.setText(display[(int) (Math.random() * display.length)]);
        Toast.makeText(getApplicationContext(), "setting button", Toast.LENGTH_SHORT).show();
    }
}

※官網有說要public,而且要有View參數,表示自己的這一個按鈕

2016年10月21日 星期五

公用:proxy (jQuery31)

※proxy

代理事件的東西
有四種方式


※第一個參數是functon,第二個參數是context(物件)

$(function(){
    var me = {
        type: "me",
        test: function(event) {
            $(event.target).css("background-color", "red");
            $("div").append(this.type + "<br>" );
            $("button").unbind("click", this.test);
        }
    };
    
    var you = {
        type: "you",
        test: function(event) {
            $("div").append(this.type + " ");
        }
    };
    
    $("button")
        .on("click", $.proxy(me.test, me)) // 只執行一次,因為被unbind了
        .on("click", $.proxy(you.test, you)) // you-->都是自己的,很好理解
        .on("click", $.proxy(you.test, me)) // me-->右邊是me,type抓的是me的
        .on("click", you.test); // button-->按鈕的type
});
----------
<button type="button">Test</button>
<div></div>

※


※第一個參數是context(物件),第二個參數是string

$(function(){
    var obj = {
        name: "John",
        xxx: function() {
            $("p").append(this.name);
            $("button").off("click", obj.test);
        }
    };
    
    $("button").on("click", $.proxy(obj, "xxx"));
});
----------
<button>Test</button>
<p></p>

※第二個參數要對應到第一個參數物件裡的名字才有效



※其他方式

第三種和第四種方式是給第三個參數(可以給很多,類似java的「…」),是給第二個參數用的
這裡以第二個參數是物件為例
$(function(){
    var me = {
        type: "dog",
        test: function(one, two, event) {
            $("p")
                .append(one.type + '<br />') // cat
                .append(two.type + '<br />') // fish
                .append(event.type + '<br />') // click
                .append(this.type + '<br />') // dog
                .append(event.target.type + '<br />'); // submit
        }
    };
    
    var you = {type: "cat"};
    var they = {type: "fish"};
    $("button").on("click", $.proxy(me.test, me, you, they));
});
----------
<button>Test</button>
<p></p>

※event.target.type 這個我不懂

公用:grep、contains、merge、map、noop、now、trim、type、unique (jQuery30)

※grep

$(function(){
    var rtn = $.grep([1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1], function(element, index){
        console.log(index + '=' + element);
        return (element != 5 && index > 4);
    },false);
    alert(rtn);
    // 第三個參數是false或不給,結果為 6,7,8,9,8,7,6,4,3,2,1
    // 第三個參數是true,結果為 1,2,3,4,5,5 也就是上一行的相反
    
    var rtn = $.grep([{'a':1, 'b':2}, {'c':3, 'd':4}, 'e', 5], function(element, index){
        console.log('index=' + index);
        if($.isPlainObject(element)){
            for(e in element){
                console.log(e); // a b c d
            }
        } else {
            console.log(element); // e 5
        }
    });
});

※過濾陣列用的,如果過濾物件不會出錯,但好像沒有執行一樣



※contains

$(function(){
    console.log($.contains(document.documentElement, document.body)); // true
    console.log($.contains(document.body, document.documentElement)); // false
    console.log($.contains(document.getElementsByTagName("div"), document.getElementsByTagName("span"))); // false
});
----------
<div>
    <span></span>
</div>

※右邊的參數是否被左邊的參數包括,這個我不太懂



※merge

$(function(){
    console.log($.merge([0,1,2], [2,3,4])); // [0, 1, 2, 2, 3, 4]
    console.log($.merge([], [2,3,4] ));  // [2, 3, 4]
    console.log($.merge($.merge([0,1,2], [2,3,4]), [4,5,6])); // [0, 1, 2, 2, 3, 4, 4, 5, 6]
    
    var test = $.merge([0,{1:function(){return 'x'}},{2:'two'}], [{2:'owt'},3,{1:function(){return 'o'}}]);
    for(t in test){
        if($.isPlainObject(test[t])){
            for(tt in test[t]){
                console.log(test[t][tt]);
            }
        } else {
            console.log(test[t]); 
        }
    }
});

※將兩個陣列合併



※map

$.map(['a','b','c'], function(val, index) {
    console.log('val=' + val); // a b c
    console.log('index=' + index); // 0 1 2
});
    
$.map({'a':1,'b':2,'c':3}, function(val, index) {
    console.log('val=' + val); // 1 2 3
    console.log('index=' + index); // a b c
});

※用法和each一樣



※noop、now、trim

console.log($.noop);// function(){}
console.log($.noop()); // undefined
console.log($.now); // function(){return (new Date()).getTime();}
console.log($.now()); // long的數字
    
var $trim = $.trim('  1 2 3  ');
console.log($trim); // 1 2 3
console.log($trim.length); // 5

※



※type

console.log($.type()); // undefined
console.log($.type(undefined)); // undefined
console.log($.type(window)); // object
console.log($.type(null)); // null
    
console.log('----------');
console.log($.type(true)); // boolean
console.log($.type(3)); // number
console.log($.type("test")); // string
console.log($.type(function(){} )); // function
console.log($.type([])); // array
    
console.log('----------');
console.log($.type({})); // object
console.log($.type(new Date())); // date
console.log($.type(new Error())); // error
console.log($.type(/test/)); // regexp

※



※unique

$(function(){
    var divs = $("div").get();
    console.log(divs.length); // 5
    console.log($.unique(divs).length); // 5
    
    divs = divs.concat($(".d").get());
    console.log(divs.length); // 7
    var xxx = $.unique(divs);
    console.log(xxx.length); // 5
    
    $('input[type="button"]').one('click', function(){
        $('p').append(xxx);
    });
});
----------
<div>d1</div>
<div class="d">d2</div>
<div>d3</div>
<div class="d">d4</div>
<div>d5</div>
<input type="button" value="click me"/>
<p>p</p>

※

2016年10月20日 星期四

公用:globalEval、makeArray、inArray (jQuery29)

※globalEval、eval 的差異

和javascript的eval很像,但是全域的

$(function(){
    test();
});
    
function test(){
    $.globalEval('var xxx = 2;');
    eval('var ooo = 3;');
    console.log('init xxx=' + xxx);
    console.log('init ooo=' + ooo);
}
    
function after(){
    console.log('after xxx=' + xxx);
    // console.log('after ooo=' + ooo); // 執行時錯誤
}
----------
<input type="button" value="click me" onclick="after()" />

※註解那行打開會發生錯誤,因為並不是全域的



※makeArray

故名思義,就是用來產生陣列的

$(function(){
    var arr = $.makeArray($('span'));
    // alert(arr[0].childNodes[0].data);
    // debugger;
    $.each(arr, function(i, v){
        console.log('v=' + v.childNodes[0].data); // s1-->s2
    });
});
----------
<span>s1</span>
<div>d1</div>
<span>s2</span>
<div>d2</div>



※makeArray 使用多層時

$(function(){
    $.each($.makeArray($('li')).reverse(), function(i, v){
        console.log('v=' + v.childNodes[0].data); // s1-->s2
    });
});
----------
<ul>
    U1
    <li>L1</li>
    <li>L2</li>
    <li>
        L3
        <ul>
            U2
            <li>L4</li>
            <li>L5</li>
        </ul>
    </li>
</ul>

※結果如以下畫面


※會發現L3前後都空很大,這是因為HTML有換行的關係,改成以下就不會了

<ul>
    U1
    <li>L1</li>
    <li>L2</li>
    <li>L3<ul>
            U2
            <li>L4</li>
            <li>L5</li>
        </ul>
    </li>
</ul>



※inArray、indexOf 的差異

var str = "abc cba array abc cba";
console.log($.inArray("b", str)); // 1
console.log($.inArray("b", str, 5)); // 5
console.log($.inArray("b", str, -8)); // 15
console.log($.inArray("x", str)); // -1
    
console.log(str.indexOf('b')); // 1
console.log(str.indexOf('b', 5)); // 5
console.log(str.indexOf('b', -8)); // 1
console.log(str.indexOf('x')); // -1
    
console.log($.inArray("ab", str)); // -1
console.log($.inArray("ab", str, 5)); // -1
console.log($.inArray("ab", str, -8)); // -1
    
console.log(str.indexOf('ab')); // 0
console.log(str.indexOf('ab', 5)); // 14
console.log(str.indexOf('ab', -8)); // 0
    
console.log($.inArray("abc", str)); // -1
console.log($.inArray("abc", str, 5)); // -1
console.log($.inArray("abc", str, -8)); // -1
    
console.log(str.indexOf('abc')); // 0
console.log(str.indexOf('abc', 5)); // 14
console.log(str.indexOf('abc', -8)); // 0
    
console.log($.inArray("John", [ 4, "Pete", 8, "John" ])); // 3
console.log($.inArray("Joh", [ 4, "Pete", 8, "John" ])); // -1
    
console.log([ 4, "Pete", 8, "John" ].indexOf("John")); // 3
console.log([ 4, "Pete", 8, "John" ].indexOf("Joh")); // -1

※inArray可以有第三個參數,沒有寫預設是0,表示從第一個字開始找

※用在搜尋字串且找一個字時:相同的地方是
使用正數時,還有找不到時都是-1,只有負數不同

※搜尋兩個字或一個單字時,inArray都是-1,也就是不支援;但indexOf有支援

※搜尋陣列時,inArray和indexOf都一樣

公用:each、isXXX、parseXXX (jQuery28)

※$.each 

就是迴圈

$(function(){
    $.each(['a', 'b', 'c'], function(i, v){
        console.log('i=' + i);
        console.log('v=' + v);
    });
    //0 a-->1 b-->2 c
    
    $.each({'a':'one', 'b':'two', 'c':'three'}, function(i, v){
        console.log('i=' + i);
        console.log('v=' + v);
    });
    //a one-->b two-->c three
    
    $.each({'a':{a1:1}, 'b':'two', 'c':{c3:3}}, function(i, v){
        console.log('i=' + i);
        if($.isPlainObject(v)){
            for(vc in v){
                console.log('vc=' + vc);
                console.log('v[vc]=' + v[vc]);
            }
        } else {
            console.log('v=' + v);
        }
    });
    // a a1 1-->b two-->c c3 3
});

※如果只有value,那第一個參數就是index



※$.isXXX 

isXXX都是判斷用的方法,目前有以下七種

1.$.isArray():是否是陣列
2.$.isEmptyObject():是否是空物件
3.$.isFunction():是否是function
4.$.isNumeric():是否是數字
5.$.isPlainObject():是否是物件
6.$.isWindow():是否是window物件
7.$.isXMLDoc():是否是XML文件



※isPlainObject、isArray、isEmptyObject

console.log($.isPlainObject({a:1, b:2})); // true
console.log($.isPlainObject([1,2,3])); // false
console.log($.isPlainObject({})); // true
console.log($.isPlainObject([])); // false
console.log($.isPlainObject({a:[4,5,6], b:[7,8,9]})); // true
console.log($.isPlainObject([{c:3}, {d:4}])); // false
console.log($.isPlainObject(function(){})); // false
    
console.log($.isArray({a:1, b:2})); // false
console.log($.isArray([1,2,3])); // true
console.log($.isArray({})); // false
console.log($.isArray([])); // true
console.log($.isArray({a:[4,5,6], b:[7,8,9]})); // false
console.log($.isArray([{c:3}, {d:4}])); // true
console.log($.isArray(function(){})); // false
    
console.log($.isEmptyObject('')); // true
console.log($.isEmptyObject("")); // true
console.log($.isEmptyObject({})); // true
console.log($.isEmptyObject([])); // true
console.log($.isEmptyObject(function(p){})); // true
console.log($.isEmptyObject(function(){var a = 5; return a + 5})); // true

※{}就是物件;[]就是陣列

※要注意判斷空物件時的function,裡面明明有東西,但還是true



※isFunction

function aFunction(){}
var bFunction = function(){}
var cFunction = new Function();
// var dFunction = (x) => {}
    
console.log($.isFunction(aFunction)); // true
console.log($.isFunction(bFunction)); // true
console.log($.isFunction(cFunction)); // true
// console.log($.isFunction(dFunction)); // true
console.log($.isFunction(function(){})); // true

※注解的部分是IE不支援



※isNumeric、isWindow

console.log($.isNumeric(+10)); // true
console.log($.isNumeric("-10")); // true
console.log($.isNumeric(0144)); // true 
console.log($.isNumeric(0xFF)); // true
console.log($.isNumeric("0xFF")); // true
console.log($.isNumeric("8e5")); // true
console.log($.isNumeric(3.1415)); // true
    
console.log($.isWindow(window)); // true
console.log($.isWindow(document)); // false

※注意判斷數字時,其他進位也有支援



※isXMLDoc、parseXML

console.log($.isXMLDoc('<xxx></xxx>')); // false
console.log($.isXMLDoc($.parseXML('<xxx></xxx>'))); // true
console.log($.isXMLDoc($.parseXML('<xxx />'))); // true

※經過parseXML後,才是XML,就算字串裡有加xml第一行的version1.0之類的結果也是一樣,反正裡面就是字串



※parseXXX

目前有三種
1. parseXML:轉成XML,上個範例已有,以下就不寫了
2.parseJSON:轉成JSON
3.parseHTML:轉成HTML


※parseJSON

// alert($.parseJSON('{a:1}').a); // 執行時錯誤
// alert($.parseJSON("{'a':1}").a); // 執行時錯誤
alert($.parseJSON('{"a":1}').a); // 1
// alert($.parseJSON('["a":1]').a); // 執行時錯誤
// alert($.parseJSON('{"a":"1\t2"}').a); // 執行時錯誤
alert($.parseJSON(null)); //null
alert($.parseJSON(undefined)); // 1.9之前null,之後執行時錯誤

※只有雙引號才可以,其他就只有null不會報錯


※parseHTML

<div id="log" />
----------
var html = $.parseHTML("hello, <b>my name is</b> jQuery.");
$("#log").append(html);
    
$.each(html, function(i, v) {
    console.log(i); // 0-->1-->2
    console.log(v); // hello,--><b>my name is</b>-->jQuery.
    console.log('-----');
});

※append時,轉不轉成HTML都可以,但如果不轉成HTML,用each會執行錯誤

※還有第二、三個參數可用,我沒研究

2016年10月13日 星期四

幫助方法、全域Ajax事件處理器 (jQuery25)

官網連結

※幫助方法

就是serialize和 serializeArray
serialize可將form變成字串的形式
serializeArray可將form變成name、value的形式,回傳JSON物件(不是JSON字串),

<form action="xxx/ooo" method="post">
    使用者:
    <input type="text" name="username" value="user" /><br />
    密碼:
    <input type="password" name="password" value="pass" /><br />
    
    <input type="radio" name="ra" value="r1" />
    <input type="radio" name="ra" value="r2" />
    <input type="radio" name="ra" value="r3" checked="checked" /><br />
    
    <input type="checkbox" name="ch" value="c1" checked="checked" />
    <input type="checkbox" name="ch" value="c2" checked="checked" />
    <input type="checkbox" name="ch" value="c3" /><br />
    
    <select name="se">
        <option>s1</option>
        <option selected="selected">s2</option>
        <option>s3</option>
    </select>
    <br />
    
    <input type="button" value="serialize" onclick="serialize()" /><br />
    <input type="button" value="serializeArray" onclick="serializeArray()" /><br />
</form>
    
<span id="span1"></span><br />
<span id="span2"></span>
-----
$(function(){
    $('#span1').text($("form").serialize());
    console.log($("form").serialize()); // username=user&password=pass&ra=r3&ch=c1&ch=c2&se=s2
    
    $('#span2').text($("form").serializeArray());
    console.log($("form").serializeArray()); // [Object, Object, Object, Object, Object, Object]
    
    $.each($("form").serializeArray(), function(i, f){
        console.log("name=" + f.name);
        console.log("value=" + f.value);
    });
});


因為serializeArray印出來是Object,所以可以用$.each印出來



官網連結

※全域Ajax事件處理器

目前共6種
由上往下執行,ajaxError、ajaxSuccess只會執行其中之一,global設false不會執行
.ajaxStart():一開始就會執行
.ajaxSend():開始發送會執行
.ajaxError():失敗時執行
.ajaxSuccess():成功時執行
.ajaxComplete():完成時執行
.ajaxStop():結束執行


var ajaxTest = function(){
    $.ajax({
        url : "xxx",
        type : "POST",
        // dataType: 'abc',
        data : $.param({ 
                    username: $('input[name="username"]').val(), 
                    password: 'p' 
                }),
        success : function(data, textStatus, jqXHR){
            console.log('data=' + data);
            console.log('textStatus=' + textStatus);
        }
    });
}
    
function setGlobalFalse(){
    $.ajaxSetup({
        global : false
    });
}
    
$(document).ajaxStart(function() {
    alert('start');
});
    
$(document).ajaxSend(function() {
    alert('send');
});
    
$(document).ajaxError(function() {
    alert('error');
});
    
$(document).ajaxSuccess(function() {
    alert('success');
});
    
$(document).ajaxComplete(function() {
    alert('complete');
});
    
$(document).ajaxStop(function() {
    alert('stop');
});
----------
<h3>${success}</h3>
<form action="xxx/ooo" method="post">
    使用者:
    <input type="text" name="username" value="user" /><br />
    密碼:
    <input type="password" name="password" value="pass" /><br />
    <input type="submit" />
</form>
    
<input onclick="ajaxTest()" type="button" value="test" />
<input onclick="setGlobalFalse()" type="button" value="globalFalse" />

※這範例是成功的,所以ajaxSuccess會跳出來;將dataType打開會失敗,所以ajaxError跳出來

※將globalFalse的按鈕按下後,都不會觸發了

※注意官網有說版本的問題,我沒有測