Record Audio for Android and iOS using Appcelerator Titanium - titanium

I'm having problems trying to record audio into a file. I'm trying to run the sample code (with the required permissions in the tiapp.xml) but i'm always getting errors (like "+[NSBlock boundBridge:withKrollObject:]: unrecognized selector sent to class 0x1b5549500"; at the stop() action).
I can't find a module for audio recording (i've used the tutorial.audiorecord but it doesn't work in newest versions of SDK)
This is the sample code from the appcelerator documentation page https://docs.appcelerator.com/platform/latest/#!/api/Titanium.Media.AudioRecorder
I try everything but doesn't work.
Someone have a working example or a module for Appcelerator SDK 7?
var window = Ti.UI.createWindow({
backgroundColor: '#fff'
});
var recordStart = Ti.UI.createButton({
title: 'Start',
top: 10
});
var recordPause = Ti.UI.createButton({
title: 'Pause',
top: 60
});
var recordStop = Ti.UI.createButton({
title: 'Stop',
top: 110
});
var recordPlay = Ti.UI.createButton({
title: 'Play',
top: 160
});
var audioRecorder = Ti.Media.createAudioRecorder();
var record;
var audioPlayer;
window.addEventListener('open', function(e) {
if (!Ti.Media.hasAudioRecorderPermissions()) {
Ti.Media.requestAudioRecorderPermissions(function(e) {
if (e.success) {
window.add(recordStart);
}
});
} else {
window.add(recordStart);
}
});
recordStart.addEventListener('click', function(e) {
audioRecorder.start();
});
recordPause.addEventListener('click', function(e) {
if (audioRecorder.getPaused()) {
recordPause.setTitle('Pause');
audioRecorder.resume();
} else {
recordPause.setTitle('Resume');
audioRecorder.pause();
}
});
recordStop.addEventListener('click', function(e) {
record = audioRecorder.stop();
Ti.API.info(record.getNativePath());
});
recordPlay.addEventListener('click', function(e) {
audioPlayer = Ti.Media.createAudioPlayer({
url: record.getNativePath()
});
audioPlayer.start();
});
window.add(recordPause);
window.add(recordStop);
window.add(recordPlay);
window.open();
Thanks in advance

This is an example using Titanium's Hyperloop: https://gist.github.com/dinahgarcia/119ac00c91334d3951601cf347bad8d4
To be able to use it you need to enable Hyperloop: https://docs.appcelerator.com/platform/latest/#!/guide/Enabling_Hyperloop

Related

Close NavigationWindow (modal ) from another js file in Titanium IOS7

