@@ -593,278 +593,7 @@ function initPascalTriangle() {
593593 generatePascal ( ) ; // Initial generation
594594}
595595
596- // ============================================
597- // CALCULATOR
598- // ============================================
599- function getCalculatorHTML ( ) {
600- return `
601- <div class="project-content">
602- <h2>🧮 Calculator</h2>
603- <div class="calculator">
604- <div class="calc-display" id="calcDisplay">0</div>
605- <div class="calc-buttons">
606- <button class="calc-btn clear" data-action="clear" tabindex="-1">C</button>
607- <button class="calc-btn operator" data-action="delete" tabindex="-1">⌫</button>
608- <button class="calc-btn operator" data-action="/" tabindex="-1">/</button>
609- <button class="calc-btn operator" data-action="*" tabindex="-1">×</button>
610-
611- <button class="calc-btn number" data-value="7" tabindex="-1">7</button>
612- <button class="calc-btn number" data-value="8" tabindex="-1">8</button>
613- <button class="calc-btn number" data-value="9" tabindex="-1">9</button>
614- <button class="calc-btn operator" data-action="-" tabindex="-1">−</button>
615-
616- <button class="calc-btn number" data-value="4" tabindex="-1">4</button>
617- <button class="calc-btn number" data-value="5" tabindex="-1">5</button>
618- <button class="calc-btn number" data-value="6" tabindex="-1">6</button>
619- <button class="calc-btn operator" data-action="+" tabindex="-1">+</button>
620-
621- <button class="calc-btn number" data-value="1" tabindex="-1">1</button>
622- <button class="calc-btn number" data-value="2" tabindex="-1">2</button>
623- <button class="calc-btn number" data-value="3" tabindex="-1">3</button>
624- <button class="calc-btn operator" data-action="**" tabindex="-1">^</button>
625-
626- <button class="calc-btn number span-2" data-value="0" tabindex="-1">0</button>
627- <button class="calc-btn number" data-value="." tabindex="-1">.</button>
628- <button class="calc-btn equals" data-action="=" tabindex="-1">=</button>
629- </div>
630- </div>
631- </div>
632-
633- <style>
634- .calculator {
635- max-width: 350px;
636- margin: 2rem auto;
637- background: var(--surface-color);
638- padding: 1.5rem;
639- border-radius: 20px;
640- box-shadow: var(--shadow);
641- }
642-
643- .calc-display {
644- background: var(--bg-color);
645- padding: 2rem;
646- border-radius: 15px;
647- font-size: 2.5rem;
648- text-align: right;
649- margin-bottom: 1rem;
650- min-height: 80px;
651- display: flex;
652- align-items: center;
653- justify-content: flex-end;
654- word-break: break-all;
655- }
656-
657- .calc-buttons {
658- display: grid;
659- grid-template-columns: repeat(4, 1fr);
660- gap: 0.75rem;
661- }
662-
663- .calc-btn {
664- padding: 1.5rem;
665- font-size: 1.5rem;
666- border: none;
667- border-radius: 15px;
668- cursor: pointer;
669- transition: var(--transition);
670- font-weight: 600;
671- }
672-
673- .calc-btn.number {
674- background: var(--surface-color);
675- border: 2px solid var(--border-color);
676- color: var(--text-color);
677- }
678-
679- .calc-btn.operator {
680- background: var(--primary-color);
681- color: white;
682- }
683-
684- .calc-btn.equals {
685- background: var(--success-color);
686- color: white;
687- }
688-
689- .calc-btn.clear {
690- background: var(--danger-color);
691- color: white;
692- }
693-
694- .calc-btn:hover {
695- transform: scale(1.05);
696- }
697-
698- .calc-btn.span-2 {
699- grid-column: span 2;
700- }
701- </style>
702- ` ;
703- }
704-
705- function initCalculator ( ) {
706- const display = document . getElementById ( "calcDisplay" ) ;
707- if ( ! display ) return ;
708- let expression = "" ;
709-
710- function update ( ) {
711- display . textContent = expression || "0" ;
712- }
713-
714- function format ( expr ) {
715- return expr
716- . replace ( / ÷ / g, "/" )
717- . replace ( / × / g, "*" )
718- . replace ( / \^ / g, "**" ) ;
719- }
720-
721- function safeEval ( expr ) {
722- try {
723- if ( ! expr ) return "" ;
724- let result = eval ( format ( expr ) ) ;
725- if ( result === undefined ) return "" ;
726- if ( isNaN ( result ) ) return "Error" ;
727- return String ( result ) ;
728- } catch {
729- return "Error" ;
730- }
731- }
732-
733- function applyFunction ( type ) {
734- try {
735- let value = eval ( format ( expression || "0" ) ) ;
736- let result ;
737- switch ( type ) {
738- case "sin" : result = Math . sin ( value ) ; break ;
739- case "cos" : result = Math . cos ( value ) ; break ;
740- case "tan" : result = Math . tan ( value ) ; break ;
741- case "sqrt" : result = Math . sqrt ( value ) ; break ;
742- case "square" : result = value * value ; break ;
743- case "inv" : result = 1 / value ; break ;
744- }
745- if ( isNaN ( result ) ) return "Error" ;
746- return String ( result ) ;
747- } catch {
748- return "Error" ;
749- }
750- }
751-
752-
753- function clearIfFinished ( ) {
754- if ( expression === "Error" || expression === "NaN" ) {
755- expression = "" ;
756- }
757- }
758-
759- document . querySelectorAll ( ".calc-btn" ) . forEach ( ( btn ) => {
760- btn . addEventListener ( "click" , ( ) => {
761- clearIfFinished ( ) ;
762-
763- const value = btn . dataset . value ;
764- const action = btn . dataset . action ;
765-
766- if ( value !== undefined ) {
767- if ( value === "." ) {
768-
769- const lastOperand = expression . split ( / [ \+ \- \* \/ \^ \( \) ] / ) . pop ( ) ;
770- if ( lastOperand . includes ( "." ) ) return ;
771- }
772- expression += value ;
773- update ( ) ;
774- return ;
775- }
776-
777- if ( ! action ) return ;
778-
779-
780- switch ( action ) {
781- case "clear" :
782- expression = "" ;
783- break ;
784- case "delete" :
785- if ( expression === "Infinity" || expression === "-Infinity" ) {
786- expression = "" ;
787- } else {
788- expression = expression . slice ( 0 , - 1 ) ;
789- }
790- break ;
791- case "=" :
792- expression = safeEval ( expression ) ;
793- break ;
794- case "sin" :
795- case "cos" :
796- case "tan" :
797- case "sqrt" :
798- case "square" :
799- case "inv" :
800- expression = applyFunction ( action ) ;
801- break ;
802- case "^" :
803- case "+" :
804- case "-" :
805- case "*" :
806- case "/" :
807-
808- const lastChar = expression . slice ( - 1 ) ;
809- if ( [ "+" , "-" , "*" , "/" , "^" ] . includes ( lastChar ) ) {
810- expression = expression . slice ( 0 , - 1 ) + action ;
811- } else {
812- expression += action ;
813- }
814- break ;
815- default :
816- expression += action ;
817- }
818- update ( ) ;
819- } ) ;
820- } ) ;
821-
822- document . addEventListener ( "keydown" , ( e ) => {
823- const key = e . key ;
824- if ( ! document . getElementById ( "calcDisplay" ) ) return ;
825-
826- // Whitelist allowed keys to prevent typing letters
827- const allowedKeys = [ "Enter" , "Backspace" , "Escape" , "=" , "+" , "-" , "*" , "/" , "^" , "." , "(" , ")" ] ;
828- if ( allowedKeys . includes ( key ) || / ^ [ 0 - 9 ] $ / . test ( key ) ) {
829- e . preventDefault ( ) ;
830- } else {
831- return ;
832- }
833-
834- clearIfFinished ( ) ;
835-
836- if ( / ^ [ 0 - 9 ] $ / . test ( key ) ) {
837- expression += key ;
838- } else if ( key === "." ) {
839- const lastOperand = expression . split ( / [ \+ \- \* \/ \^ \( \) ] / ) . pop ( ) ;
840- if ( ! lastOperand . includes ( "." ) ) {
841- expression += "." ;
842- }
843- } else if ( [ "+" , "-" , "*" , "/" , "^" ] . includes ( key ) ) {
844- const lastChar = expression . slice ( - 1 ) ;
845- if ( [ "+" , "-" , "*" , "/" , "^" ] . includes ( lastChar ) ) {
846- expression = expression . slice ( 0 , - 1 ) + key ;
847- } else {
848- expression += key ;
849- }
850- } else if ( key === ")" || key === "(" ) {
851- expression += key ;
852- } else if ( key === "Enter" || key === "=" ) {
853- expression = safeEval ( expression ) ;
854- } else if ( key === "Backspace" ) {
855- if ( expression === "Infinity" || expression === "-Infinity" ) {
856- expression = "" ;
857- } else {
858- expression = expression . slice ( 0 , - 1 ) ;
859- }
860- } else if ( key === "Escape" || key . toLowerCase ( ) === "c" ) {
861- expression = "" ;
862- }
863- update ( ) ;
864- } ) ;
865-
866- update ( ) ;
867- }
596+ // Calculator module is in js/projects/calculator.js.
868597
869598// ============================================
870599// FIBONACCI
0 commit comments