I have gotten into a small issue I can't seam to wrap my head around, and I hope for some guidesnes from you folks.
I have a timeline with a bunch of groups and subgroups, and the height of the timeline is now bigger than the height of the monitor showing it.
And that is fine it can be scrolled using the scroll wheel on the mouse, however as it is ment to be just a timeline on a wall mounted screen it would be cool if I could make an autoscroll function, that scroll the timeline up and down in a given timeframe.
Unfortunatly I can't figure out where to implement it to make it work.
I have the following code to make a div scroll ( and have tried diffrent ways to make it do it in the vis.js code, but so far no luck )
if anyone knows of a way to make it scroll up and down in a given timeframe i would really appreciate the help.
<script language="javascript">
ScrollRate = 1;
function scrollDiv_init() {
//this can be a class also.
DivElmnt = document.getElementById('MyDivName');
ReachedMaxScroll = false;
DivElmnt.scrollTop = 0;
PreviousScrollTop = 0;
ScrollInterval = setInterval('scrollDiv()', ScrollRate);
}
function scrollDiv() {
if (!ReachedMaxScroll) {
DivElmnt.scrollTop = PreviousScrollTop;
PreviousScrollTop++;
ReachedMaxScroll = DivElmnt.scrollTop >= (DivElmnt.scrollHeight - DivElmnt.offsetHeight);
}
else {
ReachedMaxScroll = (DivElmnt.scrollTop == 0) ? false : true;
DivElmnt.scrollTop = PreviousScrollTop;
PreviousScrollTop--;
}
}
function pauseDiv() {
clearInterval(ScrollInterval);
}
function resumeDiv() {
PreviousScrollTop = DivElmnt.scrollTop;
ScrollInterval = setInterval('scrollDiv()', ScrollRate);
}
</script>
Well, the only tricky part I can see about scrolling timeline at http://visjs.org/examples/timeline/other/verticalScroll.html is that you have to scroll certain element, not the container of the timeline. If you use inspector to find the element with the scrollbar, you'll probably be surprised to see this:
Indeed, if I apply scrolling to that element
var scrollerElement = document.querySelector('#mytimeline1 div.vis-panel.vis-left.vis-vertical-scroll');
scrollerElement.scrollTop = 100;
the timeline gets scrolled vertically. By the way, the vis-vertical-scroll class suggests that we are on the right way. Actually, you should probably use a shorter selector instead:
var scrollerElement = document.querySelector('#mytimeline1 .vis-vertical-scroll');
You can try this via browser console on that page. I think this should be enough for you to implement the desired autoscrolling.
Related
I need to add back navigation on swipe. I can do that fairly easily by just adding a swipe listener to the page view and calling goBack. But I really would like the animation that goes with it (in Instagram or FB) where as soon as you start dragging your thumb, the page translates to the right and the previous page starts to translate into view. And then once you get to a certain point it actually performs the navigation.
I tried animating the page, as well as the frame to the right figuring since the view isn't being destroyed it might work. But it doesn't display the page Im navigating back to.
Looking for help on how to accomplish this!
I guess you might have come across the other SO thread answering this question natively.
All you have to do is modify the default gesture recogniser on iOS frame.
export function onNavigatedFrom(args: EventData) {
console.log("Adding gesture...");
const frame = (<Page>args.object).frame;
if (frame.ios && !(<any>frame)._gestureRecognizer) {
const controller = frame.ios.controller;
const popGestureRecognizer = controller.interactivePopGestureRecognizer;
const targets = popGestureRecognizer.valueForKey("targets");
if (targets) {
let gestureRecognizer = UIPanGestureRecognizer.alloc().init();
gestureRecognizer.setValueForKey(targets, "targets");
frame.nativeView.addGestureRecognizer(gestureRecognizer);
(<any>frame)._gestureRecognizer = gestureRecognizer;
}
}
}
export function onNavigatedTo(args: EventData) {
console.log("Back to root page, removing gesture...");
const frame = (<Page>args.object).frame;
if (frame.ios && (<any>frame)._gestureRecognizer) {
frame.nativeView.removeGestureRecognizer((<any>frame)._gestureRecognizer);
(<any>frame)._gestureRecognizer = null;
}
}
Playground Sample
I have been looking at a way to save off my client side edited grid data automatically when the user changes to another row (just like in access, sql management studio etc). It really seems to be a bit of a challenge to do.
One scheme was to use the data source sync, but this ha the problem of loosing our cell position (it always jumped to cell 0, 0).
I have been shown some clever work arounds (go back to the cell after the case, which by the way is hugely appreciated thanks),
but it after some lengthy testing (by myself and others) seemed to be a little "glitchy" (perhaps I just need to work on this more)
At any rate, I wanted to explore perhaps not using this datasource sync and perhaps just do the server side calls "manually" (which is a bit is a pity, but if that's what we need to do, so be it). If I do this, I would want to reset the cell little red cell "dirty" indicators.
I thought I could use something similar to this scheme (except rather than resetting the flag, I want to unset).
So, as in the above link, I have the following..
var pendingChanges = [];
function gridEdit(e) {
var cellHeader = $("#gridID").find("th[data-field='" + e.field + "']");
if (cellHeader[0] != undefined) {
var pendingChange = new Object();
pendingChange.PropertyName = e.field;
pendingChange.ColumnIndex = cellHeader[0].cellIndex;
pendingChange.uid = e.items[0].uid;
pendingChanges.push(pendingChange);
}
}
where we call gridEdit from the datasource change..
var dataSrc = new kendo.data.DataSource({
change: function (e) {
gridEdit(e);
},
Now assuming we have a callback that detects the row change, I thought I could do the following...
// clear cell property (red indicator)
for (var i = 0; i < pendingChanges.length; i++) {
var row = grid.tbody.find("tr[data-uid='" + pendingChanges[i].uid + "']");
var cell = row.find("td:eq(" + pendingChanges[i].ColumnIndex + ")");
if (cell.hasClass("k-dirty-cell")) {
cell.removeClass("k-dirty-cell");
console.log("removed dirty class");
}
}
pendingChanges.length = 0;
// No good, we loose current cell again! (sigh..)
//grid.refresh();
When this didn't work, I also tried resetting the data source dirty flag..
// clear dirty flag from the database
var dirtyRows = $.grep(vm.gridData.view(),
function (item) {
return item.dirty == true;
})
if (dirtyRows && dirtyRows.length > 0) {
dirtyRows[0].dirty = false;
}
demo here
After none of the above worked, I tried the grid.refresh(), but this has the same problem as the datasource sync (we loose our current cell)
Would anyone have any idea how I can clear this cell indicator, without refreshing the whole grid that seems to totally loose our editing context?
Thanks in advance for any help!
Css :
.k-dirty-clear {
border-width:0;
}
Grid edit event :
edit: function(e) {
$("#grid .k-dirty").addClass("k-dirty-clear"); //Clear indicators
$("#grid .k-dirty").removeClass("k-dirty-clear"); //Show indicators
}
http://jsbin.com/celajewuwe/2/edit
Simple solution for resolve that problem is to override the color of the "flag" to transparent.
just override the ".k-dirty" class (border-color)
just adding the above lines to your css
CSS:
//k-dirty is the class that kendo grid use for mark edited cells that not saved yet.
//we override that class cause we do not want the red flag
.k-dirty {
border-color:transparent transparent transparent transparent;
}
This can also be done by applying the below style,
<style>
.k-dirty{
display: none;
}
</style>
is there a way to implement a erase method for raphael objects. in this erase method I want to remove specific parts of a particular raphael object. It means that the erase method should work like a real eraser. In the raphael documentation there is a method call Paper.clear(). But we only can delete entire paper.
Any kind of help is appreciated.
The normal way to be to use the remove() method.
http://raphaeljs.com/reference.html#Element.remove
element.remove();
You could eventually create a function that draws shapes with the same color than your paper background-color, on click. Something like this code (jsfiddle at the end of the post). It would cover your content and not erase it, but it would look like it.
var timeoutId = 0;
var cursorX;
var cursorY;
var mouseStillDown = false;
paper = Raphael("paper1","100%","100%");
paper.rect(10,10,100,100).attr({
fill : "black"
});
$("#paper1").mousemove(function(event){
cursorY=event.pageY;
cursorX=event.pageX;
});
function erase() {
if (!mouseStillDown) { return; }
paper.rect(cursorX-25,cursorY-25,50,50).attr({
fill :"white",
stroke : "white"
});
if (mouseStillDown) { setInterval("erase", 100); }
}
$("#paper1").mousedown(function(event) {
mouseStillDown = true;
erase(event.pageX,event.pageY);
});
$("#paper1").mouseup(function(event) {
mouseStillDown = false;
});
Here, each time you click, it creates a white rectangle at your cursor position.
Here's a fiddle of the code : http://jsfiddle.net/c6Xs6/
With a few modifications you could create a menu allowing the user to choose the size and shape of the form you use to "erase".
Something more or less like this : http://jsfiddle.net/8ABe9/
You could also use a div following your cursor to show exactly where the "eraser" would be drawn.
Hope that helped you :)
Well, I've been reading the documentation and I believe that I'm calling functions and passing parameters correctly, but for the life of me I can't get this simple UI code to work.
I'm generating a UI for a Spreadsheet using the following code:
function checkOut() {
var app = buildUI();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
function buildUI() {
var gui = UiApp.createApplication();
gui.setTitle("Check-Out/Check-In");
gui.setStyleAttribute("background", "lavender");
// Absolute panel for setting specific locations for elements
var panel = gui.createAbsolutePanel();
// Equipment ID#s Label
var equipmentIDLabel = gui.createLabel("Equipment ID#s");
equipmentIDLabel.setHorizontalAlignment(UiApp.HorizontalAlignment.CENTER);
equipmentIDLabel.setSize("20px", "125px");
equipmentIDLabel.setStyleAttributes({background: "SteelBlue", color: "white"});
// Add all components to panel
panel.add(equipmentIDLabel, 10, 0);
gui.add(panel);
return gui;
}
function getUIdata(eventInfo) {
// I know how to get the data from each element based on ID
}
It generates the Absolute Panel correctly when checkOut() is called, but the EquipmentIDLabel is never added to the panel. I am basing the code on the simplistic design I created in the GUI builder (that will be deprecated in a few days, which is why I am writing the code so that I can change it later):
So what exactly is going wrong here? If I can figure out how to add one element, I can infer the rest by looking at the docs. I've never been any good at GUI development!
You could maybe use grid as an interesting alternative... here is an example :
// define styles
var labelStyle = {background: "SteelBlue", color: "white",'textAlign':'center','line-height':'20px','vertical-align':'middle','font-family':"Arial, sans-serif",'fontSize':'10pt'};// define a common label style
var fieldStyle = {background: "white", color: "SteelBlue",'font-family':"Courrier, serif",'fontSize':'11pt'};// define a common label style
function checkOut() {
var app = buildUI();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
}
function buildUI() {
var gui = UiApp.createApplication();
gui.setTitle("Check-Out/Check-In");
gui.setStyleAttribute("background", "lavender");
var panel = gui.createAbsolutePanel().setStyleAttribute('padding','10px');
var grid = gui.createGrid(4,2).setWidth('300').setCellPadding(10);//define grid size in number of row & cols
var equipmentID = ['equipmentIDLabel','equipmentIDLabel1','equipmentIDLabel2','equipmentIDLabel3'];// define labels in an array of strings
for(var n=0 ;n<equipmentID.length ; n++){;// iterate
var equipmentIDLabel = gui.createLabel(equipmentID[n]).setWidth('125').setStyleAttributes(labelStyle);
var equipmentIDField = gui.createTextBox().setText('Enter value here').setName(equipmentID[n]).setSize("125", "20").setStyleAttributes(fieldStyle);
grid.setWidget(n,0,equipmentIDLabel).setWidget(n,1,equipmentIDField);
}
gui.add(panel.add(grid));
return gui;
}
It looks like the absolute panel offset method is a little capricious and take control of your positioning, in my tests I have been able to position panels that are visible in the following way:
panel.add(equipmentIDLabel);
panel.add(equipmentIDField,150,0);
panel.add(otherLabel);
panel.add(otherField, 150, 20);
Try it out with trial and error, you may get the UI you need, if not I would move to an alternate layout, verticalPanel is a little better behaved and of course you can use forms as well.
Another small bug is that you inverted the length and hight in equipmentIDLabel.setSize("20px", "125px");
Let me know if I can be of more assitance
The specific problem in your code is the following line :
// Add all components to panel
panel.add(equipmentIDLabel, 10, 0);
Simply change it to : panel.add(equipmentIDLabel);
..and you will see the field (at position 0,0).
As patt0 observes, you can then add OTHER components and use positioning. It seems to be a limitation of adding the first field to an absolutePanel.
Of course, the Google Script gui is now deprecated (since December 2014) but I was interested to try your code and see that it still basically executes (as at Feb 2016).
I'm using a tableView with a headerPullView.
It works fine, but i want to show the headerPullView when i open the tab so the user can see that new data is loaded.
Can't find any information on google or appcelerator docs.
I only found this: http://developer.appcelerator.com/blog/2010/05/how-to-create-a-tweetie-like-pull-to-refresh-table.html
but this only shows how to update when the tab is already loaded. I'm looking for a way to show that loading headerPullView when i open that window.
You can't simulate a scroll with the headerPullView but you can fire an event of scroll.
Anyways what I would advise is to create a headerView and set the table height smaller and away from the top. Attache a listener to the open event.
var headerView = Ti.UI.createView({
top: 0,
height: 60
});
Ti.UI.currentWindow.addEventListener('open', function(e) {
tableView.top = 60;
tableView.height = 400;
Ti.UI.currentWindow.add(headerView);
Ti.UI.currentWindow.add(tableView);
});
Then just set it all back the way you need it when you scroll the table the first time.
var scrolled = 0;
tableView.addEventListener('scroll', function(e) {
if(!scrolled) {
tableView.top = 0;
tableView.height = 460;
Ti.UI.currentWindow.remove(headerView);
scrolled = 1;
}
// scroll code
});
I'm not so sure why you need to do this however. After facebook replaced "shake to refresh" with this method I've started seeing it in almost all table apps and have come to just expect it. I assume many other users feel the same way about this?
you can use listView instead of tableView, it supports pull view already
check this
http://docs.appcelerator.com/titanium/3.0/#!/guide/ListViews-section-37521650_ListViews-PulltoRefresh
or you can use this modules
https://github.com/jolicode/Alloy-PullToRefresh