Merge pull request #370 from loyalpartner/master

Improve the marker experience for caret mode.
master
Andy Stewart 6 years ago committed by GitHub
commit 3478ba3edd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      core/browser.py
  2. 156
      core/js/get_codes.js
  3. 199
      core/js/get_markers.js
  4. 31
      core/js/goto_code.js
  5. 59
      core/js/goto_marker.js
  6. 91
      core/js/marker.js

@ -68,11 +68,7 @@ class BrowserView(QWebEngineView):
self.search_term = ""
self.get_markers_raw = self.read_js_content("get_markers.js")
self.goto_marker_raw = self.read_js_content("goto_marker.js")
self.marker_js = self.read_js_content("marker.js")
self.get_codes_raw = self.read_js_content("get_codes.js")
self.goto_code_raw = self.read_js_content("goto_code.js")
self.marker_js_raw = self.read_js_content("marker.js")
self.get_focus_text_js = self.read_js_content("get_focus_text.js")
self.set_focus_text_raw = self.read_js_content("set_focus_text.js")
self.clear_focus_js = self.read_js_content("clear_focus.js")
@ -828,7 +824,7 @@ class BrowserBuffer(Buffer):
self.update()
elif progress == 100 and self.draw_progressbar:
self.init_auto_fill()
self.buffer_widget._eval_js(self.buffer_widget.marker_js.replace("%1", self.emacs_var_dict["eaf-marker-letters"]))
self.buffer_widget._eval_js(self.buffer_widget.marker_js_raw.replace("%1", self.emacs_var_dict["eaf-marker-letters"]))
cursor_foreground_color = ""
cursor_background_color = ""

