Reimplemented and refactored how the main page is captured. Now using iframe to capture the main page and listening to changes and tagging inside.

This commit is contained in:
Nils Norman Haukås 2016-01-17 20:09:54 +01:00
parent 923d7af843
commit 1fb288f583
3 changed files with 88 additions and 72 deletions

View file

@ -4,13 +4,24 @@
*/
$.get(chrome.extension.getURL('index-angular-app.html'), function (htmlData) {
var iframe = document.createElement('iframe');
iframe.id = 'tagit-iframe';
iframe.srcdoc = htmlData;
iframe.seamless = 'seamless';
iframe.frameBorder = "0";
iframe.className = 'tagit-iframe';
iframe.sandbox = 'allow-same-origin allow-top-navigation allow-scripts';
$('body').children().wrapAll('<div id="tagit-body" class="tagit-body" />');
$('.tagit-body').before(iframe);
var iframeMainContent = document.createElement('iframe');
iframeMainContent.id = 'tagit-body';
iframeMainContent.className = 'tagit-body';
iframeMainContent.src = window.location.href;
//empty the page
$('body').children().remove();
//remove style sheets
$('link[rel=stylesheet]').remove();
//reinsert page this time inside an iframe
$('body').append(iframeMainContent);
var iframeMenu = document.createElement('iframe');
iframeMenu.id = 'tagit-iframe';
iframeMenu.srcdoc = htmlData;
iframeMenu.seamless = 'seamless';
iframeMenu.frameBorder = "0";
iframeMenu.className = 'tagit-iframe';
// iframe.sandbox = 'allow-same-origin allow-top-navigation allow-scripts';
$('.tagit-body').before(iframeMenu);
});

View file

