Showing posts with label Tweeting-Code. Show all posts
Showing posts with label Tweeting-Code. Show all posts

Tuesday, October 9, 2012

Set focus on input upon click on ng-repeat

Live test: http://jsfiddle.net/epAxT/5/


Model and Controller:

function TestController($scope) {
        
    // Models
    $scope.messages = 
    [
    { Message: 'Life is what happens to you...', By: 'John Lennon' },
    { Message: 'If you can\'t explain...', By: 'Albert Einstein' },
    { Message: 'The answer to life...', By: 'Douglas Adams' }
    ];
    
    
    $scope.currentMessage = null;
    
    // Controller's actions
    
    $scope.setCurrentMessage = function(msg) {
        $scope.currentMessage = msg;
    };

    $scope.isCurrentMessage = function(msg) {
        return msg == $scope.currentMessage;
    };
    
    $scope.addMessage = function() {
        var msg = {Message: 'blah', By: 'Anonymous'};
        $scope.currentMessage = msg;
        $scope.messages.push(msg);
    };
    
}
    
    


    
    
var appGreat = angular.module('AppGreat', []);

appGreat.directive('toFocus', function ($timeout) {
    return function (scope, elem, attrs) {
        scope.$watch(attrs.toFocus, function (newval) {
            if (newval) {
                $timeout(function () {
                    elem[0].focus();
                }, 0, false);
            }
        });
    };
});
​


View:
<br/>
<div ng-app='AppGreat' ng-controller='TestController'>
    
    <table>
        <thead>
            <tr>
                <th>Message</th><th>By</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat='m in messages'>
                <td width='200px'>
                    <div ng-hide='isCurrentMessage(m)' 
                         ng-click='setCurrentMessage(m)'>
                        {{m.Message}}
                    </div>
                    <div ng-show='isCurrentMessage(m)'>
                        <input ng-model='m.Message'
                               to-focus='isCurrentMessage(m)'
                               style='width: 100%' />
                    </div>
                    
                    
                </td>
                
                <td>
                    <div ng-hide='isCurrentMessage(m)' 
                         ng-click='setCurrentMessage(m)'>
                        {{m.By}}
                    </div>
                    <div ng-show='isCurrentMessage(m)'>
                        <input ng-model='m.By'/>                        
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
    
    
    <input type='button' ng-click='addMessage()' value='Add Message'/>
    
</div>       ​

Tuesday, August 7, 2012

jQuery selector nuances

​<select name="Beatle" id="Beatle"​​​​​​​​​​​​​​​​​​​​​​​>
    <option id=9>John</option>
    <option id=8>Paul</option>
    <option id=7 selected>George</option>
    <option id=6>Ringo</option>
</select>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​


<script>
 var selectedText = "";

 selectedText = $('#Beatle').text();
 alert('Not Correct: ' + selectedText);

 selectedText = $('option:selected','#Beatle').text();
 alert('Correct: ' + selectedText);

 selectedText = $('#Beatle:selected').text();
 alert('Not correct: ' + selectedText);

 selectedText = $('#Beatle :selected').text();
  alert('Correct: ' + selectedText);

});
</script>


Live test: http://jsfiddle.net/5XAYh/

Monday, August 6, 2012

Manual model and view synchronization with JavaScript

When you don't use an MVC javascript framework that can do two-way databinding, you are left on your own to synchronize the state between the model and the view.


Live test: http://jsfiddle.net/E7F7D/33/

<table id='dataHere' border='1'>
<thead>
    <!-- ID presence on HTML is optional --> 
    <!--<th style='visibility: collapse'>Id</th>-->
    
    <th>Lastname</th><th>Firstname</th><th>Asset</th><th>Actions</th>
</thead>
<tbody>
</tbody>
    
    
</table>

<hr/>

    <input type="button" id="viaModel" value="test via model"/>

    <input type="button" id="viaDom" value="test via DOM"/>
        
    <div id="debugLog">
     </div>