I am migrating a current project to 3.1.3 . I need a close button on the modal window so i had to use a NavigationWindow as suggested in the IOS7 migration guide. Here is what i have
btnSubscription.addEventListener('click', function(e) {
Ti.API.info('Subscription Button Clicked.');
openWindow("paymentsubscription.js", "Subscription");
});
function openWindow(url, title) {
var win = Ti.UI.createWindow({
url : url,
backgroundColor : 'white',
modal : true,
title : title
});
if (Titanium.Platform.osname !== "android") {
var winNav = Ti.UI.iOS.createNavigationWindow({
modal: true,
window: win
});
}
if (Titanium.Platform.osname !== "android") {
winNav.open();
}
else {
win.open();
}
}
Now on paymenttransaction.js i was previously doing this when i was using titanium 2.x
var mainWindow = Ti.UI.currentWindow;
var mainWinClose = Ti.UI.createButton({
style : Ti.UI.iPhone.SystemButtonStyle.DONE,
title : 'close'
});
if (Titanium.Platform.osname !== "android") {
mainWinClose.addEventListener('click', function() {"use strict";
mainWindow.close();
});
responseWindow.setRightNavButton(responseWinRightNavButton);
mainWindow.setRightNavButton(mainWinClose);
}
The problem i am facing is that i need to close winNav in the case of IOS and not win anymore. In paymenttransaction.js i was previously using
var mainWindow = Ti.UI.currentWindow;
But now i need to close the navigation window(winNav) and this does not hold good anymore. Is there anyway to do this? . Is there a Ti.UI.currentWindow equivalent for NavigationWindow ?
You aren't using the navigationWindow properly. You shouldn't be calling open() on a window when you use one.
You are looking for:
`winNav.openWindow(yourWindow)
Also when you are creating a new window, pass a pointer to your navigationWindow in the constructor, then you can close the window properly. Don't create a window like that use CommonJS's require() to return your window:
paymenttransaction.js:
function paymentTransactionWindow(navGroup, otherArgs) {
var mainWinClose = Ti.UI.createButton({
style : Ti.UI.iPhone.SystemButtonStyle.DONE,
title : 'close'
});
var win = Ti.UI.createWindow({
url : url,
backgroundColor : 'white',
modal : true,
title : title,
rightNavButton: mainWinClose
});
if (Titanium.Platform.osname !== "android") {
mainWinClose.addEventListener('click', function() {
navGroup.closeWindow(win);
});
return win;
}
module.exports = paymentTransactionWindow;
Then in your previousWindow:
PaymentTransactionWindow = require('/paymentTransactionWindow); //the filename minus .js
var paymentTransactionWindow = new PaymentTransactionWindow(winNav, null);
mainNav.openWindow(paymentTransactionWindow);
watch some of the videos on commonJS: http://www.appcelerator.com/blog/2011/08/forging-titanium-episode-1-commonjs-modules/

titanium display hundreds of rows with tableviewrow

using these lines of code I can display aproximately hundreds of tableviewrows in a tableview. The problem is that the window is opening in 3 seconds (android device). I guess there's some optimization I have to do in order to display the table in less than 1 sec.
any advice about it?
thanks in advance
EDIT
lines of code
module.exports.draw = function(){
els = [];
var cocktails = Ti.App.cocktails;
for(var i=0;i<cocktails.length;i++){
els.push({
type: 'Ti.UI.View',
searchableText : cocktails[i].nome,
properties : {
cocktail_id:cocktails[i].id,
borderColor:"#eee",
borderWidth: 1,
height: 100,
nome:cocktails[i].nome
},
childTemplates : [
{
type: 'Ti.UI.Label',
bindId : cocktails[i].id,
properties : {
text: cocktails[i].nome,
cocktail_id:cocktails[i].id,
color:"#000",
left:30,
zIndex:10,
top:10,
font:{
fontSize:20,
fontWeight:'bold'
}
},
events : {
click : function(e) {
Ti.App.fireEvent("render",{pag:'prepare',id:e.bindId});
}
}
},
{
type : 'Ti.UI.Label',
properties : {
left:30,
color:"#999",
top:50,
cocktail_id:cocktails[i].id,
text:cocktails[i].ingTxt != undefined?cocktails[i].ingTxt:''
},
bindId:cocktails[i].id,
events : {
click : function (e){
Ti.App.fireEvent("render",{pag:'prepare',id:e.bindId});
}
}
}
]
});
}
var search = Ti.UI.createSearchBar({
height:50,
width:'100%'
});
search.addEventListener('cancel', function(){
search.blur();
});
var content = Ti.UI.createListView({sections:[Ti.UI.createListSection({items: els})],searchView:search});
search.addEventListener('change', function(e){
content.searchText = e.value;
});
return content;
};
You need to look into lazy loading
http://www.appcelerator.com/blog/2013/06/quick-tip-cross-platform-tableview-lazy-loading/
As thiswayup suggests, lazy loading would probably be a very good idea.
If you do not wan't to use lazy loading you could do this:
function getListWindow( items ) {
var firstLayout = true;
var win = Ti.UI.createWindow({
//Your properties here.
});
var list = Ti.UI.createTableView({
data : [],
//other properties here
});
win.add(list);
win.addEventListener('postlayout', function() {
if(firstLayout) {
firstLayout = false;
var rows = [];
//Assuming the items argument is an array.
items.forEach(function( item ) {
rows.push( Ti.UI.createTableViewRow({
//Properties here based on item
}));
});
list.data = rows;
}
});
return win;
}
Doing this will open your window right away and load the rows after the window is shown. Showing a loader while the rows are being generated would probably be a good idea.

FullCalendar and Flot Resize Conflict

I've successfully integrated both a Flot line graph and an instance of FullCalendar into my site. They are both on separate pages (although the pages are loaded into a div via AJAX).
I've added the Flot Resize plugin and that works perfectly, re-sizing the line graph as expected. However, it seems to cause an error when resizing the calendar.
Even if I load the calendar page first, when I resize the window I get this error in the console (also, the calendar does not resize correctly):
TypeError: 'undefined' is not an object (evaluating 'r.w=o!==c?o:q.width()')
I was struggling to work out where the error was coming from, so I removed the link to the Flot Resize JS and tried again. Of course the line graph does not resize, but when resizing the calendar, it works correctly.
The div containers for the two elements have different names and the resize function is called from within the function to draw the line graph (as required).
I have tried moving the link to the Flot Resize plugin into different places (i.e. above/below the fullCalendar JS, into the template which holds the graph), but all to no avail.
Does anyone have any idea where the conflict might be and how I might solve it??
Thanks very much!
EDIT: It seems that the error is also triggered when loading the line graph (flot) page AFTER the fullcalendar page even without resizing the window.... Now I am very confused!
EDIT 2: The code which draws the line graph. The function is called on pageload and recieves the data from JSON pulled off the server. When the graph is loaded, I still get the error about shutdown() being undefined.
function plotLineGraph(theData){
var myData = theData['data'];
var myEvents = theData['events'];
var myDates = theData['dates'];
var events = new Array();
for (var i=0; i<myEvents.length; i++) {
events.push(
{
min: myEvents[i][0],
max: myEvents[i][1],
eventType: "Calendar Entry",
title: myEvents[i][2],
description: myEvents[i][3]
}
);
}
function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css( {
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
border: '1px solid #fdd',
padding: '2px',
'background-color': 'black',
opacity: 0.80
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
$("#placeholder").bind("plothover", function (event, pos, item) {
$("#x").text(pos.x.toFixed(2));
$("#y").text(pos.y.toFixed(2));
if ($("#enableTooltip:checked").length == 0) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
if(item.series.label != null){
showTooltip(item.pageX, item.pageY,
item.series.label + " of " + y);
}
}
}
else {
$("#tooltip").remove();
previousPoint = null;
}
}
});
var d1 = [
myData[0], myData[1], myData[2], myData[3], myData[4],
myData[5], myData[6], myData[7], myData[8], myData[9],
myData[10], myData[11], myData[12], myData[13], myData[14],
myData[15], myData[16], myData[17], myData[18], myData[19],
myData[20], myData[21], myData[22], myData[23], myData[24],
myData[25], myData[26], myData[27], myData[28], myData[29]
];
var markings = [
{ color: '#FFBDC1', yaxis: { from: 0, to: 2 } },
{ color: '#F2E2C7', yaxis: { from: 2, to: 3.5 } },
{ color: '#B6F2B7', yaxis: { from: 3.5, to: 5 } }
];
$.plot($("#placeholder"), [
{label: "Average Daily Rating", data: d1, color: "black"}
], {
events: {
data: events,
},
series: {
lines: { show: true },
points: { show: true }
},
legend: { show: true, container: '#legend-holder' },
xaxis: {
ticks:[
myDates[0], myDates[1], myDates[2], myDates[3], myDates[4],
myDates[5], myDates[6], myDates[7], myDates[8], myDates[9],
myDates[10], myDates[11], myDates[12], myDates[13], myDates[14],
myDates[15], myDates[16], myDates[17], myDates[18], myDates[19],
myDates[20], myDates[21], myDates[22], myDates[23], myDates[24],
myDates[25], myDates[26], myDates[27], myDates[28], myDates[29]
],
},
yaxis: {
ticks: 5,
min: 0,
max: 5
},
grid: {
backgroundColor: { colors: ["#fff", "#eee"] },
hoverable: true,
clickable: true,
markings: markings
},
selection: {
color: 'white',
mode: 'x'
},
});
$('#placeholder').resize();
$('#placeholder').shutdown();
}
EDIT 3:
The calendar is called like this:
function showCalendar() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#fullcalendar').fullCalendar({
header: {
left: 'prev',
center: 'title',
right: 'next'
},
clickable: true,
firstDay: 1,
eventSources: [
{
url: '/populate-calendar/{{theProductUuid}}/',
color: 'black',
data: {
text: 'text'
}
}
],
eventClick: function(calEvent, jsEvent, view) {
var startDate = $.fullCalendar.formatDate(calEvent.start, 'yyyy-MM-dd');
var endDate = $.fullCalendar.formatDate(calEvent.end, 'yyyy-MM-dd');
var eventId = calEvent.uuid;
$('#modal-event-title').text(calEvent.title);
$('#edit-event-name').val(calEvent.title);
$('#edit-start-date').val(startDate);
$('#edit-end-date').val(endDate);
$('#edit-event-text').val(calEvent.text);
$('#edit-event-btn').attr('data-uuid', eventId);
$('#modal-edit-event').on('click', '#delete-btn', function(){
deleteCalendarEvent(eventId);
});
$('#modal-edit-event').modal();
},
});
}
The AJAX to load the page containing the flot chart:
function loadDetailedReports(uuid){
$('#product-content').fadeOut('slow', function(){
$('#product-content').empty();
$('#whole-product-sub-nav .active').removeClass('active');
$('#detailed-reports-content').load('/detailed-reports/' + uuid + '/', function(){
$('#detailed-reports-btn').addClass('active');
$('#detailed-reports-content').fadeIn('slow', function(){
if (authorized){
setLocationHash('loadDetailedReports&' + uuid);
getChartData(uuid);
} else {
setLocationHash('');
}
});
});
});
}
And the AJAX to load the page containing the calendar:
function loadCalendar(uuid){
$('#detailed-reports-content').empty().hide();
$('#product-content').fadeOut('slow', function(){
$('#whole-product-sub-nav .active').removeClass('active');
$('#product-content').load('/calendar/' + uuid + '/', function(){
$('#calendar-btn').addClass('active');
$('#product-content').fadeIn('slow', function(){
if (authorized){
setLocationHash('loadCalendar&' + uuid);
} else {
setLocationHash('');
}
showCalendar();
});
});
});
}
The calls to .resize and .shutdown are there because I was under the impression that they are necessary to achieve the resizing function and in response to your earlier comment regarding shutdown...... They're quite possibly n00b errors........?!?!
It looks like this is triggering on line 198 of jquery-resize:
data.w = w !== undefined ? w : elem.width();
This sounds like a race-condition stemming from the way you load different content into the same div. Flot binds the resize event to the chart div, and only un-binds it if the plot is destroyed cleanly.
EDIT: Looking at your code, my first suggestion would be to get rid of the resize and shutdown calls at the end of plotLineGraph. The resize plugin doesn't require any setup; it hooks into Flot to attach automatically to any new plot. So your call to resize is actually to jQuery's resize event trigger, which may be what's causing the error.
EDIT #2: I'm still not clear on your structure, but to generalize: anywhere that you might be getting rid of #placeholder (via emptying its parent or anything like that) you should first call shutdown on the plot object. If you aren't keeping a reference to it, you can do it like this: $("#placeholder").data("plot").shutdown(); but then have to account for the fact that it's undefined prior to the creation of your first plot.
If that still doesn't work, I'd need to see a live (simplified) example to make any further suggestions.

RubyOnRails3 - FullCalendar

I would like to use calendar in my project, I already used table_builder gem and event_calendar gem but fullcalendar gem is more appropriate for me. The problem is I can't find any step by step tutorial to use it and somehow I'm new to RubyOnRails. Can any one help me to be able to understand how to use it please?
*I Figured Out how to use full calendar - just go to fullcalendar web site and download the required version of fullcalendar JavaScript and css files - include fullcalendar.js and fullcalendar.css in the header of layout - create a new js file called calendar and write the following code: *
$(document).ready(function() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#my_calendar').fullCalendar({
editable: true,
droppable: true,
theme: true,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultView: 'month',
height: 500,
slotMinutes: 15,
loading: function(bool){
if (bool)
$('#loading').show();
else
$('#loading').hide();
},
// a future calendar might have many sources.
eventSources: [{
url: '/events/index/',
color: 'yellow',
textColor: 'black',
ignoreTimezone: false
}],
dragOpacity: "0.5",
//http://arshaw.com/fullcalendar/docs/event_ui/eventDrop/
eventDrop: function(event, dayDelta, minuteDelta, allDay, revertFunc){
updateEvent(event);
},
// http://arshaw.com/fullcalendar/docs/event_ui/eventResize/
eventResize: function(event, dayDelta, minuteDelta, revertFunc){
updateEvent(event);
},
// http://arshaw.com/fullcalendar/docs/mouse/eventClick/
eventClick: function(event, jsEvent, view){
window.location = ('/events/show?id=' + event.id)
},
});
});
function updateEvent(the_event) {
$.ajax({
type: 'POST',
url: '/events/update_js?id='+ the_event.id +"&startd=" + the_event.start+"&endd=" + the_event.end, //the script to call to get data
data: {end: the_event.end, start: the_event.start } , //you can insert url argumnets here to pass to api.php
//for example "id=5&parent=6"
dataType: 'json', //data format
success: function() //on receive of reply
{
alert("done!")
}
});
};
There are other code in the model and view in which the calendar will appear. also I changed the code of edit event function because it didn't work with me and function in the controller of event for edit- for any help I'm here any time. hope you can use it as I did

Youtube javascript api, pjax, how to reload onYouTubeIframeAPIReady();

I have a problem with the youtube javascript player api.
I call this js code :
function onYouTubeIframeAPIReady() {
var podcast = document.getElementById('podcast')
var player = new YT.Player( document.getElementById('podcast'));
player.addEventListener('onStateChange', function(e) {
if (e.data === 1) {
alert("play");
}
});
};
with this html code :
<iframe id="podcast" type="text/html" width="720" height="405"
src="https://www.youtube.com/embed/XXXXXX?cc_load_policy=1&enablejsapi=1&theme=light"
frameborder="0" allowfullscreen>
The problem is that I use the pjax system, so the global javascript code is not reloaded when I navigate.
So, I reload some part of my javascript code when pjax:success. I tried something like this :
$(document).on('pjax:success', function() {
onYouTubeIframeAPIReady();
}
but it doesn't work. My question is how to reload onYouTubeIframeAPIReady(); when it must to be defined globally as it is said there onYouTubeIframeAPIReady function is not calling
When my player is defined I don't use onYoutubePlayerAPIReady. It's the best solution I find, and it works.
var player = {
playVideo: function(container, videoId) {
if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
window.onYouTubePlayerAPIReady = function() {
player.loadPlayer(container, videoId);
};
$.getScript('//www.youtube.com/player_api');
} else {
player.loadPlayer(container, videoId);
}
},
loadPlayer: function(container, videoId) {
window.myPlayer = new YT.Player(container,
height: 200,
width: 200,
videoId: videoId,
});
}
};
var containerId = 'podcast';
var videoId = '<%= #youtube_id %>';
player.playVideo(containerId, videoId);