将事件侦听器添加到弹出菜单中<ul>中包含的list元素

时间:2017-01-30 21:00:41

标签: javascript google-chrome dom google-chrome-extension

我正在尝试创建一个扩展程序,您可以在弹出菜单的输入框中输入数据。每次启动弹出菜单时都应保存并显示此数据。您应该可以通过单击元素从列表中删除数据。我已经能够弄清楚如何存储数据点,但我无法删除它。 这是popup.js

// global variables
var urlList=[];

document.addEventListener('DOMContentLoaded', function() {
    getUrlListAndRestoreInDom();
    // event listener for pressing enter
    var input = document.getElementById('url');
    input.addEventListener("keyup", function(event){
		if(event.keyCode == 13){
			workTab = input.value;
				if (workTab.length>0 && urlList.indexOf(workTab) === -1){
					addUrlToListAndSave(workTab);
            		addUrlToDom(workTab);
				}	
				input.value ="";
			}	
		});	
});
document.querySelectorAll('ul li').forEach(function(click){
		click.addEventListener("click",function(){
			alert(this.id);
			console.log(document)		
		})
	});

	   
function getUrlListAndRestoreInDom(){
    chrome.storage.local.get({urlList:[]},function(data){
        urlList = data.urlList;
        urlList.forEach(function(url){
            addUrlToDom(url);
        });
    });
}

function addUrlToDom(url){
    var newLine = document.createElement('li');
    newLine.textContent = url;
    newLine.setAttribute("id", url);
    document.getElementById("list").appendChild(newLine);
}

function addUrlToListAndSave(url){
    if(urlList.indexOf(url) === -1){
        //URL is not already in list
        urlList.push(url);
        saveUrlList();
    }
}
function removeUrlAndSave(url){
	myarray.splice($.inArray(url, urlList), 1);
	saveUrlList();
}

function saveUrlList(callback){
    chrome.storage.local.set({urlList},function(){
        if(typeof callback === 'function'){
            //If there was no callback provided, don't try to call it.
            callback();
        }
    });
}

这是popup.html:

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="popup.css" />
</head>
<body>
	<div id="container">
		<input type="url" id ="url" placeholder="timetowork.com">
		<ul id = "list">
			<li id="google">google</li>
   		    <li id="bbc">bbc</li>
		</ul>
	</div>
</body>

<script type="text/javascript" src="jquery.js"></script>
<script src="popup.js"></script>
</html>

如您所见,我试图在用户点击数据点时触发事件。最终发生的事情是,如果列表元素已经在原始HTML文件中,则会触发。否则,如果是通过输入框添加的,则不会。

2 个答案:

答案 0 :(得分:0)

您在首次加载页面时添加了事件侦听器,因此我猜测不会将它们添加到生成的字段中。本节

document.querySelectorAll('ul li').forEach(function(click){
    click.addEventListener("click",function(){
        alert(this.id);
        console.log(document)       
    })
});

需要在生成字段后运行。

答案 1 :(得分:0)

