Bootstrap滾動監控器

来源:http://www.cnblogs.com/xiaohuochai/archive/2017/07/09/7136678.html
-Advertisement-
Play Games

前面的話 滾動監聽插件是用來根據滾動條所處的位置來自動更新導航項的。滾動導航條下麵的區域並關註導航項的變化,下拉菜單中的條目也會自動高亮顯示。本文將詳細介紹Bootstrap滾動監控器 基本用法 滾動監聽插件是根據滾動的位置自動更新導航條中相應的導航項的,該插件可自動檢測到達哪個位置了,然後在需要高 ...


前面的話

  滾動監聽插件是用來根據滾動條所處的位置來自動更新導航項的。滾動導航條下麵的區域並關註導航項的變化,下拉菜單中的條目也會自動高亮顯示。本文將詳細介紹Bootstrap滾動監控器

 

基本用法

  滾動監聽插件是根據滾動的位置自動更新導航條中相應的導航項的,該插件可自動檢測到達哪個位置了,然後在需要高亮的菜單父元素上加了一個active樣式

  如果導航里有下拉菜單,並且滾動區域的內容到達下拉菜單子項所對應的區域,除了子菜單高亮之外,子菜單的父元素(dropdown按鈕)也會高亮

  在平時使用的過程中,滾動監聽一般有兩種用法,一種是固定一個元素的高度,進行滾動,然後對相應的菜單進行高亮顯示;另外一種是對整個頁面(body)進行滾動監聽。兩種方式的用法一樣,都需要有如下3個步驟:

  1、設置滾動容器,即在所要監聽的元素上設置data-target="#selector" data-spy="scroll"屬性

  2、設置菜單鏈接容器,該容器的id(或樣式)和data-target屬性所對應的選擇符要一致

  3、在菜單容器內,必須有.nav樣式的元素,並且在其內容有li元素,li內包含的a元素也是可以偵測高亮的菜單鏈接,即符合.nav li > a這種選擇符的條件

  4、無論何種實現方式,滾動監聽都需要被監聽的組件是 position: relative; 即相對定位方式

【固定元素高度】

<div id="myNavbar" class="navbar navbar-default navbar-fixed-top" role="navigation" style="position:relative">
     <ul class="nav navbar-nav">
        <li><a href="#html" tabindex="-1">HTML</a></li>
        <li><a href="#css" tabindex="-1">CSS</a></li>
        <li><a href="#javascript" tabindex="-1">javascript</a></li>
     </ul>
</div>

<div data-spy="scroll" data-target="#myNavbar" style="margin-top:150px;height:250px;overflow:auto;position:relative">
    <h4 id="html">Html</h4>
    <p>Html內容</p>
    <br><p>...</p><br><p>...</p><br><p>...</p>
    <h4 id="css">CSS</h4>
    <p>CSS內容</p>
    <br><p>...</p><br><p>...</p><br><p>...</p>
    <h4 id="javascript">javascript</h4>
    <p>javascript內容</p>
    <br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p>
</div>

【body元素】

<body data-spy="scroll" data-target="#myNavbar" style="height:300px;position:relative">

<div id="myNavbar" class="navbar navbar-default navbar-fixed-top" role="navigation">
     <ul class="nav navbar-nav">
        <li><a href="#html" tabindex="-1">HTML</a></li>
        <li><a href="#css" tabindex="-1">CSS</a></li>
        <li><a href="#javascript" tabindex="-1">javascript</a></li>
     </ul>
</div>

<h4 id="html" style="margin-top:150px">Html</h4>
<p>Html內容</p>
<br><p>...</p><br><p>...</p><br><p>...</p>
<h4 id="css">CSS</h4>
<p>CSS內容</p>
<br><p>...</p><br><p>...</p><br><p>...</p>
<h4 id="javascript">javascript</h4>
<p>javascript內容</p>
<br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p>

</body>

 

JS調用

  在Bootstrap框架中,使用JavaScript方法觸發滾動監控器相對來說較為簡單,只需要指定兩個容器的名稱即可

<div id="myNavbar" class="navbar navbar-default navbar-fixed-top" role="navigation">
     <ul class="nav navbar-nav">
        <li><a href="#html" tabindex="-1">HTML</a></li>
        <li><a href="#css" tabindex="-1">CSS</a></li>
        <li><a href="#javascript" tabindex="-1">javascript</a></li>
     </ul>
