The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,860 other subscribers

Some JavaScript bookmarklets for WordPress published pages centered around navigation and IDs

Posted by jpluimers on 2023/07/20

Maintaining a blog takes considerable time, so I wrote a bit of JavaScript for the browser console and bookmarklets to help me navigate faster, especially from my published posts on wiert.me back to the WordPress editing environment.

I wrote this because a query like [Wayback/Archive] wordpress get id from post html – Google Search top hits only contain results that work within the WordPress environment itself, like for instance [Wayback/Archive] 14 Ways to Get Post ID in WordPress.

This blog post is long and contains a lot of information, so I have split it in quite a few sections.

Let’s get started:

About post IDs

A post can be published with multiple ways, for instance the post with ID=85080 and title=Philosophy of management has at least these URLs:

  1. https://wiert.me/2022/02/14/philosophy-of-management/
  2. https://wiert.me/2022/02/14/85080/
  3. https://wiert.me/?p=85080/
  4. https://wiert.me/philosophy-of-management/
  5. https://wiert.wordpress.com/2022/02/14/philosophy-of-management/
  6. https://wiert.wordpress.com/2022/02/14/85080/
  7. https://wiert.wordpress.com/?p=85080/
  8. https://wiert.wordpress.com/philosophy-of-management/
  9. https://wp.me/pvelJ-m8g (not sure how that one is generated)
  10. https://wordpress.com/post/wiert.me/85080
  11. https://wiert.wordpress.com/wp-admin/post.php?post=85080&action=edit
  12. https://wiert.wordpress.com/wp-admin/post.php?post=85080&action=edit&classic-editor

If a custom domain is configured, then URLs number 2. through 9. will redirect to 1.

Without a custom domain, URLs 1. through 4. are invalid, and 6. through 9. will redirect to 4.

I bolded a few of the URLs, and this is why:

  • The first URL is where all other URLs but the last two will redirect to.
  • The fourth URL is the canonical way to refer the post within the custom domain
  • The seventh URL is the canonical way to refer the post within the original domain.
    It is the best way to refer to a published post by ID as that one stays unique over the lifetime of a post (a Title can change because of for instance fixing a typo, or forgetting that some characters in the title need to be URL-escaped: a thing I documented yesterday in Characters you need to escape in the Title of a WordPress post)
  • The last three URLs are to edit a post.

I vastly prefer the classic editor over the Gutenberg editor, see Some of my wp-admin links, as WordPress.com is hiding access to classic-editor and wp-admin links more and more. Regrettably there is no classic editor alternative for the tenth URL above.

My goal was to get JavaScript to assemble the seventh and last URLs.

Getting information from a published post

Here are some JavaScript expressions that got me going:

What How Example output
post ID document.getElementsByName("comment_post_ID")[0]?.value 85080
custom domain URL HighlanderComments.homeURL 'https://wiert.me/'
original domain URL {var a=document.createElement("a"); a.setAttribute("href", HighlanderComments.connectURL); a.pathname=''; a.search=''; a.hash=''; a.href; } 'https://wiert.wordpress.com/'
original domain URL {var a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=''; a.hash=''; a.href; } 'https://wiert.wordpress.com/'
canonical URL on original domain {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.href; } 'https://wiert.wordpress.com/?p=85080'
classic editor URL {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname='wp-admin/post.php'; a.search=`post=${postID}&action=edit&classic-editor`; a.hash=''; a.href; } 'https://wiert.wordpress.com/wp-admin/post.php?post=85080&action=edit&classic-editor'
full post title (including blog title) document.title 'Philosophy of management « The Wiert Corner – irregular stream of stuff'
post title only document.querySelector('meta[property="og:title"]')?.content 'Philosophy of management'
blog title only document.querySelector('meta[name="application-name"]')?.content 'The Wiert Corner - irregular stream of stuff'
anchor HTML to canonical URL on original domain with full post title {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.text=document.title; a; } <a href="https://wiert.wordpress.com/?p=85080">Philosophy of management « The Wiert Corner – irregular stream of stuff</a>
anchor HTML to canonical URL on original domain with full post title {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.target="blank"; a.rel="noopener"; a.text=document.querySelector('meta[property="og:title"]')?.content; a; }
<a href=​"https:​/​/​wiert.wordpress.com/​?p=85080" target=​"blank" rel=​"noopener">​The Wiert Corner - irregular stream of stuff​</a>​
popup with anchor HTML to canonical URL on original domain with full post title {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.target="blank"; a.rel="noopener"; a.text=document.querySelector('meta[property="og:title"]')?.content; prompt("Anchor", a.outerHTML); } A popup titled “wiert.me” with a prompt named “Anchor” where you can copy this HTML from:

