所以,我有一个contenteditable div--我正在制作一个所见即所得编辑器:粗体、斜体、格式化,什么都行,最近的是:插入花哨的图像(在花哨的框中,加上标题)。
<a class="fancy" href="i.jpg" target="_blank">
<img alt="" src="i.jpg" />
Optional Caption goes Here!
</a>
用户通过一个对话框添加这些精美的图像:他们填写细节,上传图像,然后和其他编辑器函数一样,我使用document.execcommand('insert html',false,fancy_image_html);
按用户的选择将其插入。
所以,现在我的用户可以在一个漂亮的图像中扑通一声--他们需要能够移动它。用户需要能够单击和拖动图像(花式框和所有),以将其放置在ContentEditable中他们喜欢的任何地方。他们需要能够在段落之间移动它,甚至在段落内--如果他们愿意的话,在两个单词之间移动它。
请记住--在contenteditable中,简单的旧标记已经被用户代理赋予了这种可爱的拖放功能。默认情况下,您可以随心所欲地拖放
标记;默认的拖放操作就像人们想象的那样。
因此,考虑到这种默认行为已经在我们的伙伴上发挥了巨大作用--我只想稍微扩展这种行为,以包括更多的HTML--这似乎是很容易实现的。
首先,我设置了带有draggable属性的特殊的标记,并禁用了contenteditable(不确定这是否必要,但似乎最好关闭它):
<a class="fancy" [...] draggable="true" contenteditable="false">
然后,因为用户仍然可以将图像拖出花哨的框,所以我不得不做一些CSS。我在Chrome上工作,所以我只给你展示-webkit-前缀,尽管我也使用了其他前缀。
.fancy {
-webkit-user-select:none;
-webkit-user-drag:element; }
.fancy>img {
-webkit-user-drag:none; }
现在用户可以拖动整个fancy box,部分褪色的小点击拖动表示图像反映了这一点--我可以看到我现在正在拾取整个box:)
我已经尝试了几种不同CSS属性的组合,上面的组合对我来说似乎是有意义的,而且似乎工作得最好。
我希望仅此CSS就足以让浏览器使用整个元素作为可拖动项,自动授予用户我梦寐以求的功能...然而,它似乎比这更复杂。
所以,我开始深入研究DnD api文档,现在我被卡住了。所以,下面是我所做的操作(是的,jQuery):
$('.fancy')
.bind('dragstart',function(event){
//console.log('dragstart');
var dt=event.originalEvent.dataTransfer;
dt.effectAllowed = 'all';
dt.setData('text/html',event.target.outerHTML);
});
$('.myContentEditable')
.bind('dragenter',function(event){
//console.log('dragenter');
event.preventDefault();
})
.bind('dragleave',function(event){
//console.log('dragleave');
})
.bind('dragover',function(event){
//console.log('dragover');
event.preventDefault();
})
.bind('drop',function(event){
//console.log('drop');
var dt = event.originalEvent.dataTransfer;
var content = dt.getData('text/html');
document.execCommand('insertHTML',false,content);
event.preventDefault();
})
.bind('dragend',function(event){
//console.log('dragend');
});
我尝试使用document.execcommand('insert html',false,content);
,但不幸的是,我在这里失败了,因为选择插入符号没有像我希望的那样位于准确的放置位置。
当然,这些操作都没有奏效:我无法按计划将选择标记插入明显可见的选择插入符号处--同样,execCommand-insertedHTML在拖动操作之前将其自身放置在选择插入符号所在的位置。
我还在寻找--还在修修补补--一旦我发现我在哪些方面做得不及格,我就会马上回传:)
console.log( window.getSelection().getRangeAt(0) );
以查看所选插入符号的实际位置。我将此插入到dragover事件中,此时我发现选择插入符号在ContentEditable中的可编辑内容之间明显地跳转。
唉,返回的Range对象会在拖放操作之前报告属于选择插入符号的偏移量索引。
这是怎么回事?我有一种感觉,我看到的小的选择插入符号跳来跳去,根本不是选择插入符号!我觉得是冒名顶替的!
原来是冒名顶替!在整个拖动操作期间,真正的选择插入符号保持在原地!你能看到那个小混蛋!
当然,您也可能需要在dragover事件周围移动插入标记。您可以像使用其他鼠标事件一样使用事件的clientX和clientY属性来确定鼠标指针的位置。
哎呀,这是不是意味着我应该根据clientX和Clienty自己搞清楚?使用鼠标坐标确定选择插入符号的位置?吓人!!
我明天会考虑这样做--除非我自己,或者这里读到这篇文章的其他人,能找到一个明智的解决办法:)
我做了一大堆乱七八糟的事。这么多的小把戏。
这不是一个健壮或完整的解决方案;我可能永远也想不出一个。如果有人有更好的解决办法,我会洗耳恭听--我不想这样做,但这是目前为止我能找到的唯一方法。下面的jsFiddle和我将要吐出来的信息在我的特定WAMP设置和计算机上的特定版本的Firefox和Chrome中为我工作。当它在你的网站上不起作用时,不要来找我哭诉。这种拖拽式的废话显然是每个人都为自己。
Jsfiddle:Chase Moskal的Dragon掉落
所以,我是无聊我的女朋友的大脑出来,她认为我一直说“龙滴”,而实际上,我只是说“拖放”。它卡住了,所以这就是我为处理这些拖放情况而创建的JavaScript小伙伴。
结果--这有点像噩梦。HTML5的拖放API即使乍一看也是可怕的。然后,当你开始理解和接受它的工作方式时,你就几乎开始热身了…当你了解到Firefox和Chrome是如何以自己特有的方式来执行这个规范的,并且似乎完全忽略了你的所有需求时,你就会意识到这实际上是一场可怕的噩梦。您发现自己会问这样的问题:“等等,现在拖动的是什么元素?我如何获取这些信息?我如何取消拖动操作?我如何停止这个特定浏览器对这种情况的独特默认处理?”...你的问题的答案是:“你只能靠自己了,失败者!继续黑进东西,直到东西起作用为止!”。
下面是我如何在多个ContentEditable的内部、周围和之间精确地拖放任意HTML元素的。(注意:我并不是对每一个细节都进行深入的讨论,您必须查看jsFiddle--我只是漫谈一下我从经验中记得的似乎相关的细节,因为我的时间有限)
user-select:none;User-drag:element;
,然后具体地User-drag:none;
在fancy box中的图像上(以及任何其他元素,为什么不呢?)。不幸的是,这对Firefox来说还不够,它需要在图像上显式设置属性draggable=“false”
以防止其被拖动。draggable=“true”
和dropzone=“copy”
应用到ContentEditables上。我将dragstart
的处理程序绑定到draggables(fancyboxs)。我们将dataTransfer设置为复制一个空白的HTML字符串''--因为我们需要欺骗它,使它以为我们要拖动HTML,但我们要取消任何默认行为。有时默认行为会以某种方式滑入,并导致重复(就像我们自己做插入一样),所以现在最坏的故障是拖动失败时插入了一个''(空格)。我们不能依赖默认行为,因为它经常失败,所以我发现这是最通用的解决方案。
DD.$draggables.off('dragstart').on('dragstart',function(event){
var e=event.originalEvent;
$(e.target).removeAttr('dragged');
var dt=e.dataTransfer,
content=e.target.outerHTML;
var is_draggable = DD.$draggables.is(e.target);
if (is_draggable) {
dt.effectAllowed = 'copy';
dt.setData('text/plain',' ');
DD.dropLoad=content;
$(e.target).attr('dragged','dragged');
}
});
我将dragleave
和drop
的处理程序绑定到dropzones。dragleave处理程序仅适用于Firefox,就像在Firefox中一样,当您试图将其拖放到contenteditable之外时,拖放会起作用(Chrome默认情况下拒绝),因此它会根据Firefox专用的relatedtarget
执行快速检查。哈夫。
Chrome和Firefox有不同的获取范围对象的方法,所以在drop事件中,每个浏览器都需要做出不同的努力。Chrome建立了一个基于鼠标坐标的范围(没错),但Firefox在事件数据中提供了它。document.execcommand('insert html',false,blah)
是我们处理丢弃的方式。哦,我忘了提一下--我们不能在Chrome上使用datatransfer.getData()
来获取我们的dragstart集HTML--这似乎是规范中的某种奇怪的bug。Firefox在它的胡扯上调用了规范,并给了我们数据--但Chrome没有,所以我们弯下腰,把内容设置为全局,并通过地狱杀死所有的默认行为...
DD.$dropzones.off('dragleave').on('dragleave',function(event){
var e=event.originalEvent;
var dt=e.dataTransfer;
var relatedTarget_is_dropzone = DD.$dropzones.is(e.relatedTarget);
var relatedTarget_within_dropzone = DD.$dropzones.has(e.relatedTarget).length>0;
var acceptable = relatedTarget_is_dropzone||relatedTarget_within_dropzone;
if (!acceptable) {
dt.dropEffect='none';
dt.effectAllowed='null';
}
});
DD.$dropzones.off('drop').on('drop',function(event){
var e=event.originalEvent;
if (!DD.dropLoad) return false;
var range=null;
if (document.caretRangeFromPoint) { // Chrome
range=document.caretRangeFromPoint(e.clientX,e.clientY);
}
else if (e.rangeParent) { // Firefox
range=document.createRange(); range.setStart(e.rangeParent,e.rangeOffset);
}
var sel = window.getSelection();
sel.removeAllRanges(); sel.addRange(range);
$(sel.anchorNode).closest(DD.$dropzones.selector).get(0).focus(); // essential
document.execCommand('insertHTML',false,'<param name="dragonDropMarker" />'+DD.dropLoad);
sel.removeAllRanges();
// verification with dragonDropMarker
var $DDM=$('param[name="dragonDropMarker"]');
var insertSuccess = $DDM.length>0;
if (insertSuccess) {
$(DD.$draggables.selector).filter('[dragged]').remove();
$DDM.remove();
}
DD.dropLoad=null;
DD.bindDraggables();
e.preventDefault();
});
好吧,我受够了。关于这件事我想写的都写了。我今天就到此为止,如果我想到什么重要的事情,我可能会更新这个。
谢谢大家。//蔡斯。
问题内容: 我想做的就是能够在屏幕上拖放精灵。我尝试了以下代码: 该代码确实起作用,但是,当我快速拖动球时,我猜它检测到“球”不再包含点“位置”并且球停止了,这意味着我又将球捡起了。我希望球能够快速响应我的触摸,从而使球不会停止移动。我该怎么做? 问题答案: 我有一个实现,其中我将UIImageView子类化,并将其称为“ DraggableImage”
问题内容: 我需要在contenteditablediv中实现数字的突出显示(将来我会添加更复杂的规则)。问题是当我用JavaScript替换插入新内容时,DOM更改和contenteditablediv失去了焦点。我需要的是将div放在当前位置上,以使注意力集中在div上,这样用户就可以键入而不会出现任何问题,而我的功能只需突出显示数字即可。谷歌搜索我认为Rangy库是最好的解决方案。我有以下代
我有一个jqueryui可拖动的图像和一个包含text/html且contentEditable=true的jqueryui可拖放的div。 我希望能够将图像拖动到contentEditable文本上,当我将其拖放时,我希望能够将图像拖放到该文本/字符位置。 我已经找到了很多方法来做到这一点,如果我点击或选择可编辑的文本,然后使用选定的文本范围拖动图像,但当我只是拖动图像并放下它时,没有选择文本。
contenteditable <element contenteditable="true|false"> <p contenteditable="true">这是一个可编辑的段落。</p> contenteditable 光标定位到最后 function keepLastIndex(elem){ var range, length; //IE兼容性处理,光
准备好,下面的内容会比较难以理解。 目前为止,我们已经使用map、nmap、vmap以及imap创建了实用的按键映射。 他们很方便,但是有个缺点。运行下面的命令: :::vim :nmap - dd :nmap \ - 试试按下\(在normal模式)。有什么现象? 当你按下\时,Vim会解释其为-。但是我们又映射了-!Vim会继续解析-为dd, 即它会删除整行。 你使用那些命令创建的映射可能会
问题内容: 我在春季有以下几点 但是,Spring会自动为/ hello /和/hello.*添加映射。如何完全匹配网址? 只有/ hello应该可以工作,其他任何都应该404 问题答案: 关闭后缀匹配()将解决您的问题,但是,如果在您的配置中使用它(实际上不是手动连接所有必需的基础结构bean),实际上并不是那么容易。在这种情况下,定义其他类型的bean 不会有任何效果。 您有两种选择: 删除将