使用jQuery动态调整iframe高度,以及jQuery对dom元素的监听

  大家可能会遇到子页面内容较多但iframe高度不够的情况。给iframe设置scrolling="no"的话子页面内容显示不全,不设置又会出现滚动条从而影响美观。当我们点击不同的菜单让iframe加载不同的html文件时,iframe的高度就需要做相应的调整。

主题思路:子页面加载完成后根据具体body的高度给iframe设置一个适合的高度

情况1:各个子页面内容与高度比较固定

<script>
$(function(){
  $("#Frame_Content").load(function(){
    var frame_content = $(this);
    //获取子页面body的高度 并适量增加
    var mainheight = frame_content.contents().find("body").height()+30;
    //给iframe设置高度(不低于350)
    frame_content.height(Math.max(mainheight,350));
  });
});
</script>
<iframe class="main" onload="this.height=350" frameborder="0" scrolling="no" id="Frame_Content" name="content"></iframe>

  这样每次加载完子页面,就可以根据实际的内容来给iframe设置相应的高度。

情况2:子页面本身内容在不断变化

  有的情况下,子页面发起Ajax请求,从后台拿到新的数据后增加或减少子页面的内容,如果只是在iframe load完成后设定好高度依然没办法真正地动态调整。到这里,我想大家肯定第一反应是使用监听事件。如果可以对子页面body的高度进行监听,那么每当内容有所调整的时候触发事件并对iframe的高度进行设置。不过这里有个问题,window对象有onresize事件,但普通的dom元素是没有的,也就是说想监听也没办法监听。想要解决这个问题,两条路摆在我们面前:

1.写一个轮询来不停的获取子页面body的高度,如果发生了变化就给iframe高度赋新的值;  
2.利用jquery的事件机制来模拟一个普通元素上的resize事件。(当然只要能实现resize事件,怎么弄都可以,这里只说jquery)

  仔细来看,其实1和2的原理是一样的,事件监听本质上其实应该也是轮询。但完整的事件机制肯定是比我们自己去写一个轮询要成熟的,而且适用所有的dom元素,如果自己写个轮询肯定能做的事就很单一,只有针对性的功能。因为我这里的页面只有一个主iframe,外面就一个框架,横向的主菜单和左侧纵向的二级、三级菜单,页面的主要内容都在iframe根据不同菜单加载的子页面里,等于说只要把唯一的iframe高度调整ok就行。这里我们不妨先简单搞一个轮询:

<script>
$(function(){
    var timer;
    $("#Frame_Content").load(function(){
        if (timer){
            clearInterval(timer);
        }
        //pre_height用于记录上次检查时body的高度
        //mainheight用于获取本次检查时body的高度,并赋予iframe的高度
        var mainheight,pre_height;
        var frame_content = $(this);
        timer = setInterval(function(){
            mainheight = frame_content.contents().find("body").height() + 30;
            if (mainheight != pre_height){
                pre_height = mainheight;
                frame_content.height(Math.max(mainheight,350));
             }
        },500);//每0.5秒检查一次
    });
});
</script>

  如果场景比较简单,一个轮询就可以搞定iframe动态调整高度的问题,比起自己写一个jquery的差价来实现resize事件肯定要轻量很多。但这样的做法毕竟是不够完善的,如果有的页面需要对多个dom元素(不局限于iframe)的高度进行监听,搞很多轮询看起来可能很不规范,同时也不便于管理。

  https://segmentfault.com/a/1190000000406026这篇文章里提到一个插件已经实现了上述的功能,并贴出了核心代码。代码长度很短也很简单,感兴趣的话可以研究一下,实际上插件也是使用轮询来不断地检查所需要监听的dom元素的高度和宽度,我也在下面贴出来:

(function($, window, undefined) {
  var elems = $([]),
    jq_resize = $.resize = $.extend($.resize, {}),
    timeout_id,
    str_setTimeout = ‘setTimeout‘,
    str_resize = ‘resize‘,
    str_data = str_resize + ‘-special-event‘,
    str_delay = ‘delay‘,
    str_throttle = ‘throttleWindow‘;
  jq_resize[str_delay] = 250;
  jq_resize[str_throttle] = true;
  $.event.special[str_resize] = {
    setup: function() {
      if (!jq_resize[str_throttle] && this[str_setTimeout]) {
        return false;
      }
      var elem = $(this);
      elems = elems.add(elem);
      $.data(this, str_data, {
        w: elem.width(),
        h: elem.height()
      });
      if (elems.length === 1) {
        loopy();
      }
    },
    teardown: function() {
      if (!jq_resize[str_throttle] && this[str_setTimeout]) {
        return false;
      }
      var elem = $(this);
      elems = elems.not(elem);
      elem.removeData(str_data);
      if (!elems.length) {
        clearTimeout(timeout_id);
      }
    },
    add: function(handleObj) {
      if (!jq_resize[str_throttle] && this[str_setTimeout]) {
        return false;
      }
      var old_handler;
      function new_handler(e, w, h) {
        var elem = $(this),
          data = $.data(this, str_data);
        data.w = w !== undefined ? w : elem.width();
        data.h = h !== undefined ? h : elem.height();
        old_handler.apply(this, arguments);
      }
      if ($.isFunction(handleObj)) {
        old_handler = handleObj;
        return new_handler;
      } else {
        old_handler = handleObj.handler;
        handleObj.handler = new_handler;
      }
    }
  };

  function loopy() {
    timeout_id = window[str_setTimeout](function() {
      elems.each(function() {
        var elem = $(this),
          width = elem.width(),
          height = elem.height(),
          data = $.data(this, str_data);
        if (width !== data.w || height !== data.h) {
          elem.trigger(str_resize, [data.w = width, data.h = height]);
        }
      });
      loopy();
    }, jq_resize[str_delay]);
  }
})(jQuery, this);

  jquery的事件机制和插件的写法这里就不具体解析了,网上搜一下都可以找到。这方面我也没有深入的学习,不过只要了解一下要点就能看明白上面的插件代码了。

  不想了解,也可以直接拿来用:

