I need to cache my HttpClient response for android device. The Example given in their official document applies for Iphone & IPad.
Ok, here is one approach to achieve this:
Within your httpRequests success handler, attach a "timestamp" to your response:
// Assuming you are working with JSON data
var response = JSON.parse(this.responseText);
response.timestamp = new Date();
// For the purpose of this example, we persist our response to properties
Ti.App.Properties.setObject('cachedResponse', response);
In your button eventListener we will check for the time that has passed
button.addEventListener('click', function() {
var cachedResponse = Ti.App.Properties.getObject('cachedResponse', { timestamp: false });
if(cachedResponse.timestamp) {
if(getHoursDiff(cachedResponse.timestamp, new Date()) > 24) {
// Last request older than 24 hours, reload data
} else {
// Last request was within 24 hours, use cached data
}
} else {
// No data has been saved yet, load Data
}
});
This function calculates the time difference in hours
// http://blogs.digitss.com/javascript/calculate-datetime-difference-simple-javascript-code-snippet/
function getHoursDiff(earlierDate, laterDate) {
var nTotalDiff = laterDate.getTime() - earlierDate.getTime();
var hours = Math.floor(nTotalDiff/1000/60/60);
return hours;
}
Note
This is not a complete example, you have to optimize and change the code to your needs.
Related
I am trying to record media using the mediaRecorder API. Here is my code (just the relevant part). I expect to get a console log in saveChunks but it appears that the ondataavailable event is never triggered.I am able to see the video in the video element.
recordedChunks = [];
navigator.mediaDevices.getUserMedia({video:true, audio:true})
.then(function(stream) {
myVideoMedia = document.getElementById("vid1");
myVideoMedia.srcObject = stream;
myVideoMedia.onloadedmetadata = function(e) {
myVideoMedia.play();
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = saveChunks;
mediaRecorder.start();
console.log(mediaRecorder);
};
})
function saveChunks(event) {
console.log("Data recorded...");
//...
};
}
The console log of mediaRecorder.state is 'recording'
I did try by passing a timeslice of 1000 to start() and its working now! If no timeslice is passed, the function is called once at the end.
I'm writing an Odoo v9 widget, which renders a URL, based on concatenation of a setting in the database, and the actual form fields.
The setting in the database I figure should live in ir_config_parameter. I'm inserting a default value with my module.
What's the best way to get this value when rendering the widget? Doing an async ajax call using
new Model("ir.config_parameter")
seems a little heavy handed. Is there a better way to be doing this?
Thanks.
Widget code:
var UrlWidget2 = form_common.FormWidget.extend({
start: function() {
this._super();
this.field_manager.on("field_changed:ref", this, this.display_result);
this.display_result();
},
display_result: function() {
var ref = this.field_manager.get_field_value("ref");
if (!ref) return;
var baseUrl = 'https://example.com'; //this is the value I want to get from the setting in the database.
var url = baseUrl + '/foo/' + ref;
this.$el.html('View Externally<br /><br/>');
}
});
You can use RPC for this. This is example which work for me:
var Model = require('web.DataModel');
var UrlWidget2 = form_common.FormWidget.extend({
// just example how to get parameter from backend
display_result: function() {
var parameter = new Model('ir.config_parameter');
// get fields value, key
parameter.query(['value', 'key'])
// criteria of search - record with id = 1
.filter([['id', '=', 1]])
// only one record
.limit(1)
.all()
.then(function (parameter) {
// here data from server
console.log(parameter);
});
// ...
}
});
Hope this helps you.
The following is my code which is not working. Any help would be appreciated.
var myPlayer;
videojs("example_video_1").ready(function(){
myPlayer = this;
if(myPlayer.currentTime()>3)
{
alert("STARTED");
});
});
The ready event only occurs once, when the video initially loads. At that point, the current time is likely 0.
console.log(myPlayer.currentTime()); // 0
To continue checking the time as it changes, you should be able to use the timeupdate event.
myPlayer = this;
myPlayer.on('timeupdate', function () {
// ...
});
Though, note that this event occurs multiple times per second. So, to avoid spamming yourself with alerts, you'll probably want to keep track whether 3 seconds have already passed.
var threshold = 4;
var thresholdReached = false;
myPlayer = this;
myPlayer.on('timeupdate', function () {
if (myPlayer.currentTime() >= threshold && !thresholdReached) {
thresholdReached = true;
alert('Started');
}
});
I am using this sample code for my YouTube analytics API:
(function() {
// Retrieve your client ID from the {{ Google Cloud Console }} at
// {{ https://cloud.google.com/console }}.
var OAUTH2_CLIENT_ID = 'YOUR_CLIENT_ID';
var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/yt-analytics.readonly',
'https://www.googleapis.com/auth/youtube.readonly'
];
var ONE_MONTH_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 30;
// Keep track of the currently authenticated user's YouTube channel ID.
var channelId;
// For information about the Google Chart Tools API, see:
// https://developers.google.com/chart/interactive/docs/quick_start
google.load('visualization', '1.0', {'packages': ['corechart']});
// Upon loading, the Google APIs JS client automatically invokes this callback.
// See http://code.google.com/p/google-api-javascript-client/wiki/Authentication
window.onJSClientLoad = function() {
gapi.auth.init(function() {
window.setTimeout(checkAuth, 1);
});
};
// Attempt the immediate OAuth 2.0 client flow as soon as the page loads.
// If the currently logged-in Google Account has previously authorized
// the client specified as the OAUTH2_CLIENT_ID, then the authorization
// succeeds with no user intervention. Otherwise, it fails and the
// user interface that prompts for authorization needs to display.
function checkAuth() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: true
}, handleAuthResult);
}
// Handle the result of a gapi.auth.authorize() call.
function handleAuthResult(authResult) {
if (authResult) {
// Authorization was successful. Hide authorization prompts and show
// content that should be visible after authorization succeeds.
$('.pre-auth').hide();
$('.post-auth').show();
loadAPIClientInterfaces();
} else {
// Authorization was unsuccessful. Show content related to prompting for
// authorization and hide content that should be visible if authorization
// succeeds.
$('.post-auth').hide();
$('.pre-auth').show();
// Make the #login-link clickable. Attempt a non-immediate OAuth 2.0
// client flow. The current function is called when that flow completes.
$('#login-link').click(function() {
gapi.auth.authorize({
client_id: OAUTH2_CLIENT_ID,
scope: OAUTH2_SCOPES,
immediate: false
}, handleAuthResult);
});
}
}
// Load the client interfaces for the YouTube Analytics and Data APIs, which
// are required to use the Google APIs JS client. More info is available at
// http://code.google.com/p/google-api-javascript-client/wiki/GettingStarted#Loading_the_Client
function loadAPIClientInterfaces() {
gapi.client.load('youtube', 'v3', function() {
gapi.client.load('youtubeAnalytics', 'v1', function() {
// After both client interfaces load, use the Data API to request
// information about the authenticated user's channel.
getUserChannel();
});
});
}
// Call the Data API to retrieve information about the currently
// authenticated user's YouTube channel.
function getUserChannel() {
// Also see: https://developers.google.com/youtube/v3/docs/channels/list
var request = gapi.client.youtube.channels.list({
// Setting the "mine" request parameter's value to "true" indicates that
// you want to retrieve the currently authenticated user's channel.
mine: true,
part: 'id,contentDetails'
});
request.execute(function(response) {
if ('error' in response) {
displayMessage(response.error.message);
} else {
// We need the channel's channel ID to make calls to the Analytics API.
// The channel ID value has the form "UCdLFeWKpkLhkguiMZUp8lWA".
channelId = response.items[0].id;
// Retrieve the playlist ID that uniquely identifies the playlist of
// videos uploaded to the authenticated user's channel. This value has
// the form "UUdLFeWKpkLhkguiMZUp8lWA".
var uploadsListId = response.items[0].contentDetails.relatedPlaylists.uploads;
// Use the playlist ID to retrieve the list of uploaded videos.
getPlaylistItems(uploadsListId);
}
});
}
// Call the Data API to retrieve the items in a particular playlist. In this
// example, we are retrieving a playlist of the currently authenticated user's
// uploaded videos. By default, the list returns the most recent videos first.
function getPlaylistItems(listId) {
// See https://developers.google.com/youtube/v3/docs/playlistitems/list
var request = gapi.client.youtube.playlistItems.list({
playlistId: listId,
part: 'snippet'
});
request.execute(function(response) {
if ('error' in response) {
displayMessage(response.error.message);
} else {
if ('items' in response) {
// The jQuery.map() function iterates through all of the items in
// the response and creates a new array that only contains the
// specific property we're looking for: videoId.
var videoIds = $.map(response.items, function(item) {
return item.snippet.resourceId.videoId;
});
// Now that we know the IDs of all the videos in the uploads list,
// we can retrieve information about each video.
getVideoMetadata(videoIds);
} else {
displayMessage('There are no videos in your channel.');
}
}
});
}
// Given an array of video IDs, this function obtains metadata about each
// video and then uses that metadata to display a list of videos.
function getVideoMetadata(videoIds) {
// https://developers.google.com/youtube/v3/docs/videos/list
var request = gapi.client.youtube.videos.list({
// The 'id' property's value is a comma-separated string of video IDs.
id: videoIds.join(','),
part: 'id,snippet,statistics'
});
request.execute(function(response) {
if ('error' in response) {
displayMessage(response.error.message);
} else {
// Get the jQuery wrapper for the #video-list element before starting
// the loop.
var videoList = $('#video-list');
$.each(response.items, function() {
// Exclude videos that do not have any views, since those videos
// will not have any interesting viewcount Analytics data.
if (this.statistics.viewCount == 0) {
return;
}
var title = this.snippet.title;
var videoId = this.id;
// Create a new <li> element that contains an <a> element.
// Set the <a> element's text content to the video's title, and
// add a click handler that will display Analytics data when invoked.
var liElement = $('<li>');
var aElement = $('<a>');
// Setting the href value to '#' ensures that the browser renders the
// <a> element as a clickable link.
aElement.attr('href', '#');
aElement.text(title);
aElement.click(function() {
displayVideoAnalytics(videoId);
});
// Call the jQuery.append() method to add the new <a> element to
// the <li> element, and the <li> element to the parent
// list, which is identified by the 'videoList' variable.
liElement.append(aElement);
videoList.append(liElement);
});
if (videoList.children().length == 0) {
// Display a message if the channel does not have any viewed videos.
displayMessage('Your channel does not have any videos that have been viewed.');
}
}
});
}
// This function requests YouTube Analytics data for a video and displays
// the results in a chart.
function displayVideoAnalytics(videoId) {
if (channelId) {
// To use a different date range, modify the ONE_MONTH_IN_MILLISECONDS
// variable to a different millisecond delta as desired.
var today = new Date();
var lastMonth = new Date(today.getTime() - ONE_MONTH_IN_MILLISECONDS);
var request = gapi.client.youtubeAnalytics.reports.query({
// The start-date and end-date parameters must be YYYY-MM-DD strings.
'start-date': formatDateString(lastMonth),
'end-date': formatDateString(today),
// At this time, you need to explicitly specify channel==channelId.
// See https://developers.google.com/youtube/analytics/v1/#ids
ids: 'channel==' + channelId,
dimensions: 'day',
sort: 'day',
// See https://developers.google.com/youtube/analytics/v1/available_reports
// for details about the different filters and metrics you can request
// if the "dimensions" parameter value is "day".
metrics: 'views',
filters: 'video==' + videoId
});
request.execute(function(response) {
// This function is called regardless of whether the request succeeds.
// The response contains YouTube Analytics data or an error message.
if ('error' in response) {
displayMessage(response.error.message);
} else {
displayChart(videoId, response);
}
});
} else {
// The currently authenticated user's channel ID is not available.
displayMessage('The YouTube channel ID for the current user is not available.');
}
}
// This boilerplate code takes a Date object and returns a YYYY-MM-DD string.
function formatDateString(date) {
var yyyy = date.getFullYear().toString();
var mm = padToTwoCharacters(date.getMonth() + 1);
var dd = padToTwoCharacters(date.getDate());
return yyyy + '-' + mm + '-' + dd;
}
// If number is a single digit, prepend a '0'. Otherwise, return the number
// as a string.
function padToTwoCharacters(number) {
if (number < 10) {
return '0' + number;
} else {
return number.toString();
}
}
// Call the Google Chart Tools API to generate a chart of Analytics data.
function displayChart(videoId, response) {
if ('rows' in response) {
hideMessage();
// The columnHeaders property contains an array of objects representing
// each column's title -- e.g.: [{name:"day"},{name:"views"}]
// We need these column titles as a simple array, so we call jQuery.map()
// to get each element's "name" property and create a new array that only
// contains those values.
var columns = $.map(response.columnHeaders, function(item) {
return item.name;
});
// The google.visualization.arrayToDataTable() function wants an array
// of arrays. The first element is an array of column titles, calculated
// above as "columns". The remaining elements are arrays that each
// represent a row of data. Fortunately, response.rows is already in
// this format, so it can just be concatenated.
// See https://developers.google.com/chart/interactive/docs/datatables_dataviews#arraytodatatable
var chartDataArray = [columns].concat(response.rows);
var chartDataTable = google.visualization.arrayToDataTable(chartDataArray);
var chart = new google.visualization.LineChart(document.getElementById('chart'));
chart.draw(chartDataTable, {
// Additional options can be set if desired as described at:
// https://developers.google.com/chart/interactive/docs/reference#visdraw
title: 'Views per Day of Video ' + videoId
});
} else {
displayMessage('No data available for video ' + videoId);
}
}
// This helper method displays a message on the page.
function displayMessage(message) {
$('#message').text(message).show();
}
// This helper method hides a previously displayed message on the page.
function hideMessage() {
$('#message').hide();
}
})();
When I insert in the client ID, it says this:
Daily Limit for Unauthenticated Use Exceeded. Continued use requires
signup.
I researched this, and it means I have to also put in the API Key. Where do I do this?
Thanks,
Ben
Before
gapi.auth.authorize
put
gapi.client.setApiKey(API_KEY);
Hi I am developing a website as my chrome extension.the extension periodically checks the output of a server file and then works according to the output of the server file.Now what I need is that presently it checks the output of the server file every 5 min.So what I need is that when the output of the server file changes at any time,at that moment I have to do some operations.How can I do this?
Here is my background.js
var myNotificationID = null;
var oldChromeVersion = !chrome.runtime;
chrome.windows.onCreated.addListener(function (){
updateIcon();
});
chrome.tabs.onCreated.addListener(function (){
updateIcon();
});
chrome.tabs.onUpdated.addListener(function (){
updateIcon();
});
function getGmailUrl() {
return "http://calpinemate.com/";
}
function isGmailUrl(url) {
return url.indexOf(getGmailUrl()) == 0;
}
chrome.windows.onCreated.addListener(function (){
updateIcon();
});
function onInit() {
updateIcon();
if (!oldChromeVersion) {
chrome.alarms.create('watchdog',{periodInMinutes:5,delayInMinutes: 0});
}
}
function onAlarm(alarm) {
if (alarm && alarm.name == 'watchdog') {
onWatchdog();
}
else {
updateIcon();
}
}
function onWatchdog() {
chrome.alarms.get('refresh', function(alarm) {
if (alarm) {
console.log('Refresh alarm exists. Yay.');
}
else {
updateIcon();
}
});
}
if (oldChromeVersion) {
updateIcon();
onInit();
}
else {
chrome.runtime.onInstalled.addListener(onInit);
chrome.alarms.onAlarm.addListener(onAlarm);
}
It is the updateIcon() which reads the server file.And when there is change in the output of server file,I have to call the updateIcon() itself.Presently only in every 5 min,the output is checked and updated in extension.But I need it to happen at the moment the status of server file changes.Anyone please help me.
In short,what I need is that when the output of API changes at any time at that time I have to call updateIcon().
Here is my updateIcon()
function updateIcon(){
var urlPrefix = 'http://www.calpinemate.com/employees/attendanceStatus/';
var urlSuffix = '/2';
var req = new XMLHttpRequest();
req.addEventListener("readystatechange", function() {
if (req.readyState == 4) {
if (req.status == 200) {
var item=req.responseText;
if(item==1){
.....//something
}
else{
// do something
}
else {
alert("ERROR: status code " + req.status);
}
}
});
var url = urlPrefix + encodeURIComponent(localStorage.username) + urlSuffix;
req.open("GET", url);
req.send(null);
}
I need to periodically monitor the API for output.
You could use a WebSocket to maintain a persistent, two-way channel between the server and your extension.
But, considering that PHP does not have native support for WebSockets (i.e. you would need to use an external library) and the fact that the interaction will be infrequent (only at log-in/-out), it might be unnecessary overhead.
I suggest you communicate the login-status directly from your web-page to your extension. For a more detailed description of the process, see my answer to one similar question of yours.
UPDATE:
Since it turned out you don't have control of the domain you need to "monitor", there is unfortunately no other option (that I know of) than polling at frequent intervals on that server-resource.
If you are using a non-persistent background-page (which is advisable due to its resource-friendliness) you must use the chrome.alarms API, which allows at most 1 triggering per minute: (in order to reduce the load on the user's machine - note: to help debug your extension, this limit is no imposed on unpacked extensions).
If you decide to use a persistent background-page, you can use setInterval() with an arbitrarily smal period (in milliseconds):
setInterval(function() {
/* Check up on the server */
...
}, 30000); // <-- trigger every 30.000 milliseconds (== 30 seconds)