I am having some trouble finding a way to push into an array based on the div.
My goal is to add up the amount of time that I am hovering over each element. Instead, of creating the same function for each div. I wanted to try a DRY approach. This is difficult to visualize.
I want to change the array I am pushing into when I change the div. I have figured out a way to add all of the time into one array. However this is not my goal.
Here is a very shortened version of my code and I am attaching a plunker to show how it is working. In the console you can see the time change.
http://plnkr.co/edit/zBRyix6TJjTjvp7OCrMC?p=preview
I am pushing into the timeArray. Ideally I could push into panelHeading array or panelHeadingArray
Here is my iffe being used in a DRY approach.
var timeMonitering = (function() {
var mouseenterTime = 0;
var timeArray = [];
var navArray = [];
var panelHeadingArray = [];
return {
inAndOut: inAndOut
}
function inAndOut(evt) {
var currentTime = new Date();
var mouseoverTime;
if(evt.type === 'mouseenter') {
mouseenterTime = currentTime.getTime();
}
else if (evt.type === 'mouseleave') {
mouseoverTime =currentTime.getTime();
}
var time =mouseoverTime - mouseenterTime;
if(time >0) {
timeArray.push(time/1000);
}
console.log('time array added',Math.round(timeArray.reduce(add,0) ));
return time/1000;
}
function add(a,b) {
return a +b;
}
})();
$(document).on('ready', function() {
$('.navbar').bind('mouseenter mouseleave', timeMonitering.inAndOut);
$('.panel-heading').bind('mouseenter mouseleave', timeMonitering.inAndOut);
});
Need to figure out how to push into navArray or panelHeadingArray
depending on where I mouseover.
Any help would be greatly appreciated.
*********Update ****************
Here is how I essentially was able to add each array's time up.
The jumbotronArray adds the seconds up as I hover over the element. However, I would like to reuse this function or like the one I showed above.
var enteredTime = 0;
var jumbotronArray = [];
var listGroupArray = [];
$('.jumbotron').hover(function(evt) {
enteredTime = new Date();
console.log('e',enteredTime)
}, function() {
var ctime = new Date();
var time = (ctime.getTime() - enteredTime.getTime())/1000;
jumbotronArray.push(time);
console.log('time spend ' + time/1000 + 'sec');
console.log('jumbotronArray',jumbotronArray)
console.log('added',Math.round(jumbotronArray.reduce(add,0) ));
})
$('.list-group').hover(function(evt) {
enteredTime = new Date();
}, function() {
var ctime = new Date();
var time = (ctime.getTime() - enteredTime.getTime())/1000;
listGroupArray.push(time);
console.log('listGroupArray',listGroupArray)
console.log('listGroupArray added',Math.round(listGroupArray.reduce(add,0) ));
})
function add(a,b) {
return a +b;
}
You could select which array using a conditional and then call push on it.
var array;
if (condition) {
array = navArray;
} else {
array = panelHeadingArray;
}
array.push(...);
or more concisely using the ternary operator
(condition ? navArray : panelHeadingArray).push(...)
Edit:
var enteredTime = 0;
var jumbotronArray = [];
var listGroupArray = [];
var mapping = {
".jumbotron": jumbotronArray,
".list-group": listGroupArray
};
Object.keys(mapping).forEach(function(selector) {
$(selector).hover(function(evt) {
enteredTime = new Date();
}, function() {
var ctime = new Date();
var time = (ctime.getTime() - enteredTime.getTime())/1000;
mapping[selector].push(time);
});
}
Related
I am trying to add a moreLink in full calendar on each day i have events and in the more link i want to force displaying all the events on that day!
this is the solutin i choose because the title of the events are very long and do not fit in a tablet or phone screen!
so far i am unsuccesfull on the days i have one single event because the function computeRowLevelLimit returns false!
i am open to any crazy idea that helps me but keep in mind that i am a java dev with minimal kowledge of js and add some extra info if possible
since i was under presure i took the matter in my own hands so here is the resolve
here i added the last else in order to be able to execute 2 methods when levelLimit is false
limitRows: function (levelLimit) {
var rowStructs = this.eventRenderer.rowStructs || [];
var row; // row #
var rowLevelLimit;
for (row = 0; row < rowStructs.length; row++) {
this.unlimitRow(row);
if (!levelLimit) {
rowLevelLimit = false;
}
else if (typeof levelLimit === 'number') {
rowLevelLimit = levelLimit;
}
else {
rowLevelLimit = this.computeRowLevelLimit(row);
}
if (rowLevelLimit !== false) {
this.limitRow(row, rowLevelLimit);
} else {
this.unlimitRow2(row);
this.addMoreLink(row);
}
}
},
The added metod are:
- one for clearing the existing links
- second for adding new links - remember this is for days with only one event
the methods are the following:
unlimitRow2: function (row) {
var rowStruct = this.eventRenderer.rowStructs[row];
var cellMatrix;
var oneDayCell;
cellMatrix = rowStruct.cellMatrix;
var _this = this;
for (i = 0; i < cellMatrix.length; i++) {
// console.log("celmatrix ", cellMatrix[i]);
oneDayCell = cellMatrix[i];
console.log("outati", oneDayCell)
if (oneDayCell.moreEls) {
oneDayCell.moreEls.remove();
oneDayCell.moreEls = null;
}
if (oneDayCell.limitedEls) {
oneDayCell.limitedEls.removeClass('fc-limited');
oneDayCell.limitedEls = null;
}
}
},
and,
addMoreLink: function (row) {
// console.log("inside addMoreMethod", row);
var rowStruct = this.eventRenderer.rowStructs[row];
var cellMatrix;
var oneDayCell;
var coloana;
var nrCol;
var td, moreWrap, moreLink;
var moreNodes = [];
var segsBelow;
// console.log ("structura randului", rowStruct);
cellMatrix = rowStruct.cellMatrix;
var _this = this;
for (i = 0; i < cellMatrix.length; i++) {
// console.log("celmatrix ", cellMatrix[i]);
oneDayCell = cellMatrix[i];
for (j = 0; j < oneDayCell.length; j++) {
coloana = oneDayCell[j];
nrCol = j;
segsBelow = _this.getCellSegs(row, nrCol);
console.log($(coloana));
moreLink = _this.renderMoreLink(row, nrCol, segsBelow);
moreWrap = $('<div/>').append(moreLink);
coloana.append(moreWrap);
moreNodes.push(moreWrap[0]);
// rowStruct.limitedEls = $(limitedNodes);
}
rowStruct.moreEls = $(moreNodes); // for easy undoing later
}
},
and for the rest i manipulated a litle bit limitRow: function (row, levelLimit)
also i had to hide the text and i choose a nasty method, not proud of it but ...
in getMoreLinkText(num) i added a last else if
else if (num === 0 ){
return '';
}
I have an object "Driver" defined at the beginning of my script as such:
function Driver(draw, name) {
this.draw = draw;
this.name = name;
}
I'm using this bit of JQuery to create new drivers:
var main = function () {
// add driver to table
$('#button').click(function ( ) {
var name = $('input[name=name]').val();
var draw = $('input[name=draw]').val();
var draw2 = "#"+draw;
var name2 = "driver"+draw
console.log(draw2);
console.log(name2);
if($(name2).text().length > 0){
alert("That number has already been selected");}
else{$(name2).text(name);
var name2 = new Driver(draw, name);}
});
That part is working great. However, when I try later on to access those drivers, the console returns that it is undefined:
$('.print').click(function ( ) {
for(var i=1; i<60; i++){
var driverList = "driver"+i;
if($(driverList.draw>0)){
console.log(driverList);
console.log(driverList.name);
}
If you're interested, I've uploaded the entire project I'm working on to this site:
http://precisioncomputerservices.com/slideways/index.html
Basically, the bottom bit of code is just to try to see if I'm accessing the drivers in the correct manner (which, I'm obviously not). Once I know how to access them, I'm going to save them to a file to be used on a different page.
Also a problem is the If Statement in the last bit of code. I'm trying to get it to print only drivers that have actually been inputed into the form. I have a space for 60 drivers, but not all of them will be used, and the ones that are used won't be consecutive.
Thanks for helping out the new guy.
You can't use a variable to refer to a variable as you have done.
In your case one option is to use an key/value based object like
var drivers = {};
var main = function () {
// add driver to table
$('#button').click(function () {
var name = $('input[name=name]').val();
var draw = $('input[name=draw]').val();
var draw2 = "#" + draw;
var name2 = "driver" + draw
console.log(draw2);
console.log(name2);
if ($(name2).text().length > 0) {
alert("That number has already been selected");
} else {
$(name2).text(name);
drivers[name2] = new Driver(draw, name);
}
});
$('.print').click(function () {
for (var i = 1; i < 60; i++) {
var name2 = "driver" + i;
var driver = drivers[name2];
if (driver.draw > 0) {
console.log(driver);
console.log(driver.name);
}
I have this object constructor function that has a preload method for preloading
rollover images pairs.
So, I have two questions:
1: why is the alert dialog just doing 'STR: ' with no data attached? (this type of problem is generally due to my blindness.
2: is it possible to treat the this.buttons_on and this.buttons_off as objects in that instead of
a numerical index, use a sting index so the rollover event handler does not need to loop through
the buttons_on and buttons_off arrays to get the one that should be swapped out;
function _NAV()
{
this.list_off = [];
this.list_on = [];
this.buttons_on = [];
this.buttons_off = [];
this.buttons_all = {}; // .on and .off
this.button_events = {};
this.img = true;
this.img_ids = {}
this.preLoad = function()
{
if(document.images) //creates image object array for preload.
{
var STR = '';
for(var i = 0; i < list_off.length; i++)
{
var lab_on = list_on[i].replace('\.jpg', '');
var lab_off = list_off[i].replace('\.jpg', '');
STR += lab_on+'||'+lab_off+"\n";
this.buttons_on[i] = new Image();
this.buttons_on[i].src = srcPath+list_on[i];
this.bottons_on[i].id = img_ids[i];
this.buttons_off[i] = new Image();
this.buttons_off[i].src = srcPath+list_off[i];
this.buttons_off[i].id = img_ids[i];
}
alert("STR: "+STR);
}
else
{
this.img = false
}
}
//// ...etc...
Here is the call before the onload event fires
var rollover = new _NAV();
rollover.preLoad();
Here are the arrays used
var srcPath = '../nav_buttons/';
var list_off = new Array(); // not new Object;
list_off[0] = "bio_off.jpg";
list_off[1] = "cd_off.jpg";
list_off[2] = "home_off.jpg";
list_off[3] = "inst_off.jpg";
list_off[4] = "photo_off.jpg";
list_off[5] = "rev_off.jpg";
list_off[6] = "samp_off.jpg";
var list_on = new Array();
list_on[0] = "bio_on.jpg";
list_on[1] = "cd_on.jpg";
list_on[2] = "home_on.jpg";
list_on[3] = "inst_on.jpg";
list_on[4] = "photo_on.jpg";
list_on[5] = "rev_on.jpg";
list_on[6] = "samp_on.jpg";
var img_ids = new Array();
Thanks for time and attention.
1:
Try PHPGlue's suggestion and add this. in front of all your member variables (this.list_on, this.list_off, this.img_ids)
You also have a typo on one line. bottons_on is misspelled.
this.bottons_on[i].id = img_ids[i];
2:
Yes, you can use a string as an index. Just make buttons_on and buttons_off objects instead of arrays.
function _NAV()
{
this.buttons_on = {};
this.buttons_off = {};
// For example:
this.buttons_off[lab_off] = new Image();
}
I have follow two functions here which working great!
As you can see these two functions are almost the same, except the code which comes below the last comment in each function.
How do I make that more simple. Could I make a code-"holder" - Where I only include a part of a code from another file? So I don't have too have the "same" code in each functions?
Should I use some kind of classes or? - I have never worked with classes.
/// Function (add_new_field)
$(document).on("click", '.add_new_field', function(e) {
e.preventDefault();
var flex0 = $(this);
var flex1 = $(this).parent().closest('div');
var flex2 = $(flex1).parent().closest('div');
var flex3 = $(flex2).parent().closest('div');
var flex4 = $(flex3).parent().closest('div');
var flex5 = $(flex4).parent().closest('div');
var flex6 = $(flex5).parent().closest('div');
/*console.log(
' -> WrapID:'+flex6.attr('id')+
' -> accordionContentID:'+flex5.attr('id')+
' -> acContentBoxID:'+flex4.attr('id')+
' -> acChildBoxID:'+flex3.attr('id')+
' -> acBabyBoxID:'+flex2.attr('id')+
' -> SecondID:'+flex1.attr('id')+
' -> FirstID:'+flex0.attr('id')
);*/
var wrapID = flex6.attr('id'); // wrapID
var accordionContentID = flex5.attr('id');
var acContentBoxID = flex4.attr('id'); // sharedID
var acChildBoxID = flex3.attr('id'); // langID
var acBabyBoxID = flex2.attr('id'); // langID
var SecondID = flex1.attr('id'); // OLD : AddLangBoxID
var FirstID = flex0.attr('id'); // OLD : add_new_fieldID
// there is a lot more code here...
)};
/// Function (del_field)
$(document).on("click", '.del_field', function(e) {
e.preventDefault();
var flex0 = $(this);
var flex1 = $(this).parent().closest('div');
var flex2 = $(flex1).parent().closest('div');
var flex3 = $(flex2).parent().closest('div');
var flex4 = $(flex3).parent().closest('div');
var flex5 = $(flex4).parent().closest('div');
var flex6 = $(flex5).parent().closest('div');
var wrapID = flex6.attr('id'); // wrapID
var accordionContentID = flex5.attr('id');
var acContentBoxID = flex4.attr('id'); // sharedID
var acChildBoxID = flex3.attr('id'); // langID
var acBabyBoxID = flex2.attr('id'); // langID
var SecondID = flex1.attr('id'); // OLD : AddLangBoxID
var FirstID = flex0.attr('id'); // OLD : add_new_fieldID
// there is a lot more code her
)};
How could I make something like this.
/// I want to include this code into the functions. So I don't have to write it twice.
var flex0 = $(this);
var flex1 = $(this).parent().closest('div');
var flex2 = $(flex1).parent().closest('div');
var flex3 = $(flex2).parent().closest('div');
var flex4 = $(flex3).parent().closest('div');
var flex5 = $(flex4).parent().closest('div');
var flex6 = $(flex5).parent().closest('div');
var wrapID = flex6.attr('id'); // wrapID
var accordionContentID = flex5.attr('id');
var acContentBoxID = flex4.attr('id'); // sharedID
var acChildBoxID = flex3.attr('id'); // langID
var acBabyBoxID = flex2.attr('id'); // langID
var SecondID = flex1.attr('id'); // OLD : AddLangBoxID
var FirstID = flex0.attr('id'); // OLD : add_new_fieldID
Thank you.
If you want to do something like classes in javascript, your best bet is to use prototyping, since javascript doesn't have classes.
In this case, I'm not sure what your code does, so prototyping might not be the best answer. Your other option is to encapsulate all of your variable definitions in another function, and call that function in both of your click functions. It would return an object with attributes, rather that a bunch of vars.
var myVarFn = function(){
var returnObject = {};
returnObject.flex0 = $(this);
returnObject.flex1 = $(this).parent().closest('div');
...
returnObject.wrapID = flex6.attr('id'); // wrapID
...
return returnOBject
}
And to use it in click, with this defined the same as in the scope of the click function:
$(document).on("click", '.del_field', function(e) {
var dataObject = myVarFn.call(this);
//Other code
};
And in the other click event,
$(document).on("click", '.add_new_field', function(e) {
var dataObject = myVarFn.call(this);
//Other code
};
You will have to modify your other code to use dataObject.flex0 instead of flex0 and so on.
Create a global object
var allId = new Object();
And a function that can be called whenever needed..
function getAllIDs(el) {
var id = ["wrapID", "accordionContentID", "acContentBoxID", "acChildBoxID", "acBabyBoxID", "SecondID", "FirstID"];
var flex;
for (var i = 0; i <= 6; i++) {
if (i == 0) {
flex = $(el).parent().closest('div');
} else {
flex = $(flex).parent().closest('div');
}
allId.id[i] = $(flex).parent().closest('div').attr('id');
}
}
Further, on jQuery event you can call getAllIDs function
$(document).on("click", '.add_new_field', function (e) {
e.preventDefault();
getAllIDs(this);
});
More details about javascript objects
I was able to utilize paging in slickGrid however I am new to jquery and slickGrid and can't get to move in between pages. can anyone help me with this? Any help is greatly appreciated. Thanks!
$(document).ready(function() {var columns = [
{id:"counter", name:"#",field:"counter"},
{id:"data1", name:"Data 1",field:"data1"},
{id:"data2", name:"Data 2",field:"data2"},
{id:"data3", name:"Data 3",field:"data3"},
{id:"data4", name:"Data 4",field:"data4"}];
var options = { enableCellNavigation: false,
enableColumnReorder: false};
var FB_C_grid;
var FB_C_data;
var selectedRowIds = [];
var dataView;
$(function() {
FB_C_data = [];
FB_C_data[0]={"id":"0",
"data1":"test1",
"data2":"test1",
"data3":"test1",
"data4":"test1,
"counter":"1"
};
for (var i=1; i<50000; i++) {
var d = (FB_C_data[i] = {});enter code here
d["id"] = "id_" + i;
d["data1"] = "data1_" + i;
d["data2"] = "data2_" + i;
d["data3"] = "data3_" + i;
d["data4"] = "data4_" + i;
d["counter"] = i;
}
dataView = new Slick.Data.DataView();
dataView.setItems(FB_C_data);
dataView.setPagingOptions({pageSize:20});
FB_C_grid= new Slick.Grid($("#FB_C_sheet"),dataView.rows, columns,options);
var pager = new Slick.Controls.Pager(dataView, FB_C_grid, $("#pagerTest"));
dataView.onRowsChanged.subscribe(function(rows) {
FB_C_grid.removeRows(rows);
FB_C_grid.render();
if (selectedRowIds.length > 0)
{
// since how the original data maps onto rows has changed,
// the selected rows in the grid need to be updated
var selRows = [];
for (var i = 0; i < selectedRowIds.length; i++)
{
var idx = dataView.getRowById(selectedRowIds[i]);
if (idx != undefined)
selRows.push(idx);
}
FB_C_grid.setSelectedRows(selRows);
}
});
dataView.onPagingInfoChanged.subscribe(function(pagingInfo) {
var isLastPage = pagingInfo.pageSize*(pagingInfo.pageNum+1)-1 >= pagingInfo.totalRows;
var enableAddRow = isLastPage || pagingInfo.pageSize==0;
var options = FB_C_grid.getOptions();
if (options.enableAddRow != enableAddRow)
FB_C_grid.setOptions({enableAddRow:enableAddRow});
});
dataView.onRowCountChanged.subscribe(function(args) {
FB_C_grid.updateRowCount();
FB_C_grid.render();
});
})
});
I see some of your errors as you are trying to pass a jQuery object into SlickGrid while SlickGrid already uses jQuery in the code behind. When you create your SlickGrid object, you just need to pass the name of your grid and so in your code, you have to replace this $("#pagerTest") without jQuery wrapper becomes this "#pagerTest"
I see you called it the same in 2 different locations, so replace your 2 lines with this:
FB_C_grid= new Slick.Grid("#FB_C_sheet",dataView.rows, columns,options);
var pager = new Slick.Controls.Pager(dataView, FB_C_grid, "#pagerTest");
Hope that helps you make it to work...