Titanium Appcelerator - method needed to replace Ti.UI.currentWindow() - javascript

An inherited project has been implemented using old deprecated methods.
A button loads a new page like so:
main.js
var thisWindow = Ti.UI.currentWindow;
var nav = Titanium.UI.iOS.createNavigationWindow({
window: thisWindow
});
nav.open();
myButton.addEventListener('click', function(evt) {
var detailWindow = Ti.UI.createWindow({
backgroundColor: '#333333',
exhibitLat: latitude,
exhibitLon: longitude,
url: 'mapPage.js'
});
thisWindow.nav = nav;
nav.openWindow(detailWindow, {
animated: true
});
};
On mapPage.js it refers to Ti.UI.currentWindow() to use data from main.js like so:
mapPage.js
var window = Ti.UI.currentWindow;
var Latitude = window.latitude;
var Longitude = window.longitude;
How can I reproduce this method to successfully pass parameters to mapPage.js with require?
Been scratching my head on this for a while - so some help (with code examples 😀 ) would be most welcome! Thanks

The url property is indeed very outdated. Instead you should create the window inside mapPage and return that.
mapPage.js:
exports.createWindow = function(latitude, longitude){
var detailWindow = Ti.UI.createWindow({
backgroundColor: '#333333',
exhibitLat: latitude,
exhibitLon: longitude,
url: 'mapPage.js'
});
return detailWindow
}
Then your main.js will look like this:
var nav = Titanium.UI.iOS.createNavigationWindow({
window: thisWindow
});
nav.open();
myButton.addEventListener('click', function(evt) {
thisWindow.nav = nav;
var detailWindow = require('mapPage').createWindow(latitude, longitude);
nav.openWindow(detailWindow, {
animated: true
});
};
I also stripped out the thisWindow section. If that gets its "currentWindow" the same way mapPage.js got it, you need to replace it with something similar as displayed here.

Related

Getting the Window Height of an Embedded Tableau Dashboard

After my dashboard initializes and is fully loaded, I need to get the window height of the embed inside the iframe. Ideally, I'd like to get innerHeight inside of onFirstInteractive, but am unable to do so.
function initViz() {
var containerDiv = document.getElementById("vizContainer");
var url = "http://public.tableau.com/views/RegionalSampleWorkbook/Storms";
var options = {
onFirstInteractive: function() {
// How do I get the height of the rendered contents?
}
};
var viz = new tableau.Viz(containerDiv, url, options);
}
Subscribe to the VIZ_RESIZE event, it provides the new dimensions of the iframe on initialization and resize:
viz.addEventListener(tableau.TableauEventName.VIZ_RESIZE, function(event) {
console.log(event.getAvailableSize());
});
Which gives the following:
When the iframe appears like this:
If you absolutely want to retrieve the information in onFirstInteractive, you can do this:
onFirstInteractive: function(viz) {
const iframeStyle = viz.$1._impl.$1h.style;
const { height, width } = iframeStyle;
console.log({ height, width });
}
But it's a little bit hacky because this solution uses properties that are not supposed to be public, so this kind of code may break on future Tableau JS library updates.

Google Maps works but without any maps displaying?

I've embedded a Google Map into my application. Interacting with the map works. Responding to map events works (map zoom_changed, marker dragend, etc). However, only some parts of the map are visible (the marker and the Google logo for example), but the maps themselves are not (at least they don't appear 95% of the time).
Can anyone tell me what's going on here?
EDIT: I'm using this as a KnockoutJS component (inserted with with <gui-map></gui-map>). The source code below. I don't believe the use of KnockoutJS has anything to do with the map issues because: a) all the observables are wired up correctly and working 100% of the time; and b) the map does work randomly without any code changes 5% of the time.
define(['knockout', 'underscore'], function(ko, _){
function Map(params, componentInfo) {
var self = this;
var defaultPosition = {lat:-25,lng:-130};
var width = ko.isObservable(params.width) ? params.width : ko.observable(params.width ? params.width : '100px');
var height = ko.isObservable(params.height) ? params.height : ko.observable(params.height ? params.height : '100px');
var center = ko.isObservable(params.center) ? params.center : ko.observable(params.center ? params.center : defaultPosition);
var zoom = ko.isObservable(params.zoom) ? params.zoom : ko.observable(params.zoom ? params.zoom : 12);
var marker = ko.isObservable(params.marker) ? params.marker : ko.observable(params.marker ? params.marker : defaultPosition);
var element = componentInfo.element;
element.style.display = 'block';
element.style.width = width();
element.style.height = height();
width.subscribe(function(){
element.style.width = width();
});
height.subscribe(function(){
element.style.height = height();
});
function onObservableCenterChanged(newValue){
onObservableCenterChanged.changing = 1;
console.log('updating center map');
map.setCenter(newValue);
setTimeout(function(){
onObservableCenterChanged.changing = 0;
}, 500);
}
center.subscribe(onObservableCenterChanged);
function onObservableZoomChanged(newValue){
onObservableZoomChanged.changing = 1;
console.log('updating map zoom');
map.setZoom(newValue);
setTimeout(function(){
onObservableZoomChanged.changing = 0;
}, 500);
}
zoom.subscribe(onObservableZoomChanged);
var map = new google.maps.Map(element, {
center: center(),
zoom: zoom()
});
var mapMarker = new google.maps.Marker({
position:center(),
map:map,
title:'',
draggable:true
});
map.addListener('center_changed', (function(){
var mapCenterChangeTimeout;
return function(){
if (mapCenterChangeTimeout) {
clearTimeout(mapCenterChangeTimeout);
}
mapCenterChangeTimeout = setTimeout(function(){
if (!onObservableCenterChanged.changing) {
var newCenter = map.getCenter();
console.log('updating center observble');
center({
lat:newCenter.lat(),
lng:newCenter.lng()
});
}
}, 500);
};
})());
map.addListener('zoom_changed', (function(){
var mapZoomChangedTimeout;
return function(){
if (mapZoomChangedTimeout) {
clearTimeout(mapZoomChangedTimeout);
}
mapZoomChangedTimeout = setTimeout(function(){
if (!onObservableZoomChanged.changing) {
console.log('updating zoom observable');
zoom(map.getZoom());
}
}, 500);
};
})());
mapMarker.addListener('dragend', function(){
var newPosition = mapMarker.getPosition();
marker({
lat:newPosition.lat(),
lng:newPosition.lng()
});
});
}
ko.components.register('gui-map', {
template:{
require:'text!components/gui/map.html'
},
viewModel:{
createViewModel:function(params, componentInfo){
return new Map(params, componentInfo);
}
}
});
});
EDIT2: I have succesfully got the above to work by wrapping the entire body of the Map function (with exception of the var self = this; assignment) in a anonymous function called with setTimeout() (with a delay of 5000 ms). However, all the code executes after the DOMContentLoaded event anyway, so I'm not sure why this is an issue.
The cause of the problem was that the Google Maps Javascript API does NOT render the map correctly if the element in which the map is contained is not visible. In my situation, the map was located in a hidden tab. The timeout mentioned above solved the problem because the delay gave me long enough to switch tabs before the function that calls the Google Maps API could be executed (if I delayed opening the tab until after the Google Maps API was called, the issue would re-surface).
I got around this issue by manually triggering a resize on the map, and manually updating the various controls on the map, e.g.:
google.maps.event.trigger(map, 'resize');
infoWindow.setContent(infoWindowElement);
infoWindow.close();
infoWindow.open(map, marker);
I hope this solution helps someone else.

