Bookmarklets

This is a React port of a CodePen I created a few years ago to help me with repetitive tasks I have to do on a regular basis as a developer – such as filling out forms and creating new logins, etc. Who knows – you may find it useful too. Once I clean it up a bit more and add some tests, I’ll share the code .

Some functional stuff

Share
Screen capture

function buildAttrs(obj) {
    let result = [];
    for (prop in obj) {
        result.push(`${prop}="${obj[prop]}"`);
    }
    return result.join(" ");
}

function createOutput(tag, attrs = {}) {
    return function outputTag(content = "") {
        return `<${tag || "div"} ${buildAttrs(attrs)}>${content}</${tag || "div"}>`;
    };
}

function outputToDom(el, tag, attrs = {}) {
    return function outputToContainer(content = "") {
        getTargetContainer(el).innerHTML += createOutput(tag, attrs)(content);
    };

    function getTargetContainer(id) {
        return document.getElementById(id) || addDiv(id);
    }

    function addDiv(id) {
        const targetDiv = document.createElement("div");
        targetDiv.id = id;
        return document.body.appendChild(targetDiv);
    }
}

function pipe(...fns) {
    return function piped(result) {
        for (let i = 0; i < fns.length; i++) {
            result = fns[i](result);
        }
        return result;
    };
}

const heading = createOutput("h1", { style: "margin: 0" });

const paragraph = createOutput("p");

const article = createOutput("article");

const output = outputToDom("js-output", "section", {
    style: "outline: 1px dotted red; padding: 10px; margin: 10px"
});

const capitalize = i => i.replace(i.charAt(0), i.charAt(0).toUpperCase());

const capitalizeHeading = pipe(capitalize, heading);

const capitalizeParagraph = pipe(capitalize, paragraph);

const buildArticle = i =>
    article(`${capitalizeHeading(i.heading)} ${capitalizeParagraph(i.body)}`);

const buildArticles = i => i.map(buildArticle);

const joinArticles = arr => arr.join("");

const content = [
    {
        heading:
            "A lot of people cry when they cut onions. The trick is not to form an emotional bond.",
        body:
            "Go Speed Racer. Go Speed Racer. Go Speed Racer go. we might as well say... Would you be mine? Could you be mine? Won't you be my neighbor? Baby if you've ever wondered - wondered whatever became of me. I'm living on the air in Cincinnati. Cincinnati WKRP. It's time to put on makeup. It's time to dress up right. It's time to raise the curtain on the Muppet Show tonight."
    },
    {
        heading:
            "I wrote a song about a tortilla. Well actually, it’s more of a wrap.",
        body:
            "Boy the way Glen Miller played. Songs that made the hit parade. Guys like us we had it made. Those were the days. Then one day he was shootin' at some food and up through the ground came a bubblin' crude. Oil that is. They're creepy and they're kooky mysterious and spooky. They're all together ooky the Addams Family."
    },
    {
        heading:
            "Some people just have a way with words, and other people ... oh ... not have way.",
        body:
            "In 1972 a crack commando unit was sent to prison by a military court for a crime they didn't commit. These men promptly escaped from a maximum security stockade to the Los Angeles underground. Sunday Monday Happy Days. Tuesday Wednesday Happy Days. Thursday Friday Happy Days.Saturday what a day. Groovin' all week with you. If you have a problem if no one else can help and if you can find them maybe you can hire The A-Team. And when the odds are against him and their dangers work to do. You bet your life Speed Racer he will see it through. The mate was a mighty sailin' man the Skipper brave and sure. Five passengers set sail that day for a three hour tour a three hour tour. Now were up in the big leagues getting' our turn at bat. In a freak mishap Ranger 3 and its pilot Captain William Buck Rogers are blown out of their trajectory into an orbit which freezes his life support systems and returns Buck Rogers to Earth five-hundred years later."
    }
];

const headingStyles = { style: "font-family: sans-serif" };

