javascript - 寻找最近的 anchor href 滚动偏移量

标签 javascript uiwebview anchor

我有一个 UIWebView,其中的 HTML 页面已完全加载。 UIWebView 有一个 320 x 480 的框架并水平滚动。我可以获得用户当前所在的当前偏移量。我想使用 XY 偏移找到最近的 anchor ,这样我就可以“跳转到”那个 anchor 位置。这是可能吗?有人可以向我指出用于执行此操作的 Javascript 资源吗?

<a id="p-1">Text Text Text Text Text Text Text Text Text<a id="p-2">Text Text Text Text Text Text Text Text Text ... 

更新

我 super 伤心的JS代码:

function posForElement(e)
{
    var totalOffsetY = 0;

    do
    {
        totalOffsetY += e.offsetTop;
    } while(e = e.offsetParent)

    return totalOffsetY;
}

function getClosestAnchor(locationX, locationY)
{
    var a = document.getElementsByTagName('a');

    var currentAnchor;
    for (var idx = 0; idx < a.length; ++idx)
    {
        if(a[idx].getAttribute('id') && a[idx+1])
        {
            if(posForElement(a[idx]) <= locationX && locationX <= posForElement(a[idx+1])) 
            {
                currentAnchor = a[idx];
                break;
            }
            else
            {
                currentAnchor = a[0];
            }
        }
    }

    return currentAnchor.getAttribute('id');
}

目标-C

float pageOffset = 320.0f;

NSString *path = [[NSBundle mainBundle] pathForResource:@"GetAnchorPos" ofType:@"js"];
NSString *jsCode = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[webView stringByEvaluatingJavaScriptFromString:jsCode];

NSString *execute = [NSString stringWithFormat:@"getClosestAnchor('%f', '0')", pageOffset];
NSString *anchorID = [webView stringByEvaluatingJavaScriptFromString:execute];

最佳答案

[更新] 我重写了代码以匹配所有具有 id 的 anchor ,并简化了我的 sortByDistance 函数中向量范数的比较。

检查我的尝试 on jsFiddle (上一个是 here )。

JavaScript 部分:

// findPos : courtesy of @ppk - see http://www.quirksmode.org/js/findpos.html
var findPos = function(obj) {
    var curleft = 0,
        curtop = 0;
    if (obj.offsetParent) {
        curleft = obj.offsetLeft;
        curtop = obj.offsetTop;
        while ((obj = obj.offsetParent)) {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        }
    }
    return [curleft, curtop];
};

var findClosestAnchor = function (anchors) {

    var sortByDistance = function(element1, element2) {

        var pos1 = findPos( element1 ),
            pos2 = findPos( element2 );

        // vect1 & vect2 represent 2d vectors going from the top left extremity of each element to the point positionned at the scrolled offset of the window
        var vect1 = [
                window.scrollX - pos1[0],
                window.scrollY - pos1[1]
            ],
            vect2 = [
                window.scrollX - pos2[0],
                window.scrollY - pos2[1]
            ];

        // we compare the length of the vectors using only the sum of their components squared
        // no need to find the magnitude of each (this was inspired by Mageek’s answer)
        var sqDist1 = vect1[0] * vect1[0] + vect1[1] * vect1[1],
            sqDist2 = vect2[0] * vect2[0] + vect2[1] * vect2[1];

        if ( sqDist1 <  sqDist2 ) return -1;
        else if ( sqDist1 >  sqDist2 ) return 1;
        else return 0;
    };

    // Convert the nodelist to an array, then returns the first item of the elements sorted by distance
    return Array.prototype.slice.call( anchors ).sort( sortByDistance )[0];
};

当 dom 准备好时,您可以像这样检索和缓存 anchor :var anchors = document.body.querySelectorAll('a[id]');

我还没有在智能手机上测试过它,但我看不出有任何它不起作用的原因。 Here这就是我使用 var foo = function() {}; 形式 ( more javascript patterns ) 的原因。

return Array.prototype.slice.call( anchors ).sort( sortByDistance )[0]; 行实际上有点棘手。

document.body.querySelectorAll('a['id']') 返回一个 NodeList,其中包含当前页面正文中具有属性“id”的所有 anchor 。 遗憾的是,NodeList 对象没有“排序”方法,并且无法使用 Array 原型(prototype)的 sort 方法,as it is with some other methods, such as filter or map (NodeList.prototype.sort = Array.prototype.sort 会非常好)。

This article更好地解释了为什么我使用 Array.prototype.slice.call 将我的 NodeList 转换为数组。

最后,我使用 Array.prototype.sort 方法(以及自定义的 sortByDistance 函数)将 NodeList 的每个元素相互比较,然后我只返回最接近的第一项。

要查找使用固定定位的元素的位置,可以使用 findPos 的更新版本:http://www.greywyvern.com/?post=331 .

我的回答可能不是最有效的(drdigit 的肯定比我的更有效)但我更喜欢简单而不是效率,而且我认为它是最容易维护的。

[又一更新]

这是一个经过大量修改的 findPos 版本,适用于 webkit css 列(没有间隙):

// Also adapted from PPK - this guy is everywhere ! - check http://www.quirksmode.org/dom/getstyles.html
var getStyle = function(el,styleProp)
{
    if (el.currentStyle)
        var y = el.currentStyle[styleProp];
    else if (window.getComputedStyle)
        var y = document.defaultView.getComputedStyle(el,null).getPropertyValue(styleProp);
    return y;
}

// findPos : original by @ppk - see http://www.quirksmode.org/js/findpos.html
// made recursive and transformed to returns the corect position when css columns are used

var findPos = function( obj, childCoords ) {
   if ( typeof childCoords == 'undefined'  ) {
       childCoords = [0, 0];
   }

   var parentColumnWidth,
       parentHeight;

   var curleft, curtop;

   if( obj.offsetParent && ( parentColumnWidth = parseInt( getStyle( obj.offsetParent, '-webkit-column-width' ) ) ) ) {
       parentHeight = parseInt( getStyle( obj.offsetParent, 'height' ) );
       curtop = obj.offsetTop;
       column = Math.ceil( curtop / parentHeight );
       curleft = ( ( column - 1 ) * parentColumnWidth ) + ( obj.offsetLeft % parentColumnWidth );
       curtop %= parentHeight;
   }
   else {
       curleft = obj.offsetLeft;
       curtop = obj.offsetTop;
   }

   curleft += childCoords[0];
   curtop += childCoords[1];

   if( obj.offsetParent ) {
       var coords = findPos( obj.offsetParent, [curleft, curtop] );
       curleft = coords[0];
       curtop = coords[1];
   }
   return [curleft, curtop];
}

关于javascript - 寻找最近的 anchor href 滚动偏移量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10642587/

相关文章:

javascript - 如何将输入字段值作为将在单击提交按钮时打开的 url 查询字符串传递?

WebThread 中的 iOS uiwebview 崩溃

iOS:在 didFinishLoad 后调整 UIWebView 的大小(内容应该适合而不滚动)

ios - 加载隐藏/离屏 UIWebView

html - 使 <a> anchor 标记填充列表 <li> 显示 : table-cell

javascript - 抑制浏览器的身份验证对话框

javascript - Jquery获取请求Uri太长

javascript - HTML/CSS/JS - 如何在点击时更改图像和文本

javascript - 由于 html anchor 中的 onclick 事件导致页面加载缓慢

ios - 使用 NSFetchedResultsController 锚定一行