How do I create a sliding menu in appcelerator titanium? - menu

I want to make a menu that opens up from the left side, that has an image at the top, and then a few sections that redirects to a page each. I have searched online, some post a github link and when I go there I freeze. No idea what I am asupposed to do? Should I install something? Is that a sample code? Would appreciate any help.

You have to use the third party module for this, their are some in the market. I'll give example of the one I use, or else you can search for some other with key work Drawer in Titanium.
For Android : https://github.com/viezel/NappDrawer/tree/master/android
var homeScreen = Alloy.createController("homeScreen").getView();
var NappDrawerModule = require('dk.napp.drawer');
Alloy.Globals.drawer = NappDrawerModule.createDrawer({
fullscreen : false,
leftWindow : Alloy.createController('leftMenu').getView(),
centerWindow : homeScreen,
fading : 0.2, // 0-1
parallaxAmount : 0.2, //0-1
exitOnClose : true,
shadowWidth : "5dp",
leftDrawerWidth : "280dp",
animationMode : NappDrawerModule.ANIMATION_NONE,
closeDrawerGestureMode : NappDrawerModule.CLOSE_MODE_NONE,
openDrawerGestureMode : NappDrawerModule.OPEN_MODE_NONE,
orientationModes : [Ti.UI.PORTRAIT, Ti.UI.UPSIDE_PORTRAIT]
});
Alloy.Globals.drawer.addEventListener("didChangeOffset", function(e) {
//Ti.API.info("didChangeOffset: " + e.offset);
});
Alloy.Globals.drawer.addEventListener("android:back", function(e) {
Ti.API.info('currentWindow : ' + Alloy.Globals.currentWindow);
if (Alloy.Globals.currentWindow != null) {
return;
}
});
Alloy.Globals.drawer.addEventListener("windowDidOpen", function(e) {
if (e.window == NappDrawerModule.LEFT_WINDOW) {
Ti.API.info("windowDidOpen - LEFT DRAWER");
} else if (e.window == NappDrawerModule.RIGHT_WINDOW) {
Ti.API.info("windowDidOpen - RIGHT DRAWER");
}
});
Alloy.Globals.drawer.addEventListener("open", function(e) {
Ti.API.info('Drawer Open');
});
Alloy.Globals.drawer.addEventListener("windowDidClose", function(e) {
Ti.API.info("windowDidClose");
});
// lets open it
Alloy.Globals.drawer.open();
For iOS : https://github.com/viezel/NappSlideMenu
Alloy.Globals.SlideWindow = Alloy.createController("leftMenu");
var homeWindow = Alloy.createController("homeScreen").getView();
var NappSlideMenu = require('dk.napp.slidemenu');
var window = NappSlideMenu.createSlideMenuWindow({
centerWindow : homeWindow,
leftWindow : Alloy.Globals.SlideWindow.getView(),
leftLedge : (Alloy.Globals.iPad) ? 170 : 70,
parallaxAmount : 0.2,
});
Alloy.Globals.window = window;
window.addEventListener("viewWillOpen", function(e) {
});
window.addEventListener("viewWillClose", function(e) {
});
exports.openLeft = function() {
window.toggleLeftView();
};
exports.openRight = function() {
window.toggleRightView();
};
window.open();
Note : leftMenu and homeScreen for android is a View, but for iOS it is a Window.
Good Luck, Cheers

Related

Can't manage object alignments selection with FabricJs 2

