<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Abidemi Kusimo &#8211; Blanla</title>
	<atom:link href="https://blanla.com/author/asufutimaehaehfutbw_f5b7f6/feed/" rel="self" type="application/rss+xml" />
	<link>https://blanla.com</link>
	<description>A web developer&#039;s journey</description>
	<lastBuildDate>Mon, 10 Feb 2025 22:49:59 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>How I Installed MSSQL Server on macOS Using Docker</title>
		<link>https://blanla.com/how-i-installed-mssql-server-on-macos-using-docker/</link>
		
		<dc:creator><![CDATA[Abidemi Kusimo]]></dc:creator>
		<pubDate>Tue, 28 Jan 2025 15:27:00 +0000</pubDate>
				<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">https://blanla.com/?p=466</guid>

					<description><![CDATA[This is how I installed and set up Microsoft SQL Server on my Mac using Docker. In this guide, I&#8217;ll walk you through the steps I followed to get MSSQL up and running, including how I backed up and restored a sample database. This assumes that you already have Docker installed on your Mac. If &#8230; <div class="article-more-link"><a href="https://blanla.com/how-i-installed-mssql-server-on-macos-using-docker/" class="read-more" aria-label="Read How I Installed MSSQL Server on macOS Using Docker">Continue reading</a></div><div class="clearfix"></div>]]></description>
										<content:encoded><![CDATA[
<p>This is how I installed and set up <strong>Microsoft SQL Server</strong> on my Mac using <strong>Docker</strong>. In this guide, I&#8217;ll walk you through the steps I followed to get MSSQL up and running, including how I backed up and restored a sample database. This assumes that you already have <strong>Docker</strong> installed on your Mac.</p>



<p>If Docker is not already running, launch the Docker application on your system. Once it is up and running, open the command line to proceed.</p>



<h2 class="wp-block-heading"><strong>Part 1: Installing and Running MSSQL Server</strong></h2>



<h3 class="wp-block-heading"><strong>Step 1: Pull the MSSQL Server Docker Image</strong></h3>



<p>Run the following command to download the latest MSSQL Server 2022 Docker image:</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="285" src="https://blanla.com/wp-content/uploads/2025/01/Docker-Pull-Command-Execution-1024x285.png" alt="" class="wp-image-478" srcset="https://blanla.com/wp-content/uploads/2025/01/Docker-Pull-Command-Execution-1024x285.png 1024w, https://blanla.com/wp-content/uploads/2025/01/Docker-Pull-Command-Execution-300x83.png 300w, https://blanla.com/wp-content/uploads/2025/01/Docker-Pull-Command-Execution-768x214.png 768w, https://blanla.com/wp-content/uploads/2025/01/Docker-Pull-Command-Execution.png 1053w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Docker Pull Command Execution</figcaption></figure>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
docker pull mcr.microsoft.com/mssql/server:2022-latest
</pre></div>


<h3 class="wp-block-heading"><strong>Step 2: Run the MSSQL Server Container</strong></h3>



<p>Run the following command to start the MSSQL container. Replace the placeholder&nbsp;&#8216;<code><em>YourPasswordHere</em></code>&#8216;&nbsp;with a strong password for the&nbsp;<code>sa</code>&nbsp;(system administrator) account:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
docker run -e &quot;ACCEPT_EULA=Y&quot; -e &quot;MSSQL_SA_PASSWORD=YourPasswordHere&quot; \
   -p 1433:1433 --name sql1 --hostname sql1 \
   -d \
   mcr.microsoft.com/mssql/server:2022-latest
</pre></div>


<p>Note: Replace <code>YourPasswordHere</code> with a strong password.</p>



<ul class="wp-block-list">
<li><code>ACCEPT_EULA=Y</code>: Accepts the End User License Agreement.</li>



<li><code>MSSQL_SA_PASSWORD</code>: Sets the password for the&nbsp;<code>sa</code>&nbsp;account.</li>



<li><code>-p 1433:1433</code>: Maps port 1433 on your Mac to port 1433 in the container.</li>



<li><code>--name sql1</code>: Names the container&nbsp;<code>sql1</code>.</li>



<li><code>-d</code>: Runs the container in detached mode.</li>
</ul>



<h3 class="wp-block-heading"><strong>Step 3: Change SA Password (Optional But Recommended)</strong></h3>



<p>To change the&nbsp;SA&nbsp;password, use the following command:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
docker exec -it sql1 /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa \
 -P &quot;$(read -sp &quot;Enter current SA password: &quot;; echo &quot;${REPLY}&quot;)&quot; \
 -Q &quot;ALTER LOGIN sa WITH PASSWORD='$(read -sp &quot;Enter new SA password: &quot;; echo &quot;${REPLY}&quot;)'&quot;
</pre></div>


<h3 class="wp-block-heading"><strong>Step 4: Connect to the SQL Server</strong></h3>



<p>Start an interactive bash shell inside the running container:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="285" src="https://blanla.com/wp-content/uploads/2025/01/Connecting-Container-via-Bash-1024x285.png" alt="" class="wp-image-475" srcset="https://blanla.com/wp-content/uploads/2025/01/Connecting-Container-via-Bash-1024x285.png 1024w, https://blanla.com/wp-content/uploads/2025/01/Connecting-Container-via-Bash-300x83.png 300w, https://blanla.com/wp-content/uploads/2025/01/Connecting-Container-via-Bash-768x214.png 768w, https://blanla.com/wp-content/uploads/2025/01/Connecting-Container-via-Bash.png 1053w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Connecting to the Container via Bash</figcaption></figure>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
docker exec -it sql1 &quot;bash&quot;
</pre></div>


<p>Once inside the container, connect to the SQL Server using&nbsp;<code><strong>sqlcmd</strong></code>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P &quot;YourPasswordHere&quot;
</pre></div>


<p>Note: Replace <code>YourPasswordHere</code> with your password.</p>



<h2 class="wp-block-heading"><strong>Part 2: Troubleshooting Connection Issues</strong></h2>



<h3 class="wp-block-heading"><strong>SSL Certificate Error</strong></h3>



<pre class="wp-block-code"><code>Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : SSL Provider: &#91;error:0A000086:SSL routines::certificate verify failed:self-signed certificate].Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : Client unable to establish connection. For solutions related to encryption errors, see https://go.microsoft.com/fwlink/?linkid=2226722.</code></pre>



<p>If you encounter an SSL certificate error, use the&nbsp;<code><strong>-No</strong></code>&nbsp;option to make encryption optional:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P &quot;YourPasswordHere&quot; -No
</pre></div>


<h3 class="wp-block-heading"><strong>View Error Logs</strong></h3>



<p>To view the SQL Server error logs:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
docker exec -t sql1 cat /var/opt/mssql-tools18/log/errorlog | grep connection
</pre></div>


<h2 class="wp-block-heading"><strong>Part 3: Backing Up a Sample Database</strong></h2>



<h3 class="wp-block-heading"><strong>Step 1: Download a Sample Database</strong></h3>



<p>Download a sample database (e.g.,&nbsp;<code>AdventureWorks2022.bak</code>) from <a href="https://learn.microsoft.com/en-us/sql/samples/adventureworks-install-configure?view=sql-server-ver16&amp;tabs=ssms">Microsoft&#8217;s website</a> and save it to your Downloads folder. </p>



<h3 class="wp-block-heading"><strong>Step 2: Copy the Backup File to the Container</strong></h3>



<p>Ensure the backup directory exists in the container. If not, create it:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
docker exec -it sql1 mkdir -p /var/opt/mssql-tools18/backup
</pre></div>


<p>Copy the&nbsp;<code>.bak</code>&nbsp;file to the container&#8217;s backup directory:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo docker cp /Users/yourname/Downloads/AdventureWorks2022.bak sql1:/var/opt/mssql-tools18/backup
</pre></div>


<p>Replace <code>'yourname'</code> with your macOS username. If you&#8217;re unsure of your username, open the terminal and run the command:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
whoami
</pre></div>


<h2 class="wp-block-heading"><strong>Part 4: Restoring the Sample Database</strong></h2>



<h3 class="wp-block-heading"><strong>Step 1: List the Files in the Backup</strong></h3>



<p>Before restoring, list the files in the backup to identify the logical names of the data and log files:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo docker exec -it sql1 /opt/mssql-tools18/bin/sqlcmd -S localhost \
   -U sa -P 'your_password' \
   -Q 'RESTORE FILELISTONLY FROM DISK = &quot;/var/opt/mssql/backup/AdventureWorks2022.bak&quot;' \
   | tr -s ' ' | cut -d ' ' -f 1-2
</pre></div>


<p>Note the logical names of the&nbsp;<code>Data</code>&nbsp;and&nbsp;<code>Log</code>&nbsp;files.</p>



<h3 class="wp-block-heading"><strong>Step 2: Restore the Database</strong></h3>



<p>Use the following command to restore the database:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
sudo docker exec -it sql1 /opt/mssql-tools18/bin/sqlcmd -S localhost \
   -U sa -P 'your_password' \
   -Q 'RESTORE DATABASE AdventureWorks2022 FROM DISK = &quot;/var/opt/mssql/backup/AdventureWorks2022.bak&quot; WITH MOVE &quot;AdventureWorks2022_Data&quot; TO &quot;/var/opt/mssql/data/AdventureWorks2022.mdf&quot;, MOVE &quot;AdventureWorks2022_Log&quot; TO &quot;/var/opt/mssql/data/AdventureWorks2022.ldf&quot;'
</pre></div>


<p>Make sure to replace the <strong>logical file names</strong> (<code>AdventureWorks2022_Data</code> and <code>AdventureWorks2022_Log</code>) with the ones retrieved in Step 1.</p>



<h3 class="wp-block-heading"><strong>Step 3: Verify the Restoration</strong></h3>



<p>Connect to SQL Server and run the following query:</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="285" src="https://blanla.com/wp-content/uploads/2025/01/show-all-databases-1024x285.png" alt="" class="wp-image-490" srcset="https://blanla.com/wp-content/uploads/2025/01/show-all-databases-1024x285.png 1024w, https://blanla.com/wp-content/uploads/2025/01/show-all-databases-300x83.png 300w, https://blanla.com/wp-content/uploads/2025/01/show-all-databases-768x214.png 768w, https://blanla.com/wp-content/uploads/2025/01/show-all-databases.png 1053w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Show all databases with select statement</figcaption></figure>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
SELECT name FROM sys.databases;
</pre></div>


<p>You should see <code>AdventureWorks</code> in the list of databases.</p>



<h2 class="wp-block-heading"><strong>Part 5: External Connections</strong></h2>



<h3 class="wp-block-heading"><strong>Step 1: Find Your IP Address</strong></h3>



<p>Find your Mac&#8217;s IP address:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="285" src="https://blanla.com/wp-content/uploads/2025/01/Find-Your-IP-Address-1024x285.png" alt="" class="wp-image-481" srcset="https://blanla.com/wp-content/uploads/2025/01/Find-Your-IP-Address-1024x285.png 1024w, https://blanla.com/wp-content/uploads/2025/01/Find-Your-IP-Address-300x83.png 300w, https://blanla.com/wp-content/uploads/2025/01/Find-Your-IP-Address-768x214.png 768w, https://blanla.com/wp-content/uploads/2025/01/Find-Your-IP-Address.png 1053w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption"><strong>Find Your IP Address</strong></figcaption></figure>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
ipconfig getifaddr en0
</pre></div>


<h3 class="wp-block-heading"><strong>Step 2: Connect from an External Client</strong></h3>



<p>Use the IP address to connect to the SQL Server from an external client (e.g., Azure Data Studio):</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="285" src="https://blanla.com/wp-content/uploads/2025/01/Connect-from-an-External-Client-1024x285.png" alt="" class="wp-image-483" srcset="https://blanla.com/wp-content/uploads/2025/01/Connect-from-an-External-Client-1024x285.png 1024w, https://blanla.com/wp-content/uploads/2025/01/Connect-from-an-External-Client-300x83.png 300w, https://blanla.com/wp-content/uploads/2025/01/Connect-from-an-External-Client-768x214.png 768w, https://blanla.com/wp-content/uploads/2025/01/Connect-from-an-External-Client.png 1053w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Replace <code>192.168.X.X</code> with your own IP address and <code>YourPasswordHere</code> with your actual password before running the command.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
sudo sqlcmd -S 192.168.X.X,1433 -No -U sa -P 'YourPasswordHere'
</pre></div>


<h2 class="wp-block-heading"><strong>Troubleshooting</strong></h2>



<h3 class="wp-block-heading"><strong>Connection Issues</strong></h3>



<p>If you encounter an encryption error like:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
Sqlcmd: Error: Microsoft ODBC Driver 18 for SQL Server : SSL Provider: &#x5B;error:0A000086:SSL routines::certificate verify failed:self-signed certificate].
</pre></div>


<p>Use the <code>-No</code> flag to disable encryption:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
sqlcmd -S localhost -U sa -P &quot;YourPasswordHere&quot; -No
</pre></div>


<h3 class="wp-block-heading"><strong>Checking Logs for Errors</strong></h3>



<p>If you experience issues, check the error logs using:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
docker exec -it sql1 cat /var/opt/mssql/log/errorlog | grep connection
</pre></div>


<h2 class="wp-block-heading"><strong>Part 6: Installing Azure Data Studio and Connecting to SQL Server</strong></h2>



<h3 class="wp-block-heading"><strong>Step 1: Download and Install Azure Data Studio</strong></h3>



<ol start="1" class="wp-block-list">
<li>Go to the&nbsp;<a href="https://learn.microsoft.com/en-us/sql/azure-data-studio/download-azure-data-studio" target="_blank" rel="noreferrer noopener">Azure Data Studio download page</a>.</li>



<li>Download the macOS version.</li>



<li>Open the downloaded&nbsp;<code>.zip</code>&nbsp;file and drag the Azure Data Studio app to your&nbsp;<code>Applications</code>&nbsp;folder.</li>
</ol>



<h3 class="wp-block-heading"><strong>Step 2: Launch Azure Data Studio</strong></h3>



<ol start="1" class="wp-block-list">
<li>Open Azure Data Studio from your&nbsp;<code>Applications</code>&nbsp;folder.</li>



<li>Follow the setup wizard to complete the installation.</li>
</ol>



<h3 class="wp-block-heading"><strong>Step 3: Connect to Your SQL Server</strong></h3>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="996" height="1024" src="https://blanla.com/wp-content/uploads/2025/01/connect-to-Azure-Data-Studio-996x1024.png" alt="" class="wp-image-493" style="width:385px;height:auto" srcset="https://blanla.com/wp-content/uploads/2025/01/connect-to-Azure-Data-Studio-996x1024.png 996w, https://blanla.com/wp-content/uploads/2025/01/connect-to-Azure-Data-Studio-292x300.png 292w, https://blanla.com/wp-content/uploads/2025/01/connect-to-Azure-Data-Studio-768x790.png 768w, https://blanla.com/wp-content/uploads/2025/01/connect-to-Azure-Data-Studio.png 1000w" sizes="(max-width: 996px) 100vw, 996px" /><figcaption class="wp-element-caption">Azure Studio Connection</figcaption></figure>



<ol start="1" class="wp-block-list">
<li>Open Azure Data Studio.</li>



<li>Click on&nbsp;<strong>New Connection</strong>&nbsp;in the&nbsp;<strong>Servers</strong>&nbsp;sidebar.</li>



<li>Enter the following details:
<ul class="wp-block-list">
<li><strong>Server:</strong>&nbsp;<code>localhost,1433</code></li>



<li><strong>Authentication Type:</strong>&nbsp;SQL Login</li>



<li><strong>User Name:</strong>&nbsp;<code>sa</code></li>



<li><strong>Password:</strong>&nbsp;The password you set for the&nbsp;<code>sa</code>&nbsp;account.</li>
</ul>
</li>



<li>Click&nbsp;<strong>Connect</strong>.</li>
</ol>



<h3 class="wp-block-heading"><strong>Step 4: Verify the Restored Database</strong></h3>



<ol start="1" class="wp-block-list">
<li>In the&nbsp;<strong>Servers</strong>&nbsp;sidebar, expand your SQL Server instance.</li>



<li>Expand the&nbsp;<strong>Databases</strong>&nbsp;folder.</li>



<li>Look for the&nbsp;<code>AdventureWorks2022</code>&nbsp;database (or the name of the database you restored).</li>



<li>Right-click the database and select&nbsp;<strong>New Query</strong>.</li>



<li>Run a simple query to verify the database is working:</li>
</ol>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
USE AdventureWorks2022;
SELECT TOP 10 * FROM SalesLT.Customer;
</pre></div>


<p>If the query returns results, the database is successfully restored and accessible.</p>



<h2 class="wp-block-heading"><strong>Conclusion</strong></h2>



<p>This is the process I used to install <strong>MSSQL Server</strong> on my Mac using Docker. After installing Azure Data Studio, I connected to the SQL Server instance and verified that the <strong>AdventureWorks</strong> database was successfully restored. With this setup, you can develop and test SQL Server applications directly on your Mac.</p>



<h2 class="wp-block-heading"><strong>References</strong></h2>



<p>For more details, check out the following resources:</p>



<ul class="wp-block-list">
<li><a href="https://learn.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-ver16&amp;tabs=cli&amp;pivots=cs1-bash" target="_blank" rel="noreferrer noopener">Install and Connect to SQL Server on Docker (Microsoft)</a></li>



<li><a href="https://learn.microsoft.com/en-us/sql/samples/adventureworks-install-configure?view=sql-server-ver16&amp;tabs=ssms" target="_blank" rel="noreferrer noopener">AdventureWorks Sample Database Installation (Microsoft)</a></li>



<li><a href="https://learn.microsoft.com/en-us/azure-data-studio/tutorial-backup-restore-sql-server" target="_blank" rel="noreferrer noopener">Backup and Restore in Azure Data Studio (Microsoft)</a></li>



<li><a href="https://learn.microsoft.com/en-us/azure-data-studio/quickstart-sql-server" target="_blank" rel="noreferrer noopener">Quickstart Guide for Azure Data Studio (Microsoft)</a></li>



<li><a href="https://setapp.com/how-to/install-sql-server" target="_blank" rel="noreferrer noopener">Installing SQL Server on macOS (Setapp)</a></li>
</ul>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>3 quick ways to fix Unexpected tokens in JSON at position 0 in JavaScript</title>
		<link>https://blanla.com/unexpected-token-in-json-at-position-0-in-javascript/</link>
					<comments>https://blanla.com/unexpected-token-in-json-at-position-0-in-javascript/#respond</comments>
		
		<dc:creator><![CDATA[Abidemi Kusimo]]></dc:creator>
		<pubDate>Sat, 20 May 2023 21:08:52 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://www.blanla.com/?p=178</guid>

					<description><![CDATA[The Unexpected token in JSON at position 0 syntax error occurs when the JSON data is not valid and we try to pass functions like JSON.parse or JSON.stringify to it. We can fix this error by making sure the JSON content is valid. Why an unexpected token in JSON Syntax Error? A common reason why &#8230; <div class="article-more-link"><a href="https://blanla.com/unexpected-token-in-json-at-position-0-in-javascript/" class="read-more" aria-label="Read 3 quick ways to fix Unexpected tokens in JSON at position 0 in JavaScript">Continue reading</a></div><div class="clearfix"></div>]]></description>
										<content:encoded><![CDATA[
<p class="lead">The Unexpected token in JSON at position 0 syntax error occurs when the JSON data is not valid and we try to pass functions like JSON.parse or JSON.stringify to it. We can fix this error by making sure the JSON content is valid.</p>



<h2 class="wp-block-heading">Why an unexpected token in JSON Syntax Error?</h2>



<p>A common reason why the error occurs is that somewhere in our JSON file, we have a typo issue. This causes the JSON file to be invalid (a malformed JSON). The error may occur due to other reasons but the most common are:</p>



<ul class="wp-block-list">
<li>Calling a function on invalid JSON data.</li>



<li>The content contains a typo; This means you probably placed a character where they are not supposed to be.</li>



<li>The Content-Type is not JSON.</li>
</ul>



<h3 class="wp-block-heading">Calling a function on an invalid JSON data</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-medium-font-size">Example of an invalid JSON. A single typo error like the one below will render a JSON file invalid. The last curly braces should be removed from the scope below.</p>
</blockquote>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [5]; title: ; notranslate">
{
  &quot;type&quot;: &quot;image&quot;,
  &quot;extension&quot;: &quot;png&quot;,
  &quot;size&quot;: 1024
}}
</pre></div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-medium-font-size">Passing empty array or empty string to the JSON.parse function. This will result in a syntax error &#8211; Unexpected end of JSON input.</p>
</blockquote>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
console.log(JSON.parse(&#x5B;]));

console.log(JSON.parse(''));
</pre></div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-medium-font-size">JSON strigify function called on invalid JSON data/object will result in an error.</p>
</blockquote>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
const file = {
	&quot;type&quot;: &quot;image&quot;,
	&quot;extension&quot;: &quot;png&quot;,
	&quot;size&quot;: 1024
}}

let result = JSON.strigify(file);
console.log(result);
</pre></div>


<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="700" height="90" src="https://www.blanla.com/wp-content/uploads/2023/05/syntax-error-token.png" alt="Uncaught SyntaxError: Unexpected token" class="wp-image-182" srcset="https://blanla.com/wp-content/uploads/2023/05/syntax-error-token.png 700w, https://blanla.com/wp-content/uploads/2023/05/syntax-error-token-300x39.png 300w" sizes="(max-width: 700px) 100vw, 700px" /><figcaption class="wp-element-caption">Uncaught SyntaxError: Unexpected token</figcaption></figure>



<h3 class="wp-block-heading">The content contains a typo</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-medium-font-size">In the example below the semicolon should be removed.</p>
</blockquote>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; highlight: [4]; title: ; notranslate">
const file = {
	&quot;type&quot;: &quot;image&quot;,
	&quot;extension&quot;: &quot;png&quot;,
	&quot;size&quot;: 1024;
}

let result = JSON.strigify(file);
console.log(result);
</pre></div>


<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="700" height="97" src="https://www.blanla.com/wp-content/uploads/2023/05/syntax-error-semicolon-in-json.png" alt="Uncaught SyntaxError: Unexpected token ';'" class="wp-image-184" srcset="https://blanla.com/wp-content/uploads/2023/05/syntax-error-semicolon-in-json.png 700w, https://blanla.com/wp-content/uploads/2023/05/syntax-error-semicolon-in-json-300x42.png 300w" sizes="(max-width: 700px) 100vw, 700px" /><figcaption class="wp-element-caption">Uncaught SyntaxError: Unexpected token &#8216;;&#8217;</figcaption></figure>



<h2 class="wp-block-heading">Common typo error to look for in JSON</h2>



<ul class="wp-block-list">
<li><strong>Expected comma, got expression</strong>: Check that you have not used a semi-colon instead of a comma to separate JSON attribute and value.</li>



<li><strong>Not enough brackets / Extra brackets</strong>: To control the flow of code into code blocks, we use a subset of characters. Brackets, braces, etc are used to preserve code. Leaving any of these characters unclosed will result in an error.</li>



<li><strong>Remove trailing comma</strong>: Remove a trailing comma on the last line of your JSON file if present.</li>
</ul>



<h3 class="wp-block-heading">The Content-Type is not JSON</h3>



<p>The correct MIME media type for JSON is&nbsp;<code class="note">application/json</code>, you can check this is correct by looking in the header of the response. The file should be served with the right HTTP Content-Type.</p>



<h2 class="wp-block-heading">3 quick ways to fix an unexpected token in JSON Syntax Error</h2>



<h3 class="wp-block-heading">1. Make sure the JSON data is formatted correctly.</h3>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-medium-font-size">You can do this manually by looking at every line of your JSON file for typo errors or you can use an&nbsp;<a rel="noreferrer noopener" href="https://jsonformatter.curiousconcept.com/" target="_blank">online JSON checker</a>. If you are using the visual studio code editor, you can install the a&nbsp;<a rel="noreferrer noopener" href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" target="_blank">JavaScript linter plugin</a>.</p>
</blockquote>



<h3 class="wp-block-heading">2. Error handling through Try and catch block</h3>



<p>Let’s look at example below:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const file = {
    &quot;type&quot;: &quot;image&quot;,
    &quot;extension&quot;: &quot;png&quot;,
    &quot;size&quot;: 1024
}
try {
    let result = JSON.parse(file); // issue: The object should be stringyfy before using JSON.parse on it
    console.log(result);
} catch (err) {
    console.log('error', err);
}
console.log('done'); // This code will still execute even there is error in the code.
</pre></div>


<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="700" height="171" src="https://www.blanla.com/wp-content/uploads/2023/05/object-object-not-valid-json.png" alt="SyntaxError: Object Object is not valid JSON at JSON.parse" class="wp-image-189" srcset="https://blanla.com/wp-content/uploads/2023/05/object-object-not-valid-json.png 700w, https://blanla.com/wp-content/uploads/2023/05/object-object-not-valid-json-300x73.png 300w" sizes="(max-width: 700px) 100vw, 700px" /><figcaption class="wp-element-caption">SyntaxError: Object Object is not valid JSON at JSON.parse</figcaption></figure>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-medium-font-size">To fix the issue above, we need to call the JSON.stringyfy function before JSON.parse.</p>
</blockquote>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const file = {
    &quot;type&quot;: &quot;image&quot;,
    &quot;extension&quot;: &quot;png&quot;,
    &quot;size&quot;: 1024
}

try {
    let result = JSON.stringify(file);
    result = JSON.parse(result);
    console.log(result);
} catch (err) {
    console.log('error', err);
}

console.log('done');
</pre></div>


<h3 class="wp-block-heading">3. Verify that the header Content-Type is in JSON</h3>



<p>This type of error is rare, most of the time you consume JSON data from a server you don’t have control of. It is worth checking if the Content-Type is right.</p>



<p>Let’s assume that we have our own server and we want to set the content type in the header. I will use a PHP server for this example.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
$media_arr = array(
    &quot;type&quot; =&gt; &quot;image&quot;,
    &quot;extension&quot; =&gt; &quot;png&quot;,
    &quot;size&quot; =&gt; 1024
);
header('Content-Type: application/json');
echo json_encode($media_arr);
</pre></div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-medium-font-size">In the example above, our server includes the content header type as JSON.</p>
</blockquote>



<p>To check the Content-Type, open the developer tools and click the Network tab. Click on ‘Fetch/XHR’, then click on the Headers tab, you will see the Content-Type, under the Response Headers section.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="700" height="458" src="https://www.blanla.com/wp-content/uploads/2023/05/inspect-content-header-type.png" alt="Inspect JSON Content-Type in the Chrome Inspector" class="wp-image-190" srcset="https://blanla.com/wp-content/uploads/2023/05/inspect-content-header-type.png 700w, https://blanla.com/wp-content/uploads/2023/05/inspect-content-header-type-300x196.png 300w" sizes="(max-width: 700px) 100vw, 700px" /><figcaption class="wp-element-caption">Inspect JSON Content-Type in the Chrome Inspector</figcaption></figure>
]]></content:encoded>
					
					<wfw:commentRss>https://blanla.com/unexpected-token-in-json-at-position-0-in-javascript/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>2 ways to show and hide elements using HTML and CSS, I prefer the first one</title>
		<link>https://blanla.com/show-hide-element-html-css/</link>
		
		<dc:creator><![CDATA[Abidemi Kusimo]]></dc:creator>
		<pubDate>Thu, 27 Apr 2023 18:58:35 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<guid isPermaLink="false">https://www.blanla.com/?p=98</guid>

					<description><![CDATA[You can show or hide elements on a page in many different ways. We are going to focus on hiding/showing elements&#160;when users interact with them (click). I will show you my preferred method of achieving this using HTML and CSS only, I will also show you another method in which this can be achieved. Use &#8230; <div class="article-more-link"><a href="https://blanla.com/show-hide-element-html-css/" class="read-more" aria-label="Read 2 ways to show and hide elements using HTML and CSS, I prefer the first one">Continue reading</a></div><div class="clearfix"></div>]]></description>
										<content:encoded><![CDATA[
<p>You can show or hide elements on a page in many different ways. We are going to focus on hiding/showing elements&nbsp;when users interact with them (click). I will show you my preferred method of achieving this using HTML and CSS only, I will also show you another method in which this can be achieved.</p>



<h2 class="wp-block-heading">Use the Details and Summary tags</h2>



<p>The details and summary tags act like an accordion element, you click on an element to reveal another element, and clicking again will hide the element that was revealed.&nbsp; This is an example of the details and summary tags:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; gutter: false; title: ; notranslate">
&lt;details&gt;
    &lt;p&gt;This is the hidden content, will only show when the summary is clicked. &lt;/p&gt;
    &lt;summary&gt;Terms and condition&lt;/summary&gt;
&lt;/details&gt;
</pre></div>


<div class="example">
    <details>
        <p>This is the hidden content, will only show when the summary is clicked. </p>
        <summary>Terms and condition</summary>
    </details>
</div>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-medium-font-size">Inside the details element, the summary tag is the only element that is shown by default, everything else is hidden. You can show the content inside details by adding the&nbsp;open&nbsp;property to the details tag.</p>
</blockquote>



<h3 class="wp-block-heading">Change the summary tag default arrow<br></h3>



<p>The summary has a default arrow (see above) which we are able to hide or change. To hide the arrow, we need to add&nbsp;&#8216;none&#8217;&nbsp;as the value to the&nbsp;<code>list-style-type</code>&nbsp;attribute. I will also create space for the custom arrow that we are going to be adding by adding extra CSS attributes.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
details&gt; summary {
    list-style-type: none; /* This removes the default arrow */
    cursor: pointer;
    position: relative;
    margin-left: 24px;
}
</pre></div>


<div class="example example-2" id="example-2">
    <details open="">
        <p>This is the hidden content, will only show when the summary is clicked. </p>
        <summary>Terms and condition</summary>
    </details>
</div>



<p>After we applied the CSS, you will see that the default arrow has been removed, and we have created a space to add our own custom arrow. First, I will use + and &#8211; to indicate the open and closed state, then I will use custom SVG to achieve the same result.</p>



<h3 class="wp-block-heading">Replace the default toggle arrow with a custom element</h3>



<p>The method for replacing the default arrow with a custom one is the same for many HTML elements, for example, select and option tags.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
details&gt; summary:before, details&#x5B;open]&gt; summary:before {
    content: '+';
    position: absolute;
    width: 16px;
    height: 16px;
    left: -21px;
    transition: .2s;
}

details&#x5B;open]&gt; summary:before {
    content: '-';
}
</pre></div>


<div class="example example-3" id="example-3">
    <details open="">
        <p>This is the hidden content, will only show when the summary is clicked. </p>
        <summary>Terms and condition</summary>
    </details>
</div>



<h3 class="wp-block-heading">Replace the arrow with SVG/Image</h3>



<p>We can replace the summary’s arrow with a custom image by adding the image URL to our CSS and removing the + sign in our content attribute as below:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
details&gt; summary:before, details&#x5B;open]&gt; summary:before {
    content: '';
    position: absolute;
    width: 16px;
    height: 16px;
    left: -21px;
    background-image: url(&quot;data:image/svg+xml,%3Csvg width='14' height='9' viewBox='0 0 14 9' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L7 7.5L13 1.5' stroke='%230039A6' stroke-width='2'/%3E%3C/svg%3E%0A&quot;);
    background-repeat: no-repeat;
    background-position: center center;
    transition: .2s;
}

details&#x5B;open]&gt; summary:before {
    transform: rotate(180deg);
}
</pre></div>


<div class="example example-4" id="example-4">
    <details>
        <p>This is the hidden content, will only show when the summary is clicked. </p>
        <summary>Terms and condition</summary>
    </details>
</div>
<style>
#example-2 details> summary, #example-3 details> summary, #example-4 details> summary {
    list-style-type: none;
    cursor: pointer;
    position: relative;
    margin-left: 24px;
}
#example-4 details> summary:before, #example-4 details[open]> summary:before {
    content: '';
    position: absolute;
    width: 16px;
    height: 16px;
    left: -21px;
    top: 5px;
    background-image: url("data:image/svg+xml,%3Csvg width='14' height='9' viewBox='0 0 14 9' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L7 7.5L13 1.5' stroke='%230039A6' stroke-width='2'/%3E%3C/svg%3E%0A");
    background-repeat: no-repeat;
    background-position: center center;
    transition: .2s;
}
</style>



<h2 class="wp-block-heading">Use the hidden checkbox input field to toggle an element</h2>



<p>Another way to toggle elements on a page is by using the input checkbox field to control what is hidden and shown on the page. The checkbox will need to be a direct sibling of the element you want to hide or show. I will explain this with an example.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; title: ; notranslate">
&lt;input type=&quot;checkbox&quot; name=&quot;question&quot;&gt;
&lt;label for=&quot;question&quot;&gt;&lt;div class=&quot;heading&quot;&gt;Click here to toggle&lt;/div&gt;&lt;/label&gt;
&lt;p class=&quot;answer&quot;&gt;Answer here&lt;/p&gt;
</pre></div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-small-font-size">Before adding CSS</p>
</blockquote>



<div id="example-5" class="example">
    <input type="checkbox" id="question-example" name="question-example">
    <label for="question-example">
        <div class="heading">Click here to toggle</div>
    </label>
    <p class="answer">Answer here</p>
</div>



<p>In the example above, we have an input, a label for the input, and a paragraph element. We need to hide the input as clicking on the label will emulate the input click. We also want to hide the paragraph and show it when the label is clicked (input state checked). This can be achieved with the following CSS.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
label&#x5B;for=&quot;question&quot;] {
        cursor: pointer;
    }
    input#question {
        display:none
    }
    input#question ~ p {
        display: none;
    }
    input#question:checked ~ p {
        display: block;
    }
</pre></div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-small-font-size">After adding CSS</p>
</blockquote>



<div id="example-6" class="example">
    <input type="checkbox" id="question" name="question">
    <label for="question">
        <div class="heading">Click here to toggle</div>
    </label>
    <p class="answer">Answer here</p>
</div>



<h2 class="wp-block-heading">Real-life scenario using the toggle method to create a FAQ component</h2>



<p>The above methods of hiding and showing elements on a page are very simple but they can be very useful when working as a front-end web developer, you may need to hide and show elements on click. For example, you may be asked to create a FAQ component. The most common method of achieving this is by using the toggle method; this can be plain HTML/CSS or JavaScript.</p>



<p>The example below used HTML and CSS only to achieve a toggle on FAQ.</p>



<h2 class="wp-block-heading">Example Toggle FAQ Using Checkbox to Hide/Show Element</h2>



<div id="example-7" class="feature-faq">
        <h2 class="section-header__title_text blue-title">
            <span class="heading-title-text">
                FAQ
            </span>
        </h2>
        <div class="faq-element">
            <faq-tab classname="faq-wrapper">
                <input id="faq-title-3" type="checkbox" name="tabs">
                <label for="faq-title-3" class="h4 accordion__title"><span>What is General sibling combinator (<code>~</code>)?</span></label>
                <div class="faq-content">
                    <p>Please check <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator" rel="noopener">MDN Tutorial</a></p>
                </div>
            </faq-tab>
        </div>
        <div class="faq-element">
            <faq-tab classname="faq-wrapper">
                <input id="faq-title-4" type="checkbox" name="tabs">
                <label for="faq-title-4" class="h4 accordion__title"><span>Is Details disclosure element?</span></label>
                <div class="faq-content">
                    <p>The details HTML element creates a disclosure widget in which information is visible only when the widget is toggled into an &#8220;open&#8221; state. 
                        <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details" rel="noopener"> Check MDN for more.</a></p>
                </div>
            </faq-tab>
        </div>
        <div class="faq-element">
            <faq-tab classname="faq-wrapper">
                <input id="faq-title-5" type="checkbox" name="tabs">
                <label for="faq-title-5" class="h4 accordion__title"><span>Can I use JavaScript to toggle element?</span></label>
                <div class="faq-content">
                    <p>Yes.</p>
                </div>
            </faq-tab>
        </div>
</div>

<style>
    .example {
        padding: 2rem 0;
    }
    #example-2 details> summary, #example-3 details> summary, #example-4 details> summary {
        list-style-type: none;
        cursor: pointer;
        position: relative;
        margin-left: 24px;
    }


     #example-3 details> summary:before,  #example-3 details[open]> summary:before {
        content: '+';
        position: absolute;
        width: 16px;
        height: 16px;
        left: -21px;
        transition: .2s;
    }

    #example-3 details[open]> summary:before {
        content: '-';
    }

    #example-4 details> summary:before,  #example-4 details[open]> summary:before {
    content: '';
    position: absolute;
    width: 16px;
    height: 16px;
    left: -21px;
    top: 5px;
    background-image: url("data:image/svg+xml,%3Csvg width='14' height='9' viewBox='0 0 14 9' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1.5L7 7.5L13 1.5' stroke='%230039A6' stroke-width='2'/%3E%3C/svg%3E%0A");
    background-repeat: no-repeat;
    background-position: center center;
    transition: .2s;
    }

    #example-4 details[open]> summary:before {
        transform: rotate(180deg);
    }

    /* CSS for input checkbox */
    #example-6 label[for="question"] {
        cursor: pointer;
    }
    #example-6 input#question {
        display:none
    }
    #example-6 input#question ~ p {
        display: none;
    }
    #example-6 input#question:checked ~ p {
        display: block;
    }

    /* CSS for FAQ */
    #example-7 { padding-bottom: 2rem;}
    #example-7 input {
            position: absolute;
            opacity: 0;
            z-index: -1;
        }

    #example-7 label {
            position: relative;
            display: flex;
            padding: 15px;
            margin-bottom: 5px;
            line-height: normal;
            cursor: pointer;
            border-top: 1px solid #ececec;
        }

    #example-7 .accordion__title span,
    #example-7 .faq-content p {
            margin-left: 32px;
        }

     #example-7 label::before {
            position: absolute;
            content: "+";
            color: #F6AE2D;
            top: 45%;
            transform: translateY(-50%);
            font-size: 28px;
            transition: all .5s;
            padding: 0 5px;
        }

     #example-7 input:checked~label::before {
            content: "-";
        }

        .faq-content {
            max-height: 0;
            overflow: hidden;
            transition: max-height .35s;
        }

        #example-7 input:checked~.faq-content {
            max-height: none;
        }
