我正在尝试存储对 contentEditable 元素的选择并在以后恢复它。
我想观察 paste 事件并像以前一样存储 HTML,清除 html,然后在选定位置手动插入粘贴的文本并进行一些更改。
看看这个例子:jsfiddle.net/gEhjZ
当您选择文本的一部分时,点击 store,再次删除选择并点击 restore,它按预期工作。
但是当您第一次点击 store 时,然后通过点击 overwrite html 将 HTML 替换为完全相同的 HTML,然后尝试 restore,没有任何反应。
我认为使用 .cloneRange() 会有所作为,但事实并非如此。即使对象的深拷贝 ($.extend(true, {}, oldRange)) 也无法解决问题。一旦我覆盖了 HTML,选择对象 sel 也被改变了。对我来说,更改选择上下文会删除范围,但我正在尝试为完全相同的 HTML 恢复它。
我知道我可以使用 rangy ,但我真的不想为了这个小功能而使用庞大的库。我错过了什么?任何帮助将不胜感激!
注意:仅限 Firefox/Chrome,因此无需跨浏览器破解。
@Tim Down 的回答在使用 div 时有效,但我实际上使用的是 iframe。当我举那个例子时,我认为它不会有任何不同。
现在,当我尝试恢复 iframe 的主体时,出现以下错误:TypeError: Value does not implement interface Node. 在以下行 preSelectionRange.selectNodeContents(containerEl);。我没有从谷歌搜索中得到太多。我试图包装正文的内容并恢复包装的 html,但我得到了同样的错误。
jsfiddle 在这种情况下不起作用,因为它使用 iframe 来显示结果本身,所以我在这里举了一个例子:snipt.org/AJad3
同样没有换行:snipt.org/AJaf0
更新 2:
我认为我当然必须使用 editable.get(0)。但是现在 iframe 选择的 start 和 end 是 0。参见 snipt.org/AJah2
最佳答案
您可以使用如下函数保存和恢复字符位置:
https://stackoverflow.com/a/13950376/96100
我稍微调整了这些函数以适用于 iframe 中的元素。
演示:http://jsfiddle.net/timdown/gEhjZ/4/
代码:
var saveSelection, restoreSelection;
if (window.getSelection && document.createRange) {
saveSelection = function(containerEl) {
var doc = containerEl.ownerDocument, win = doc.defaultView;
var range = win.getSelection().getRangeAt(0);
var preSelectionRange = range.cloneRange();
preSelectionRange.selectNodeContents(containerEl);
preSelectionRange.setEnd(range.startContainer, range.startOffset);
var start = preSelectionRange.toString().length;
return {
start: start,
end: start + range.toString().length
};
};
restoreSelection = function(containerEl, savedSel) {
var doc = containerEl.ownerDocument, win = doc.defaultView;
var charIndex = 0, range = doc.createRange();
range.setStart(containerEl, 0);
range.collapse(true);
var nodeStack = [containerEl], node, foundStart = false, stop = false;
while (!stop && (node = nodeStack.pop())) {
if (node.nodeType == 3) {
var nextCharIndex = charIndex + node.length;
if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
range.setStart(node, savedSel.start - charIndex);
foundStart = true;
}
if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
range.setEnd(node, savedSel.end - charIndex);
stop = true;
}
charIndex = nextCharIndex;
} else {
var i = node.childNodes.length;
while (i--) {
nodeStack.push(node.childNodes[i]);
}
}
}
var sel = win.getSelection();
sel.removeAllRanges();
sel.addRange(range);
};
} else if (document.selection) {
saveSelection = function(containerEl) {
var doc = containerEl.ownerDocument, win = doc.defaultView || doc.parentWindow;
var selectedTextRange = doc.selection.createRange();
var preSelectionTextRange = doc.body.createTextRange();
preSelectionTextRange.moveToElementText(containerEl);
preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);
var start = preSelectionTextRange.text.length;
return {
start: start,
end: start + selectedTextRange.text.length
};
};
restoreSelection = function(containerEl, savedSel) {
var doc = containerEl.ownerDocument, win = doc.defaultView || doc.parentWindow;
var textRange = doc.body.createTextRange();
textRange.moveToElementText(containerEl);
textRange.collapse(true);
textRange.moveEnd("character", savedSel.end);
textRange.moveStart("character", savedSel.start);
textRange.select();
};
}
关于javascript - HTML 修改后无法恢复选择,即使是相同的 HTML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17678843/
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)