I used to manage object alignments selection on FabricJS with getActiveGroup as below :
canvas.on("selection:created", function(e) {
var activeObj = canvas.getActiveObject();
console.log('e.target.type', e.target.type);
if(activeObj.type === "group") {
console.log("Group created");
var groupWidth = e.target.getWidth();
var groupHeight = e.target.getHeight();
e.target.forEachObject(function(obj) {
var itemWidth = obj.getBoundingRect().width;
var itemHeight = obj.getBoundingRect().height;
$('#objAlignLeft').click(function() {
obj.set({
left: -(groupWidth / 2),
originX: 'left'
});
obj.setCoords();
canvas.renderAll();
});
...
}
});
more detailed here
But now that I use FabricJS 2 and that getActiveObject() has been removed, I don't know what to do. I read on the doc that we could use getActiveObjects(), but it does nothing.
Please how can I reproduce the action of this code with FabricJS 2 (where getActiveGroup isn't supported anymore) ?
Selections of more than one object have the type activeSelection. The group type is only used when you purposefully group multiple objects using new fabric.Group([ obj1, obj2]
When you create a multi-selection using the shift-key as opposed to drawing a selection box, you'll trigger the selection:created event only on the first object selected, while objects added to the selection will trigger the selection:updated event. By calling your alignment code from both the selection:created and selection:updated events you'll make sure that your code is executed every time a multi-selection is created.
Also, you can use getScaledWidth() and getScaledHeight() to get scaled dimensions, or just .width and .height if you just want the unscaled width/height values. Good luck!
canvas.on({
'selection:updated': function() {
manageSelection();
},
'selection:created': function() {
manageSelection();
}
});
function manageSelection() {
var activeObj = canvas.getActiveObject();
console.log('activeObj.type', activeObj.type);
if (activeObj.type === "activeSelection") {
console.log("Group created");
var groupWidth = activeObj.getScaledWidth();
var groupHeight = activeObj.getScaledHeight();
activeObj.forEachObject(function(obj) {
var itemWidth = obj.getBoundingRect().width;
var itemHeight = obj.getBoundingRect().height;
console.log(itemWidth);
$('#objAlignLeft').click(function() {
obj.set({
left: -(groupWidth / 2),
originX: 'left'
});
obj.setCoords();
canvas.renderAll();
});
});
}
}

Using Stored Data to Define Sub Menu Entries

My extension should use the user's options to build submenus under the main extension context menu entry. The options are stored in a table, where each line is defining a submenu. The whole table is stored as a json string in chrome.local.storage with the key jsondata.
The manifest is:
"background": {
"persistent": true,
"scripts": [ "js/storage.js", "js/backgroundlib.js", "js/background.js" ]
},
...
"permissions": [ "storage", "contextMenus", "http://*/*", "https://*/*", "tabs", "clipboardRead", "clipboardWrite" ],
...
In the background script, I'm trying to get the data using:
window.addEventListener('load', function () {
var key = 'jsondata';
storage.area.get(key, function (items){
console.log(items[key]);
build_submenu(items[key]);});
});
function build_submenu(json) {
console.log("build_submenu: " + json);
}
and build_submenu should then call multiple chrome.contextMenus.create({... }) to add the submenus.
For now, I can't get build_submenu being called. Am I trying to do something that is not possible or am I just missing something obvious?
Thanks, F.
Replace storage.area.get with chrome.storage.local.get.
Another suggestion would be removing the outer window.onload listener, since you are using background scripts and window.onload makes no sense.
OK, I finally got this, that works:
manifest.json
"background": {
"persistent": false,
"scripts": [ "js/storage.js", "js/backgroundlib.js", "js/background.js" ]
},
in background.js, The context menu is build in the callback function when reading from storage. This reading is called when onInstalled is fired.
I use a global var that is saved onSuspend et read again onStartup. and that associate the submenu id and the corresponding row from the user's option. The onClick listener test if the global variable is defined. If not it is read again from storage.
var regex = new Object();
chrome.runtime.onInstalled.addListener( function () {
console.log("onInstalled called");
var key = 'jsondata';
storage.area.get(key, function (items){ get_jsondata(items[key]);});
function get_jsondata(value){
var data = JSON.parse(value);
var fcb =[ {fcb_context: "fcb_copy", title:"Copy filtered", context: ["selection", "link"]}, {fcb_context:"fcb_paste", context:["editable"], title:"Paste filtered"}];
for (var i=0; i<fcb.length; i++) {
var menu = fcb[i];
chrome.contextMenus.create({
//title: "Look up: %s",
title: menu.title,
id: menu.fcb_context,
contexts: menu.context,
});
var last = data.length;
//var sel = info.selectionText;
for (var j=0; j<last; j++){
chrome.contextMenus.create({
title: data[j].name,
contexts: menu.context,
id: menu.fcb_context + "_" + j,
parentId: menu.fcb_context,
//onclick: function(info, tab){ run_cmd( data[j].regex, info, menu.fcb_context ); }
});
regex[ menu.fcb_context + "_" + j] = data[j];
//console.log(regex[menu.fcb_context + "_" + j]);
}// for j
} // for i
}//get_jsondata
}); //add listener
chrome.contextMenus.onClicked.addListener(function(info, tabs){
var id = info.menuItemId;
if (typeof regex === "undefined" ){
storage.area.get("regex", function(items){
regex = JSON.parse(items["regex"]);
console.log("get " + items["regex"] + " from storage");
run_cmd( regex, info );
});
} else {
console.log("regex was defined... " + JSON.stringify(regex));
run_cmd( regex, info );
}
});
chrome.runtime.onSuspend.addListener(function() {
// Do some simple clean-up tasks.
console.log("onSuspend called saving " + JSON.stringify(regex));
storage.area.set({ "regex" : JSON.stringify(regex)}, function(){console.log("regex saved");} );
});
chrome.runtime.onStartup.addListener(function() {
console.log("onStartup called");
storage.area.get("regex", function(items){
regex = JSON.parse(items["regex"]);
console.log("get " + items["regex"] + " from storage");
});
});
function getSelectedText(info){
var sel = info.selectionText;
chrome.tabs.executeScript(null, {file:"js/script.js"});
}
function pasteFilteredText(info){
chrome.tabs.executeScript(null, {file:"js/script.js"});
}
function run_cmd(regex, info){
var id = info.menuItemId;
var data = regex[id];
var sel = info.selectionText;
var fcb_context = info.parentMenuItemId;
//console.log("run_cmd regex " + data.regex + " sel " + (sel ? sel : ""));
alert("run_cmd regex " + data.regex + " sel " + (sel ? sel : "") + " fcb_context: " + fcb_context);
}
Thanks for pointing me what is superfluous or missing.

Titanium mobile - Common JS. Objects values are lost when lauching a fireEvent

I'm dev an app into titanium mobile in javascript.
The dynamic menu insert each new object(id,text,...., page) into a loop for (var x in tab).
with thoses items, specifics views are made.
var items = [];
var menuIconsItem = require('view/module/menuIconsItem');
for(var i in itemTab) {
var page = itemTab[i].page;
items[i] = new menuIconsItem(itemTab[i]);
menuFirstLine.add(items[i]);
(function(itemsEvent) {
itemsEvent.addEventListener('click', function() {
Ti.App.fireEvent('test' +i, {
id : i
});
})
})(items[i]);
}
on the other controller side, i only get the last id reference.
If i = 0 to 5, i only get the last reference. The rest is undefined.
How could i do please?
First you have to set id for your menuIconsItem, I am taking button an an example here.
items[i] = Titanium.UI.createButton({
id:"button_"+i,
_index: i
})
Then do this:
(function(itemsEvent) {
itemsEvent.addEventListener('click', function(e) {
alert(e.source.id);
})
})(items[i]);

Titanium: Error trying to play a sound when tapping a row in a table?

I'm making a rather simple app that displays a table where each row contains an English word and the corresponding Polish word. When a row is pressed it should play a sound clip of the word expressed. However, I cannot make it work, even though I've tried to troubleshoot it with all that Google has to offer. Would appreciate if someone could point out the flaw...
var win = Titanium.UI.currentWindow;
var data =[];
var CustomData = [
{ file:'001', english:'Do you?', polish:'Czy masz?', fav:false },
{ file:'002', english:'How long?', polish:'Jak d?ugo?', fav:false },
{ file:'003', english:'Is it?', polish:'Czy?', fav:false },
];
var section = Ti.UI.createTableViewSection();
data.push(section);
for (var i=0; i<CustomData.length; i++) {
var row = Ti.UI.createTableViewRow({layout : 'vertical', height:'auto'});
var item = Ti.UI.createLabel({
color:'#000',
text:CustomData[i].english,
font:{fontSize:12, fontWeight:'bold'},
top:3,
left:10,
right:30,
height:'auto'
});
row.add(item);
var cost = Ti.UI.createLabel({
color:'#444',
text:CustomData[i].polish,
font:{fontSize:12},
top:0,
left:15,
right:30,
bottom:5,
height:'auto'
});
row.add(cost);
row.filter = CustomData[i].english;
section.add(row);
};
var tableview = Titanium.UI.createTableView({
data:data, search:search, searchHidden:false, filterAttribute: 'filter' });
win.add(tableview);
tableview.addEventListener('click', function(e)
{
var sound = Titanium.Media.createSound();
sound.url = '../sound/' + e.rowData.file + '.mp3';
sound.play();
if (e.rowData.test)
{
var win = Titanium.UI.createWindow({
url:e.rowData.test,
title:e.rowData.title
});
Titanium.UI.currentTab.open(win,{animated:true});
}
});
Just a shot in the dark, but are you sure you can set the URL after the sound object is created? Have you tried:
Titanium.Media.createSound({url:'../sound/' + e.rowData.file + '.mp3'});
Aside from that, are you sure the relative URL is evaluated from where you think? Maybe try it with an absolute URL just to be sure.

YUI 2 in 3 locally

I am new to YUI and I want to load YUI 2 in 3 locally, not from CDN. I have pasted both 2 and 3 in same directory named Scripts. I am pasting my code below:
<script type="text/javascript" src="/Scripts/build-yui3/yui/yui-min.js"></script>
function showError(panelId) {
YUI({
groups: {
yui2: {
base: '/build-yui2/',
// If you have a combo service, you can configure that as well
// combine: true,
// comboBase: 'http://myserver.com/combo?',
// root: '/2in3/build/',
patterns: {
'yui2-': {
configFn: function(me) {
if(/-skin|reset|fonts|grids|base/.test(me.name)) {
me.type = 'css';
me.path = me.path.replace(/\.js/, '.css');
me.path = me.path.replace(/\/yui2-skin/, '/assets/skins/sam/yui2-skin');
}
}
}
}
}
}
}).use('dd-drag', 'yui2-container', function (Y) {
Y.one("#" + panelId).setStyle('display', null);
var YAHOO = Y.YUI2;
var config = {
close: true,
width: "300px",
fixedcenter: true,
modal: true
};
panel = new YAHOO.widget.Panel(panelId, config);
var keylistener = new YAHOO.util.KeyListener(
document, {
keys: 27
}, {
fn: panel.hide,
scope: panel,
correctScope: true
});
panel.cfg.queueProperty("keylisteners", keylistener);
panel.render();
});
}
But this is not working. Throwing error: "YAHOO is undefined". Please help. Thanks..
Add an onFailure: function (error) {} method to your YUI3 config object. The error it gives you will tell you which files didn't load properly. I'm guessing the base property needs to be a full path not a relative path. I've never used patterns so I'm not sure how to debug it.

Resources