</style>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-small-font-size">Below is the HTML code for the FAQ</p>
</blockquote>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; gutter: false; title: ; notranslate">
&lt;div class=&quot;feature-faq&quot;&gt;
        &lt;h2 class=&quot;section-header__title_text blue-title&quot;&gt;
            &lt;span class=&quot;heading-title-text&quot;&gt;
                Frequently Asked Question
            &lt;/span&gt;
        &lt;/h2&gt;
        &lt;div class=&quot;faq-element&quot;&gt;
            &lt;faq-tab class=&quot;faq-wrapper&quot;&gt;
                &lt;input id=&quot;faq-title-3&quot; type=&quot;checkbox&quot; name=&quot;tabs&quot;&gt;
                &lt;label for=&quot;faq-title-3&quot; class=&quot;h4 accordion__title&quot;&gt;&lt;span&gt;What is General sibling combinator (&lt;code&gt;~&lt;/code&gt;)?&lt;/span&gt;&lt;/label&gt;
                &lt;div class=&quot;faq-content&quot;&gt;
                    &lt;p&gt;Please check &lt;a target=&quot;_blank&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_combinator&quot;&gt;MDN Tutorial&lt;/a&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/faq-tab&gt;
        &lt;/div&gt;
        &lt;div class=&quot;faq-element&quot;&gt;
            &lt;faq-tab class=&quot;faq-wrapper&quot;&gt;
                &lt;input id=&quot;faq-title-4&quot; type=&quot;checkbox&quot; name=&quot;tabs&quot;&gt;
                &lt;label for=&quot;faq-title-4&quot; class=&quot;h4 accordion__title&quot;&gt;&lt;span&gt;Is Details disclosure element?&lt;/span&gt;&lt;/label&gt;
                &lt;div class=&quot;faq-content&quot;&gt;
                    &lt;p&gt;The details HTML element creates a disclosure widget in which information is visible only when the widget is toggled into an &quot;open&quot; state. 
                        &lt;a target=&quot;_blank&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details&quot;&gt; Check MDN for more.&lt;/a&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/faq-tab&gt;
        &lt;/div&gt;
        &lt;div class=&quot;faq-element&quot;&gt;
            &lt;faq-tab class=&quot;faq-wrapper&quot;&gt;
                &lt;input id=&quot;faq-title-5&quot; type=&quot;checkbox&quot; name=&quot;tabs&quot;&gt;
                &lt;label for=&quot;faq-title-5&quot; class=&quot;h4 accordion__title&quot;&gt;&lt;span&gt;Can I use JavaScript to toggle element?&lt;/span&gt;&lt;/label&gt;
                &lt;div class=&quot;faq-content&quot;&gt;
                    &lt;p&gt;Yes.&lt;/p&gt;
                &lt;/div&gt;
            &lt;/faq-tab&gt;
        &lt;/div&gt;
    &lt;/div&gt;