@ -1,156 +0,0 @@
(function() {
function cssSelector(el) {
let path = [], parent;
while (parent = el.parentNode) {
path.unshift(`${el.tagName}:nth-child(${[].indexOf.call(parent.children, el)+1})`);
el = parent;
}
return `${path.join(' > ')}`.toLowerCase();
}
function getCoords(link){
let rect = link.getBoundingClientRect();
return [ rect.top, rect.left, rect.right, rect.bottom, cssSelector(link) ];
}
function isElementOnScreen(rect){
let clientHeight = document.documentElement.clientHeight;
let clientWidth = document.documentElement.clientWidth;
return (rect[0] >= 0 && rect[0] <= clientHeight &&
rect[1] >= 0 && rect[1] <= clientWidth &&
rect[2] != 0 && rect[3] != 0);
}
function isElementOnTop(element, rect){
let topElement = document.elementFromPoint((rect[1] + rect[2])/2, (rect[0] + rect[3])/2);
return topElement != undefined && (element.isSameNode(topElement) || element.contains(topElement) || topElement.contains(element));
}
function hasCopy(validRects, rect){
for(let i = 0; i < validRects.length; i++) {
let each = validRects[i];
if(each[0] === rect[0] && each[1] === rect[1]){
return true;
}
}
return false;
}
function addElementToRects(validRects, elements){
let rect;
for(let i = 0; i < elements.length; i++) {
rect = getCoords(elements[i]);
if(!hasCopy(validRects, rect) &&
isElementOnScreen(rect) &&
isElementOnTop(elements[i], rect)){
validRects.push(rect);
}
}
}
function cAdd1(keyCounter, index, maxDigit){
if(keyCounter[index] + 1 == maxDigit){
keyCounter[index] = 0;
cAdd1(keyCounter, index + 1, maxDigit);
} else {
keyCounter[index]++;
}
}
function generateKeys(markerContainer) {
let lettersString = "%1";
let letters = lettersString.split("");
let linkNum = markerContainer.children.length;
let keyLen = linkNum == 1 ? 1 : Math.ceil(Math.log(linkNum)/Math.log(letters.length));
let keyCounter = [];
for(let i = 0; i < keyLen; i++) keyCounter[i] = 0;
for(let l = 0; l < linkNum; l++) {
let keyStr = '';
for(let k = 0; k < keyLen; k++) {
let mark = document.createElement('span');
mark.setAttribute('class', 'eaf-mark');
let key = letters[keyCounter[k]];
mark.textContent = key;
markerContainer.children[l].appendChild(mark);
keyStr += key;
cAdd1(keyCounter, 0, letters.length);
}
markerContainer.children[l].id = keyStr;
}
}
let style = document.createElement('style');
document.head.appendChild(style);
style.type = 'text/css';
style.setAttribute('class', 'eaf-style');
style.appendChild(document.createTextNode('\
.eaf-mark {\
background: none;\
border: none;\
bottom: auto;\
box-shadow: none;\
color: black !important;\
cursor: auto;\
display: inline;\
float: none;\
font-size: inherit;\
font-variant: normal;\
font-weight: bold;\
height: auto;\
left: auto;\
letter-spacing: 0;\
line-height: 100%;\
margin: 0;\
max-height: none;\
max-width: none;\
min-height: 0;\
min-width: 0;\
opacity: 1;\
padding: 0;\
position: static;\
right: auto;\
text-align: left;\
text-decoration: none;\
text-indent: 0;\
text-shadow: none;\
text-transform: none;\
top: auto;\
vertical-align: baseline;\
white-space: normal;\
width: auto;\
z-index: 100000;\
}'));
style.appendChild(document.createTextNode('\
.eaf-marker {\
position: fixed;\
display: block;\
white-space: nowrap;\
overflow: hidden;\
font-size: 11.5px;\
background: linear-gradient(to bottom, #ffdd6e 0%, #deb050 100%);\
padding-left: 3px;\
padding-right: 3px;\
border: 1px solid #c38a22;\
border-radius: 3px;\
box-shadow: 0px 3px 7px 0px rgba(0, 0, 0, 0.3);\
z-index: 100000;\
}'));
let validRects = [];
addElementToRects(validRects, document.querySelectorAll('pre'));
let body = document.querySelector('body');
let markerContainer = document.createElement('div');
markerContainer.setAttribute('class', 'eaf-marker-container');
body.insertAdjacentElement('afterend', markerContainer);
for(let i = 0; i < validRects.length; i++) {
let marker = document.createElement('div');
marker.setAttribute('class', 'eaf-marker');
marker.setAttribute('style', 'left: ' + validRects[i][1] + 'px; top: ' + validRects[i][0] + 'px;');
marker.setAttribute('pointed-link', validRects[i][4]);
markerContainer.appendChild(marker);
}
generateKeys(markerContainer);
})();

