Share what you are working on and using!

I have no fancy code to share yet, but the next item on my list to work on is to style my page according to how I want it in terms of link colors, fonts and page layout. I’m sure I’ll reach out to this wonderful community along the way. Looking forward to seeing helpful tips others have used.

1 Like

Looking forward to seeing the final result @digorsink! If you haven’t seen it already, I’d recommend checking out the Write.as Themes blog. It showcases a host of themes from the Write.as community that you can use for inspiration.

Okay so this one isn’t really a JavaScript or CSS trick, but is more of using what’s available to solve a problem. I wanted to be able to write a post with spoilers, but somehow hide the spoiler, so it’s not plain for everyone to see. I wanted readers to intentionally do something to view the spoiler. I found that with write.as’ anonymous post feature, you can hide spoilers as anonymous post. You can then make them available via links in a post. So a reader can read the post, know that there is a spoiler, but not see the spoiler, unless they specifically click the link to the spoiler.

2 Likes

Sharing in case it might be helpful to someone new.

3 Likes

I saw that on the RWa feed and was meaning to post it here. Thanks for sharing this @dino! Do you have the code available publicly anywhere? I’d be curious to see it as someone who hasn’t used .NET but would be interested in learning more of it!

Are you talking about the code for the building the list for a static Archive page app? If so, I have it on my local box. I haven’t uploaded it to Github yet because right now, it’s just a mess. I was just trying to get it to work and didn’t really think about making it useful for somebody else. I’ll try to clean up the code soon and put it up on Github.

I actually plan to write a very barebones .NET Write.as API wrapper library, similar to what you did using Python. But my goal is to expose just the “get” methods for a public blog. Those get methods are all I really need to redo the Glitch apps into Blazor WebAssembly apps.

Now that sounds great! I am really looking forward to seeing even aa barebones version of the library. Let us know if you need any help with working with the Write.as API along the way! I’d be glad to help.

Yeah I’ll definitely reach out if I need some help and guidance with it.

@cjeller1592 do you guys have a test blog that I can point to for testing? Something meant specifically for testing that has a few posts on it. I didn’t want to spam your web service with calls to get all posts from my blog every time I test something.

Web Monetized exclusive content on Write.as! Web Monetization

1 Like

I wanted to share something @blake implemented on his blog that excited me the moment I saw it…

DYNAMIC TABLE OF CONTENTS ON BLOG POSTS!

He adds Custom JavaScript that looks for (sub)headers that creates a table of contents. It’s a sticky toc that follows the reader wherever they go and allows them to go to each section by clicking on the link in the toc.

Really great stuff and would love to show the JavaScript if that’s okay @blake!

3 Likes

That is pretty cool!

2 Likes

Ahh! SO cool that you saw that and thought to share it here! Thanks so much @cjeller1592!

My code’s a little bit spaghetti-ish and might be a little buggy! I’m 100% sure someone here could find a much cleaner solution! I wrote it so people using my tutorials/class could jump to the parts they need or go back to where they left off.

One more heads up before I put the code and explain it: you need to add <div id="toc"></div> to posts where you want the table of contents to appear. I also recommend putting this element after the fold so that the script doesn’t generate a TOC for your home page. Again, I’m sure there’s a cleaner solution!

The code is:

CSS

#post-body {
    max-width: 40rem;
}

body#post article ul, body#post article ul ul, body#post article li {
    margin: 0;
}

#post nav a:not(.home), header nav a {
    margin: 0;
}


#post nav a:not(.home):not(.sub-nav), header nav a {
    margin: 0 0 0 1em;
}

@media only screen and (min-width: 60rem) {
    #post .tutorial {
        max-width: 60rem;
    }
    
    #article-container {
        display: flex;
        justify-content: space-between;
    }
    
    #table-of-contents, #spacer {
        min-width: 18rem;
        max-width: 18rem;
    }
    
    .sticky {
      position: fixed;
      top: 10px;
      width: 100%;
    }
}

JavaScript

var toc = document.createElement("nav");

if (document.getElementById("toc")) {
    window.onscroll = function() {onScroll()};
    document.getElementsByTagName("article")[0].classList.add("tutorial");
    
    var body = document.getElementsByClassName("e-content")[0];
    body.id = "article-container";
    
    var article = document.createElement("div");
    article.innerHTML = body.innerHTML;
    document.getElementById("post-body").id = "";
    article.id = "post-body";
    article.classList = body.classList;
    
    var contents = document.getElementById("toc");
    toc.id = "table-of-contents";
    toc.innerHTML = "<h3>Contents</h3>";
    
    body.innerHTML = "";
    body.appendChild(toc);
    body.appendChild(article);
    
    document.getElementById("toc").remove();
    makeTableOfContents();
}