<script>
    var people = [
        { Id: 1, Lastname: 'Lennon', Firstname: 'John', Asset: 40090.1296 },
        { Id: 2, Lastname: 'McCartney', Firstname: 'Paul', Asset: 38000.34 },
        { Id: 3, Lastname: 'Harrison', Firstname: 'George', Asset: 37000.56 },
        { Id: 4, Lastname: 'Starr', Firstname: 'Ringo', Asset: 40000.78 },
        
        { Id: 5, Lastname: 'Buendia', Firstname: 'Ely', Asset: 40000.93 },
        { Id: 6, Lastname: 'Marasigan', Firstname: 'Raymund', Asset: 39000.12 },
        { Id: 7, Lastname: 'Zabala', Firstname: 'Buddy', Asset: 39000.13 },
        { Id: 8, Lastname: 'Adoro', Firstname: 'Marcus', Asset: 39000.14344 }    
        
        ];
    
    
    var tbl = $('#dataHere');
    
    $('#viaModel').click(function() {
        var dl = $('#debugLog');
        dl.html('Model-based approach. Data are in their pristine state');
        $.each(people, function() {
            var person = this;
            
            dl.append(person.Id + '-->' + person.Lastname + ', ' + person.Firstname + ': ' + this.Asset + '<p/>');
        });
    });
    
    $('#viaDom').click(function() {
        try {
            var dl = $('#debugLog');
            var tbl = $('#dataHere');
    
            dl.html('Using DOM approach for stashing and extracting data, the Id won\'t be available unless we stash it on HTML');
            
            
    
            var trs = $('tbody > tr', tbl);
    
    
            $.each(trs, function() {
                var tr = this;
                var tds = $('td', tr);
        
                // Alas! ID won't be available if you didn't put it in td tag or whatnot.
                // If we use DOM approach for stashing our data, 
                // we have to stash ID on the HTML itself, 
                // this is called Smart UI approach, this is abhored, 
                // as the code is tightly coupled to UI/presentation layer.
                
        
                var tdLastname = $(tds[0]);
                var tdFirstname = $(tds[1]);                       
                var tdAsset = $(tds[2]);
                
                
                
                var lastname = tdLastname.text();
                var firstname = tdFirstname.text();
                // another problem with Smart UI approach is the data gets mangled
                
                var asset = tdAsset.text().replace('Php ','').replace(',','');
                
                dl.append(lastname + ', '+ firstname + ': ' + asset);                
                
                
            })
                
            dl.append('And data gets mangled and truncated too. Check the rounding-offs');
        
        } catch(e) {
            alert(e);
        }
                       
    });
    
    
    $.each(people, function() {
        var person = this;
        
        var trPerson = $('<tr/>');
    
        
        // optional
        // var tdId = $('<td/>').css('visibility','collapse');
        
        var tdLastname = $('<td/>');
        var tdFirstname = $('<td/>');
        var tdAsset = $('<td/>');
        var tdActions = $('<td/>');
        
        var aEditAction = $('<a/>').prop('href','#').text('Edit');
        var aDeleteAction = $('<a/>').prop('href','#').text('Delete');
        
       
        // optional
        // tdId.text(this.Id);
        
        tdLastname.text(this.Lastname);
        tdFirstname.text(this.Firstname);
        tdAsset.text(formatMoney(this.Asset, 2, 'Php ', ',','.'));
    
        
        aEditAction.click(function() {
            // alert('Will edit ' + person.Id + ' ' + person.Lastname);
            
            
            var ln = prompt('Enter value', person.Lastname);
            person.Lastname = ln == null ? person.Lastname : ln;
            
            tdLastname.text(person.Lastname);
        });        
        
     
        
        aDeleteAction.click(function() {
            if (confirm('Will delete ' + person.Id + ' ' + person.Lastname)) {   
                
                people.splice(people.indexOf(person),1);
                
                trPerson.remove();
            }
        });
        
            
    
        
        trPerson
            // .append(tdId) // optional
            .append(tdLastname).append(tdFirstname)
            .append(tdAsset).append(tdActions);
        
        tdActions.append(aEditAction).append('|').append(aDeleteAction);
    
      
          
        tbl.append(trPerson);
    
            
    });
    
     // alert(8);
        // alert(formatMoney(92334.55, 2,'Php ',',','.'));
        
    // http://www.josscrowcroft.com/2011/code/format-unformat-money-currency-javascript/
    function formatMoney(number, places, symbol, thousand, decimal) {
        number = number || 0;
        places = !isNaN(places = Math.abs(places)) ? places : 2;
        symbol = symbol !== undefined ? symbol : "$";
        thousand = thousand || ",";
        decimal = decimal || ".";
        var negative = number < 0 ? "-" : "",
            i = parseInt(number = Math.abs(+number || 0).toFixed(places), 10) + "",
            j = (j = i.length) > 3 ? j % 3 : 0;
        return symbol + negative + (j ? i.substr(0, j) + thousand : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousand) + (places ? decimal + Math.abs(number - i).toFixed(places).slice(2) : "");
    }
</script>

Monday, May 14, 2012

Java, moving furnitures around is a no-no. Refactoring-happy fellow be warned

class A { void m() { System.out.println("outer"); }}

public class TestInners {

 public static void main(String[] args) {
  new TestInners().go();
 }

 void go() {  
  new A().m();

  class A { void m() { System.out.println("inner"); } }  
 }

 class A { void m() { System.out.println("middle"); } }
}

You might have assumed the output is inner, since the class is in the same scope as the method. I don't know what are the Java language designers are thinking, it's more intuitive to choose the inner regardless of what line the class is declared. Java has some quirks on rules for resolving classes scope and accessibility, and this is one of those.

That code output is middle.


Move the class A at first line of go(), the output is inner:

void go() { 
 class A { void m() { System.out.println("inner"); } }  
 
 new A().m();
}

Tuesday, May 8, 2012

Capping negative numbers to zero

select 
   ( col1 + abs(col1) ) / 2 as capped_to_zero
from tbl

is faster than:


