I have a custom component being used on a Joomla 3.9 site.
The below code creates hyperlinks with proper anchors ( for 2 pages ) from a database and works OK except that it's also creating irrelevant hidden links.
You can only see the href links if you view the source of the page.
i.e.
What can I try here to make sure the code doesn't create these hidden links?
else:
JFactory::getDocument()->addStyleDeclaration('#media (max-width:540px){table.all-regions tr td{width: 100% !important;display: inline-block !important;text-align: center !important;}}');
$regionsList = '';
$regionsList .= '<table class="all-regions">';
$regions = $this->get('regions');
for($i = 0;$i <= count($regions); $i+=3):
$regionsList .= '<tr>';
$regionsList .= '<td style="width: 1%;padding: 9px; line-height: 24px;">'.$regions[$i]->region_name.'</td>';
$regionsList .= '<td style="width: 1%;padding: 9px; line-height: 24px;">'.$regions[$i+1]->region_name.'</td>';
$regionsList .= '<td style="width: 1%;padding: 9px; line-height: 24px;">'.$regions[$i+2]->region_name.'</td>';
$regionsList .= '</tr>';
endfor;
$regionsList .= '</table>';
$text = JString::str_ireplace('{%regions_list%}', $regionsList, $this->article->text);
$this->setBreadcrumbs(
array(
'country'
)
);
endif;
echo $text;
Details that may or may not help:
One page shows 3 hidden links and the other 2 hidden links. The hidden links point to the same page I'm currently on. The page with 3 hidden links is showing 3 even columns of links while the one with 2 hidden links has one row with 5 links and the other 2 rows with 4 links
There are better ways to do this whole thing, but without rewriting the code, you need to see if those elements are set and aren't empty or else you will get empty anchors:
if(!empty($regions[$i]->region_name)) {
$regionsList .= '<td style="width: 1%;padding: 9px; line-height: 24px;">'.$regions[$i]->region_name.'</td>';
}
if(!empty($regions[$i+1]->region_name)) {
$regionsList .= '<td style="width: 1%;padding: 9px; line-height: 24px;">'.$regions[$i+1]->region_name.'</td>';
}
if(!empty($regions[$i+2]->region_name)) {
$regionsList .= '<td style="width: 1%;padding: 9px; line-height: 24px;">'.$regions[$i+2]->region_name.'</td>';
}
As #AbraCadaver hinted, your code could use some DRYing out and some polishing up.
Differing from Abra's suggested resolution, it is important to consistently output the same number of cells in each row of the html table for valid html markup. If there is no region data at a particular index, just print an empty cell.
Rather than repeating the same cell markup text and inserting manually incremented indexes, use a cell template string and a for() loop.
I also recommend moving all your styling to the css declaration and referencing .all-regions td.
Suggested rewrite (not tested)
$html = '<table class="all-regions">';
$cellTemplate = '<td style="width: 1%; padding: 9px; line-height: 24px;">%s</td>';
$regions = $this->get('regions');
foreach (array_chunk($regions, 3) as $chunk) {
$html .= '<tr>';
for ($i = 0; $i < 3; ++$i) {
if (!isset($chunk[$i])) {
$html .= '<td></td>';
} else {
$html .= sprintf(
$cellTemplate,
JUri::root(),
$country
strtolower(str_replace(' ', '-', $chunk[$i]->region_name)),
$chunk[$i]->region_name
);
}
}
$html .= '</tr>';
}
$html .= '</table>';
$text = JString::str_ireplace('{%regions_list%}', $html, $this->article->text);
$this->setBreadcrumbs(['country']);
Related
Having a bit of an issue here. Could use some insight. I'm displaying user created events to visitors to my website. I'm using a while loop to display everything that hasn't not yet already passed. My goal is to display two separate events right next to each other, then another two below that and so on. Currently I'm using the flex box css property to achieve this, but it's only displaying the output vertically and not the way I want it to, meaning it's only putting one event per line. Here is my current output for displaying the events.
include 'db_connect.php';
$event_type = $_POST['event_type'];
$state = $_POST['state'];
$current_date = date("Y-m-d");
$sql = "SELECT * FROM events WHERE event_type LIKE '%".$event_type."%' AND state LIKE '%".$state."%' AND end_date > '$current_date' ORDER By end_date ASC";
$result = mysqli_query($conn, $sql);
if (isset($_POST['search-events']) && !empty($event_type) && !empty($state)) {
while($row = mysqli_fetch_array($result)) {
$event_name= $row['event_name'];
$image = $row['image'];
$start_date = $row['start_date'];
$end_date = $row['end_date'];
$start_time = $row['start_time'];
$end_time = $row['end_time'];
$street = $row['street'];
$city = $row['city'];
$state = $row['state'];
$zip_code = $row['zip_code'];
$id = $row['event_id'];
echo '<div class="filter-wrap">';
echo '<div id="filter-boxes">';
echo '<div id="list_image"><img src="'.$image.'"></div>';
echo '<div id="list_name">'.$event_name.'</div>';
echo '<div id="list_date">'.$start_date. ' - ' .$end_date. '</div>';
echo '<div id="list_time">' .$start_time. ' - ' .$end_time. '</div>';
echo '<div id="list_location">'.$street.''.$city.''.$state.''.$zip_code.'</div>';
echo '</div>';
echo '</div>';
}
}
Then there's the css that I'm using.
.filter-wrap {
display: flex;
flex-direction: row;
padding: 10px;
justify-content: center;
align-items: center;
}
#filter-boxes {
border: 2px solid #999;
text-align: center;
width: 50%;
height: 150px;
}
As you can see, I'm using the flex property inside the container that holds each of the individual boxes that holds each event. I have the flex direction set to row since I want it to display horizontally, then go the next line after it runs out of room on each line.
I tried a few things. I tried switching to the css column count property but didn't get the results I was expecting. I honestly probably didn't tweak with that property enough, but I have my heart set on the flex box property. I also tried setting the flex direction to column and also tried adding an inline-block display property to the boxes that are suppose to repeat on the while loop with each event. I'm finding this online that are kind of similar to my issue, but not quite. One uses javascript, but this can obviously also be accomplished somehow with php. I also found several articles talking about centering the content using flexbox, which is not the goal here.
Try move your .filter-wrap div element to outside of the while() {} loop.
Your current coding:
while() {
echo '<div class="filter-wrap">';
echo '<div id="filter-boxes">';
// content goes here...
echo '</div>';
echo '</div>';
}
will result in following structure where each .filter-wrap only container a single child .filter-boxes, which will always results in vertical presentation:
<div class="filter-wrap">
<div id="filter-boxes"> content </div>
</div>
<div class="filter-wrap">
<div id="filter-boxes"> content </div>
</div>
<div class="filter-wrap">
<div id="filter-boxes"> content </div>
</div>
For horizontal presentation, the correct structure should be one .filter-wrap consists of multiple .filter-boxes childs:
<div class="filter-wrap">
<div id="filter-boxes"> content </div>
<div id="filter-boxes"> content </div>
<div id="filter-boxes"> content </div>
</div>
So you can try change your coding to:
echo '<div class="filter-wrap">';
while() {
echo '<div id="filter-boxes">';
// content goes here...
echo '</div>';
}
echo '</div>';
Snippet for demo to you the coding logic result. It is in JS but you just have to apply the same in your PHP
Hope it helps and Happy coding!
var result_1 = document.getElementById('result_1');
var result_2 = document.getElementById('result_2');
var content_1 = '';
var content_2 = '';
content_2 = '<div class="filter-wrap">';
for (var i = 1; i <= 5; i++)
{
// result 1
content_1 += '<div class="filter-wrap"> <div class="filter-boxes">content ' + i + '</div> </div>';
// result 2
content_2 += '<div class="filter-boxes">content ' + i + '</div>';
}
content_2 += '</div>';
result_1.insertAdjacentHTML('beforeend', content_1);
result_2.insertAdjacentHTML('beforeend', content_2);
.filter-wrap {
display: flex;
flex-direction: row;
flex-wrap: wrap;
padding: 10px;
justify-content: center;
align-items: center;
}
.filter-boxes {
border: 2px solid #999;
text-align: center;
width: 50%;
height: 50px;
/* for two columns display */
max-width: 49%;
}
#result_1,
#result_2 {
background-color: lightgray;
border: 1px dashed black;
margin: 3px;
}
result 1
<div id="result_1"></div>
result 2
<div id="result_2"></div>
I have generated 2 HTML tables with PHP. The first table is always ontop of the 2nd table. I can't seem to get them to be side by side. the 2nd one is always under the first table.
I've also tried adding an html style of float left as well as inline in the html for the tables and it still doesn't come out side by side. Any help would be greatly appreciated!
//add table for bids and asks
function build_table($bidarray){
// start table
$html = '<table style="display: inline-block;">';
// header row
$html .= '<tr>';
foreach($bidarray[0] as $key=>$value){
$html .= '<th>' . htmlspecialchars($key) . '</th>';
}
$html .= '</tr>';
// data rows
foreach( $bidarray as $key=>$value){
$html .= '<tr>';
foreach($value as $key2=>$value2){
$html .= '<td>' . htmlspecialchars($value2) . '</td>';
}
$html .= '</tr>';
}
// finish table and return it
$html .= '</table>';
return $html;
}
$bidarray = array(
array('Company'=>'cardsltd', 'Min Qty'=>'5', 'Max Qty'=>'10', '$/box'=>'5.00'),
);
$askarray = array(
array('Company'=>'comp', 'Min Qty'=>'4', 'Max Qty'=>'9', '$/box'=>'4.00'),
);
echo build_table($bidarray) . build_table($askarray) ;
You need to use <div>s.
Take a <div>
Put two <div>s in it containing a table each.
<div>
<div style="float:left; width: 49%">
<table>
...
</table>
</div>
<div style="float:left; width: 49%">
<table>
...
</table>
</div>
</div>
This will put your tables side by side.
Also, we can change/adjust/manage widths.
49% is just for demo purposes.
PHP Code:
//define class for table
$html = '<div class="half-width"><table> ...';
CSS code:
.half-width
{
position: relative;
width: 100%;
padding-right: 15px; /*optional*/
padding-left: 15px; /*optional*/
-ms-flex: 0 0 50%;
flex: 0 0 50%;
max-width: 50%;
}
Also you can add float:right;width:50% for defined class (here class name is half-width)
I have the following code that dynamically loads items in an invoice. I am looking for a way to adds excess items to a new page, and so on. I would like to limit the # of items on a page to a set amount, say 15 items. Is there a way to do this in php? The code below is within a document that uses dompdf to appear in pages form
foreach ( $invoice['InvoiceDetail'] as $key=>$item){
$html .= '<tr style="border-bottom: 1px solid #ccc; line-height: 15px;">';
$itemNo = isset($item['product_id']) ? $item['product_id'] : '';
$itemName = isset($item['productName']) ? $item['productName']: '';
$price = isset($item['price']) ? invoiceNumFormat($item['price']): '';
$quantity = isset($item['quantity']) ? $item['quantity'] : '';
$total = invoiceNumFormat( $item['price']*$item['quantity']);
$html .= '<td style="text-align: left"><h5>'.$itemNo.'</h5></td>';
$html .= '<td style="text-align: left">'.$itemName.'</td>';
$html .= '<td style="text-align: left">'.$price.'</td>';
$html .= '<td style="text-align: left" width="10px">'.$quantity.'</td>';
$html .= '<td style="text-align: right">'.$total.'</td>';
$html .= '</tr>';
}
For your particular situation you could just indicate to dompdf to break the page, something along the lines of:
$itemCount = 0;
foreach ( $invoice['InvoiceDetail'] as $key=>$item){
$itemCount++;
$html .= '<tr style="border-bottom: 1px solid #ccc; line-height: 15px;">';
/* snip */
if ($itemCount % 20 == 0) {
$html .= '<tr><td><div style="page-break-before: always;"></div></td></tr>';
}
$html .= '<td style="text-align: left"><h5>'.$itemNo.'</h5></td>';
$html .= '<td style="text-align: left">'.$itemName.'</td>';
$html .= '<td style="text-align: left">'.$price.'</td>';
$html .= '<td style="text-align: left" width="10px">'.$quantity.'</td>';
$html .= '<td style="text-align: right">'.$total.'</td>';
$html .= '</tr>';
}
Dompdf does not yet recognize page break styling on table rows/cells. Otherwise it would make more sense to place the styling there.
Does this help?
<?php
$per_page = 20;
if ( $pagenum < 2 || !$pagenum ) {
$limit_start = 0;
} else {
$limit_start = (( $pagenum -1 ) * $per_page);
}
$sql = "select foo, bar, baz from table where $conditions limit $limit_start, $per_page";
$db->query( $sql ); //or whatever your method is
// while statement to get data into $invoice array
//foreach statement to display it
//pagination links
I have a procedural while loop that echos out rows in my DB like:
echo '<tr align="left"> <td>'.$row['address'].','.$row['state'].'</td>'.
'<td><a href="'.$row['shopurl'].'">'.$row['datedesc'].'</td>'.
'</tr>';
And works great! The problem now is that I need to add a "SOLD OUT" png across the address & state, of only one (currently) of the rows. I have CSS:
#sold-out{
background-image: url("/graphics/png/soldout.png");
}
With the image as the back-ground.
How can I add a Z-Index to php inside a While loop?
Thanks in advance!
You do not add z-index to PHP, you add it to CSS. However, in this case, you can simply print out an absolutely positioned div with the image in the td that you want.
PHP
foreach ($rows as $row) {
echo '<tr align="left">
<td>';
//conditional to determine if row is sold out
if ($row['soldOut'] === 'yes') {
echo '<div class="sold-out"> </div>';
}
echo $row['address'].','.$row['state'].'</td>'.
'<td><a href="'.$row['shopurl'].'">'.$row['datedesc'].'</td>'.
'</tr>';
}
CSS
.sold-out {
position:absolute;
background-image: url("/graphics/png/soldout.png");
opacity: 0.8;
top: 0;
left: 0;
right: 0;
bottom: 0;
I wanna make the dropdown list to appear in the center of the page. How do I do that?
Code:
echo '<div class="dropCenter" align="center">';
echo '<label><SELECT name="projectDropdown" id="projectDropdown" class="projectSelect">'.'<br>';
echo '<OPTION VALUE=" ">'."".'</OPTION>';
while($row = oci_fetch_array($compCuttingResult,OCI_ASSOC)) {
$projectName = $row ['PROJECT_NAME'];
echo "<OPTION VALUE='$projectName'>$projectName</OPTION>";
}
echo '</SELECT></label><br />';
First, remove all BR and LABEL tags from the HTML markup.
Next append a closind DIV tag at the end of the markup.
PHP Code
$html = null;
$html .= "<div class=\"dropCenter\">";
$html .= "<select id=\"projectDropDown\" name=\"projectDropDown\">";
$html .= "<option value=\"\"></option>";
while($row = oci_fetch_array($compCuttingResult,OCI_ASSOC)){
$projectName = $row['PROJECT_NAME'];
$html = sprintf("<option value=\"%s\">%s</option>", $projectName, $projectName);
}
$html .= "</select>";
$html .= "</div>";
print $html;
CSS Code
<style type="text/css">
select.projectSelect{ width:280px; height:24px; margin:10px; }
select.projectSelect option{line-height:24px;}
div.dropCenter{ display:inline-block; position:absolute; width:300px; height:34px; margin-left:-150px; margin-top:-17px; background-color:#e0e0e0; border:1px solid #c0c0c0; }
</style>
use the style to the first div
margin: 0px auto;
This should put the div in center
You can use this code
margin:auto;
<div class="dropCenter" style= 'margin:auto;'>
also you will have to check what are the divs you have above this. If there is no effect with above divs this would work fine.
External Inherited Style Sheets will also have an effect.