</pre></div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-small-font-size">Below is the CSS for the FAQ</p>
</blockquote>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
.faq-wrapper input {
            position: absolute;
            opacity: 0;
            z-index: -1;
        }

        .faq-wrapper label {
            position: relative;
            display: block;
            padding: 20px;
            margin-bottom: 5px;
            line-height: normal;
            cursor: pointer;
            border-top: 1px solid #ececec;
            color: #000000;
        }

        .accordion__title span,
        .faq-content p {
            margin-left: 32px;
        }

        .faq-wrapper label::before {
            position: absolute;
            content: &quot;+&quot;;
            color: #F6AE2D;
            top: 50%;
            transform: translateY(-50%);
            font-size: 28px;
            transition: all .5s;
            padding: 0 5px;
        }

        .faq-wrapper input:checked~label::before {
            content: &quot;-&quot;;
        }

        .faq-content {
            max-height: 0;
            overflow: hidden;
            transition: max-height .35s;
        }

        .faq-wrapper input:checked~.faq-content {
            max-height: none;
        }
</pre></div>


<h2 class="wp-block-heading">Example of Using Detail and Summary HTML tags to Hide/Show Element</h2>



<p>Below is the HTML structure for creating FAQ using Detail and Summary Tags.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; gutter: false; title: ; notranslate">
&lt;div class=&quot;feature-faq&quot;&gt;
        &lt;h2 class=&quot;section-header&quot;&gt;
            &lt;span class=&quot;heading-title-text&quot;&gt;
                FAQ
            &lt;/span&gt;
        &lt;/h2&gt;

        &lt;div class=&quot;faqExample-element&quot;&gt;
            &lt;details class=&quot;faqExample-wrapper&quot;&gt;
                &lt;summary class=&quot;h3 faqExample-question-label&quot;&gt;&lt;span&gt;Can I use this tool to add text to an image?&lt;/span&gt;&lt;/summary&gt;
                &lt;div class=&quot;faqExample-content&quot;&gt;
                    &lt;p&gt;Yes, you can use this tool to add text to an image.&lt;/p&gt;
                &lt;/div&gt;
            &lt;/details&gt;
        &lt;/div&gt;

        &lt;div class=&quot;faqExample-element&quot;&gt;
            &lt;details class=&quot;faqExample-wrapper&quot;&gt;
                &lt;summary class=&quot;h3 faqExample-question-label&quot;&gt;&lt;span&gt;How do I create a quote wallpaper?&lt;/span&gt;&lt;/summary&gt;
                &lt;div class=&quot;faqExample-content&quot;&gt;
                    &lt;p&gt;Creating a quote wallpaper is easy! Just follow the step-by-step instructions in our How to Create a Quote Wallpaper section above. &lt;/p&gt;
                &lt;/div&gt;
            &lt;/details&gt;
        &lt;/div&gt;

        &lt;div class=&quot;faqExample-element&quot;&gt;
            &lt;details class=&quot;faqExample-wrapper&quot;&gt;
                &lt;summary class=&quot;h3 faqExample-question-label&quot;&gt;&lt;span&gt;Is the quote wallpaper maker free to use?&lt;/span&gt;&lt;/summary&gt;
                &lt;div class=&quot;faqExample-content&quot;&gt;
                    &lt;p&gt;Yes.&lt;/p&gt;
                &lt;/div&gt;
            &lt;/details&gt;
        &lt;/div&gt;

        &lt;div class=&quot;faqExample-element&quot;&gt;
            &lt;details class=&quot;faqExample-wrapper&quot;&gt;
                &lt;summary class=&quot;h3 faqExample-question-label&quot;&gt;&lt;span&gt;Do I need to create an account to use the tool?&lt;/span&gt;&lt;/summary&gt;
                &lt;div class=&quot;faqExample-content&quot;&gt;
                    &lt;p&gt;No.&lt;/p&gt;
                &lt;/div&gt;
            &lt;/details&gt;
        &lt;/div&gt;
    &lt;/div&gt;
