Firefox OS - BuildingBlock drawer usage - javascript

I am developing a Firefox OS based application what uses the building block drawer component. My problem is when I click the top-left corner icon - the drawer shows up properly - but the content of the main page disappears. Could you suggest me a solution?
Thanks.

If your intent is to clear each list (Projects, Users, Plugins) when someone clicks on them, you could remove line visibility attribute from the tablist in tabs.css
[role="tablist"] [role="tabpanel"] {
position: absolute;
top: 4rem;
left: 0;
/*visibility: hidden;*/
width: 100%;
height: calc(100% - 4rem);
z-index: -1;
display: block;
overflow: auto;
}
And then clear the list in your code. You will need to do this for each of the functions:
function clearLists(){
$("#resultsProjects").empty();
$("#resultsUsers").empty();
$("#resultsPlugins").empty();
}
function processProjects() {
return function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var obj = jQuery.parseJSON(xhr.responseText);
clearLists();
for (var i = 0; i < obj.length; i++) {
$('#resultsProjects').append("<li><p>" + obj[i].name + "</p><p>" + obj[i].lang + "</p></li>");
}
}
}
}

Related

Make scrollable elements of varying sizes scroll at once and meet evenly using Javascript

I have three column classes of varying heights that I want to meet evenly once scrolled to the bottom by having each scroll at different speeds. Something like this
https://forum.bubble.io/t/synchronized-scrolling-multiple-columns-scroll-at-different-speeds/161938/2
The larger columns should scroll slower in order to meet evenly once scrolled down all the way.
The columns are filled with images using other javascript code I wrote.
The method I've tried using event listeners is extremely slow and unreliable since the events start to nest and interrupt one another. How else could I approach this?
.column{
overflow: auto;
scrollbar-width: none;
-ms-overflow-style: none;
height: 100%;
background-color: #468189;
float: left;
width: 33.33%;
padding-right: 10px;
}
.portfolio-grid{
overflow: auto;
height: 100%;
width: 80%;
}
<div class="portfolio-grid">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
var columns = document.getElementsByClassName("column");
columns[0].addEventListener("scroll", myfunction);
columns[1].addEventListener("scroll", myfunction2);
columns[2].addEventListener("scroll", myfunction3);
function myfunction(){
columns[1].removeEventListener("scroll", myfunction2);
columns[2].removeEventListener("scroll", myfunction3);
columns[1].scrollTop = this.scrollTop;
columns[2].scrollTop = this.scrollTop;
columns[1].addEventListener("scroll", myfunction2);
columns[2].addEventListener("scroll", myfunction3);
}
function myfunction2(){
columns[0].removeEventListener("scroll", myfunction2);
columns[2].removeEventListener("scroll", myfunction3);
columns[0].scrollTop = this.scrollTop;
columns[2].scrollTop = this.scrollTop;
columns[0].addEventListener("scroll", myfunction);
columns[2].addEventListener("scroll", myfunction3);
}
function myfunction3(){
columns[0].removeEventListener("scroll", myfunction2);
columns[1].removeEventListener("scroll", myfunction3);
columns[0].scrollTop = this.scrollTop;
columns[1].scrollTop = this.scrollTop;
columns[0].addEventListener("scroll", myfunction);
columns[1].addEventListener("scroll", myfunction2);
}
The scroll event fires repeatedly and asynchronously. In your code, you disable the listener, set the scrollTop of the other elements and recover the listener. What actually happens is that the scrollTop is scheduled and handled by the system, whereas the listener is recovered synchronously. This means that, by the time the scrollTop is done, the event handler is already working.
Aside from other problems, you may want to read about event throttling. A working example, which can be improved:
const els = document.getElementsByClassName('column');
let factors = [];
let hfuncts = [];
let ticking = false;
let ttimer;
let ffactor = els[0].scrollHeight;
function recoverScroll(i){
if (ticking === false){
for (let j = 0; j < els.length; j++){
if (j !== i){
els[j].addEventListener('scroll', hfuncts[j]);
}
}
}
else{
if (ttimer){
clearTimeout(ttimer);
}
ticking = false;
ttimer = setTimeout(() => {recoverScroll(i)}, 300)
}
}
function handleScroll(i){
ticking = true;
for (let j = 0; j < els.length; j++){
if (j !== i){
els[j].removeEventListener('scroll', hfuncts[j]);
let tpos = els[i].scrollTop * factors[j] / factors[i];
els[j].scrollTo(0, tpos);
}
}
recoverScroll(i);
}
for (let i = 0; i < els.length; i++){
factors.push((els[i].scrollHeight - els[i].clientHeight) / ffactor);
}
for (let i = 0; i < els.length; i++){
let cf = function(){handleScroll(i)};
hfuncts.push(cf);
els[i].addEventListener('scroll', cf);
}
.column{
overflow: auto;
scrollbar-width: none;
-ms-overflow-style: none;
height: 100%;
background-color: #468189;
float: left;
width: 30%;
padding-right: 10px;
}
.portfolio-grid{
overflow: auto;
height: 200px;
width: 80%;
}
<div class="portfolio-grid">
<div class="column"><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p></div>
<div class="column"><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p></div>
<div class="column"><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p><p>Text</p></div>
</div>
As you can see, the key is that recoverScroll only works about 300 ms after the last scroll event has been fired. This delay needs to be chosen carefully. Too short and you get the same problem as before. Too long and the user can scroll a different element and not get the effect. Unfortunately, this depends on how each system chooses to do the scroll event. This event is notoriously difficult to intercept.