</div>
<div id="scrollspy"  style="margin-top:150px;height:250px;overflow:auto;position:relative">
    <h4 id="html">Html</h4>
    <p>Html內容</p>
    <br><p>...</p><br><p>...</p><br><p>...</p>
    <h4 id="css">CSS</h4>
    <p>CSS內容</p>
    <br><p>...</p><br><p>...</p><br><p>...</p>
    <h4 id="javascript">javascript</h4>
    <p>javascript內容</p>
    <br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p>
</div>
<script>
$('#scrollspy').scrollspy({ target: '#myNavbar' })    
</script>

 

方法

  當使用滾動監聽插件的同時在 DOM 中添加或刪除元素後,需要像下麵這樣調用此刷新( refresh) 方法 

$('[data-spy="scroll"]').each(function () {
  var $spy = $(this).scrollspy('refresh')
})

  要註意的是,這種refresh方法只對聲明式用法有效。如果使用的是JS觸發,並且需要刷新DOM,則需要重新應用該插件;或者從data-scrollspy屬性上獲取該實例,然後再調用refresh方法

【參數】

  可以通過 data 屬性或 JavaScript 傳遞參數。對於 data 屬性,其名稱是將參數名附著到 data- 後面組成,例如 data-offset=""

  滾動監控提供了一個offset參數,此參數預設值為10。預設情況下,滾動內容距離滾動容器10px以內的話,就高亮顯示所對應的菜單項

【事件】

  滾動監控也支持事件的訂閱和觸發功能,目前只支持一個activate事件

activate.bs.scrollspy    每當一個新條目被激活後都將由滾動監聽插件觸發此事件。
<div id="myNavbar" class="navbar navbar-default navbar-fixed-top" role="navigation">
     <ul class="nav navbar-nav">
        <li><a href="#html" tabindex="-1">HTML</a></li>
        <li><a href="#css" tabindex="-1">CSS</a></li>
        <li><a href="#javascript" tabindex="-1">javascript</a></li>
     </ul>
</div>
<div id="scrollspy" data-spy="scroll" data-target="#myNavbar"  data-offset="0" style="margin-top:150px;height:250px;overflow:auto;position;relative">
    <h4 id="html">Html</h4>
    <p>Html內容</p>
    <br><p>...</p><br><p>...</p><br><p>...</p>
    <h4 id="css">CSS</h4>
    <p>CSS內容</p>
    <br><p>...</p><br><p>...</p><br><p>...</p>
    <h4 id="javascript">javascript</h4>
    <p>javascript內容</p>
    <br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p><br><p>...</p>
</div>
<script>
$(function(){
    $("#myNavbar").on('activate.bs.scrollspy',function(e){
        $(e.target).siblings().css('outline','none')
            .end().css('outline','1px solid black');    
    })
})    
</script>

 

JS源碼

【1】IIFE

  使用立即調用函數,防止插件內代碼外泄,從而形成一個閉環,並且只能從jQuery的fn里進行擴展

+function ($) {
    //使用es5嚴格模式
    'use strict';
    //
}(window.jQuery);

【2】初始設置

  function ScrollSpy(element, options) {
    this.$body          = $(document.body)
    //判斷滾動容器是否是body,如果是則使用window,如果不是則使用該元素本身
    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
    //將預設值和傳進來的options參數合併,後者優先順序高
    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
    //如果option里設置了target,即data-target有值,則優先使用
    //如果沒有,則查找通過.nav樣式的子元素,即.nav樣式內的li子元素內的a鏈接,作為菜單容器
    this.selector       = (this.options.target || '') + ' .nav li > a'
    this.offsets        = []
    this.targets        = []
    //高亮顯示的菜單
    this.activeTarget   = null
    this.scrollHeight   = 0
    //給滾動容器綁定滾動事件
    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
    //計算當前頁面內所有滾動容器內的id集合和每個id元素距離瀏覽器頂部的像素距離
    this.refresh()
    //開始正式處理
    this.process()
  }
  //版本是3.3.7
  ScrollSpy.VERSION  = '3.3.7'
  //預設值為offset:10
  ScrollSpy.DEFAULTS = {
    offset: 10
  }