@ -16,6 +16,8 @@ module tagIt {
// we need to remember what the currently selected word was
tagStorageService: TagStorageService;
savedSelection: Object;
iframeDocument: Document;
iframeWindow: Window;
/* @ngInject */
constructor($log: ng.ILogService, TagStorageService: TagStorageService) {
@ -29,23 +31,25 @@ module tagIt {
wireUpListener(callbackOnSelectFunc: (result: Object) => void,
callbackOnDeSelectFunc: () => void) {
var that = this;
parent.document.getElementById('tagit-body')
.addEventListener('click', (evt: any) => {
if (!parent.document.hasFocus()) {
return true;
}
else if (wasRemoveTagButtonClicked(evt)) {
this.$log.debug('remove tag button was clicked');
removeTagFromWebpage(evt);
this.tagStorageService.deleteTagById(evt.target.parentElement.id);
}
else if (this.findSelectedText()) {
this.updateSavedSelection();
callbackOnSelectFunc(joinLongWords(this.findSelectedText()));
} else {
callbackOnDeSelectFunc();
}
}, false);
var iframe = <HTMLIFrameElement>parent.document.getElementById('tagit-body');
this.iframeDocument = iframe.contentDocument;
this.iframeWindow = iframe.contentWindow;
this.iframeDocument.addEventListener('click', (evt: any) => {
if (!this.iframeDocument.hasFocus()) {
return true;
}
else if (wasRemoveTagButtonClicked(evt)) {
this.$log.debug('remove tag button was clicked');
removeTagFromWebpage(evt);
this.tagStorageService.deleteTagById(evt.target.parentElement.id);
}
else if (this.findSelectedText()) {
this.updateSavedSelection();
callbackOnSelectFunc(joinLongWords(this.findSelectedText()));
} else {
callbackOnDeSelectFunc();
}
}, false);
function joinLongWords(possiblyLongWord: string) {
return possiblyLongWord.replace(" ", "_");
}
@ -61,7 +65,7 @@ module tagIt {
}
findSelectedText() {
var selectedText = parent.getSelection().toString();
var selectedText = this.iframeDocument.getSelection().toString();
if (selectedText) {
this.$log.debug('text that was selected: ' + selectedText);
return selectedText;
@ -70,30 +74,11 @@ module tagIt {
}
}
initializeNewTag = (sense: ISense): ISenseTag => {
this.$log.debug('initializeNewTag');
rangy.restoreSelection(this.savedSelection);
var range: Range = rangy.getSelection(parent).getRangeAt(0);
var serializedRange = rangy.serializeRange(
range, true, parent.document.getElementById('tagit-body'));
var generatedUuid: string = uuid.v4();
var parentElement = <HTMLElement>range.commonAncestorContainer;
return {
id: generatedUuid,
userEmail: 'testEmail',
sense: sense,
wordThatWasTagged: this.findSelectedText(),
context: parentElement.innerText,
serializedSelectionRange: serializedRange
}
};
removeAllTagsFromPage(callback: () => void) {
//loop that will keep asking for spans to remove
//until they are all gone.
while (parent.document.getElementsByClassName('tagit-tag').length > 0) {
var spanElement = parent.document.getElementsByClassName('tagit-tag')[0];
while (this.iframeDocument.getElementsByClassName('tagit-tag').length > 0) {
var spanElement = this.iframeDocument.getElementsByClassName('tagit-tag')[0];
var spanElementParent = spanElement.parentNode;
spanElementParent.replaceChild(
spanElement.firstChild,
@ -105,12 +90,27 @@ module tagIt {
readdTagsToPage(tagsToLoad: ISenseTag[]) {
this.$log.debug('readdTagsToPage()');
//first deselect before we go to work
parent.getSelection().removeAllRanges();
this.iframeDocument.getSelection().removeAllRanges();
//deserialize ranges
_.map(tagsToLoad, deserializeRange);
_.map(tagsToLoad, (tagToLoad) => {
try {
tagToLoad.deserializedRange = rangy.deserializeRange(
tagToLoad.serializedSelectionRange,
this.iframeDocument.documentElement,
this.iframeWindow
);
} catch (e) {
var errorMsg = `Error in rangy.js: Was not able to deserialize range.
In other words: The page might have changed. Is not able
to determine where this tag should have been placed.`
this.$log.debug(errorMsg);
this.$log.debug("Couldn't load: " + tagToLoad.sense.word);
this.$log.debug(e);
}
});
this.$log.debug('finished deserializing tags');
@ -129,35 +129,39 @@ module tagIt {
});
this.$log.debug('finished adding tags to page');
parent.getSelection().removeAllRanges();
function deserializeRange(tagToLoad: ISenseTag) {
try {
tagToLoad.deserializedRange = rangy.deserializeRange(
tagToLoad.serializedSelectionRange,
parent.document.getElementById('tagit-body'));
} catch (e) {
var errorMsg = `Error in rangy.js: Was not able to deserialize range.
In other words: The page might have changed. Is not able
to determine where this tag should have been placed.`
console.log(errorMsg);
console.log("Couldn't load: " + tagToLoad.sense.word);
console.log(e);
}
}
this.iframeDocument.getSelection().removeAllRanges();
}
initializeNewTag = (sense: ISense): ISenseTag => {
this.$log.debug('initializeNewTag');
rangy.restoreSelection(this.savedSelection);
var range: Range = rangy.getSelection(this.iframeDocument).getRangeAt(0);
var serializedRange = rangy.serializeRange(range, true, this.iframeDocument.documentElement);
var generatedUuid: string = uuid.v4();
var parentElement = <HTMLElement>range.commonAncestorContainer;
return {
id: generatedUuid,
userEmail: 'testEmail',
sense: sense,
wordThatWasTagged: this.findSelectedText(),
context: parentElement.innerText,
serializedSelectionRange: serializedRange
}
};
private updateSavedSelection() {
if (this.savedSelection) {
rangy.removeMarkers(this.savedSelection);
}
this.savedSelection = rangy.saveSelection(parent);
this.savedSelection = rangy.saveSelection(this.iframeWindow);
}
private surroundRangeWithSpan(sense: ISense, range: Range, uuid: string) {
// add span around content
var span: HTMLSpanElement = parent.document.createElement('span');
var span: HTMLSpanElement = this.iframeDocument.createElement('span');
span.id = uuid;
span.title = sense.explanation;
span.className = 'tagit-tag';
@ -165,9 +169,9 @@ module tagIt {
range.surroundContents(span);
// add a button for removing the tag.
var btn = parent.document.createElement("BUTTON");
var btn = this.iframeDocument.createElement("BUTTON");
btn.className = 'js-tagit-remove-tag';
btn.appendChild(document.createTextNode("X"));
btn.appendChild(this.iframeDocument.createTextNode("X"));
span.appendChild(btn);
}
}

View file

@ -4,6 +4,7 @@
overflow-y: auto;
right: 0;
padding: 10px;
height: 100%;
}
.tagit-iframe {