Prevent the creation of events with conflicting times with FullCalendar - ruby-on-rails

I'm trying to disable dayclick from functioning when there is already an event at the time. Is this possible? I've seen functions that stop people dragging one event to a conflicting time, but nothing that acts before creation.
Thanks

I've sorted it with click events function
function checkOverlap(event) {
var start = new Date(event);
var end = new Date(event.end);
var overlap = $('#calendar').fullCalendar('clientEvents', function(ev) {
if( ev == event) {
return false;
}
var estart = new Date(ev.start);
var eend = new Date(ev.end);
return (Math.round(estart) == Math.round(start));
});
if (overlap.length){
return false;
} else {
return true;
}
}
This is mostly possible because my app only allows users to make appointments for 1 hour and always on the hour. If you have a more flexible model where you can have variable length and starting time of the appointments, you will have to fiddle with the following line:
return (Math.round(estart) == Math.round(start));

Related

In Firebase, how do I handle new children added after I statically loaded the latest N?

Here's my pagination/infinite scrolling scenario:
Load the initial N with startAt().limit(N).once('value'). Populate a list items.
On scroll, load the next N. (I pass a priority to startAt() but that's tangential.)
When a new item is added, I'd like to pop it to the top of items.
If I use a .onChildAdded listener for step 3, it finds all the items including those I've already pulled in thus creating duplicates. Is there a better way?
Another method would be to use the .onChildAdded listener for the initial N in step 1 instead of .once, but when the initial N items come in I do items.add(item) to sort one after the other as they are already in order, but with the new one that comes in after the fact I need to somehow know it's unique so I can do items.insert(0, item) to force it to the top of the list. I'm not sure how to set this up, or if I'm off the mark here.
EDIT: Still in flux, see: https://groups.google.com/forum/#!topic/firebase-talk/GyYF7hfmlEM
Here's a working solution I came up with:
class FeedViewModel extends Observable {
int pageSize = 20;
#observable bool reloadingContent = false;
#observable bool reachedEnd = false;
var snapshotPriority = null;
bool isFirstRun = true;
FeedViewModel(this.app) {
loadItemsByPage();
}
/**
* Load more items pageSize at a time.
*/
loadItemsByPage() {
reloadingContent = true;
var itemsRef = f.child('/items_by_community/' + app.community.alias)
.startAt(priority: (snapshotPriority == null) ? null : snapshotPriority).limit(pageSize+1);
int count = 0;
// Get the list of items, and listen for new ones.
itemsRef.once('value').then((snapshot) {
snapshot.forEach((itemSnapshot) {
count++;
// Don't process the extra item we tacked onto pageSize in the limit() above.
print("count: $count, pageSize: $pageSize");
// Track the snapshot's priority so we can paginate from the last one.
snapshotPriority = itemSnapshot.getPriority();
if (count > pageSize) return;
// Insert each new item into the list.
// TODO: This seems weird. I do it so I can separate out the method for adding to the list.
items.add(toObservable(processItem(itemSnapshot)));
// If this is the first item loaded, start listening for new items.
// By using the item's priority, we can listen only to newer items.
if (isFirstRun == true) {
listenForNewItems(snapshotPriority);
isFirstRun = false;
}
});
// If we received less than we tried to load, we've reached the end.
if (count <= pageSize) reachedEnd = true;
reloadingContent = false;
});
// When an item changes, let's update it.
// TODO: Does pagination mean we have multiple listeners for each page? Revisit.
itemsRef.onChildChanged.listen((e) {
Map currentData = items.firstWhere((i) => i['id'] == e.snapshot.name);
Map newData = e.snapshot.val();
newData.forEach((k, v) {
if (k == "createdDate" || k == "updatedDate") v = DateTime.parse(v);
if (k == "star_count") v = (v != null) ? v : 0;
if (k == "like_count") v = (v != null) ? v : 0;
currentData[k] = v;
});
});
}
listenForNewItems(endAtPriority) {
// If this is the first item loaded, start listening for new items.
var itemsRef = f.child('/items').endAt(priority: endAtPriority);
itemsRef.onChildAdded.listen((e) {
print(e.snapshot.getPriority());
print(endAtPriority);
if (e.snapshot.getPriority() != endAtPriority) {
print(e.snapshot.val());
// Insert new items at the top of the list.
items.insert(0, toObservable(processItem(e.snapshot)));
}
});
}
void paginate() {
if (reloadingContent == false && reachedEnd == false) loadItemsByPage();
}
}
Load the initial N with startAt().limit(N).once('value'). Populate a list items.
On the first run, note the first item's priority, then start an onChildAdded listener that has an endAt() with that priority. This means it'll only listen to stuff from there and above.
In that listener, ignore the first event which is the topmost item we already have, and for everything else, add that to the top of the list.
Of course, on scroll, load the next N.
EDIT: Updated w/ some fixes, and including the listener for changes.

How to catch the deselection event in Add-on SDK in Firefox

I use the Add-on Builder & SDK to develop Firefox add-on. I catch the event when users select a piece of text by the snippet:
var selection = require("sdk/selection");
selection.on('select', function () {
//Doing something
});
However, what I want also is to do other things when users does not select that text anymore, but I can not figure it out how to do it. Anyone can help me with this? Thank you very much.
I am not aware if there are events on Deselection of a text.
However, you could register for Mouse click event on body or div containing that text and then in the callback function of the event, you could check if last selected texts is currently selected or not.
var selection = require("sdk/selection");
var lastText;
function addSelection(){
var selection = false;
var body = document.body;
if(!selection.text){
//deselection
//remove DOM listeners
body.removeListener('click', addSelection);
}
if (!selection.isContiguous) {
for (var subselection in selection) {
if(subselection.text == lastText){
selection = true;
}
}
} else if(selection.text && selection.text == lastText){
selection = true;
}
if(!selection){
//deselected
//remove DOM listeners
}
}
selection.on('select', function () {
var body;
if(lastText !== selection.text){
//deselected
//remove listeners
};
lastText = selection.text;
body = document.body;
//add DOM listeners like click - that can potentially remove selection
body.addEventListener('click', addSelection);
});

How to wait for 3 seconds in ActionScript 2 or 3?

Is there any way to implement waiting for, say, 3 seconds in ActionScript, but to stay within same function? I have looked setInterval, setTimeOut and similar functions, but what I really need is this:
public function foo(param1, param2, param3) {
//do something here
//wait for 3 seconds
//3 seconds have passed, now do something more
}
In case you wonder why I need this - it is a legal requirement, and no, I can't change it.
Use the Timer to call a function after 3 seconds.
var timer:Timer = new Timer(3000);
timer.addEventListener(TimerEvent.TIMER, callback); // will call callback()
timer.start();
To do this properly, you should create the timer as an instance variable so you can remove the listener and the timer instance when the function is called, to avoid leaks.
class Test {
private var timer:Timer = new Timer(3000);
public function foo(param1:int, param2:int, param3:int):void {
// do something here
timer.addEventListener(TimerEvent.TIMER, fooPartTwo);
timer.start();
}
private function fooPartTwo(event:TimerEvent):void {
timer.removeEventListener(TimerEvent.TIMER, fooPartTwo);
timer = null;
// 3 seconds have passed, now do something more
}
}
You could also use another function inside your foo function and retain scope, so you don't need to pass variables around.
function foo(param1:int, param2:int, param3:int):void {
var x:int = 2; // you can use variables as you would normally
// do something here
var timer:Timer = new Timer(3000);
var afterWaiting:Function = function(event:TimerEvent):void {
timer.removeEventListener(TimerEvent.TIMER, afterWaiting);
timer = null;
// 3 seconds have passed, now do something more
// the scope is retained and you can still refer to the variables you
// used earlier
x += 2;
}
timer.addEventListener(TimerEvent.TIMER, afterWaiting);
timer.start();
}
For AS3 use Radu's answer.
For AS2 use the setInterval function like so:
var timer = setInterval(function, 3000, param1, param2);
function (param1, param2) {
// your function here
clearInterval(timer);
}
You can also use delayedCall, from TweenMax. IMHO, it's the sharpest way to do that if you are familiar to TweenMax family.
TweenMax.delayedCall(1, myFunction, ["param1", 2]);
function myFunction(param1:String, param2:Number):void
{
trace("called myFunction and passed params: " + param1 + ", " + param2);
}
In your case, using a anonymous function:
public function foo(param1, param2, param3) {
//do something here
trace("I gonna wait 3 seconds");
TweenMax.delayedCall(3, function()
{
trace("3 seconds have passed");
});
}
why you are doing some confused ways instead of doing the right way?
there is a method named:"setTimeout()";
setTimeout(myFunction,3000);
myFunction is the function you want to call after the period.and 3000 is the period you want to wait(as miliseconds).
you don't need to set then clear interval, or make a timer with one repeat count or do sth else with more trouble☺.
There is no Sleep in ActionScript. But there are other ways to achieve the same thing without having all your code in a single function and wait within that function a specific amount of time.
You can easily have your code in two functions and call the 2nd one after a specific timeout you set in your 1st function.
THIS IS NOT WITHIN ONE FUNCTION - ANSWERS: "How to wait for X seconds in AS2 & 3"
...without using setInterval or clearInterval.
The answers posted above are much faster and easier to use. I posted this here, just in case...
Sometimes you may not be able to use set/clearInterval or other methods based on development restrictions. Here is a way to make a delay happen without using those methods.
AS2 - If you copy/paste the code below to your timeline, make sure to add two movie clips to the stage, btnTest and btnGlowTest (include like instance names). Make "btnGlowTest" larger, a different color, & behind "btnTest" (to simulate a glow and a button, respectively).
Compile and check the output panel for the trace statements to see how the code is working. Click on btnTest - btnGlowTest will then become visible throughout the duration of the delay, (just for visual representation).
I have an onEnterFrame countdown timer in here as well, (demos stopping/switching timers).
If you want the delay/glow to be longer - increase the glowGameTime number. Change the names to fit your own needs and/or apply the logic differently.
var startTime:Number = 0;
var currentTime:Number = 0;
var mainTime:Number = 5;//"game" time on enter frame
var glowStartTime:Number = 0;
var glowCurrentTime:Number = 0;
var glowGameTime:Number = 1.8;//"delayed" time on press
btnGlowTest._visible = false;
this.onEnterFrame = TimerFunction;
startTime = getTimer();
function TimerFunction()
{
currentTime = getTimer();
var timeLeft:Number = mainTime - ((currentTime - startTime)/1000);
timeLeft = Math.floor(timeLeft);
trace("timeLeft = " + timeLeft);
if(timeLeft <= 0)
{
trace("time's up...3 bucks off");
//...do stuff here
btnGlowTest._visible = false;//just for show
btnTest._visible = false;//just for show
StopTime();
}
}
function glowTimerFunction()
{
glowCurrentTime = getTimer();
var glowTimeLeft:Number = glowGameTime - ((glowCurrentTime - glowStartTime)/1000);
glowTimeLeft = Math.floor(glowTimeLeft);
//trace("glowTimeleft = " + glowTimeLeft);
if(glowTimeLeft <= 0)
{
trace("TIME DELAY COMPLETE!");
//...do stuff here
btnGlowTest._visible = false;//just for show
btnTest._visible = false;//just for show
StopTime();
}
}
btnTest.onPress = function()
{
trace("onPress");
btnGlowTest._visible = true;
StopTime();
GlowTime();
}
function GlowTime()
{
trace("GlowTime Function");
this.onEnterFrame = glowTimerFunction;
glowStartTime = getTimer();
}
function StopTime()
{
trace(">>--StopTime--<<");
delete this.onEnterFrame;
}
AS3 - Below is the code from above setup to run in AS3. There are different ways to accomplish similar results, yet based on the project scope, these are the methods that were used in order to get things functioning properly.
If you copy/paste the code below to your timeline, make sure to add two movie clips to the stage, btnTest and btnGlowTest (include like instance names). Make "btnGlowTest" larger, a different color, & behind "btnTest" (to simulate a glow and a button, respectively).
Compile and check the output panel for the trace statements to see how the code is working. Click on btnTest - btnGlowTest will then become visible throughout the duration of the delay, (just for visual representation).
If you want the delay/glow to be longer - increase the GlowTimer:Timer number, (currently set to 950). Change the names to fit your own needs and/or apply the logic differently.
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
var startTime:Number = 0;
var currentTime:Number = 0;
var gameTime:Number = 4;//"game" time on enter frame
var GlowTimer:Timer = new Timer(950,0);//"delayed" time on press
btnGlowTest.visible = false;
GlowTimer.addEventListener(TimerEvent.TIMER, GlowTimeListener, false, 0, true);
btnTest.addEventListener(MouseEvent.MOUSE_DOWN, btnTestPressed, false, 0, true);
addEventListener(Event.ENTER_FRAME,TimerFunction, false, 0, true);
startTime = getTimer();
function TimerFunction(event:Event)
{
currentTime = getTimer();
var timeLeft:Number = gameTime - ((currentTime - startTime)/1000);
timeLeft = Math.floor(timeLeft);
trace("timeLeft = " + timeLeft);
if(timeLeft <= 0)
{
trace("time's up, 3 bucks off");
StopTime();
}
}
function GlowTimeListener (e:TimerEvent):void
{
trace("TIME DELAY COMPLETE!");
StopTime();
}
function btnTestPressed(e:MouseEvent)
{
trace("PRESSED");
removeEventListener(Event.ENTER_FRAME, TimerFunction);
btnGlowTest.visible = true;
GlowTimer.start();
}
function StopTime()
{
trace(">>--Stop Time--<<");
btnGlowTest.visible = false;//just for show
btnTest.visible = false;//just for show
GlowTimer.stop();
removeEventListener(TimerEvent.TIMER, GlowTimeListener);
removeEventListener(Event.ENTER_FRAME, TimerFunction);
}

jQuery Datepicker, select multiple dates and mark them via css at selection time, permanently

so I have spent a day developing and reading (teh other way around) to enable my jQuery datepicker to select and highlight mutliple dates.
For this I have managed to write the selected dates to an array which is visualized in a simple textfield.
What I could not manage is to permanently modify the look of the selected date in the datepicker.
I have implemented the "beforeShowDay:" option, which is working properly uppon loading the datepicker, but of course is not called directly on selecting a date.
For this I guessed, I would need to refresh the view "onSelect", but the refresh is not working properly.
Right now, I have some small methods for handling the datearray.
Uppon adding or removing a date, I am trying to refresh the datepicker.
Uppon selecting a date, I am either adding it to, or remove it from the dates-array.
Also, onSelect, I am matching the selected day and try to addClass().
But once again, I think I missed something all the way round, as it is not shown in my datepicker.
Here's my code for now:
var dates = new Array();
function addDate(date) {
if (jQuery.inArray(date, dates) < 0 && date) {
dates.push(date);
}
}
function removeDate(index) {
dates.splice(index, 1);
}
// Adds a date if we don't have it yet, else remove it and update the dates
// textfield
function addOrRemoveDate(date) {
var index = jQuery.inArray(date, dates);
if (index >= 0) {
removeDate(index);
updateDatesField(dates);
} else {
addDate(date);
updateDatesField(dates);
}
jQuery(calContainer).datepicker("refresh");
}
var calContainer = document.getElementById("calendar-container");
jQuery(calContainer).datepicker({
minDate : new Date(),
dateFormat : "#",
onSelect : function(dateText, inst) {
addOrRemoveDate(dateText);
jQuery(".ui-datepicker-calendar tbody tr td a").each(function() {
if (jQuery(this).text() == inst.selectedDay) {
jQuery(this).addClass("ui-state-highlight");
jQuery(this).parent().addClass("selected");
}
});
// addTimeSelectorColumns(dates);
},
beforeShowDay : function(_date) {
var gotDate = -1;
for ( var index = 0; index < dates.length; index++) {
if (_date.getTime() == dates[index]) {
gotDate = 1;
} else {
gotDate = -1;
}
}
if (gotDate >= 0) {
return [ true, "ui-datepicker-today", "Event Name" ];
}
return [ true, "" ];
}
});
function updateDatesField(dates) {
if (dates.length > 0) {
var tmpDatesStrArr = new Array();
var dateString = "";
var datesField = document.getElementById("dates");
for ( var index = 0; index < dates.length; index++) {
var dateNum = dates[index];
var tmpDate = new Date();
tmpDate.setTime(dateNum);
dateString = tmpDate.getDate() + "." + tmpDate.getMonth() + "."
+ tmpDate.getFullYear();
tmpDatesStrArr.push(dateString);
}
jQuery(datesField).val(tmpDatesStrArr);
}
}
(I am still a beginner in Javascript/jQuery, so any help or hints towards my coding are welcome, btw...)
It depends whether you want to stick with jQuery UI or not. If you are open to other library, there is a jQuery Datepicker that supports multiple selection: jquery.datePicker with multiple select enabled. It may save you sometmie fiddling with jQuery UI's one, as it does not natively support multiple selection.
EDIT:
If your main library is not jQuery, I think you should look for a standalone or Prototype-dependent library instead. The JS Calendar looks promising. It natively supports multiple selection by detecting the Ctrl key.

iOS UIAutomation UIAElement.isVisible() throwing stale response?

I'm trying to use isVisible() within a loop to create a waitForElement type of a function for my iOS UIAutomation. When I try to use the following code, it fails while waiting for an element when a new screen pops up. The element is clearly there because if I do a delay(2) before tapping the element it works perfectly fine. How is everyone else accomplishing this, because I am at a loss...
Here's the waitForElement code that I am using:
function waitForElement(element, timeout, step) {
if (step == null) {
step = 0.5;
}
if (timeout == null) {
timeout = 10;
}
var stop = timeout/step;
for (var i = 0; i < stop; i++) {
if (element.isVisible()) {
return;
}
target.delay(step);
}
element.logElement();
throw("Not visible");
}
Here is a simple wait_for_element method that could be used:
this.wait_for_element = function(element, preDelay) {
if (!preDelay) {
target.delay(0);
}
else {
target.delay(preDelay);
}
var found = false;
var counter = 0;
while ((!found) && (counter < 60)) {
if (!element.isValid()) {
target.delay(0.5);
counter++;
}
else {
found = true;
target.delay(1);
}
}
}
I tend to stay away from my wait_for_element and look for any activityIndicator objects on screen. I use this method to actual wait for the page to load.
this.wait_for_page_load = function(preDelay) {
if (!preDelay) {
target.delay(0);
}
else {
target.delay(preDelay);
}
var done = false;
var counter = 0;
while ((!done) && (counter < 60)) {
var progressIndicator = UIATarget.localTarget().frontMostApp().windows()[0].activityIndicators()[0];
if (progressIndicator != "[object UIAElementNil]") {
target.delay(0.25);
counter++;
}
else {
done = true;
}
}
target.delay(0.25);
}
Here is a simple and better one using recursion. "return true" is not needed but incase u want it.
waitForElementToDismiss:function(elementToWait,waitTime){ //Using recursion to wait for an element. pass in 0 for waitTime
if(elementToWait && elementToWait.isValid() && elementToWait.isVisible() && (waitTime < 30)){
this.log("Waiting for element to invisible");
target.delay(1);
this.waitForElementToDismiss(elementToWait, waitTime++);
}
if(waitTime >=30){
fail("Possible login failed or too long to login. Took more than "+waitTime +" seconds")
}
return true;
}
Solution
I know this is an old question but here is my solution for a situation where I have to perform a repetitive task against a variable timed event. Since UIAutomation runs on javascript I use a recursive function with an empty while loop that checks the critical control state required before proceeding to the next screen. This way one never has to hard code a delay.
// Local target is the running simulator
var target = UIATarget.localTarget();
// Get the frontmost app running in the target
var app = target.frontMostApp();
// Grab the main window of the application
var window = app.mainWindow();
//Get the array of images on the screen
var allImages = window.images();
var helpButton = window.buttons()[0];
var nextButton = window.buttons()[2];
doSomething();
function doSomething ()
{
//only need to tap button for half the items in array
for (var i=0; i<(allImages.length/2); i++){
helpButton.tap();
}
//loop while my control is NOT enabled
while (!nextButton.isEnabled())
{
//wait
}
//proceed to next screen
nextButton.tap();
//go again
doSomething();
}

Resources