-1

Notes:
chrome.browserAction.onClicked.addListener with popup
Chrome Extension get selected text
Window.postMessage()
Capturing ctrl+z key combination in javascript

Related paradigms explanations:
(() => {} ES6 Arrow Function Is Simple, This Article Just Made It Simpler For JS Beginners
(() What do parentheses surrounding an object/function/class declaration mean?
return {} What do curly braces in JavaScript mean?

I'm searching for help on how to correctly understand and rewrite ugly code.

This is a working and tested code I was given:

document.body.appendChild(document.createElement('script')).text = '(' + (() => {
 addEventListener('message', function _(e) {
   if (e.data && e.data.type === 'getSelectedTextReply') {
     removeEventListener('message', _);
     alert('SUCCESS:\n' + e.data.selectedText);
   }
 });
 document.getElementById('plugin').postMessage({type: 'getSelectedText'}, '*');
   }) + ')()';

Current state of the script, tested and working:

function onKeyboardKeyDown() {
    //Checking if Content-Script is inserted inside PDF viewer extension)
    if (document.getElementById('plugin')) {
        alert('This is a PDF file opened by Chrome PDF viewer');


        //After opening a PDF page with Chrome PDF viewer
        //Assign a listener to the browser window,
        //to listen for a Selected Content by an User
        function addTextSelectionListener() {
            function receiveMessage(e) {
                if (e.data && e.data.type === 'getSelectedTextReply') {
                    removeEventListener('message', receiveMessage);
                    alert('SUCCESS:\n' + e.data.selectedText);
                }
            }
            //Setup listener to listen for a message from Chrome PDF viewer API
            window.addEventListener('message', receiveMessage);
            //Send request to get Selected Text from Chrome PDF viewer
            document.getElementById('plugin').postMessage({
                type: 'getSelectedText'
            }, '*');
        }


        //add Self executable addListener() function to the Script Tag
        //before appending it to the PDF viewer
        var scriptElement = document.createElement('script');
        scriptElement.text = '(' + addTextSelectionListener + ')()';
        document.body.appendChild(scriptElement);

    } else {
        //alert("This is not a PDF file page opened by Chrome PDF viewer");
    }

}
document.onkeydown = onKeyboardKeyDown;


Earlier, solved:


This is what I have done yet:

var scriptElement = document.createElement('script');

function listener(){
  return {
     addEventListener('message', function _(e) {
       if (e.data && e.data.type === 'getSelectedTextReply') {
         removeEventListener('message', _);
         alert('SUCCESS:\n' + e.data.selectedText);
       }
     });
     document.getElementById('plugin').postMessage({type: 'getSelectedText'}, '*');
   };
}

scriptElement.text = '(' + listener + ')()';
document.body.appendChild(scriptElement);

However, right now it has error:

Uncaught SyntaxError: Unexpected string myscript.js:5

This is the fifth line, where Syntax error occurs:

addEventListener('message', function _(e) {
user3789797
  • 450
  • 6
  • 15

2 Answers2

0

You need to put a

function()

before the brackets on line 4. In javascript, you have to use function() for something to be a function.

Your new code will be more like:

return function(){
...};
trinalbadger587
  • 1,905
  • 1
  • 18
  • 36
0

You need to be clear for what you intend to do with listener method.

Judging by this line scriptElement.text = '(' + listener + ')()';, I believe that you are expecting your addEventListener and rest of the logic to run as soon as listener is called after getting appended to body.

Look carefully you are actually returning a wrapper around your logic, an object.

function listener(){
  return {
    ...
  };
  ...
}

Your code won't get executed immediately as soon as your script gets appended to DOM, instead your call to listener will just return with a wrapper (at least it should, but you have an error there as well).

If it is intended then look for Solution 1 and Solution 2, otherwise look for Solution 3 (Recommended).

Solution 1 If you intend to return a wrapper around your logic and if it has to be run immediately then change listener implementation to look like below -

function listener() {
    return function () {
        addEventListener('message', function _(e) {
          if (e.data && e.data.type === 'getSelectedTextReply') {
              removeEventListener('message', _);
              alert('SUCCESS:\n' + e.data.selectedText);
          }
        });
        document.getElementById('plugin').postMessage({ type: 'getSelectedText' }, '*');
    }
}

and your listener call like this - scriptElement.text = '(' + listener + ')()()';

Solution 2 (Less likely to be a choice)

If you intended to return a wrapper around your logic and that too an object, then you have multiple syntax mistake there. Like -

1. You are returning an object but no key specified, so the value returned by addEventListener call won't get assigned to any prop in returned object.

This is the reason the interpreter was reporting unexpected string error because as per old ES, objects containing functions must be defined using following syntax:

{ 'addEventListener': function (msg, callBack) {} }

and as per ES6 the objects can take a shape like this -

{
  addListener (msg, callBack) {}
}

As you can see in both the cases we are not calling our addListener function, only defining it as the prop in object. But in your code, in the returned function you actually called that addListener method and there is nowhere to save the returned value.

2. You cannot have semicolon separated key value pairs in an object. Which is also the reason I believe that you do not intend to return an object.

Change your listener implementation to look like below, if you intend to return an object -

function listener(){
  return {
    methodName () {
      addEventListener('message', function _(e) {
        if (e.data && e.data.type === 'getSelectedTextReply') {
        removeEventListener('message', _);
        alert('SUCCESS:\n' + e.data.selectedText);
      }
    });
   document.getElementById('plugin').postMessage({type: 'getSelectedText'}, '*');
   }
  }
}

Solution 3 (Recommended as per scenario)

Just remove the return statement, and your function should look like this -

function listener() {
  addEventListener('message', function _(e) {
      if (e.data && e.data.type === 'getSelectedTextReply') {
          removeEventListener('message', _);
          alert('SUCCESS:\n' + e.data.selectedText);
      }
  });
  document.getElementById('plugin').postMessage({ type: 'getSelectedText' }, '*');
}

All set to execute as soon as script get appended to body node.

Community
  • 1
  • 1
Himanshu Singh
  • 970
  • 2
  • 6
  • 18
  • Thank you Himanshu, right now the script is in a way better state due to your explanations and working properly. It still looks not that nice to the of most of eyes beholders. But at very least it is now easier to understand most part of what the script does. – user3789797 Apr 07 '18 at 08:55
  • That would be good if you could give me your opinion on the current state of the script. – user3789797 Apr 07 '18 at 08:58
  • Also, to what element in the document is addEventListener('message', callback); assigned to? https://www.w3schools.com/jsref/met_element_addeventlistener.asp – user3789797 Apr 07 '18 at 09:13
  • w3school seems to suggest only this syntax: element.addEventListener(event, function, useCapture) – user3789797 Apr 07 '18 at 09:14
  • but in this case, there is no element, only function: addEventListener('message', callback); – user3789797 Apr 07 '18 at 09:15
  • Is it by default assigned to window.addEventListener('message', callback); if no element is specified? – user3789797 Apr 07 '18 at 09:16
  • Kindly let me know which solution are you referring to, only then I will be able to answer your queries. – Himanshu Singh Apr 07 '18 at 10:33
  • It's under the header of "Current state of the script, tested and working" - check the question post. But basically it's in every script version I shared here. – user3789797 Apr 07 '18 at 11:13
  • To directly answer, it's yours - Solution 3 (Recommended as per scenario) – user3789797 Apr 07 '18 at 11:23
  • Sorry, I didn't see the edit. Yes you are right, addEventListener method needs to be called on a DOM element. So current implementation calls addEventListener method on window object because of which the listener of 'message' event will listen to 'message' event on window. If it is not desired then simply call addEventListener on the DOM node from which you expect the message event to originate. That maybe your plugin node - in that case, just do - document.getElementById('plugin').addEventListener('message', callBack) – Himanshu Singh Apr 07 '18 at 13:22
  • I know that it is against the rules of stackoverflow, but thank you, due to your help i'm on the way to understand the code that was given – user3789797 Apr 07 '18 at 17:07
  • Great, way to go! Now if you have got your answer then it would be wise to close this question and mark an answer as correct. – Himanshu Singh Apr 07 '18 at 17:29
  • At first I avoided marking answer as correct due the following logic of stackoverflow that new guys there can't even vote "if answer is useful". So I though to myself indirectly: well if I can't vote for an useful answer, then I must not be able to select the solution in my own question. That is strange, sounds like buggy logic, but maybe there is reasons for that to exist in stackoverflow. – user3789797 Apr 07 '18 at 18:06
  • To be more clear: In my own asked question "if answer useful" upvotes are only recorded for the new guys out there and not shown until 15 reputation. However selecting the solution in my own question is possible without any limits. The later should not be possible, as the whole stackoverflow platform is oriented around community and not a single user. Marking a solution should require even more reputation than upvoting for a useful answer. – user3789797 Apr 07 '18 at 18:12
  • However that is way out of topic, you are really one of the good kind here on stackoverflow as I have seen. Thanks for pointing out. I'll try to keep clicking those stackoverflow buttons. – user3789797 Apr 07 '18 at 18:14