【问题标题】:Insert html based on array基于数组插入html
【发布时间】:2016-12-14 12:31:51
【问题描述】:

第 12-22 行

函数openManu 当前在加载时显示一个块,并为我的数组创建一个 for 循环。然后根据数组创建一个obj 变量,并从调用该函数的链接定义的数组中获取Manufacturer。因此,例如我的 HTML 中的链接将有一个 onMouseOver 事件绑定到 openManu('manufacturer') 并且 manu 将被定义为制造商,只有与该制造商对应的数组中的“描述”才会插入到 HTML 中。

我的问题是我正在尝试创建另一个在此之前运行的函数,该函数通过我的数组并根据数组中的内容创建链接。然后,由于一旦正文加载就会调用它,因此应该存在链接,并且链接还将具有 onMouseOver 事件,其中可以调用第 12-22 行的第二个函数。

目前只有openManu() 工作onMouseOver 并将基于指定制造商的Description 插入到我的HTML 称为内容的对象中。我拥有的 createLinks() 函数打开数组并将 URL 定义为变量并将其插入到创建的链接标记中。

这可能吗?订单是否搞砸了?

javascript:

var arr =   
[
  {
    "Manufacturer": "Any manufacturer",
    "Description": "Traditional values",
    "URL": "http://www.website.com"
  },
  {
    "Manufacturer": "Different Manufacturer",
    "Description": "Short description of said manufacturer",
    "URL": "http://www.website2.com"
  },
  {
    "Manufacturer": "A Similar Manufacturer",
    "Description": "Not quite the same as the previous manufacturer",
    "URL": "http://www.website3.com"
  },
  {
    "Manufacturer": "Manufacturer",
    "Description": "Essentially a ripoff of the first manufacturer",
    "URL": "http://www.website4.com"
  }
]

function createLinks() {
    for (var i=0; i<arr.length; i++){
      var obj = arr[i];
      var m = obj["Manufacturer"];
      if (manu == m) {
        URL = obj["URL"];
      }
    }
    document.getElementById('col').innerHTML = "<a onmouseover=\"openManu(\'" ++ m ++ "\')\" onmouseout=\"mouseOut()\" onClick=\"openWeb(\'" ++ URL ++ "\')\">" ++ m ++ "</a>");
}

function openManu(manu) {
  document.getElementById('content').style.display = 'block';
    for (var i=0; i<arr.length; i++){
      var obj = arr[i];
      var m = obj["Manufacturer"];
      if (manu == m) {
        desc = obj["Description"];  
      }
    }
    document.getElementById('content').innerHTML = desc;
}

window.onmousemove = function (e) {
    var tooltipSpan = document.getElementById('content');
    var x = e.clientX,
        y = e.clientY;
    tooltipSpan.style.top = (y - 20) + 'px';
    tooltipSpan.style.left = x + 'px';
}

var mouseOut = function(){
    document.getElementById('content').style.display = 'none'
}

function openWeb(URL) {
    window.open(URL);
}
#container{
width:870px;
margin-top:2em;
font-size:1.1em;
position:relative;
padding-left:20px;
display:inline-block;
background-color:#3C3C4E;}

#content{
z-index:1;
display:none;
width:300px;
font-size:16px;
font-family: 'Raleway', sans-serif;
position:absolute;
padding:10px;
background-color:white;}

a {
cursor:pointer;
padding:0;
display:inline-block;
margin:0;
color: white;
font-family: 'Raleway', sans-serif;
position:inherit;
}

h4 {
padding:0;
z-index:0;
display:inline-block;
margin:0;
color: white;
font-family: 'Raleway', sans-serif;
font-weight:normal;
font-size:15px;
background-color:#3C3C4E;
position:absolute;
left:8px;
padding:24px;
top:400px;
width:842px;
}

pre {
display:block;
float:left;
line-height:21px;
}
<!DOCTYPE html>
<html onload="createLinks()">

<div id="content"></div>

<pre id="col"></pre>

</html>

旧的 HTML 包含看起来像这样的链接。

