I have infinite scroll working w/ one set of data properly. When I'm doing a similar task (image index) using an HTML table, the loadMore() function is being called far too often. Generally one light scroll will go through the whole set of data. Google didn't give me a specific example using a table, so wondering if I'm messing something up.
<table>
<span infinite-scroll="loadMore()" infinite-scroll-distance='2' infinite-scroll-disabled="load_disabled">
<tr data-ng-repeat="row in data">
<td data-ng-repeat="item in row">
<div class="image_box">
<img data-ng-src="{{item.thumb_src}}"><br>{{item.title_eng}}
</div>
</td>
</tr>
</span>
</table>
Javascript. Note that $scope.data is an array of arrays of my items. $scope.data[0] will have 5 items, which hold a thumbnail, and a bit of text.
angular.module('myApp', ['ngRoute','infinite-scroll'])
.controller("imageController",
['$scope',
'$http',
'$routeParams',
'$rootElement',
'$location',
function($scope,$http,$routeParams,$rootElement,$location) {
$scope.data = new Array();
row = -1;
for ( var i = 0; i < 100; i++ ) {
if ( i % 5 == 0 ) {
row++;
$scope.data[row] = new Array();
}
var item = [];
item["title_eng"] = "title " + i;
$scope.data[row].push( item );
}
console.log( "We got " + row + 1 + " rows." );
$scope.rows = new Array();
var row_ix = 0;
$scope.loadMore = function() {
if ( !$scope.data[row_ix] || !$scope.data[row_ix].length ) {
return;
}
var x = 1; // 1 at a time
console.log( "row_ix: " + row_ix + "." );
for ( var i = 0; i < x; i++ ) {
$scope.rows[row_ix] = new Array();
$scope.rows[row_ix] = $scope.data[row_ix].slice(0);
row_ix++;
}
}
angular.module('infinite-scroll').value('THROTTLE_MILLISECONDS', 250);\
EDIT: Coming back to this after some time off. The Throttle seems to not be working. :(
Related
I have a div on a website that needs to be a real time agenda for a list of events. I have the events loaded through a json file and am using javascript to populate the div with the data from the file.
The problem is that the data displays stacked item by item in one column within a div, I need to now split the div into three separate columns/divs. One for events happening now, next, and coming soon. Ex) one event is at 7am, next is 7:30, and coming soon is 8am.
But I am not able to select each item and move it using css since the code just populates by one item upon page load and I cannot see an index for each item (video side content item) over and over to display what events are necessary.
This would be a lot easier if I could just format the items being populated into three separate columns through css, but I can't figure out how to do this.
By the way this site is written using FlexBox, hence why there is a "row" in one of the divs.
Also can someone please point in the right direction as to how to get this to be real time? Or any other helpful solution that could achieve this?
Thanks in advance for any help.
picture of what I'm trying to do
Function to populate the data
function agendaRealTimeUpdate() {
if ($('.real-time-agenda').length !== 0) {
videoSideContentType = 'agenda';
$.getJSON("ac.json", function(data) {
var sessions = data.session;
var contentString = '';
var currentSessionIndex;
var currentSession;
var currentTime;
var currentDay;
var title;
var time;
var room;
var description;
var d;
var i = 0;
d = new Date();
//gets the current time and returns it in a string with 3-4 digits EX: "1000" = 10 am
currentTime = parseInt(d.getHours().toString() + ((d.getMinutes() < 10 ? '0' : '') + d.getMinutes()).toString());
currentDay = d.getDate();
// this loop runs as long as we haven't figured out which session matches the time
while (currentSessionIndex === undefined && i < sessions.length) {
//this takes the current time and compares it to the sessions start and end times
if ((currentTime >= sessions[i].startTime && currentTime <= sessions[i].endTime) &&
currentDay === sessions[i].day &&
sessions[i].track === "none")
{
currentSessionIndex = i;
}
i++;
}
if (currentSessionIndex === undefined) {
currentSessionIndex = 0;
}
// This function finds the sessions that come after the identified current session
function findNextSessions() {
var sessionsCopy = sessions.slice(); //make a copy of the sessions array so we aren't altering it when we remove indexes
for (var z = 0; z < 2; z++) {
var index = currentSessionIndex + z;
// breaks out of the loop if the next session is undefined
if (sessionsCopy[index] === undefined) {
z = 2;
}
currentSession = sessionsCopy[index];
// loops through the sessions and if the session has a track it is removed from the sessionsCopy array
while (currentSession.track !== "none") {
console.log('has a track: ' + currentSession.track);
sessionsCopy.splice(index, 1);
currentSession = sessionsCopy[index];
}
time = currentSession.timeString !== undefined ? "<div class='video-side-content__time'><b>Time:</b> " + currentSession.timeString + "</div>" : '';
room = currentSession.room !== undefined ? "<div class='video-side-content__room'><b>Room:</b> " + currentSession.room + "</div>" : '';
title = currentSession.title !== undefined ? "<div class='video-side-content__secondary-title'>" + currentSession.title + "</div>" : '';
description = currentSession.content !== undefined ? "<div class='video-side-content__content'>" + currentSession.content + "</div>" : '';
contentString += "<div class='video-side-content__item'>" + time + room + title + description + "</div>";
}
}
findNextSessions();
$('.real-time-agenda').html(contentString);
});
}
}
Div I'm working with
<div class="row__item">
<h2 class="video-side-content__title"><img src="img/agenda-icon.png"> Thursday. Sept. 22</h2>
<div class="row__flex-container">
<div class="row__item video-side-content__strip video-side-content__strip-left"> </div>
<div class="row__item video-side-content__row">
<div class="video-side-content">
<div class="video-side-content__items">
<div class="video-side-content__item">
<h2 class="count-down__sub-header"><br>
SHOWING NOW</h2><br>
<div class="real-time-agenda">
<!--data populates upon page load from the json file
It lays the data out as: Time, Title, Room, Description-->
</div>
<br>
</div>
</div>
</div>
</div>
</div>
</div>
I am currently working on a little recreational Google Apps Script (GAS) for EVE Online and I have hit a brick wall when I am getting my server side functions talking to my client side ones.
HTML:
<form id="frm1" name = "mat_add">
<input width="1000" type="text" name="mat" value="Enter Item Here"><br />
<input type="button" value="Submit" name="mat_sub" onclick= "google.script.run.withSuccessHandler(onSuccess).shortlist(this.parentNode,document.getElementById('spn1').innerHTML)">
</form>
<span id="spn1"><table><tr><td>Type Name</td><td>Type ID</td></tr></table></span>
<script>
function onSuccess(output) {
document.getElementById(output[0]).innerHTML = output[1];
};
</script>
GAS:
function doGet() {
return HtmlService.createTemplateFromFile('Index').evaluate().setTitle('UMX Web App');
};
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
};
function shortlist(form,table) {
var arr = transpose(htmlToArray(table));
var item = form.mat;
if ( isNaN(item) ) {
var url = 'https://www.fuzzwork.co.uk/api/typeid2.php?format=xml&typename=' + item.toString();
} else {
var url = 'https://api.eveonline.com/eve/TypeName.xml.aspx?ids=' + item.toString();
};
var xml = UrlFetchApp.fetch(url).getContentText();
var document = XmlService.parse(xml);
var name = document.getRootElement().getChild('result').getChild('rowset').getChild('row').getAttribute('typeName').getValue();
if ( arr[0].indexOf(name) == -1 && name != 'Unknown Type' && name != 'bad item' ) {
arr[0].push(name);
arr[1].push(document.getRootElement().getChild('result').getChild('rowset').getChild('row').getAttribute('typeID').getValue());
};
var str = arrayToHTML(transpose(arr));
return ['spn1',str]
};
function arrayToHTML(arr) {
var i = 0;
var j = 0;
var str = '<table>';
while ( i < arr.length ) {
str = str + '<tr>';
while ( j < arr[i].length ) {
str = str + '<td>' + arr[i][j] + '</td>';
j += 1
};
str = str + '</tr>';
j = 0;
i += 1
};
str = str + '</table>';
return str
};
function htmlToArray(str) {
var arr1 = str.replace(/<tr>/g,'</tr>').split('</tr>');
var arr2 = [];
var i = 1;
var j = 1;
var x = [];
while ( i < arr1.length ) {
arr2.push([]);
x = arr1[i].replace(/<td>/g,'</td>').split('</td>');
while ( j < x.length ) {
arr2[arr2.length - 1].push(x[j]);
j += 2
};
j = 1;
i += 2
};
return arr2
};
function transpose(input) {
var output = [];
var i = 0;
var j = 0;
while ( i < input[0].length ) {
output.push([]);
while ( j < input.length ) {
output[i].push(input[j][i]);
j += 1
};
j = 0;
i += 1
};
return output
};
function direct(input) {
return input
}
The problem seems to be on the submit button because everything else is working fine. I have been looking for a workaround but that submit button is the only point of entry I can get and it will not accept more than one variable.
The problem seems to be on the submit button because everything else is working fine. I have been looking for a workaround but that submit button is the only point of entry I can get and it will not accept more than one variable.
Let's focus on this, and ignore all the irrelevant code. Basic question: how to get multiple inputs from a form to a server-side GAS function?
This example will demonstrate communication of the form object to the server, by throwing an error that contains all the received parameters. An errorHandler on the client side will alert with the received error message.
Index.html
<form id="frm1" name = "mat_add">
<input width="1000" type="text" name="mat" placeholder="Enter Item Here" /><br />
<input width="1000" type="text" name="mat2" placeholder="Enter Quantity Here" /><br />
<input type="button" value="Submit" name="mat_sub" onclick="google.script.run
.withSuccessHandler(onSuccess)
.withFailureHandler(onFailure)
.shortlist(this.parentNode)" />
</form>
<script>
function onSuccess(output) {
document.getElementById(output[0]).innerHTML = output[1];
};
function onFailure(error) {
alert( error.message );
}
</script>
Code.gs
function doGet() {
return HtmlService.createTemplateFromFile('Index').evaluate().setTitle('UMX Web App');
};
function shortlist(input) {
reportErr(JSON.stringify(input,null,2))
}
function reportErr(msg) {
throw new Error( msg );
}
Run this webapp, and here's your result:
The two named input elements, mat and mat2 were communicated to the server function shortlist() via the this.parent parameter. Since the button invoking this.parent in its clickHandler is contained in the frm1 form, all input elements of that form were included, and may be referenced on the server side as named properties of the input parameter of shortlist(). (NOT as array elements.)
The upshot of this is that your shortlist() function can be modified thusly:
function shortlist(input) {
var item = input.mat;
if ( isNaN(item) ) {
var url = 'https://www.fuzzwork.co.uk/api/typeid2.php?format=xml&typename=' + item;
} else {
var url = 'https://api.eveonline.com/eve/TypeName.xml.aspx?ids=' + item.toString();
};
...
I have a page with two columns of a fixed height. The items in each column are ng-repeated.
How can I scroll within each column to a certain id? is that possible with AngularJS?
Code
<div>
Scroll to a position
Column #: <input style="width: 20px;">
Item #: <input style="width: 20px;">
</div>
<div class='column'>Column one
<div id="col-1-{{$index}}" class='item' ng-repeat='item in itemsOne track by $index'>
{{$index}} ..... {{item}}
</div>
</div>
<div class='column'>Column two
<div id="col-2-{{$index}}" class='item' ng-repeat='item in itemsTwo track by $index'>
{{$index}} ..... {{item}}
</div>
</div>
JS:
app.controller( 'myCtrl', [ '$scope', function ( $scope ){
$scope.value = 'test';
$scope.itemsOne = [];
$scope.itemsTwo = [];
for(var i=0; i<10; i++){
$scope.itemsOne.push(makeSentence());
$scope.itemsTwo.push(makeSentence());
}
function makeSentence() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < Math.random() * 200; i++ ){
for( var i=0; i < Math.random() * possible.length; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
text += " ";
}
//console.log(text);
return text;
}
$scope.scrollMeTo = function(column, row){
// scroll me to an area in a column
};
}] );
http://plnkr.co/edit/WYtntRagJdQoK7k6fAPc?p=preview
I changed your plunkr to make it work, there is room for a lot of improvement, but please take notice that when you need to handle things in the DOM, you must always do that using directives, as the one I made:
app.directive('autoScrollTo', function () {
return function(scope, element, attrs) {
scope.$watch(attrs.autoScrollTo, function(value) {
if (value) {
var pos = $("#" +attrs.prefixId +value, $(element)).position().top + $(element).scrollTop() - $(element).position().top;
$(element).animate({
scrollTop : pos
}, 1000);
}
});
}
});
See it running: http://plnkr.co/edit/2gb8ZdZ5DPanRBVQvTwa?p=preview
Hope that helps.
I have some divs in the page that show different things of the same kind, for example offers, now offers have ending time, and also posted time, if the user wants to order by ending time, or posted time, they should be re ordered.
I'm looking for a javascript solution that could do that, any particular libraries under Ext JS , or JQuery would work
Here is how these divs look like
<div data-sortunit="1" data-sort1="40" data-sort2="156" data-sort3="1"
data-sort4="1317620220" class="item">
</div>
<div data-sortunit="2" data-sort1="30" data-sort2="116" data-sort3="5"
data-sort4="1317620220" class="item">
</div>
<div data-sortunit="3" data-sort1="10" data-sort2="157" data-sort3="2"
data-sort4="1317620220" class="item">
</div>
So I wanna be able to sort these divs based on data-sortN, N being an integer
Edit: OK, now that you've supplied some HTML, here's javascript code that will sort that specific HTML by the desired column number:
function sortByDataItem(containerID, dataNum) {
var values = [];
$("#" + containerID + " .item").each(function(index) {
var item = {};
item.index = index;
item.obj = this;
item.value = $(this).data("sort" + dataNum);
values.push(item);
});
values.sort(function(a, b) {return(b.value - a.value);});
var container = $("#" + containerID);
for (var i = 0; i < values.length; i++) {
var self = $(values[i].obj);
self.detach();
container.prepend(self);
}
return;
}
$("#sort").click(function() {
var sortValue = $("#sortColumn").val();
if (sortValue) {
sortValue = parseInt(sortValue, 10);
if (sortValue && sortValue > 0 && sortValue <= 3) {
sortByDataItem("container", sortValue);
return;
}
}
$("#msg").show(1).delay(5000).fadeOut('slow');
});
You can see it work here in a jsFiddle: http://jsfiddle.net/jfriend00/JG32X/
Since you've given us no HTML to go on, I've made my own HTML and shown you how you can use jQuery to sort:
HTML:
<button id="sort">Sort</button><br>
<div id="productList">
<div class="row"><div class="productName">Popcorn</div><div class="price">$5.00</div></div>
<div class="row"><div class="productName">Peanuts</div><div class="price">$4.00</div></div>
<div class="row"><div class="productName">Cookie</div><div class="price">$3.00</div></div>
<div class="row"><div class="productName">Beer</div><div class="price">$5.50</div></div>
<div class="row"><div class="productName">Soda</div><div class="price">$4.50</div></div>
</div>
Javascript (run after page is loaded):
$("#sort").click(function() {
var prices = [];
// find all prices
$("#productList .price").each(function(index) {
var str = $(this).text();
var item = {};
var matches = str.match(/\d+\.\d+/);
if (matches && matches.length > 0) {
// parse price and add it to the prices array
item.price = parseFloat(matches[0]);
item.row = $(this).closest(".row").get(0);
item.index = index;
prices.push(item);
}
});
// now the prices array has all the prices in it
// sort it using a custom sort function
prices.sort(function(a, b) {
return(a.price - b.price);
});
// now pull each row out and put it at the beginning
// starting from the end of the prices list
var productList = $("#productList");
for (var i = prices.length - 1; i >= 0; i--) {
var self = $(prices[i].row);
self.detach();
productList.prepend(self);
}
});
And, a jsFiddle that shows it in action: http://jsfiddle.net/jfriend00/vRdrA/.
I made a tiny jqueryPlugin out of jfriend00's answer:
(function($){
$.fn.sortChildrenByDataKey = function(key, desc){
var i, els = this.children().sort(function(a, b) {return (desc?1:-1)*($(a).data(key) - $(b).data(key));});
for (i = 0; i < els.length; i++) {
this.prepend($(els[i]).detach());
}
return this;
};
})(jQuery);
Your HTML:
<div id="myContainer">
<div data-myKey="4"> ... </div>
<div data-myKey="2"> ... </div>
...
</div>
Usage:
$('div#myContainer').sortChildrenByDataKey('myKey', true_or_false);
The children of the container can be any Elements. Its only important, that they are immediate children and have data-X key.
Thank you, jfriend00!!
Have the following script:
var CurrentPageTop = 0;
var PageHeight = 496;
var TotalPages = 9;
var CurrenPage = 1;
function Slide( control, panel ){
if ( control.name == "SlideDown" ){
if ( (CurrenPage >= 1) && (CurrenPage <= TotalPages-1) ){
CurrenPage++;
CurrentPageTop = ( CurrentPageTop - PageHeight );
}
}
if ( control.name == "SlideUp" ){
if ( (CurrenPage > 1) && (CurrenPage <= TotalPages) ){
CurrenPage--;
CurrentPageTop = (CurrentPageTop + PageHeight);
}
}
var PanelScroller = document.getElementById(panel);
PanelScroller.style.top = CurrentPageTop + 'px';
var CurrenPageId = document.getElementById("CurrenPageId");
CurrenPageId.innerHTML = "Page " + CurrenPage + " of 9";
}
which accompanies a single image gallery on a page:
<table cellpadding="0" cellspacing="0">
<tr>
<td>
<div class="SlidingPanel">
<div id="PanelScroller">
<div class="Page">
<img src="i/gal/g1.jpg">
</div>
How would I set this up to have multiple instances on one page?
Some galleries have 9 images, some have 6, etc.
Is there a way to count the number of <div class="Page"> within a <div id="PanelScroller"> ?
I want to avoid having to use 3 slightly different instances of this script for 3 different galleries. I just can't wrap my head around it because I'm a novice.
function number_of_elements_with_class_name(class_name) {
var elements = getElementsByClassName(class_name);
var count = 0;
for(var i in elements) {
count++;
}
return count;
}
node.getElementsByClassName()
http://www.quirksmode.org/blog/archives/2008/05/getelementsbycl.html