</pre></div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Below is the CSS to be used with the HTML above.</p>
</blockquote>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: css; title: ; notranslate">
    .faqExample-element {
        /* Add styles for each FAQ item container*/
        border-top: 1px solid #ececec; /* Example: Add a border between items */
    }

    .faqExample-wrapper {
        /* Styles for the details element */
    }

    .faqExample-wrapper .faqExample-question-label { 
        position: relative;
        display: block;
        padding: 20px;
        margin-bottom: 5px;
        line-height: normal;
        cursor: pointer;
        color: #000000;
    }

    .faqExample-question-label span, 
    .faqExample-content p {
        margin-left: 32px;
        display: block;
        line-height: 1.5;
    }

    .faqExample-wrapper .faqExample-question-label::before { /* Style for the +/- icon */
        position: absolute;
        content: &quot;+&quot;;
        color: #03726f;
        top: 50%;
        left: 0; /* Adjust position as needed */
        transform: translateY(-50%);
        font-size: 28px;
        transition: all .5s;
        padding: 0 5px;
    }

    details.faqExample-wrapper&#x5B;open] .faqExample-question-label::before { /* When details is open */
        content: &quot;-&quot;!important;
    }


    .faqExample-wrapper details &gt; .faqExample-content {
      padding-bottom: 20px; /* Add some padding to the bottom of the answer*/
    }