function makeTableOfContents() {
    var headers = Array.from(document.querySelectorAll("h1,h2,h3,h4,h5,h6"));    
    var currentLevel = 3;
    
    var lists = [];
    var rootList = document.createElement("ul");
    lists.push(rootList);
    var currentList = 0;
    toc.appendChild(rootList);
    
    for (var i = 3; i < headers.length; i++) {
        var level = headers[i].tagName.charAt(1);
        if (level > currentLevel) {
            var list = document.createElement("ul");
            lists.push(list);
            lists[currentList].appendChild(list);
            currentList = lists.length - 1;
            currentLevel = level;
        }
        else if (level < currentLevel) {
            currentList -= 1;
            currentLevel = level;
        }
        var listItem = document.createElement("li");
        listItem.innerHTML = "<a class=\"sub-nav\" href=\"#" + headers[i].id + "\">"  + headers[i].innerHTML + "</a>";
        lists[currentList].appendChild(listItem);
    }
}

var sticky = 150;

function onScroll() {
  if (document.documentElement.scrollTop >= sticky) {
    if (document.getElementById("spacer") === null) {
        toc.classList.add("sticky");
        var body = document.getElementsByClassName("e-content")[0];
        var spacer = document.createElement("div");
        spacer.id = "spacer";
        body.insertBefore(spacer, document.getElementById("post-body"));
    }
  } else if (document.getElementById("spacer") !== null) {
    toc.classList.remove("sticky");
    document.getElementById("spacer").remove();
  }
}

The general approach is:

Making the table of contents

  1. Make the original article element essentially a container for both the table of contents and a new div, which I fill with the article element’s contents (the post itself). I then empty the original article element and fill it with both the table of contents element and the new div.
  2. Fill the table of contents element. Start by creating a root list ul element and add it to the list of ul elements. Then, iterate through every header element. (I think there could be a recursive solution here instead?) (I start at h3 elements and only care about the headers starting at the third one to avoid getting the blog name, the post title, and the “Contents” header.) For each header, if the header level (like h3, h4, etc.) is greater than the current level, so if this is a subheader of the previous header, create a new ul and add it to the list. Then add the new header link li that links to the associated header id (only possible because Write.as headers come with their own ids! Perfect!) to the current ul. If the new header level is less, so this is a larger header than the last, just go to the previous ul in the list and add this new header link to that one. If it’s the same, just add it to the current ul.

Making the table of contents sticky
edit: whoops, I didn’t know about this – https://davidwalsh.name/detect-sticky

  1. Bind the scroll event to a function called onScroll, so the onScroll method will be called whenever the user scrolls.
  2. In your onScroll function, if the current scroll position is lower on the page than your table of contents, add the sticky CSS class to anchor it to the top of the page. But because the sticky class anchors the TOC to the top of the page, you need a spacer element to fill its position in the article; otherwise the post contents would shift to center in the whole 60rem (when it’s supposed to stay shifted to the right). So create a new spacer element with the CSS id spacer (associated with a width of 18rem, allowing up to 2rem of space between.) and put it before the new post div. If the user scrolls back up, just undo that.

Design

  1. Make CSS that adjusts the page so that the TOC + content takes 60rem instead of the usual 40 to accommodate a TOC. Make sure the post header covers the whole 60rem. Ensure that the sticky element keeps the same width as the TOC so that the transition to the TOC being positioned fixed is relatively seamless. On mobile, keep the TOC in place for now. Style the lists and list elements to look more natural as a table of contents (remove/adjust margins).

Really hope this is helpful for someone! Please let me know if you have a nicer solution! I’m happy to answer any questions y’all might have about the code.

Thanks again @cjeller1592! Was really cool to see that you liked it :smile:

1 Like

Here is how to update a mailto link and add the title of the post as the subject.

First you need a mailto link of course:
<a id="mailtolink" href="mailto:youremail@mail.com">Send email</a>

Then this is the JavaScript that you can add to your Custom Javascript:

/* Add Subject to Mailto Link */
if (document.getElementById("mailtolink")) {
    var title = document.getElementById("title").innerHTML;
    if (title) {
        var newHref = "mailto:youremail@mail.com?subject=" + title;
        document.getElementById("mailtolink").setAttribute("href", newHref);
    }
}

I just realized after writing this, that I don’t need to type in the email address again when setting the newHref value. I can use use the existing. Anyway, you get the idea.