Ticker-style getting cut in Mobile View

The requirement is to sow the information continuously hence opted for a ticker style.
Now I am using an [ticker-style.css] along with [jquery.ticker.js]
It works fine in a Full Screen however while browsing in a Mobile/Tabler - the text is getting cut (see below screenshot) - I tried to play around the width however the rendering was not as expected.
Can you help here.
Thanks in advance.
/*
jQuery News Ticker is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2 of the License.
jQuery News Ticker is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with jQuery News Ticker. If not, see <http://www.gnu.org/licenses/>.
*/
(function($){
$.fn.ticker = function(options) {
// Extend our default options with those provided.
// Note that the first arg to extend is an empty object -
// this is to keep from overriding our "defaults" object.
var opts = $.extend({}, $.fn.ticker.defaults, options);
// check that the passed element is actually in the DOM
if ($(this).length == 0) {
if (window.console && window.console.log) {
window.console.log('Element does not exist in DOM!');
}
else {
alert('Element does not exist in DOM!');
}
return false;
}
/* Get the id of the UL to get our news content from */
var newsID = '#' + $(this).attr('id');
/* Get the tag type - we will check this later to makde sure it is a UL tag */
var tagType = $(this).get(0).tagName;
return this.each(function() {
// get a unique id for this ticker
var uniqID = getUniqID();
/* Internal vars */
var settings = {
position: 0,
time: 0,
distance: 0,
newsArr: {},
play: true,
paused: false,
contentLoaded: false,
dom: {
contentID: '#ticker-content-' + uniqID,
titleID: '#ticker-title-' + uniqID,
titleElem: '#ticker-title-' + uniqID + ' SPAN',
tickerID : '#ticker-' + uniqID,
wrapperID: '#ticker-wrapper-' + uniqID,
revealID: '#ticker-swipe-' + uniqID,
revealElem: '#ticker-swipe-' + uniqID + ' SPAN',
controlsID: '#ticker-controls-' + uniqID,
prevID: '#prev-' + uniqID,
nextID: '#next-' + uniqID,
playPauseID: '#play-pause-' + uniqID
}
};
// if we are not using a UL, display an error message and stop any further execution
if (tagType != 'UL' && tagType != 'OL' && opts.htmlFeed === true) {
debugError('Cannot use <' + tagType.toLowerCase() + '> type of element for this plugin - must of type <ul> or <ol>');
return false;
}
// set the ticker direction
opts.direction == 'rtl' ? opts.direction = 'right' : opts.direction = 'left';
// lets go...
initialisePage();
/* Function to get the size of an Object*/
function countSize(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
function getUniqID() {
var newDate = new Date;
return newDate.getTime();
}
/* Function for handling debug and error messages */
function debugError(obj) {
if (opts.debugMode) {
if (window.console && window.console.log) {
window.console.log(obj);
}
else {
alert(obj);
}
}
}
/* Function to setup the page */
function initialisePage() {
// process the content for this ticker
processContent();
// add our HTML structure for the ticker to the DOM
$(newsID).wrap('<div id="' + settings.dom.wrapperID.replace('#', '') + '"></div>');
// remove any current content inside this ticker
$(settings.dom.wrapperID).children().remove();
$(settings.dom.wrapperID).append('<div id="' + settings.dom.tickerID.replace('#', '') + '" class="ticker"><div id="' + settings.dom.titleID.replace('#', '') + '" class="ticker-title"><span><!-- --></span></div><p id="' + settings.dom.contentID.replace('#', '') + '" class="ticker-content"></p><div id="' + settings.dom.revealID.replace('#', '') + '" class="ticker-swipe"><span><!-- --></span></div></div>');
$(settings.dom.wrapperID).removeClass('no-js').addClass('ticker-wrapper has-js ' + opts.direction);
// hide the ticker
$(settings.dom.tickerElem + ',' + settings.dom.contentID).hide();
// add the controls to the DOM if required
if (opts.controls) {
// add related events - set functions to run on given event
$(settings.dom.controlsID).on('click mouseover mousedown mouseout mouseup', function (e) {
var button = e.target.id;
if (e.type == 'click') {
switch (button) {
case settings.dom.prevID.replace('#', ''):
// show previous item
settings.paused = true;
$(settings.dom.playPauseID).addClass('paused');
manualChangeContent('prev');
break;
case settings.dom.nextID.replace('#', ''):
// show next item
settings.paused = true;
$(settings.dom.playPauseID).addClass('paused');
manualChangeContent('next');
break;
case settings.dom.playPauseID.replace('#', ''):
// play or pause the ticker
if (settings.play == true) {
settings.paused = true;
$(settings.dom.playPauseID).addClass('paused');
pauseTicker();
}
else {
settings.paused = false;
$(settings.dom.playPauseID).removeClass('paused');
restartTicker();
}
break;
}
}
else if (e.type == 'mouseover' && $('#' + button).hasClass('controls')) {
$('#' + button).addClass('over');
}
else if (e.type == 'mousedown' && $('#' + button).hasClass('controls')) {
$('#' + button).addClass('down');
}
else if (e.type == 'mouseup' && $('#' + button).hasClass('controls')) {
$('#' + button).removeClass('down');
}
else if (e.type == 'mouseout' && $('#' + button).hasClass('controls')) {
$('#' + button).removeClass('over');
}
});
// add controls HTML to DOM
$(settings.dom.wrapperID).append('<ul id="' + settings.dom.controlsID.replace('#', '') + '" class="ticker-controls"><li id="' + settings.dom.playPauseID.replace('#', '') + '" class="jnt-play-pause controls"><!-- --></li><li id="' + settings.dom.prevID.replace('#', '') + '" class="jnt-prev controls"><!-- --></li><li id="' + settings.dom.nextID.replace('#', '') + '" class="jnt-next controls"><!-- --></li></ul>');
}
if (opts.displayType != 'fade') {
// add mouse over on the content
$(settings.dom.contentID).mouseover(function () {
if (settings.paused == false) {
pauseTicker();
}
}).mouseout(function () {
if (settings.paused == false) {
restartTicker();
}
});
}
// we may have to wait for the ajax call to finish here
if (!opts.ajaxFeed) {
setupContentAndTriggerDisplay();
}
}
/* Start to process the content for this ticker */
function processContent() {
// check to see if we need to load content
if (settings.contentLoaded == false) {
// construct content
if (opts.ajaxFeed) {
if (opts.feedType == 'xml') {
$.ajax({
url: opts.feedUrl,
cache: false,
dataType: opts.feedType,
async: true,
success: function(data){
count = 0;
// get the 'root' node
for (var a = 0; a < data.childNodes.length; a++) {
if (data.childNodes[a].nodeName == 'rss') {
xmlContent = data.childNodes[a];
}
}
// find the channel node
for (var i = 0; i < xmlContent.childNodes.length; i++) {
if (xmlContent.childNodes[i].nodeName == 'channel') {
xmlChannel = xmlContent.childNodes[i];
}
}
// for each item create a link and add the article title as the link text
for (var x = 0; x < xmlChannel.childNodes.length; x++) {
if (xmlChannel.childNodes[x].nodeName == 'item') {
xmlItems = xmlChannel.childNodes[x];
var title, link = false;
for (var y = 0; y < xmlItems.childNodes.length; y++) {
if (xmlItems.childNodes[y].nodeName == 'title') {
title = xmlItems.childNodes[y].lastChild.nodeValue;
}
else if (xmlItems.childNodes[y].nodeName == 'link') {
link = xmlItems.childNodes[y].lastChild.nodeValue;
}
if ((title !== false && title != '') && link !== false) {
settings.newsArr['item-' + count] = { type: opts.titleText, content: '' + title + '' }; count++; title = false; link = false;
}
}
}
}
// quick check here to see if we actually have any content - log error if not
if (countSize(settings.newsArr < 1)) {
debugError('Couldn\'t find any content from the XML feed for the ticker to use!');
return false;
}
settings.contentLoaded = true;
setupContentAndTriggerDisplay();
}
});
}
else {
debugError('Code Me!');
}
}
else if (opts.htmlFeed) {
if($(newsID + ' LI').length > 0) {
$(newsID + ' LI').each(function (i) {
// maybe this could be one whole object and not an array of objects?
settings.newsArr['item-' + i] = { type: opts.titleText, content: $(this).html()};
});
}
else {
debugError('Couldn\'t find HTML any content for the ticker to use!');
return false;
}
}
else {
debugError('The ticker is set to not use any types of content! Check the settings for the ticker.');
return false;
}
}
}
function setupContentAndTriggerDisplay() {
settings.contentLoaded = true;
// update the ticker content with the correct item
// insert news content into DOM
$(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
$(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
// set the next content item to be used - loop round if we are at the end of the content
if (settings.position == (countSize(settings.newsArr) -1)) {
settings.position = 0;
}
else {
settings.position++;
}
// get the values of content and set the time of the reveal (so all reveals have the same speed regardless of content size)
distance = $(settings.dom.contentID).width();
time = distance / opts.speed;
// start the ticker animation
revealContent();
}
// slide back cover or fade in content
function revealContent() {
$(settings.dom.contentID).css('opacity', '1');
if(settings.play) {
// get the width of the title element to offset the content and reveal
var offset = $(settings.dom.titleID).width() + 20;
$(settings.dom.revealID).css(opts.direction, offset + 'px');
// show the reveal element and start the animation
if (opts.displayType == 'fade') {
// fade in effect ticker
$(settings.dom.revealID).hide(0, function () {
$(settings.dom.contentID).css(opts.direction, offset + 'px').fadeIn(opts.fadeInSpeed, postReveal);
});
}
else if (opts.displayType == 'scroll') {
// to code
}
else {
// default bbc scroll effect
$(settings.dom.revealElem).show(0, function () {
$(settings.dom.contentID).css(opts.direction, offset + 'px').show();
// set our animation direction
animationAction = opts.direction == 'right' ? { marginRight: distance + 'px'} : { marginLeft: distance + 'px' };
$(settings.dom.revealID).css('margin-' + opts.direction, '0px').delay(20).animate(animationAction, time, 'linear', postReveal);
});
}
}
else {
return false;
}
};
// here we hide the current content and reset the ticker elements to a default state ready for the next ticker item
function postReveal() {
if(settings.play) {
// we have to separately fade the content out here to get around an IE bug - needs further investigation
$(settings.dom.contentID).delay(opts.pauseOnItems).fadeOut(opts.fadeOutSpeed);
// deal with the rest of the content, prepare the DOM and trigger the next ticker
if (opts.displayType == 'fade') {
$(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {
$(settings.dom.wrapperID)
.find(settings.dom.revealElem + ',' + settings.dom.contentID)
.hide()
.end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
.show()
.end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
.removeAttr('style');
setupContentAndTriggerDisplay();
});
}
else {
$(settings.dom.revealID).hide(0, function () {
$(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {
$(settings.dom.wrapperID)
.find(settings.dom.revealElem + ',' + settings.dom.contentID)
.hide()
.end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
.show()
.end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
.removeAttr('style');
setupContentAndTriggerDisplay();
});
});
}
}
else {
$(settings.dom.revealElem).hide();
}
}
// pause ticker
function pauseTicker() {
settings.play = false;
// stop animation and show content - must pass "true, true" to the stop function, or we can get some funky behaviour
$(settings.dom.tickerID + ',' + settings.dom.revealID + ',' + settings.dom.titleID + ',' + settings.dom.titleElem + ',' + settings.dom.revealElem + ',' + settings.dom.contentID).stop(true, true);
$(settings.dom.revealID + ',' + settings.dom.revealElem).hide();
$(settings.dom.wrapperID)
.find(settings.dom.titleID + ',' + settings.dom.titleElem).show()
.end().find(settings.dom.contentID).show();
}
// play ticker
function restartTicker() {
settings.play = true;
settings.paused = false;
// start the ticker again
postReveal();
}
// change the content on user input
function manualChangeContent(direction) {
pauseTicker();
switch (direction) {
case 'prev':
if (settings.position == 0) {
settings.position = countSize(settings.newsArr) -2;
}
else if (settings.position == 1) {
settings.position = countSize(settings.newsArr) -1;
}
else {
settings.position = settings.position - 2;
}
$(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
$(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
break;
case 'next':
$(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
$(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
break;
}
// set the next content item to be used - loop round if we are at the end of the content
if (settings.position == (countSize(settings.newsArr) -1)) {
settings.position = 0;
}
else {
settings.position++;
}
}
});
};
// plugin defaults - added as a property on our plugin function
$.fn.ticker.defaults = {
speed: 0.10,
ajaxFeed: false,
feedUrl: '',
feedType: 'xml',
displayType: 'reveal',
htmlFeed: true,
debugMode: true,
controls: true,
titleText: '',
direction: 'ltr',
pauseOnItems: 3000,
fadeInSpeed: 600,
fadeOutSpeed: 300
};
})(jQuery);
/* Ticker Styling */
.ticker-wrapper.has-js {
margin: 0;
padding: 0;
width: 780px;
height: 32px;
display: block;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
background-color:inherit;
font-size: inherit;
}
.ticker {
width: 710px;
height: 23px;
display: block;
position: relative;
overflow: hidden;
background-color: #fff;
#media #{$xs}{
width: 200px;
}
}
.ticker-title {
padding-top: 9px;
color: #990000;
font-weight: bold;
background-color: #fff;
text-transform: capitalize;
}
.ticker-content {
margin: 0px;
/* padding-top: 9px; */
position: absolute;
color: #506172;
font-weight: normal;
background-color: #fff;
overflow: hidden;
white-space: nowrap;
font-family: "Roboto",sans-serif;
font-size: 16px;
}
.ticker-content:focus {
none;
}
.ticker-content a {
text-decoration: none;
color: #1F527B;
}
.ticker-content a:hover {
text-decoration: underline;
color: #0D3059;
}
.ticker-swipe {
padding-top: 9px;
position: absolute;
top: 0px;
background-color: #fff;
display: block;
width: 800px;
height: 23px;
}
.ticker-swipe span {
margin-left: 1px;
background-color: #fff;
border-bottom: 1px solid #1F527B;
height: 12px;
width: 7px;
display: block;
}
.ticker-controls {
padding: 8px 0px 0px 0px;
list-style-type: none;
float: left;
}
.ticker-controls li {
padding: 0px;
margin-left: 5px;
float: left;
cursor: pointer;
height: 16px;
width: 16px;
display: block;
}
.ticker-controls li.jnt-play-pause {
background-image: url('../images/controls.png');
background-position: 32px 16px;
}
.ticker-controls li.jnt-play-pause.over {
background-position: 32px 32px;
}
.ticker-controls li.jnt-play-pause.down {
background-position: 32px 0px;
}
.ticker-controls li.jnt-play-pause.paused {
background-image: url('../images/controls.png');
background-position: 48px 16px;
}
.ticker-controls li.jnt-play-pause.paused.over {
background-position: 48px 32px;
}
.ticker-controls li.jnt-play-pause.paused.down {
background-position: 48px 0px;
}
.ticker-controls li.jnt-prev {
background-image: url('../images/controls.png');
background-position: 0px 16px;
}
.ticker-controls li.jnt-prev.over {
background-position: 0px 32px;
}
.ticker-controls li.jnt-prev.down {
background-position: 0px 0px;
}
.ticker-controls li.jnt-next {
background-image: url('../images/controls.png');
background-position: 16px 16px;
}
.ticker-controls li.jnt-next.over {
background-position: 16px 32px;
}
.ticker-controls li.jnt-next.down {
background-position: 16px 0px;
}
.js-hidden {
display: none;
}
.no-js-news {
padding: 10px 0px 0px 45px;
color: #fff;
}
.left .ticker-swipe {
/*left: 80px;*/
}
.left .ticker-controls, .left .ticker-content, .left .ticker-title, .left .ticker {
float: left;
}
.left .ticker-controls {
padding-left: 6px;
}
.right .ticker-swipe {
/*right: 80px;*/
}
.right .ticker-controls, .right .ticker-content, .right .ticker-title, .right .ticker {
float: right;
}
.right .ticker-controls {
padding-right: 6px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<strong>Trending now</strong>
<!-- <p>Rem ipsum dolor sit amet, consectetur adipisicing elit.</p> -->
<div class="trending-animated">
<ul id="js-news" class="js-hidden">
<li class="news-item">Dolor sit amet, consectetur adipisicing elit.</li>
<li class="news-item">Spondon IT sit amet, consectetur.......</li>
<li class="news-item">Rem ipsum dolor sit amet, consectetur adipisicing elit.</li>
</ul>
</div>
The problem is that you are setting fixed widths for ticker elements.The ticker container has a width of 720px no matter what size the screen, and on screens < 767px the container for the scrolling text is just 230px.
Either change the CSS if it is your own, or if not you can add these rules after the Ticker CSS in included:
#media (max-width: 767px){
.ticker-wrapper.has-js,
.ticker,
.trending-tittle .ticker {
width: 100%!important;
}
}
This sets them to use the full width of the screen.

Image gallery with max items and pagination with javascript

This is my situation:
I have a image gallery with 10 images visible on the main page and a pagination bar. The images came from a for loop iteration over a json file. That's no problem, they are just there ;-)
Something like:
for i=0; i <10; i++
create div with styles and images[i].image;
My question is:
I want to display the next 10 images on page 2, so when you click on page 2, it counts from 11 to 20.
I found the jQuery 'Jpaginate'-plugin...
Can i accomplish that with this plugin?
Could someone explain me in the way i have to thing with Vars, Counts, Objects??
Thanks and kind regards,
Mike
I have made you an example on how you can approach this. I'm not saying it is bugproof, but it's the concept that matters. You might find some inspiration and maybe reach your goal.
var imgSrc = "https://s-media-cache-ak0.pinimg.com/236x/36/a5/7b/36a57b0f0ab16e885fcc230addb695c2.jpg";
var json = [];
for (var i = 0; i < 36; i++)
json.push({
Title: "Title " + (i + 1),
Source: imgSrc
});
/*
Just for ease, I'm creating an array with 36 objects (3x3 gallery)
so 9 images per page
*/
var pageLimit = 9;
var page = 1;
showImages();
$("#btnPrevious").click(function() {
if (pageLimit <= 9) {
pageLimit = 9;
page = 1;
} else {
page--;
pageLimit -= 9;
}
showImages();
});
$("#btnNext").click(function() {
if (pageLimit >= json.length) {
pageLimit = json.length;
} else {
page++;
pageLimit += 9;
}
showImages();
});
function showImages() {
$(".images").empty();
for (var i = pageLimit - 9; i < pageLimit; i++) {
var template = $("<div></div>").addClass("template");
var img = $("<img>");
img.attr("src", json[i].Source);
img.attr("alt", json[i].Title);
var br = $("<br/>");
var title = $("<span></span>").html(json[i].Title);
template.append(img).append(br).append(title);
$(".images").append(template);
}
$("#page").html("Page " + page);
}
.gallery {
width: 100%;
height: 500px;
border: 1px solid black;
background-color: lightgray;
text-align: center;
}
.images {
width: 90%;
margin: 0 auto;
height: 100%;
margin-bottom: 15px;
}
img {
height: auto;
width: 33%;
margin: 20px 5px;
}
.template {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gallery">
<div class="images"></div>
<button id="btnPrevious">
< Previous
</button>
<span id="page"></span>
<button id="btnNext">
> Next
</button>
</div>
Don't mind the CSS, because I suck at that (lol). It was based on the space I had on jsFiddle, but looking at it now (on full page or just the area the snippet provides) it looks awful. If a CSS guru could fix this .. Question in a question?
You can create your own pagination plugin.
You must store current page somewhere and modify your factory.
Something like: for i=current_page * count_per_page; i < count_per_page * (current_page + 1); i++ create div with styles and images[i].image;

Text in javascript div and click anywere to close div

I have a javascript which opens up a window just before a surfer enters my site which has 24 hours cookie meaning it will popup again after the surfer visits my site again after 24 hours.
Right now one can only close the div if the red "x" button is pressed. Also when I run it I can only add images or iframes but I'd like o add some text like "welcome to my site".
Here is the code
var floatingAd={
run: function (e, t) {
if (e === 2 || e === 1 && (this.getCookie("floatingAd") === null || this.getCookie("floatingAd") === "")) {
document.write('<div id="floatingAdFixed" style="bottom: 0px; background: #fff; font-family: Arial, Helvetica, sans-serif; left: 0; padding: 0px 0; position: fixed; font-size: 16px; width: 100%; z-index: 99999; float: left; vertical-align: middle; margin: 0px 0 0; opacity: 0.88; font-weight: bold;">');
document.write('<div style="text-align: right; width: 710px; margin: 340px auto;"><img onclick="floatingAd.close(' + e + ');" style="position: absolute; margin-top: -11px; margin-left: -23px; cursor: pointer;" src="data:image/png;base64,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"></div>');
document.write('<div id="floatingAd" style="text-align: center; width: 710px; margin: 300px auto; ">');
document.write("</div>");
document.write("</div>");
document.getElementById("floatingAd").innerHTML = t
}
},
close: function (e) {
if (e === 1) {
this.setCookie("floatingAd", 1, 1)
}
document.getElementById("floatingAdFixed").style.display = "none"
},
setCookie: function (t, n, r) {
var i = new Date;
i.setDate(i.getDate() + r);
var s = escape(n) + (r == null ? "" : "; expires=" + i.toUTCString());
document.cookie = t + "=" + s + ";path=/"
},
getCookie: function (e) {
var t = document.cookie;
var n = t.indexOf(" " + e + "=");
if (n == -1) {
n = t.indexOf(e + "=")
}
if (n == -1) {
t = null
} else {
n = t.indexOf("=", n) + 1;
var r = t.indexOf(";", n);
if (r == -1) {
r = t.length
}
t = unescape(t.substring(n, r))
}
return t
}
}
/**
* Run the script
* 1 = 24 hours cookie, 2 = refresh
*/
floatingAd.run(1, '');
Two questions:
How do I make it to close if you click anywhere on the screen?
Hwo do I make it to show text in the floatingAd.run(1, '');?
For 1 check out How do I detect a click outside an element?
EDIT: If you would like to have the window closed if "you click anywhere on the screen", just use your object in the following way:
$('html').click(function() {
// You may skip the following if statement, it may work without it
if (document.getElementById("floatingAdFixed").style.display != "none")
// The following line is what you'll definitely need
floatingAd.close(1);
});
For 2, just add it as another variable in run like this
var floatingAd={
run: function (e, t, text) {
// ...
document.write('<div id="textContainer">' + text + '</div>');
// ...
}
Then use it like this:
floatingAd.run(1, '', 'Writing some text');
DEMO HERE

Pagination Alternatives

I am looking for ideas for pagination alternatives. I am aware of 2 pagination schemes:
Click on pages pagination - my favorite example
Infinite scroll pagination - one implementation here that seems to work
There must be some other less known/popular ways to do it. Bonus points if you can provide a link to a demo
Thanks
I think that a good alternative to paging is a way, or more than one way, for the user to tell the server something about what it is they're looking for. For some types of content (like, a whole lot of text, say from a research paper or a work of fiction), of course you're probably stuck with paging. But when the content is naturally searchable (like tables of checking account transactions), good, simple filtering tools are probably more useful than pagination schemes. (Actually you may need both.)
I worked on a GWT hybrid technique where it did an "infinite scroll" but only showed a "window/page" of information at a time. So it only loaded a fixed amount of data to the browser at any given time. If you could display 20 items and scrolled it just updated the list 20 items at a time. Paging without paging, scrolling without scrolling.
Of course this is a trivial definition of the actual implementation, which was much smarter than this sounds and very optimized for round trips. And this was a list of results that was already filtered down with search criteria. They go hand in hand.
Take a look at 'logarithmic' pagination, as described in my answer here:
How to do page navigation for many, many pages? Logarithmic page navigation
It's like regular pagination, but solves the problem of getting to pages in the middle of a '...' range without many repeated mouseclicks. i.e. How long would it take to get to page 2456 out of 10380 if these are your links: 1 2 3 4 5 ... 10376 10377 10378 10379 10380 ?
(But, Pointy has, uhm... a point also (!))
Here is the code for a pure JavaScript pagination control I built recently. It is similar to your favorite with these added benefits...
Clicking the ... allows quick jump to any page
No words means no localization (next, prev, first, last buttons aren't
needed in this simple control)
No dependencies (jQuery not required)
var Pagination = {
code: '',
Extend: function(data) {
data = data || {};
Pagination.size = data.size || 300;
Pagination.page = data.page || 1;
Pagination.step = data.step || 3;
},
Add: function(s, f) {
for (var i = s; i < f; i++) {
Pagination.code += '<a>' + i + '</a>';
}
},
Last: function() {
Pagination.code += '<i>...</i><a>' + Pagination.size + '</a>';
},
First: function() {
Pagination.code += '<a>1</a><i>...</i>';
},
Click: function() {
Pagination.page = +this.innerHTML;
Pagination.Start();
},
Prev: function() {
Pagination.page--;
if (Pagination.page < 1) {
Pagination.page = 1;
}
Pagination.Start();
},
Next: function() {
Pagination.page++;
if (Pagination.page > Pagination.size) {
Pagination.page = Pagination.size;
}
Pagination.Start();
},
TypePage: function() {
Pagination.code = '<input onclick="this.setSelectionRange(0, this.value.length);this.focus();" onkeypress="if (event.keyCode == 13) { this.blur(); }" value="' + Pagination.page + '" /> / ' + Pagination.size;
Pagination.Finish();
var v = Pagination.e.getElementsByTagName('input')[0];
v.click();
v.addEventListener("blur", function(event) {
var p = parseInt(this.value);
if (!isNaN(parseFloat(p)) && isFinite(p)) {
if (p > Pagination.size) {
p = Pagination.size;
} else if (p < 1) {
p = 1;
}
} else {
p = Pagination.page;
}
Pagination.Init(document.getElementById('pagination'), {
size: Pagination.size,
page: p,
step: Pagination.step
});
}, false);
},
Bind: function() {
var a = Pagination.e.getElementsByTagName('a');
for (var i = 0; i < a.length; i++) {
if (+a[i].innerHTML === Pagination.page) a[i].className = 'current';
a[i].addEventListener('click', Pagination.Click, false);
}
var d = Pagination.e.getElementsByTagName('i');
for (i = 0; i < d.length; i++) {
d[i].addEventListener('click', Pagination.TypePage, false);
}
},
Finish: function() {
Pagination.e.innerHTML = Pagination.code;
Pagination.code = '';
Pagination.Bind();
},
Start: function() {
if (Pagination.size < Pagination.step * 2 + 6) {
Pagination.Add(1, Pagination.size + 1);
} else if (Pagination.page < Pagination.step * 2 + 1) {
Pagination.Add(1, Pagination.step * 2 + 4);
Pagination.Last();
} else if (Pagination.page > Pagination.size - Pagination.step * 2) {
Pagination.First();
Pagination.Add(Pagination.size - Pagination.step * 2 - 2, Pagination.size + 1);
} else {
Pagination.First();
Pagination.Add(Pagination.page - Pagination.step, Pagination.page + Pagination.step + 1);
Pagination.Last();
}
Pagination.Finish();
},
Buttons: function(e) {
var nav = e.getElementsByTagName('a');
nav[0].addEventListener('click', Pagination.Prev, false);
nav[1].addEventListener('click', Pagination.Next, false);
},
Create: function(e) {
var html = [
'<a>◄</a>', // previous button
'<span></span>', // pagination container
'<a>►</a>' // next button
];
e.innerHTML = html.join('');
Pagination.e = e.getElementsByTagName('span')[0];
Pagination.Buttons(e);
},
Init: function(e, data) {
Pagination.Extend(data);
Pagination.Create(e);
Pagination.Start();
}
};
var init = function() {
Pagination.Init(document.getElementById('pagination'), {
size: 30, // pages size
page: 1, // selected page
step: 2 // pages before and after current
});
};
document.addEventListener('DOMContentLoaded', init, false);
html {
height: 100%;
width: 100%;
background-color: #ffffff;
}
body {
margin: 0;
height: 100%;
width: 100%;
text-align: center;
font-family: Arial, sans-serif;
}
body:before {
content: '';
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
}
#pagination {
display: inline-block;
vertical-align: middle;
padding: 1px 2px 4px 2px;
font-size: 12px;
color: #7D7D7D;
}
#pagination a,
#pagination i {
display: inline-block;
vertical-align: middle;
width: 22px;
color: #7D7D7D;
text-align: center;
padding: 4px 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
#pagination a {
margin: 0 2px 0 2px;
cursor: pointer;
}
#pagination a:hover {
background-color: #999;
color: #fff;
}
#pagination i {
border: 2px solid transparent;
cursor: pointer;
}
#pagination i:hover {
border: 2px solid #999;
cursor: pointer;
}
#pagination input {
width: 40px;
padding: 2px 4px;
color: #7D7D7D;
text-align: right;
}
#pagination a.current {
border: 1px solid #E9E9E9;
background-color: #666;
color: #fff;
}
<div id="pagination"></div>
There's a cool logarithmic pagination solution here:
http://jobcloud.cz/glPagiSmart.jc
But I'm not sure how many people would actually want to use the hex or binary implementations :)

Categories