</pre></div>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="has-small-font-size">Below is the result for the HTML and CSS</p>
</blockquote>



<div class="feature-faq">
        <h2 class="section-header">
            <span class="heading-title-text">
                This Example Could be Used for FAQ
            </span>
        </h2>

        <div class="faqExample-element">
            <details class="faqExample-wrapper">
                <summary class="h3 faqExample-question-label"><span>Can I use this tool to add text to an image?</span></summary>
                <div class="faqExample-content">
                    <p>Yes, you can use this tool to add text to an image.</p>
                </div>
            </details>
        </div>

        <div class="faqExample-element">
            <details class="faqExample-wrapper">
                <summary class="h3 faqExample-question-label"><span>How do I create a quote wallpaper?</span></summary>
                <div class="faqExample-content">
                    <p>Creating a quote wallpaper is easy! Just follow the step-by-step instructions in our How to Create a Quote Wallpaper section above. </p>
                </div>
            </details>
        </div>

        <div class="faqExample-element">
            <details class="faqExample-wrapper">
                <summary class="h3 faqExample-question-label"><span>Is the quote wallpaper maker free to use?</span></summary>
                <div class="faqExample-content">
                    <p>Yes.</p>
                </div>
            </details>
        </div>

        <div class="faqExample-element">
            <details class="faqExample-wrapper">
                <summary class="h3 faqExample-question-label"><span>Do I need to create an account to use the tool?</span></summary>
                <div class="faqExample-content">
                    <p>No.</p>
                </div>
            </details>
        </div>
    </div>
