Alloy and require external JS - titanium

Right now I have a function in my alloy.js file that is a global.
Alloy.Globals.indicator = function(parent)
{
var view = Ti.UI.createView({
width: '100%',
height: '100%',
backgroundColor: '#000',
opacity: 0.6,
visible: false
});
function osIndicatorStyle()
{
style = Ti.UI.iPhone.ActivityIndicatorStyle.PLAIN;
if ('iPhone OS' !== Ti.Platform.name) style = Ti.UI.ActivityIndicatorStyle.DARK;
return style;
};
var activityIndicator = Ti.UI.createActivityIndicator({
style: osIndicatorStyle(),
height: Ti.UI.FILL,
width: 100
});
view.add(activityIndicator);
parent.add(view);
function openIndicator()
{
view.visible = true;
activityIndicator.show();
}
view.openIndicator = openIndicator;
function closeIndicator()
{
activityIndicator.hide();
view.visible = false;
}
view.closeIndicator = closeIndicator;
return view;
};
I'd rather not have this large function as a global and instead import it to the files I need using require.
I have searched and cannot figure out first, where to place this file and second how to actually "require" it.
All this simply does is create a view that acts as a modal view with a activity indicator. The function also includes two function to show and hide it.

Make a folder called "lib" inside the "app" folder.
Inside this folder, make a file called whatever you like e.g. functions.js:
var functionName = function(){
//your function code here
}
exports.functionName = functionName;
In your controller:
var functions = require('functions');
functions.functionName();
You might want to also look at Widgets which are re-usable components complete with view/controller/styles as I think this would fit your requirement slightly better.
Link to docs

Related

How can I pass the current theme of the app into StyleSheet.create()?

Due to various limitations, I cannot store the current theme in props. I have to use a custom props that I cannot modify at the moment. I have been able to get around this by using React Context to store the current theme.
I have a class called pageStyle. In it, I have a pageContainer that I'd like to be able to set backgroundColor either to dark or light values.
I am able to get the current theme in a separate class R by using this.context.theme. R is also where I am rendering the FlatList object and passing style={pageStyle.pageContainer}.
I could create two separate pageContainers, called pageContainerDark and pageContainerLight, and have the correct respective backgroundColors for both. However, this feels messy to me. This would also require having a method for each style page to determine which pageContainer to use and is not scalable whatsoever. I have also tried using a global variable but was having some issues with this.
Is there a cleaner way to set pageContainer's backgroundColor based on the current theme?
I have attached the pageStyle.ts file below.
//pageStyle.ts
import { StyleSheet} from 'react-native';
const pageStyles = StyleSheet.create({
pageContainer: {
flex: 1,
backgroundColor: "#232323"
},
// pageContainerDark: {
// flex: 1,
// backgroundColor: "#232323"
// },
// pageContainerLight: {
// flex: 1,
// backgroundColor: "#FFFFFF"
// },
pageContentContainer: {
paddingBottom: 0
}
});
// export function getPageContainerFromPageStyles(theme: string) {
// if (theme == 'light') {
// return pageStyle.pageContainerForLightTheme
// } else {
// return pageStyle.pageContainerForDarkTheme
// }
// }
export { pageStyle };

ScrollMagic - set a variable scene

I have a page with multiple similar sections with the class ".imgPanel" that I would like to apply the same animation to each section every time the page scrolls into view.
I don't want to create a new scene for each animation as they are all the same. I know there is a way to create a variable scene (i hope that is the correct terminology), and I am hoping someone can help.
Does anyone know how I would adjust the code below to make that happen. I am sure if I get one example of it with my code below I will be able to understand and use this technique again.
Thanks in advance. Adam.
function scrollMagic() {
if (!Modernizr.touch) {
var controller = new ScrollMagic.Controller({
duration: "200%",
});
var panelAnim = new TimelineMax();
panelAnim
.from($('.imgPanel'), 1.4, {
y: '-50px',
autoAlpha: 0,
ease: Power1.easeOut
}, '-=0.2')
var introScene = new ScrollMagic.Scene({
duration: "100%",
})
.setTween(panelAnim)
.addTo(controller);
}
}
I figured it out after watching Ihatetomatoes video
function scrollMagic() {
if (!Modernizr.touch) {
var controller = new ScrollMagic.Controller({
duration: "100%",
});
$('.imgPanel').each(function(){
var tween = TweenMax.from($(this), 1.4, { y: '-50px', autoAlpha: 0,
ease: Power1.easeOut }, '-=0.2');
var scene = new ScrollMagic.Scene ({
duration: "100%",
offset: -300, // offset trigger position by 100px
triggerElement: this
})
.setTween(tween)
.addTo(controller);
});
}
}

Changing layout onOrientationChange

Is there a currently supported way to change layouts according to device orientation?
The following code returns this error:
onOrientationChange: function () {
this.remove();
this.setLayout( Ext.Viewport.getOrientation() == 'landscape' ?
{ type: 'hbox', pack: 'center', align: 'stretch' } : { type: 'vbox', align: 'stretch', pack: 'center' } );
},
"Replacing a layout after one has already been initialized is not currently supported."
Please any one give me suggestion.
Check out the code for the Sencha Meetcha app on GitHub.
What you may have to do, since replacing a layout is unsupported, is use some CSS tricks and when the orientation changes, remove the old cls and apply the new one.
I haven't tried this myself but the demo app seems to do layout changes very well.
Code snippet included
orientationCls: ['home-portrait', 'home-landscape'],
doOrientation: function() {
var me = this,
orientation = Ext.Viewport.getOrientation(),
letter = orientation.charAt(0),
items = this.getItems().getRange(),
i = 0,
ln = items.length,
item, el, top, left;
me.element.removeCls(me.orientationCls);
me.element.addCls('home-' + orientation);
for (; i < ln; i++) {
item = items[i];
top = item.initialConfig[letter + 'top'];
left = item.initialConfig[letter + 'left'];
el = item.element;
if (el) {
el.setBox({
top: top,
left: left
});
}
}
}
Hope this helps

