-
Showing Salesforce RecordId in the Contact List
I have a table of contacts in Salesforce. To my surprise you cannot choose to show the RecordId (e.g., 0036g00002d4BOHAAU) in the field configuration. I did some digging and it seems it’s not possible without using some workaround that requires a calculated field or similar. I just needed the IDs for a one-time use. I realized the ID is included in the linked fields but didn’t want to have to hover each of the “Name” and “Account Name” links to see the IDs. So, I whipped up some javascript to simply append the RecordId to the end of these links. I can run the javascript via console, or even add it to a user script or place it automatically with a code injector extension.
-
Using Dataview with Charts in Obsidian
Obsidian is my third most used application after Keyboard Maestro and Alfred. I’ve been using the dataview plugin since I got started with Obsidian. It’s an incredible plugin that gives you the ability to treat your notes like database records. In this example I’ll show how I use dataview to make my projects queryable, and then how I use Obsidian-Charts to make some bar charts of this data.
Using Dataview Variables
Here’s an example of a Project file in my Obsidian vault:
-
Adding a Global Function to Cypress for a Date {num} Months Ago
I’m working on a COVID-19 booster shot registration form. On this form I ask the user when they received their last COVID-19 vaccine shot. This is three simple fields (the month values are 01, 02, 03, etc.):
Each vaccine brand (Pfizer, Moderna, J&J) has different eligibility criteria as it relates to the time since the individual received their original vaccine series. Pfizer, for example, is 6 months. My form needs to reject a user who says they received Pfizer less than 6 months ago.
Using Cypress I wanted some test coverage of this functionality. Original I had hard-coded a date value of 5 months ago:
123cy.get('select[name="datelastvax_month"]').select('08');cy.get('select[name="datelastvax_day"]').select('01');cy.get('select[name="datelastvax_year"]').select('2021');As you can imagine this would work well for a while. Fast-forward a few months from now… the time ago will eventually be more than 6 months ago. I don’t want to have to keep updating this code with a recent date. The obvious solution is to dynamically choose the dates based on the current date. A global helper function would be ideal as I need to use this in many tests. Here’s a simple solution:
Step 1: Define the Function in index.js
The support/index.js file is loaded before each Cypress run. Creating a global function here is a quick way to introduce a reusable piece of code.
12345678910111213141516171819202122/*** Returns a simple object for {num} months ago, containing YYYY, MM, DD.** @param {number} num* Number of months to subtract from current date.** @return object* Object containing three properties (year:YYYY, month:MM, day:DD)*/cy.getDateMonthsAgo = (num) => {const dateObj = new Date(new Date().getFullYear(),new Date().getMonth() - num,new Date().getDate());return {year: dateObj.getFullYear().toString(),month: ('0' + (dateObj.getMonth() + 1)).slice(-2),day: ('0' + dateObj.getDate()).slice(-2),}}There are many solutions to handle getting a date from {num} months ago. If you start looking around for “What is a month, really?” you will find many different opinions. The code I’m using above responds like most humans do: give the same day of the month from {num} months ago. With a {num} of 5 (five months ago), on October 25, 2021 the result would be May 25, 2021.
WARNING: Please note the following:
12345new Date(2021, 1, 28) ==> February 28, 2021new Date(2021, 1, 29) ==> March 1, 2021new Date(2021, 1, 30) ==> March 2, 2021new Date(2021, 1, 31) ==> March 3, 2021new Date(2021, 1, 32) ==> March 4, 2021Step 2: Use the Function
1234const fiveMonthsAgo = cy.getDateMonthsAgo(5);cy.get('select[name="datelastvax_month"]').select(fiveMonthsAgo.month);cy.get('select[name="datelastvax_day"]').select(fiveMonthsAgo.day);cy.get('select[name="datelastvax_year"]').select(fiveMonthsAgo.year); -
NightwatchJS Command to Repeat a Keystroke
Here’s a simple custom command that lets you repeat a specific key (single or combo) N number of times.
In the Drupal world you want to place this in your “Commands” directory (as defined in DRUPAL_NIGHTWATCH_SEARCH_DIRECTORY in web/core/.env).
You’d want to change “sitename” to be your site’s name (so it feels namespaced).
/tests/Nightwatch/Commands/sitenameRepeatKeystroke.js
123456789101112131415161718192021222324252627282930313233/*** Repeats a keystroke (can be multiple keys) a specific number of times.** @param {array} keys* Array of keys to send.* Example 1: [browser.Keys.TAB]* Example 2: [browser.Keys.SHIFT, browser.Keys.TAB, browser.Keys.NULL]);* (it's important to terminate modifier keys with NULL)* @param {integer} times* Number of times to repeat the key send.* @param {integer} pauseBetween* Number of milliseconds to pause between each key send (100 ms default).* @param {function} callback* A callback which will be called.* @return {object}* The 'browser' object.*/exports.command = function myCommand(keys, times, pauseBetween = 100, callback) {const self = this;for (let i = 0; i < times; i++) {this.keys(keys);if (pauseBetween) {this.pause(pauseBetween);}}if (typeof callback === 'function') {callback.call(self);}return this;};Using this in /tests/Nightwatch/Tests/misc.js with a 1000ms pause between each keystroke:
12345678910111213/* eslint-disable no-unused-expressions */module.exports = {'@tags': ['mysite', 'learn-page', 'accessibility'],'When I hit shift-tab 9 times on the Learn page my logo becomes the active element': browser => {browser.drupalRelativeURL('/learn');browser.sitenameRepeatKeystroke([browser.Keys.SHIFT, browser.Keys.TAB, browser.Keys.NULL],9,1000,);},}; -
Monitoring Which Element Has Focus in a Web Browser
While building accessibility-minded websites, it’s useful to be able to monitor which element has focus in your browser.
Using a screen reader works well, but there may be an easier solution for those who aren’t used to screen readers.
Chrome makes this pretty simple. See https://developers.google.com/web/tools/chrome-devtools/accessibility/focus.
In Firefox, Safari, Chrome, and other browsers I’m able to achieve similar functionality (maybe even better) by running a simple snippet in the web developer tools console.
New lines appear as you move through the elements with your keyboard (or mouse).
You may want to turn this into a one-liner for easier pasting.
1234567var lastElement = document.activeElement;setInterval(function() {if (lastElement != document.activeElement) {lastElement = document.activeElement;console.log(document.activeElement);}}, 100);Output in Firefox:
-
Sort “Select an existing field” options in Drupal by Label instead of Type
Normally Drupal sorts the “Select an existing field” select list by the field types. Here’s an example of what this looks like:
This looks good at first glance, but often it’s hard to quickly find the field you want to reuse. Most of the time you’re scanning the list for the name (label) of the field you want to reuse. Wouldn’t it make more sense to put the field label at the beginning and sort by that? I thought it would, so I made it happen with a quick userscript.
-
Keyboard Maestro URL Handler – Link Injection
Introduction
This post outlines some advanced usage of the Keyboard Maestro URL handler (KMLink).
A few weeks ago I was automating some Chrome form filling with Keyboard Maestro. It occurred to me that the perfect trigger for what I was doing would actually be a simple link within the Chrome webpage itself (or a simple bookmarklet); when the link/bookmarklet is clicked, the KM macro is executed. How about a little backstory before I get to the “here’s how to do it!” ?
We use a project management system called ActiveCollab. It’s a great piece of web-based software, but often simple things take several steps. When I want to quickly mark a task as “Due in 2 business days” (which I need to do very often) it’d be whole lot nicer to click a link to set this, than to have to go to the edit screen, pull up the date picker, think about what two business days from today is, click that date and submit the form. Sure, I could write a module for Active Collab that would do what I want, but Keyboard Maestro provides me with much more freedom and I can build it in minutes instead of hours.
-
Userscript: Hulu Right-Click for Pop Out Video
Hulu’s default rather large video player is usually too big for my needs. I prefer the “Pop Out” player. So, I often load the large video, click the cog wheel, move my mouse to the “popout” link, click it, then close the main window. It’s been a pain in the butt. So, I took some time to write a simple userscript that lets you right-click on any video thumbnail to open its video in the popout immediately. It’s working great for me but I have not tested it elsewhere, so I won’t be surprised if it doesn’t work for you… just let me know in the comments below…
http://userscripts.org/scripts/show/311800UPDATE: I rewrote this as a Chrome Extension and published it. View the blog post.
-
Maintaining Lightbox2 Templating
Lightbox2 is a very popular and powerful Drupal module. One of the helpful features is that you can render a Drupal node in a lightbox rather easily in either PHP or HTML. View detailed explanation. The issue is that when you click a link within that lightboxed content, you will lose the lightbox2 templating (e.g., if your lightbox template hides sidebars, they’ll only be hidden when the node loads. If you click a link within the lightbox, the new node will load and sidebars will appear). Read on for a quick fix.
-
Make menu header a link to its first child link
We use menu block a lot to create sidebar menus with specific depths, starting points, etc. The following snippet shows how we can use jQuery to turn a normal <h2> tag into a link. The link’s destination will be the same as the first child link.
12var href = $('#block-menu_block-1 h2.title').next().find('li a').attr('href');$('#block-menu_block-1 h2.title').html($('<a></a>').html($('#block-menu_block-1 h2.title').html()).attr('href', href));