browser_object_follow: do not give $opener for following non-element/window in new...
[conkeror.git] / modules / follow-relationship.js
blob6e927017bdeadec051209a5e511e40bdfaceace5
1 /**
2  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
3  *
4  * Portions of this file were derived from Vimperator,
5  * (C) Copyright 2007 Doug Kearns
6  * (C) Copyright 2007-2008 Martin Stubenschrott.
7  *
8  * Use, modification, and distribution are subject to the terms specified in the
9  * COPYING file.
10 **/
12 in_module(null);
14 require("element.js");
16 const RELATIONSHIP_NEXT = 0;
17 const RELATIONSHIP_PREVIOUS = 1;
19 var browser_relationship_rel_regexp = ["next", "prev|previous"];
20 var browser_relationship_rev_regexp = ["prev|previous", "next"];
22 define_variable("browser_relationship_patterns", {},
23     "Patterns used by `follow-next' and `follow-previous'. "+
24     "User value may be overridden for specific websites by "+
25     "page-modes.");
27 browser_relationship_patterns[RELATIONSHIP_NEXT] =
28     [/^next$/i,
29      new RegExp("^>$","i"),
30      new RegExp("^(>>|»)$","i"),
31      new RegExp("^(>|»)","i"),
32      new RegExp("(>|»)$","i"),
33      new RegExp("\\bnext","i")
34     ];
36 browser_relationship_patterns[RELATIONSHIP_PREVIOUS] =
37     [/^(prev|previous)$/i,
38      new RegExp("^<$","i"),
39      new RegExp("^(<<|«)$","i"),
40      new RegExp("^(<|«)","i"),
41      new RegExp("(<|«)$","i"),
42      new RegExp("\\bprev|previous\\b","i")
43     ];
45 function document_get_element_by_relationship (doc, patterns, relationship) {
46     patterns = patterns[relationship];
47     var rel_name = new RegExp(browser_relationship_rel_regexp[relationship], "i");
48     var rev_name = new RegExp(browser_relationship_rev_regexp[relationship], "i");
50     var elems = doc.getElementsByTagName("link");
51     // links have higher priority than anchors
52     for (var i = 0; i < elems.length; i++) {
53         if (rel_name.test(elems[i].rel) || rev_name.test(elems[i].rev))
54             return elems[i];
55     }
57     // no links? look for anchors
58     elems = doc.getElementsByTagName("a");
59     for (var i = 0; i < elems.length; i++) {
60         if (rel_name.test(elems[i].rel) || rev_name.test(elems[i].rev))
61             return elems[i];
62     }
64     for (var j = 0; j < patterns.length; ++j) {
65         var pattern = patterns[j];
66         for (var i = 0; i < elems.length; i++) { // loop through list of anchors again
67             if (pattern.test(elems[i].textContent))
68                 return elems[i];
70             // images with alt text being href
71             var children = elems[i].childNodes;
72             for (var k = 0; k < children.length; k++) {
73                 if (children[k].alt && pattern.test(children[k].alt))
74                     return elems[i];
75             }
76         }
77     }
78     return null;
81 define_browser_object_class("relationship-next", null,
82     function (I, prompt) {
83         var doc = I.buffer.document;
84         for (let frame in frame_iterator(I.buffer.top_frame, I.buffer.focused_frame)) {
85             let elem = document_get_element_by_relationship(
86                 frame.document,
87                 I.local.browser_relationship_patterns,
88                 RELATIONSHIP_NEXT);
89             if (elem)
90                 yield co_return(elem);
91         }
92         throw interactive_error("No \"next\" link found.");
93     });
95 define_browser_object_class("relationship-previous", null,
96     function (I, prompt) {
97         var doc = I.buffer.document;
98         for (let frame in frame_iterator(I.buffer.top_frame, I.buffer.focused_frame)) {
99             let elem = document_get_element_by_relationship(
100                 frame.document,
101                 I.local.browser_relationship_patterns,
102                 RELATIONSHIP_PREVIOUS);
103             if (elem)
104                 yield co_return(elem);
105         }
106         throw interactive_error("No \"previous\" link found.");
107     });
109 provide("follow-relationship");