I am returning a large array (of products), and am using array_slice to grab only the first 8 items.
I will implement a "See More" button, which will load the remaining items on the frontend for the user.
<?php
$split_output = array_slice($_associatedProducts, 0, 8); // returns set number of products in array (8), for more button
?>
My question is, how do I then return the remaining items in the array, following the 8 displayed? These items will then be displayed when the user clicks "See More".
Thanks in advance!
Instead of using array_slice, output all values of the array to the page but hide the values from the ninth value onwards (easily achievable with a foreach loop and a counter variable). Apply Javascript to unhide these values on the click of a button:
<?php
$_associatedProducts = array(); // then add values to the array
$num = 0;
foreach($_associatedProducts as $prod){
if(++$num <= 8){
print("<div>$prod</div>");
}
else{
print("<div class=\"more\" style=\"display:none;\">$prod</div>");
}
}
?>
<button type="button" id="myButton">See More</button>
<script type="text/javascript">
document.getElementById("myButton").onclick = function(){
var divs = document.getElementsByClassName("more");
var len = divs.length;
for(var i = 0; i < len; i++){
divs[i].style.display = "block";
}
this.style.display = "none";
}
</script>
Use this go get the remaining items:
$more_output = array_slice($_associatedProducts, 8);
Then place them inside a hidden div:
<div class="moreProducts">
Place your hidden Products here
</div>
Style:
.moreProducts {
display: none;
}
HTML Link:
More Products
jQuery:
$('a.showMore').bind('click', function() {
$('.moreProducts').show();
});
The above code is just an example. You have to change it to your needs.
You can slice the rest with the starting point of where you left. The ninth item (which is offset 8). If you don't supply the length to array_slice it will simply return all remaining items.
$remaining_items = array_slice($_associatedProducts, 8);
If you wan't to do this after the user clicks a link, there are many routes to take on this problem.
Getting the data Asynchronous with JS
Multiple pages, first page has LIMIT 0,8 in the query, the see more page does not.
Simply sending all data to the page, and make the remaining products initially hidden and show them with a button.
Many more...
Below an example of Simply sending all data to the page, and make the remaining products initially hidden and show them with a button.
Which can also be done in many ways, it's just an example.
Then when clicking see more... you can show the remaining items with javascript.
This way you don't even have to slice.
Example:
css:
.hide{
display:none;
}
php / html
<ul id="productlist">
<?php
$i=1;
foreach($_associatedProducts as $product){
$hide = ($i++>8)?' class="hide"':'';
echo "<li$hide>$product</li>";
}
?>
</ul>
<button id="seemore">See more..</button>
Will generate:
<ul id="productlist">
<li>product 1</li>
<li>product 2</li>
<li>product 3</li>
<li>product 4</li>
<li>product 5</li>
<li>product 6</li>
<li>product 7</li>
<li>product 8</li>
<li class="hide">product 9</li>
<li class="hide">product 10</li>
</ul>
<button>See more..</button>
Now add jquery:
$('#seemore').on('click', function(){
$('#productlist>li.hide').removeClass('hide');
});
Related
I have some HTML generated by a WYSIWYG-editor (WordPress).
I'd like to show a preview of this HTML, by only showing up to 3 lines of text (in HTML format).
Example HTML: (always formated with new lines)
<p>Hello, this is some generated HTML.</p>
<ol>
<li>Some list item<li>
<li>Some list item</li>
<li>Some list item</li>
</ol>
I'd like to preview a maximum of 4 lines of text in this formated HTML.
Example preview to display: (numbers represent line numbers, not actual output).
Hello, this is some generated HTML.
Some list item
Some list item
Would this be possible with Regex, or is there any other method that I could use?
I know this would be possible with JavaScript in a 'hacky' way, as questioned and answered on this post.
But I'd like to do this purely on the server-side (with PHP), possibly with SimpleXML?
It's really easy with XPath:
$string = '<p>Hello, this is some generated HTML.</p>
<ol>
<li>Some list item</li>
<li>Some list item</li>
<li>Some list item</li>
</ol>';
// Convert to SimpleXML object
// A root element is required so we can just blindly add this
// or else SimpleXMLElement will complain
$xml = new SimpleXMLElement('<root>'.$string.'</root>');
// Get all the text() nodes
// I believe there is a way to select non-empty nodes here but we'll leave that logic for PHP
$result = $xml->xpath('//text()');
// Loop the nodes and display 4 non-empty text nodes
$i = 0;
foreach( $result as $key => $node )
{
if(trim($node) !== '')
{
echo ++$i.'. '.htmlentities(trim($node)).'<br />'.PHP_EOL;
if($i === 4)
{
break;
}
}
}
Output:
1. Hello, this is some generated HTML.<br />
2. Some list item<br />
3. Some list item<br />
4. Some list item<br />
I have personally coded the following function, which isn't perfect, but works fine for me.
function returnHtmlLines($html, $amountOfLines = 4) {
$lines_arr = array_values(array_filter(preg_split('/\n|\r/', $html)));
$linesToReturn = array_slice($lines_arr, 0, $amountOfLines);
return preg_replace('/\s{2,}/m', '', implode('', $linesToReturn));
}
Which returns the following HTML when using echo:
<p>Hello, this is some generated HTML.</p><ol><li>Some list item<li><li>Some list item</li>
Or formatted:
<p>Hello, this is some generated HTML.</p>
<ol>
<li>Some list item<li>
<li>Some list item</li>
Browsers will automatically close the <ol> tag, so it works fine for my needs.
Here is a Sandbox example
I am trying to fetch something through file_get_html everything seems fine but stuck on one part, i am using foreach function to extract a <li> and the problem is it is extracting all the li under that specific div or ul please read the following code.
Trying to extract from these lines
<ul class="x-name y-name">
<li>example 1</li>
<li>example 2</li>
<li>example 3</li>
</ul>
using
foreach($html->find("div#master") as $e){
foreach ($e->find("otherobject]") as $es){
$val["myuse-".strip_tags($es)] = "";
foreach($e->find("ul[class='x-name b-name'] li") as $elist){
$val["myuse-".strip_tags($es)] .= "<li>".strip_tags($elist->innertext)."</li>";
}
}
}
The problem is its not returning after completion of 3 <li> it is continuing drilling down to all the same name <li> What I want it to stop after the <li> numbers are complete and return to the previous foreach and when the next name is selected then it will search for next ul li.
I have a case where I have to pull data from the server and make pagination in the results. There are thousands of the data, and I'm planning to show 20 items per page.
My plan is to call this Laravel function each time new page is clicked:
public static function GetPagingListing($limLow=null, $limTop=null) {
$data = array();
$results = DB::table('news')->orderBy('date','desc')->limit($limLow, $limTop)->get(array('id','title','category','edituser','date'));
if($results != null) {
$i = 0;
foreach($results as $k=>$v) {
$data[$i][] = $v;
$i++;
}
}
$count = DB::table('news')->count(); //this gives total count of the data, for pagination later
return Response::json(['data'=>$data, 'count'=> ($count/20)]);
}
Then my current way of displaying the pagination is this (.html in Angular):
<ul>
<li ng-class="{disabled: currentPage == 0}">
<a href ng-click="prevPage()"><i class="fa fa-angle-double-left"></i> Before</a>
</li>
<li ng-repeat="n in range(itemCount)" ng-class="{active: n == currentPage}" ng-click="setPage()">
<a href ng-bind="n + 1">1</a>
</li>
<li ng-class="{disabled: currentPage == newsList.length - 1}">
<a href ng-click="nextPage()">After <i class="fa fa-angle-double-right"></i></a>
</li>
</ul>
This all works fine, but the total of my data count is 1000+, that's like 50+ pagination that user can click. How to make the pagination like [<prev][1][2][3][...][21][22][23][...][50][51][52][next>] (or at least a logic)?
EDIT
Solved my problem using Angular UI Bootstrap:
<pagination total-items="itemCount" page="currentPage" on-select-page="setPage(page)" boundary-links="true" rotate="false" max-size="5"></pagination>
with its cdn:
<script src="//cdn.jsdelivr.net/angular.bootstrap/0.7.0/ui-bootstrap-tpls.min.js"></script>
I've just think about this recently, and my conclusion is that the logic of the pagination is surprisingly involved. One place you can look for inspiration is Wordpress's paginate_links function http://core.trac.wordpress.org/browser/tags/3.7.1/src/wp-includes/general-template.php#L1988.
You need to know the total number of pages total, the current page current, number of first/last pages to be displayed end_size (3 in your example) and the number of pages around the current page mid_size (1 in your example); then:
if total < 2, no pagination needed
if current > 1, shows prev
for n from 1 to total:
if n <= end_size (the first part) or n > total - end_size (the last part) or (n >= current - mid_size and n <= current + mid_size) (the middle part), display link to page n
else display dots if not displayed
if current < total, shows next
I am trying to link an anchor to cycle to a specific div. This is what I have:
The menu
<div id="mainmenu">
<ul class="sidenav" id="menu">
<li>
<a href="#page2">Serviciile noastre
</a>
</li>
<li>
<a href="#page8">Credite Nevoi personale fara ipoteca
</a>
</li>
<li>
<a href="">Credite Nevoi personale cu ipoteca
</a>
</li>
<li>
<a href="">Credite ipotecare
</a>
</li>
<li>
<a href="">Carduri de credit
</a>
</li>
<li>
<a href="">Credite "Prima Casa"
</a>
</li>
<li>
<a href="">Refinantari credite/carduri
</a>
</li>
<li>
<a href="">Acte necesare
</a>
</li>
<li>
<a href="">Economisire creditare
</a>
</li>
</ul>
</div>
And the JavaScript
var $jts = jQuery.noConflict();
$jts(function() {
// maincontent cycle
$jts('#maincontent').cycle({
fx: 'blindY', // You can choose effect do you like, for reference : http://www.malsup.com/jquery/cycle/browser.html
speed: 'slow',
timeout: 0,
cleartype: true, // true if clearType corrections should be applied (for IE)
cleartypeNoBg: true,
pager: '#menu',
startingSlide : 0,
after:onAfter,
pagerAnchorBuilder: function(idx, slide) {
// return sel string for existing anchor
return '#menu li:eq(' + (idx) + ') a';
}
});
function onAfter(curr, next, opts, fwd){
//get the height of the current slide
var $ht = $jts(this).height();
I am using jquery.cycle.all.min.js.
So if I understand correctly, you wish to have an <a href=... click event to take it to the corresponding slide.
Simplest way to do this for your example slide id of 7:
The link you want to click to view a specific slide:
<!-- support for those strange users
without Javascript - we will fix this later -->
Sample text
Your JS to control the behaviour
//if the user has JS enabled, we will stop the
//link from taking us away from the page
//and only do the sweet animation
$(".go-to").click(function(gt){
gt.preventDefault();
var slide = $(this).attr("rel");
$("#maincontent").cycle(slide);
});
Main things to note:
Use of the rel attribute. Use it, it's great.
Use of the empty selector class go-to - used only to define that particular link to interact with cycle. This can be any name you like (so long as it follows the conventions outlined below), for example foo, bar, coco-the-clown etc.
Finally, the next is a little off-topic, but a useful piece of information none-the-less;
If you want your pages to validate to W3C standards, ID's must be unique, and start with a letter. Direct from the horse's mouth:
ID tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").
http://www.w3.org/TR/html4/types.html#type-name
in response to your comment
So the basic premise of what we want to do:
Assign an identifier to each link that corresponds with the slide number - which means this will have to be a number.
Find out the slide order.
Using your link you posted in the comment you should change it to reflect which ever slide number you want to see when clicked, like so:
<a href="credite.php" class="go-to" rel="1" >Credite Nevoi personale fara ipoteca</a>
Also, remove the rel="opt" and class="go-to" from your div element.
If you go and try this now (assuming you have more than 1 slide...) and it is what you wanted, you probably won't need to come back and read the rest.
So when you click the link mentioned above, this should take you to slide number 2 - provided you are not on slide number 2. "What?!" I hear you cry. Read on.
So, if you were to look at the rendered source code in your browser, you will see that inside of your cycle element, maincontent, each of the div elements that are direct descendants of maincontent will be the slides. These are in order (for a computer); 0 is the starting slide and 1 is the second slide, 2 is the third slide ad infinitum.
So - if you are using PHP & MySQL to show your content, it will be super-easy to assign "IDs" to your anchor's rel attributes. Alternatively, you can hard-code these.
Let me know how you did!
I have one form which is submitting by ajax.
I am running on php.
After the entry completed by ajax, that entry should be updated to my html.
For example
My HTML Code
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
Now when any one insert new entry with 5, then my html should be updated with below HTML.
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
Thanks in advance.
Avinash
Using the "dollar" function to select and extend the UL, then using one of MooTool's Element methods to insert the new LI will probably work.
http://mootools.net/docs/core/Element/Element#dollar
http://mootools.net/docs/core/Element/Element#Element:inject
I have done it my own.
Please check the below code for the answer.
// Select UL to append
var commentUL = $('comment_ul');
//Create new li to insert
var commentnewLI = new Element('li', {id: 'myFirstElement'});
// Append text to li
commentnewLI.appendText(responseValueArray[1]);
// Insert li into UL
commentUL.adopt(commentnewLI);
Mootools' admopt method has works for me.
But i have some problem regarding this.
My response has some HTML in the to append in the LI.
Like below
Dummy text, Dummy text,Dummy text,<br/><span>User Name</span>
Can u please suggest that whats the problem over here.
Thanks
Avinash
My HTML problem is solved.
I have just replace the
commentnewLI.appendText(responseValueArray[1]);
with below code.
commentnewLI.innerHTML= responseValueArray[1];
Its working fine.....
Here's how I did it:
//the list
<ul id='the_list'>
<li>list item 1</li>
<li>list item 2</li>
<li id='template_row' class='hidden'>list template. Can have <span class='bold'>HTML</span></li>
</ul>
//get the template
var template = $('template_row');
//create a new row, based on the template
var newRow = new Element('li').set('html', template.innerHTML);
//add it to the list
newRow.inject($('the_list'));
My template row has HTML and it is rendered properly.