@ -1,199 +0,0 @@
(function() {
function cssSelector(el) {
let path = [], parent;
while (parent = el.parentNode) {
path.unshift(`${el.tagName}:nth-child(${[].indexOf.call(parent.children, el)+1})`);
el = parent;
}
return `${path.join(' > ')}`.toLowerCase();
}
function getCoords(node){
let rect = node.getBoundingClientRect();
return [ rect.top, rect.left, rect.right, rect.bottom, cssSelector(node) ];
}
function isElementOnScreen(rect){
let clientHeight = document.documentElement.clientHeight;
let clientWidth = document.documentElement.clientWidth;
return (rect[0] >= 0 && rect[0] <= clientHeight &&
rect[1] >= 0 && rect[1] <= clientWidth &&
rect[2] != 0 && rect[3] != 0);
}
function isElementOnTop(element, rect){
let topElement = document.elementFromPoint((rect[1] + rect[2])/2, (rect[0] + rect[3])/2);
return topElement != undefined && (element.isSameNode(topElement) || element.contains(topElement) || topElement.contains(element));
}
function hasCopy(validRects, rect){
for(let i = 0; i < validRects.length; i++) {
let each = validRects[i];
if(each[0] === rect[0] && each[1] === rect[1]){
return true;
}
}
return false;
}
function addElementToRects(validRects, elements){
let rect;
for(let i = 0; i < elements.length; i++) {
rect = getCoords(elements[i]);
if(!hasCopy(validRects, rect) &&
isElementOnScreen(rect) &&
isElementOnTop(elements[i], rect)){
validRects.push(rect);
}
}
}
function cAdd1(keyCounter, index, maxDigit){
if(keyCounter[index] + 1 == maxDigit){
keyCounter[index] = 0;
cAdd1(keyCounter, index + 1, maxDigit);
} else {
keyCounter[index]++;
}
}
function generateKeys(markerContainer) {
let lettersString = "%1";
let letters = lettersString.split("");
let nodeNum = markerContainer.children.length;
let keyLen = nodeNum == 1 ? 1 : Math.ceil(Math.log(nodeNum)/Math.log(letters.length));
let keyCounter = [];
for(let i = 0; i < keyLen; i++) keyCounter[i] = 0;
for(let l = 0; l < nodeNum; l++) {
let keyStr = '';
for(let k = 0; k < keyLen; k++) {
let mark = document.createElement('span');
mark.setAttribute('class', 'eaf-mark');
let key = letters[keyCounter[k]];
mark.textContent = key;
markerContainer.children[l].appendChild(mark);
keyStr += key;
cAdd1(keyCounter, 0, letters.length);
}
markerContainer.children[l].id = keyStr;
}
}
let style = document.createElement('style');
document.head.appendChild(style);
style.type = 'text/css';
style.setAttribute('class', 'eaf-style');
style.appendChild(document.createTextNode('\
.eaf-mark {\
background: none;\
border: none;\
bottom: auto;\
box-shadow: none;\
color: black !important;\
cursor: auto;\
display: inline;\
float: none;\
font-size: inherit;\
font-variant: normal;\
font-weight: bold;\
height: auto;\
left: auto;\
letter-spacing: 0;\
line-height: 100%;\
margin: 0;\
max-height: none;\
max-width: none;\
min-height: 0;\
min-width: 0;\
opacity: 1;\
padding: 0;\
position: static;\
right: auto;\
text-align: left;\
text-decoration: none;\
text-indent: 0;\
text-shadow: none;\
text-transform: none;\
top: auto;\
vertical-align: baseline;\
white-space: normal;\
width: auto;\
z-index: 100000;\
}'));
style.appendChild(document.createTextNode('\
.eaf-marker {\
position: fixed;\
display: block;\
white-space: nowrap;\
overflow: hidden;\
font-size: 11.5px;\
background: linear-gradient(to bottom, #ffdd6e 0%, #deb050 100%);\
padding-left: 3px;\
padding-right: 3px;\
border: 1px solid #c38a22;\
border-radius: 3px;\
box-shadow: 0px 3px 7px 0px rgba(0, 0, 0, 0.3);\
z-index: 100000;\
}'));
let operationString = "%2";
let validRects = [];
if (operationString != "select_text") {
addElementToRects(validRects, document.links); // collect links
addElementToRects(validRects, document.querySelectorAll('a')); // collect <a> without href
addElementToRects(validRects, document.querySelectorAll('input')); // collect <input>
addElementToRects(validRects, document.querySelectorAll('button')); // collect <button>
addElementToRects(validRects, document.querySelectorAll('[class*="btn"]')); // collect class=btn buttons
addElementToRects(validRects, document.querySelectorAll('[aria-haspopup]')); // collect menu buttons
addElementToRects(validRects, document.querySelectorAll('[role="button"]')); // collect role="button"
addElementToRects(validRects, document.querySelectorAll('textarea')); // collect <textarea>
addElementToRects(validRects, document.querySelectorAll('select')); // collect <select>
addElementToRects(validRects, document.querySelectorAll('summary')); // collect <summary>
addElementToRects(validRects, document.querySelectorAll('[class="gap"]')); // collect class="gap"
addElementToRects(validRects, document.querySelectorAll('[ng-click]')); // collect ng-click
}
else {
addElementToRects(validRects, document.querySelectorAll('p')); // collect <p>
let spanElements = document.querySelectorAll('span')
let FilteredspanElements = [];
for(let i = 0; i < spanElements.length; i++) {
if(spanElements[i].innerText != "") {
isInnerElement = false;
parNode = spanElements[i].parentNode;
if(parNode) {
while(parNode.nodeName.toLowerCase() != 'html' && parNode.nodeName.toLowerCase() != 'div'){
if(parNode.nodeName.toLowerCase() != 'p' && parNode.nodeName.toLowerCase() != 'span') {
parNode = parNode.parentNode;
if(!parNode) {
break
}
}
else {
isInnerElement = true;
break;
}
}
}
if (!isInnerElement) {
// collect <span> elements with text and not being Inner Element
FilteredspanElements.push(spanElements[i]);
}
}
}
addElementToRects(validRects, FilteredspanElements);
}
let body = document.querySelector('body');
let markerContainer = document.createElement('div');
markerContainer.setAttribute('class', 'eaf-marker-container');
body.insertAdjacentElement('afterend', markerContainer);
for(let i = 0; i < validRects.length; i++) {
let marker = document.createElement('div');
marker.setAttribute('class', 'eaf-marker');
marker.setAttribute('style', 'left: ' + validRects[i][1] + 'px; top: ' + validRects[i][0] + 'px;');
marker.setAttribute('pointed-link', validRects[i][4]);
markerContainer.appendChild(marker);
}
generateKeys(markerContainer);
})();