//bind resize事件
$("body").bind(‘resize‘,function(){
    //callback
    //...
    //...
});

ps:

  正常情况下对页面中的dom元素高宽进行监听使用上面的插件应该是没什么问题的,但如果有和我一样是对iframe子页面的body进行监听可能会遇到报错。

  看过插件的源码后,会发现当我们对n个dom元素bind resize事件时,实际上有一个队列,轮询中会对队列的每一个元素都检查高宽有没有变化,如果高宽改变了就触发resize事件,从而执行我们自己定义的回调函数。unbind后会把相应的元素从队列中踢掉。我这里的场景是,每个菜单项的target都指向同一个iframe,点击不同的菜单项主iframe加载不同的页面。我在iframe完成load的时候给子页面的body bind resize事件。当切换菜单时,新的子页面加入队列,但老的子页面此时已经不存在了,遍历队列去取对应元素的高宽就会出错。对插件的源码进行修改可以解决这个问题,但我个人认为为了这个单一的目的去修改插件的源码还不如最初的时候就用一个简单的轮询搞定。所以不改源码的情况下,建议把bind放到子页面中去做,回调中调用父页面的接口来给iframe高度赋值。

时间: 2024-10-08 10:28:54

使用jQuery动态调整iframe高度,以及jQuery对dom元素的监听的相关文章

动态设置iframe高度

<%//动态设置iframe高度 %><script language="javascript" type="text/javascript">      function SetWinHeight(obj) {                              var win = obj;        if (document.getElementByIdx_x) {            if (win && !

05---MVC模式下动态调整Cell高度三部曲

动态调整Cell高度三部曲 我们在做项目开发的过程中经常会遇到每一个cell的高度及cell的子控件的显示个数不同,以我最近开发的微格为例,讲解一下MVC模式动态的调整Cell宽高的三部曲 1>.自定义Cell,重写- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier方法 在此方法中添加所有的可能显示的子控件 子控件的frame通过构建的cellFrame模型进行设置

iOS 动态调整tableViewCell 高度

效果图: 分析:从plist文件中读取数据源,plist最外层是一个Array,Array中存放的是字典,每个字典存放的key值并不完全相同. 一.单元格复用问题 1.首先读取数据源,建立数据模型,这里我只创建了一个数据模型,包含plist中所有的key值所对应的属性. 2.创建tableView,同时定制Cell, 根据category,可以分成四种单元格,在tableView创建单元格时创建4种代码如下: 1 -(UITableViewCell *)tableView:(UITableVie

自己编写jQuery动态引入js文件插件 (jquery.import.dynamic.script)

这个插件主要是结合jquery或者xhr异步请求来使用的,它可以把已经引入过的js文件记录在浏览器内存中,当下次再引入相同的文件就忽略该文件的引入. 当你用$.load("dir/my-page.jsp"); 或xhr.request("server/to-my-page");等异步请求加载html页面的时候,在页面中导入js文件用本插件进行引入的话, 那么其他请求的页面中也导入了和前面页面相当的js文件的情况下,那这些js文件就不需要重新引入.插件会自动忽略之前已

Android - 动态调整ListView高度

布局中,如果设计ListView的高度为包裹内容,那么ListView的高度是随着它的子条目的数量的变化而改变的, 这就可能会导致ListView下面的一些控件的位置也会随着ListView的高度的变化而变化. 项目中可能会碰到需要动态调整或控制ListView的高度的情况,下面就分享一下我自己使用的一种办法. 我遇到的问题: ListView下面有一个Button,如果ListView子条目的数量较少,Button可以正常显示在屏幕上,但如果ListView子条目的数量较多时,Button就会

jquery动态修改div高度

<!DOCTYPE html> <html> <head> <script src="jquery-1.4.2.min.js"></script> </head> <script type=text/javascript> $(function(){ //var a = $(window).height(); alert($(window).height()*0.6); $('div').css('he

H5特性 MutationObserver 监听元素 动态改变iframe高度

这些代码要写在iframe页中执行 <script type="text/javascript"> $(function () { // Firefox和Chrome早期版本中带有前缀 var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver // 选择目标节点 var target = document.body

根据文字动态调整 UILabel 高度

#import <UIKit/UIKit.h> @interface UILabel (dynamicSize) -(float)resizeToFit; -(float)expectedHeight; @end #import "UILabel+dynamicSize.h" @implementation UILabel (dynamicSize) -(float)resizeToFit{ float height = [self expectedHeight]; CGR

父子页面(iframe)相互获取对方dom元素

现在iframe的使用虽然开始越来越少,但是还是有牵涉到iframe的使用情况,特别是多个iframe互相嵌套,又要进行获取的情况. 现在整理了父子iframe之间互相获取的方式. (1)父页面获取子页面的方式. 主要通过: iframe的contentWindow属性,代表iframe所在的window对象. 示例如下: <script type="text/javascript"> window.onload = function(){ var cWindow = do