【3】插件核心代碼

  //獲取滾動容器的滾動高度
  ScrollSpy.prototype.getScrollHeight = function () {
    //獲取特定滾動容器的滾動高度,如果沒有則獲取body元素的滾動高度
    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
  }

  ScrollSpy.prototype.refresh = function () {
    var that          = this
    var offsetMethod  = 'offset'
    var offsetBase    = 0

    this.offsets      = []
    this.targets      = []
    this.scrollHeight = this.getScrollHeight()

    if (!$.isWindow(this.$scrollElement[0])) {
      offsetMethod = 'position'
      offsetBase   = this.$scrollElement.scrollTop()
    }

    this.$body
      .find(this.selector)
      .map(function () {
        var $el   = $(this)
        var href  = $el.data('target') || $el.attr('href')
        var $href = /^#./.test(href) && $(href)
        //返回一個二維數組,每個滾動容器內的id對象到頁面頂部的距離以及高亮菜單容器里所對應的href值
        return ($href
          && $href.length
          && $href.is(':visible')
          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
      })
      .sort(function (a, b) { return a[0] - b[0] })
      .each(function () {
        //收集所有的偏移值,也就是距離top的距離
        that.offsets.push(this[0])
        //收集菜單容器里的所有href值,也就是滾動容器里的id值
        that.targets.push(this[1])
      })
  }

  ScrollSpy.prototype.process = function () {
    //獲取滾動容器的scrollTop,再加上設置的offset值
    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
    //獲取滾動高度
    var scrollHeight = this.getScrollHeight()
    //最大滾動=總scrollheight + 設置的offset值 - 設置高度height
    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
    var offsets      = this.offsets
    var targets      = this.targets
    var activeTarget = this.activeTarget
    var i
    if (this.scrollHeight != scrollHeight) {
      this.refresh()
    }
    //如果超過了最大滾動,說明已經滾動到底了
    if (scrollTop >= maxScroll) {
      //如果最後一個元素還沒有高亮,則設置最後一個元素高亮
      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
    }

    if (activeTarget && scrollTop < offsets[0]) {
      this.activeTarget = null
      return this.clear()
    }
    //倒序遍歷所有元素的offset
    for (i = offsets.length; i--;) {
      //如果i元素不等於當前高亮元素
      activeTarget != targets[i]
        //滾動高度 大於 i元素的offsets
        && scrollTop >= offsets[i]
        //i+1元素不存在,或者i+1元素大於滾動高度
        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
        //則設置i為高亮元素
        && this.activate(targets[i])
    }
  }

  //設置高亮菜單元素
  ScrollSpy.prototype.activate = function (target) {
    //賦值實例屬性
    this.activeTarget = target

    this.clear()
    //查找菜單中符合[data-target+"#' + 所高亮元素的id + '"]屬性的元素
    //或者href值是#' +  所高亮元素的id + '的話,也可以
    var selector = this.selector +
      '[data-target="' + target + '"],' +
      this.selector + '[href="' + target + '"]'
    //查找父元素li,然後添加active高亮樣式
    var active = $(selector)
      .parents('li')
      .addClass('active')
    //如果li元素的父元素有dropdown-menu樣式,則表示是一個dropdown下拉菜單
    if (active.parent('.dropdown-menu').length) {
      active = active
        .closest('li.dropdown')
        //則需要給dropdown的li元素也加上active高亮樣式
        .addClass('active')
    }
    //觸發自定義高亮事件
    active.trigger('activate.bs.scrollspy')
  }
  
  //刪除其他高亮元素的active樣式
  ScrollSpy.prototype.clear = function () {
    $(this.selector)
      .parentsUntil(this.options.target, '.active')
      .removeClass('active')
  }

【4】jQuery插件定義

  function Plugin(option) {
    //根據選擇器,遍歷所有符合規則的元素
    return this.each(function () {
      var $this   = $(this)
      //獲取自定義屬性bs.scrollspy的值
      var data    = $this.data('bs.scrollspy')
      //如果option參數是對象,則作為ScrollSpy的參數傳入
      var options = typeof option == 'object' && option
      //如果值不存在,則將ScrollSpy實例設置為bs.scrollSpy值
      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
      //如果option傳遞了string,則表示要執行某個方法
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.scrollspy
  //保留其他庫的$.fn.modal代碼(如果定義的話),以便在noConflict之後可以繼續使用該老代碼
  $.fn.scrollspy             = Plugin
  //重設插件構造器,可以通過該屬性獲取插件的真實類函數
  $.fn.scrollspy.Constructor = ScrollSpy

【5】防衝突處理

  $.fn.scrollspy.noConflict = function () {
     //恢復以前的舊代碼
    $.fn.scrollspy = old
    //將$.fn.scrollspy.noConflict()設置為Bootstrap的Scrollspy插件
    return this
  }

【6】綁定觸發事件

  $(window).on('load.bs.scrollspy.data-api', function () {
    //遍歷所有符合條件的滾動容器
    $('[data-spy="scroll"]').each(function () {
      var $spy = $(this)
      //執行scrollspy插件,並傳入滾動容器上設置的自定義參數(data-開頭)
      Plugin.call($spy, $spy.data())
    })
  })

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目描述 Zxl有一次決定製造一條項鏈,她以非常便宜的價格買了一長條鮮艷的珊瑚珠子,她現在也有一個機器,能把這條珠子切成很多塊(子串),每塊有k(k>0)個珠子,如果這條珠子的長度不是k的倍數,最後一塊小於k的就不要拉(nc真浪費),保證珠子的長度為正整數。 Zxl喜歡多樣的項鏈,為她應該怎樣選擇數 ...
  • python內置封裝了很多常見的網路協議的庫,因此python成為了一個強大的網路編程工具,這裡是對python的網路方面編程的一個簡單描述。 urllib 和 urllib2模塊 urllib 和urllib2是python標準庫中最強的網路工作庫。這裡簡單介紹下urllib模塊。本次主要用url ...
  • 題目描述 如題,給出一個網路圖,以及其源點和匯點,求出其網路最大流。 輸入輸出格式 輸入格式: 第一行包含四個正整數N、M、S、T,分別表示點的個數、有向邊的個數、源點序號、匯點序號。 接下來M行每行包含三個正整數ui、vi、wi,表示第i條有向邊從ui出發,到達vi,邊權為wi(即該邊最大流量為w ...
  • md5解密網站:http://cmd5.la 網站語言:php 免費指數:★★★ (8位內小寫數字字母免費,11位內數字免費) 解密範圍:★★★★☆ (覆蓋了1-12位很多常用密碼和特殊密碼) 解密類型:★★★★☆ (1-3次md5解密,ntlm,sha1,mysql4/5密碼,ntlm,部分加鹽和 ...
  • 封裝 1.為什麼要封裝? 封裝就是要把數據屬性和方法的具體實現細節隱藏起來,只提供一個介面。封裝可以不用關心對象是如何構建的 2.封裝包括數據的封裝和函數的封裝,數據的封裝是為了保護隱私,函數的封裝是為了隔離複雜度 3.數據的封裝就是在屬性前面加一個__ 咦,報錯了,讓我們打開對象的名稱空間,看看發 ...
  • 題目描述 有一個a*b的整數組成的矩陣,現請你從中找出一個n*n的正方形區域,使得該區域所有數中的最大值和最小值的差最小。 輸入輸出格式 輸入格式: 第一行為3個整數,分別表示a,b,n的值 第二行至第a+1行每行為b個非負整數,表示矩陣中相應位置上的數。每行相鄰兩數之間用一空格分隔。 輸出格式: ...
  • 1.什麼是繼承? 使一個類擁有另一個類全部公開的屬性與行為的一種機制。 2.繼承的目的 假如一個類擁有另一個類的全部行為與屬性,並且這些屬性與行為數量較大,同時為其他類所共用,可以將這個類定義為子類去繼承另一個類,實現代碼復用。 3.繼承的影響 子類擁有了父類中非private的方法與屬性。 4.繼 ...
  • 1、獲取已勾選的行: var rows = $('#datagrid').datagrid('getChecked'); 2、判斷checkbox是否全選: var allFlg = $(".datagrid-header-check").find("input").is(":checked"); ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...