@ -1,31 +0,0 @@
(function() {
function moveCursorToEnd(el) {
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
el.focus();
var range = el.createTextRange();
range.collapse(false);
range.select();
}
}
let key = "%1";
let markers = document.querySelectorAll('.eaf-marker');
let match;
for(let i = 0; i < markers.length; i++) {
if(markers[i].id === key.toUpperCase()) {
match = markers[i];
break;
}
}
if(match != undefined){
let selector = match.getAttribute('pointed-link');
let link = document.querySelector(selector);
return link.textContent;
}
return "";
})();

@ -1,59 +0,0 @@
(function() {
function moveCursorToEnd(el) {
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
el.focus();
var range = el.createTextRange();
range.collapse(false);
range.select();
}
}
let key = "%1";
let markers = document.querySelectorAll('.eaf-marker');
let match;
for(let i = 0; i < markers.length; i++) {
if(markers[i].id === key.toUpperCase()) {
match = markers[i];
break;
}
}
if(match != undefined){
let selector = match.getAttribute('pointed-link');
let node = document.querySelector(selector);
if(node.nodeName.toLowerCase() === 'select'){
node.focus();
}else if(node.nodeName.toLowerCase() === 'input' ||
node.nodeName.toLowerCase() === 'textarea') {
if((node.getAttribute('type') === 'submit') ||
(node.getAttribute('type') === 'checkbox')){
node.click();
} else {
node.focus(); // focus
node.click(); // show blink cursor
moveCursorToEnd(node); // move cursor to the end of line after focus.
}
} else if((node.nodeName.toLowerCase() === 'button') || // normal button
(node.nodeName.toLowerCase() === 'summary') || // summary button
(node.hasAttribute('aria-haspopup')) || // menu button
(node.getAttribute('role') === 'button') || // role="button" buttons
(node.hasAttribute('ng-click')) || // ng-click buttons
(node.classList.contains('btn')) || // class="btn" buttons
(node.classList.contains('gap')) || // class="gap" links
(node.getAttribute('href') === '') || // special href button
(node.getAttribute('href') === '#')){ // special href # button
node.click();
} else if(node.nodeName.toLowerCase() === 'p'||
node.nodeName.toLowerCase() === 'span') { // select text section
window.getSelection().selectAllChildren(node);
} else if(node.href != undefined && node.href != '' && node.getAttribute('href') != ''){
return node.href;
} else if(node.nodeName.toLowerCase() === 'a') {
node.click(); // most general a tag without href
}
}
return "";
})();