<style>
.faqExample-element {
        /* Add styles for each FAQ item container*/
        border-top: 1px solid #ececec; /* Example: Add a border between items */
    }

    .faqExample-wrapper {
        /* Styles for the details element */
    }

    .faqExample-wrapper .faqExample-question-label { 
        position: relative;
        display: block;
        padding: 20px;
        margin-bottom: 5px;
        line-height: normal;
        cursor: pointer;
        color: #000000;
    }

    .faqExample-question-label span, 
    .faqExample-content p {
        margin-left: 32px;
        display: block;
        line-height: 1.5;
    }

    .faqExample-wrapper .faqExample-question-label::before { /* Style for the +/- icon */
        position: absolute;
        content: "+";
        color: #03726f;
        top: 50%;
        left: 0; /* Adjust position as needed */
        transform: translateY(-50%);
        font-size: 28px;
        transition: all .5s;
        padding: 0 5px;
    }

    details.faqExample-wrapper[open] .faqExample-question-label::before { /* When details is open */
        content: "-"!important;
    }


    .faqExample-wrapper details > .faqExample-content {
      padding-bottom: 20px; /* Add some padding to the bottom of the answer*/
    }
</style>



<p></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Both the checkbox and <code>details</code>/<code>summary</code> methods are effective for creating interactive content. In my experience, <code>details</code> and <code>summary</code> offer a cleaner, more semantic approach for simple disclosures like FAQs. They eliminate the need for extra HTML elements and CSS rules, making your code easier to read and maintain. Plus, they have built-in accessibility features!</p>
</blockquote>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Roll back Shopify CLI 3 install to Shopify CLI 2</title>
		<link>https://blanla.com/roll-back-shopify-cli-3-install-to-shopify-cli-2/</link>
		
		<dc:creator><![CDATA[Abidemi Kusimo]]></dc:creator>
		<pubDate>Fri, 20 Jan 2023 20:01:21 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<guid isPermaLink="false">https://localhost/blanla/?p=29</guid>

					<description><![CDATA[To roll back to Shopify CLI 2, you first need to uninstall Shopify CLI 3. Before you roll back, here are the things to consider.]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Before you roll back to Shopify CLI 2</h2>



<p>Before you roll back to Shopify CLI 2 if your reason for rolling back is not finding some command lines in version 3.</p>



<p>Below are the differences.</p>



<h3 class="wp-block-heading"><strong>How to log in to a store in CLI3?</strong></h3>



<p>You don’t need to log in, just type a command in your terminal, if you have not already logged in, you will be prompted to do so.</p>



<p>For example, in version 2, if you want to pull a theme from a store, you will do it like this:</p>



<pre class="wp-block-code"><code>shopify login --store the_url_backend_of_the_store</code></pre>



<p>The above command will prompt you to log in; after a successful log-in, then you will run:</p>



<pre class="wp-block-code"><code>shopify theme pull</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>Difference</strong>: You don’t have to be logged in before running the command; just run the&nbsp;<code>shopify theme pull</code>&nbsp;command, and then you will be prompted to log in</p>
</blockquote>



<p><strong>How do I serve a theme in my development environment in CLI 3?</strong></p>



<p>The way of doing this in version 2.0 is to run the command below:</p>



<pre class="wp-block-code"><code>shopify theme serve</code></pre>



<p>In CLI version 3, use the command line below:</p>



<pre class="wp-block-code"><code>shopify theme dev</code></pre>



<p>From the examples above you can see that there is not much difference, see the list of changes here&nbsp;<a href="http://https//shopify.dev/themes/tools/cli/migrate/" target="_blank" rel="noreferrer noopener">Shopify migrate</a></p>



<p>Still, want to roll back? Follow the instruction that follows.</p>



<p>If you already installed Shopify CLI 3 and you want to roll back to Shopify CLI 2, you will need to uninstall version 3.<a href="https://blanla.com/rollback-shopify-cli-3-install-to-shopify-cli-2/#uninstall-shopify-cli-3"></a></p>



<h2 class="wp-block-heading">Uninstall Shopify CLI 3</h2>



<ol class="wp-block-list">
<li>Open the terminal</li>



<li>Run the command below:</li>
</ol>



<pre class="wp-block-code"><code>brew uninstall shopifycli@3</code></pre>



<h2 class="wp-block-heading" id="install-shopify-cli-version-20">Install Shopify CLI Version 2.0<a href="https://blanla.com/rollback-shopify-cli-3-install-to-shopify-cli-2/#requirement-for-installing-shopify-cli"></a></h2>



<h3 class="wp-block-heading" id="requirement-for-installing-shopify-cli">Requirement for installing Shopify CLI</h3>



<ul class="wp-block-list">
<li>Homebrew</li>



<li>Ruby</li>



<li>Git</li>



<li>Node.js</li>
</ul>



<p>If you are using a Mac, git may already be installed on your system. Find out by running:</p>



<pre class="wp-block-code"><code>git --version</code></pre>



<p>If you do not already have it installed, it will prompt you to install it. Ensure your system meets all the requirements (Homebrew, Ruby, Git, Node) before proceeding.</p>



<h3 class="wp-block-heading">Install Shopify CLI 2 using Homebrew</h3>



<pre class="wp-block-code"><code>brew tap shopify/shopify 
brew install shopify-cli@2</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Issue: If you run the&nbsp;<code>shopify version</code>&nbsp;command after installation and get the error:&nbsp;<strong>shopify: command not found</strong></p>
</blockquote>



<h2 class="wp-block-heading">To fix the Shopify command not found, do any of the following:</h2>



<ul class="wp-block-list">
<li>Install the latest version of node.js and reinstall Shopify cli</li>



<li>Uninstall Shopify version 2.0 using the brew uninstall command(<code>brew uninstall shopifycli@2</code>), and install it using npm</li>
</ul>



<h3 class="wp-block-heading">Install Shopify CLI 2 using NPM</h3>



<pre class="wp-block-code"><code>npm install -g @shopify/cli@2 @shopify/theme</code></pre>



<p>If you are having trouble installing Shopify CLI 2 or issues with getting it to work, uninstall all previous versions on your system and stick with version 3. This is a stable version.<a href="https://blanla.com/rollback-shopify-cli-3-install-to-shopify-cli-2/#install-shopify-cli-version-3"></a></p>



<h2 class="wp-block-heading">Install Shopify CLI Version 3</h2>



<ul class="wp-block-list">
<li>Ensure you are using the&nbsp;<strong>latest version of node</strong>&nbsp;to avoid the Shopify command not found error.<a href="https://blanla.com/rollback-shopify-cli-3-install-to-shopify-cli-2/#install-shopify-cli-3-using-homebrew"></a></li>
</ul>



<h3 class="wp-block-heading">Install Shopify CLI 3 using homebrew</h3>



<pre class="wp-block-code"><code>brew tap shopify/shopify 
brew install shopify-cli</code></pre>



<h2 class="wp-block-heading">Conclusions</h2>



<p>This tutorial explained how to install Shopify CLI on the macOS system using homebrew.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Create a Custom HTML Audio Player using HTML and JavaScript</title>
		<link>https://blanla.com/custom-html-audio-player/</link>
					<comments>https://blanla.com/custom-html-audio-player/#respond</comments>
		
		<dc:creator><![CDATA[Abidemi Kusimo]]></dc:creator>
		<pubDate>Sat, 30 Jul 2022 18:04:00 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[JavaScript]]></category>
		<guid isPermaLink="false">https://localhost/blanla/?p=1</guid>

					<description><![CDATA[HTML5 Audio Interface Creating a custom HTML audio player gives you the ability to fully customize the look and functionality of the player to match the design and needs of your website. In this blog post, we’ll cover how to create a custom HTML audio player from scratch. This tutorial is divided into three sections. &#8230; <div class="article-more-link"><a href="https://blanla.com/custom-html-audio-player/" class="read-more" aria-label="Read How to Create a Custom HTML Audio Player using HTML and JavaScript">Continue reading</a></div><div class="clearfix"></div>]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">HTML5 Audio Interface</h2>



<p>Creating a custom HTML audio player gives you the ability to fully customize the look and functionality of the player to match the design and needs of your website. In this blog post, we’ll cover how to create a custom HTML audio player from scratch.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="736" height="134" src="https://www.blanla.com/wp-content/uploads/2023/05/example-custom-html5-audio-player.png" alt="Custom HTML Audio Player" class="wp-image-167" srcset="https://blanla.com/wp-content/uploads/2023/05/example-custom-html5-audio-player.png 736w, https://blanla.com/wp-content/uploads/2023/05/example-custom-html5-audio-player-300x55.png 300w" sizes="(max-width: 736px) 100vw, 736px" /><figcaption class="wp-element-caption">Custom HTML 5 Audio Player</figcaption></figure>



<p>This tutorial is divided into three sections.</p>



<ul class="wp-block-list">
<li>The Play Button</li>



<li>Track Progress</li>



<li>Time (Current / Total Duration)</li>



<li>Repeat Button</li>
</ul>



<h2 class="wp-block-heading" id="the-play-button">The play button</h2>



<p>We need the HTML5 audio element for the audio player to be displayed on a web page. To use the audio element, simply add the following code to your HTML file:</p>



<pre class="wp-block-code"><code>&lt;audio controls&gt;
  &lt;source src="https://cldup.com/qR72ozoaiQ.mp3" type="audio/mpeg"&gt;
  Your browser does not support the audio element.
&lt;/audio&gt;</code></pre>



<p>The HTML code above will output something similar to the audio element (image) below:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="431" height="120" src="https://www.blanla.com/wp-content/uploads/2023/05/example-html5-audio-default.png" alt="Default Audio Player" class="wp-image-168" srcset="https://blanla.com/wp-content/uploads/2023/05/example-html5-audio-default.png 431w, https://blanla.com/wp-content/uploads/2023/05/example-html5-audio-default-300x84.png 300w" sizes="(max-width: 431px) 100vw, 431px" /><figcaption class="wp-element-caption">Default HTML5 Audio Player</figcaption></figure>



<p>To show only the play button, first, remove the&nbsp;<code>controls</code>&nbsp;property(attribute) from the audio element and add an id of ‘track’ (See code below).</p>



<p>This hides all the controls, giving us the flexibility to add a custom control using CSS, HTML and JavaScript.</p>



<p>Once we have gotten rid of the controls, we need to provide our own custom controls. For the play button, add the following code just under the now invisible audio element.</p>



<pre class="wp-block-code"><code>&lt;audio id="track"&gt;
  &lt;source src="https://cldup.com/qR72ozoaiQ.mp3" type="audio/mpeg" /&gt;
&lt;/audio&gt;

&lt;div id="player-container"&gt;
  &lt;div id="play-pause" class="play"&gt;Play&lt;/div&gt;
&lt;/div&gt;</code></pre>



<h3 class="wp-block-heading">Add Play/Pause Button CSS</h3>



<p>It is up to you how you want your play button to look. Copy and paste the code below in your file to show an icon instead of the text that our play button is currently displaying.</p>



<pre class="wp-block-code"><code>#player-container #play-pause {
  cursor: pointer;
  text-indent: -999999px;
  height:40px;
  width: 40px;
  padding: 12px 18px;
  z-index: 2;
    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMiAyNHYtMjRsMjAgMTItMjAgMTJ6Ii8+PC9zdmc+);
    background-repeat: no-repeat!important;
    background-position: center;
    background-size: 16px;
  background-repeat:no-repeat;
  background-position:center;
  background-size:20px;
  background-color: gainsboro;
}
.play {
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMiAyNHYtMjRsMjAgMTItMjAgMTJ6Ii8+PC9zdmc+);
}
.pause {
   background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTAgMjRoLTZ2LTI0aDZ2MjR6bTEwLTI0aC02djI0aDZ2LTI0eiIvPjwvc3ZnPg==)!important;
}</code></pre>



