最近需要給HTML5的WebAPP在頁面上實現一個複制功能:用戶點擊長按文本會全選文字並彈出系統複製菜單,用戶可以點擊複製進行複制操作,然後粘貼到AppStore搜索對應的應用。之所以不是採用鏈接形式直接跳轉到AppStore對應應用是為了通過用戶的主動輸入關鍵詞搜索給推廣的企業App增加權重。所以這一個複制功能對用戶的體驗至關重要。
嘗試了一些做法,在安卓/iOS平台上的兼容性都不是很好。在微信瀏覽器內是很容易實現長按文本激發系統菜單,高亮全選文本內容的。但是在其他瀏覽器的表現就不是很一致了。包括模擬focus input,JavaScript Selection, 使用a標籤嘗試激活系統菜單。這些方法都存在兼容的缺陷。
1)雖然使用帶有href屬性的a標籤在uc瀏覽器和百度瀏覽器上長按文本會出現自由複制/選擇文本菜單,選擇該菜單後會出現全選/複製的菜單,但是在一些安卓手機的系統瀏覽器和iPhone中卻被視為純鏈接,只彈出複制鏈接,沒有復製文本菜單。況且即使只考慮少部分瀏覽器可行,這樣也給用戶操作多了一步,增加了複雜度。所以該方案不可取。
2)借助selection和range的方法需要考慮到不同瀏覽器的兼容性,代碼如下:
function selectText(element) { var doc = document, text = docgetElementById(element), range, selection; if (docbodycreateTextRange) { range = documentbodycreateTextRange(); rangemoveToElementText(text); rangeselect(); } else if (windowgetSelection) { selection = windowgetSelection(); range = documentcreateRange(); rangeselectNodeContents(text); selectionremoveAllRanges(); selectionaddRange(range); /*if(selectionsetBaseAndExtent){ selectionsetBaseAndExtent(text, 0, text, 1); }*/ }else{ alert (none); } }遺憾的是在iphone Safari上依然無法通過點擊或長按高亮選中所有文本(既然也支持window.getSelection,為何在Safari瀏覽器addRange操作後文本不能默認選中,知道原因的請留言指教)。因此,該方式存在缺陷。主動選中文本區域的方法後面後附上。
3)iPhone用戶可能知道,長按某一文本選區內文字周圍的空白區域,Safari會自動將該選區內的文本高亮全選(目標文本需要放在獨立的div塊級容器內)。根據這一特性,用CSS margin修飾一下,利用這個特點,正好可以解決上述第二種方法在ios設備的不兼容。經過測試,無論安卓和ios平台,一般手機自帶的系統瀏覽器都是可以兼容的。至於uc瀏覽器、百度瀏覽器等其他廠家的移動端產品,由於有不同的機制,只能使用這些瀏覽器菜單提供的自由複制功能。
所以,我綜合了第二種和第三種方式,使用jQuery mobile中的taphold事件來模擬longtap操作激發手機系統的複制菜單,這樣基本上可以做到在所有移動設備瀏覽器上都能實現長按文本區域來高亮選中所有文本內容。再提一句,taphold的兼容bug這裡就不詳細附解決方法了,如果你的項目要求精益求精,你可以自行搜索解決方案。
下面列出我的解決方案。具體代碼如下:
HTML代碼:
<div class= para requirement> <div class=tips tips-t> 1、必須首次下載才生效<br/> 2、不能從排行榜下載哦</div> <div class=cparea> <div class=kwd id=kwd><span>三國艷義手機優化大師</span></div> </div> <div class=cparea> <span class=kdes><b>★</b>長按虛線框,拷貝關鍵詞</span> </div> <a href=https://itunesapplecom/cn/ data-role=button class=downlink>去AppStore搜索下載</a> </div>
JavaScript代碼:
<script type=text/javascript> $(#kwd)bind(taphold, function(){ //不支持iPhone/iTouch/iPad Safari var doc = document, text = docgetElementById(kwd), range, selection; if (docbodycreateTextRange ) { range = documentbodycreateTextRange(); rangemoveToElementText(text); rangeselect(); } else if (windowgetSelection) { selection = windowgetSelection(); range = documentcreateRange(); rangeselectNodeContents(text); selectionremoveAllRanges(); selectionaddRange(range); }else{ alert(瀏覽器不支持長按複製功能); } }); </script>關鍵的CSS代碼:
cparea{ text-align: center; font-family: Microsoft Yahei; margin: -2em 0 0; } kwd{ display: inline-block; color: #272727; background-color: #fff; font-size: 1875em; font -size: 1875em; padding: 75em 1em; border: 1px dashed #e60012; -webkit-user-select:element; margin: 2em; } kwd span{ display: block; border: 1px solid #fff; } kdes{ display: inline-block; color: #212121; font-size: 875em; padding-top: 0; } kdes b{ color: #ed5353; font-size: 25em; padding-right: 1em; }說明:這裡的margin:2em正是為了實現Safari瀏覽器上的長按全選功能,為了尊重還原設計稿效果,父容器.cparea又使用了負邊距來抵消這個2em的外邊距。最終,不僅視覺上和設計圖保持了一致,也實現了長按全選激發系統菜單。
最後再補充一下支持Safari下的完整方法:
$(#kwd).bind(taphold, function(){ var doc = document, text = docgetElementById(kwd), range, selection; if (docbodycreateTextRange) { //IE range = documentbodycreateTextRange(); rangemoveToElementText(text); rangeselect (); } else if (windowgetSelection) { //FF CH SF selection = windowgetSelection(); range = documentcreateRange(); rangeselectNodeContents(text); selectionremoveAllRanges(); selectionaddRange(range); //測試consolelog(texttextContent); textinnerText && consolelog(textinnerText); //FireFox不支持innerText consolelog(texttextContentlength); textinnerText && consolelog(textinnerTextlength); //在Chrome下長度比IE/FF下多1 consolelog(textfirstChildtextContentlength); textinnerText && consolelog(textfirstChildinnerTextlength); consolelog (textfirstChildinnerHTMLlength); //注意IE9-不支持textContent makeSelection(0, textfirstChildtextContentlength, 0, textfirstChild); /* if(selectionsetBaseAndExtent){ selectionselectAllChildren(text); selectionsetBaseAndExtent(text, 0, text, 4); } */ } else{ alert(瀏覽器不支持長按複製功能); } }); function makeSelection(start, end, child, parent) { var range = documentcreateRange(); //consolelog(parentchildNodes[child]); rangesetStart(parentchildNodes [child], start); rangesetEnd(parentchildNodes[child], end); var sel = windowgetSelection(); selremoveAllRanges(); seladdRange(range); }以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。