您的问题是,在添加事件侦听器后,您在<li>下添加了<ul>个元素。因此,新元素没有分配click事件侦听器。有两种方法可以解决这个问题:

  1. 在添加时为每个元素添加事件侦听器。
  2. 使用所谓的事件委派。这是在您感兴趣的人的祖先元素上添加事件侦听器,然后仅在event.target匹配您希望执行某些操作的元素的条件时才执行操作。

    在这种情况下,最简单的方法是向<ul>添加一个事件监听器,然后仅在event.target<li>时执行某些操作。因此,添加click事件侦听器可能会更改为:

    document.querySelector('ul').addEventListener("click",function(event){
        if(event.target.nodeName !=='LI') {
            return;
        }
        alert(event.target.id);
        //Way too much information:
        //console.log(document)     
    });
    
  3. 演示更改的片段

    下面是一个代码段,演示代码只是按照上面提到的更改运行。

    HTML中有一些额外的代码会伪造chrome.storage.local以便在此代码段中使用。 HTML的所有更改都不应该应用于您的扩展程序。他们用于在片段中演示这一点。

    我没有添加代码来移除点击的<li>,因为这实际上并不是您问题的一部分。

    &#13;
    &#13;
    // global variables
    var urlList=[];
    
    document.addEventListener('DOMContentLoaded', function() {
        getUrlListAndRestoreInDom();
        // event listener for pressing enter
        var input = document.getElementById('url');
        input.addEventListener("keyup", function(event){
            if(event.keyCode == 13){
                workTab = input.value;
                if (workTab.length>0 && urlList.indexOf(workTab) === -1){
                    addUrlToListAndSave(workTab);
                    addUrlToDom(workTab);
                }	
                input.value ="";
            }	
        });	
    });
    document.querySelector('ul').addEventListener("click",function(event){
        if(event.target.nodeName !=='LI') {
            return;
        }
        alert(event.target.id);
        //Way too much information:
        //console.log(document)		
    });
    	   
    function getUrlListAndRestoreInDom(){
        chrome.storage.local.get({urlList:[]},function(data){
            urlList = data.urlList;
            urlList.forEach(function(url){
                addUrlToDom(url);
            });
        });
    }
    
    function addUrlToDom(url){
        var newLine = document.createElement('li');
        newLine.textContent = url;
        newLine.setAttribute("id", url);
        document.getElementById("list").appendChild(newLine);
    }
    
    function addUrlToListAndSave(url){
        if(urlList.indexOf(url) === -1){
            //URL is not already in list
            urlList.push(url);
            saveUrlList();
        }
    }
    function removeUrlAndSave(url){
        myarray.splice($.inArray(url, urlList), 1);
        saveUrlList();
    }
    
    function saveUrlList(callback){
        chrome.storage.local.set({urlList},function(){
            if(typeof callback === 'function'){
                //If there was no callback provided, don't try to call it.
                callback();
            }
        });
    }
    &#13;
    <!DOCTYPE html>
    <html>
    <head>
    <!--You need the following line, but for faking this in a snippet, it is commented out
    <link rel="stylesheet" type="text/css" href="popup.css" />
    -->
      <!-- Fake Chrome storage.local DON'T PUT THIS IN YOUR Chrome extension it is only
             for testing in a Stack Overflow snippet.-->
      <script>
        var chrome = {
          storage: {
            local: {
              storage:{},
              set: function(obj,callback){
                //This properly stores things that the real API does not.
                Object.keys(obj).forEach(prop=>{
                  chrome.storage.local.storage[prop] = JSON.stringify(obj[prop]);
                });
                if(typeof callback === 'function') callback();
              },
              get: function(arg1,callback){
                let output={};
                let obj = typeof arg1 === 'object' && !Array.isArray(arg1) && arg1 !== null?arg1:{};
                props = typeof arg1 === 'string'?[arg1]:Array.isArray(arg1)?arg1:arg1 === null?Object.keys(chrome.storage.local.storage):Object.keys(arg1);
                props.forEach(prop=>{
                  output[prop]= typeof chrome.storage.local.storage[prop] !== 'undefined'?JSON.parse(chrome.storage.local.storage[prop]):obj[prop];
                });
                if(typeof callback === 'function') callback(output);
              }
            }
          }
        };
      </script>  
    </head>
    <body>
    	<div id="container">
    		<input type="url" id ="url" placeholder="timetowork.com"> &nbsp;←&nbsp;Enter a URL to add it to the list. Below, click to alert that item:
    		<ul id = "list">
    			<li id="google">google</li>
       		    <li id="bbc">bbc</li>
    		</ul>
    	</div>
    </body>
    <!--You need the following 2 lines, but for faking this in a snippet, they are commented out
    <script type="text/javascript" src="jquery.js"></script>
    <script src="popup.js"></script>
    -->
    
    </html>
    &#13;
    &#13;
    &#13;