国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

task0002(四)- 練習(xí):數(shù)據(jù)處理、輪播及交互

cnTomato / 470人閱讀

摘要:獲取下一個(gè)元素節(jié)點(diǎn),存在的話,取消現(xiàn)有選中狀態(tài),設(shè)置下一個(gè)元素節(jié)點(diǎn)為選擇中,調(diào)用運(yùn)動(dòng)框架實(shí)現(xiàn)動(dòng)畫(huà),添加定時(shí)器,調(diào)用該函數(shù),實(shí)現(xiàn)自動(dòng)播放。移出時(shí),開(kāi)啟定時(shí)器,繼續(xù)輪播。輪播間隔時(shí)間單位為毫秒,默認(rèn)為,在內(nèi)部,以下部分進(jìn)行修改或添加。

轉(zhuǎn)載自我的個(gè)人博客

歡迎大家批評(píng)指正

包括5部分:

小練習(xí)1-處理用戶輸入

小練習(xí)2-日期對(duì)象的使用

小練習(xí)3:輪播圖

小練習(xí)4:輸入提示框

小練習(xí)5:界面拖拽交互

源碼地址
task0002 在線Demo

小練習(xí)1:處理用戶輸入

這里直接可以利用原來(lái)寫(xiě)過(guò)的util.js。所以應(yīng)該不是特別難。主要考察對(duì)字符串的操作,以及正則表達(dá)式的使用

任務(wù)描述

task0002目錄下創(chuàng)建一個(gè)task0002_1.html文件,以及一個(gè)js目錄和css目錄,在js目錄中創(chuàng)建task0002_1.js,并將之前寫(xiě)的util.js也拷貝到js目錄下。然后完成以下需求。

第一階段

在頁(yè)面中,有一個(gè)單行輸入框,一個(gè)按鈕,輸入框中用來(lái)輸入用戶的興趣愛(ài)好,允許用戶用半角逗號(hào)來(lái)作為不同愛(ài)好的分隔。

當(dāng)點(diǎn)擊按鈕時(shí),把用戶輸入的興趣愛(ài)好,按照上面所說(shuō)的分隔符分開(kāi)后保存到一個(gè)數(shù)組,過(guò)濾掉空的、重復(fù)的愛(ài)好,在按鈕下方創(chuàng)建一個(gè)段落顯示處理后的愛(ài)好。

實(shí)現(xiàn)

根據(jù)題目要求,這個(gè)地方比較簡(jiǎn)單,可以直接利用前面寫(xiě)過(guò)的一些函數(shù),分成四步,進(jìn)行。

使用正則表達(dá)式來(lái)對(duì)字符串進(jìn)行分割操作。

uniqArray函數(shù)進(jìn)行去重操作。

for循環(huán),trim函數(shù)對(duì)數(shù)組項(xiàng)進(jìn)行去除首尾空格,用來(lái)處理,該項(xiàng)為空的情況。

innerHTML進(jìn)行輸出。