select 
   case when col1 >= 0 then col1 else 0 end as capped_to_zero
from tbl


Tuesday, April 24, 2012

Javascript's object and associative array duality. A dynamic method invocation feature hiding in plain sight

The duality of Object and associative array in javascript is a neat functionality you can tap anytime

var something = new Object();

something["FirstName"] = "Michael";
something.LastName = "Buen";

something["MiddleName"] = "Ignite";
something.Age = "Forever";

window.alert(something.FirstName);
window.alert(something["LastName"]);

window.alert(something["MiddleName"]);
window.alert(something.Age);

alert("iterate");

for(var x in something) alert(x + ": " + something[x]);
​


With that in mind, dynamic method invocation like this is possible:

window.alert('ok');
window.confirm('ok');

var arr = ["alert", "confirm"];

for(i = 0; i < arr.length; ++i) window[arr[i]]("Nice!");

And since the alert function is available on implied this object, alert can be done in these ways:

this.alert("would work");
this["alert"]("This would work too");
alert("works"); // the usual

There's another language which has these sort of duality, C language. Its arrays are pointers can be accessed in almost the same ways. Though some might argue that this duality is confusing for beginners.

Saturday, April 21, 2012

Detect if a given column has all values set to null

Given this:

create table test(
x char(1) not null,
y char(1)
);

insert into test(x,y) values
('A',null),
('A','E'),
('B', null),
('B', null);


How you would detect that if column x's y column has all values set to null? in this case, the output is B

One might right away write the code like this:

select x
from test
group by x
having sum((y is not null)::int) = count(x);


That logic is needlessly complicated to detect if a given column has all values set to null. Just use MAX


select x
from test
group by x
having max(y) is null;


UPDATE 2012-05-09

This is way much better:

select x
from test
group by x
having every(y is null)

every works only on Postgresql.

every shall stop as soon any of its element didn't satisfy the condition. It's faster than max or sum-count combo approach. every is an alias for bool_and. For MySQL, use bit_and. Postgresql's every is short-circuited

Tuesday, March 6, 2012

Assigning integer to character is perfectly allowable in Java, C/C++

char c = 65; // Java, C/C++ would allow this. C# won't
System.out.println(c); // outputs A



need to typecast in C#
char c = (char) 65;
Console.WriteLine(c);

Saturday, July 30, 2011

Pad blank rows to Flexigrid

$('#nav').flexigrid({
 url: '/Person/Management/List',
 dataType: 'json',
 colModel: [
  { display: 'Username', name: 'Username', width: 150, sortable: true, align: 'left' },
  { display: 'Firstname', name: 'Firstname', width: 150, sortable: true, align: 'left' },
  { display: 'Lastname', name: 'Lastname', width: 150, sortable: true, align: 'left' },
  { display: 'Favorite#', name: 'FavoriteNumber', width: 150, sortable: true, align: 'left' }
 ],
 buttons: [
  { name: 'Add', bclass: 'add', onpress: add },
  { separator: true },
  { name: 'Edit', bclass: 'edit', onpress: edit },
  { separator: true },
  { name: 'Delete', bclass: 'delete', onpress: del }
 ],
 singleSelect: true,
 sortname: 'Lastname',
 sortorder: 'asc',
 usepager: true,
 title: 'Persons',
 useRp: true,
 rp: 5, 
 rpOptions: [5, 10, 15, 20, 25, 40],
 showTableToggleBtn: true,
 width: 560,
 height: 'auto',
 preProcess: function (data) {                

    var rp = getFgRowsPerPage($('#nav'));
    for (i = data.rows.length; i < rp; ++i) {
        data.rows.push({ 'id': '', 'cell': ['', '', '', ''] });
    }
    return data;
 }
});

function getFgRowsPerPage(tbl) {
    return $('select[name=rp] option:selected', tbl.closest('.flexigrid')).val();
}


Sample output(the last two rows are from the for loop):

Resize Flexigrid's Height

/*
Flexigrid's height is for table's tbody only, it does not include the chrome's (grid's navigation panel, title bar, etc) height. So if you pass 250 to flexigrid's height parameter, and you pass the same 250 to resizeFgHeight, it will actually make the flexigrid smaller.
*/
function resizeFgHeight(tbl, newHeight) {
    grd = tbl.closest('.flexigrid');
    var heightWithChromes = grd.height();
    
    var contentHeight = $('.bDiv', grd).height();
    var chromesHeight = heightWithChromes - contentHeight;    

    $('.bDiv', grd).height(newHeight - chromesHeight);
    grd.css('height', newHeight);
}

// This height is the same as flexigrid's height parameter. 
// Flexigrid's height parameter describes the the tbody's height of the table only,
// it does not include the chromes' heights
function resizeFgContentHeight(tbl, newHeight) {
    grd = tbl.closest('.flexigrid');
    $('.bDiv', grd).height(newHeight);
}

To use
<table id="nav"></table>

$(function() {
   $('#adjust').click(function() { 
      resizeFgHeight($('#nav'), 480);
   });
});