I have buttons I want to center horizontally in a view. There are three, and all I can seem to get is:
[button1-button2-button3------------------------------]
What I really want is
[--------button1--------button2--------button3--------]
These buttons are dynamic widths too. The amount of buttons will change, some views have 1, others have 2 or 3. Depending on an action, the number of buttons can change. I need this support both iOS and android.
Try splitting the screen into n different columns using percentage layout. Then add your buttons to their respective invisible container.
var n = // Your number of buttons horizontal
var container = Ti.UI.createView({width : "100%", layout: "horizontal" });
for(var i=0;i<n;i++) {
var column = Ti.UI.createView({
width : (100/n)+"%",
});
// Create your button here
// .....
// .....
// Now add it to the column
column.add(yourNthButton);
// Now add the column to the container
container.add(column);
}
How about wrapping your buttons in a view with layout set to 'horizontal'?
var wrapperView = Ti.UI.createView({
layout : 'horizontal',
...
});
// In a view with horizontal layout,
// the positioning is relative to the preceding element
var buttonOne = Ti.UI.createButton({
right : 10,
...
});
wrapperView.add(buttonOne);
Untested, but give it a try!
UPDATE
Ok, the above code alone won't do what you wanted. I wrote a more complete example here.
Seems a bit clumsy, so if someone has a better solution, please let us know!
// Create our window
var win = Ti.UI.createWindow();
// Our wrapper view
var wrapperView = Ti.UI.createView({
width : Ti.UI.FILL,
height : 40,
top : 0,
layout : 'horizontal',
});
// Add some test buttons to our wrapper
for(var i=0; i<3; i++) {
wrapperView.add(Ti.UI.createButton({
title : 'Test ' + i,
height : 30,
}));
}
// Add wrapperView to our window and open it
win.add(wrapperView);
win.open();
// Wait until "size" becomes available
win.addEventListener('postlayout', distributeButtons);
// Distribute buttons evenly
function distributeButtons() {
if(wrapperView.children) {
// Get the width of the wrapper view
var wrapperWidth = wrapperView.size.width;
var buttonWidths = 0;
var buttonSpacer;
var childrenLength = wrapperView.children.length;
// Get the button sizes
for(var i=0; i<childrenLength; i++) {
buttonWidths += wrapperView.children[i].size.width;
};
// Calculate the spaces between the buttons
buttonSpacer = (wrapperWidth - buttonWidths) / (childrenLength + 2);
// Set the buttons left value
for(var i=0; i<childrenLength; i++) {
wrapperView.children[i].left = buttonSpacer;
};
}
}
If you can put a toolbar, you can use the "flexspace" button, which will create a space necessary to fill the gap between other buttons. Here's the syntax from simple toolbar example in titanium docs:
var send = Titanium.UI.createButton({
title: 'Send',
style: Titanium.UI.iPhone.SystemButtonStyle.DONE,
});
var camera = Titanium.UI.createButton({
systemButton: Titanium.UI.iPhone.SystemButton.CAMERA,
});
var cancel = Titanium.UI.createButton({
systemButton: Titanium.UI.iPhone.SystemButton.CANCEL
});
flexSpace = Titanium.UI.createButton({
systemButton:Titanium.UI.iPhone.SystemButton.FLEXIBLE_SPACE
});
var toolbar = Titanium.UI.iOS.createToolbar({
items:[send, flexSpace, camera, flexSpace, cancel],
bottom:0,
borderTop:true,
borderBottom:false
});
win.add(toolbar)
try this
var yourView = Ti.UI.createView({ layout:"horizontal"});
var buttonsHolder = Ti.UI.createView({ width:"100%" });
// this view will hold the buttons
var button1 = Ti.UI.createButton({title:"button1 , left:0"}); // the left button
var button2 = Ti.UI.createButton({title:"button2"}); // the middle button
var button3 = Ti.UI.createButton({title:"button3",right:0}); // the right button
buttonsHolder(button1);
buttonsHolder(button2);
buttonsHolder(button3);
yourView.add(buttonsHolder);
Hieyy bro
If you are want achieve this using titanium alloy in xml. in that case you can use %.
Container ------------width 100%-----layout horizontal---------
first child--------left 10%------- width 20%
second child--------left 10%------- width 20%
third child--------left 10%------- width 20%-----right 10%
if you don't get your answer please let me know
Spartacus Thanks:)
If using Alloy, then I recommend using percentages to control width and position. Here's an example that centers three small images below a larger image, also centered:
<TableViewRow selectionStyle="Ti.UI.iPhone.TableViewCellSelectionStyle.NONE" backgroundColor="white" layout="vertical">
<ImageView id="detailsFeaturedImage" top="10"/>
<View height="60">
<View layout="horizontal">
<View left="25%" width="10%"><ImageView image="images/thumb-up-7#2x.png" onClick="thumb_up" /></View>
<View left="10%" width="10%"><ImageView image="images/thumb-down-7#2x.png" onClick="thumb_down"/></View>
<View left="10%" width="10%"><ImageView image="images/flag-7#2x.png" onClick="flag_for_review"/></View>
</View>
</View>
</TableViewRow>
Related
I have used this solution to get a toggle legend for a composite line chart and it works perfectly fine.
However, after i added a range chart to this composite chart, the deselected legend loses its translucence and becomes normal.
How can i keep the deselected legend object in faded state while filtering?
Here are screenshots for reference:
Before filter:
After filter:
This is the code I'm using for charts:
multiLineChart
.width(1000)
.height(300)
.transitionDuration(1000)
.margins({top: 30, right: 50, bottom: 40, left: 40})
.x(d3.time.scale().domain([startDate,endDate]))
.yAxisLabel("Data (Scaled)")
.xAxisLabel("Date And Time")
.rangeChart(timeSlider)
.legend(dc.legend().x(800).y(20).itemHeight(13).gap(5))
.renderHorizontalGridLines(true)
//.dimension(DateDim)
.compose([
dc.lineChart(multiLineChart)
.dimension(DateDim)
.colors('red')
.group(Line1Grp, 'Line1'),
dc.lineChart(multiLineChart)
.dimension(DateDim)
.colors('blue')
.group(Line2Grp, 'Line2')
])
.brushOn(false)
.on('pretransition.hideshow', function(chart) {
chart.selectAll('g.dc-legend .dc-legend-item')
.on('click.hideshow', function(d, i) {
var subchart = chart.select('g.sub._' + i);
var visible = subchart.style('visibility') !== 'hidden';
subchart.style('visibility', function() {
return visible ? 'hidden' : 'visible';
});
d3.select(this).style('opacity', visible ? 0.2 : 1);
});
});
//.xAxis().tickFormat(d3.time.format("%b %d %H:%M"));
timeSlider
.width(1000)
.height(50)
.margins({top: 0, right: 50, bottom: 20, left: 40})
.dimension(DateDim)
.group(Line1Grp)
.x(d3.time.scale().domain([startDate, endDate]))
.on("filtered", function (chart) {
dc.events.trigger(function () {
multiLineChart.focus(chart.filter());
dc.redrawAll(chart.chartGroup());
});
})
.xAxis().tickFormat(d3.time.format("%b %d"));
Here is a fiddle for the same.
Any help is appreciated.
Thanks for pointing this out - there was a bad practice in my earlier answer, and I went back and corrected it.
It's always better style, and more robust, to separate event handling and drawing, and always draw everything based on the data, not some event that is in flight.
If you follow these practices, then the code looks more like this:
function drawLegendToggles(chart) {
chart.selectAll('g.dc-legend .dc-legend-item')
.style('opacity', function(d, i) {
var subchart = chart.select('g.sub._' + i);
var visible = subchart.style('visibility') !== 'hidden';
return visible ? 1 : 0.2;
});
}
function legendToggle(chart) {
chart.selectAll('g.dc-legend .dc-legend-item')
.on('click.hideshow', function(d, i) {
var subchart = chart.select('g.sub._' + i);
var visible = subchart.style('visibility') !== 'hidden';
subchart.style('visibility', function() {
return visible ? 'hidden' : 'visible';
});
drawLegendToggles(chart);
})
drawLegendToggles(chart);
}
multiLineChart
.on('pretransition.hideshow', legendToggle);
Now, whenever we redraw the composite chart and its legend - no matter what the cause - all of the items in the legend will be updated based on whether the corresponding child chart has been hidden.
And the event handler is only concerned with hiding and showing charts, not drawing.
Fork of your fiddle.
I want to create an "image comparison slider" for contents. Example:
Codepen Link
// Call & init
$(document).ready(function(){
$('.ba-slider').each(function(){
var cur = $(this);
// Adjust the slider
var width = cur.width()+'px';
cur.find('.resize img').css('width', width);
// Bind dragging events
drags(cur.find('.handle'), cur.find('.resize'), cur);
});
});
// Update sliders on resize.
// Because we all do this: i.imgur.com/YkbaV.gif
$(window).resize(function(){
$('.ba-slider').each(function(){
var cur = $(this);
var width = cur.width()+'px';
cur.find('.resize img').css('width', width);
});
});
function drags(dragElement, resizeElement, container) {
// Initialize the dragging event on mousedown.
dragElement.on('mousedown touchstart', function(e) {
dragElement.addClass('draggable');
resizeElement.addClass('resizable');
// Check if it's a mouse or touch event and pass along the correct value
var startX = (e.pageX) ? e.pageX : e.originalEvent.touches[0].pageX;
// Get the initial position
var dragWidth = dragElement.outerWidth(),
posX = dragElement.offset().left + dragWidth - startX,
containerOffset = container.offset().left,
containerWidth = container.outerWidth();
// Set limits
minLeft = containerOffset + 10;
maxLeft = containerOffset + containerWidth - dragWidth - 10;
// Calculate the dragging distance on mousemove.
dragElement.parents().on("mousemove touchmove", function(e) {
// Check if it's a mouse or touch event and pass along the correct value
var moveX = (e.pageX) ? e.pageX : e.originalEvent.touches[0].pageX;
leftValue = moveX + posX - dragWidth;
// Prevent going off limits
if ( leftValue < minLeft) {
leftValue = minLeft;
} else if (leftValue > maxLeft) {
leftValue = maxLeft;
}
// Translate the handle's left value to masked divs width.
widthValue = (leftValue + dragWidth/2 - containerOffset)*100/containerWidth+'%';
// Set the new values for the slider and the handle.
// Bind mouseup events to stop dragging.
$('.draggable').css('left', widthValue).on('mouseup touchend touchcancel', function () {
$(this).removeClass('draggable');
resizeElement.removeClass('resizable');
});
$('.resizable').css('width', widthValue);
}).on('mouseup touchend touchcancel', function(){
dragElement.removeClass('draggable');
resizeElement.removeClass('resizable');
});
e.preventDefault();
}).on('mouseup touchend touchcancel', function(e){
dragElement.removeClass('draggable');
resizeElement.removeClass('resizable');
});
}
Same as above, but instead of images, I want to create content divs with text, images, html. Like 2 pages with a slider to compare both.
Your comparison script utilizes a resizing a div, so there's no way (that I know of) to achieve this without some considerable trickery (or how to achieve the same effect without resizing).
The only way to prevent the text from automatically wrapping is by using ...
white-space: nowrap;
... but that would just result in one continuous line of text.
Breaks <br> could be inserted from there, but that would just look awful and negate any resizing.
Personally, my approach would be to render the text within a canvas element first (https://www.w3schools.com/graphics/canvas_text.asp).
Since a canvas is treated nearly identical to that of an image, it wouldn't require any changes to the existing comparison script.
I have a Google map driven by Advanced Custom Fields. I have created an iconType to dictate which icon is used as the marker depending on the custom field.
My marker images are 80px square but I want to force them to 40px square for retina reasons. I have tried lots of variations of code I've found via google etc but nothing works and the size gets ignored showing my markers at the larger 80px. My guess is because I have the 2 icons depending on iconType?
Can anyone help me force the size of these markers to 40px square please...
function add_marker( $marker, map ) {
// var
var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng'));
var iconType = $marker.attr('data-icon');
var iconBase = '<?php echo get_template_directory_uri(); ?>/assets/';
var size = new google.maps.Size(40, 40);
if (iconType === 'Costa') {
iconName = 'costa#2x.png';
} else {
iconName = 'starbucks#2x.png';
}
// create marker
var marker = new google.maps.Marker({
position : latlng,
map : map,
clickable: false,
animation: google.maps.Animation.DROP,
icon: iconBase + iconName,
});
// add to array
map.markers.push( marker );
// if marker contains HTML, add it to an infoWindow
if( $marker.html() )
{
// create info window
var infowindow = new google.maps.InfoWindow({
content : $marker.html()
});
}
}
I did something like this recently, and I believe you'll need to use the new Icon object to specify your custom Icon properties, and use the size and scaledSize properties. I fixed my issues following this guide:
How to add retina ready pin marker to your Google maps?
I have an image slider that is controlled by text navigation. The text is highlighted orange when it's relative slide is current in the gallery. I would like the other text to have an inactive state with a black background but cannot get this to work!
(In case that didn't make much sense! Basically, I want background-color orange when current, background-color black when inactive.) THANKS
$(document).ready(function(){
$('.slider').each(function(e){
if(e == 0){
$(this).addClass('current');
}
$(this).attr('id', 'handle' + e);
})
$('.tabs li').each(function(e){
if(e == 0){
$(this).addClass('current'); //adds class current to 1st li
}
$(this).wrapInner('<a class="title"></a>'); //wraps list items in anchor tag
$(this).children('a').attr('href', '#handle' + e);//adds href to the anchors
t = $(this).children('a').text();
$('#handle' + e).append('<h2>' + t + '</h2>'); //adds h2 and text to big images
})
$('.tabs li a').click(function(){
c = $(this).attr('href');
if($(c).hasClass('current')){
return false;
}else{
showImage($(c), 20);
$('.tabs li').removeClass('current');
$(this).parent().addClass('current');
return false;
}
})
runRotateImages();
$("#featured").hover(
function(){
clearTimeout(xx);
},
function(){
runRotateImages();
}
)
})
function showImage(img, duration){
$('.slider').removeClass('current').css({
"opacity" : 0.0,
"zIndex" : 2
});
img.animate({opacity:1.0}, duration, function(){
$(this).addClass('current').css({zIndex:1});
});
}
function rotateImages(){
var curPhoto = $("div.current");
var nxtPhoto = curPhoto.next();
var curTab = $(".tabs li.current");
var nxtTab = curTab.next();
if (nxtPhoto.length == 0) {
nxtPhoto = $('#featured div:first');
nxtTab = $('.tabs li:first-child');
}
curTab.removeClass('current');
nxtTab.addClass('current');
showImage(nxtPhoto, 300);
}
function runRotateImages(){
xx = setInterval("rotateImages()", 5000);
}
I have added a jsfiddle - http://jsfiddle.net/n5EPM/3/
However, on jsfiddle it does not seem to automatically cycle through the images, not sure why, have no problems in browser.
Try using not() method: http://api.jquery.com/not/
Basically, you need to create a new class disabled
.disabled{
background-color:#000000;
}
Then, add the following line to your tabs.li's each loop:
$(".tabs li").not(".current").addClass('disabled'); //add disabled class for non-current tabs
At last you need to remove disabled class in the rotateimage() function before assigning current and then disable non-current again. like this:
curTab.removeClass('current');
nxtTab.removeClass('disabled'); //remove diabled class
nxtTab.addClass('current');
$(".tabs li").not(".current").addClass('disabled'); // disable non-current again
Working jsfiddle here: http://jsfiddle.net/n5EPM/9/
This might not be the perfect solution but you will need to tweak it a little bit.
Hope this helps.
I have a bar chart and i want each bar to render in different color. So i tried using thems,
sample code is:
Ext.define('Ext.chart.theme.FancyTheme',{
extend : 'Ext.chart.theme.Base',
constructor : function(config){
this.callParent([Ext.apply({
colors : ['#9CC5C9','#D5544F','#D5544F','#5288DB']
},config)])
}
});
and my chart code is:
var tc = Ext.create('Ext.chart.Chart',{
renderTo: Ext.getBody(),
width: 500,
height: 300,
animate : true,
insetPadding : 20,
theme: 'FancyTheme',
But all the bar colors are changing to same color i.e, to '#9cc5c9' in above example.
But i want bars to render in differnt colors as mentioned in theme. One more thing i dont want to use render function to render coloirs.
So wat is the soln to get different colors. Can anyone help me out!!
Sorry, but using a renderer is the correct solution. The colors property is used for successive series in a chart, such as multiple areas in the same plot space.
I don't understand why you don't want to use a renderer, but here's all you would need to do:
renderer: function(sprite, record, attr, index, store) {
var colors = ['#9CC5C9','#D5544F','#D5544F','#5288DB'];
return Ext.apply(attr, {
fill: colors[index % colors.length]
});
}
You can also extend Ext.chart.series.Bar. For example:
Ext.define('Ext.chart.series.MyBar', {
extend: 'Ext.chart.series.Bar',
//type: 'mybar',
alias: 'series.mybar',
getPaths: function() {
this.callParent(arguments);
var items = this.items,
i, iLen = items.length,
colors = this.colorArrayStyle,
colorsLength = colors && colors.length || 0;
for (var i = 0; i < iLen; ++i) {
items[i].attr.fill = colors[i % colorsLength];
}
}
});
Then in series you should use mybar instead of bar.