<p>The CSS above hide the text inside our container by using&nbsp;<code>text-indent</code>&nbsp;and setting the value off the screen.</p>



<p>We also use CSS to add background image for the play and pause button which we are going to be controlling using JavaScript.</p>



<h3 class="wp-block-heading">Add JavaScript to control the Play &amp; Pause</h3>



<p>Now that our play button is now showing on the page, we need to add some JavaScript to control the play button.</p>



<p>Add the JavaScript code below.</p>



<pre class="wp-block-code"><code>var track = document.getElementById('track');

var controlBtn = document.getElementById('play-pause');

function playPause() {
    if (track.paused) {
        track.play();
        //controlBtn.textContent = "Pause";
        controlBtn.className = "pause";
    } else { 
        track.pause();
         //controlBtn.textContent = "Play";
        controlBtn.className = "play";
    }
}

controlBtn.addEventListener("click", playPause);
track.addEventListener("ended", function() {
  controlBtn.className = "play";
});</code></pre>



<h4 class="wp-block-heading">Play button final result:</h4>



<p class="codepen" data-height="249.38824462890625" data-default-tab="html,result" data-slug-hash="pGzJGy" data-user="abikuk" style="height: 249.38824462890625px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/abikuk/pen/pGzJGy">
  Custom Audio Player Play Pause Button</a> by Abidemi Kusimo (<a href="https://codepen.io/abikuk">@abikuk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async="" src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>



<h2 class="wp-block-heading">Add Audio Track Progress</h2>



<p>Before we continue, I will like to mention that our audio player will always load on the page. This is not good for user experience and can affect the page speed score of your site.</p>



<h3 class="wp-block-heading">Load audio on request</h3>



<p>We are going to remove the audio src from the audio element and load audio only when the user click on the play button. Update our HTML like the below:</p>



<pre class="wp-block-code"><code>&lt;audio id="track"&gt;
      &lt;source src="" type="audio/mpeg" /&gt;
  &lt;/audio&gt;

  &lt;div id="player-container"&gt;
      &lt;div id="timeline" data-ol-has-click-handler=""&gt;
          &lt;div id="scrub"&gt;&lt;/div&gt;
          &lt;div id="playhead"&gt;&lt;/div&gt;
      &lt;/div&gt;
      &lt;div id="play-pause" class="play" data-audio="https://cldup.com/qR72ozoaiQ.mp3"&gt;Play&lt;/div&gt;
  &lt;/div&gt;</code></pre>



<p>In the above code, we removed the audio file from the audio element and add a&nbsp;<code>data-audio</code>&nbsp;attribute to the pause/play element. We also added 3 elements for the track progress; timeline, scrub, and play-head.</p>



<p>Now let’s update our JavaScript (The&nbsp;<code>playPause</code>&nbsp;function) to set the audio source only when the user clicks on the play button.</p>



<pre class="wp-block-code"><code>function playPause() {
                
    null === track.getAttribute('src') ? track.setAttribute('src', source) : '';
    
    if (track.paused) {
        track.play();
        controlBtn.className = "pause";
    } else {
        track.pause();
        controlBtn.className = "play";
    }

}</code></pre>



<h3 class="wp-block-heading">Add the track progress CSS</h3>



<p>We need to style the 3 elements we just added (timeline, scrub and playhead ) by updating our CSS. Update the CSS to look like below:</p>



<pre class="wp-block-code"><code>#player-container {
    position: relative;
    width: 100%;
    overflow: hidden;
    min-height: 6.25rem;
    background: #eee;
    color: black;
}

#player-container #play-pause {
    cursor: pointer;
    text-indent: -999999px;
    width: 100px;
    height: 100px;
    position: relative;
    float: left;
    padding: 12px 18px;
    z-index: 2;
    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMiAyNHYtMjRsMjAgMTItMjAgMTJ6Ii8+PC9zdmc+);
    background-repeat: no-repeat !important;
    background-position: center;
    background-size: 16px;
    background-repeat: no-repeat;
    background-position: center;
    background-size: 20px;
    background-color: gainsboro;
}

.play {
    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMiAyNHYtMjRsMjAgMTItMjAgMTJ6Ii8+PC9zdmc+);
}

.pause {
    background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTAgMjRoLTZ2LTI0aDZ2MjR6bTEwLTI0aC02djI0aDZ2LTI0eiIvPjwvc3ZnPg==) !important;
}

#timeline {
    width: 100%;
    height: 5px;
    background: #bebebe;
    float: left;
    z-index: 9;
    position: absolute;
}

#scrub {
    height: 5px;
    background-color: #b8a07e;
    border: none;
    color: hsl(44, 100%, 44%);
    float: left;
}

#playhead {
    width: 5px;
    height: 5px;
    background: #f0d9d6;
}</code></pre>



<h3 class="wp-block-heading">Add the track progress JavaScript</h3>



<p>With our CSS updated, we can see the track progress but to make it work we need to add some JavaScript. Update the JavaScript to look like the below:</p>



<pre class="wp-block-code"><code>document.addEventListener("DOMContentLoaded", (event) =&gt; {
  const controlBtn = document.getElementById("play-pause");
  let track = document.getElementById("track"),
    duration = track.duration, // Duration of audio clip (NaN here as the track is not loaded)
    playhead = document.getElementById("playhead"), // playhead
    timeline = document.getElementById("timeline"), // timeline
    timelineWidth = timeline.offsetWidth - playhead.offsetWidth;
  source = controlBtn.getAttribute("data-audio");

  if (!track) return;

  // Update the track duration when the track is loaded.
  track.addEventListener(
    "canplaythrough",
    function () {
      duration = track.duration;
    },
    false
  );

  function playPause() {
    // Check if the attribute is not set, then set it. If attribute is set, do nothing.
    null === track.getAttribute("src") ? track.setAttribute("src", source) : "";

    if (track.paused) {
      track.play();
      controlBtn.className = "pause";
    } else {
      track.pause();
      controlBtn.className = "play";
    }
  }

  controlBtn.addEventListener("click", playPause);

  track.addEventListener("ended", function () {
    controlBtn.className = "play";
    track.currentTime = 0; // reset the playhead
  });

  // timeupdate event listener
  track.addEventListener("timeupdate", timeUpdate, false);

  // makes timeline clickable
  timeline.addEventListener(
    "click",
    function (event) {
      moveplayhead(event);
      track.currentTime = duration * clickPercent(event);
    },
    false
  );

  // Moves playhead as user clicks
  function moveplayhead(event) {
    let newMargLeft = event.clientX - getPosition(timeline);

    if (newMargLeft &gt;= 0 &amp;&amp; newMargLeft &lt;= timelineWidth) {
      playhead.style.marginLeft = newMargLeft + "px";
    }
    if (newMargLeft &lt; 0) {
      playhead.style.marginLeft = "0px";
    }
    if (newMargLeft &gt; timelineWidth) {
      playhead.style.marginLeft = timelineWidth + "px";
    }
  }

  function getPosition(el) {
    return el.getBoundingClientRect().left;
  }

  // returns decimal number of the total timelineWidth
  function clickPercent(event) {
    return (event.clientX - getPosition(timeline)) / timelineWidth;
  }

  // Time update. Manipulate the playhead in the DOM using CSS by increasing the scrub width and the playhead margin.
  function timeUpdate() {
    let playPercent = timelineWidth * (track.currentTime / duration);
    playhead.style.marginLeft = playPercent + "px";
    scrub.style.width = playPercent + "px";
  }
});</code></pre>



