MozillaZine


Copy and paste the code of an .js file in a bookmarklet

User Help for Mozilla Firefox
user2018
 
Posts: 88
Joined: September 23rd, 2018, 11:07 am

Post Posted May 13th, 2020, 5:23 am

I am trying to use https://leaverou.github.io/stretchy/stretchy.js as a bookmarklet. It is fine if I define the bookmarklet as follows, as suggested in the web page:

javascript:(function(script){script.src='https://leaverou.github.io/stretchy/stretchy.min.js';document.body.appendChild(script);})(document.createElement('script'))

However, in this case the script has to be loaded remotely (by accessing https://leaverou.github.io/stretchy/stretchy.min.js). I would like to avoid that indirect access through the Internet. I tried to load the file locally (through "file://") but it does not work, probably for security reasons.

Is there any way to copy and paste the contents of the stretchy.js or stretchy.min.js file so that I can have a "local" version of the bookmarklet that does not need to connect remotely to download the updated .js file?

morat
 
Posts: 4204
Joined: February 3rd, 2009, 6:29 pm

Post Posted May 13th, 2020, 8:47 am

The following code snippet works in the console.

Code: Select all
(function () {

if (!self.Element) {
  return;
}

if (!Element.prototype.matches) {
  Element.prototype.matches = Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || null;
}

if (!Element.prototype.matches) {
  return;
}

function $$(expr, con) {
  return expr instanceof Node || expr instanceof Window? [expr] :
         [].slice.call(typeof expr == "string"? (con || document).querySelectorAll(expr) : expr || []);
}

var _ = self.Stretchy = {
  selectors: {
    base: 'textarea, select:not([size]), input:not([type]), input[type="' + "text number url email tel".split(" ").join('"], input[type="') + '"]',
    filter: "*"
  },

  script: document.currentScript || $$("script").pop(),

  resize: function(element) {
    if (!_.resizes(element)) {
      return;
    }

    var cs = getComputedStyle(element);
    var offset = 0;
    var empty;

    if (!element.value && element.placeholder) {
      empty = true;
      element.value = element.placeholder;
    }

    var type = element.nodeName.toLowerCase();

    if (type == "textarea") {
      element.style.height = "0";

      if (cs.boxSizing == "border-box") {
        offset = element.offsetHeight;
      }
      else if (cs.boxSizing == "content-box") {
        offset = -element.clientHeight + parseFloat(cs.minHeight);
      }

      element.style.height = element.scrollHeight + offset + "px";
    }
    else if (type == "input") {
      element.style.width = "1000px";

      if (element.offsetWidth) {
        element.style.width = "0";

        if (cs.boxSizing == "border-box") {
          offset = element.offsetWidth;
        }
        else if (cs.boxSizing == "padding-box") {
          offset = element.clientWidth;
        }
        else if (cs.boxSizing == "content-box") {
          offset = parseFloat(cs.minWidth);
        }

        var width = Math.max(offset, element.scrollWidth - element.clientWidth);

        element.style.width = width + "px";

        for (var i=0; i<10; i++) {
          element.scrollLeft = 1e+10;

          if (element.scrollLeft == 0) {
            break;
          }

          width += element.scrollLeft;

          element.style.width = width + "px";
        }
      }
      else {
        element.style.width = element.value.length + 1 + "ch";
      }
    }
    else if (type == "select") {
      var selectedIndex = element.selectedIndex > 0? element.selectedIndex : 0;

      var option = document.createElement("_");
      option.textContent = element.options[selectedIndex].textContent;
      element.parentNode.insertBefore(option, element.nextSibling);

      var appearance;

      for (var property in cs) {
        var value = cs[property];
        if (!/^(width|webkitLogicalWidth|length)$/.test(property) && typeof value == "string") {
          option.style[property] = value;

          if (/appearance$/i.test(property)) {
            appearance = property;
          }
        }
      }

      option.style.width = "";

      if (option.offsetWidth > 0) {
        element.style.width = option.offsetWidth + "px";

        if (!cs[appearance] || cs[appearance] !== "none") {
          element.style.width = "calc(" + element.style.width + " + 2em)";
        }
      }

      option.parentNode.removeChild(option);
      option = null;
    }

    if (empty) {
      element.value = "";
    }
  },

  resizeAll: function(elements) {
    $$(elements || _.selectors.base).forEach(function (element) {
      _.resize(element);
    });
  },

  active: true,

  resizes: function(element) {
    return element &&
           element.parentNode &&
           element.matches &&
           element.matches(_.selectors.base) &&
           element.matches(_.selectors.filter);
  },

  init: function(){
    _.selectors.filter = _.script.getAttribute("data-filter") ||
                         ($$("[data-stretchy-filter]").pop() || document.body).getAttribute("data-stretchy-filter") || _.selectors.filter;

    _.resizeAll();

    if (self.MutationObserver && !_.observer) {
      _.observer = new MutationObserver(function(mutations) {
        if (_.active) {
          mutations.forEach(function(mutation) {
            if (mutation.type == "childList") {
              _.resizeAll(mutation.addedNodes);
            }
          });
        }
      });
      _.observer.observe(document.documentElement, {
        childList: true,
        subtree: true
      });
    }
  },

  $$: $$
};

if (document.readyState !== "loading") {
  requestAnimationFrame(_.init);
}
else {
  document.addEventListener("DOMContentLoaded", _.init);
}

window.addEventListener("load", function(){
  _.resizeAll();
});

var listener = function(evt) {
  if (_.active) {
    _.resize(evt.target);
  }
};

document.documentElement.addEventListener("input", listener);

document.documentElement.addEventListener("change", listener);

})();

Stretchy Usage
http://leaverou.github.io/stretchy/

Bookmarklet Builder
http://subsimple.com/bookmarklets/jsbuilder.htm

user2018
 
Posts: 88
Joined: September 23rd, 2018, 11:07 am

Post Posted May 13th, 2020, 8:55 am

Maybe I am using the Bookmarklet Builder incorrectly, but if I enter there the code and then I drag the bookmark to the bookmark list and click on it, nothing happens. Looking at the console, I see this error:

SyntaxError: missing } in compound statement 2 superoldbrowser}if(!Element.prototype.matches){Element.prototype.matches=Element.prototype.webkitMatchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||null;}if(!Element.prototype.matches){return;}function $$(expr,con){return exprinstanceofNode||exprinstanceofWindow:1:4459note: { opened at line 1, column 142superoldbrowser}if(!Element.prototype.matches){Element.prototype.matches=Element.prototype.webkitMatchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||null;}if(!Element.prototype.matches){return;}function $$(expr,con){return exprinstanceofNode||exprinstanceofWindow:1:142

Snapshot of the Bookmarklet Builder (last check: May 13, 2020): https://pasteboard.co/J8cwqjb.png

Any ideas?

morat
 
Posts: 4204
Joined: February 3rd, 2009, 6:29 pm

Post Posted May 13th, 2020, 9:12 am

Bookmarklet Builder fails with the new syntax.

Try these:

Bookmarkleter
http://chriszarate.github.io/bookmarkleter

JSCompress with ECMAScript 2018 support
http://jscompress.com/

Note that I removed the comments in the code snippet so the bookmarklet utility works correctly.

therube

User avatar
 
Posts: 20587
Joined: March 10th, 2004, 9:59 pm
Location: Maryland USA

Post Posted May 15th, 2020, 1:02 pm

Does the bookmarklet (from his webpage) actually work (in FF)?
Wasn't quite sure what it's supposed to do, but either saw no change to the page, or in one case, it seemed to cause a doubling-like (& only a smidgen at that) of one field on a page.

(Kind of surprised that FF would allow the bookmarklet to "call" that foreign .js, hosted on his site.)
Fire 750, bring back 250.
Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.19) Gecko/20110420 SeaMonkey/2.0.14 Pinball CopyURL+ FetchTextURL FlashGot NoScript

user2018
 
Posts: 88
Joined: September 23rd, 2018, 11:07 am

Post Posted May 29th, 2020, 2:40 am

Yes, it works. I was also surprised: executing a foreign .js file seems quite risky, unless additional restrictions are applied...

Return to Firefox Support


Who is online

Users browsing this forum: Bing [Bot], Google Adsense [Bot] and 5 guests