html:



    task0002_1.js中的js:

    //自執(zhí)行的匿名函數(shù)
    (function handle_1() {
        //其實(shí)這里沒(méi)必要使用id因?yàn)閿?shù)據(jù)那么少$函數(shù)直接獲取標(biāo)簽就行
        var inp = $("#user_input");
        var out = $("#user_output");
        $.click("#btn", function () {
            var value = inp.value.split(/,|,/); //1.根據(jù)半角逗號(hào)分割成數(shù)組。
            var unValue = uniqArray(value); //2.數(shù)組去重
            for (var i = 0, len = unValue.length; i < len; i++) {
                var trimValue = trim(unValue[i]); //3.對(duì)每一項(xiàng)進(jìn)行去除首尾空格操作
                console.log(trimValue);
                if (trimValue !== "") { //4.只有在去除首尾空格后不為空的數(shù)組才輸出。
                    out.innerHTML += "
  • " + trimValue + "
  • " } } }) })();
    第二階段

    單行變成多行輸入框,一個(gè)按鈕,輸入框中用來(lái)輸入用戶的興趣愛(ài)好,允許用戶用換行、空格(全角/半角)、逗號(hào)(全角/半角)、頓號(hào)、分號(hào)來(lái)作為不同愛(ài)好的分隔。

    當(dāng)點(diǎn)擊按鈕時(shí)的行為同上

    實(shí)現(xiàn)

    看題目描述,主要是對(duì)于第一步進(jìn)行修改,第一階段只要求對(duì)半角逗號(hào)進(jìn)行處理,但是在第二階段中,需要對(duì)“換行、空格(全角/半角)、逗號(hào)(全角/半角)、頓號(hào)、分號(hào)”進(jìn)行處理。
    主要是考察對(duì)于正則表達(dá)式的應(yīng)用。

    只需要對(duì)var value = inp.value.split(/,|,/); 進(jìn)行更改如下:

    var value = inp.value.split(/ |s+|,|,|、|;|;/);
    需要注意的是:在正則表達(dá)式進(jìn)行匹配這些符號(hào)時(shí)最好是前面加上轉(zhuǎn)義字符。

    第三階段

    用戶輸入的愛(ài)好數(shù)量不能超過(guò)10個(gè),也不能什么都不輸入。當(dāng)發(fā)生異常時(shí),在按鈕上方顯示一段紅色的錯(cuò)誤提示文字,并且不繼續(xù)執(zhí)行后面的行為;當(dāng)輸入正確時(shí),提示文字消失。

    同時(shí),當(dāng)點(diǎn)擊按鈕時(shí),不再是輸出到一個(gè)段落,而是每一個(gè)愛(ài)好輸出成為一個(gè)checkbox,愛(ài)好內(nèi)容作為checkbox的label。

    實(shí)現(xiàn)

    嗯,其實(shí)這里按照題目要求應(yīng)該要實(shí)時(shí)監(jiān)聽(tīng)輸入值變化,但是那樣太麻煩了,,所以就直接在點(diǎn)擊按鈕的時(shí)候判斷了。

    直接判斷數(shù)組長(zhǎng)度就行了。。輸入為空時(shí),判斷字符串=“”。

    輸出checkbox這里不過(guò)多的設(shè)置了,只是演示。

    最終完成

    html:

    
    

    輸入的愛(ài)好數(shù)量不能超過(guò)10個(gè),或什么都不輸入

    js:

    (function handle_1() {
        var inp = $("#user_input");
        var out = $("#user_output");
        $.click("#btn", function () {
            var value = inp.value.split(/
    |s+|,|,|、|;|;/); //分割成數(shù)組。
            var unValue = uniqArray(value); //數(shù)組去重
            var i = 0;
            var len = unValue.length;
            if (len > 10 || unValue == "") {
                $("p").style.disautoPlay = "block";
            } else {
                $("p").style.disautoPlay = "none";
                for (; i < len; i++) {
                    var trimValue = trim(unValue[i]); //對(duì)每一項(xiàng)進(jìn)行去除首尾空格操作
                    console.log(trimValue);
                    if (trimValue !== "") { //只有在去除首尾空格后不為空的數(shù)組才輸出。
                        out.innerHTML += ""
                    }
                }
            }
        })
    })();

    在線演示:小練習(xí)1:處理興趣列表

    小練習(xí)2:日期對(duì)象的使用 任務(wù)描述

    在和上一任務(wù)同一目錄下面創(chuàng)建一個(gè)task0002_2.html文件,在js目錄中創(chuàng)建task0002_2.js,并在其中編碼,實(shí)現(xiàn)一個(gè)倒計(jì)時(shí)功能。

    界面首先有一個(gè)文本輸入框,允許按照特定的格式YYYY-MM-DD輸入年月日;

    輸入框旁有一個(gè)按鈕,點(diǎn)擊按鈕后,計(jì)算當(dāng)前距離輸入的日期的00:00:00有多少時(shí)間差

    在頁(yè)面中顯示,距離YYYY年MM月DD日還有XX天XX小時(shí)XX分XX秒

    每一秒鐘更新倒計(jì)時(shí)上顯示的數(shù)

    如果時(shí)差為0,則倒計(jì)時(shí)停止

    實(shí)現(xiàn)思路 了解日期對(duì)象

    這里主要是考察的對(duì)于日期對(duì)象的使用。

    new Date()。如果沒(méi)有輸入任何參數(shù),則Date的構(gòu)造器會(huì)依據(jù)系統(tǒng)設(shè)置的當(dāng)前時(shí)間來(lái)創(chuàng)建一個(gè)Date對(duì)象。表示當(dāng)前系統(tǒng)時(shí)間。

    //時(shí)間對(duì)象創(chuàng)建的幾種方式。
    var today = new Date();
    var birthday = new Date("December 17, 1995 03:24:00");
    var birthday = new Date("1995-12-17T03:24:00");
    var birthday = new Date(1995,11,17);
    var birthday = new Date(1995,11,17,3,24,0);

    Date對(duì)象中處理時(shí)間和日期的常用方法:詳細(xì)內(nèi)容在MDN上

    正式開(kāi)始:

    創(chuàng)建時(shí)間處理函數(shù),使用正則表達(dá)式,處理輸入的值,value.match(/(^d{4})-(d{2})-(d{2}$)/);用到了match方法和正則的分組,在我寫(xiě)的正則博客里應(yīng)該有過(guò)詳細(xì)介紹了。這里也不過(guò)的說(shuō)明了。

    使用目標(biāo)時(shí)間的getTime()毫秒數(shù)減去得到當(dāng)前的毫秒數(shù),得到相差的毫秒數(shù)。處理它:(注意毫秒的問(wèn)題)

    (60 * 60 * 24) :剩余的天數(shù)。

    (60 * 60) % 24) :剩余的小時(shí)數(shù)。依次類推。

    innerHTML輸出,并且判斷相差時(shí)間,改變輸出的值。

    定時(shí)器的使用。(我這里使用的setTimeout(),使用遞歸調(diào)用實(shí)現(xiàn)自執(zhí)行)

    計(jì)時(shí)器setTimeout(函數(shù),延遲時(shí)間);,在載入后延遲指定時(shí)間后,去執(zhí)行一次表達(dá)式,僅執(zhí)行一次。

    取消計(jì)時(shí)器:clearTimeout()停止計(jì)時(shí)器。

    給按鈕添加點(diǎn)擊事件,在點(diǎn)擊時(shí),調(diào)用剛剛編寫(xiě)的的時(shí)間處理函數(shù)。

    在線演示:小練習(xí)2:倒計(jì)時(shí)

    小練習(xí)3:輪播圖組件 任務(wù)描述

    在和上一任務(wù)同一目錄下面創(chuàng)建一個(gè)task0002_3.html文件,在js目錄中創(chuàng)建task0002_3.js,并在其中編碼,實(shí)現(xiàn)一個(gè)輪播圖的功能。

    圖片數(shù)量及URL均在HTML中寫(xiě)好

    可以配置輪播的順序(正序、逆序)、是否循環(huán)、間隔時(shí)長(zhǎng)

    圖片切換的動(dòng)畫(huà)要流暢

    在輪播圖下方自動(dòng)生成對(duì)應(yīng)圖片的小點(diǎn),點(diǎn)擊小點(diǎn),輪播圖自動(dòng)動(dòng)畫(huà)切換到對(duì)應(yīng)的圖片

    效果示例:http://echarts.baidu.com/ 上面的輪播圖(不需要做左右兩個(gè)箭頭)

    實(shí)現(xiàn)思路:

    主要是對(duì)于考察對(duì)于定時(shí)器,以及事件綁定的處理,以及動(dòng)畫(huà)效果,為此我專門(mén)寫(xiě)了一篇博客《JS完美運(yùn)動(dòng)框架的封裝過(guò)程》。 這里就直接使用里面封裝好的函數(shù)了。

    本來(lái)都要放棄組件的編寫(xiě)了,只想按照常規(guī)方法來(lái)寫(xiě)個(gè)輪播圖就好,但是在先把小練習(xí)4完成的情況下,就發(fā)現(xiàn)了一種新方法,可以幫助我完成這個(gè)任務(wù)(強(qiáng)烈建議先看小練習(xí)四!)使用nextElementNode,圖片向左切換。(不涉及任何css,我假設(shè)css都會(huì)了,也沒(méi)有用到特別難css屬性)

    該輪播圖有依賴函數(shù)。主要使用到以下函數(shù):

    選擇器函數(shù)$(class);

    運(yùn)動(dòng)框架startMove

    同時(shí)在該函數(shù)引入時(shí),還依賴于獲取實(shí)際樣式函數(shù)getStyle

    獲取當(dāng)前元素在同級(jí)元素的索引getIndex;

    事件代理函數(shù):delegateEvent

    添加class與刪除class元素addClass、romoveClass

    第一步:實(shí)現(xiàn)點(diǎn)擊切換

    編寫(xiě)幻燈片函數(shù):Slideshow(element)

    根據(jù)圖片的數(shù)量創(chuàng)建與圖片數(shù)量相同的導(dǎo)航小點(diǎn):ul>li*length 。設(shè)置其li樣式,并且默認(rèn)把第一個(gè)li設(shè)置為活動(dòng)狀態(tài)classNameactive

    編寫(xiě)點(diǎn)擊函數(shù)clickLi

    li添加事件代理函數(shù)。

    據(jù)點(diǎn)擊的li的索引值算出來(lái)動(dòng)畫(huà)的目標(biāo)值,-iCurrent * getIndex(this);

    移除所有li上的選中狀態(tài)active:編寫(xiě)函數(shù)removeLiClass(),在后面我們還要用到它。

    設(shè)置當(dāng)前點(diǎn)擊的li為選中:狀態(tài)active

    調(diào)用運(yùn)動(dòng)框架實(shí)現(xiàn)動(dòng)畫(huà)效果。

    function Slideshow(element) {
        //1.創(chuàng)建li
        var imgArr = element.getElementsByTagName("img"); //獲取圖片數(shù)量
        var imgArrLen = imgArr.length; //緩存圖片數(shù)量
        var createUl = document.createElement("ul"); //創(chuàng)建小點(diǎn)的ul
        var iCurrent = parseInt(getStyle(imgArr[0], "width")); //獲取一張圖片的寬度
        element.style.width = iCurrent * imgArrLen + "px"; //設(shè)置圖片容器的寬度。
        //創(chuàng)建li
        for (var i = 0, len = imgArrLen; i < len; i++) {
            createUl.innerHTML += "
  • "; } element.parentNode.appendChild(createUl); //插入導(dǎo)航 addClass(createUl, "Slideshow-nav"); //添加導(dǎo)航樣式 addClass(createUl.getElementsByTagName("li")[0], "active"); //默認(rèn)設(shè)置第一個(gè)為第當(dāng)前活動(dòng)的li //編寫(xiě)點(diǎn)擊函數(shù)clickLi: clickLi(); /** * 點(diǎn)擊導(dǎo)航 */ function clickLi() { delegateEvent(createUl, "li", "click", function () { var iTaget = -iCurrent * getIndex(this); removeLiClass(); addClass(this, "active"); //移出 startMove(element, { "left": iTaget }); }); } /** * 用于移除所有的Li的選中狀態(tài):active */ function removeLiClass() { var oLi = createUl.getElementsByTagName("li"); for (var i = 0, len = oLi.length; i < len; i++) { removeClass(oLi[i], "active"); } } }
    第二步:實(shí)現(xiàn)自動(dòng)播放

    為了方便后續(xù)的封裝,暫時(shí)只考慮:正序不循環(huán)的情況!

    創(chuàng)建自動(dòng)播放函數(shù)paly(),獲取當(dāng)前為選中狀態(tài)active的li.

    設(shè)置目標(biāo)值,根據(jù)選中狀態(tài)的索引+1 *width來(lái)設(shè)置。(注意是負(fù)值,同時(shí)考慮索引值+1為length的情況。)

    因?yàn)椴谎h(huán),需要在設(shè)置(getIndex(heightLi)+1)===imgArrLen-1清除定時(shí)器。(其實(shí)就是輪播到最后的時(shí)候,至于為什么是這樣,可以自己研究一下,更改一下值。)

    獲取下一個(gè)元素節(jié)點(diǎn),存在的話,取消現(xiàn)有選中狀態(tài),設(shè)置下一個(gè)元素節(jié)點(diǎn)為選擇中,調(diào)用運(yùn)動(dòng)框架!實(shí)現(xiàn)動(dòng)畫(huà),

    添加定時(shí)器setInterval(),調(diào)用該函數(shù),實(shí)現(xiàn)自動(dòng)播放。

    測(cè)試幾次,你會(huì)發(fā)現(xiàn):點(diǎn)擊li和自動(dòng)播放之間存在沖突,動(dòng)畫(huà)效果都沒(méi)做完就播放下一張了,如何解決呢?

    給圖片容器添加一個(gè)鼠標(biāo)移入和移除事件(mouseover、mouseover)也就是hover上去的效果

    移入時(shí),清除定時(shí)器,暫停播放。

    移出時(shí),開(kāi)啟定時(shí)器,繼續(xù)輪播。

    然后你會(huì)發(fā)現(xiàn)問(wèn)題成功的解決了!(而且我觀察了大部分的輪播,都是這個(gè)效果,移入暫停,移出繼續(xù))

    這里我們的最基本的功能都實(shí)現(xiàn)了,代碼如下:(放在Slideshow()函數(shù)內(nèi)部)

    var iSpeed = 4000;//定時(shí)器間隔。
    
    hoverElement(); 
    /*
    * 移入圖片容器暫停,移除繼續(xù)播放。
    */
    function hoverElement() {
        addEvent(element.parentNode, "mouseover", function () {
            clearInterval(timer);
        });
        addEvent(element.parentNode, "mouseout", function () {
            timer = setInterval(autoPlay, iSpeed);
        });
    }
    
    var timer = null;
    timer = setInterval(autoPlay, iSpeed);
    /*
    * 自動(dòng)播放函數(shù)。
    */
    function autoPlay() {
        var heightLi = $(".Slideshow-nav .active"); //高亮的li
        var iTaget;
        iTaget = (getIndex(heightLi) + 1) === imgArrLen ? 0 : (-iCurrent * (getIndex(heightLi) + 1));
    
        if (getIndex(heightLi) + 1 === imgArrLen - 1) {
            clearInterval(timer);
        }
        var nextLi = heightLi.nextElementSibling;
        if (nextLi) {
            removeLiClass();
            addClass(nextLi, "active");
        }
        startMove(element, {
            "left": iTaget
        });
    }
    第三步:添加配置項(xiàng)(題目要求完成)

    獲取題目要求:主要是以下三點(diǎn)。

    是否循環(huán),默認(rèn)為循環(huán)。

    是否反向,默認(rèn)不反向。只有循環(huán)時(shí),才可反向。

    輪播間隔時(shí)間,默認(rèn)4000。

    如何實(shí)現(xiàn)?(使用JSON如下:)

    /*
     * @param {JSON}         option       配置項(xiàng)
     *   @config   {String}  noLoop       不循環(huán)?,默認(rèn)為循環(huán),只要存在則不循環(huán),任意值
     *   @config   {String}  reverse      是否反向,任意值。只有“noLoop”不存在時(shí),也就是只有循環(huán)時(shí),才執(zhí)行。
     *   @config   {Number}  intervalTime 輪播間隔時(shí)間(單位為毫秒),默認(rèn)為4000,
    */

    Slideshow()內(nèi)部,以下部分進(jìn)行修改或添加。

    先從簡(jiǎn)單的開(kāi)始吧!判斷option.intervalTime是否存在并且更改iSpeed的值(這樣,輪播間隔時(shí)間配置就成功了),默認(rèn)為4000毫秒。

    改變自動(dòng)播放(一):autoPlay函數(shù)。這里是整個(gè)改造中最復(fù)雜的部分!分幾步進(jìn)行。

    把剛剛寫(xiě)的autoPlay函數(shù)內(nèi)的內(nèi)容,除去var heightLi = $(".Slideshow-nav .active"); var iTaget;這兩個(gè)內(nèi)容,其他的都使用if(option.noLoop){}包裹起來(lái)。
    這樣就又完成了一個(gè)內(nèi)容,當(dāng)配置為不循環(huán)時(shí)的情況,就寫(xiě)好了。

    既然有if不循環(huán)的情況,那么就肯定有else對(duì)應(yīng)循環(huán)時(shí)的情況對(duì)吧?(笑)那么在里面應(yīng)該怎么做呢?

    第一次練習(xí)時(shí),可以不添加函數(shù),直接使用if else,對(duì)應(yīng)正向與反向的情況!但是,在這里為了后面的進(jìn)化,且不過(guò)多的闡述,就直接使用使用函數(shù)了,就叫他play(reverse)吧。
    在這里當(dāng)然傳入的參數(shù)是option.reverse

    改變自動(dòng)播放(二):編寫(xiě)play(reverse)

    第一要?jiǎng)?wù)就是加入if eles啦,用來(lái)區(qū)分,true時(shí)為反向,false為正向(默認(rèn))。

    先來(lái)說(shuō)正向的情況!其實(shí)特別簡(jiǎn)單,有兩步:

    第一步:刪除(getIndex(heightLi)+1)===imgArrLen-1清除定時(shí)器的部分,只有這樣才能實(shí)現(xiàn)循環(huán),

    第二步:在上面被提取到不循環(huán)的內(nèi)容中(也就是第一版的autoPlay())的if (nextLi)部分加上else的情況就行了!

    //在下一個(gè)元素節(jié)點(diǎn)不存在的情況下(也就是到了最后了),設(shè)置第一個(gè)節(jié)點(diǎn)為活動(dòng)狀態(tài),就這樣正向的循環(huán)就成功了!
     else {
        removeLiClass();
        addClass($(".Slideshow-nav li"), "active");
    }

    反向的情況(只需要對(duì)正向循環(huán)進(jìn)行修改):

    改變目標(biāo)值iTagetgetIndex(heightLi) === 0 ? -iCurrent * (imgArrLen - 1) : -iCurrent * (getIndex(heightLi) - 1);

    改變下一個(gè)元素節(jié)點(diǎn),為前一個(gè)元素節(jié)點(diǎn)previousElementSibling

    改變上面else的情況,為設(shè)置最后一個(gè)節(jié)點(diǎn)為活動(dòng)狀態(tài)。代碼就不貼了,有興趣的看源碼吧!

    到現(xiàn)在函數(shù)就修改完成了。只需要在循環(huán)的情況下,調(diào)用該函數(shù),并且傳入option.reverse

    其實(shí)到這里我們題目要求就完成了!

    但是!不挑戰(zhàn)一下怎么能行?

    為什么不把左右點(diǎn)擊切換一起實(shí)現(xiàn)了呢?

    既然這樣,我們就繼續(xù)吧!

    第四步:擴(kuò)展!左右箭頭實(shí)現(xiàn)!

    創(chuàng)建并設(shè)置箭頭樣式(配合css使用)

    //創(chuàng)建左右導(dǎo)航
    var createSpan = document.createElement("div");
    addClass(createSpan, "left-right")
    createSpan.innerHTML = "<>"
    element.parentNode.appendChild(createSpan);

    創(chuàng)建點(diǎn)擊事件,事件代理。

    炸裂的函數(shù)調(diào)用。

    還記得我們剛剛的play(reverse)函數(shù)嗎?剛剛的功能完全不用封裝函數(shù),那為什么要做呢?就是這里啦!

    想想剛剛的函數(shù)實(shí)現(xiàn)了什么功能呢?是不是正向循環(huán),和反向循環(huán)?,自動(dòng)播放是因?yàn)樵谕鈱佑卸〞r(shí)器的緣故。

    所以只需要調(diào)用傳參就行了!

    傳什么參數(shù)?

    想想左右箭頭的索引,是不是0和1。這樣就懂了吧!

    對(duì)索引進(jìn)行取反。傳參!代碼如下:

    delegateEvent(createSpan, "span", "click", function () {
        var heightLi = $(".Slideshow-nav .active"); //高亮的待選li
        var leftIndex = !getIndex(this); //點(diǎn)擊左時(shí)為true,點(diǎn)擊又為false
        //移動(dòng)的目標(biāo)值,默認(rèn)正向
        play(leftIndex);
    });

    至此,我們的輪播圖組件就完成了! 需要配合CSS使用。 通過(guò)這次封裝,收益良多,感興趣的話可以看看源碼

    在線演示:小練習(xí)3:圖片輪播組件

    小練習(xí)4:輸入提示框 任務(wù)描述

    在和上一任務(wù)同一目錄下面創(chuàng)建一個(gè)task0002_4.html文件,在js目錄中創(chuàng)建task0002_4.js,并在其中編碼,實(shí)現(xiàn)一個(gè)類似百度搜索框的輸入提示的功能。

    要求如下:

    允許使用鼠標(biāo)點(diǎn)擊選中提示欄中的某個(gè)選項(xiàng)

    允許使用鍵盤(pán)上下鍵來(lái)選中提示欄中的某個(gè)選項(xiàng),回車確認(rèn)選中

    選中后,提示內(nèi)容變更到輸入框中

    初級(jí)班:

    不要求和后端交互,可以自己偽造一份提示數(shù)據(jù)例如:

    var suggestData = ["Simon", "Erik", "Kener"];

    中級(jí)班:

    自己搭建一個(gè)后端Server,使用Ajax來(lái)獲取提示數(shù)據(jù)

    示例:

    實(shí)現(xiàn)思路

    這里我并沒(méi)有一開(kāi)始就直接進(jìn)行數(shù)據(jù)獲取的部分,而是進(jìn)行了任務(wù)分解,如下:

    第一階段

    先在使用寫(xiě)好的ul>li標(biāo)簽下,。添加3個(gè)事件mouseovermouseoutclick。實(shí)現(xiàn)點(diǎn)擊li使其值變成輸入框內(nèi)的值。(直接使用事件代理)

    對(duì)輸入框添加鍵盤(pán)事件(對(duì),你沒(méi)看錯(cuò),只有在聚焦在輸入框時(shí)才觸發(fā))

    獲取當(dāng)前高亮的li。沒(méi)有則設(shè)第一個(gè)為高亮active

    判斷keyCode使用鍵盤(pán)下鍵,使用nextElementSibling方法獲取下一個(gè)節(jié)點(diǎn)(向上同理),取消當(dāng)前的active,設(shè)置下一個(gè)為active。(使用鍵盤(pán)上下選中的效果,處理完成)

    判斷keyCode,獲取當(dāng)前狀態(tài)為active的值,實(shí)現(xiàn)回車時(shí),把其設(shè)為input的值。

    需要注意的地方:

    在移除高亮狀態(tài)時(shí),最好是遍歷一遍。因?yàn)殒I盤(pán)與鼠標(biāo)劃過(guò)有可能同時(shí)觸發(fā),導(dǎo)致有多個(gè)高亮。

    錯(cuò)誤處理

    第二階段

    刪除原來(lái)的ul>lihtml部分的li。添加對(duì)于輸入框進(jìn)行實(shí)時(shí)監(jiān)聽(tīng)(這部分不在這里展開(kāi)講,如何實(shí)現(xiàn)大家去google吧,因?yàn)橐徽归_(kāi)就太多要說(shuō)的了)。

    給個(gè)參考:實(shí)時(shí)監(jiān)聽(tīng)輸入框值變化

    使用AJAX獲取服務(wù)器上的數(shù)據(jù),解析,遍歷,并進(jìn)行數(shù)據(jù)匹配。

    匹配成功顯示ul,否則設(shè)為none

    使用正則表達(dá)式的match方法,來(lái)獲取匹配成功的把部分,使用span進(jìn)行高亮顯示。并且插入ul

    改造第一階段的函數(shù):

    因?yàn)槭鞘褂玫氖录恚苯訉?duì)ul添加事件,所以需要修改的部分不是很多。

    clickenter部分獲取的值,因?yàn)?b>span標(biāo)簽的存在,需要使用正則進(jìn)行處理,輸出刪除span后的值。

    在線演示:小練習(xí)4:輸入框即時(shí)提示

    小練習(xí)5:界面拖拽交互

    實(shí)現(xiàn)一個(gè)可拖拽交互的界面

    如示例圖,左右兩側(cè)各有一個(gè)容器,里面的選項(xiàng)可以通過(guò)拖拽來(lái)左右移動(dòng)

    被選擇拖拽的容器在拖拽過(guò)程后,在原容器中消失,跟隨鼠標(biāo)移動(dòng)

    注意拖拽釋放后,要添加到準(zhǔn)確的位置

    拖拽到什么位置認(rèn)為是可以添加到新容器的規(guī)則自己定

    注意交互中良好的用戶體驗(yàn)和使用引導(dǎo)

    實(shí)現(xiàn)思路: 第一步:封裝拖拽函數(shù)

    開(kāi)一個(gè)DEMO頁(yè)面,實(shí)踐如下:

    了解應(yīng)該用到的事件,onmousedownonmousemoveonmouseup

    思考對(duì)誰(shuí)添加事件?

    在鼠標(biāo)點(diǎn)擊div時(shí),對(duì)div添加onmousedown,表示鼠標(biāo)按下。

    在事件內(nèi)給document添加onmousemove。(為啥給document加呢?因?yàn)榻odiv加在移動(dòng)過(guò)快時(shí)會(huì)跳出去)表示鼠標(biāo)移動(dòng)。

    并且添加document添加onmouseup,表示鼠標(biāo)已經(jīng)抬起,清除移動(dòng)事件,以及本身。

    思考如何設(shè)置對(duì)象的位置?

    直接獲取鼠標(biāo)的位置并設(shè)置給div行不行呢?試試吧!顯然,會(huì)出現(xiàn)問(wèn)題,點(diǎn)擊鼠標(biāo)就到div左上角去了。

    那么怎么改變呢?獲取鼠標(biāo)在div中的位置?對(duì)。就這樣,在鼠標(biāo)按下時(shí)記錄鼠標(biāo)在div中的位置.

    在鼠標(biāo)移動(dòng)時(shí),用當(dāng)前的位置,減去剛剛的位置,這就是應(yīng)該的值!

    別忘了鼠標(biāo)抬起時(shí),需要清除事件,不然鼠標(biāo)就粘住了。

    這里用到了event,事件對(duì)象的相關(guān)概念,推薦觀看慕課網(wǎng)的視頻。DOM事件探秘

    善用this。
    擴(kuò)展

    /**
     * 鼠標(biāo)拖拽函數(shù)。
     * @param {HTMLElement} element 需要拖拽的對(duì)象
     */
    function setDrag(element) {
        addEvent(element, "mousedown", onmousedown);
        //鼠標(biāo)按下
        function onmousedown(ev) {
            var oEvent = ev || event;
            var disX = oEvent.clientX - this.offsetLeft;
            var disY = oEvent.clientY - this.offsetTop;
            var that = this;
            addEvent(document, "mousemove", onmousemove);
            addEvent(document, "mouseup", onmouseup);
            /**
             * 鼠標(biāo)移動(dòng)
             */
            function onmousemove(ev) {
                var oEvent = ev || event;
                that.style.left = oEvent.clientX - disX + "px";
                that.style.top = oEvent.clientY - disY + "px"
            }
            /**
             * 鼠標(biāo)抬起刪除事件
             */
            function onmouseup() {
                removeEvent(document, "mousemove", onmousemove);
                removeEvent(document, "mouseup", onmouseup);
            }
        }
    }
    第二步:布局轉(zhuǎn)換函數(shù)

    兩個(gè)參數(shù),第一個(gè)參數(shù),傳入父級(jí)對(duì)象。第二個(gè)參數(shù)傳入標(biāo)簽名,

    循環(huán),使用數(shù)組,對(duì)象,獲取標(biāo)簽當(dāng)前元素的位置lefttop。(offsetLeft)。這里不能使用獲取實(shí)際樣式函數(shù),因?yàn)楸旧砭托枰@取其相對(duì)父元素的位置。

    第二個(gè)循環(huán)

    設(shè)置lefttop值。

    設(shè)置絕對(duì)定位。

    取消原有的margin值。

    調(diào)用函數(shù),把對(duì)象從文檔流布局,變成絕對(duì)定位布局。

    /**
     * 布局轉(zhuǎn)換函數(shù)
     * @param {HTMLElment} element  HTML對(duì)象
     * @param {string}     childEle 其內(nèi)需要轉(zhuǎn)換的標(biāo)簽名
     */
    function toPosition(element, childEle) {
        var eleArr = element.getElementsByTagName(childEle);
        var aPos = [];
        //
        for (var i = 0, len = eleArr.length; i < len; i++) {
            aPos[i] = {
                left: eleArr[i].offsetLeft,
                top: eleArr[i].offsetTop
            };
        }
        for (var i = 0, len = eleArr.length; i < len; i++) {
            eleArr[i].style.left = aPos[i].left + "px";
            eleArr[i].style.top = aPos[i].top + "px";
            eleArr[i].style.position = "absolute";
            eleArr[i].style.margin = "0";
        }
    }

    在線演示:小練習(xí)5:拖拽交互

    第三步:實(shí)現(xiàn)拖拽

    前面我們已經(jīng)實(shí)現(xiàn)了setDrag(element)函數(shù),常規(guī)方法就是直使用循環(huán),然后傳入element

    但是,為什么不用事件代理呢?

    特別簡(jiǎn)單,只需要對(duì)上面寫(xiě)的函數(shù)進(jìn)行一些簡(jiǎn)單的改裝。

    delegateEvent(parentElement, "li", "mousedown", function (ev) {
    //此處是原函數(shù)中的內(nèi)容。
    }

    現(xiàn)在知道為什么上面的函數(shù)會(huì)用到this了吧?

    第四步:碰撞檢測(cè)函數(shù)

    先來(lái)看張圖:

    是不是有瞬間豁然開(kāi)朗的感覺(jué)呢?

    獲取相關(guān)值,只需要考慮不碰不上的情況就行了!。如下:

    /**
     * 碰撞檢測(cè)函數(shù)
     * @param   {object}  obj1 對(duì)象1
     * @param   {object}  obj2 對(duì)象2
     * @returns {boolean} 碰撞時(shí)返回true,否則反正false
     */
    function hitDetection(obj1, obj2) {
        //對(duì)象1的相關(guān)值
        var l1 = obj1.offsetLeft;
        var r1 = obj1.offsetLeft + obj1.offsetWidth;
        var t1 = obj1.offsetTop;
        var b1 = obj1.offsetTop + obj1.offsetHeight;
        //對(duì)象2的相關(guān)值
        var l2 = obj2.offsetLeft;
        var r2 = obj2.offsetLeft + obj2.offsetWidth;
        var t2 = obj2.offsetTop;
        var b2 = obj2.offsetTop + obj2.offsetHeight;
    
        if (r1 < l1 || l1 > r2 || b1 < t2 || t1 > b2) {
            return false;//沒(méi)碰上
        } else {
            return true;
        }
    }
    第五步:處理各種碰撞情況

    這里講起來(lái)就太復(fù)雜了。源代碼中注釋還是比較詳細(xì)的,有興趣可以看下

    文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/91575.html

    相關(guān)文章

    • task0002)- 練習(xí)數(shù)據(jù)處理播及交互

      摘要:獲取下一個(gè)元素節(jié)點(diǎn),存在的話,取消現(xiàn)有選中狀態(tài),設(shè)置下一個(gè)元素節(jié)點(diǎn)為選擇中,調(diào)用運(yùn)動(dòng)框架實(shí)現(xiàn)動(dòng)畫(huà),添加定時(shí)器,調(diào)用該函數(shù),實(shí)現(xiàn)自動(dòng)播放。移出時(shí),開(kāi)啟定時(shí)器,繼續(xù)輪播。輪播間隔時(shí)間單位為毫秒,默認(rèn)為,在內(nèi)部,以下部分進(jìn)行修改或添加。 轉(zhuǎn)載自我的個(gè)人博客 歡迎大家批評(píng)指正 包括5部分: 小練習(xí)1-處理用戶輸入 小練習(xí)2-日期對(duì)象的使用 小練習(xí)3:輪播圖 小練習(xí)4:輸入提示框 小練習(xí)...

      趙春朋 評(píng)論0 收藏0
    • 實(shí)現(xiàn)簡(jiǎn)單的輪播

      摘要:小練習(xí)輪播圖組件任務(wù)描述在和上一任務(wù)同一目錄下面創(chuàng)建一個(gè)文件,在目錄中創(chuàng)建,并在其中編碼,實(shí)現(xiàn)一個(gè)輪播圖的功能。實(shí)現(xiàn)思路考察對(duì)節(jié)點(diǎn),定時(shí)器,事件的處理。 小練習(xí)3:輪播圖組件 任務(wù)描述在和上一任務(wù)同一目錄下面創(chuàng)建一個(gè)task0002_3.html文件,在js目錄中創(chuàng)建task0002_3.js,并在其中編碼,實(shí)現(xiàn)一個(gè)輪播圖的功能。 圖片數(shù)量及URL均在HTML中寫(xiě)好 可以配置輪播的順...

      EsgynChina 評(píng)論0 收藏0
    • task0002(一)- JavaScript數(shù)據(jù)類型及語(yǔ)言基礎(chǔ)

      摘要:不過(guò)讓流行起來(lái)的原因應(yīng)該是是目前所有主流瀏覽器上唯一支持的腳本語(yǔ)言。經(jīng)過(guò)測(cè)試,數(shù)字字符串布爾日期可以直接賦值,修改不會(huì)產(chǎn)生影響。再考慮對(duì)象類型為或者的情況。對(duì)于結(jié)果聲明其類型。判斷對(duì)象的類型是還是,結(jié)果類型更改。 轉(zhuǎn)載自我的個(gè)人博客 歡迎大家批評(píng)指正 1. 第一個(gè)頁(yè)面交互 這里最需要學(xué)習(xí)的老師的代碼中,每一部分功能都由函數(shù)控制,沒(méi)有創(chuàng)建一個(gè)全部變量。且最后有一個(gè)函數(shù)來(lái)控制執(zhí)行代碼...

      elarity 評(píng)論0 收藏0
    • 使用flex進(jìn)行網(wǎng)易云音樂(lè)界面構(gòu)建和布局解析(2)

      摘要:使用進(jìn)行網(wǎng)易云音樂(lè)界面構(gòu)建和布局解析前面我們通過(guò)布局簡(jiǎn)史與決勝未來(lái)的第四代布局技術(shù)了解了布局發(fā)展史和未來(lái),下面,我們通過(guò)使用進(jìn)行網(wǎng)易云音樂(lè)界面構(gòu)建和布局解析了解一下,如何在實(shí)際項(xiàng)目中使用進(jìn)行布局,相信大家也體會(huì)到了它的便捷之處。 使用flex進(jìn)行網(wǎng)易云音樂(lè)界面構(gòu)建和布局解析 前面我們通過(guò)《css布局簡(jiǎn)史與決勝未來(lái)的第四代css布局技術(shù)》了解了css布局發(fā)展史和未來(lái),下面,我們通過(guò)《使用...

      geekzhou 評(píng)論0 收藏0

    發(fā)表評(píng)論

    0條評(píng)論

    最新活動(dòng)
    閱讀需要支付1元查看
    <