<a href="https://wiert.wordpress.com/?p=85080" target="blank" rel="noopener">Philosophy of management</a>

Note that:

  • I did not go the blind way of using regex and string concatenation that you often see: these regularly give a mess and well-tested built-in APIs are far less prone to errors
  • I know HighlanderComments is undocumented ([Wayback/Archive] “HighlanderComments” “WordPress” – Google Search returning no real meaningful results), but it is stable (for why: see below)
  • I tested these in various browsers both while logged on to a WordPress site and in an anonymous browser Windows: this code works for WordPress.com sites!

Note: for non-WordPress.com sites:

  • I verified that the hidden input element with ID comment_post_ID does exist, so that part already works.
  • I need to check out the form element with ID commentform to get to the edit URLs.

When there the post is not yet published, you will get a 404-page like https://wiert.me/?p=138835, but that page does contain this snippet pointing to the canonical domain:

<link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://wiert.wordpress.com/xmlrpc.php?rsd" />

You can obtain the value with document.querySelector('link[rel="EditURI"]').href.

Similarly this snippet is present in the page twice:

<input type="hidden" name="source" value="https://wiert.me/?p=138835"/>

You can get is through document.querySelector('input[name="source"]').value, but also via window.location.href as it is the URL of the 404-page itself.

Going the window.location route has the benefit of being able to use window.location.search to get the parameter which allows the use of [Wayback/Archive] URLSearchParams – Web APIs | MDN to get to the value of the p URL parameter.

This leads to this bit of JavaScript

searchParams = new URLSearchParams(window.location.search); searchParams.get("p");

A bookmarklet that lets me edit a post

The whole goal of writing this post is to figure a fast way to navigate from one of my own posts (for instance after finding it back through Google: the main aim of this blog is to document what I learned in the past) into editing it.

This is the Bookmarklet for it:

javascript:{ var postID = document.getElementsByName("comment_post_ID")[0]?.value; var a = document.createElement("a"); if (postID === undefined) { a.href = document.querySelector('link[rel="EditURI"]').href; var searchParams = new URLSearchParams(window.location.search); postID = searchParams.get("p");} else { a.href=HighlanderComments.connectURL; }; a.pathname='wp-admin/post.php'; a.search=`post=${postID}&action=edit&classic-editor`; a.hash=''; open(a.href); }


javascript:{ var postID = document.getElementsByName("comment_post_ID")[0]?.value; var a = document.createElement("a"); if (postID === undefined) { a.href = document.querySelector('link[rel="EditURI"]').href; var searchParams = new URLSearchParams(window.location.search); postID = searchParams.get("p");} else { a.href=HighlanderComments.connectURL; }; a.pathname='wp-admin/post.php'; a.search=`post=${postID}&action=edit&classic-editor`; a.hash=''; open(a.href); }

view raw

bookmarklet.url

hosted with ❤ by GitHub

A bookmarklet that gives the canonical post anchor

For now I will leave it at getting the canonical post anchor ID in an easy to copy way.

This is the Bookmarklet for it:

javascript:{var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.target="blank"; a.rel="noopener"; a.text=document.querySelector('meta[property="og:title"]')?.content; prompt("Anchor", a.outerHTML); }


javascript:{var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.target="blank"; a.rel="noopener"; a.text=document.querySelector('meta[property="og:title"]')?.content; prompt("Anchor", a.outerHTML); }

view raw

bookmarklet.url

hosted with ❤ by GitHub

More on HighlanderComments

Despite [Wayback/Archive] “HighlanderComments” “WordPress” – Google Search returning no real meaningful results, but [Wayback/Archive] “WordPress” “Highlander” “comments” – Google Search gives a bit more insight.

Highlander Comments is the commenting system for WordPress.com sites and, if I understand the below links correctly, is part of the JetPack under the name Jetpack Comments:

JavaScript and URL building

This I learned from [Wayback/Archive] javascript – Get protocol, domain, and port from URL – Stack Overflow (thanks [Wayback/Archive] David Calhoun for answering and [Wayback/Archive] yelo3 for answering) via the query [Wayback/Archive] javascript get scheme and hostname from url – Google Search:

Method 1: Use the URL API (caveat: no IE11 support)

You can use the URL API (not supported by IE11, but available everywhere else).
This also makes it easy to access search params. Another bonus: it can be used in a Web Worker since it doesn’t depend on the DOM.
const url = new URL('http://example.com:12345/blog/foo/bar?startIndex=1&pageSize=10');

Method 2 (old way): Use the browser’s built-in parser in the DOM

Use this if you need this to work on older browsers as well.
//  Create an anchor element (note: no need to append this element to the document)
const url = document.createElement('a');
//  Set href to any path
url.setAttribute('href', 'http://example.com:12345/blog/foo/bar?startIndex=1&pageSize=10');

That’s it!

The browser’s built-in parser has already done its job. Now you can just grab the parts you need (note that this works for both methods above):
//  Get any piece of the url you're interested in
url.hostname;  //  'example.com'
url.port;      //  12345
url.search;    //  '?startIndex=1&pageSize=10'
url.pathname;  //  '/blog/foo/bar'
url.protocol;  //  'http:'

More details are below in the documentation for Document.createElement and HTMLAnchorelement (as that is what is what document.createElement("a"); returns).

Showing data that can be copied

I am still looking for a solution that pops this up in a new window or tab, but for now this method is OK for me:

  • [Wayback/Archive] Window.prompt() – Web APIs | MDN
    window.prompt() instructs the browser to display a dialog with an optional message prompting the user to input some text, and to wait until the user either submits the text or cancels the dialog.
    Under some conditions — for example, when the user switches tabs — the browser may not actually display a dialog, or may not wait for the user to submit text or to cancel the dialog.

    Syntax

    result = window.prompt(message, default);

Note that one can prompt without window, but I am not sure why yet.

JavaScript and DOM references

Writing this blog post taught me a few new JavaScript and DOM tricks, so here are the references for that below.

Instead of HTMLAnchorelement.search, I could have used HTMLAnchorelement.searchParams (implemented by URL.searchParams) and the returning URLSearchParams instance. The code would have become slightly better readable, but a lot longer. For completeness, I have included links and abstracts to those two as well.

JavaScript querying of elements

I wrote about this earlier in Bookmarklets for Archive.is and the WayBack Machine to go to the original page, but did not include many details, so here are more:

  • [Wayback/Archive] javascript – How to use querySelector with an anchor tag with href? – Stack Overflow: Wrap the href value in proper quotes.
  • [Wayback/Archive] html – How do I get the information from a meta tag with JavaScript? – Stack Overflow:
    The other answers should probably do the trick, but this one is simpler and does not require jQuery:
    document.head.querySelector("[property~=video][content]").content;
    
    The original question used an RDFa tag with a property="" attribute. For the normal HTML <meta name="" …> tags you could use something like:
    document.querySelector('meta[name="description"]').content
    
  • [Wayback/ArchiveElement.querySelector() – Web APIs | MDN

    The querySelector() method of the Element interface returns the first element that is a descendant of the element on which it is invoked that matches the specified group of selectors.

    In this first example, the first <style> element which either has no type or has type “text/css” in the HTML document body is returned:

    var el = document.body.querySelector("style[type='text/css'], style:not([type])");
  • [Wayback/Archive] Document.querySelector() – Web APIs | MDN
    The Document method querySelector() returns the first Element within the document that matches the specified selector, or group of selectors. If no matches are found, null is returned.
    Note: The matching is done using depth-first pre-order traversal of the document’s nodes starting with the first element in the document’s markup and iterating through sequential nodes by order of the number of child nodes.
  • [Wayback/ArchiveDocument.querySelectorAll() – Web APIs | MDN

    The Document method querySelectorAll() returns a static (not live) NodeList representing a list of the document’s elements that match the specified group of selectors.

    Here, an attribute selector is used to return a list of the list items contained within a list whose ID is userlist which have a data-active attribute whose value is 1:

    const container = document.querySelector("#userlist");
    const matches = container.querySelectorAll("li[data-active='1']");
  • [Wayback/ArchiveCSS selectors – CSS: Cascading Style Sheets | MDN

    CSS selectors define the elements to which a set of CSS rules apply.

    • Basic: universal, type, class, ID, attribute
    • Grouping: selector list
    • Combinators: descendant, child, general sibling, adjacent sibling, column
    • Pseudo: pseudo classes, pseudeo elements

JavaScript string building

Getting link rel values

[Wayback/Archive] <link>: The External Resource Link element – HTML: HyperText Markup Language | MDN

[Wayback/Archive] How to get the url from link rel=”next” in with javascript – Stack Overflow (thanks [Wayback/Archive] Jes and [Wayback/Archive] Mohsen):

Q

How to get the url from

<link rel="prev" title="Selected 3" href="http://mydomain.com/2.html" />

in the head using pure javascript?

A

IE8+

document.querySelector('link[rel="prev"]').href;

–jeroen


Code (which broke at 20230914 because of WordPress.com changes: the undocumented HighlanderComments structure got removed; I will update the gist later on and post an updated blog post)

[Wayback/Archive] Revisions · Scripts for “Some JavaScript bookmarklets for WordPress published pages centered around navigation and IDs” https://wiert.me/2023/07/20/some-javascript-bookmarklets-for-wordpress-published-pages-centered-around-navigation-and-ids/


document.getElementsByName("comment_post_ID")[0]?.value
// 85080

view raw

01.post-ID.js

hosted with ❤ by GitHub


// HighlanderComments.homeURL // as of 20230914 this does not work any more as HighlanderComments got removed
// Find this HTML element in stead and take the href:
// <link rel='openid.delegate' href='https://wiert.me/&#39; />
document.querySelector('link[rel="openid.delegate"]').href
// 'https://wiert.me/&#39;


// {var a=document.createElement("a"); a.setAttribute("href", HighlanderComments.connectURL); a.pathname=''; a.search=''; a.hash=''; a.href; } // as of 20230914 this does not work any more as HighlanderComments got removed
// Find the below HTML element in stead, then strip the "xmlrpc.php?rsd" from the end by removing the "pathname" and "search" bits
// <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://wiert.wordpress.com/xmlrpc.php?rsd&quot; />
{var a=document.createElement("a"); a.setAttribute("href", document.querySelector('link[rel="EditURI"]').href); a.pathname=''; a.search=''; a.hash=''; a.href; }
// 'https://wiert.wordpress.com/&#39;


// {var a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=''; a.hash=''; a.href; } // as of 20230914 this does not work any more as HighlanderComments got removed
// Find the below HTML element in stead, then strip the "xmlrpc.php?rsd" from the end by removing the "pathname" and "search" bits
// <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://wiert.wordpress.com/xmlrpc.php?rsd&quot; />
{var a=document.createElement("a"); a.href=document.querySelector('link[rel="EditURI"]').href; a.pathname=''; a.search=''; a.hash=''; a.href; }
// 'https://wiert.wordpress.com/&#39;


// {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.href; } // as of 20230914 this does not work any more as HighlanderComments got removed
// Find the below HTML element in stead, then strip the "xmlrpc.php?rsd" from the end by removing the "pathname" and "search" bits
// <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://wiert.wordpress.com/xmlrpc.php?rsd&quot; />
{var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=document.querySelector('link[rel="EditURI"]').href; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.href; }
// 'https://wiert.wordpress.com/?p=85080&#39;


// {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname='wp-admin/post.php'; a.search=`post=${postID}&action=edit&classic-editor`; a.hash=''; a.href; } // as of 20230914 this does not work any more as HighlanderComments got removed
// Find the below HTML element in stead, then strip the "xmlrpc.php?rsd" from the end by removing the "pathname" and "search" bits
// <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://wiert.wordpress.com/xmlrpc.php?rsd&quot; />
{var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=document.querySelector('link[rel="EditURI"]').href; a.pathname='wp-admin/post.php'; a.search=`post=${postID}&action=edit&classic-editor`; a.hash=''; a.href; }
// 'https://wiert.wordpress.com/wp-admin/post.php?post=85080&action=edit&classic-editor&#39;


document.title
// 'Philosophy of management « The Wiert Corner – irregular stream of stuff'


document.querySelector('meta[property="og:title"]')?.content
// 'Philosophy of management'


document.querySelector('meta[name="application-name"]')?.content
// 'The Wiert Corner – irregular stream of stuff'


// {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.text=document.title; a; } // as of 20230914 this does not work any more as HighlanderComments got removed
// Find the below HTML element in stead, then strip the "xmlrpc.php?rsd" from the end by removing the "pathname" and "search" bits
// <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://wiert.wordpress.com/xmlrpc.php?rsd&quot; />
{var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=document.querySelector('link[rel="EditURI"]').href; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.text=document.title; a; }
// <a href="https://wiert.wordpress.com/?p=85080">Philosophy of management « The Wiert Corner – irregular stream of stuff</a>


// {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.target="blank"; a.rel="noopener"; a.text=document.querySelector('meta[property="og:title"]')?.content; a; } // as of 20230914 this does not work any more as HighlanderComments got removed
// Find the below HTML element in stead, then strip the "xmlrpc.php?rsd" from the end by removing the "pathname" and "search" bits
// <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://wiert.wordpress.com/xmlrpc.php?rsd&quot; />
{var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=document.querySelector('link[rel="EditURI"]').href; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.target="blank"; a.rel="noopener"; a.text=document.querySelector('meta[property="og:title"]')?.content; a; }
// <a href="https://wiert.wordpress.com/?p=85080&quot; target="blank" rel="noopener">The Wiert Corner – irregular stream of stuff</a>


// {var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=HighlanderComments.connectURL; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.target="blank"; a.rel="noopener"; a.text=document.querySelector('meta[property="og:title"]')?.content; prompt("Anchor", a.outerHTML); } // as of 20230914 this does not work any more as HighlanderComments got removed
// Find the below HTML element in stead, then strip the "xmlrpc.php?rsd" from the end by removing the "pathname" and "search" bits
// <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://wiert.wordpress.com/xmlrpc.php?rsd&quot; />
{var postID=document.getElementsByName("comment_post_ID")[0]?.value; a=document.createElement("a"); a.href=document.querySelector('link[rel="EditURI"]').href; a.pathname=''; a.search=`?p=${postID}`; a.hash=''; a.target="blank"; a.rel="noopener"; a.text=document.querySelector('meta[property="og:title"]')?.content; prompt("Anchor", a.outerHTML); }
// A popup titled “wiert.me” with a prompt named “Anchor” where you can copy this HTML from:
// <a href="https://wiert.wordpress.com/?p=85080&quot; target="blank" rel="noopener">Philosophy of management</a>

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.