每日记载内容总结27
1.只用css美化下拉框实现:在select下拉框外面套一层div,这个div比下拉框的width短,然后设置overflow:hidden,隐藏掉原来的下拉框的下拉点击按钮,设置div的背景图片,用自己的图片来代替下拉框的原来按钮。(需要设置select背景透明background:transparent; )
现在的效果是进入网页加载之后,div的背景图片是一个图片,然后鼠标悬浮到select(当然也悬浮到select外面的div上面了),div的背景图片改为另外一个图片,而且还要改变select的字体颜色以及select外div的背景颜色
出现的问题:(1)在css中设置改变select的字体颜色,在ie9以及以下版本失效
.styled-select:hover select{ color: white; /*font-size : 25px; background-color : white; */ }
上面的css设置字体以及背景颜色都可以,唯独设置字体没有效果,至今不知道为何。
(2)上面问题解决不了,于是转投js实现,又遇到问题。这次,鼠标悬浮事件可以了,注意一点的是在ie9以及以下版本设置select下拉框字体颜色,需要设置select option的颜色,而在别的情况下,设置select的颜色就可以了。这次遇到的问题是点击下拉框之后会自动缩回去。后来研究之后发现原因如下:鼠标点击的时候,虽然位置是在select上面(当然也悬浮到select外面的div上面了),但是mousedown会触发select的悬浮离开事件,然后mouseup之后,悬浮又回来了,明明一直在select框上面。这个问题依旧没解决……
上面两个问题有哪位知道如何解决的话,请留言
2.js或者jquery屏蔽事件(以鼠标离开为例)
js:document.getElementById("element").onmouseout = null ;
jquery :$("#element").attr("onmouseout",null);
3.js或者jquery修改className
js:document.getElementById("element").className = "XXX";
jquery : $("#element").attr("class","XXX");
4.刚刚看了一篇关于dom event的文章,现将部分知识点记录如下:(原文链接:http://www.cnblogs.com/ziran/p/3458834.html)
(1)给对象添加监听事件
var element = document.getElementById('element'); function callback() { alert('Hello'); } // Add listener element.addEventListener('click', callback);
(2)给对象移除监听事件
用removeElementListener函数,有一点需要注意的是:必须要有这个被绑定的回调函数的引用。简单地调用element.removeEventListener('click');是不能达到想要的效果的。还有就是我们不能使用匿名函数作为回调函数。
var element = document.getElementById('element'); function callback() { alert('Hello once'); element.removeEventListener('click', callback); } // Add listener element.addEventListener('click', callback);
或者是依靠别的元素事件来移除监听
var element = document.getElementById('element'); var remoelement = document.getElementById('remoelement'); function callback() { alert('Hello once'); } // Add listener element.addEventListener('click', callback); remoelement.onclick = function remove(){ element.removeEventListener('click', callback); }
(3).回调函数上下文引用
一个很容易遇到的问题就是回调函数没有在预想的运行上下文被调用.例如如下例子:
var element = document.getElementById('element'); var user = { firstname: 'Wilson', greeting: function(){ alert('My name is ' + this.firstname); } }; // Attach user.greeting as a callback element.addEventListener('click', user.greeting); // alert => 'My name is undefined'
我们希望回调函数中能够正确的输出”My name is Wilson”。事实上,结果确是”My name is undefined”。为了使得 this.firstName 能够返回”Wilson”,user.greeting必须在user对象的上下文环境(context)中被执行(这里的运行上下文指的是.号左边的对 象)。
当我们将greeting函数传给addEventListener方法的时候,我们传递的是一个函数的引用;user相应的上下文并没有传递过去。 运行的时候,这个回调函数实际上是在element的上下文中被执行了,也就是说,在运行的时候,this指向的是element,而不是user。所以 this.firstName是undefined。
有两种方式可以避免这种上下文错误的问题。第一种方法,我们可以在一个匿名函数内部调用user.greeting()方法,从而获得正确的函数执行上下文(user)。
element.addEventListener('click', function() { user.greeting(); // alert => 'My name is Wilson' });
上一种方式并不是非常好,因为我们不能获得回调函数的句柄以便后面通过.removeEventListener()移除事件监听。另外,这种方式也 比较丑陋。。我更喜欢使用.bind()方法(做为ECMAScript 5的标准内建在所有的函数对象中)来生成一个新的函数(被绑定过的函数),这个函数会在指定的上下文中被执行。然后我们将这个被绑定过的函数作为参数传 给.addEventListener()的回调函数。
var element = document.getElementById('element'); var helloelement = document.getElementById('helloelement'); var user = { firstname: 'Bob', greeting: function(){ alert('My name is ' + this.firstname); } }; // Overwrite the original function with // a new function with its execution // context 'bound' to the user object user.greeting = user.greeting.bind(user); // Add the bound function as the callback element.addEventListener('click', user.greeting); helloelement.onclick = function(){ element.removeEventListener('click', user.greeting); }
(4).事件阶段(Event Phases)
当一个DOM事件被触发的时候,它并不只是在它的起源对象上触发一次,而是会经历三个不同的阶段。简而言之:事件一开始从文档的根节点流向目标对象(捕获阶段),然后在目标对向上被触发(目标阶段),之后再回溯到文档的根节点(冒泡阶段)。
(4.1)事件捕获阶段(Capture Phase)
事件的第一个阶段是捕获阶段。事件从文档的根节点出发,随着DOM树的结构向事件的目标节点流去。途中经过各个层次的DOM节点,并在各节点上触发捕 获事件,直到到达事件的目标节点。捕获阶段的主要任务是建立传播路径,在冒泡阶段,事件会通过这个路径回溯到文档跟节点。
(4.2)目标阶段(Target Phase)
当事件到达目标节点的,事件就进入了目标阶段。事件在目标节点上被触发,然后会逆向回流,直到传播至最外层的文档节点。
对于多层嵌套的节点,鼠标和指针事件经常会被定位到最里层的元素上。假设,你在一个<div>元素上设置了click事件的监听函数,而 用户点击在了这个<div>元素内部的<p>元素上,那么<p>元素就是这个事件的目标元素。事件冒泡让我们可以在 这个<div>(或者更上层的)元素上监听click事件,并且事件传播过程中触发回调函数。
(4.3)冒泡阶段(Bubble Phase)
事件在目标元素上触发后,并不在这个元素上终止。它会随着DOM树一层层向上冒泡,直到到达最外层的根节点。也就是说,同一个事件会依次在目标节点的父节点,父节点的父节点。。。直到最外层的节点上被触发。
将DOM结构想象成一个洋葱,事件目标是这个洋葱的中心。在捕获阶段,事件从最外层钻入洋葱,穿过途径的每一层。在到达中心后,事件被触发(目标阶段)。然后事件开始回溯,再次经过每一层返回(冒泡阶段)。当到达洋葱表面的时候,这次旅程就结束了。
(5).停止传播(Stopping Propagation)
可以通过调用事件对象的stopPropagation方法,在任何阶段(捕获阶段或者冒泡阶段)中断事件的传播。此后,事件不会在后面传播过程中的经过的节点上调用任何的监听函数。
child.addEventListener('click', function(event) { event.stopPropagation(); }); parent.addEventListener('click', function(event) { // If the child element is clicked // this callback will not fire });
var overlay = document.querySelector('.overlay'); overlay.addEventListener('click', function(event) { event.stopPropagation(); }); // Remove the overlay when a 'click' // is heard on the document (<html>) element document.addEventListener('click', function(event) { overlay.parentNode.removeChild(overlay); });
调用event.stopPropagation()不会阻止当前节点上此事件其他的监听函数被调用。如果你希望阻止当前节点上的其他回调函数被调用的话,你可以使用更激进的event.stopImmediatePropagation()方法。
(6). 阻止浏览器默认行为
我们需要阻止浏览器针对点击事件的默认行为,而使用我们自己的处理方式。这时,我们就需要调用event.preventDefault().
调用event.stopPropagation()只会阻止传播链中后续的回调函数被触发。它不会阻止浏览器的自身的行为。
var a = document.querySelector('a'); // Listen for clicks and prevent the default // browser behaviour (following the href url) a.addEventListener('click', function(event) { event.preventDefault(); alert('Default behaviour prevented'); });
(7).代理事件监听可以让你使用一个事件监听器去监听大量的DOM节点的事件,在这种情况下,它是一种更加方便并且高性能的事件监听方法。举例来说,如果有 一个列表<ul>包含了100个子元素<li>,它们都需要对click事件做出相似的响应,那么我们可能需要查询这100个子 元素,并分别为他们添加上事件监听器。这样的话,我们就会产生100个独立的事件监听器。如果有一个新的元素被添加进去,我们也需要为它添加同样的监听 器。这种方式不但代价比较大,维护起来也比较麻烦。
代理事件监听可以让我们更简单的处理这种情况。我们不去监听所有的子元素的click事件,相反,我们监听他们的父元素<ul>。当一 个<li>元素被点击的时候,这个事件会向上冒泡至<ul>,触发回调函数。我们可以通过检查事件的event.target属 性来判断具体是哪一个<li>被点击了。
var list = document.querySelector('ul'); list.addEventListener('click', function(event) { var target = event.target; while (target.tagName !== 'LI') { target = target.parentNode; if (target === list) return; } // Do stuff here });
这样就好多了,我们仅仅使用了一个上层的事件监听器,并且我们不需要在为添加元素而考虑它的事件监听问题。这个概念很简单,但是非常有用。
但是我并不建议你在你的项目中使用上面的这个粗糙的实现。可以使用jQuery,你可以在调用.on()方法的时候,将一个选择器作为第二个参数的方式来轻松的实现事件代理。
// Bind an event listener to each // item in the list (bad) $('.list-1 li').on('click', callback); // Bind single 'delegate' listener // to the list and trigger callback // if event came from an decendent // matching the given selector (good) $('.list-2').on('click', 'li', callback); function callback() { alert('With delegate event handlers we get the same functionality with less overhead and more convenience :)'); }
(8).window.onbeforeunload让开发人员可以在想用户离开一个页面的时候进行确认。
需要注意的是,对页面添加onbeforeunload处理会导致浏览器不对页面进行缓存,这样会影响页面的访问响应时间。 同时,onbeforeunload的处理函数必须是同步的(synchronous)。
(9)resize函数 可以用js来动态控控制元素的样式
var span = document.querySelector('span'); function update() { span.innerHTML = window.innerWidth + ' x ' + window.innerHeight; } update(); window.addEventListener('resize', update);