Adding a javascript function and removing it from the HTML instantly - javascript

I'm trying to add a script element to the HTML from the PHP code and instantly remove it so it won't be visible in the HTML. The script only contains things to execute at the same moment and not functions. Generally, I'm trying to replicate ASP.NETs runat property, so I'll be able to set values of elements (inputs for now) right from the PHP code.
This is what I tried so far (which I found in a different question, with some changes of mine) and it adds the script properly, but won't remove it.
function JSSetValue($id, $value) // Input 'value' only
{
echo '<script>
var input = document.getElementById("' . $id . '");
input.value = "' . $value . '"
</script>';
$html = <<<HTML
...
HTML;
$dom = new DOMDocument();
$dom->loadHTML($html);
$script = $dom->getElementsByTagName('script');
foreach($script as $item)
{
$item->parentNode->removeChild($item);
break;
}
$html = $dom->saveHTML();
}

Thanks for everyone who were trying to help. Anyway, I found a solution to my question, which is this:
function JSSetValue($id, $value) // Input 'value' only
{
echo '<script id="phpjs">
var input = document.getElementById("' . $id . '");
input.value = "' . $value . '";
document.getElementById("phpjs").remove();
</script>';
}
It adds the script and removes it, so it won't be visible when inspecting elements anymore.

Related

IDs not working as expected in a while loop in PHP

I am trying to create a while loop that echoes a button for each $version value. shell_exec() returns a value from a Python file and is responsive to a unique $version value. To that end, the basic goal is to create a page where the quantity of buttons is dependent on the version value.
Then, the user can click any specific button and access data for that one specific button(version). To do this, I tried to mix variables with IDs but it did not seem to work. What can I do to fix this? None of the buttons are responsive right now.
Code:
<?php
while ($version != 0) {
echo '
<br>
<br>
<button id="toggle-' . $version . '">TOGGLE</button>
<div style= "display:none;" id="content-' . $version . '">
';
$command = escapeshellcmd("C:/Python38/python.exe C:/xampp/htdocs/Ensemble/login/test.py $email $version");
$output = shell_exec("$command 2>&1");
echo($output);
echo '
</div>
<script>
var toggle = document.getElementById("toggle-' . $version . '");
var content = document.getElementById("content-' . $version . '");
toggle.addEventListener("click", function() {
content.style.display = (content.dataset.toggled ^= 1) ? "block" : "none";
});
</script>
'
;
$version--;
}
?>
Edit
A new issue arose. Only one of the buttons work. Both buttons when clicked output the same thing instead of different versions. In SQL all versions are different so this is an error most likely with the html/JS.
Perhaps the following might help - though it is not tested as far as the Python call is concerned but I think the other code should work OK if I understood correctly.
Every ID must be unique in the DOM which I guess is why you tried to make them so by adding the $version number to each. This is not really necessary if you utilise querySelectorAll with a suitable expression. Doing this in conjunction with one or more of the parent/sibling selectors that exists in vanilla javascript allow fairly easy DOM navigation and manipulation. It also means you can use the same piece of code for all the buttons... hope it helps.
<?php
while( $version > 0 ) {
$command = escapeshellcmd( "C:/Python38/python.exe C:/xampp/htdocs/Ensemble/login/test.py $email $version" );
$output = shell_exec("$command 2>&1");
printf('
<br />
<br />
<button data-version="%d">Toggle</button>
<div style="display:none">%s</div>',
$version,
$output
);
$version--;
}
echo "
<script>
Array.from( document.querySelectorAll('button') ).forEach( bttn=>{
bttn.addEventListener('click', function(e){
let version=this.dataset.version;
let div=this.nextElementSibling;
div.style.display=div.style.display=='block' ? 'none' : 'block';
});
})
</script>";
?>
Replace
<div style= "display:none;" "id="content-' . $version . '">
to
<div style= "display:none;" id="content-' . $version . '">
and try.

How to insert a php array with innerHTML in javascript