outputToDom("js-headings", "h1", headingStyles)(
    "Functional JS"
);

outputToDom("js-headings", "h2", headingStyles)(
    "AKA This is wickedly cool shit!"
);

pipe(buildArticles, joinArticles, output)(content);
Share

Array Iteration

Share

Two quick ways to iterate through an array (from .length to 0).

What’s the point?

  • It’s fast to compare something to zero
  • Less code overall

Why it’s weird…

We’re used to counting from zero to length – not vice-versa

When not to use

The only place I can think of that this wouldn’t be a good idea would be when you need to iterate over the array in ascending key order.

var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
var b = a.length;

// quickly iterate through array
while (b--) {
console.log(a[b]);
}

// declaring var in same line
for (var c = a.length; c--; ) {
console.log(a[c]);
}

// of course THIS is best
a.forEach(i => console.log(i));
Share

Thoughts on coercion

Share

Thoughts on coercion

Here’s an interesting tidbit. If you’ve ever used indexOf to determine if a string contains another string (perhaps I could word this better…), then you’ve probably used something like:

var a = 'Jim';
a.indexOf('i') !== -1; // true

As you’re probably aware, if the string is not found, –1 is the return value.

A simpler and more efficient way to accomplish this test is:

var a = 'Jim';
~a.indexOf('i'); // true (coerced)

or

Boolean(~a.indexOf('i')); // true

A lot of people will state that coercion in JS is evil. I’d state that what is really evil is when people don’t know what that coercion is doing. I recently watched a video series by Kyle Simpson where he illustrated a few places where using coercion to your advantage will create simpler, easier to understand, less error-prone code. For example:

var foo; // undefined

Let’s say that foo, in this case could be undefined or null.
Using explicit coercion, our check for this value would be:

if ( foo===undefined || foo===null ) {
    // should work, all bases are covered
}

A simpler, more readable check:

if ( foo == null ) {
    // works for null or undefined
}
Share

Partially-Applied Function – Practical Example

Share
This example demonstrates several concepts:
  • modules
  • partially applied functions
  • functional programming techniques
The partialGetElID function creates a partially applied function that replaces hyphenated, underscored, or dotted names with their camelCased variant.
module.exports = {
    partialGetElID: (wf, pg) =>el=>`${sepsToCamelCase(wf)}-${sepsToCamelCase(pg)}-${sepsToCamelCase(el)}`
};

var sepsToCamelCase = function(arg) {

    var upperFirst = s => s.replace(s.charAt(0), s.charAt(0).toUpperCase());
    var lowerFirst = s => s.replace(s.charAt(0), s.charAt(0).toLowerCase());

    return (
        R.pipe(
            R.split(/[._-]/g),
            R.map(upperFirst),
            R.join(''),
            lowerFirst
        )(arg)
    );
};
Usage:

var X = require('path/to/module');
var getID = X.partialGetElId('workflow.name', 'step_name');

getID('element-name') // returns workflowName-stepName-elementName
Share

Functional Programming Example – using Ramda

Share

Functional Programming Example – using Ramda

Copy and paste this code into your console. It automatically loads Ramda and uses that to process the beerData.

Two concepts covered in this example:

  • Loading external scripts into the console (which works in chrome developer tools snippets at minimum). I can’t seem to find a way to make it work in firefox.
  • Functional programming.

#functional, #loadingScripts

var script = document.createElement('script');
script.type = 'text/javascript';
script.src = '//cdnjs.cloudflare.com/ajax/libs/ramda/0.21.0/ramda.min.js';
document.head.appendChild(script);

