我试图创建一个页面,允许用户点击一个单词后得到一个小的建议框(如一个相当小的弹出窗口),他可以点击并选择他想要的同义词。
我不确定用什么语言可以做javascript,但我没有找到任何例子。
html代码如下:
Original:
I <b class="synonyms" style="color:black;"
title="love|really like|really love">like</b> apples.
The result should be(after a user chooses synonyms):
I <b>{like|love}</b> apples.
因此,例如当他点击“我喜欢苹果”一句中的“喜欢”时,应该有一个小的建议框,他可以在所有建议的选项中选择(爱|真的很喜欢)。
结果是原创加上他选择的内容。
这是我javascript的一个例子,但我不确定是否有办法点击特定单词(句子中可能有多个单词),还有方法来设置建议框的样式并添加单击列表可以选择的单词。
<!DOCTYPE html>
<html>
<body>
<p>I <b id="demo">like</b> apples.</p>
<button onclick="choose()">Try it</button>
<script>
function choose() {
var synonym = prompt("Choose synonyms:", "like");
if (synonym != null) {
document.getElementById("demo").innerHTML =
"{" + "like" + "|" + synonym + "}";
}
}
</script>
</body>
</html>
答案 0 :(得分:9)
...但是我不确定是否有 点击特定单词的方式(一个单词中可能有多个单词 句子),也有方法来设置建议框的样式并添加 单击列表可以选择的单词。
将您的问题分解为几个步骤。这将使您更容易理解问题域并设计解决方案。从我的问题出发,广泛的步骤及其实施可能与下面描述的步骤相同。
注1 :答案基于纯JavaScript。请记住,像jQuery等所有框架都是仅在更高级别抽象的JavaScript。首先学习基本的JavaScript非常重要。
注2 :在本答案中,我以嵌入式链接的形式提供了关键概念的参考资料(供您了解更多信息和学习)。
1)单词的标记和Javascript设置:某些单词具有同义词。标识符属性中的标记本身可以使用同义词。你到达的标记就好了:
标记:
<p>
I <i class="synonyms" title="love|really like|really love">like</i> apples.
I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges.
</p>
我们需要能够识别所有带有同义词的单词,以便我们可以使用Javascript来操作它们。这些标记在标记中标识为i
元素,其中包含一个名为synonyms
的类。
的Javascript :
var words = [].slice.call(document.querySelectorAll('i.synonyms'));
querySelectorAll
返回一个节点列表,因此将其转换为数组的最简单方法是调用slice on array prototype。我们需要一个数组,以便我们以后可以迭代它。
2)菜单的标记和Javascript设置:需要弹出一个建议框。所以,只需添加一个可以保存同义词的元素。您已经知道会有一个同义词列表,所以在语义上有一个列表元素是有意义的。并给它一个id。我们稍后会动态填写它。
标记:
<ul id="synonymMenu"></ul>
的Javascript :
var menu = document.getElementById('synonymMenu');
3)建议框菜单应该弹出:只要点击这样的单词。因此,我们需要在所有会听取click事件的单词上添加和事件监听器。我们已经在上面第一步中的变量words
中有了单词。我们只需迭代并add the event listener执行函数manageMenu
。我们稍后会定义该函数。在我们处理它的同时,我们还会在数据属性中缓存现有单词,以便以后能够使用setAttribute
来使用它。
words.forEach(function(wrd) {
wrd.setAttribute('data-word', wrd.textContent);
wrd.addEventListener('click', manageMenu);
});
4)用选定的同义词替换单词:每当在建议框菜单中单击同义词时。因此,我们还必须将click事件侦听器添加到同义词列表中。我们已经将菜单存储在上面第2步中的变量menu
中。只需添加侦听器即可执行函数applySynonym
。我们稍后会定义该函数。
menu.addEventListener('click', applySynonym);
5)我们必须关闭悬空建议箱:我们可以通过点击身体的任何地方来做到这一点。只需在body上添加另一个click事件处理程序。使用toggleMenu
参数执行函数hide
。稍后会定义这个函数。
document.body.addEventListener('click', function() {
toggleMenu('hide');
});
6)从title属性创建一个同义词列表,并在单击单词时在建议框菜单中显示:它。我们将在我们在步骤3中声明的manageMenu
函数中定义。解释在代码注释中。
function manageMenu(e) {
// define variables
var synonyms, optn, link, position;
// clear existing list and then show the menu
clearMenu(); toggleMenu('show');
// cache the click event target to a variable to be used later
currentWord = e.target;
// get the position of word relative to viewport
position = currentWord.getBoundingClientRect();
// use that position to shift the popup menu near to the word
menu.style.top = position.top + 24 + 'px';
menu.style.left = position.left + 2 + 'px';
// extract title attribute, split by | and store in array
synonyms = currentWord.getAttribute('title').split('|');
// iterate array creating an li and anchor for each synonym
// createElement creates a new element
// appendChild adds an element to another
synonyms.forEach(function(syn) {
optn = document.createElement('li');
link = document.createElement('a');
link.setAttribute('href', '#'); link.textContent = syn;
// add anchor to li, and the li to the menu
optn.appendChild(link); menu.appendChild(optn);
});
// stop propagation of click, so that it doesn't go to body
e.stopPropagation();
}
上述代码中的关键参考资料包括using the event object and its target,getting the position of word relative to viewport,createElement,appendChild和stopPropagation
7)同义词应附加到原始单词:并在单击同义词后显示在其位置。我们将在步骤4中引用的applySynonym
函数中定义。
function applySynonym(e) {
var txt = '';
// Because we added event listener to the parent ul element,
// we have to check if the clicked element is the anchor or not
if (e.target.tagName != 'A') { return false; }
// We retrieve the orginal text from the data attribute,
// which we cached in step 6 above. And append current anchor's text
txt += '{' + currentWord.getAttribute('data-word') + '|';
txt += e.target.textContent + '}';
// replace the text of the word
currentWord.textContent = txt;
toggleMenu('hide'); // hide the suggestion box menu
// stop propagation of click, so that it doesn't go to body
// prevent default so that clicking anchor doesn't jump to top
e.stopPropagation(); e.preventDefault();
}
上述代码中的关键参考资料是preventDefault。
8)我们定义了其他辅助函数:
function toggleMenu(mode) {
if (mode == 'show') { menu.style.display = 'block'; }
if (mode == 'hide') { menu.style.display = 'none'; }
}
function clearMenu() {
// we loop the child nodes of menu ul element,
// remove the last child (last li) of that ul element,
// until it does not has-child-nodes.
while (menu.hasChildNodes()) {
menu.removeChild(menu.lastChild);
}
}
上述代码中的关键参考资料大约为hasChildNodes,removeChild和lastChild。
9)通过CSS 定义演示文稿,特别是使菜单绝对定位,在第一次加载时隐藏它并美化演示文稿:
ul#synonymMenu {
position: absolute; display: none;
...
border: 1px solid #bbb; background-color: #efefef;
}
10)测试。
演示小提琴:https://jsfiddle.net/abhitalks/zske2aoh/
演示代码段
(function() {
var menu = document.getElementById('synonymMenu'),
words = [].slice.call(document.querySelectorAll('i.synonyms')),
currentWord = null
;
words.forEach(function(wrd) {
wrd.setAttribute('data-word', wrd.textContent);
wrd.addEventListener('click', manageMenu);
});
menu.addEventListener('click', applySynonym);
document.body.addEventListener('click', function() {
toggleMenu('hide');
});
function manageMenu(e) {
var synonyms, optn, link, position;
clearMenu(); toggleMenu('show');
currentWord = e.target;
position = currentWord.getBoundingClientRect();
menu.style.top = position.top + 24 + 'px';
menu.style.left = position.left + 2 + 'px';
synonyms = currentWord.getAttribute('title').split('|');
synonyms.forEach(function(syn) {
optn = document.createElement('li');
link = document.createElement('a');
link.setAttribute('href', '#'); link.textContent = syn;
optn.appendChild(link); menu.appendChild(optn);
});
e.stopPropagation();
}
function applySynonym(e) {
var txt = '';
if (e.target.tagName != 'A') { return false; }
txt += '{' + currentWord.getAttribute('data-word') + '|';
txt += e.target.textContent + '}';
currentWord.textContent = txt;
toggleMenu('hide');
e.stopPropagation(); e.preventDefault();
}
function toggleMenu(mode) {
if (mode == 'show') { menu.style.display = 'block'; }
if (mode == 'hide') { menu.style.display = 'none'; }
}
function clearMenu() {
while (menu.hasChildNodes()) {
menu.removeChild(menu.lastChild);
}
}
})();
* { font-family: sans-serif; }
html, body { height: 100%; }
i.synonyms { cursor: pointer; color: #333; }
ul#synonymMenu {
position: absolute; display: none;
width: auto; max-height: 120px;
overflow: hidden; overflow-y: auto;
list-style: none; padding: 0; margin: 0;
border: 1px solid #bbb; background-color: #efefef;
box-shadow: 0px 0px 6px 1px rgba(128,128,128,0.3);
}
ul#synonymMenu > li { display: block; }
ul#synonymMenu a {
display: block; padding: 4px 20px 4px 6px;
color: #333; font-size: 0.9em; text-decoration: none;
}
ul#synonymMenu a:hover {
background-color: #99b;
}
<p>
I <i class="synonyms" title="love|really like|really love">like</i> apples.
I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges.
</p>
<ul id="synonymMenu"></ul>
根据Op的评论,代码已经更新,以通过复选框容纳多个同义词选择。增加的复杂性在于添加复选框而不是普通锚点,为相同的更新样式更改事件侦听器,以及在重复点击时保留预先存在的选择的逻辑。
更新小提琴:https://jsfiddle.net/abhitalks/ffpL4f7k/
更新了摘录:
(function() {
var menu = document.getElementById('synonymMenu'),
menuWrap = document.getElementById('menuWrapper'),
okButton = document.getElementById('synOk'),
words = [].slice.call(document.querySelectorAll('i.synonyms')),
currentWord = null
;
words.forEach(function(wrd) {
wrd.setAttribute('data-word', wrd.textContent);
wrd.addEventListener('click', manageMenu);
});
okButton.addEventListener('click', applySynonym);
document.body.addEventListener('click', function(e) {
if (isDescendant(menuWrapper, e.target)) {
return;
}
toggleMenu('hide');
});
function manageMenu(e) {
var synonyms, opt, lbl, chk, txt, position, existing;
clearMenu(); toggleMenu('show');
currentWord = e.target;
position = currentWord.getBoundingClientRect();
menuWrap.style.top = position.top + 20 + 'px';
menuWrap.style.left = position.left + 2 + 'px';
existing = currentWord.textContent;
synonyms = currentWord.getAttribute('title').split('|');
synonyms.forEach(function(syn) {
opt = document.createElement('li');
lbl = document.createElement('label');
chk = document.createElement('input');
chk.setAttribute('type', 'checkbox');
txt = document.createTextNode(syn);
lbl.appendChild(chk);
lbl.appendChild(txt);
opt.appendChild(lbl);
menu.appendChild(opt);
});
preSelect(existing);
e.stopPropagation();
}
function preSelect(existing) {
var labels = [].slice.call(menu.querySelectorAll('label'));
labels.forEach(function(lbl) {
if (existing.indexOf(lbl.textContent) > -1) {
lbl.firstChild.checked = true;
}
});
}
function applySynonym(e) {
var txt = '', labels, checked, selected;
labels = [].slice.call(menu.querySelectorAll('label'));
checked = labels.filter(function(lbl){
return lbl.firstChild.checked;
});
selected = checked.map(function(lbl){
return lbl.textContent;
}).join('|');
txt += '{' + currentWord.getAttribute('data-word') + '|';
txt += selected + '}';
currentWord.textContent = txt;
toggleMenu('hide');
e.stopPropagation();
}
function toggleMenu(mode) {
if (mode == 'show') { menuWrap.style.display = 'block'; }
if (mode == 'hide') { menuWrap.style.display = 'none'; }
}
function clearMenu() {
while (menu.hasChildNodes()) {
menu.removeChild(menu.lastChild);
}
}
function isDescendant(parent, child) {
var node = child.parentNode;
while (node != null) {
if (node == parent) {
return true;
}
node = node.parentNode;
}
return false;
}
})();
* { font-family: sans-serif; box-sizing: border-box; }
html, body { height: 100%; }
div.wrap {
border: 1px solid #ddd; max-height: 480px;
padding: 4px 22px 4px 4px; font-size: 0.9em;
overflow: hidden; overflow-y: auto;
}
i.synonyms { cursor: pointer; color: #333; }
div#menuWrapper {
position: absolute; display: none; width: 128px;
padding: 4px; margin: 0;
border: 1px solid #bbb; background-color: #efefef;
box-shadow: 0px 0px 6px 1px rgba(128,128,128,0.3);
}
ul#synonymMenu {
max-height: 120px;
overflow: hidden; overflow-y: auto;
list-style: none; padding: 0; margin: 0;
}
ul#synonymMenu > li { display: block; }
ul#synonymMenu label {
display: block; color: #333; font-size: 0.9em;
padding: 2px 18px 2px 4px;
}
ul#synonymMenu label:hover { background-color: #99b; }
button#synOk { padding: 2px; width: 100%; }
<div class="wrap">
<p>
I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges.
</p>
<p>
I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges.
</p>
<p>
I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges. I <i class="synonyms" title="love|relish|savor">like</i> apples. I <i class="synonyms" title="love|relish|savor|enjoy|patronize|adore">like</i> oranges.
</p>
</div>
<div id="menuWrapper">
<ul id="synonymMenu"></ul>
<hr/>
<button id="synOk">Ok</button>
</div>
答案 1 :(得分:5)
我建立了以下适合您需求的jQuery组件。我相信 如果你愿意的话,这是jsbin。
//jquery component
$.fn.synonyms = function(options){
options = $.extend({}, {separator: '|'}, options);
this.each(function(elKey, el){
var $el = $(el),
originalText = $el.text(),
originalTextSpan = $('<span>'+originalText+'</span>');
$el.html(originalTextSpan);
var suggestionBox = '<div>';
$.each($el.attr('data-synonyms').split(options.separator),
function(key, suggestion){
suggestionBox+='<span>'+suggestion+'</span> - ';
}
);
suggestionBox = suggestionBox.slice(0, -2);
suggestionBox += '</div>';
suggestionBox = $(suggestionBox);
suggestionBox.css({
display: 'none'
});
$el.click(function(){
suggestionBox.toggle();
});
suggestionBox.on('click','span',function(){
var selectedText = $(this).text();
originalTextSpan.text('{'+originalText+'|'+selectedText+'}');
onSelected(selectedText);
});
$el.append(suggestionBox);
});
function onSelected(selectedText){
if(options.onSelected){
options.onSelected(selectedText);
}
}
};
// How to use the component
$(function(){
$('[data-synonyms]').synonyms({
onSelected: function(selectedText){
alert('you selected:'+selectedText);
}
});
});
div[data-synonyms]{
display: inline;
position: relative;
cursor: pointer;
text-decoration: underline;
}
div[data-synonyms] > div{
white-space: nowrap;
position: absolute;
top: 1.2em;
left: 0;
background: #fff;
border: 1px solid #bbb;
padding: 2px;
}
div[data-synonyms] > div > span{
text-decoration: underline;
cursor: pointer;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
I <div data-synonyms="love|really like|really love">like</div> apples. Carrots are the <div data-synonyms="worst|orangest">best</div> though.
</body>
</html>
答案 2 :(得分:4)
rand.Next
$(document).ready(function() {
$("b").on("click", function() {
var $b = $(this),
alternatives = this.title.split('|').join('</option><option>');
$b.after('<select class="selector"><option> </option><option>' + alternatives + '</option><select>');
});
$("body").on("change", "select.selector", function() {
var $sl = $(this),
txt = $sl.val();
$sl.prev('b').text(txt);
$sl.remove();
});
});
b {
color: red;
cursor: pointer;
}
答案 3 :(得分:1)
我使用bootstrap的下拉列表创建了另一个解决方案:
http://www.bootply.com/rWfTgSwf1z
我们的想法是使用下拉列表来显示您想要使用同义词的所有单词。当前代码为每个单词手动添加下拉列表,并在选择时替换原始单词。
在data-synonyms
属性中定义单词的同义词时,您可以使用以下句子:
<div>
I
<span data-synonyms="love|really like|really love">like</span>
apples and
<span data-synonyms="mangoes|bananas|other fruits">oranges</span>.
</div>
然后,在javascript中我们创建下拉列表并替换现有元素:
$('[data-synonyms]').each(function () {
// get the current element
var $this = $(this);
// create a dropdown wrapper
var $dropdownDiv = $('<div>').addClass('dropdown word-dropdown');
// create the dropdown trigger
var $a = $('<a>').attr('data-toggle', 'dropdown').text($this.text()).appendTo($dropdownDiv);
// create the dropdown list
var $ul = $('<ul>').addClass('dropdown-menu').appendTo($dropdownDiv);
// get the synonyms and append the existing word
var synonyms = $this.attr('data-synonyms').split('|');
synonyms.splice(0, 0, $this.text());
// create an entry in the dropdown for each synonym
$.each(synonyms, function (idx, syn) {
var $li = $('<li>').addClass('synonyms').appendTo($ul).append($('<a>').text(syn.trim()));
// add a handler which replaces the existing word with the synonym
$li.on('click', function () {
$a.text(syn.trim());
});
});
// replace the current element with the dropdown element
$this.replaceWith($dropdownDiv);
// activate the dropdown
$a.dropdown();
});
答案 4 :(得分:1)
这里有a Fiddle,其中有两个选项。
我使用过jQuery,并稍微改变了语法。每个选项都应为struct oneCell{
var date = NSDate()
var money = Int()
}
var spend = [oneCell]()
,其中包含span
类。然后它需要selectable
属性。选项以您建议的方式呈现。
我的脚本与其他脚本的不同之处在于它没有列出已经选择的选项。
HTML:
options
CSS:
<p>I <span class="selectable" options="love|really like|really love">like</span> apples.</p>
JavaScript:
.selectable{
position: relative;
}
.selectable span{
color: #F00;
cursor: pointer;
}
.selectable ul{
position: absolute;
top: 100%;
left: 0;
list-style: none;
padding: 0;
margin: 0;
pointer-events: none;
opacity: 0;
}
.selectable.active ul{
pointer-events: initial;
opacity: 1;
}
.selectable li{
cursor: pointer;
white-space: nowrap;
background-color: #FFF;
}
.selectable li:hover{
background-color: #F7F7F7;
}
.selectable li.active{
display: none;
}
希望这有帮助