How to communicate between two views( different js files) in Famo.us

I am creating a famo.us app in which header footer and content area is there. In content area different views are rendering using RenderController on action of each other and in each view different sub views are there. Events are communicating through java script using document.dispatchEvent() and addEventLiserner() method instead of famo.us events. I just want to ask that whether it is worth using this listener functions.
As I have tried through famous events like setInputHandler, setOnputHandler, emit , addListener, pipe given in famo.us documentation, But I cannot able to communicate using this.
The main question is the static app created by me is taking huge time when loaded from server and animations are running very slowly. Is there any solution for this.
Actually code is too long dummy example is below. I am creating an application having header footer and content view. In Content view I am rendering different views using renderController.
Content View
define(function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var LoginView = require('views/login/LoginView');
var AccountsView = require('views/login/AccountsView'); //need to call on login
function ContentView() {
View.apply(this, arguments);
var renderController = new RenderController({
inTransition: {curve: Easing.easeOut, duration: 1000},
outTransition: {curve: Easing.easeIn, duration: 1000},
overlap: true,
});
var loginview = new LoginView();
renderController.show(loginview); //rendered initially
this.add(renderController);
document.addEventListener("showAccountsView",function(){
var accoutsView = new AccountsView()
renderController.show(accoutsView);
}.bind(this));
}
});
Login View
define(function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var InputSurface = require("famous/surfaces/InputSurface");
function LoginView() {
View.apply(this, arguments);
var loginBoxContainer = new ContainerSurface({
classes:["backfaceVisibility"],
size:[undefined,295],
properties: {
overflow: 'hidden',
padding:'0 10px'
}
});
this.add(loginBoxContainer);
var userInput = new InputSurface({
size: [undefined, 45],
});
var userInputModifier = new StateModifier({
transform: Transform.translate(0,53,1)
});
var pwdInput = new InputSurface({
classes:["pwdInput"],
size: [undefined, 45],
});
var pwdInputModifier = new StateModifier({
transform: Transform.translate(0,100,1)
});
loginBoxContainer.add(userInputModifier).add(userInput);
loginBoxContainer.add(pwdInputModifier).add(pwdInput);
var submit = new Surface({
content:["Submit"],
size:[100,30],
});
submit.on("click",function(){
document.dispatchEvent(new Event("showAccountsView"));
});
loginBoxContainer.add(submit);
}
});
I have to render different view on clicking ligin submit button. I have used dispatchEvent and addEventListener of Javascript to make communication between two files. I want to use famous events. I have tried various ways using setInputHandler, setOnputHandler, emit , addListener, pipebut could not able to do that as data and listener functions cannot calling. Please explain..
Inside LoginView, replace this code:
submit.on("click",function(){
document.dispatchEvent(new Event("showAccountsView"));
});
with:
submit.on("click",function(){
this._eventOutput.emit('showAccountsView', { data: someValue });
});
In ContentView, replace:
document.addEventListener("showAccountsView",function(){
var accoutsView = new AccountsView()
renderController.show(accoutsView);
}.bind(this));
with:
loginView.on('showAccountsView', function(data){
var accoutsView = new AccountsView()
renderController.show(accoutsView);
}.bind(this));