Create custom picker control

See screenshot of custom picker:
I know there isn't a way to style the picker control in Titanium. This picker only needs to work on iOS (iPad only). I was thinking I could hack the TableView control to use instead of the picker to achieve the style desired. Is that reasonable? How would I snap the TableViewRows so one is always in the center like seen in typical picker controls?
that's a tough one i would say you just only need views and labels and the swipe event (you can recognize if some one swipe up and down ) and just changes the labels. you can do this with a callback function i hope this code will help you (we have created a custom picker with this code)
using alloy
XML
<View id="numOfIntrusionsPickerContainer" class="compositeWrapperPicker noMargins" >
<View id="numOfIntrusionsButtonContainer" class="horizontalWrapper"></View>
CSS
".compositeWrapperPicker" : {
height: Ti.UI.SIZE,
layout: "composite",
width:Ti.UI.SIZE
},
".horizontalWrapper" : {
width: Ti.UI.SIZE,
height: Ti.UI.SIZE,
layout: "horizontal"
},
JS
// INSTANTIATION
var args = arguments[0] || {};
var widthValue = 120;
var pickerEnabled = true;
if(args.width != null){
widthValue = args.width;
}
if(args.isEnabled != null){
pickerEnabled = args.isEnabled;
}
// STYLING
// ADDITIONS
// pressed arg can be: true,false,null. false & null are equal
// true = 'yes' is Pressed at creation, false/null = 'no' is pressed
var btn_main = Ti.UI.createButton({
top: 5,
bottom: 0,
left:0,
right:5,
height: 45,
enabled: pickerEnabled,
width: widthValue,
borderRadius: 5,
backgroundImage: "/images/bttn_gray_flex.png",
backgroundSelectedImage : "/images/bttn_gray_press_flex.png",
backgroundFocusedImage : "/images/bttn_gray_press_flex.png"
});
var picker_divider = Ti.UI.createImageView({
right: 43,
bottom:2,
touchEnable:false,
focusable:false,
image: "/images/Divider_picker.png"
});
var picker_arrows = Ti.UI.createImageView({
right: 16,
top: 17,
touchEnabled: false,
focusable: false,
image: "/images/bttn_selector_arrow.png"
});
$.pickerContainer.add(btn_main);
$.pickerContainer.add(picker_divider);
$.pickerContainer.add(picker_arrows);
// CODE
// LISTENERS
if(args.callBack != null){
btn_main.addEventListener("click",function(_event){
args.callBack(_event);
});
}

Extending dojo.gfx.Group with default instanciated shapes

I'm attempting to create some simple UI components with dojo.gfx. I've managed to extend dojo.gfx.Group, but am out of my depth getting any of the default shapes drawn to the surface. Inspecting the rendered SVG in Firebug, there's rightfully a node but no rect.
The simplified class looks like this:
dojo.provide("gfxui.SimpleButton");
dojo.require("dojox.gfx.shape");//-¿ needed?
dojo.require("dojox.gfx.svg");
dojo.require("dojox.gfx._base");
dojo.declare("gfxui.SimpleButton", dojox.gfx.Group, {
constructor: function(){
this.draw();
},
draw:function(){
var bg = this.createRect(this.rect_props);
//var bg = this.createObject(dojox.gfx.Rect);
}
}
gfxui.SimpleButton.nodeType = dojox.gfx.Group.nodeType;
dojo.extend(dojox.gfx.Surface, {
createButton: function(){
var button = this.createObject(gfxui.SimpleButton, null, true);
this.add(button);
return button;
}
});
And the javascript in the HTML looks like this:
dojo.require("dojox.gfx");
dojo.require("gfxui.SimpleButton");
function init(){
var g = dojox.gfx;
var surface = dojox.gfx.createSurface(dojo.byId("gfx_holder"), 800, 280, "#eee");
var button = container.createButton();
};
dojo.addOnLoad(init);
I prefer a simple augmentation technique. Below is the content of a script tag:
// let's include gfx (renderer will be selected dynamically)
dojo.require("dojox.gfx");
// useful short names
var d = dojo, g = dojox.gfx;
// our creator function
function createButton(color){
// let's create our main shape: group
var group = this.createGroup();
// add custom properties, if any
group._rect = group.createRect().
setShape({x: 5, y: 5, width: 100, height: 30}).
setStroke("black").
setFill(color);
return group;
}
// we want it to be available on groups and surfaces
d.extend(g.Surface, {createButton: createButton});
d.extend(g.Group, {createButton: createButton});
// let's test the result
dojo.addOnLoad(function(){
var s = g.createSurface(dojo.byId("surface"), 500, 400),
b = s.createButton("red");
});
The example above assumes that there is a <div> called "surface".
The augmentation technique works for any renderer regardless its implementation, and uses only published APIs.