beerData = [
    {"name": "Bitter Hop", "type": "ipa", "locale": "domestic", "abv": 7.9},
    {"name": "Dragonblood Black IPA", "type": "ipa", "locale": "domestic", "abv": 6.5},
    {"name": "Good Dog Lager", "type": "lager", "locale": "domestic", "abv": 4.8},
    {"name": "Good Dog Snowpants", "type": "stout", "locale": "domestic", "abv": 8.1},
    {"name": "Lake Erie 2x IPA", "type": "ipa", "locale": "domestic", "abv": 9.3},
    {"name": "Lake Erie Session", "type": "ale", "locale": "domestic", "abv": 4.2},
    {"name": "Samwell British Pale Ale", "type": "ale", "locale": "import", "abv": 6.5},
    {"name": "Samwell Oatmeal Stout", "type": "stout", "locale": "import", "abv": 5.5},
    {"name": "Samwell Winter Ale", "type": "ale", "locale": "import", "abv": 6.8},
    {"name": "Sparkwood Beer Five", "type": "lager", "locale": "domestic", "abv": 6.2},
    {"name": "Sparkwood Campfire Lager", "type": "lager", "locale": "domestic", "abv": 5.8},
    {"name": "Tartan Scottish Ale", "type": "ale", "locale": "import", "abv": 7.5}
]

console.clear();

console.log('beerData:');
console.table(beerData);

var uniqueTypes = R.pipe(R.pluck('type'), R.uniq, R.sort((a, b) => a > b));
var typeList = uniqueTypes(beerData);

console.log('typeList: ', typeList);

var displayBeerByType = R.pipe(
    R.propEq('type'),
    R.filter(R.__, beerData),
    console.table.bind(console)
);


R.forEach(displayBeerByType, typeList);
Share

Text Scrambler Plugin

Share

Want to see the Text Scrambler in action? You can find that here.

Want to cut to the chase and download a copy of your own so that you can go play? Here you go.

This plug-in is written in plain ol’ vanilla JavaScript and is not dependent on any other libraries (such as jQuery).

There are just two things you need to do to include the Text Scrambler on your web page:

  1. Include the HTML markup for the controls and the containers that hold them and the scrambled text
  2. Include the JavaScript plug-in that does all the heavy lifting

1. HTML Markup

Somewhere within the body of your page, you’ll need to include markup similar to the example below. You can customize the text if you like – and if you delve into the script itself, you’ll see that you can change the names of the controls too. There are also plenty of hooks for CSS, so that you can customize the appearance.

[html]
<textarea name=”inputContainer” id=”inputContainer” cols=”30″ rows=”10″ placeholder=”Enter some content here, then press the button below.”></textarea><br><br>

<button id=”actionDoIt”>Do it!</button> <button id=”actionReset”>Reset</button><br><br>

<textarea name=”outputContainer” id=”outputContainer” cols=”30″ rows=”10″ placeholder=”And it wlil apaepr sbarmelcd here.”></textarea>
[/html]

2. Include the JavaScript plugin

You’ll need to host the script itself somewhere – then adjust the path/to the file to reflect that location

[html]
<script src=”path/to/randomizer.js”></script>
[/html]

3. Enjoy!

Share

Text Scrambler

Share

Inspired by an image I saw on Facebook, I decided to create a little web app that scrambles text, but keeps the first and last letters in place.
This text has made its way around as office spam too.

If you can read tihs, you have a stnarge mind too. Can you raed tihs? Olny 55 peolpe out of 100 can. I coldnu’t belviee taht I cluod alctualy udnaerstnd waht I was reanidg. The pnonhemael pweor of the human mind, adocicrng to a reaesrch at Cmrgabide Uivtsinery, it dnoe’st mtater in what oredr the leretts in a wrod are, the olny irpatomnt tihng is taht the fisrt and lsat ltteer be in the rgiht pcale. The rset can be a toatl mses and you can still raed it woituht a plborem. This is busacee the hmaun mnid does not raed ervey letetr by isltef, but the word as a whloe. Aizanmg huh? Yaeh, and I aywals tohghut slenpilg was impotnart.

Input Text

If you like this plugin and would like info on including it on your own website (it’s free!), then you can find more info right here.

Share