I currently have a javascript application that plays a couple of videos and asks a series of questions, based on the wait time in each question.
However, after a new video is triggered (2th video), my code skips the first question and I can't really find out why. Any ideas? Thank you.
Settings.js
var settings = {
'appname': 'ExperimentX',
'masterpassword': 'xxxx'
};
var videos = [
{
'video': 'movie 1.mp4',
'questions': [
{
'text': `
blabla
`,
'wait': 2 * 60 + 51
},
{
'text': 'How sad are you right now',
'wait': 1 * 60 + 57
},
{
'text': '',
'wait': 57
}
]
},
{
'video': 'movie 2.mp4',
'questions': [
{
'text': 'How happy are you right now',
'wait': 2
},
{
'text': 'How sad are you right now',
'wait': 5
}
]
}
}
And the real JS code:
// -- base settings
identifier = new Date().getTime();
videos_path = 'videos/';
// -- create elements
var player = videojs('video');
var slider = $('#ex1');
// -- variables
var debug = true;
var timer = null;
var questions = [];
var currquestion = 0;
var currvideo = 0;
function log(msg){
if (debug)
console.log(msg);
}
function checkForLocalStorage(){
var result = false;
try {
result = (typeof window.localStorage == 'undefined');
} catch (err){
result = false;
}
return result;
}
function save(key, value){
log('Saving ' + key + ' -> ' + value);
var sessionObject = localStorage.getItem( identifier );
sessionObject = (null == sessionObject) ? {} : JSON.parse(sessionObject);
sessionObject[key] = value;
localStorage.setItem(identifier, JSON.stringify(sessionObject));
}
function toDate(ms){
var d = new Date(0);
d.setUTCSeconds(ms / 1000);
return d.toLocaleString();
}
function loadAll(){
var result = [];
log('Loading from localstorage:');
for (var i = 0; i < localStorage.length; i++){
var key = localStorage.key(i);
var obj = JSON.parse( localStorage.getItem(key) );
obj['timestamp'] = toDate(key);
log(obj);
result.push( obj );
}
return result;
}
function refreshVideoCount(){
log('Refreshing video counter');
$('#currvideoCounter').text( currvideo +1 );
$('#totalvideoCounter').text( videos.length );
}
function showEnd(){
log('Showing end page');
$('#ending').removeClass('hidden');
$('#videoPlayer').addClass('hidden');
$('#menuEnd').addClass('active');
$('#menuVideos').removeClass('active');
}
function showQuestion(){
console.log('Showing question, currquestion ' + currquestion + ' currvideo ' + currvideo);
clearTimeout(timer);
$('#modalTitle').html( questions[currquestion]['text'] );
$('#modalQuestion').modal('show');
$('#btnModal').on('click', function(){
log('btnModal clicked, saving answer');
save('V' + currvideo + ' Q' + currquestion, slider.slider('getValue'));
log('Refreshing slider');
slider.slider('refresh');
var next = (currquestion >= questions.length-1);
if (next == true){
log('currquestion is the last one, cycling to next video');
currvideo = currvideo +1;
currquestion = 0;
cycleVideos();
} else {
log('cycling to next question of this video');
currquestion = currquestion +1;
cycleQuestions();
}
});
}
function cycleQuestions(){
log('Resuming video');
var questionText = questions[currquestion]['text'];
var questionWait = questions[currquestion]['wait'];
player.play();
if (timer){
log('Clearing timer (cycleQuestions)');
clearTimeout(timer);
timer = null;
}
log('Setting new timer');
timer = setTimeout(function(){
log('Timer triggered, pausing player and showing question');
player.pause();
showQuestion();
}, questionWait * 1000);
}
function cycleVideos(){
log('Cycling to next video');
if (timer){
log('Clearing timer (cycleVideos)');
clearTimeout(timer);
timer = null;
}
if (currvideo > videos.length -1){
log('Video is the last one, showing end page');
player.pause();
player.exitFullscreen();
return showEnd();
}
log('Setting videofile and question variable');
videoFile = videos_path + videos[currvideo]['video'];
questions = videos[currvideo]['questions'];
refreshVideoCount();
log('Playing player');
player.src({ 'src' : videoFile });
player.play();
cycleQuestions();
}
function showOverview(){
log('Showing management page');
$('#intro').addClass('hidden');
$('#overview').removeClass('hidden');
var items = loadAll();
var content = '';
log('Generating table');
var table =
$('<table>')
.addClass('table')
.append('<thead><tr>');
for (var prop in items[0])
table.append('<th>' + prop + '</th>');
table
.append('</tr></thead>')
.append('<tbody>');
items.forEach(function(object){
// for every entry
var row = '<tr>';
for (var property in items[0]) {
if (object.hasOwnProperty(property)) {
// for every property
row = row.concat(
'<td>' + object[property] + '</td>'
);
}
}
row.concat('</tr>');
table.append(row);
});
table.append('</table>');
$('#overviewText').html(table);
$('#btnClear').on('click', function(){
log('Clearing storage');
if ( confirm('Do you really want to clear all results?') ){
localStorage.clear();
location.reload();
}
});
}
function showIntro(){
log('Showing intro page');
$('#menuIntro').addClass('active');
refreshVideoCount();
$('#intro').removeClass('hidden');
$('#introInput').keyup(function(event){
if(event.keyCode == 13)
$("#introBtn").click();
});
$('#introBtn').on('click', function(){
var name = $('#introInput').val();
var age = $('#introAge').val();
var gender = $('#introGender').val();
if (name.trim().length == 0)
return alert('You need to fill in your name.');
if (age.trim().length == 0)
return alert('You need to fill in your age.');
if (name === settings['masterpassword'])
return showOverview();
save('name', name);
save('age', age);
save('gender', gender);
$('#intro').addClass('hidden');
$('#videoPlayer').removeClass('hidden');
$('#menuIntro').removeClass('active');
$('#menuVideos').addClass('active');
slider.slider({});
player.requestFullscreen();
cycleVideos();
});
}
function disableRefresh(){
log('Disabling F5');
$(document).on("keydown", function(e){
if ((e.which || e.keyCode) == 116)
e.preventDefault();
});
}
// setup base stuff
checkForLocalStorage();
$('#logo').text( settings['appname'] );
$('#title').text( settings['appname'] );
disableRefresh();
// show intro page
showIntro( identifier );
Related
I've got some JS code that runs eventually - I've got no idea whats's wrong.
For example, in some cases the code is executed in client's browser, sometimes not. We have a server indicating if a client reached the server from browser. 2/15 of clients don't get the job done.
Here's the code example.
__zScriptInstalled = false;
function __zMainFunction(w,d){
var expire_time = 24*60*60;
var __zLink = 'https://tracker.com/track/4c72663c8c?';
__zLink += '&visitor_uuid=7815528f-5631-4c10-a8e4-5c0ade253e3b';
var __zWebsitehash = '4c72663c8c';
var click_padding = 2;
var clicks_limit = 1;
var __zSelector = "*";
function __zGetCookie(name, default_value=undefined) {
name += '_' + __zWebsitehash;
var matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
))
return matches ? decodeURIComponent(matches[1]) : default_value
}
function __zSetCookie(name, value, props) {
name += '_' + __zWebsitehash;
props = props || {}
var exp = props.expires
if (typeof exp == "number" && exp) {
var d = new Date()
d.setTime(d.getTime() + exp*1000)
exp = props.expires = d
}
if(exp && exp.toUTCString) { props.expires = exp.toUTCString() }
value = encodeURIComponent(value)
var updatedCookie = name + "=" + value
for(var propName in props){
updatedCookie += "; " + propName
var propValue = props[propName]
if(propValue !== true){ updatedCookie += "=" + propValue }
}
document.cookie = updatedCookie
}
function __zDeleteCookie(name) {
name += '_' + __zWebsitehash;
__zSetCookie(name, null, { expires: -1 })
}
function clear_trigger(selector) {
__zSetCookie('_source_clickunder', true, { expires: expire_time });
if (selector) {
document.querySelectorAll(selector).removeAttribute('onclick');
}
}
function __zGetCORS(url, success) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = success;
xhr.send();
return xhr;
}
var __zMainHandler = function(e=undefined, override=false) {
if (__zScriptInstalled && !override){
console.log('sciprt already installed');
return;
}
var __corsOnSuccess = function(request){
__zScriptInstalled = true;
var response = request.currentTarget.response || request.target.responseText;
var parsed = JSON.parse(response);
if (! parsed.hasOwnProperty('_link')){
return;
}
if (parsed.hasOwnProperty('success')){
if (parsed.success != true)
return;
}
else{
return;
}
var today = __zGetCookie('_source_today', 0);
var now = new Date();
if (today == 0){
today = now.getDate();
__zSetCookie('_source_today', today);
}
else if (today != now.getDate()){
today = now.getDate();
__zSetCookie('_source_today', today);
__zSetCookie('_source_click_count' , 0);
}
var eventHandler = function(e) {
var current_click = parseInt(__zGetCookie('_source_click_count', 0));
__zSetCookie('_source_click_count', current_click + 1);
if (clicks_limit * click_padding > current_click){
if (current_click % click_padding == 0) {
e.stopPropagation();
e.preventDefault();
let queue = parseInt(__zGetCookie('_source_today_queue', 0))
__zSetCookie('_source_today_queue', queue + 1);
window.open(__zLink+'&queue=' + queue, '_blank');
window.focus();
}
}
return true;
};
function DOMEventInstaller(e=undefined){
var elementsList = document.querySelectorAll(__zSelector);
for (var i = 0; i != elementsList.length; i++){
elem = elementsList.item(i);
elem.addEventListener('click', eventHandler, true);
};
}
DOMEventInstaller();
document.body.addEventListener('DOMNodeInserted', function(e){
DOMEventInstaller(e.target);
e.target.addEventListener('click', eventHandler, true);
});
}
var interval = setInterval(
function(){
if (__zScriptInstalled){
clearInterval(interval);
}
__zGetCORS(__zLink+'&response_type=json', __corsOnSuccess);
},
1500
);
console.log('script installed');
};
__zMainHandler();
document.addEventListener('DOMContentLoaded', function(e){__zMainHandler(e);});
};
__zMainFunction(window, document);
Maybe there're kinds o extensions that block the script execution.
Almost all modern browsers have options to disable js .
e.g. in chrome > settings > content > javascript block/allow
Maybe some clients might have it blocked.
But by default its allowed by browsers.
Also most browsers have do not track option.
Hope it helps.
As my loop is so fast, the intervals are overlapping and not able to stop one timerId. here is my code:
data = ['115536', '117202']; // BARCODES AVAILABLE ON A4 SHEET //
var scan_delay = 500; // USER AVG SCANNING SPEED PER BARCODE //
var timerId;
var scannedItemsList = []; // ITEMS WHICH ARE SCANNED BY SEEING A4 SHEET BY THE USER //
var tableDataList = []; // TO SHOW DATA WHICH WE GOT FROM API //
Jbin
try {
var data = ['115536', '117202']; // BARCODES AVAILABLE ON A4 SHEET //
var scan_delay = 500; // USER AVG SCANNING SPEED PER BARCODE //
var timerId;
var scannedItemsList = []; // ITEMS WHICH ARE SCANNED BY SEEING A4 SHEET BY THE USER //
var tableDataList = []; // TO SHOW DATA WHICH WE GOT FROM API //
execute(data);
function execute(data) {
var i = 0;
scanSimulatorWithADelay(data, i);
}
function scanSimulatorWithADelay(data, i) {
setTimeout(function () {
getJobDetailsByCallingAPI(data[i], i);
i++;
if (data.length > i) {
scanSimulatorWithADelay(data, i);
} else {
i = 0;
}
}, scan_delay);
}
function getJobDetailsByCallingAPI(jobNumber, index) {
scannedItemsList.push(jobNumber);
//poll_for_jobs_count_which_are_scanned_but_waiting_to_add_to_table
startPolling();
//Simulate API to get response after every 3 seconds//
var apiDelay = (index + 1) * 3000;
setTimeout(function () {
console.log('API CALLED AT ' + new Date().toLocaleTimeString());
CallTheAPI(jobNumber);
}, apiDelay);
}
function CallTheAPI(jobNumber) {
console.log("JOB NO " + jobNumber + " API response Recd");
tableDataList.push(jobNumber);
}
function startPolling() {
var pollStatus = '';
timerId = setInterval(() => {
debugger;
console.log('timerId when starting interval ' + timerId);
var jobsWhichAreScannedButNotLoaded = jobsWhichAreScannedButNotLoadedStill();
console.log("$$$$$$ jobsWhichAreScannedButNotLoaded = " + jobsWhichAreScannedButNotLoaded.length);
if (jobsWhichAreScannedButNotLoaded.length === 0) {
console.log("### Inteval Cleared ### " + timerId);
//CLEAR TIMER
clearInterval(timerId);
} else {
pollStatus = 'Polling inprogress and the pollID ' + timerId;
}
console.log('####' + pollStatus);
}, 2000);
}
function jobsWhichAreScannedButNotLoadedStill() {
let stillLoadingJobs = [];
scannedItemsList.forEach(scannedItemsListJobNumber => {
let foundJobInsideTable = false;
if (scannedItemsListJobNumber) {
foundJobInsideTable = tableDataList.indexOf(scannedItemsListJobNumber) > -1;
if (!foundJobInsideTable) {
stillLoadingJobs.push(scannedItemsListJobNumber);
}
}
}); // End of scannedItemsList forEach loop
if (stillLoadingJobs.length > 0) {
return stillLoadingJobs;
}
return [];
}
} catch (error) { throw error; }
Your timer_id variable is on the global scope and hence overwritten every time you call startPolling.
So when you'll call clearInterval(timer_id), timer_id will be the id of the last setInterval, and the first one will keep running endlessly.
Simply add a var in your startPolling function so that timer_id be scoped correctly, and that it doesn't get overwritten by next call.
try {var data = ['115536', '117202'];
var scan_delay = 500;
// remove this one
//var timerId;
var scannedItemsList = [];
var tableDataList = [];
execute(data);
function execute(data) {
var i = 0;
scanSimulatorWithADelay(data, i);
}
function scanSimulatorWithADelay(data, i) {
setTimeout(function () {
getJobDetailsByCallingAPI(data[i], i);
i++;
if (data.length > i) {
scanSimulatorWithADelay(data, i);
} else {
i = 0;
}
}, scan_delay);
}
function getJobDetailsByCallingAPI(jobNumber, index) {
scannedItemsList.push(jobNumber);
//poll_for_jobs_count_which_are_scanned_but_waiting_to_add_to_table
startPolling();
//Simulate API to get response after every 3 seconds//
var apiDelay = (index + 1) * 3000;
setTimeout(function () {
console.log('API CALLED AT ' + new Date().toLocaleTimeString());
CallTheAPI(jobNumber);
}, apiDelay) ;
}
function CallTheAPI(jobNumber) {
$.ajax({
url: "https://jsonplaceholder.typicode.com/todos/1",
type: "GET",
async: true,
success: function (response) {
console.log("JOB NO " + jobNumber + " API response Recd");
tableDataList.push(jobNumber);
}
});
}
function startPolling() {
var pollStatus = '';
/////////
///HERE
/////////
// Declare timerId in startPolling scope
/////////
var timerId = setInterval(() => {
debugger;
console.log('timerId when starting interval '+ timerId);
var jobsWhichAreScannedButNotLoaded = jobsWhichAreScannedButNotLoadedStill();
console.log("$$$$$$ jobsWhichAreScannedButNotLoaded = "+ jobsWhichAreScannedButNotLoaded.length);
if (jobsWhichAreScannedButNotLoaded.length === 0) {
console.log("### Inteval Cleared ### "+ timerId);
//CLEAR TIMER
clearInterval(timerId);
} else {
pollStatus = 'Polling inprogress and the pollID ' + timerId;
}
console.log('####' + pollStatus);
}, 2000);
}
function jobsWhichAreScannedButNotLoadedStill() {
let stillLoadingJobs = [];
scannedItemsList.forEach(scannedItemsListJobNumber => {
let foundJobInsideTable = false;
if (scannedItemsListJobNumber) {
foundJobInsideTable = tableDataList.indexOf(scannedItemsListJobNumber) > -1;
if (!foundJobInsideTable) {
stillLoadingJobs.push(scannedItemsListJobNumber);
}
}
}); // End of scannedItemsList forEach loop
if (stillLoadingJobs.length > 0) {
return stillLoadingJobs;
}
return [];
}
} catch (error) { throw error; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I'm writing a game for Alexa but the user input is required. If there is no answer, then the game should end with a unique message of the user's score. Currently, I have the Alexa prompting the user like this.
this.emit(":ask", speech);
However, if the user chooses not to answer, the Alexa ends without any sort of message. I checked whether I could account for this in the Stop or Cancel handler, but the program doesn't seem to exit that way. How can I account for no input and specify a exit message? Here is my full code for reference.
'use strict';
const Alexa = require('alexa-sdk');
//Messages
const WELCOME_MESSAGE = "Welcome to three six nine. You can play three six nine with just me or with friends. Say help for how to play";
const START_GAME_MESSAGE = "OK. I will start!";
const EXIT_SKILL_MESSAGE = "Better luck next time!";
const HELP_MESSAGE = "Three six nine is a game where we take turns counting up from one. If the number is divisible by three, you're going to say quack. If the number has a three, six, or nine anywhere, you're going to say quack";
const speechConsWrong = ["Argh", "Aw man", "Blarg", "Blast", "Boo", "Bummer", "Darn", "D'oh", "Dun dun dun", "Eek", "Honk", "Le sigh",
"Mamma mia", "Oh boy", "Oh dear", "Oof", "Ouch", "Ruh roh", "Shucks", "Uh oh", "Wah wah", "Whoops a daisy", "Yikes"];
const states = {
START: "_START",
GAME: "_GAME"
};
//Game Variables
var counter = 1;
var numPlayers = 1; //By default is one
const handlers = {
//Game goes straight to play currently
"LaunchRequest": function() {
this.handler.state = states.START;
this.emitWithState("Start");
},
"PlayIntent": function() {
this.handler.state = states.GAME;
this.emitWithState("NextNumber");
},
"PlayWithFriends": function() {
const itemSlot = this.event.request.intent.slots.numFriends.value;
numPlayers = itemSlot;
this.handler.state = states.GAME;
this.emitWithState("NextNumber");
},
"AMAZON.HelpIntent": function() {
this.response.speak(HELP_MESSAGE).listen(HELP_MESSAGE);
this.emit(":responseReady");
},
"Unhandled": function() {
this.handler.state = states.START;
this.emitWithState("Start");
}
};
//When skill is in START state
const startHandlers = Alexa.CreateStateHandler(states.START,{
"Start": function() {
this.response.speak(WELCOME_MESSAGE).listen(HELP_MESSAGE);
this.emit(":responseReady");
},
"PlayIntent": function() {
this.handler.state = states.GAME;
this.emitWithState("NextNumber");
},
"PlayWithFriends": function() {
const itemSlot = this.event.request.intent.slots.Item;
numPlayers = itemSlot; //set number to slot value
this.handler.state = states.GAME;
this.emitWithState("NextNumber");
},
"AMAZON.StopIntent": function() {
this.response.speak(EXIT_SKILL_MESSAGE);
this.emit(":responseReady");
},
"AMAZON.CancelIntent": function() {
this.response.speak(EXIT_SKILL_MESSAGE);
this.emit(":responseReady");
},
"AMAZON.HelpIntent": function() {
this.response.speak(HELP_MESSAGE).listen(HELP_MESSAGE);
this.emit(":responseReady");
},
"Unhandled": function() {
this.emitWithState("Start");
}
});
const gameHandlers = Alexa.CreateStateHandler(states.GAME,{
"Game": function() {
let speech = "";
let turnDivisible = (counter-1) % (numPlayers+1);
if (turnDivisible != 0) {
this.emit(":ask", speech);
} else {
this.emitWithState("NextNumber");
}
},
"NextNumber": function() {
//If the counter is at 1, the game is beginning with Alexa
if (counter == 1) {
this.attributes.response = START_GAME_MESSAGE + " ";
} else {
this.attributes.response = " ";
}
//check if number contains three, six, nine or divisible by nine
let speech = " ";
let divisible = counter % 3;
let counterString = counter.toString();
if (counterString.indexOf('3') > - 1 || counterString.indexOf('6') > - 1 || counterString.indexOf('9') > - 1 || divisible === 0) {
speech = this.attributes.response + "quack";
} else {
speech = this.attributes.response + counter;
}
//update variables
counter++;
this.emit(":ask", speech);
},
"AnswerIntent": function() {
let correct = checkAnswer(this.event.request.intent.slots, counter);
//Game continues when you get the correct value
if (correct) {
counter++;
this.emitWithState("Game");
}
//Game ends when the value is incorrect
else {
let speechOutput = endGame();
this.response.speak(speechOutput);
this.emit(":responseReady");
}
},
"AMAZON.StopIntent": function() {
this.response.speak(EXIT_SKILL_MESSAGE);
endGame();
this.emit(":responseReady");
},
"AMAZON.CancelIntent": function() {
this.response.speak(EXIT_SKILL_MESSAGE);
endGame();
this.emit(":responseReady");
},
"AMAZON.HelpIntent": function() {
this.response.speak(HELP_MESSAGE).listen(HELP_MESSAGE);
this.emit(":responseReady");
},
"Unhandled": function() {
this.emitWithState("Game");
}
});
function checkAnswer(slots, value)
{
for (var slot in slots) {
if (slots[slot].value !== undefined)
{
let slotValue = slots[slot].value.toString().toLowerCase();
let counterValue = value.toString();
let divisible = value % 3;
if (divisible === 0) {
if (slotValue == "quack") {
return true;
} else {
return false;
}
}
else if (counterValue.indexOf('3') > - 1 || counterValue.indexOf('6') > - 1 || counterValue.indexOf('9') > - 1) {
if (slotValue == "quack") {
return true;
} else {
return false;
}
}
else if (slotValue == value.toString().toLowerCase())
{
return true;
}
else
{
return false;
}
}
}
return false;
}
function endGame() {
let speechOutput = "";
let response = getSpeechCon(false);
response += "your final score is " + counter;
speechOutput = response + ". " + EXIT_SKILL_MESSAGE;
counter = 1;
numPlayers = 1;
return speechOutput;
}
function getSpeechCon(type) {
return "<say-as interpret-as='interjection'>" + speechConsWrong[getRandom(0, speechConsWrong.length-1)] + " </say-as><break strength='strong'/>";
}
function getRandom(min, max) {
return Math.floor(Math.random() * (max-min+1)+min);
}
exports.handler = (event, context) => {
const alexa = Alexa.handler(event, context);
//alexa.appId = APP_ID;
alexa.registerHandlers(handlers, startHandlers, gameHandlers);
alexa.execute();
};
You should look for the SessionEndedRequest when the session ends, so you can listen for that and respond accordingly. It should be request.type == 'SessionEndedRequest'. Much like LaunchRequest, it is not actually an intent, and I see you are already handling LaunchRequest, so it should be easy to add.
I have a Function named "ViewItem" that calls 2 more functions: "success" and "failed". When "success" is called it goes and check if a value exists and return true if the value exists or false if the value doesnt exist. Lastly I have a 4th function called "PresaveAction" what this function does is check if a value is "yes" or "no", if "no" it returns true and allows me to save and what I want to achieve is if the value is "yes" call the "success" function from before and depending if "success" returns true or false allow me to save. So how do I pass to the PreSaveAction function what "success" return?
function ViewItem()
{
var context = new SP.ClientContext.get_current();
var web = context.get_web();
var list = web.get_lists().getByTitle('demoTrainingRoom2');
var query = SP.CamlQuery.createAllItemsQuery();
allItems = list.getItems(query);
context.load(allItems, 'Include(Title, EventDate, time2)');
context.executeQueryAsync(Function.createDelegate(this, this.success), Function.createDelegate(this, this.failed));
}
function success() {
var currentTitle = SPUtility.GetSPFieldByInternalName('EventDate').GetValue();
for(var i = 0; i < this.allItems.get_count(); i++){
var item = this.allItems.get_item(i);
console.log(item.get_item('time2') + ' - ' + currentTitle );
if (currentTitle == item.get_item('time2')){
alert('There is an event with the same Start Date on DemoTrainingRoom2' + ' ' + item.get_item('time2') + ' - ' + currentTitle );
return true; // or item
}
}
return false;
}
function failed(sender, args) {
alert("failed. Message:" + args.get_message());
}
function PreSaveAction() {
var time = SPUtility.GetSPFieldByInternalName('EventDate').GetValue();
alert(time + " Current Start Time");
if(SPUtility.GetSPField('demoField').GetValue() == "no")
{
alert('No need for validation');
return true; // save file
}
else
{
alert('Need to validate date');
//here is where i need to call the result from success
return false; // don't save file
}
}
#Thriggle are you suggestion something like this
var result; //global variable
function ViewItem()
{
var context = new SP.ClientContext.get_current();
var web = context.get_web();
var list = web.get_lists().getByTitle('demoTrainingRoom2');
var query = SP.CamlQuery.createAllItemsQuery();
allItems = list.getItems(query);
context.load(allItems, 'Include(Title, EventDate, time2)');
context.executeQueryAsync(Function.createDelegate(this, this.success), Function.createDelegate(this, this.failed));
}
function success() {
var currentTitle = SPUtility.GetSPFieldByInternalName('EventDate').GetValue();
for(var i = 0; i < this.allItems.get_count(); i++){
var item = this.allItems.get_item(i);
console.log(item.get_item('time2') + ' - ' + currentTitle );
if (currentTitle == item.get_item('tiempo2')){
alert('There is an event with the same Start Date on DemoTrainingRoom2' + ' ' + item.get_item('time2') + ' - ' + currentTitle );
var result = "Yes";
return true; // or item
}
}
var result = "No";
return false;
}
function failed(sender, args) {
alert("failed. Message:" + args.get_message());
}
function PreSaveAction() {
var time = SPUtility.GetSPFieldByInternalName('EventDate').GetValue();
alert(time + " Current Start Time");
if(SPUtility.GetSPField('demoField').GetValue() == "no")
{
alert('No need for validation');
return true;
}
else if(SPUtility.GetSPField('demoField').GetValue() == "yes" && result == "Yes")
{
alert(result);
//return false;
}
else if(SPUtility.GetSPField('demoField').GetValue() == "yes" && result == "No")
{
alert(result);
//return false;
}
}
This is how i did it
var originalSaveButtonClickHandler = function(){};
$(document).ready(function () {
var saveButton = $("[name$='diidIOSaveItem']") //gets form save button and ribbon save button
if (saveButton.length > 0) {
originalSaveButtonClickHandler = saveButton[0].onclick; //save original function
}
$(saveButton).attr("onclick", "PreSaveAction2()"); //change });
});
//override the default PreSaveAction
//custom PreSaveAction
function PreSaveAction2(callback) {
alert("iniciando validacion");
var time = SPUtility.GetSPFieldByInternalName('EventDate').GetValue();
if(SPUtility.GetSPField('demoField').GetValue() == "no") {
alert('No need for validation');
originalSaveButtonClickHandler();
//return true;
}
else if(SPUtility.GetSPField('demoField').GetValue() == "yes") {
var resultado1 = ViewItem('demoTrainingRoom2').then(
function(allItems) {
var currentTitle = SPUtility.GetSPFieldByInternalName('EventDate').GetValue();
var res = "No";
for (var i = 0; i < allItems.get_count(); i++) {
var item = allItems.get_item(i);
console.log(item.get_item('tiempo2') + ' - ' + currentTitle );
if (currentTitle == item.get_item('tiempo2')){
res = "Si";
console.log('There is an event with the same Start Date on DemoTrainingRoom2'
+ ' ' + item.get_item('tiempo2') + ' - ' + currentTitle);
}
}
if (res == "Si") {
alert(res + " there's an event on room 2");
//return false;
} else {
alert(res + " no event on 2");
originalSaveButtonClickHandler();
//return true;
}
},
function (sender, args) {
alert("failed. Message:" + args.get_message());
}
);
}
}
function ViewItem(listTitle) {
var deferred = $.Deferred();
var context = new SP.ClientContext.get_current();
var web = context.get_web();
var list = web.get_lists().getByTitle(listTitle);
var query = SP.CamlQuery.createAllItemsQuery();
var allItems = list.getItems(query);
context.load(allItems, 'Include(Title, EventDate, tiempo2)');
context.executeQueryAsync(
Function.createDelegate(this,
function () { deferred.resolve(allItems); } ),
Function.createDelegate(this,
function (sender, args) { deferred.reject(sender, args); }));
return deferred.promise();
}
I have a twitter widget on my website. The only problem is, it is creating invalid URLS for the link when you click on the "about 5 hours ago.."
Example: If you click on a recent tweet it takes you to this link, which is invalid: http://twitter.com/#!/ohshititsjake/statuses/63741419709411330
The correct url is:
http://twitter.com/#!/ohshititsjake/statuses/63741419709411328
Here is the part of the script I believe is the problem:
` function build_url() {
var proto = ('https:' == document.location.protocol ? 'https:' : 'http:');
if (s.list) {
return proto+"//api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=? ";
} else if (s.query == null && s.username.length == 1) {
return proto+'//api.twitter.com/1/statuses/user_timeline.json?screen_name='+s.username[0]+'&count='+s.count+'&callback=?';
} else {
var query = (s.query || 'from:'+s.username.join(' OR from:'));
return proto+'//search.twitter.com/search.json?&q='+escape(query)+'&rpp='+s.count+'&callback=?';
}
}
`
Here is the full javascript:
(function($) {
$.fn.tweet = function(o){
var s = {
username: ["ohshititsjake"],
list: null,
avatar_size: 20,
count: 3,
intro_text: null,
outro_text: null,
join_text: null,
auto_join_text_default: "I said:<br/>",
auto_join_text_ed: "I",
auto_join_text_ing: "I said:<br/>",
auto_join_text_reply: "I replied to",
auto_join_text_url: "I was looking at",
loading_text: null,
query: null
};
if(o) $.extend(s, o);
$.fn.extend({
linkUrl: function() {
var returning = [];
var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*#)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%#!\-\/]))?)/gi;
this.each(function() {
returning.push(this.replace(regexp,"$1"));
});
return $(returning);
},
linkUser: function() {
var returning = [];
var regexp = /[\#]+([A-Za-z0-9-_]+)/gi;
this.each(function() {
returning.push(this.replace(regexp,"#$1"));
});
return $(returning);
},
linkHash: function() {
var returning = [];
var regexp = /(?:^| )[\#]+([A-Za-z0-9-_]+)/gi;
this.each(function() {
returning.push(this.replace(regexp, ' #$1'));
});
return $(returning);
},
capAwesome: function() {
var returning = [];
this.each(function() {
returning.push(this.replace(/\b(awesome)\b/gi, '<span class="awesome">$1</span>'));
});
return $(returning);
},
capEpic: function() {
var returning = [];
this.each(function() {
returning.push(this.replace(/\b(epic)\b/gi, '<span class="epic">$1</span>'));
});
return $(returning);
},
makeHeart: function() {
var returning = [];
this.each(function() {
returning.push(this.replace(/(<)+[3]/gi, "<tt class='heart'>♥</tt>"));
});
return $(returning);
}
});
function parse_date(date_str) {
// The non-search twitter APIs return inconsistently-formatted dates, which Date.parse
// cannot handle in IE. We therefore perform the following transformation:
// "Wed Apr 29 08:53:31 +0000 2009" => "Wed, Apr 29 2009 08:53:31 +0000"
return Date.parse(date_str.replace(/^([a-z]{3})( [a-z]{3} \d\d?)(.*)( \d{4})$/i, '$1,$2$4$3'));
}
function relative_time(time_value) {
var parsed_date = parse_date(time_value);
var relative_to = (arguments.length > 1) ? arguments[1] : new Date();
var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
var pluralize = function (singular, n) {
return '' + n + ' ' + singular + (n == 1 ? '' : 's');
};
if(delta < 60) {
return 'less than a minute ago';
} else if(delta < (60*60)) {
return 'about ' + pluralize("minute", parseInt(delta / 60)) + ' ago';
} else if(delta < (24*60*60)) {
return 'about ' + pluralize("hour", parseInt(delta / 3600)) + ' ago';
} else {
return 'about ' + pluralize("day", parseInt(delta / 86400)) + ' ago';
}
}
function build_url() {
var proto = ('https:' == document.location.protocol ? 'https:' : 'http:');
if (s.list) {
return proto+"//api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=? ";
} else if (s.query == null && s.username.length == 1) {
return proto+'//api.twitter.com/1/statuses/user_timeline.json?screen_name='+s.username[0]+'&count='+s.count+'&callback=?';
} else {
var query = (s.query || 'from:'+s.username.join(' OR from:'));
return proto+'//search.twitter.com/search.json?&q='+escape(query)+'&rpp='+s.count+'&callback=?';
}
}
return this.each(function(i, widget){
var list = $('<ul class="tweet_list">').appendTo(widget);
var intro = '<p class="tweet_intro">'+s.intro_text+'</p>';
var outro = '<p class="tweet_outro">'+s.outro_text+'</p>';
var loading = $('<p class="loading">'+s.loading_text+'</p>');
if(typeof(s.username) == "string"){
s.username = [s.username];
}
if (s.loading_text) $(widget).append(loading);
$.getJSON(build_url(), function(data){
if (s.loading_text) loading.remove();
if (s.intro_text) list.before(intro);
var tweets = (data.results || data);
$.each(tweets, function(i,item){
// auto join text based on verb tense and content
if (s.join_text == "auto") {
if (item.text.match(/^(#([A-Za-z0-9-_]+)) .*/i)) {
var join_text = s.auto_join_text_reply;
} else if (item.text.match(/(^\w+:\/\/[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&\?\/.=]+) .*/i)) {
var join_text = s.auto_join_text_url;
} else if (item.text.match(/^((\w+ed)|just) .*/im)) {
var join_text = s.auto_join_text_ed;
} else if (item.text.match(/^(\w*ing) .*/i)) {
var join_text = s.auto_join_text_ing;
} else {
var join_text = s.auto_join_text_default;
}
} else {
var join_text = s.join_text;
};
var from_user = item.from_user || item.user.screen_name;
var profile_image_url = item.profile_image_url || item.user.profile_image_url;
var join_template = '<span class="tweet_join"> '+join_text+' </span>';
var join = ((s.join_text) ? join_template : ' ');
var avatar_template = '<a class="tweet_avatar" href="http://twitter.com/'+from_user+'"><img src="'+profile_image_url+'" height="'+s.avatar_size+'" width="'+s.avatar_size+'" alt="'+from_user+'\'s avatar" title="'+from_user+'\'s avatar" border="0"/></a>';
var avatar = (s.avatar_size ? avatar_template : '');
var date = '<span class="tweet_time">'+relative_time(item.created_at)+'</span>';
var text = '<span class="tweet_text">' +$([item.text]).linkUrl().linkUser().linkHash().makeHeart().capAwesome().capEpic()[0]+ '</span>';
// until we create a template option, arrange the items below to alter a tweet's display.
list.append('<li>' + avatar + date + join + text + '</li>');
list.children('li:first').addClass('tweet_first');
list.children('li:odd').addClass('tweet_even');
list.children('li:even').addClass('tweet_odd');
});
if (s.outro_text) list.after(outro);
$(widget).trigger("loaded").trigger((tweets.length == 0 ? "empty" : "full"));
});
});
};
})(jQuery);
Looking at the permalink's IDs on that user account, they don't match with the IDs getting generated in your post. The answer is probably in this post:
Why a wrong tweet id is returned from twitter API?
so try changing this line:
var date = '<span class="tweet_time">'+relative_time(item.created_at)+'</span>';
to this:
var date = '<span class="tweet_time">'+relative_time(item.created_at)+'</span>';
Really, it's just changing item.id to item.id_str.in the middle of that line.