Skip to content

Commit b39389d

Browse files
committed
Simplify bookmarklet copy: single button extracts from href
Replace the visible code block with a single "Copy Bookmarklet Code" button. The button now extracts the code directly from the bookmarklet link's href attribute, ensuring the copied code is always in sync with the draggable link.
1 parent 7499bf9 commit b39389d

1 file changed

Lines changed: 24 additions & 16 deletions

File tree

lobsters-bookmarklet.html

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,9 @@ <h3>Chrome / Firefox / Desktop Safari</h3>
161161
<div class="instructions">
162162
<h3>Mobile Safari (iPhone/iPad)</h3>
163163
<ol>
164-
<li><strong>Copy the bookmarklet code</strong> below (tap and hold, then "Select All" and "Copy"):</li>
164+
<li><strong>Copy the bookmarklet code</strong> using the button below:</li>
165165
</ol>
166-
<div class="code-block" id="bookmarklet-code">javascript:(function(){if(document.querySelector('#comment-view-tabs'))return;const commentsLabel=document.querySelector('.comments_label');const commentsContainer=document.querySelector('ol.comments');if(!commentsLabel||!commentsContainer){alert('This bookmarklet only works on Lobste.rs comment pages');return}const originalCommentsHTML=commentsContainer.innerHTML;function getAuthor(element){const links=element.querySelectorAll('a[href^="/~"]');for(const link of links){const text=link.textContent?.trim();if(text)return text}return null}function extractComments(){const comments=[];document.querySelectorAll('.comments_subtree').forEach(subtree=>{const comment=subtree.querySelector(':scope > .comment[id^="c_"]');if(!comment)return;const timeEl=comment.querySelector('time');const parentSubtree=subtree.parentElement?.closest('.comments_subtree');const parentComment=parentSubtree?.querySelector(':scope > .comment[id^="c_"]');comments.push({id:comment.id,element:comment.cloneNode(true),author:getAuthor(comment),timestamp:parseInt(timeEl?.getAttribute('data-at-unix')||'0'),parentId:parentComment?.id||null,parentAuthor:parentComment?getAuthor(parentComment):null})});return comments}const tabsContainer=document.createElement('div');tabsContainer.id='comment-view-tabs';tabsContainer.innerHTML=`<style>#comment-view-tabs{margin:10px 0}#comment-view-tabs .tab-buttons{display:flex;gap:0}#comment-view-tabs .tab-btn{padding:8px 16px;border:1px solid #ac0000;background:white;cursor:pointer;font-size:14px;color:#ac0000}#comment-view-tabs .tab-btn:first-child{border-radius:4px 0 0 4px}#comment-view-tabs .tab-btn:last-child{border-radius:0 4px 4px 0;border-left:none}#comment-view-tabs .tab-btn.active{background:#ac0000;color:white}#comment-view-tabs .tab-btn:hover:not(.active){background:#f0f0f0}.flat-comment{margin:0 0 15px 0!important;padding:10px!important;border-left:3px solid #ddd!important}.reply-to-link{font-size:12px;color:#666;margin-left:10px}.reply-to-link a{color:#ac0000;text-decoration:none}.reply-to-link a:hover{text-decoration:underline}</style><div class="tab-buttons"><button class="tab-btn active" data-view="default">Default</button><button class="tab-btn" data-view="latest">Latest</button></div>`;const byline=commentsLabel.closest('.byline');byline.parentNode.insertBefore(tabsContainer,byline.nextSibling);function switchToDefault(scrollToId){document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));document.querySelector('.tab-btn[data-view="default"]').classList.add('active');commentsContainer.innerHTML=originalCommentsHTML;if(scrollToId){setTimeout(()=>{const el=document.getElementById(scrollToId);if(el){el.scrollIntoView({behavior:'smooth',block:'center'});el.style.transition='background 0.3s';el.style.background='#ffffd0';setTimeout(()=>el.style.background='',2000)}},100)}}function buildFlatView(){const comments=extractComments();comments.sort((a,b)=>b.timestamp-a.timestamp);const flatContainer=document.createElement('div');comments.forEach(c=>{const wrapper=document.createElement('div');wrapper.className='flat-comment-wrapper';const commentEl=c.element;commentEl.classList.add('flat-comment');commentEl.style.marginLeft='0';if(c.parentId&&c.parentAuthor){const byline=commentEl.querySelector('.byline');if(byline){const replySpan=document.createElement('span');replySpan.className='reply-to-link';replySpan.innerHTML=` ↩ reply to <a href="#${c.parentId}">@${c.parentAuthor}</a>`;byline.appendChild(replySpan)}}const timeLink=commentEl.querySelector('a[href^="/c/"]');if(timeLink){const commentId=c.id;timeLink.addEventListener('click',function(e){e.preventDefault();switchToDefault(commentId)})}wrapper.appendChild(commentEl);flatContainer.appendChild(wrapper)});return flatContainer}let flatViewCache=null;const tabButtons=tabsContainer.querySelectorAll('.tab-btn');tabButtons.forEach(btn=>{btn.addEventListener('click',()=>{tabButtons.forEach(b=>b.classList.remove('active'));btn.classList.add('active');const view=btn.dataset.view;if(view==='default'){commentsContainer.innerHTML=originalCommentsHTML}else if(view==='latest'){if(!flatViewCache){flatViewCache=buildFlatView()}commentsContainer.innerHTML='';commentsContainer.appendChild(flatViewCache.cloneNode(true));commentsContainer.querySelectorAll('a[href^="/c/"]').forEach(link=>{const wrapper=link.closest('.flat-comment-wrapper');const commentEl=wrapper?.querySelector('.comment');const commentId=commentEl?.id;if(commentId){link.addEventListener('click',function(e){e.preventDefault();switchToDefault(commentId)})}})}})})})()</div>
166+
<button id="copy-bookmarklet-btn" style="display:block;margin:10px 0;padding:12px 24px;background:#ac0000;color:white;border:none;border-radius:4px;cursor:pointer;font-size:14px;font-weight:bold;">Copy Bookmarklet Code</button>
167167
<ol start="2">
168168
<li><strong>Create a new bookmark:</strong>
169169
<ul>
@@ -400,20 +400,28 @@ <h2>Source Code</h2>
400400
</footer>
401401