<a onmouseover="openManu('Any manufacturer')" onmouseout="mouseOut()" onClick="openWeb('http://www.website.com/')">Any manufacturer</a>

@Zer00ne 响应您的回答,我将 createLinks() 更改为此。我无法让它工作我可能不完全理解你的解决方案。

function createLinks() {
  arr[i]["Manufacturer"]
  var obj = arr[i];
  var m = obj["Manufacturer"];
  document.getElementById('col').innerHTML = "<a onmouseover=\"openManu(\'" ++ m ++ "\')\" onmouseout=\"mouseOut()\" onClick=\"openWeb(\'" ++ URL ++ "\')\">" ++ m ++ "</a>");
}

JSFiddle

【问题讨论】:

  • 不会更容易做到这一点:arr[i]["Manufacturer"]var obj = arr[i]; var m = obj["Manufacturer"];
  • innerHTML 中添加 HTML 事件会让小猫哭泣。为什么不createElement('a') 直接在 JavaScript 中附加事件。在代码中使用函数引用比让浏览器解析 HTML 和 eval() 字符串更高效且更容易推理,这将引入 XSS(跨站点脚本)问题。
  • 我明白了,我已经纠正了createLinks(),但现在又出现了一系列错误......
  • >>Zer00ne 响应您的回答,我将 createLinks() 更改为此。我无法让它工作我可能不完全理解你的解决方案。innerHTML 生成的正确事件实际上确实让小猫哭了。我会走createElement('a') 的路,但我没时间了。

标签: javascript html arrays loops for-loop


【解决方案1】:

乍一看createLinks函数中的字符串变量拼接格式不正确。

function createLinks() {
    for (var i=0; i<arr.length; i++){
      var obj = arr[i];
      var m = obj["Manufacturer"];
      if (manu == m) {
        URL = obj["URL"];
      }
    }
    //document.getElementById('col').innerHTML = "<a onmouseover=\"openManu(\'" ++ m ++ "\')\" onmouseout=\"mouseOut()\" onClick=\"openWeb(\'" ++ URL ++ "\')\">" ++ m ++ "</a>");

// should be.
document.getElementById('col').innerHTML = "<a onmouseover=\"openManu(" + m + ") onmouseout=\"mouseOut()\" onClick=\"openWeb(" + URL + ") >" + m + "</a>";
}

// Although m and URL are never defined.

我也不确定您是否尝试将变量或字符串传递给 openMenu 函数,但我看到您正在检查 if 语句中的参数。

    function openManu(manu) {
      document.getElementById('content').style.display = 'block';
        for (var i=0; i<arr.length; i++){
          var obj = arr[i];
          var m = obj["Manufacturer"];
          if (manu == m) { 
            /* 
This will never be true because your argument (manu) comes from whatever you are passing into your function which appears to be a string based on your code. The m that is being assigned from the obj will never be 'm' based on the code. It will be the value that is assigned to the "Manufacturer" key of the object."
*/
            desc = obj["Description"];  
          }
        }
        document.getElementById('content').innerHTML = desc;
    }

我希望这是正在发生的事情的一个良好开端。

更新——这工作

此代码是基于您的 JSFiddle 代码。

HTML

<body onload="createLinks()">

<div id="container">
<pre id="col"></pre>
</div>
<div id="content2"></div>
</body>

CSS

#container{
width:300px;
margin-top:2em;
font-size:1.1em;
position:relative;
display:inline-block;
background-color:#3C3C4E;}


#content{
display:none;
width:300px;
height: 45px;
font-size:16px;
font-family: 'Raleway', sans-serif;
padding:10px;
background-color:white;
}

#col a{
  display:block;
  padding-left:20px;
}
a {
cursor:pointer;
padding:0;
display:inline-block;
margin:0;
color: white;
font-family: 'Raleway', sans-serif;
position:inherit;
}

h4 {
padding:0;
z-index:0;
display:inline-block;
margin:0;
color: white;
font-family: 'Raleway', sans-serif;
font-weight:normal;
font-size:15px;
background-color:#3C3C4E;
position:absolute;
left:8px;
padding:24px;
top:400px;
width:842px;
}

pre {
display:block;
float:left;
line-height:21px;
}

JavaScript

var arr =   
[
  {
    "Manufacturer": "Any manufacturer",
    "Description": "Traditional values",
    "URL": "http://www.website.com"
  },
  {
    "Manufacturer": "Different Manufacturer",
    "Description": "Short description of said manufacturer",
    "URL": "http://www.website2.com"
  },
  {
    "Manufacturer": "A Similar Manufacturer",
    "Description": "Not quite the same as the previous manufacturer",
    "URL": "http://www.website3.com"
  },
  {
    "Manufacturer": "Manufacturer",
    "Description": "Essentially a ripoff of the first manufacturer",
    "URL": "http://www.website4.com"
  }
];

// cache the col element
var col = document.getElementById("col")
// The forEach loop goes through the array 
arr.forEach( function(key, idx){ // grab the key an dthe index
    var newAchr = document.createElement("a"); // create an anchor DOM element
    newAchr.href = key.URL; // assign the href for the element
    newAchr.text = key.Manufacturer; // assign the text
    newAchr.setAttribute("class", idx); // assign a class that will store the index. This will be used to get the description on mouseover.

    document.getElementById('col').appendChild(newAchr); // apend the element to the DOM
});

col.addEventListener("mouseover", function(e){
    var target = e.target, //get the currently targeted anchor tag
        idx = target.classList[0], // get the index that wsa stored inthe elements class
        desc = arr[idx].Description, // get the description from the array usinf the index from the class
        contentElem = document.getElementById('content2'); // get a reference to the content element

    contentElem.style.display = "block"; // display the content area
    contentElem.innerHTML = desc; // add the discription text to the content area
});

col.addEventListener("mouseout", function(e){
    var contentElem = document.getElementById('content2'); // get a reference to the content area

    contentElem.style.display = "none"; // hide the content area on mouseout
});

【讨论】:

  • 因此设置了键 "Manufacturer" 应该取决于悬停在哪个链接上,然后是键的相应对象 "描述” 放置在内容块内。我更改了我的原始帖子以包含将 manu 参数传递给函数的旧 HTML 链接标记。它传递的参数应该与 "Manufacturer" 相关,并通过 onMouseOver 事件返回它的 "Description"。我试图消除对这些硬编码链接标签的需求,以便只需要修改数组。
  • 您不能使用 onmouseover 功能,除非您只想要放置在该功能中的“制造商”。它从不循环遍历数组。这些动作中的大部分应该放在它们自己的函数中,或者至少放在 click 函数中。
  • 看起来您正在尝试将数组索引与 HTML 中的菜单项匹配。您可以通过将菜单索引与数组索引匹配来做到这一点。
  • 对不起,我只是糊涂了。 openManu 完美无瑕,就像我需要的那样。它找到相应的描述并将其插入到 div 中。我唯一遇到的问题是对其进行更改,以便从 createLinks() 函数生成链接。我对 JS 很陌生,所以我的术语很弱,我很难理解。该数组与 HTML 中的链接匹配并显示描述。我应该打开一个 JSFiddle 吗?
  • JSFiddle 将使您更容易浏览。
【解决方案2】:

更新

添加了工具提示,我意识到你的意图是什么,#content 现在跟随光标。这可以解释我遇到的古怪风格。

我修好了,这个概念很合理,代码需要大量工作。我删除了 mousemove 事件处理程序,因为当您已经在 #content 中显示了描述时,工具提示毫无意义。以下片段在/* comments */// comments中有描述。

片段