@ -1,13 +1,38 @@
(function(_) {
var self = {}
let self;
_.Marker = self = {};
function getVisibleElements(filter) {
let all = Array.from(document.documentElement.getElementsByTagName("*"));
let visibleElements = [];
for (let i = 0; i < all.length; i++) {
let e = all[i];
// include elements in a shadowRoot.
if (e.shadowRoot) {
let cc = e.shadowRoot.querySelectorAll('*');
for (let j = 0; j < cc.length; j++) {
all.push(cc[j]);
}
}
let rect = e.getBoundingClientRect();
if ( (rect.top <= window.innerHeight) && (rect.bottom >= 0)
&& (rect.left <= window.innerWidth) && (rect.right >= 0)
&& rect.height > 0
&& getComputedStyle(e).visibility !== 'hidden'
) {
filter(e, visibleElements);
}
}
return visibleElements;
}
function moveCursorToEnd(el) {
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
el.focus();
var range = el.createTextRange();
let range = el.createTextRange();
range.collapse(false);
range.select();
}
@ -23,8 +48,12 @@
}
function getCoords(node){
let rect = node.getBoundingClientRect();
return [ rect.top, rect.left, rect.right, rect.bottom, cssSelector(node) ];
if (node.getBoundingClientRect){
let rect = node.getBoundingClientRect();
return [ rect.top, rect.left, rect.right, rect.bottom, cssSelector(node) ];
}
return getCoords(node.parentNode); // TextNode not define getBoundingClientRect
}
function isElementOnScreen(rect){
@ -62,31 +91,6 @@
}
}
function getVisibleElements(filter) {
var all = Array.from(document.documentElement.getElementsByTagName("*"));
var visibleElements = [];
for (var i = 0; i < all.length; i++) {
var e = all[i];
// include elements in a shadowRoot.
if (e.shadowRoot) {
var cc = e.shadowRoot.querySelectorAll('*');
for (var j = 0; j < cc.length; j++) {
all.push(cc[j]);
}
}
var rect = e.getBoundingClientRect();
if ( (rect.top <= window.innerHeight) && (rect.bottom >= 0)
&& (rect.left <= window.innerWidth) && (rect.right >= 0)
&& rect.height > 0
&& getComputedStyle(e).visibility !== 'hidden'
) {
filter(e, visibleElements);
}
}
return visibleElements;
}
function cAdd1(keyCounter, index, maxDigit){
if(keyCounter[index] + 1 == maxDigit){
keyCounter[index] = 0;
@ -118,6 +122,7 @@
}
}
self.generateMarker = (selectors) => {
let style = document.createElement('style');
@ -179,9 +184,9 @@ z-index: 100000;\
let validRects = [];
if (typeof(selectors)=="function"){
addElementToRects(validRects, selectors.call()); // collect links
addElementToRects(validRects, selectors());
}else if (typeof(selectors) == "string"){
selectors = selectors.split(",")
selectors = selectors.split(",");
selectors.forEach((s)=>addElementToRects(validRects, document.querySelectorAll(s.trim())));
}
@ -212,7 +217,7 @@ z-index: 100000;\
if (match !== undefined && callback !== undefined){
let selectors = match.getAttribute('pointed-link');
let node = document.querySelector(selectors);
return callback(node)
return callback(node);
} else
return "";
}
@ -249,19 +254,33 @@ z-index: 100000;\
} else if(node.nodeName.toLowerCase() === 'a') {
node.click(); // most general a tag without href
}
return ""
return "";
}
self.generateTextNodeMarker = () => {
var elements = getVisibleElements(function(e, v) {
var aa = e.childNodes;
for (var i = 0, len = aa.length; i < len; i++) {
let elements = getVisibleElements(function(e, v) {
let aa = e.childNodes;
for (let i = 0, len = aa.length; i < len; i++) {
if (aa[i].nodeType == Node.TEXT_NODE && aa[i].data.length > 0) {
v.push(e);
break;
}
}
});
elements = Array.prototype.concat.apply([], elements.map(function (e) {
let aa = e.childNodes;
let bb = [];
for (let i = 0, len = aa.length; i < len; i++) {
if (aa[i].nodeType == Node.TEXT_NODE && aa[i].data.trim().length > 1) {
bb.push(aa[i]);
}
}
return bb;
}));
return elements;
}

Loading…
Cancel
Save