402402
<script>
403-
// Add copy button for mobile
404-
const codeBlock = document.getElementById('bookmarklet-code');
405-
if (navigator.clipboard) {
406-
const copyBtn = document.createElement('button');
407-
copyBtn.textContent = 'Copy to Clipboard';
408-
copyBtn.style.cssText = 'display:block;margin:10px 0;padding:8px 16px;background:#ac0000;color:white;border:none;border-radius:4px;cursor:pointer;';
409-
copyBtn.onclick = () => {
410-
navigator.clipboard.writeText(codeBlock.textContent).then(() => {
411-
copyBtn.textContent = 'Copied!';
412-
setTimeout(() => copyBtn.textContent = 'Copy to Clipboard', 2000);
413-
});
414-
};
415-
codeBlock.parentNode.insertBefore(copyBtn, codeBlock.nextSibling);
416-
}
403+
// Copy button extracts code from the bookmarklet link's href
404+
const copyBtn = document.getElementById('copy-bookmarklet-btn');
405+
const bookmarkletLink = document.querySelector('.bookmarklet-link');
406+
407+
copyBtn.onclick = () => {
408+
// Get the href attribute which contains the bookmarklet code
409+
const code = bookmarkletLink.getAttribute('href');
410+
navigator.clipboard.writeText(code).then(() => {
411+
copyBtn.textContent = 'Copied!';
412+
setTimeout(() => copyBtn.textContent = 'Copy Bookmarklet Code', 2000);
413+
}).catch(() => {
414+
// Fallback for older browsers
415+
const textarea = document.createElement('textarea');
416+
textarea.value = code;
417+
document.body.appendChild(textarea);
418+
textarea.select();
419+
document.execCommand('copy');
420+
document.body.removeChild(textarea);
421+
copyBtn.textContent = 'Copied!';
422+
setTimeout(() => copyBtn.textContent = 'Copy Bookmarklet Code', 2000);
423+
});
424+
};
417425
</script>
418426
</body>
419427
</html>

0 commit comments

Comments
 (0)