3 Likes

To change the image that shows up in the “card” when you share a link to your post, you can hide an image in your post, say by using the Post Signature feature. You can add something like the html tag below:

<img src="yourImage.jpg" width="250" height="250" style="display: none;">

What that does is it will change the content for the og:image meta property on your post. At the same time, since the style is set to display: none;, the image won’t show up on your post. This is useful for those posts that don’t have an image in the first place, but you want a specific image to show up when sharing links to your site.

2 Likes

Upon further testing of the “card” image trick I’ve shared above, I’ve found that you don’t even need the width and height attributes at all. It is best to resize the image to something small, like say 256x256. Then you can just point to that image without having to specify the width and height attributes.

<img src="yourImage.jpg" style="display: none;">

2 Likes

This forum won’t let me add more replies to the Share what you are working on and using! thread, so you guys get a new post.

I’ve been thinking of ways to add a “Featured Post” feature on my sites. This is the easiest idea to implement. Using the Javascript for providing a link to a Random post, you can use the same approach to adding a Featured Post link to your site. You control what post to feature by simply changing the link in your custom Javascript. It will look something like this:

image

First create a placeholder post and pin it on your homepage. I created a post titled “:notes: Featured Song :notes:”. Then here is the custom Javascript that I use on my site:

/* Featured Song Link */
var a = document.querySelector('a[href="https://write.as/now-listening-to/featured-song"]');
if (a) {
  a.setAttribute('href', 'https://nowlisteningto.dinobansigan.com/hate-me-sometimes');
  a.setAttribute('title', 'Featured song for this month');
}
var b = document.querySelector('a[href="/now-listening-to/featured-song"]');
if (b) {
  b.setAttribute('href', 'https://nowlisteningto.dinobansigan.com/hate-me-sometimes');
  b.setAttribute('title', 'Featured song for this month');
}
var c = document.querySelector('a[href="https://nowlisteningto.dinobansigan.com/featured-song"]');
if (c) {
  c.setAttribute('href', 'https://nowlisteningto.dinobansigan.com/hate-me-sometimes');
  c.setAttribute('title', 'Featured song for this month');
}

Just remember to change the link to something else every month or every week, or however often you want to.

1 Like

This is awesome @dino! I think having a “Featured Post” is great for first time readers.

I was first confused why there was an addition variable, but I see that you’re also setting the title attribute too, so that the song will show up as “Featured song for this month.” Didn’t even think of changing the title attribute of a post — thanks for sharing that!

PS: I made it so that your post shows up on this topic — don’t know why you couldn’t contribute to it. Maybe the forum software thought it was spam?

2 Likes

Thanks @cjeller1592. Yeah it was saying that I can’t post anymore since I already had 3 posts in a row :slight_smile:

In preparation of coming out of my 2nd digital declutter, I’ve been trying to find ways to optimize how I use my music blog. One of the things I want to do is to share my post to my friends who are on FB. Since write.as doesn’t have a cross post option to FB, I do this manually. This means opening FB on my browser, creating a new FB post with a link to my blog post. I want to find ways to make this even quicker, possibly with me not even having to open up FB.

What I’ve come up with here, is a way to add an FB share button at the bottom of my posts. This button when clicked, will open up a new tab where all I have to do, is click the Post button and it will automatically share my blog post to FB. And after I click the Post button, it also automatically closes the new tab, which means I don’t even end up on FB after. This share button only shows up when I’m logged in, which means other readers won’t see it. This is perfect for me since I can quickly hit the share button after publishing a new post.

Here is the custom Javascript I am using:

/* Show FB Share Button only when logged-in to write.as */
var currentURL = window.location.href;
var isLoggedInToWA = currentURL.indexOf("https://write.as/now-listening-to/") != -1;
if (isLoggedInToWA && document.getElementById("post-body")) {
    var shareUrl = currentURL.replace("write.as/now-listening-to", "nowlisteningto.dinobansigan.com");
    var shareText = '<iframe src="https://www.facebook.com/plugins/share_button.php?href=URLTOSHARE&layout=button&size=small&width=68&height=20&appId" width="68" height="20" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true" allow="encrypted-media"></iframe>';
    shareText = shareText.replace("URLTOSHARE", shareUrl);
    document.getElementsByTagName("article")[0].insertAdjacentHTML('beforeend', shareText);
}

You can replace the urls above to make it work on your site. Also, if you remove the script that checks for isLoggedInToWA, then you will have enabled the FB share button on all your posts, and your readers can click it and instantly share to FB.

Here is what it looks like at the bottom of a post on my music blog: