Accessing HTML unordered list elements in PHP - php

I'm trying to access unordered list elements in php so I can insert them in a database, I need to be able to access them via position but I'm not sure how to do this in PHP. I'm using jQuery so that the list is sortable on the client side.
In Javascript it would be accessed with
alert($("#sortable li:first").text() + ' is first ' + $("#sortable li:eq(1)").text() + ' is second ' + $("#sortable li:eq(11)").text() + ' is last');
The list I'm using is on http://jsfiddle.net/mMTtc/
I'm simply looking for help as for how to store those list items in a php variable i.e. lets say I wanted the 6th element based on how the user had ordered the list.
How would I do this?
Thanks

Using the following code you can send updates to the PHP backend as the user changes the order of elements in the front-end:
$("#sortable").on("sortupdate", function() {
var dataArr = [];
$("#sortable li").each(function(idx, elem) {
dataArr[idx] = $(elem).html();
});
var dataStr = '{"newOrder":' + JSON.stringify(dataArr) + '}';
$.ajax({
url: "<url_to_php_file>",
data: dataStr
});
// alert(dataStr);
});
Live example (frontend part): here
You'll have to replace <url_to_php_file> with the path to your PHP file that does the processing of the elements order (i.e. saving them in the DB). The file will be able to access the user-defined order in a normal PHP Array, using json_decode($_POST["newOrder"]), i.e.
...
$newOrder = json_decode($_POST["newOrder"]);
for ($i = 0; $i < count($newOrder); $i++) {
echo("The item labeled '" . $newOrder[$i] . "' is placed by the user at index " . $i . ".\n";
/* 1st item: index 0 */
/* 2st item: index 1 */
/* ... */
}
Example:
You present a sortable list to the user, containing items: item1, item2, item3 (in this order).
The user places item2 before item1, at which point an AJAX call is made passing to the server the array ["item2", "item1", "item3"] (note the order). The above snippet would echo:
The item labeled 'item2' is placed by the user at index 0.
The item labeled 'item1' is placed by the user at index 1.
The item labeled 'item3' is placed by the user at index 2.
(Of course, instead of echoing anything, you would update the value of an index-field in the DB for each item or do something useful.)

You can use DomDocument to parse your HTML. This can be done either via a string using loadHTML(), or loading an external HTML file using loadHTMLFile().
This example uses loadHTML():
<?php
$html = '<html>
<body>
<ul id="sortable">
<li class="ui-state-default">1</li>
<li class="ui-state-default">2</li>
<li class="ui-state-default">3</li>
<li class="ui-state-default">4</li>
<li class="ui-state-default">5</li>
<li class="ui-state-default">6</li>
<li class="ui-state-default">7</li>
<li class="ui-state-default">8</li>
<li class="ui-state-default">9</li>
<li class="ui-state-default">10</li>
<li class="ui-state-default">11</li>
<li class="ui-state-default">12</li>
</ul>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</body>
</html>';
$dom = new DomDocument;
$dom->loadHTML($html);
$li = $dom->getElementsByTagName('li');
// Print first item value
echo $li->item(0)->nodeValue;
// Print third item value
echo $li->item(2)->nodeValue;

Here's what I'd do, and it's certainly not the cleanest way, but it should work.
This assumes you're working with your own pages, and not the scenario where you're getting the page html via http request to some external site (e.g. via CURL) and needing to parse it. DOMDocument serves just fine for the latter case. This solution is for the former, as I'm assuming that since you're working with javascript on the client-side of it, it's probably your own page (unless you're injecting that javascript into the page after it's loaded).
First of all, inside each list item, I'd include a server-side accessible input tag. It will serve to keep track of the position and value, and pass it to the server-side script on form submission.
<form method="POST">
<ul id="sortable">
<li class="ui-state-default">1
<input id="the_list_item_1" name="the_list_item[]" type="text" value="1_0" style="display: none;">
</li>
...
</ul>
</form>
The value is the item's actual value (the example had them ranged 1 - 12) and it's position separated by an underscore (value + "_" + position);
The list needs to be inside a form variable if you only need to submit the list to the server for processing when the user's done. However, if you intend to only use Ajax to get that data to the server, this solution isn't really necessary (as you'd simply just use jquery to get each position and value pair and send them directly in your ajax call).
You'll need to handle updating these input tags as the user drags items and changes the ordering of the list. See here if you need to know how to work with the sortable events. Perhaps, on update, for each list item call this function with the new position:
function update_pos(value,pos)
{
$("#the_list_item_"+value).val(value+"_"+pos);
}
So on form submit, we're now on the PHP side.
$list_items = $_POST["the_list_item"]; // This is basically an array of all the list_items, thanks to naming all the list items with "the_list_item[]", note the empty subscript (square braces).
$ordered_list_items = array(); // Let's push them into an associative array.
foreach($list_items as $li)
{
$li_split = explode("_",$li);
if(count($li_split) <= 0)
continue; // maybe you'd want to handle this situation differently, it really shouldn't happen at all though. Here, I'm just ignoring nonsensical values.
$item_id = $li_split[0];
$pos = $li_split[1];
$ordered_list_items[$item_id] = $pos;
}
// Then later you can shoot through this list and do whatever with them.
foreach($ordered_list_items as $item_id => $pos)
{
// postgres perhaps. Insert if not already there, update regardless.
pg_query("insert into the_list_item (item_id,position) select '$item_id','$pos' where '$item_id' not in (select item_id from the_list_item where '$item_id' = item_id limit 1));
pg_query("update the_list_item set position = '$pos' where item_id = '$item_id'");
}
Of course, all that said, depending on your needs you may need to be reloading this data onto the page. So looping through your db results (perhaps, for that user), you'd output each list_item into place.
$list_items = pg_fetch_all(pg_query($sql)); // $sql needs to be the query to get the results. Probably should order by position ascending.
$lic = count($list_items);
?>
<html> and stuff
<form method="POST">
<ul id="sortable">
<?php
for($i = 0; $i < $lic; $i++)
{
$li = $list_items[$i];
echo "<li class=\"ui-state-default\">".$li["item_id"]."<input id=\"the_list_item_".$li["item_id"]."\" name=\"the_list_item[]\" type=\"text\" value=\"".$li["item_id"]."_".$li["position"]."\" style=\"display: none;\"></li>";
}
?>
</ul>
</form>

Related

Display loop data in sorted manner

I want to display <li> where, I am having issue with my loop, see my code below
<?php
for ($j=0;$j<$task_count;$j++)
{
$task_name = $task[$j]['summary'];
$summary_length = strlen('');
$task_id = $task[$j]['_id'];
$task_status = $task[$j]['status'];
$summary_count = strlen($task_name);
if ($task_name=='task') {
$final_task_summary = $task_id ;
}
elseif($summary_count <= 50)
{
$final_task_summary = $task_name;
}
else
{
$final_task_summary = mb_substr($task_name, 0, 50);
}
?>
Here, I want to display <li> </li> in order where first it shows <li> having status "open" then "resolved" and then "close" and only 20 <li> should take place.
If I understand correctly, you want to:
Print list items for the first 20 items.
Printing should be done ordered based on status.
If you're getting the data from a database, then it would be better to handle this in the query, If not, you can do as follows.
Change your loop to get only 20 items instead of task count
Declare three strings to hold li items for each status.
Within the loop, Check for the status and append the desired string with li items.
After the loop, print the three strings in the required order.
Let me know if anything needs clarification.
Thanks,

Can you put multiple elements in an html <a> tag?

Is there any way to create a new a href that remembers all the submitted data earlier. I don't know how to say it properly so I will describe in the code:
The first button
Click me
After the user clicks it, he is redirected to the same page but with the new button :
Click me
And so on :
Click me
How do i create the n variable to be added and increased after the button is pressed ?
( I have a table displayed from a database by using the while command with mysqli_fetch_array($database); )
The table is created like (trivial ) :
$retrieve_items = mysql_query("SELECT * FROM items WHERE id > 0");
$col = 0;
echo '<table width=100% border= 1><tr>';
while($row = mysql_fetch_array( $retrieve_items )) {
$col ++;
echo '<td>'.$row['name_item'].'</td>';
if ($col % 5 == 0 )
{
echo '</tr><tr>';
}
}
echo '</tr></table>';
I recommend not to try managing numbered variable names. If there is no important reason to do so, it will make your logic unnecessarily complicated.
PHP understands array parameters in e.g. $_GET. They are passed from HTML with empty braces appended to the parameter name.
This is a little demo to illustrate this alternative approach:
<?php
// get the passed array or generate a new one
$n = isset($_GET['n']) ? (array) $_GET['n'] : [];
//ppend 2 random numbers
$n[] = rand(1,100);
$n[] = rand(1,100);
//output the link with GET parameters in query
?>
the link
<!-- or let PHP's built-in generate a propper query --><br>
the link
Be aware, that the second link generated by http_build_query contains indexes of the array, which are commonly based on 0.
in php, to access the current query String, you can use
$_SERVER['QUERY_STRING']
so you could so something like
Click me
or you could replace your previous value in the query string

Writing PHP variable based on jQuery calculations and displaying predetermined value

Context:
I'm trying to make an automatically generated list that has a different amount of items on each page. Each item needs a name and a link, based on its place on the list. Here's an example with two items for the problematic part:
PHP variables:
$item_link_1 = "link1";
$item_name_1 = "first item";
$item_link_2 = "link2";
$item_name_2 = "second item";
jQuery:
$("#items").each(function(i) {
$(this).find("a").attr("href", "<?php echo $item_link_"+ ++i +";?>");
});
$("#items").each(function(i) {
$(this).find("a").text("<?php echo $item_name_"+ ++i +";?>");
});
HTML output:
<div id="items">
first item
second item
</div>
Problem:
Obviously, $item_name_"+ ++i +"; will never work. I need a way to add the number generated by jQuery to the end of the variable and echo this new variable.
So, if it's the 4th item, the variable will be $item_name_4. The value of this variable (set manually) will be displayed by jQuery with the text() function.
At least that's my idea for how to automate the process. If there's a way to do this, please tell me. If you know a better way, please tell me.
The problem your having is the difference between server-side processing and client-side processing.
An easy way to think about this is that PHP is handled before the HTML is even put on the screen replacing all the PHP parts with their variable contents. meaning that adding that php text with a client-side language like javascript won't be able to execute the php code and achieving the results you're after.
Luckily your example can be done explicitly in php:
<?php
$links = array(
array('link' => "Link1", 'name' => "first item"),
array('link' => "Link2", 'name' => "second item")
);
?>
<div id="items">
<?php for($i = 0; $i < count($links); $i++){ ?>
<?php echo $links[$i]['name']; ?>
<?php } ?>
</div>

Only add item as needed in PHP array

I have bits of code I want to throw in to my site, and provisioned a space right after <body> using 'flairs' (divs) that sit outside the design. Here's the code:
//Add Flair Containers as needed
if($flairs>0){
echo "<!--Flair Graphics (if needed)-->\n";
while($fQty = --$flairs+1){ //-- subracts 1, +1 accounts for 1 being 0
$flair = array($flair1, $flair2, $flair3);
foreach($flair as $flairCode){
echo "<div id=\"flair-".$fQty++."\">".$flairCode."</div>\n";
};
};
};
It prints correctly, where content = $flair1, $flair2, and so on.
<div id="flair-1">Content1</div>
<div id="flair-2">Content2</div>
<div id="flair-3">Content3</div>
But if $flair2/$flair3 is empty, it still prints a div. How can I fix this?
Within your foreach loop you can check if the value is empty and continue (i.e. skip) to the next value if it is.
Like so:
if($flairs>0){
echo "<!--Flair Graphics (if needed)-->\n";
while($fQty = --$flairs+1){ //-- subracts 1, +1 accounts for 1 being 0
$flair = array($flair1, $flair2, $flair3);
foreach($flair as $flairCode){
if (empty($flairCode)) continue;
echo "<div id=\"flair-".$fQty++."\">".$flairCode."</div>\n";
};
};
};
I suspect that you could simply prepend if($flairCode) to your echo statement. That would make your inner loop:
foreach($flair as $flairCode){
if($flairCode) echo "<div id=\"flair-".$fQty++."\">".$flairCode."</div>\n";
};
Some points to note:
Since the $flair array will always be the same, construct it outside of the loop (this will let you evaluate the condition only once too.
Using $fQty++ is not enough to guarantee unique ID's, especially since every time it hits the while the value is reset. I suggest $fQty should not be part of the while condition and simply stay as an independent tally.
Stop using double-quotes. They're slow.

To make an action based on the link location by jQuery

How can you retrieve the value of the rel attribute of a given link and pass it to the handler?
I have a list of links such that
Link list
<div id='one_answer'>Answer1
<a href="$" class="delete_answer" rel='Answer1'>delete</a>
</div>
<div id='one_answer'>Answer2
<a href="$" class="delete_answer" rel='Answer2'>delete</a>
</div>
<div id='one_answer'>Answer3
<a href="$" class="delete_answer" rel='Answer3'>delete</a>
</div>
These links are generated by the following code.
The following value of the rel does not seem to be passed to the handler.
Links generated by PHP
echo ($answer . "<a href='#'"
. "class='delete_answer'"
. " rel='" . $body . "'" // I identify the answer
// by the body of the answer
// in the database
. ">delete</a>"
);
The user clicks the second link.
The rel attribute should pass the answer to the handler.
jQuery should perform the following action based on the POST -data.
jQuery
jQuery('a.delete_answer').live('click', function(){
jQuery.post('/codes/handlers/delete_an_answer.php',
{ delete_answer: jQuery(this).attr('rel') },
function(){
$("#one_answer").removeClass("yellow");
})
});
The file delete_an_answer.php
$dbconn = pg_connect("host=localhost port=5432 dbname=masi user=masi password=123");
// remove the answer
$result = pg_query_params ( $dbconn,
'DELETE FROM answers
WHERE answer = $1',
array ($_POST['answer'] ) // Problem here, because
// $_POST['answer'] is empty when it gets here
// so no answer is deleted
);
I fetch answers from Postgres and put at the same time the value of the rel attribute to be $body.
I can see several problems with this code:
You have more than one <div id='one_answer'>. IDs should be unique, so $("#one_answer").removeClass("yellow"); will always select the first div, not all divs.
delete_an_answer.php - In the php you're looking for $_POST['answer'], but the ajax has {question_id: jQuery(this).attr('rel')}.
The links in your sample don't have a rel, and href='$', which is weird. Also <div id='one_answer> is broken, should be another single quote. I assume these are copy-paste problems.
Ok, well... To answer your first question, you can get the index of the element that was clicked within the array of elements matching a given selector using jQuery's index() method:
$('a.delete_answer').live('click', function()
{
var index = $("a.delete_answer").index(this);
// index will be 0 for the first matching link,
// 1 for the second, and so on. Do what you will with this...
...
});
As for the rest of your question, I really have no idea what it is you're asking.

Categories