Various fixes for the blog and editor. As well as finally adding in the carousel!
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				🚀 Deploy website on push / 🎉 Deploy (push) Successful in 24s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	🚀 Deploy website on push / 🎉 Deploy (push) Successful in 24s
				
			Signed-off-by: rodude123 <rodude123@gmail.com>
This commit is contained in:
		
							parent
							
								
									7d6eeb2310
								
							
						
					
					
						commit
						b28e7b2da5
					
				
							
								
								
									
										39
									
								
								dist/api/blog/blogData.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								dist/api/blog/blogData.php
									
									
									
									
										vendored
									
									
								
							@ -673,9 +673,17 @@ EOD;
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function changeHTMLSrc(string $body, string $to, string $from): string
 | 
					    public function changeHTMLSrc(string $body, string $to, string $from): string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					//        $body = preg_replace_callback('/>([^<]+)</', function($matches) {
 | 
				
			||||||
 | 
					//            // Convert special characters to HTML entities
 | 
				
			||||||
 | 
					//            return '>' . htmlentities(trim($matches[1]), ENT_QUOTES | ENT_HTML5, 'UTF-8') . '<';
 | 
				
			||||||
 | 
					//        }, $body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $htmlDoc = new DOMDocument();
 | 
					        $htmlDoc = new DOMDocument();
 | 
				
			||||||
        $body = mb_convert_encoding($body, "HTML-ENTITIES", "UTF-8");
 | 
					
 | 
				
			||||||
        $htmlDoc->loadHTML($body, LIBXML_NOERROR);
 | 
					        // Load the raw HTML content into DOMDocument
 | 
				
			||||||
 | 
					        @$htmlDoc->loadHTML($body, LIBXML_NOERROR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get the body and process images
 | 
				
			||||||
        $doc = $htmlDoc->getElementsByTagName('body')->item(0);
 | 
					        $doc = $htmlDoc->getElementsByTagName('body')->item(0);
 | 
				
			||||||
        $imgs = $doc->getElementsByTagName('img');
 | 
					        $imgs = $doc->getElementsByTagName('img');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -688,9 +696,11 @@ EOD;
 | 
				
			|||||||
            $srcList[] = $src;
 | 
					            $srcList[] = $src;
 | 
				
			||||||
            $fileName = basename($src);
 | 
					            $fileName = basename($src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Update the src attribute to the new location
 | 
				
			||||||
            $img->setAttribute("src", substr($to, 2) . $fileName);
 | 
					            $img->setAttribute("src", substr($to, 2) . $fileName);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Rename files and clean up old ones
 | 
				
			||||||
        $files = scandir($from);
 | 
					        $files = scandir($from);
 | 
				
			||||||
        foreach ($files as $file)
 | 
					        foreach ($files as $file)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -706,15 +716,36 @@ EOD;
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Process the HTML content for output
 | 
				
			||||||
        $newBody = '';
 | 
					        $newBody = '';
 | 
				
			||||||
        foreach ($doc->childNodes as $node)
 | 
					        foreach ($doc->childNodes as $node)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $newHTML = $htmlDoc->saveHTML($node);
 | 
					            // Only convert text nodes to HTML entities
 | 
				
			||||||
            $newBody .= mb_convert_encoding($newHTML, "UTF-8", mb_detect_encoding($newHTML));
 | 
					            if ($node->nodeType === XML_TEXT_NODE)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                $newBody .= $this->convertToHtmlEntities($node->nodeValue); // Convert text nodes
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                $newBody .= $htmlDoc->saveHTML($node); // Keep HTML tags intact
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $newBody;
 | 
					        return $newBody;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Convert all characters in a string to HTML entities while leaving HTML tags intact.
 | 
				
			||||||
 | 
					     * @param string $text - The text to convert
 | 
				
			||||||
 | 
					     * @return string - The converted text with HTML entities
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private function convertToHtmlEntities(string $text): string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Convert characters to HTML entities using mb_encode_numericentity
 | 
				
			||||||
 | 
					        return htmlentities($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get all posts with the given category
 | 
					     * Get all posts with the given category
 | 
				
			||||||
     * @param string $category - Category of the post
 | 
					     * @param string $category - Category of the post
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								dist/api/user/userRoutes.php
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/api/user/userRoutes.php
									
									
									
									
										vendored
									
									
								
							@ -181,7 +181,7 @@ class userRoutes implements routesInterface
 | 
				
			|||||||
                $inactive = 60 * 60 * 48; // 2 days
 | 
					                $inactive = 60 * 60 * 48; // 2 days
 | 
				
			||||||
                $_SESSION["timeout"] = time() + $inactive;
 | 
					                $_SESSION["timeout"] = time() + $inactive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return $response->withHeader("Location", "https://rohitpai.co.uk/editor/")->withStatus(302);
 | 
					                return $response->withHeader("Location", "https://rohitpai.co.uk/editor/")->withStatus(302);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            $response->getBody()->write(json_encode(array("error" => "Unauthorised")));
 | 
					            $response->getBody()->write(json_encode(array("error" => "Unauthorised")));
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								dist/blog/css/main.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/blog/css/main.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/blog/js/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/blog/js/index.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/blog/js/prism.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/blog/js/prism.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/editor/js/CKEditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/editor/js/CKEditor/ckeditor.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/editor/js/editor.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/editor/js/editor.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2786
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2786
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -673,9 +673,17 @@ EOD;
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    public function changeHTMLSrc(string $body, string $to, string $from): string
 | 
					    public function changeHTMLSrc(string $body, string $to, string $from): string
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					//        $body = preg_replace_callback('/>([^<]+)</', function($matches) {
 | 
				
			||||||
 | 
					//            // Convert special characters to HTML entities
 | 
				
			||||||
 | 
					//            return '>' . htmlentities(trim($matches[1]), ENT_QUOTES | ENT_HTML5, 'UTF-8') . '<';
 | 
				
			||||||
 | 
					//        }, $body);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $htmlDoc = new DOMDocument();
 | 
					        $htmlDoc = new DOMDocument();
 | 
				
			||||||
        $body = mb_convert_encoding($body, "HTML-ENTITIES", "UTF-8");
 | 
					
 | 
				
			||||||
        $htmlDoc->loadHTML($body, LIBXML_NOERROR);
 | 
					        // Load the raw HTML content into DOMDocument
 | 
				
			||||||
 | 
					        @$htmlDoc->loadHTML($body, LIBXML_NOERROR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Get the body and process images
 | 
				
			||||||
        $doc = $htmlDoc->getElementsByTagName('body')->item(0);
 | 
					        $doc = $htmlDoc->getElementsByTagName('body')->item(0);
 | 
				
			||||||
        $imgs = $doc->getElementsByTagName('img');
 | 
					        $imgs = $doc->getElementsByTagName('img');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -688,9 +696,11 @@ EOD;
 | 
				
			|||||||
            $srcList[] = $src;
 | 
					            $srcList[] = $src;
 | 
				
			||||||
            $fileName = basename($src);
 | 
					            $fileName = basename($src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Update the src attribute to the new location
 | 
				
			||||||
            $img->setAttribute("src", substr($to, 2) . $fileName);
 | 
					            $img->setAttribute("src", substr($to, 2) . $fileName);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Rename files and clean up old ones
 | 
				
			||||||
        $files = scandir($from);
 | 
					        $files = scandir($from);
 | 
				
			||||||
        foreach ($files as $file)
 | 
					        foreach ($files as $file)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -706,15 +716,36 @@ EOD;
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Process the HTML content for output
 | 
				
			||||||
        $newBody = '';
 | 
					        $newBody = '';
 | 
				
			||||||
        foreach ($doc->childNodes as $node)
 | 
					        foreach ($doc->childNodes as $node)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            $newHTML = $htmlDoc->saveHTML($node);
 | 
					            // Only convert text nodes to HTML entities
 | 
				
			||||||
            $newBody .= mb_convert_encoding($newHTML, "UTF-8", mb_detect_encoding($newHTML));
 | 
					            if ($node->nodeType === XML_TEXT_NODE)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                $newBody .= $this->convertToHtmlEntities($node->nodeValue); // Convert text nodes
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                $newBody .= $htmlDoc->saveHTML($node); // Keep HTML tags intact
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return $newBody;
 | 
					        return $newBody;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Convert all characters in a string to HTML entities while leaving HTML tags intact.
 | 
				
			||||||
 | 
					     * @param string $text - The text to convert
 | 
				
			||||||
 | 
					     * @return string - The converted text with HTML entities
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private function convertToHtmlEntities(string $text): string
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Convert characters to HTML entities using mb_encode_numericentity
 | 
				
			||||||
 | 
					        return htmlentities($text, ENT_QUOTES | ENT_HTML5, 'UTF-8');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get all posts with the given category
 | 
					     * Get all posts with the given category
 | 
				
			||||||
     * @param string $category - Category of the post
 | 
					     * @param string $category - Category of the post
 | 
				
			||||||
 | 
				
			|||||||
@ -123,3 +123,102 @@ section.largePost .outerContent .postContent a {
 | 
				
			|||||||
    display: table-cell;
 | 
					    display: table-cell;
 | 
				
			||||||
    vertical-align: middle;
 | 
					    vertical-align: middle;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts {
 | 
				
			||||||
 | 
					    /*max-width: 90%;*/
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts .carousel {
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts .arrow {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    top: 50%;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    width: 2.5em;
 | 
				
			||||||
 | 
					    height: 2.5em;
 | 
				
			||||||
 | 
					    justify-content: center;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    border-radius: 50%;
 | 
				
			||||||
 | 
					    z-index: 1;
 | 
				
			||||||
 | 
					    font-size: 1.625em;
 | 
				
			||||||
 | 
					    color: white;
 | 
				
			||||||
 | 
					    background: var(--mutedBlack);
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts .arrow:hover {
 | 
				
			||||||
 | 
					    background: var(--grey);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts #prev {
 | 
				
			||||||
 | 
					    left: -4em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts #next {
 | 
				
			||||||
 | 
					    right: -4em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts .carouselOuter {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: row;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    gap: 1em;
 | 
				
			||||||
 | 
					    overflow: hidden;
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts #allCarouselItems {
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts #carouselInner {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: row;
 | 
				
			||||||
 | 
					    align-items: stretch;
 | 
				
			||||||
 | 
					    justify-content: center;
 | 
				
			||||||
 | 
					    gap: 1em;
 | 
				
			||||||
 | 
					    transition: transform 0.5s ease-in-out;
 | 
				
			||||||
 | 
					    left: 0;
 | 
				
			||||||
 | 
					    height: 50%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts #carouselInner .cardItem {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    justify-content: space-between;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    border: 2px solid var(--primaryDefault);
 | 
				
			||||||
 | 
					    -webkit-border-radius: 0.625rem;
 | 
				
			||||||
 | 
					    -moz-border-radius: 0.625rem;
 | 
				
			||||||
 | 
					    border-radius: 0.625rem;
 | 
				
			||||||
 | 
					    width: 30em;
 | 
				
			||||||
 | 
					    height: 40rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts #carouselInner .cardItem img {
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    height: 300px;
 | 
				
			||||||
 | 
					    object-fit: cover;
 | 
				
			||||||
 | 
					    object-position: left;
 | 
				
			||||||
 | 
					    -webkit-border-radius: 0.625rem;
 | 
				
			||||||
 | 
					    -moz-border-radius: 0.625rem;
 | 
				
			||||||
 | 
					    border-radius: 0.625rem;
 | 
				
			||||||
 | 
					    color: #FFFFFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					section#olderPosts #carouselInner .cardItem .content {
 | 
				
			||||||
 | 
					    height: auto;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    justify-content: space-evenly;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    background: #FFFFFF;
 | 
				
			||||||
 | 
					    margin: 0 2em 1.5em;
 | 
				
			||||||
 | 
					    padding: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,12 @@
 | 
				
			|||||||
@import "home.css";
 | 
					@import "home.css";
 | 
				
			||||||
@import "category.css";
 | 
					@import "category.css";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					div.menuBar a.link::before, main a.link::before,
 | 
				
			||||||
 | 
					div.menuBar a.link::after, main a.link::after {
 | 
				
			||||||
 | 
					    margin-top: -1px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Modal Styling */
 | 
				
			||||||
.policy {
 | 
					.policy {
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
    flex-direction: column;
 | 
					    flex-direction: column;
 | 
				
			||||||
@ -73,6 +79,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@media screen and (max-width: 90em) {
 | 
					@media screen and (max-width: 90em) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    section#olderPosts #carouselInner .cardItem {
 | 
				
			||||||
 | 
					        width: 25em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /***** Individual Blog Posts ***/
 | 
					    /***** Individual Blog Posts ***/
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    div.mainContent {
 | 
					    div.mainContent {
 | 
				
			||||||
@ -124,6 +135,25 @@
 | 
				
			|||||||
        width: 90%;
 | 
					        width: 90%;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    section#olderPosts .arrow {
 | 
				
			||||||
 | 
					        width: 2em;
 | 
				
			||||||
 | 
					        height: 2em;
 | 
				
			||||||
 | 
					        font-size: 1.25em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    section#olderPosts #prev {
 | 
				
			||||||
 | 
					        left: -3em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    section#olderPosts #next {
 | 
				
			||||||
 | 
					        right: -3em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    section#olderPosts #carouselInner .cardItem {
 | 
				
			||||||
 | 
					        width: 20em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /***** Individual Blog Posts ***/
 | 
					    /***** Individual Blog Posts ***/
 | 
				
			||||||
    section#individualPost {
 | 
					    section#individualPost {
 | 
				
			||||||
        flex-direction: column-reverse;
 | 
					        flex-direction: column-reverse;
 | 
				
			||||||
@ -219,6 +249,24 @@
 | 
				
			|||||||
        max-width: 75%;
 | 
					        max-width: 75%;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    section#olderPosts .arrow {
 | 
				
			||||||
 | 
					        width: 1.5em;
 | 
				
			||||||
 | 
					        height: 1.5em;
 | 
				
			||||||
 | 
					        font-size: 1em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    section#olderPosts #prev {
 | 
				
			||||||
 | 
					        left: -1.75em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    section#olderPosts #next {
 | 
				
			||||||
 | 
					        right: -1.75em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    section#olderPosts #carouselInner .cardItem {
 | 
				
			||||||
 | 
					        width: 15em;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /***** Individual Blog Posts ***/
 | 
					    /***** Individual Blog Posts ***/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    aside.sideContent > div.authorInfo {
 | 
					    aside.sideContent > div.authorInfo {
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,6 @@ function goToURL(url)
 | 
				
			|||||||
	if (url === '/blog' || url === 'blog' || url === '/blog/')
 | 
						if (url === '/blog' || url === 'blog' || url === '/blog/')
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		loadHomeContent();
 | 
							loadHomeContent();
 | 
				
			||||||
		// window.history.pushState(null, null, url);
 | 
					 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
@ -162,6 +161,10 @@ function submitNewsletter()
 | 
				
			|||||||
	}));
 | 
						}));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * unsubscribe by email
 | 
				
			||||||
 | 
					 * @param email the email to unsubscribe
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
function unsubscribe(email)
 | 
					function unsubscribe(email)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	fetch(`/api/blog/newsletter/${email}`, {
 | 
						fetch(`/api/blog/newsletter/${email}`, {
 | 
				
			||||||
@ -243,6 +246,32 @@ function createLargePost(post)
 | 
				
			|||||||
	return outerContent;
 | 
						return outerContent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Creates a card post element
 | 
				
			||||||
 | 
					 * @param post the object
 | 
				
			||||||
 | 
					 * @returns {HTMLDivElement} the outer content of the post
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function createCardPost(post)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						let cardItem = document.createElement('div');
 | 
				
			||||||
 | 
						cardItem.classList.add('cardItem');
 | 
				
			||||||
 | 
						cardItem.id = 'post' + post.ID;
 | 
				
			||||||
 | 
						let img = document.createElement('img');
 | 
				
			||||||
 | 
						img.className = 'cardImg';
 | 
				
			||||||
 | 
						img.src = post.headerImg.replaceAll('%2F', '/');
 | 
				
			||||||
 | 
						img.alt = post.title;
 | 
				
			||||||
 | 
						cardItem.appendChild(img);
 | 
				
			||||||
 | 
						let content = document.createElement('div');
 | 
				
			||||||
 | 
						content.classList.add('content');
 | 
				
			||||||
 | 
						content.innerHTML = `
 | 
				
			||||||
 | 
										<h2>${post.title}</h2>
 | 
				
			||||||
 | 
										<h3>Last updated: ${createFormattedDate(post.dateModified)}</h3>
 | 
				
			||||||
 | 
										<a href="/blog/post/${post.title}" class="btn btnPrimary">See Post</a>
 | 
				
			||||||
 | 
										`;
 | 
				
			||||||
 | 
						cardItem.appendChild(content);
 | 
				
			||||||
 | 
						return cardItem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Loads the home content
 | 
					 * Loads the home content
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -250,6 +279,30 @@ function loadHomeContent()
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	fetch('/api/blog/post').then(res => res.json().then(json =>
 | 
						fetch('/api/blog/post').then(res => res.json().then(json =>
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							// older posts outside the carousel and loop
 | 
				
			||||||
 | 
							let olderPosts = document.createElement('section');
 | 
				
			||||||
 | 
							olderPosts.classList.add('largePost');
 | 
				
			||||||
 | 
							olderPosts.id = 'olderPosts';
 | 
				
			||||||
 | 
							let h1 = document.createElement('h1');
 | 
				
			||||||
 | 
							h1.innerHTML = 'older posts';
 | 
				
			||||||
 | 
							olderPosts.appendChild(h1);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							let carousel = document.createElement('div');
 | 
				
			||||||
 | 
							carousel.classList.add('carousel');
 | 
				
			||||||
 | 
							carousel.innerHTML += `<div class="arrow" id="prev"><i class="fa-solid fa-chevron-left"></i></div>
 | 
				
			||||||
 | 
												   <div class="arrow" id="next"><i class="fa-solid fa-chevron-right"></i></div>
 | 
				
			||||||
 | 
											 	  `;
 | 
				
			||||||
 | 
							let carouselOuter = document.createElement('div');
 | 
				
			||||||
 | 
							let carouselInner = document.createElement('div');
 | 
				
			||||||
 | 
							let allCarouselItems = document.createElement('div');
 | 
				
			||||||
 | 
							carouselOuter.classList.add('carouselOuter');
 | 
				
			||||||
 | 
							carouselInner.id = 'carouselInner';
 | 
				
			||||||
 | 
							allCarouselItems.id = 'allCarouselItems';
 | 
				
			||||||
 | 
							carouselOuter.appendChild(allCarouselItems);
 | 
				
			||||||
 | 
							carouselOuter.appendChild(carouselInner);
 | 
				
			||||||
 | 
							carousel.appendChild(carouselOuter);
 | 
				
			||||||
 | 
							olderPosts.appendChild(carousel);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
		for (let i = 0; i < json.length; i++)
 | 
							for (let i = 0; i < json.length; i++)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (json[i].featured === 1)
 | 
								if (json[i].featured === 1)
 | 
				
			||||||
@ -278,10 +331,142 @@ function loadHomeContent()
 | 
				
			|||||||
				document.querySelector('#main').appendChild(latestPost);
 | 
									document.querySelector('#main').appendChild(latestPost);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
 | 
								if (i > 1)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									allCarouselItems.appendChild(createCardPost(json[i]));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							document.querySelector('#main').appendChild(olderPosts);
 | 
				
			||||||
 | 
							//carousel loop
 | 
				
			||||||
 | 
							carouselLoop(carouselInner, allCarouselItems);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
	}));
 | 
						}));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Creates the loop for the carousel
 | 
				
			||||||
 | 
					 * @param {HTMLDivElement} carouselInner
 | 
				
			||||||
 | 
					 * @param {HTMLDivElement} allItems
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function carouselLoop(carouselInner, allItems)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const prev = document.querySelector('#prev');
 | 
				
			||||||
 | 
						const next = document.querySelector('#next');
 | 
				
			||||||
 | 
						const mediaBig = window.matchMedia('(max-width: 75em)');
 | 
				
			||||||
 | 
						const mediaSmall = window.matchMedia('(max-width: 30em)');
 | 
				
			||||||
 | 
						let cards = document.querySelectorAll('#allCarouselItems .cardItem');
 | 
				
			||||||
 | 
						let visibleCardsCount = 3;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (mediaBig.matches)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							visibleCardsCount = 2; // only show 2 cards if on a slightly smaller screen e.g. tablet/laptop
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (mediaSmall.matches)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							visibleCardsCount = 1; // only show 1 card if on a mobile, although it'll only work on portrait
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						let visibleCards = [];
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// put the first n (3, 2, or 1) cards in the carousel
 | 
				
			||||||
 | 
						for (let i = 0; i < visibleCardsCount; i++)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							carouselInner.appendChild(cards[i]);
 | 
				
			||||||
 | 
							visibleCards.push(cards[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						next.addEventListener('click', () =>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							const firstCard = visibleCards.shift();
 | 
				
			||||||
 | 
							firstCard.style.visibility = 'hidden'; // hide the first card
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// add the next card to the end and off the screen
 | 
				
			||||||
 | 
							const nextCard = allItems.querySelector('.cardItem');
 | 
				
			||||||
 | 
							nextCard.style.transform = 'translateX(100%)';
 | 
				
			||||||
 | 
							nextCard.style.transition = 'none';
 | 
				
			||||||
 | 
							carouselInner.appendChild(nextCard);
 | 
				
			||||||
 | 
							visibleCards.push(nextCard);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// transition all the cards to the left after 50ms
 | 
				
			||||||
 | 
							// i.e. after the next card is added hence the setTimeout
 | 
				
			||||||
 | 
							setTimeout(() =>
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// move all the cards to the left
 | 
				
			||||||
 | 
								for (let i = 0; i < carouselInner.children.length; i++)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									carouselInner.children[i].style.transition = 'transform 0.5s ease-out';
 | 
				
			||||||
 | 
									carouselInner.children[i].style.transform = 'translateX(-100%)';
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}, 50);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// after 500ms move all cards back to the center and move
 | 
				
			||||||
 | 
							// the first card to the hidden div
 | 
				
			||||||
 | 
							setTimeout(() =>
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// move the first card back to the center
 | 
				
			||||||
 | 
								// instantly and move it to the hidden div
 | 
				
			||||||
 | 
								firstCard.style.transition = 'none';
 | 
				
			||||||
 | 
								firstCard.style.transform = 'translateX(0)';
 | 
				
			||||||
 | 
								allItems.appendChild(firstCard);
 | 
				
			||||||
 | 
								firstCard.style.visibility = 'visible'; // make it visible again
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								// for the remaining cards, reset them
 | 
				
			||||||
 | 
								for (let i = 0; i < carouselInner.children.length; i++)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									carouselInner.children[i].style.transition = 'none';
 | 
				
			||||||
 | 
									carouselInner.children[i].style.transform = 'translateX(0%)';
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
							}, 500);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// everything is done in reverse
 | 
				
			||||||
 | 
						prev.addEventListener('click', () =>
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							const lastCard = visibleCards.pop();
 | 
				
			||||||
 | 
							lastCard.style.visibility = 'hidden'; // hide the last card
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// add the previous card to the beginning and off the screen
 | 
				
			||||||
 | 
							const prevCard = allItems.querySelector('.cardItem:last-child');
 | 
				
			||||||
 | 
							prevCard.style.transform = 'translateX(-100%)';
 | 
				
			||||||
 | 
							prevCard.style.transition = 'none';
 | 
				
			||||||
 | 
							carouselInner.insertBefore(prevCard, carouselInner.firstChild);
 | 
				
			||||||
 | 
							visibleCards.unshift(prevCard);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// transition all the cards to the right after 50ms
 | 
				
			||||||
 | 
							// i.e. after the previous card is added hence the setTimeout
 | 
				
			||||||
 | 
							setTimeout(() =>
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// move all the cards to the right
 | 
				
			||||||
 | 
								for (let i = 0; i < carouselInner.children.length; i++)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									carouselInner.children[i].style.transition = 'transform 0.5s ease-out';
 | 
				
			||||||
 | 
									carouselInner.children[i].style.transform = 'translateX(100%)';
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}, 50);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// after 500ms move all cards back to the center and move
 | 
				
			||||||
 | 
							// the last card to the hidden div
 | 
				
			||||||
 | 
							setTimeout(() =>
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// move the last card back to the center
 | 
				
			||||||
 | 
								// instantly and move it to the hidden div
 | 
				
			||||||
 | 
								lastCard.style.transition = 'none';
 | 
				
			||||||
 | 
								lastCard.style.transform = 'translateX(0)';
 | 
				
			||||||
 | 
								allItems.insertBefore(lastCard, allItems.firstChild);
 | 
				
			||||||
 | 
								lastCard.style.visibility = 'visible';
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								// for the remaining cards reset them
 | 
				
			||||||
 | 
								for (let i = 0; i < carouselInner.children.length; i++)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									carouselInner.children[i].style.transition = 'none';
 | 
				
			||||||
 | 
									carouselInner.children[i].style.transform = 'translateX(0%)';
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}, 500);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Gets the latest and featured posts
 | 
					 * Gets the latest and featured posts
 | 
				
			||||||
 * @returns {Promise<any[]>} the latest and featured posts
 | 
					 * @returns {Promise<any[]>} the latest and featured posts
 | 
				
			||||||
@ -848,6 +1033,9 @@ function loadPrivacyPolicy()
 | 
				
			|||||||
		`;
 | 
							`;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *  Loads the cookie policy
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
function loadCookiePolicy()
 | 
					function loadCookiePolicy()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	document.querySelector('#main').innerHTML = `
 | 
						document.querySelector('#main').innerHTML = `
 | 
				
			||||||
 | 
				
			|||||||
@ -876,7 +876,7 @@ function createEditors(...ids)
 | 
				
			|||||||
                            
 | 
					                            
 | 
				
			||||||
                            return (
 | 
					                            return (
 | 
				
			||||||
                                `<iframe width="560" height="315" style="text-align:center;" src="https://www.youtube.com/embed/${id}${time ? `?start=${time}` : ''}" ` +
 | 
					                                `<iframe width="560" height="315" style="text-align:center;" src="https://www.youtube.com/embed/${id}${time ? `?start=${time}` : ''}" ` +
 | 
				
			||||||
                                'frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen>' +
 | 
					                                'allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen>' +
 | 
				
			||||||
                                '</iframe>'
 | 
					                                '</iframe>'
 | 
				
			||||||
                            );
 | 
					                            );
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
@ -1229,7 +1229,7 @@ function updateProjectItem(id, e)
 | 
				
			|||||||
    data['gitLink'] = document.querySelector(`#git${id}proj`).value;
 | 
					    data['gitLink'] = document.querySelector(`#git${id}proj`).value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let imgData = new FormData();
 | 
					    let imgData = new FormData();
 | 
				
			||||||
    imgData.append("img", document.querySelector(`#img${id}`).files[0]);
 | 
					    imgData.append('img', document.querySelector(`#img${id}proj`).files[0]);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    fetch("/api/projectData/" + id, {
 | 
					    fetch("/api/projectData/" + id, {
 | 
				
			||||||
        method: "PATCH",
 | 
					        method: "PATCH",
 | 
				
			||||||
@ -1254,8 +1254,8 @@ function updateProjectItem(id, e)
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                document.querySelector(`#projectItem${id}`).classList.toggle("editing");
 | 
					                document.querySelector(`#projectItem${id}`).classList.toggle("editing");
 | 
				
			||||||
                document.querySelector(`#title${id}`).setAttribute("disabled", "");
 | 
					                document.querySelector(`#title${id}proj`).setAttribute('disabled', '');
 | 
				
			||||||
                document.querySelector(`#info${id}`).setAttribute("disabled", "");
 | 
					                document.querySelector(`#info${id}proj`).setAttribute('disabled', '');
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            console.log("updating image")
 | 
					            console.log("updating image")
 | 
				
			||||||
@ -1293,8 +1293,8 @@ function updateProjectItem(id, e)
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            document.querySelector(`#projectItem${id}`).classList.toggle("editing");
 | 
					            document.querySelector(`#projectItem${id}`).classList.toggle("editing");
 | 
				
			||||||
            document.querySelector(`#title${id}`).setAttribute("disabled", "");
 | 
					            document.querySelector(`#title${id}proj`).setAttribute('disabled', '');
 | 
				
			||||||
            document.querySelector(`#info${id}`).setAttribute("disabled", "");
 | 
					            document.querySelector(`#info${id}proj`).setAttribute('disabled', '');
 | 
				
			||||||
            document.querySelector(`#projectImage${id}`).src = updatedProjectImage.imgLocation;
 | 
					            document.querySelector(`#projectImage${id}`).src = updatedProjectImage.imgLocation;
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user