/* Wrapped in an anonymous function to avoid globals */
(function() {
  var mfc = [{
    "Manufacturer": "Any manufacturer",
    "Description": "Traditional values",
    "URL": "http://www.website.com"
  }, {
    "Manufacturer": "Different Manufacturer",
    "Description": "Short description of said manufacturer",
    "URL": "http://www.website2.com"
  }, {
    "Manufacturer": "A Similar Manufacturer",
    "Description": "Not quite the same as the previous manufacturer",
    "URL": "http://www.website3.com"
  }, {
    "Manufacturer": "Manufacturer",
    "Description": "Essentially a ripoff of the first manufacturer",
    "URL": "http://www.website4.com"
  }];

  /* It's better to declare variable of 'for' loop outside of loop */
  var i, len = mfc.length;


  for (i = 0; i < len; i++) {
    // Use of bracket notation requires quotes 
    var m = mfc[i]["Manufacturer"];
    var URL = mfc[i]["URL"];
    var desc = mfc[i]["Description"];
    var col = document.getElementById('col');
    /*
    /| When concatenating strings, alternate between single and double
    /| quotes and don't double up on '+'
    */
    // title attribute will be "Description"
    // Just use href attribute instead of a function that does the same thing (i.e. openWeb(URL)
    // The text of an anchor is m
    /* 
    /| Notice the '+=' operand, this allows us to accumulate strings 
    /| instead of overwriting them on every loop. 
    */
    col.innerHTML += '<a title="' + desc + '" href="' + URL + '">' + m + '</a>';
  }
  var content = document.getElementById('content');


  /*
  /| Instead of attribute events, use addEventListener() on the 
  /| parent of the links (i.e. #col). In order to determine which anchor
  /| was clicked, you assign a var to event.target.
  */

  col.addEventListener("mouseover", function(e) {
    // Find the e.target (i.e. element that was hovered over), and get it's title
    // display content with desc as it's content.
    var desc = e.target.getAttribute('title');
    content.style.display = "block";
    content.innerHTML = desc;
  }, false);

  col.addEventListener("mouseleave", function(e) {
    content.style.display = "none";
  }, false);


  col.addEventListener("mousemove", function(e) {
    var x = e.clientX,
      y = e.clientY;
    content.style.top = (y - 20) + 'px';
    content.style.left = x + 'px';
  }, false);

})();
#container {
  width: 870px;
  line-height: 1.2;
  margin-top: 2em;
  font-size: 1.1em;
  position: relative;
  padding-left: 20px;
  display: inline-block;
  background-color: #3C3C4E;
}
#content {
  z-index: 0;
  display: none;
  width: 400px;
  font-size: 16px;
  font-family: 'Raleway', sans-serif;
  position: absolute;
  padding: 10px;
  color: white;
  background-color: black;
  top: 0;
}
col {
  position: absolute;
  top: 70px;
}
a {
  cursor: pointer;
  padding: 0;
  display: inine-block;
  margin: 0 5px;
  color: white;
  font-family: 'Raleway', sans-serif;
}
h4 {
  padding: 0;
  z-index: 0;
  display: inline-block;
  margin: 0;
  color: white;
  font-family: 'Raleway', sans-serif;
  font-weight: normal;
  font-size: 15px;
  background-color: #3C3C4E;
  position: absolute;
  left: 8px;
  padding: 24px;
  top: 400px;
  width: 842px;
}
pre {
  display: block;
  float: left;
  line-height: 21px;
}
<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <title></title>
</head>

<body>

  <div id="container">
    <div id="content"></div>
    <div id="col">
    </div>
  </div>
</body>

</html>

【讨论】:

  • 您的解决方案最适合我,我能够通过 3 列和添加链接的能力使其发挥最佳效果,这正是我所需要的。我知道在某些浏览器上使用title 标签会在自定义工具提示旁边显示一个工具提示,所以我没有使用title,而是将其更改为alt,它只显示所需的工具提示时工作。这是一个好的解决方案吗?它似乎工作得很好,只是想知道您是否出于特定原因使用了title
  • 太好了,我很高兴能帮上忙。我选择了title,因为这是默认的工具提示,所以如果由于某种原因您的代码由于浏览器更新或插件不兼容等原因而损坏,您仍然会有某种工具提示作为备份。 alt 用于img 描述,主要用于屏幕阅读器,但如果可访问性不是问题,那么它与大多数其他属性一样有效。 data-* 应该也可以。
猜你喜欢
  • 1970-01-01
  • 2015-05-05
  • 2021-02-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-15
  • 2019-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多