Jump to content

kicken

Gurus
  • Posts

    4,695
  • Joined

  • Last visited

  • Days Won

    177

Everything posted by kicken

  1. You can generate whatever HTML you want and swap it out using the JS code. The HTML structure in my example is how I'd probably code it, but nothing about it is required. You'd need to adjust the JS to match up with whatever your final HTML is with regards to the classes/IDs etc. There are a variety of ways to handle the next question bit. You could include a link to the next question when loading the current question. You could load a list of question IDs when the page first loads and use JS to walk the list. You could load the questions by a display number (1, 2, 3, ...) and just keep incrementing it until you get a 'No more questions' response. Since you already have code to load a question by it's ID, one of the first two options might be easiest to implement. The first option would keep you coding mostly in PHP by just returning a link for the JS to follow. The second involves a little more JS work to walk the list of question IDs.
  2. The main issue with your code is how you're trying to find the days element. To explain a bit, lets look at how your HTML gets rendered: <div class='month-container'> <div class='days' id='Vendémiaire'> <div class='day'>1<span class='name'>Raisin</span></div> <div class='day'>2<span class='name'>Safran</span></div> <div class='day'>3<span class='name'>Châtaigne</span></div> <div class='day'>4<span class='name'>Colchique</span></div> <div class='day'>5<span class='name'>Cheval</span></div> </div> <div class='month'>Vendémiaire</div> </div> You are attaching your click handler to the div.month element. That means in your click handler, el is going to reference that element. To try and find the days element, you are looping over the nextElementSibling property until there are no more siblings. Think about that for a moment. nextElementSibling is going to find the elements that come after the current element. What comes after div.next? Nothing. You need to be looking at the previous siblings, using prevElementSibling. Now, once you find your days element, you have another problem. You are testing if it's style.display value is equal to "none". One might think this should be true since you have applied display: none; in your css, but it's not. The reason is that the style properties on the element only refer to styles applied directly to that element via a style="" attribute, not anything inherited via css selectors. Since no direct style was applied to your element, the style.display will be the empty string, fail your condition, and you'll set it to display. On a second click, it would pass and you'd set block and your toggle would start working. Reversing the conditional would fix this double-click issue. --- Now that the issues have been pointed out, there are other things of note and also general ideas that should be applied to make this better. You have both an onclick="" attribute and an addEventListener call on your month elements. You should only have one, and the preferred method is to use addEventListener in your code and stop using the on* attributes. It should be removed, notice I didn't include it in my example html above. Your loop to find the days element is unnecessary. The way your HTML is structured, the days element will be simply el.prevElementSibling, no looping required. If you want to add other elements between your month div and the days elements, a better approach would be to use querySelector on the parent element: el.parentElement.querySelector('.days'); Dealing with style properties directly should generally be avoided if possible. Changing the applied classes is a better approach. For something like this, create another class that sets display to block which can be applied to your days element. You can then use javascript to toggle this class on and off. .days.visible { display: block; } days.classList.toggle('visible'); You can view the above suggestions implemented in this demo fiddle.
  3. If you're not interested in storing results for the quiz, then probably the easiest approach would be to just dump out all the questions when the initial page loads, then use some JavaScript to display them one at a time. That removes the complexity of dynamically loading the questions. Either way though, step 1 is just getting your JavaScript sorted out for marking your correct/incorrect answers and showing the next button. That's the same whether you load the questions dynamically or all at once. You need a way in your HTML to indicate which answer is correct, then attach some on click handlers to your answer divs that checks if the one they clicked is correct or not and updates the display accordingly. Here's an example of loading all the questions at once, then displaying them one at a time. HTML: <div id="quiz"> <div class="question active"> <p> In the movie "Father of the Bride", George Banks played by Steve Martin goes to jail for opening up what food in the supermarket? </p> <ul class="answers"> <li>Burger buns</li> <li data-correct>Hot dog rolls</li> <li>Sausages</li> <li>Twinkies</li> </ul> </div> <div class="question"> <p> Some second example question </p> <ul class="answers"> <li>Answer 1</li> <li>Answer 2</li> <li>Answer 3</li> <li data-correct>Answer 4</li> </ul> </div> <div class="buttons"> <button type="button" id="next-question"> Next question </button> </div> </div> JS: window.addEventListener('DOMContentLoaded', () => { const quiz = document.getElementById('quiz'); document.getElementById('next-question').addEventListener('click', nextQuestion); for (let question of document.querySelectorAll('.question')){ setupQuestion(question); } function setupQuestion(question){ const answers = question.querySelector('.answers'); answers.addEventListener('click', (e) => { if (e.target.nodeName!=='LI' || quiz.classList.contains('answered')){ return; } e.target.classList.add('selected'); quiz.classList.add('answered'); }); } function nextQuestion(){ const activeQuestion = document.querySelector('.question.active'); const nextQuestion = activeQuestion.nextElementSibling; if (nextQuestion.classList.contains('question')){ activeQuestion.classList.remove('active'); nextQuestion.classList.add('active'); quiz.classList.remove('answered'); } } }); CSS: /** Base styles */ .buttons { visibility: hidden; text-align: center; } .question { display: none; } .question.active { display: block; } .answers { list-style-type: none; display: grid; grid-template-columns: auto auto; grid-gap: 20px; } .answers > li { border: 2px solid black; text-align: center; padding: 10px 0; } .answers > li:hover { background-color: #888; } /** Styles for when the question has been answered */ .answered .buttons { visibility: visible; } .answered .answers .selected { background: #f88; } .answered .answers .selected::before { display: inline-block; content: '\274c'; } .answered .answers [data-correct] { background-color: #8f8; } .answered .answers [data-correct]::before { display: inline-block; content: '\2705'; }
  4. Does the problem happen if you use a desktop browser's responsive design tools, or only on the physical device?
  5. If I am understanding the problem right, then it sounds like there's some element on the page that cannot be scaled down so the entire page gets scaled down so that element will fit. Examples could be form elements or images with set widths. My site for example has a couple pages with textarea elements that cause the page to not display scaled down on mobile. Adding width: 100% to them in the mobile styles would fix it, I just haven't done it.
  6. This is something from the days of Internet Explorer. It will not work on any modern browser. If you want to use a local database, use IndexedDB.
  7. It'd be easier to handle this if you restructure the code to separate gathering the query results, and displaying your output. The problem you have currently is trying to determine whether or not you displayed anything after the loop. That could be done somewhat easily by just adding an extra variable, but it's messy. Much cleaner to check before trying to output stuff, and that also gives you greater control over the output. //Assume no results. $results = []; $questionId = $_GET['question'] ?? ''; if ($questionId){ //Only run the query if we have an id. $sql = "SELECT q.question, o.choice, q.image FROM questions q JOIN quiz_options o ON q.qid = o.qid WHERE q.qid = :id;"; $stmt = $pdo->prepare($sql); $stmt->execute(['id' => $questionId]); //Fetch all the result rows $results = $stmt->fetchAll(PDO::FETCH_NUM); } //If we have any results if ($results){ //Display them $last_q = 'x'; // a non-existent value $choice_num = 0; foreach ($results as [$q, $c, $i]){ if ($q <> $last_q) // starting a new question so close the last div and begin a new one { if ($last_q <> 'x') // is this the first question? If not, close the last question's box { echo "</div>"; } echo "<div class='quizContent'>"; // start the new question box echo "<p>$q</p>"; // show the question - figure out later how to prevent repetition (which I did earlier) $pathx = "images/db_images/"; echo '<img class="picture" src="' . $pathx . $i . '">'; $choice_num = 0; // new question; new choice count } $choice_class = 'choice' . $choice_num; // setup the appropriate choice class $last_q = $q; // remember the current question //echo "<p>$q</p>"; // show the question - figure out later how to prevent repetition (which I did earlier) echo "<div class='$choice_class'>"; // a box for this choice echo "<p>$c</p>"; echo "</div>"; // close this choice's box $choice_num++; // bump the choice cnt } echo "</div>"; // close the last question box } else { //Display an error $errorAnswer = 'Question does not exist'; } This does not distinguish between 'ID not passed' and 'ID not found' errors, and I see little reason to do so. If you wanted to do so though, you could by checking $questionId again in the error code.
  8. You can't just stick your PHP code into a JavaScript function like that. By the time your page is rendered in the browser and JavaScript can start doing it's thing, PHP is done. There's no going back for that request. If you want to do more PHP stuff, you have to make a new request in some way, such as via a redirect, a form post, or a background request with fetch(). That new request needs to include whatever information your script will need to perform the appropriate action. A good way to pass this information along is with data attributes on your HTML elements. Here is a quick example of making a request and taking some action according to the response. fetch('/the/url/to/request', {method: 'post', body: 'the content to send'}).then(function(response){ //Check if the response is successful. if (response.ok){ //Decode JSON body of the response. return response.json(); } else { throw new Error(response.statusText); } }).then(function(data){ //Consume the JSON response data to do something if (data.complete){ e.target.disabled = true; } }, function(err){ //Handle any errors. alert('Failed to make request.'); }); When you have your JS making a request on click, then you just need to develop a PHP page for that request to go to. That page will take the data in and call your Set_Checks function.
  9. Yes. Your falling afoul of the common misunderstanding of the line between JavaScript and PHP. onclick and any other such user-interaction mechanism are in the realm of JavaScript, not PHP. JavaScript cannot directly call a PHP function, they are two completely separate things. What JavaScript can do is make a web request to a PHP file, which then calls your PHP function to do whatever needs done. You need modify your onclick handler to call a JavaScript function which will issue a web request to a PHP script with any information required. That PHP then needs to take that information and call your PHP function.
  10. If you want to use /api/houseinfo/1 as your URL, then you need it have that mapped by the server to /api/houseinfo.php?id=1. This is typically done using a URL rewriting feature of your server software. For apache, that is mod_rewrite. Since you're getting a 404 when using /api/houseinfo/1, that implies such rewriting is not taking place. Either you have not configured it, or have configured it incorrectly.
  11. If you're getting a 404 then something about your server configuration is not correct. Probably your URL rewriting configuration is incorrect. Do you get a proper response if you try the url directly, ie: http://localhost/api/houseinfo.php?id=1 Once you've solved that issue and your script is running successfully, you can move on to fixing the JS issue (if it's still an issue at all).
  12. The braces specify a repetition range, like so: {min[,max]}. If you only set the min value then it is an exact count. So what you have says match exactly 5 digits, no more and no less. Presumably, you'd want to instead match between 0 and 5 digits, assuming something like 8M is valid. To do that, you set both values accordingly. \d{0,5}
  13. You are missing a </div> tag. I suspect for the logo_div, but can't be sure. Your translate div is currently a child of your logo div, which doesn't seem correct. You seem to make quite a bit of these basic HTML structure mistakes. You might want to see if you can get better help from your editor in spotting these, or spend more time proof reading your HTML code. For these types of questions, rather than just posting the code it would be preferable if you re-create the problem using something like JSFiddle and provide a link to that. This will make it easier to show what you're seeing and describe what you want instead. I copied your code into a fiddle and attempted to fix the HTML problem, but can't really be sure if the result is the same as what you're seeing. I'm not 100% sure I understand what you want either. My guess is you want the logo to be on the left, the translation widget 20px in from the right, with whatever extra space there is between the two. You can do that by setting justify-content: space-between; on the logo_bar, and margin-right: 20px; (not left) on your translate_div.
  14. padding-top: 250px; Try that on your .nav_div
  15. Unless $return_link is defined somewhere above in that script, that code is still incorrect, but like before PHP doesn't complain too hard about undefined variables. If you have nothing to pass for that parameter, try either null or the empty string (''). <?php echo php_file_tree($FileLocations["tracy"], '', array("gif", "jpg", "jpeg", "png","pdf", "zip", "xlsx")); ?>
  16. Fundamentally you'd use PHP to host a websocket server which will connect to whatever VNC server and relay the data back to the browser. Your JS would then connect to that websocket server to receive the VNC data and present it. I wrote something like this many years ago to toy around with websocket's when they were first being introduced. I doubt the code still works, but if your interested you can look at it.
  17. position: fixed Setting the position to fixed takes the element out of the normal document flow. That means it does not actually take up space, and instead acts as a separate floating layer. Since it doesn't take up space, your nav bar then becomes the "first" thing in the document, thus showing at the top below your top bar "layer". What you need to do then, is create some space where your top bar should be, such as by giving your body element a top margin (or maybe padding) the same height as your top bar.
  18. Then the script was fundamentally broken on PHP 7.3 as well. The difference is just that PHP 7.3 didn't complain about this mistake as hard. In 7.3 the error would trigger a warning, but your configuration probably did not show those. PHP 8 treats it as a full error now, since the code is improper. So to fix it, you need to either figure out why $return_link is an array, or change the logic to match the previous behavior. The invalid array access would have resulted in a null value on 7.3, making the str_replace do nothing so you might just be able to replace the line with this: $slfile=$directory."/".$this_file; But that is assuming the function is always used incorrectly. If $return_link is valid sometimes, then you will need to do more debugging.
  19. There is a syntax error because I accidentally used a colon instead of semi-colon. If you only get a generic 500 error for such errors, you might want to look into adjusting your development environment to show proper error messages so it's easier to resolve such problems.
  20. All your cookie code there is redundant. session_start manages its own cookie, you don't need to do it yourself. You can control the SameSite value either using the configuration option session.cookie_samesite or the session_set_cookie_params function (before calling session_start). Example: session_set_cookie_params([ 'lifetime' => 0 , 'path' => '/' , 'domain' => '.site.com' , 'secure' => true , 'httponly' => true , 'samesite' => 'Lax' ]): session_start();
  21. That it still not enough information. $return_link is a function parameter, so you need find where the function is being called and determine what value it is being called with and why.
  22. The default height of the body and html elements is not 100%, it's as high as they need to be for the content they contain. If you want them to be 100%, you need to specify that. html, body { height: 100%; }
  23. The error is due to $return_link being some non-scalar value, such as an array or an object. You need to find where $return_link is defined and why it's not a scalar value. There's not enough information in the code given to determine how it should be fixed.
  24. For a basic keyword based search engine, there's nothing really to add to what was shown above. All you need is a list of URLs and the associated keywords. The page table stores details about the page. Each keyword associated with the page gets inserted into the page_keyword table as it's own row. Just to make things slightly more interesting, say you wanted to track of the links a page has. You would add another table storing the ID of the page, an the ID of the linked page. In addition to the above, for each link found in a page, you'd create a new entry in the page table for that link's URL then insert a record in page_link with the original page id and the newly created page id. -- MySQL Script generated by MySQL Workbench -- Thu 13 Apr 2023 12:21:03 AM EDT -- Model: New Model Version: 1.0 -- MySQL Workbench Forward Engineering SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; -- ----------------------------------------------------- -- Table `page` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `page` ( `id` INT NOT NULL AUTO_INCREMENT, `url` VARCHAR(2000) NOT NULL, `title` VARCHAR(100) NOT NULL, `last_accessed` DATETIME NOT NULL, PRIMARY KEY (`id`), UNIQUE INDEX `UQ_page_url` (`url` ASC)) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `page_link` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `page_link` ( `page_id` INT NOT NULL, `linked_page_id` INT NOT NULL, PRIMARY KEY (`page_id`, `linked_page_id`), INDEX `fk_page_link_linked_page_id_idx` (`linked_page_id` ASC), CONSTRAINT `fk_page_link_page_id` FOREIGN KEY (`page_id`) REFERENCES `page` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `fk_page_link_linked_page_id` FOREIGN KEY (`linked_page_id`) REFERENCES `page` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `page_keyword` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `page_keyword` ( `page_id` INT NOT NULL, `keyword` VARCHAR(100) NOT NULL, `points` INT NOT NULL, PRIMARY KEY (`page_id`, `keyword`), CONSTRAINT `fk_page_keyword_page_id` FOREIGN KEY (`page_id`) REFERENCES `page` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB; -- ----------------------------------------------------- -- Data for table `page` -- ----------------------------------------------------- START TRANSACTION; INSERT INTO `page` (`id`, `url`, `title`, `last_accessed`) VALUES (1, 'kicken.com', 'Kickens World', '2023-04-12 23:54:00'); INSERT INTO `page` (`id`, `url`, `title`, `last_accessed`) VALUES (2, 'phpfreaks.com', 'PHPFreaks', '2023-04-12 23:55:00'); INSERT INTO `page` (`id`, `url`, `title`, `last_accessed`) VALUES (3, 'borobhaisab.com', 'Boro', '2023-04-12 23:56:00'); INSERT INTO `page` (`id`, `url`, `title`, `last_accessed`) VALUES (4, 'php.com', 'PHP', '2023-04-12 23:57:00'); COMMIT; -- ----------------------------------------------------- -- Data for table `page_link` -- ----------------------------------------------------- START TRANSACTION; INSERT INTO `page_link` (`page_id`, `linked_page_id`) VALUES (1, 2); INSERT INTO `page_link` (`page_id`, `linked_page_id`) VALUES (3, 2); INSERT INTO `page_link` (`page_id`, `linked_page_id`) VALUES (1, 4); INSERT INTO `page_link` (`page_id`, `linked_page_id`) VALUES (3, 4); INSERT INTO `page_link` (`page_id`, `linked_page_id`) VALUES (2, 4); COMMIT; -- ----------------------------------------------------- -- Data for table `page_keyword` -- ----------------------------------------------------- START TRANSACTION; INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (1, 'usa', 3); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (1, 'phone', 3); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (1, 'apps', 2); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (1, 'tutorial', 2); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (2, 'uk', 1); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (2, 'php', 4); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (2, 'apps', 3); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (2, 'price', 3); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (3, 'tutorial', 3); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (3, 'book', 3); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (3, 'php', 2); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (3, 'usa', 3); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (4, 'PHPs', 5); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (4, 'books', 5); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (4, 'united states america', 5); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (4, 'prices', 5); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (4, 'python', 5); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (4, 'book', 5); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (4, 'apps', 5); INSERT INTO `page_keyword` (`page_id`, `keyword`, `points`) VALUES (4, 'usa', 5); COMMIT; SET SQL_MODE=@OLD_SQL_MODE; SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS; DB Fiddle example.
  25. I'm not going to spend time writing SQL that I don't believe should be written in the first place, but if you insist on pursing this, I'll at least give you a hint. CASE
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.