cc.sprite.create not working? cocos2d-html

I am new to Cocos2d-html5 v2.2.1 and I am trying to add a sprite (simple image) to the canvas. The code does add an image with the correct width and height but it is just black.
I cant seem to find any errors so I am kinda stuck.
Any help would be great. My code is below:
In main.js i load the resources:
applicationDidFinishLaunching:function () {
if(cc.RenderDoesnotSupport()){
//show Information to user
alert("Browser doesn't support WebGL");
return false;
}
// initialize director
var director = cc.Director.getInstance();
//cc.EGLView.getInstance()._adjustSizeToBrowser();
//cc.EGLView.getInstance()._resizeWithBrowserSize(true);
//cc.EGLView.getInstance().setDesignResolutionSize(600, 400, cc.RESOLUTION_POLICY.SHOW_ALL);
// set FPS. the default value is 1.0/60 if you don't call this
director.setAnimationInterval(1.0 / this.config['frameRate']);
//load resources
cc.LoaderScene.preload(g_resources, function () {
director.replaceScene(new this.startScene());
}, this);
return true;
}
g_resources is defined in resource.js:
var s_jet = "images/jet.png";
var s_character = "images/p1_front.png";
var g_resources = [
//image
{src:s_jet},
{src:s_character}];
spriteScene.js:
init:function () {
var selfPointer = this;
this._super();
var size = cc.Director.getInstance().getWinSize();
var lazyLayer = cc.LayerColor.create(new cc.Color4B(45, 50, 128, 255), 600, 600);
//var lazyLayer = cc.Layer.create();
lazyLayer.setAnchorPoint(new cc.Point(0.5,0.5));
var characterSprite = cc.Sprite.create("./images/p1_front.png");
lazyLayer.addChild(characterSprite, 0);
this.addChild(lazyLayer);
var rotateToA = cc.RotateTo.create(2, 0);
var scaleToA = cc.ScaleTo.create(2, 1, 1);
characterSprite.setPosition(new cc.Point(size.width/2,size.height/2));
I just dont understand why the sprite is just being drawn as a black box.
Edit: When I uncomment the line below from main.js; at first the image is still black but when I resize the browser, the image appears:-
cc.EGLView.getInstance().setDesignResolutionSize(600, 400, cc.RESOLUTION_POLICY.SHOW_ALL);
I dont know what this is implying.
Ok guys! I figured it out and I am pissed. Changed this line:
this.characterSprite.setPosition(new cc.Point(size.width/2,size.height/2));
to:
this.characterSprite.setPosition(cc.p(size.width/2, size.height/2));
Documentation/tutorials for cocos2d-html5 are outdated and this is getting frustrating.

"Cannot read property 'zindex' of undefined" Google maps

I'm trying to add custom controls to a Google map using the API. I already have two custom controls added and they work just fine. I tried to copy and paste the code for a third control (changing the relevant variables of course) and I keep getting the above error (in the title).
Chrome console and Firebug don't seem to point to a particular problem (it breaks inside the google maps api code). By progressively commented out lines, I've narrowed it down to this particular line:
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(churchControlDiv);
The full code for adding the control is as follows:
function ChurchControl(churchControlDiv, map) {
churchControlDiv.style.padding = '5px 0px';
var churchControlUI = document.createElement('DIV');
churchControlUI.style.backgroundColor = 'white';
churchControlUI.style.borderStyle = 'solid';
churchControlUI.style.borderWidth = '1px';
churchControlUI.style.borderColor = 'gray';
churchControlUI.style.boxShadow = 'rgba(0, 0, 0, 0.398438) 0px 2px 4px';
churchControlUI.style.cursor = 'pointer';
churchControlUI.style.textAlign = 'center';
churchControlUI.title = 'Click to see Churches';
churchControlDiv.appendChild(churchControlUI);
var churchControlText = document.createElement('DIV');
churchControlText.style.fontFamily = 'Arial,sans-serif';
churchControlText.style.fontSize = '13px';
churchControlText.style.padding = '1px 6px';
churchControlText.style.fontWeight = 'bold';
churchControlText.innerHTML = 'Churches<br>āđāļŠāļ”āļ‡āļˆāļģāļ™āļ§āļ™āļ„āļĢāļīāļŠāđ€āļ•āļĩāļĒāļ™';
churchControlUI.appendChild(churchControlText);
google.maps.event.addDomListener(churchControlUI, 'click', function() {
toggle(churches);
if (churchControlText.style.fontWeight == 'bold') {
churchControlText.style.fontWeight = 'normal';
} else {
churchControlText.style.fontWeight = 'bold';
}
});
google.maps.event.addDomListener(churchControlUI, 'mouseover', function() {
churchControlUI.style.backgroundColor = '#e8e8e8';
});
google.maps.event.addDomListener(churchControlUI, 'mouseout', function() {
churchControlUI.style.backgroundColor = 'white';
});
}
function initialize(){
map = new google.maps.Map(document.getElementById("map_canvas"), {
center: centerLatLng,
zoom: 7,
streetViewControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var churchControlDiv = document.createElement('DIV');
var churchControlDiv = new ChurchControl(churchControlDiv, map);
churchControlDiv.index = 3;
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(churchControlDiv);
}
Any ideas? Any reason why having 3 controls would be a problem?
I had the same error pop up on my console whilst following the tutorial for a different reason.
Rather than using default javascript DOM manipulation, I'd been using jQuery to create my elements, e.g.
var controlDiv = $('<div></div>');
var controlUI = $('<div class="alert alert-info"></div>');
controlDiv.append(controlUI);
var controlText = $('<div>Control text here</div>');
controlUI.append(controlText);
Doing this is fine, so long as you give the DOM node to the map (and not the jQuery element!) at the end, using controlUI[0] or controlUI.get(0), like this:
map.controls[google.maps.ControlPosition.TOP_RIGHT].push(controlDiv[0]);
See also:
How to get the native DOM element from a jQuery object - jQuery FAQ
I followed the tutorial, which is very close to your code.
This line near the end needs to change
var churchControlDiv = new ChurchControl(churchControlDiv, map);
Replace churchControlDiv with churchControl or another name because churchControlDiv should not be overwritten.
See here http://jsfiddle.net/FTjnE/2/
I marked my changes with //CHANGED an alert for the click, and new map center
The general underlying cause of this issue seems to be the element or its properties being removed or otherwise made not present. Maps API is trying to find the zIndex in the style property.
I had this issue in a Vue app custom component that interacted with the Maps API controls. We resolved it by exercising more caution in the teardown of the component.
Basically you need to ensure that you don't add a null element to the control, and don't make the element or its properties null before removing it, by doing something funky with say, v-if.

Categories