<h4 class="wp-block-heading">Track Progress final result:</h4>



<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="XWBmeoj" data-user="abikuk" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/abikuk/pen/XWBmeoj">
  Custom Audio Player Track Progress</a> by Abidemi Kusimo (<a href="https://codepen.io/abikuk">@abikuk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async="" src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>



<h2 class="wp-block-heading">Add Time and Duration</h2>



<p>To add the current time, we are going to add a function that synchronises the play-head position with the current point in the audio. We are also going to update our <code>timeUpdate</code> to use this new function.</p>



<h3 class="wp-block-heading">Code For Time and Duration</h3>



<p>Let’s update our HTML by adding the elements to hold the current time and total duration like the one below:</p>



<pre class="wp-block-code"><code>&lt;audio id="track"&gt;
      &lt;source src="" type="audio/mpeg" /&gt;
  &lt;/audio&gt;

  &lt;div id="player-container"&gt;
      &lt;div id="timeline" data-ol-has-click-handler=""&gt;
          &lt;div id="scrub"&gt;&lt;/div&gt;
          &lt;div id="playhead"&gt;&lt;/div&gt;
      &lt;/div&gt;
      &lt;div id="play-pause" class="play" data-audio="https://cldup.com/qR72ozoaiQ.mp3"&gt;Play&lt;/div&gt;
      &lt;div class="item-inner"&gt;
          &lt;div id="time-bar"&gt;
              &lt;div id="time-holder"&gt;
                  &lt;div id="is-left"&gt;
                      &lt;span id="current-time"&gt;
                          00:00
                      &lt;/span&gt;
                  &lt;/div&gt;

                  &lt;div id="is-right"&gt;
                      &lt;span id="duration-time"&gt;
                          &lt;span class="duration-minutes" data-duration-minutes="true"&gt;0&lt;/span&gt;:&lt;span class="duration-minutes" data-duration-seconds="true"&gt;00&lt;/span&gt;
                      &lt;/span&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;</code></pre>



<p>Let’s update our CSS by adding the code below:</p>



<pre class="wp-block-code"><code>#time-holder {
    font-size: 12px;
    margin-top: 5px;
}
div#is-right, div#is-left {
    display: inline;
    bottom: auto;
    padding: 3px 7px;
    padding-left: 0;
}</code></pre>



<p>Let’s add a function that synchronises the play-head position with the current point in audio like below:</p>



<pre class="wp-block-code"><code>// Synchronizes playhead position with current point in audio
function formatSecondsAsTime(secs, format) {
    let hr = Math.floor(secs / 3600);
    let min = Math.floor((secs - (hr * 3600)) / 60);
    let sec = Math.floor(secs - (hr * 3600) - (min * 60));

    if (min &lt; 10) {
        min = "0" + min;
    }
    if (sec &lt; 10) {
        sec = "0" + sec;
    }

    return min + ':' + sec;
}</code></pre>



<p>Now locate the&nbsp;<code>timeUpdate</code>&nbsp;function and update it to look like below:</p>



<pre class="wp-block-code"><code>// Time update
  function timeUpdate() {
      let playPercent = timelineWidth * (track.currentTime / duration);
      playhead.style.marginLeft = playPercent + "px";
      scrub.style.width = playPercent + "px";

      // Current time
      document.getElementById('duration-time').innerHTML = formatSecondsAsTime(duration);
      document.getElementById('current-time').innerHTML = formatSecondsAsTime(Math.floor(track.currentTime));

  }</code></pre>



<h4 class="wp-block-heading">Time &amp; Duration final result:</h4>



<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ZEjbvvq" data-user="abikuk" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/abikuk/pen/ZEjbvvq">
  Custom Audio Player Time &amp; Duration</a> by Abidemi Kusimo (<a href="https://codepen.io/abikuk">@abikuk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async="" src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>



<h2 class="wp-block-heading">Add a Repeat/Replay Button</h2>



<p>So far, all the features we’ve added are already present in the default HTML players but the repeat/replay feature is missing in the default player.</p>



<p>To add the replay, we need to add and element to hold the repeat button. Update the HTML code to look like the below:</p>



<pre class="wp-block-code"><code>&lt;audio id="track"&gt;
  &lt;source src="" type="audio/mpeg" /&gt;
&lt;/audio&gt;

&lt;div id="player-container"&gt;

  &lt;!-- Timeline--&gt;
  &lt;div id="timeline" data-ol-has-click-handler=""&gt;
    &lt;div id="scrub"&gt;&lt;/div&gt;
    &lt;div id="playhead"&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- play pause--&gt;
  &lt;div id="play-pause" class="play" data-audio="https://cldup.com/qR72ozoaiQ.mp3"&gt;Play&lt;/div&gt;

  &lt;!-- duration --&gt;
  &lt;div class="item-inner"&gt;
    &lt;div id="time-bar"&gt;
      &lt;div id="time-holder"&gt;
        &lt;div id="is-left"&gt;
          &lt;span id="current-time"&gt;
            00:00
          &lt;/span&gt;
        &lt;/div&gt;
        &lt;div id="is-right"&gt;
          &lt;span id="duration-time"&gt;
            &lt;span class="duration-minutes" data-duration-minutes="true"&gt;0&lt;/span&gt;:&lt;span class="duration-minutes" data-duration-seconds="true"&gt;00&lt;/span&gt;
          &lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;!-- repeat button---&gt;
  &lt;div class="repeat-button"&gt;
    &lt;div id="repeat" class="icon-repeat" repeat="0"&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;</code></pre>



<p>Update our CSS to include the following lines of code:</p>



<pre class="wp-block-code"><code>/* Repeat */
  .repeat-button {
      display: flex;
      justify-content: center;
      align-items: center;
      position: absolute;
      top: 15px;
      right: 10px;
      border-radius: 30px;
      -webkit-border-radius: 30px;
      -moz-border-radius: 30px;
      width: 30px;
      height: 30px;
      cursor: pointer;
      outline: 0;
      background-color: #b8a07e;
  }
  
  .icon-repeat {
      border: none;
      overflow: auto;
      border-radius: 3px;
      cursor: pointer;
      height: 30px;
      width: 30px;
      background: url('data:image/svg+xml;utf8,&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"&gt;&lt;path d="M13.5 2c-5.288 0-9.649 3.914-10.377 9h-3.123l4 5.917 4-5.917h-2.847c.711-3.972 4.174-7 8.347-7 4.687 0 8.5 3.813 8.5 8.5s-3.813 8.5-8.5 8.5c-3.015 0-5.662-1.583-7.171-3.957l-1.2 1.775c1.916 2.536 4.948 4.182 8.371 4.182 5.797 0 10.5-4.702 10.5-10.5s-4.703-10.5-10.5-10.5z"/&gt;&lt;/svg&gt;')
      5px center no-repeat;
      background-size: 24px;
      background-position: center;
      filter: invert(1);
      margin-left: -3px;
      margin-top: -3px;
  }
  .icon-repeat-again {
      background-image: url('data:image/svg+xml;utf8,&lt;svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd"&gt;&lt;path d="M8 6.012h-6.58l1.935-6.012 1.718 2.223c1.958-1.389 4.346-2.211 6.927-2.211 6.623 0 12 5.377 12 12s-5.377 11.988-12 11.988-12-5.365-12-11.988c0-1.036.132-2.041.379-3h2.079c-.297.947-.458 1.955-.458 3 0 5.52 4.481 10 10 10 5.52 0 10-4.48 10-10 0-5.519-4.48-10-10-10-2.121 0-4.083.668-5.703 1.796l1.703 2.204zm4 1.988c2.208 0 4 1.792 4 4s-1.792 4-4 4-4-1.792-4-4 1.792-4 4-4z"/&gt;&lt;/svg&gt;');
      margin-left: unset;
      margin-top: unset;
      background-size: 22px;
  }</code></pre>



<p>We need to use JavaScript to control the repeat button by checking if the user has clicked on repeat when the audio finished playing. If this is true, then the audio will play again.</p>



<p>Add the JavaScript like below:</p>



<pre class="wp-block-code"><code>let repeatButton = document.getElementsByClassName("icon-repeat");</code></pre>



<p>Then update the&nbsp;<code>ended</code>&nbsp;event handler like below:</p>



<pre class="wp-block-code"><code>track.addEventListener("ended", function () {
    controlBtn.className = "play";
    track.currentTime = 0; // reset the playhead

    // Let's check if the repeat button is on, then play the track again.
    let times = repeatButton&#91;0].getAttribute("repeat");
    if (times &gt; 0) {
    controlBtn.className = "";
    controlBtn.className = "pause";
    track.play();
    }
});</code></pre>



<p>Lastly, let’s add a toggle to the repeat to make this user-friendly. Add the JS below:</p>



<pre class="wp-block-code"><code>// Repeat
repeatButton&#91;0].onclick = function () {
    repeatButton&#91;0].setAttribute("repeat", 0);
    repeatButton&#91;0].classList.toggle("icon-repeat-again");

    if (repeatButton&#91;0].classList.contains("icon-repeat-again")) {
    repeatButton&#91;0].setAttribute("repeat", 1);
    }
};</code></pre>



<h4 class="wp-block-heading">Repeat/Replay button final result:</h4>



<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="rNrOpbg" data-user="abikuk" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/abikuk/pen/rNrOpbg">
  Custom Audio Player Replay/Repeat Button</a> by Abidemi Kusimo (<a href="https://codepen.io/abikuk">@abikuk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async="" src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
]]></content:encoded>
					
					<wfw:commentRss>https://blanla.com/custom-html-audio-player/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://cldup.com/qR72ozoaiQ.mp3" length="535116" type="audio/mpeg" />

			</item>
	</channel>
</rss>