I would like to be able to insert html code from javascript, which inserts php code that contains an array. What I do is get in the variable $ teams an array of teams. And then I go through the array with a foreach to set the values ​​in the select options
I have done the following but it does not work.
document.getElementById('selectTeam').innerHTML = '<select class="form-control"><?php $teams = ControllerTeam::ctrTeam(); foreach ($teams as $key => $value) { echo '<option value="'.$value["id"].'">'.$value["name"].'</option>';}?></select>';
First problem is that, probably, the content is loaded after the JS so the selector returns null hence the error in the OP code.
Cannot set property 'innerHTML' of null
That means, you should only execute the JS code on window.load or any other similar event that ensures the fact that the HTML is loaded before trying to execute.
Now, for the other issue in the comments, if you rewrite the PHP code like this :
<?php
$teams = ControllerTeam::ctrTeam();
$options_html = '';
foreach ($teams as $key => $value) {
$options_html .= '<option value="' . $value["id"] . '">' . $value["name"] . '</option>';
}?>
And in the JS - make sure it loads on window.load or similar -
document.getElementById('selectTeam').innerHTML =
'<select class="form-control"><?php echo $options_html ?></select>';
This makes the code more readable and helps you debug easier.
There is a typo in your code. Please change it to:
document.getElementById('selectTeam').innerHTML = '<select class="form-control"><?php
$teams = ControllerTeam::ctrTeam();
foreach ($teams as $key => $value) {
echo '<option value="' . $value["id"] . '">' . $value["name"] . '</option>';
}
?></select>';

Expanding the content by click it

