ios reader html,Any alternative to using execCommand for Highlighting HTML in iOS ebook reader

问题

I'm developing a book reader for iOS using a UIWebView. At the moment I'm working with some basic HTML files but will eventually work with ePubs. I am looking for a suitable way of styling ranges of text. My ranges are a little bit special in that they usually encompass three ranges - a keyrange and a range immediately before and range immediately after. The keyrange may span multiple nodes and may start or end for example within a selection of bold text etc. The styling should not be written to file.

At the moment I have a working solution as follows:

document.designMode = "on";

// Color the first section

var selection = window.getSelection();

selection.removeAllRanges();

selection.addRange(range1);

if (!selection.isCollapsed){

document.execCommand("foreColor", false, color1);

}

// Color the middle section

selection.removeAllRanges();

selection.addRange(range2);

if (!selection.isCollapsed){

document.execCommand("backColor", false, color2);

document.execCommand("foreColor", false, color3);

}

// Color the last section

selection.removeAllRanges();

selection.addRange(range3);

if (!selection.isCollapsed){

document.execCommand("foreColor", false, color1);

}

document.designMode = "off";

selection.removeAllRanges();

This works fine but is noticeably slow (on an iPad2), even if I modify it to highlight a single range in a short HTML document. There is always a very noticeable delay before the text is stylised. Looking at ebook readers on iPad such as kindle or iBooks there is no discernible delay. How might they implement their highlighting function? Might they be reading the geographical location on the selected text and applying some kind of overlay?

I have searched for a better solution than I'm already using but with no luck so if anyone has an idea I would be very grateful.

Thank you!

回答1:

I have made an alternative method to above which appears to be much faster. It is mainly based on mikeB's excellent code given in this question.

How to get nodes lying inside a range with javascript?

I first split the start and end nodes creating new text nodes with

only the text which falls with the given range. I adjust the range

for the new nodes.

I use a slightly modified version of the code at the above link to

return an array of text nodes contained within the range.

I loop through the array and put spans with styles around each text

node.

As far as I've tested the code works well. When applying styles to a number of ranges simultaneously there is still a delay but its much better than before. I'd be interested to know if anyone has any improvements.

My code:

function styleRange(range, style) // the style is a string of css styles. eg."background-color:darkblue; color:blue;"

{

// Get the start and end nodes and split them to give new start and end nodes with only text that falls inside the range.

var startNode = range.startContainer.splitText(range.startOffset);

var endNode = range.endContainer.splitText(range.endOffset).previousSibling;

// Adjust the range to contain the new start and end nodes

// The offsets are not really important anymore but might as well set them correctly

range.setStart(startNode,0);

range.setEnd(endNode,endNode.length);

// Get an array of all text nodes within the range

var nodes = getNodesInRange(range);

// Place span tags with style around each textnode

for (i = 0; i < nodes.length; i++)

{

var span = document.createElement('span');

span.setAttribute("style", style);

span.appendChild( document.createTextNode(nodes[i].nodeValue));

nodes[i].parentNode.replaceChild( span, nodes[i] );

}

}

Modified code from mikeB's code:

function getNodesInRange(range)

{

var start = range.startContainer;

var end = range.endContainer;

var commonAncestor = range.commonAncestorContainer;

var nodes = [];

var node;

// walk parent nodes from start to common ancestor

for (node = start.parentNode; node; node = node.parentNode)

{

if (node.nodeType == 3) //modified to only add text nodes to the array

nodes.push(node);

if (node == commonAncestor)

break;

}

nodes.reverse();

// walk children and siblings from start until end is found

for (node = start; node; node = getNextNode(node))

{

if (node.nodeType == 3) //modified to only add text nodes to the array

nodes.push(node);

if (node == end)

break;

}

return nodes;

}

function getNextNode(node, end)

{

if (node.firstChild)

return node.firstChild;

while (node)

{

if (node.nextSibling)

return node.nextSibling;

node = node.parentNode;

}

}

回答2:

Apollo in order to succeed that, you have to set an onclick listener when you create the span, by passing a callback function like

span.addEventListener("click",callbackwhenclickeventtrigger,false);

function callbackwhenclickeventtrigger(e){//pass as param the event target, inside this function create the un-bold function

}

来源:https://stackoverflow.com/questions/8429290/any-alternative-to-using-execcommand-for-highlighting-html-in-ios-ebook-reader

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值