Bra*_*ana 13 html javascript css ajax jquery
我试图创建一个页面,允许用户点击一个单词后得到一个小的建议框(如一个相当小的弹出窗口),他可以点击并选择他想要的同义词.
我不确定用什么语言可以做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.Run Code Online (Sandbox Code Playgroud)
因此,例如当他点击"我喜欢苹果"这句话时"喜欢"时,应该有一个小的建议框,他可以在所有建议的选项中选择(爱|真的很喜欢).
在结果是原始加上他选择的.
这是一个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>Run Code Online (Sandbox Code Playgroud)
...however I am not sure if there is a way to click on specific word (there could be more than one word in a sentence), and also is there way to style the suggestion box and add list of words to choose from by clicking on them.
Break down your problem into steps. This will make it easy for you to understand the problem domain and design a solution. From what I could make out of your question, the broad steps and their implementation could be like the ones described below.
Note 1: The answer is based on pure JavaScript. Remember that all frameworks like jQuery etc are JavaScript only abstracted at a higher level. It is important for you to learn basic JavaScript first.
Note 2: I've provided references for key concepts (for you to get more information and learn from) in the form of embedded links throughout this answer.
1) Markup and Javascript setup for words: There are certain words which have synonyms. The synonyms are available in the markup itself in the title attribute. The markup you arrived at, is just fine:
Markup:
<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>
Run Code Online (Sandbox Code Playgroud)
We need to be able to identify all words that carry synonyms, so that we could use Javascript to manipulate those. These are identified in the markup as i elements with a class called synonyms.
Javascript:
var words = [].slice.call(document.querySelectorAll('i.synonyms'));
Run Code Online (Sandbox Code Playgroud)
querySelectorAll返回一个节点列表,因此将其转换为数组的最简单方法是在数组原型上调用slice.我们需要一个数组,以便我们以后可以迭代它.
2)菜单的标记和Javascript设置:需要弹出一个建议框.所以,只需添加一个可以保存同义词的元素.您已经知道会有一个同义词列表,所以在语义上有一个列表元素是有意义的.并给它一个id.我们稍后会动态填写它.
加价:
<ul id="synonymMenu"></ul>
Run Code Online (Sandbox Code Playgroud)
Javascript:
var menu = document.getElementById('synonymMenu');
Run Code Online (Sandbox Code Playgroud)
3)应该弹出建议框菜单:只要点击这样的单词.因此,我们需要在所有会听取click事件的单词上添加和事件监听器.我们words在上面的第一步中已经有变量中的单词.我们只是迭代并添加事件监听器来执行该函数manageMenu.我们稍后会定义该函数.在我们处理它的同时,我们还将数据属性中的现有单词缓存,以便以后能够使用它setAttribute.
words.forEach(function(wrd) {
wrd.setAttribute('data-word', wrd.textContent);
wrd.addEventListener('click', manageMenu);
});
Run Code Online (Sandbox Code Playgroud)
4)用选定的同义词替换单词:每当在建议框菜单中单击同义词时.所以我们还要在同义词列表中添加一个click事件监听器.我们已经menu在上面的步骤2 中将菜单存储在变量中.只需添加侦听器即可执行函数applySynonym.我们稍后会定义该函数.
menu.addEventListener('click', applySynonym);
Run Code Online (Sandbox Code Playgroud)
5)我们也必须关闭悬空建议箱:我们可以通过点击身体的任何地方来做到这一点.只需在body上添加另一个click事件处理程序.toggleMenu使用hide参数执行功能.稍后会定义此功能.
document.body.addEventListener('click', function() {
toggleMenu('hide');
});
Run Code Online (Sandbox Code Playgroud)
6) Create a list of synonyms from the title attribute and show: it in the suggestion box menu, when the word is clicked. That we will define in the manageMenu function which we declared in step 3. Explanation is in code comments.
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();
}
Run Code Online (Sandbox Code Playgroud)
The key references for you in the code above are about using the event object and its target, getting the position of word relative to viewport, createElement, appendChild, and stopPropagation
7) Synonym should be appended to the original word: and shown in its place, once a synonym is clicked. This we will define in the applySynonym fucntion that we referenced in step 4.
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();
}
Run Code Online (Sandbox Code Playgroud)
上面代码中的关键参考是关于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);
}
}
Run Code Online (Sandbox Code Playgroud)
上面代码中的关键参考是关于hasChildNodes,removeChild和lastChild.
9)通过CSS定义演示文稿,特别是使菜单绝对定位,将其隐藏在第一次加载时,并美化演示文稿:
ul#synonymMenu {
position: absolute; display: none;
...
border: 1px solid #bbb; background-color: #efefef;
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
})();Run Code Online (Sandbox Code Playgroud)
* { 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;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
Per the Op's comments the code has been updated to accommodate multiple selections of synonyms via checkboxes. Added complexity is around adding checkboxes instead of plain anchors, changing the event listeners for the same, updated styles, and the logic to retain pre-existing selection on repeat clicks.
Updated Fiddle: https://jsfiddle.net/abhitalks/ffpL4f7k/
Updated Snippet:
(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;
}
})();Run Code Online (Sandbox Code Playgroud)
* { 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%; }Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
我相信,我构建了以下适合您需求的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);
}
});
});Run Code Online (Sandbox Code Playgroud)
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;
}Run Code Online (Sandbox Code Playgroud)
<!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>Run Code Online (Sandbox Code Playgroud)