When i click the more. I wanted the content should expand. I my page i have about 10 question with more option. The question content is coming through the php script.
<?php
$result = mysqli_query($conn, $query) or die("error: " . mysqli_error($conn));
//fetch the data.
if (mysqli_num_rows($result) > 0) {
while($data = mysqli_fetch_assoc($result)) {
$question = $data['question'];
echo "<span class=\"spanstyle\" id=\"fullquestion\">" . substr($question, 0, 170);
echo "...more</span><br>";
}
}
?>
I try to do that by javascript. ContectExpand() fire of when i click.
<script>
function contentExpand() {
var question = <?php echo $question; ?>;
document.getElementById("content").innerHTML = question;
}
</script>
Problem is, $question is changing the value as it is inside the loop. It doesn't have a fixed value.
Also I want to know that I can do that only along with php without javascipt.
For my solution you need some sort of $data['id'], which is unique for each question.. I think it cannot be done only in PHP, but you should try to use jQuery, it makes javascript much easier
<?php
$result = mysqli_query($conn, $query) or die("error: " . mysqli_error($conn));
//fetch the data.
if (mysqli_num_rows($result) > 0) {
while($data = mysqli_fetch_assoc($result)) {
$question = $data['question'];
echo "<span class='spanstyle' id='shortQuestion{$data['id']}'>" . substr($question, 0, 170).
"...<a href='#' onClick='return contentExpand({$data['id']});'>more</a></span>
<span class='spanstyle' id='longQuestion{$data['id']}'>{$data['question']}</span>
<br>";
}
}
?>
Javascript
<script>
function contentExpand( fullcontentId ) {
document.getElementById('shortQuestion'+fullcontentId).style.display = "none";
document.getElementById('longQuestion'+fullcontentId).style.display = "inline";
return false;
}
</script>
There are several issues with you code. Regarding your question, the most important are:
The while loop is generating several span elements with the same id.
The onClick function should content a reference to the element you want to expand.
You dind't include any code constraining the size of the span element, so there is nothing to be expanded.
How to fix them:
Modify the while loop
Create a $i variable that counts the rows and add it to the span id, to the link id and to the javascript function in this way:
$i = 0;
while($data = mysqli_fetch_assoc($result)) {
$i++;
$question = $data['question'];
echo "<span class='spanstyle' id='fullquestion_" . $i. "' >";
echo "<a href='#' id='link_" . $i . "' onClick='contentExpand(" . $i. ");'>more</a> ";
echo $question."</span><br>";
}
Create a javascript function that resize the span element:
You didn't tell us how you want to expand the content. There would be a lot of different ways to achieve it. This is just one that tries to respect your HTML markup, but surely not the best:
<script>
function contentExpand(id) {
var link = document.getElementById('link_'+id);
var span = document.getElementById('fullquestion_'+id);
if(link.innerHTML=='more')
{
link.innerHTML = 'less';
span.style.width = '100px';
}else{
link.innerHTML = 'more';
span.style.width = 'auto';
}
}
</script>
Modify the css of the span element:
A block element like a div would suit better anyway, but maybe you have very good reasons to use a span.
span {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: right;
}
How to do it without javascript (just PHP):
It is certainly possible, but I guess you don't want to do it.
But if still you want to do so, generate the loop with just partial information about the related $question (as you do in the original code, substr($question, 0, 170)) but put the elements inside a form.
When the user click the more span element, submit the form to send from the client back to the server the information about the selected item.
Then, the PHP script would generate again the page but, this time, the selected item will load the full text of the question ($question instead of substr($question, 0, 170)).
So, you will have to make a new HTTP request call (that means to reload the page, AJAX is not an option if you don't want to use javascript).
Doing all this add a new layer of complexity and make it less efficient.
My advice is, if you don't have strong reasons to don't use javascript, use it.

Executing javascript in an an AJAX response - Codeigniter

I am using Codigniter to redo a website. I have the following controller code:
public function get_topics()
{
$topic = $this->input->post('input_data');
$topics = $this->firstcoast_model->get_topics_like($topic);
foreach ($topics as $val) {
echo "<pre id = \"pre_" . $val['id'] . "\">";
echo $val['formula'];
echo "<br />";
// generate a unique javascript file.
$f = "file_" . $val['id'] . ".js";
if (!file_exists($f));
{
$file = fopen($f,"w");
$js = "\$(\"#button_" . $val['id'] . "\").click(function(){\$(\"#pre_" . $val['id'] . "\").hide();});";
fwrite($file,$js);
fclose($file);
}
echo "<script src=\"file_" . $val['id'] . ".js\"></script>";
echo "<button id=\"button_" . $val['id'] . "\">Hide</button>";
echo "</pre>";
}
}
The basic idea to make an AJAX call to the function to retrieve a list of formulas.
The purpose of the javascript is to be able to hide any of the formulas by
hiding the <pre> </pre> tag that surrounds them The js file (i.e. file_1.js) I generate looks like:
$("#button_1").click(function(){$("#pre_1").hide();});
and the button code is:
<button id="button_1">Hide</button>
The problem is that it doesn't work. The files get generated, but clicking on the "Hide"
button does nothing. The puzzling part is that the exact same code works on the original website where I just make an AJAX call to a PHP file that generates the same code.
Any ideas what could be going on here?
Edit:
On my old website I used:
$query = "SELECT * FROM topics WHERE term LIKE '%" . $term . "%'";
$result = mysql_query($query);
while ($val = mysql_fetch_array($result))
{
echo "<pre id = \"pre_" . $val['id'] . "\">";
etc.
etc.
}
and everything works fine. If I now put the results of the while loop into to an array and then do a foreach loop on that, the results are very intermittent. I'm wondering if the foreach loop is the problem.
i think you can return list buttons in json response
public function get_topics()
{
$topic = $this->input->post('input_data');
$topics = $this->firstcoast_model->get_topics_like($topic);
$response = array('buttons' => $topics);
header('Content-Type: application/json');
echo json_encode( $arr );
}
so client can parse which button element to be hide.
<script type="text/javascript">
$(document).ready(function(){
$('somEL').on('submit', function() { // This event fires when a somEl loaded
$.ajax({
url: 'url to getTopics() controller',
type : "POST",
data: 'input_data=' + $(this).val(), // change this based on your input name
dataType: 'json', // Choosing a JSON datatype
success: function(data)
{
for (var btn in data.buttons) {
$(btn).hide();
}
}
});
return false; // prevent page from refreshing
});
});
</script>

Why wont javascript get values of php generated html?

im using ajax to query my mysql to my database.
But im stock at issue with my php generated html form input - javascript/jquery will simply not pick up the value. From normal html is no issue of course.
php (works fine, all echos are good)
<?php
function getAge() {
$age = "<select name='age'>";
$result = $mysqli->query("select * from ages");
while ($row = $result->fetch_row()) {
$age.="<option value=" . $row[0] . ">". $row[1] ."</option>";
}
$age.="</select>";
return $age;
}
?>
html
<form id="myform">
<input name='name' value='Nick'>
<input name='sport' value='Football'>
<?php echo getAge(); ?>
<input type='submit'>
</form>
javascript
$("form#myform").on('submit', function(e){
e.preventDefault();
var json = {}
$.each(this.elements, function(){
json[this.name] = this.value || '';
});
}
Everything works well except it wont get the value of the <select>. If i make a normal html select it works.. ?!
Also anybody know how to delete the submit button from the json object? :-)
Any dynamically generated HTML will not have the events applied to them, as those events are applied on page load. So if you apply the events to the document, you will be able to pull values from dynamically generated html. Like so:
var json = {};
$(document).on('submit', 'form#myform', function(e){
$('*', this).each(function(){
json[$(this).attr('name')] = $(this).val();
});
});
Hope this helps!
change this line:
$age.="<option value=" . $row[0] . ">". $row[1] ."</option>";
to this:
$age.="<option value='" . $row[0] . "'>". $row[1] ."</option>";
//----------------^---------------^------put quotes
And i think you can make use of .serializeArray() which does the same you want but in a different way like multiple objects with multiple [{ name : value}] pairs:
$(function(){ //<-----put this block too
$("form#myform").on('submit', function(e){
e.preventDefault();
var json = $(this).serializeArray();
}); //<----checkout the closing
}); //<---doc ready closed.

Categories

Resources