Friday, February 26, 2016

hide icon/logo from action bar on android



/Users/smr/current_projects/oeg-a/OEGAndroid/cards_th67/src/main/res/values/styles.xml

    <!-- Base application theme. -->
    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="android:logo">@android:color/transparent</item>
    </style>








content_info timestamp for the oeg android apps


/Users/smr/current_projects/oeg-a/work/add-content-info-timestamp.rb

#!/usr/bin/env ruby
# add a content_info table with a timestamp column
require 'sqlite3'

tablename = "content_info"

y = 2015
m = 1
d = 29

born_on_date = DateTime.new(y,m,d,17,0,0)

ARGV.each do|filename|
  puts "filename=#{filename}"
  puts "timestamp date=#{y}-#{m}-#{d}"
  begin
      
      db = SQLite3::Database.open filename
      version = db.get_first_value 'SELECT SQLITE_VERSION()'
      puts "sqlite version=#{version}"

      # android metadata
      db.execute "DROP TABLE IF EXISTS android_metadata;"
      db.execute "CREATE TABLE android_metadata (locale TEXT);"
      db.execute "insert into android_metadata values('en_US')"

      #content_info (born-on timestamp)
      timestamp = born_on_date.to_time.to_i
      db.execute "DROP TABLE IF EXISTS #{tablename};"
      db.execute "CREATE TABLE #{tablename} (timestamp INT);"
      db.execute "insert into #{tablename} values(#{timestamp})"
      puts "timestamp int=#{timestamp}"

      system "open", filename
      
  rescue SQLite3::Exception => e 
      
      puts "Exception occured"
      puts e
      
  ensure
      db.close if db
  end

end


Thursday, February 25, 2016

add timestamp and android_metadata with add-content-info-timestamp.rb


/Users/smr/bin/add-content-info-timestamp.rb

#!/usr/bin/env ruby
# add a content_info table with a timestamp column
require 'sqlite3'

tablename = "content_info"

y = 2016
m = 2
d = 25

born_on_date = DateTime.new(y,m,d,12,0,0)

ARGV.each do|filename|
  puts "filename=#{filename}"
  puts "timestamp date=#{y}-#{m}-#{d}"
  begin
      
      db = SQLite3::Database.open filename
      version = db.get_first_value 'SELECT SQLITE_VERSION()'
      puts "sqlite version=#{version}"

      # android metadata
      db.execute "DROP TABLE IF EXISTS android_metadata;"
      db.execute "CREATE TABLE android_metadata (locale TEXT);"
      db.execute "insert into android_metadata values('en_US')"

      #content_info (born-on timestamp)
      timestamp = born_on_date.to_time.to_i
      db.execute "DROP TABLE IF EXISTS #{tablename};"
      db.execute "CREATE TABLE #{tablename} (timestamp INT);"
      db.execute "insert into #{tablename} values(#{timestamp})"
      puts "timestamp int=#{timestamp}"

      system "open", filename
      
  rescue SQLite3::Exception => e 
      
      puts "Exception occured"
      puts e
      
  ensure
      db.close if db
  end

end

/Users/smr/current_projects/oeg-a/work/add-content-info-timestamp.rb
#!/usr/bin/env ruby
# add a content_info table with a timestamp column
# usage ./add-content-info-timestamp.rb oeg.db
require 'sqlite3'

tablename = "content_info"

y = 2015
m = 1
d = 29

born_on_date = DateTime.new(y,m,d,17,0,0)

ARGV.each do|filename|
  puts "filename=#{filename}"
  puts "timestamp date=#{y}-#{m}-#{d}"
  begin
      
      db = SQLite3::Database.open filename
      version = db.get_first_value 'SELECT SQLITE_VERSION()'
      puts "sqlite version=#{version}"

      # android metadata
      db.execute "DROP TABLE IF EXISTS android_metadata;"
      db.execute "CREATE TABLE android_metadata (locale TEXT);"
      db.execute "insert into android_metadata values('en_US')"

      #content_info (born-on timestamp)
      timestamp = born_on_date.to_time.to_i
      db.execute "DROP TABLE IF EXISTS #{tablename};"
      db.execute "CREATE TABLE #{tablename} (timestamp INT);"
      db.execute "insert into #{tablename} values(#{timestamp})"
      puts "timestamp int=#{timestamp}"

      system "open", filename
      
  rescue SQLite3::Exception => e 
      
      puts "Exception occured"
      puts e
      
  ensure
      db.close if db
  end

end

ruby script to encapsulate android icons - encapsulate-android-icons.rb


ruby script to encapsulate icon files

icons are supplied with naming like:
ic_launcher_AMA_rev2:
ic_launcher_AMA_36.png
ic_launcher_AMA_48.png
ic_launcher_AMA_64.png
ic_launcher_AMA_72.png
ic_launcher_AMA_96.png
ic_launcher_AMA_144.png
ic_launcher_AMA_192.png
ic_launcher_AMA_512.png

but we need something like:
ic_launcher_AMA_rev2:
drawable-hdpi:
ic_launcher.png
drawable-mdpi:
ic_launcher.png
drawable-xhdpi:
ic_launcher.png
drawable-xxhdpi:
ic_launcher.png


to be able to drag these folders onto the folders in the res folder and do a merge copy for a quick replace.

this script automates the tedium:
/Users/smr/bin/encapsulate-android-icons.rb


#!/usr/bin/env ruby
require "fileutils"


def encapsulate dir_name, file_wildcard
  FileUtils.rm_rf(dir_name)
  Dir.mkdir(dir_name)
  Dir.glob(file_wildcard).each do |f| 
    dest_path = File.join(dir_name, 'ic_launcher.png')
    FileUtils.cp f, dest_path
  end  
end

# dir_name = "drawable-hdpi"
# file_wildcard = '*72.png'
encapsulate('drawable-mdpi', '*48.png')
encapsulate('drawable-hdpi', '*72.png')
encapsulate('drawable-xhdpi', '*96.png')
encapsulate('drawable-xxhdpi', '*144.png')

system "open", "."





create a new android target by making a copy of an existing target folder


duplicate an existing build

close AS
copy the folder
rename to target name, e.g. cards_th67
delete build folder

find replace package name

e.g.
old: com.asa2fly.cards.th67
new: com.asa2fly.cards.r22
replaces 3 occurrences across 3 files.

build.gradle:
    defaultConfig {
        applicationId "com.asa2fly.cards.th67"
        minSdkVersion 17
        targetSdkVersion 21
        versionCode 1
        versionName "1.00"
    }

find replace the package name:
/Users/smr/current_projects/oeg-a/OEGAndroid/cards_th67/build.gradle:
    6
    7      defaultConfig {
    8:         applicationId "com.asa2fly.cards.th67"
    9          minSdkVersion 17
   10          targetSdkVersion 21

/Users/smr/current_projects/oeg-a/OEGAndroid/cards_th67/src/androidTest/java/com/asa2fly/oeg/helicopter/ApplicationTest.java:
    1: package com.asa2fly.cards.th67;
    2
    3  import android.app.Application;

/Users/smr/current_projects/oeg-a/OEGAndroid/cards_th67/src/main/AndroidManifest.xml:
    1  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    2:     package="com.asa2fly.cards.th67">
    3
    4      <application

iml file

make a copy of iml file
tweak as below (including renaming the file), then delete the old one

/Users/smr/current_projects/oeg-a/OEGAndroid/cards_th67/cards_th67.iml:
    1  <?xml version="1.0" encoding="UTF-8"?>
    2: <module external.linked.project.id=":cards_th67" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="OEGAndroid" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
    3    <component name="FacetManager">
    4      <facet type="android-gradle" name="Android-Gradle">
    5        <configuration>
    6:         <option name="GRADLE_PROJECT_PATH" value=":cards_th67" />
    7        </configuration>
    8      </facet>


top level settings.gradle:
include ':cards_th67', ':oeg_private', ':oeg_common', ':oeg_atp', ':oeg_bfr', ':oeg_instrument', ':oeg_cfi', ':oeg_commercial', ':oeg_helicopter', ':oeg_multiengine'

this includes the subprojects in the parent project.

check project in AS

project should appear in the subprojects tree

build on command line

[smr@smr OEGAndroid (master *%)]$ ./gradlew cards_r22:assembleDebug













ruby script to list image dimensions


/Users/smr/bin/get-image-dimensions.rb

#!/usr/bin/env ruby
#get-image-dimensions.rb *.png
require 'dimensions'

ARGV.each do |image_file|
  size = Dimensions.dimensions(image_file)
  puts "#{image_file}: #{size}"
end


Monday, February 22, 2016

DataTables mo bettah


this just works for PWO, n monkey patching needed, and no issues with ajax links/buttons in table cells (was having problems with bootgrid).




  1. look into datatables
    1. bower
    2. basic setup
    3. action buttons
    4. hidden columns
      1. columnDefs
      2. "visible": false
    5. default ordering
    6. prevent searching for certain cols
      1. columnDefs
      2. "searchable": false
    7. prevent ordering for certain cols
      1. columnDefs
    8. customs batch lengths
      1. "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]




add DataTables for bootstrap 3 using bower


search for packages
[smr@smr rails4sandbox (master *%)]$ bower search datatables.net
Search results:
...
    datatables.net git://github.com/DataTables/Dist-DataTables.git
...
[smr@smr rails4sandbox (master *%)]$ bower search datatables.net-bs
Search results:
    datatables.net-bs git://github.com/DataTables/Dist-DataTables-Bootstrap.git

add datatables to Bowerfile
Bowerfile:
asset 'datatables.net'
asset 'datatables.net-bs'

install:
rake bower:install

add datatables javascript
app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require bootstrap-sass-official/assets/javascripts/bootstrap
//= require google-code-prettify
//= require jquery.bootgrid
//= require datatables.net
//= require datatables.net-bs
//= require_tree .

add datatables stylesheets
app/assets/stylesheets/application.scss
@import "bootstrap-sass-official/assets/stylesheets/bootstrap-sprockets";
@import "bootstrap-sass-official/assets/stylesheets/bootstrap";
@import "jquery.bootgrid/dist/jquery.bootgrid.css";

@import "datatables.net-bs/css/dataTables.bootstrap.css";

Friday, February 19, 2016

monkeypatch bootgrid to prevent removal of links in cells


this doesn't appear broken for all links
links created with link_to
this has something to do with rails templating process.


/Users/smr/current_projects/rails4sandbox/vendor/assets/bower_components/jquery.bootgrid/dist/jquery.bootgrid.js


https://github.com/rstaib/jquery-bootgrid/issues/15

I added new data-... attribute that named isitemtemplate and changed the code like this :
$.each(that.columns, function (i, column) {
if(column.isitemtemplate){
row[column.id] = column.converter.from(cells.eq(i).html());
} else {
row[column.id] = column.converter.from(cells.eq(i).text());
}
});

loadColumns

added stuff in bold:
    function loadColumns()
    {
        var that = this,
            firstHeadRow = this.element.find("thead > tr").first(),
            sorted = false;

        /*jshint -W018*/
        firstHeadRow.children().each(function ()
        {
            var $this = $(this),
                data = $this.data(),
                column = {
                    id: data.columnId,
                    identifier: that.identifier == null && data.identifier || false,
                    converter: that.options.converters[data.converter || data.type] || that.options.converters["string"],
                    text: $this.text(),
                    align: data.align || "left",
                    headerAlign: data.headerAlign || "left",
                    cssClass: data.cssClass || "",
                    headerCssClass: data.headerCssClass || "",
                    isItemTemplate: data.isItemTemplate || false,
                    formatter: that.options.formatters[data.formatter] || null,
                    order: (!sorted && (data.order === "asc" || data.order === "desc")) ? data.order : null,
                    searchable: !(data.searchable === false), // default: true
                    sortable: !(data.sortable === false), // default: true
                    visible: !(data.visible === false), // default: true
                    visibleInSelection: !(data.visibleInSelection === false), // default: true
                    width: ($.isNumeric(data.width)) ? data.width + "px" : 
                        (typeof(data.width) === "string") ? data.width : null
                };
            that.columns.push(column);
            if (column.order != null)
            {
                that.sortDictionary[column.id] = column.order;
            }

            // Prevents multiple identifiers
            if (column.identifier)
            {
                that.identifier = column.id;
                that.converter = column.converter;
            }

            // ensures that only the first order will be applied in case of multi sorting is disabled
            if (!that.options.multiSort && column.order !== null)
            {
                sorted = true;
            }
        });
        /*jshint +W018*/
    }


loadRows

altered stuff in bold:

    function loadRows()
    {
        console.log("loadRows");
        if (!this.options.ajax)
        {
            var that = this,
                rows = this.element.find("tbody > tr");

            rows.each(function ()
            {
                var $this = $(this),
                    cells = $this.children("td"),
                    row = {};

                $.each(that.columns, function (i, column)
                {
                    if(column.isItemTemplate){ 
                        row[column.id] = column.converter.from(cells.eq(i).html());
                    } else {
                        row[column.id] = column.converter.from(cells.eq(i).text());
                    }
                });

                appendRow.call(that, row);
            });

            setTotals.call(this, this.rows.length);
            sortRows.call(this);
        }
    }


add this to the columns where you don't want the links to get borked:
<th data-is-item-template="true">Actions</th>















Wednesday, February 17, 2016

evaluate jquery bootgrid - grid control using bootstrap


http://www.jquery-bootgrid.com/

https://github.com/rstaib/jquery-bootgrid

http://localhost/~smr/jquery-bootgrid/demo/index.htm

http://www.jquery-bootgrid.com/Documentation

http://www.jquery-bootgrid.com/Examples

clone repo, run sample in localhost

http://localhost/~smr/jquery-bootgrid/demo/index-work.htm

basics

basics: take a bootstrap table and turn it into a grid control

There are two ways to populate jQuery Bootgrid. Either you use the server-side way (e.g. a REST service) for querying a dynamic data source like a database or you use the client-side way for simple in-memory data visualization.

To use the client-side way you need almost no configuration. Just add your rows via HTML or use the append method to append rows dynamically (see  here).

For using the server-side way you must set at least the ajax option to true and pass an URL to the url option (see  here).

All settings can also be set via the data API on the table tag for general settings and th tags for column specific settings.

simple example (client-side data) in the rails4sandbox

N.B. you need a table head section with this structure:
<table>
  <thead>
    <tr>
      <th></th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr></tr>
  </tbody>
</table>

for the grid to work properly.


http://localhost:3001/boot_grid/index
http://localhost:3001/boot_grid/simple

install with bower:
http://www.jquery-bootgrid.com/GettingStarted
in app js:
//= require jquery.bootgrid
in application.scss:
@import "jquery.bootgrid/dist/jquery.bootgrid.css";

make a new rails controller
/Users/smr/current_projects/rails4sandbox/app/views/boot_grid/index.html.erb
copy table data from /Users/smr/Sites/jquery-bootgrid/demo/index-work.htm

<table id="grid" class="table table-condensed table-hover table-striped" data-selection="true" data-multi-select="true" data-row-select="true" data-keep-selection="true">
    <thead>
        <tr>
            <th data-column-id="id" data-identifier="true" data-type="numeric" data-align="right" data-width="40">ID</th>
            <th data-column-id="sender" data-order="asc" data-align="center" data-header-align="center">Sender</th>
            <th data-column-id="received" data-css-class="cell" data-header-css-class="column" data-filterable="true">Received</th>
            <th data-column-id="link" data-formatter="link" data-sortable="false" data-width="75px">Link</th>
            <th data-column-id="status" data-type="numeric" data-visible="false">Status</th>
            <th data-column-id="hidden" data-visible="false" data-visible-in-selection="false">Hidden</th>
        </tr>
    </thead>
    <tbody>
...
    </tbody>
</table>

init with normal js embedded in the page:
<script>
  $(function()
  {
      function init()
      {
          $("#grid").bootgrid({
              formatters: {
                  "link": function(column, row)
                  {
                      return "<a href=\"#\">" + column.id + ": " + row.id + "</a>";
                  }
              },
              rowCount: [-1, 10, 50, 75]
          });
      }
      
      init();
      
  });
</script>

the coffeescript equivalent:
jQuery ->

  if $('table#grid_simple').length
    init = ->
      console.log("bootgrid: init grid_simple")
      $("#grid_simple").bootgrid({
        formatters: {
          "link": (column, row) ->
            return "<a href=\"#\">" + column.id + ": " + row.id + "</a>"
        },
        rowCount: [-1, 10, 50, 77]
      })

    init()


ajax example (server-side data) in the rails4sandbox


need to set ajax=true and set the url that will provide the row data.

create an empty table (will be filled with the ajax call):
<table id="grid_data" class="table table-condensed table-hover" data-ajax="true" data-url="<%= get_bootgrid_table_data_path %>">
    <thead>
        <tr>
            <th data-column-id="id" data-identifier="true" data-type="numeric" data-align="right" data-width="40">ID</th>
            <th data-column-id="sender" data-order="asc" data-align="center" data-header-align="center">Sender</th>
            <th data-column-id="received" data-css-class="cell" data-header-css-class="column" data-filterable="true">Received</th>
            <th data-column-id="link" data-formatter="link" data-sortable="false" data-width="75px">Link</th>
            <th data-column-id="statusRENAMED" data-type="numeric" data-visible="true">Status</th>
            <th data-column-id="hidden" data-visible="false" data-visible-in-selection="false">Hidden</th>
        </tr>
    </thead>
    <tbody></tbody>
</table>


data url can specified via the data api:
<table id="grid_data" class="table table-condensed table-hover" data-ajax="true" data-url="<%= get_bootgrid_table_data_path %>">

 or in coffeescript
  if $('table#grid_data').length
    init = ->
      console.log("bootgrid: init grid_data")
      $("#grid_data").bootgrid({
        rowCount: [-1, 10, 50, 75],
        ajax: true,
        url: "/get_bootgrid_table_data"
      })

    init()

stub controller method returns data that will be used to will the table:
  def get_bootgrid_table_data
    dict = {
      current:1,
      rowCount: 10,
      rows: [
        {
          id: 1,
          sender: "me@rafaelstaib.com",
          received: "",
        },
        {
          id: 2,
          sender: "me@rafaelstaib.com",
          received: "",
        },
        {
          id: 3,
          sender: "",
          received: "stephen@fretlessmultimedia.com",
        },
        {
          id: 4,
          sender: "",
          received: "stephen@prepware.com",
        },
      ],
      total: 4
    }
    render json: dict
  end


the controller method gets passed parameters for sort, search, etc:
sort parameter (along with column names) get passed when a header is clicked:
Started POST "/get_bootgrid_table_data" for ::1 at 2016-02-19 08:46:32 -0500
Processing by BootGridController#get_bootgrid_table_data as */*
  Parameters: {"current"=>"1", "rowCount"=>"-1", "sort"=>{"sender"=>"desc"}, "searchPhrase"=>""}

if a row count is specified:

Parameters: {"current"=>"1", "rowCount"=>"50", "sort"=>{"sender"=>"desc"}, "searchPhrase"=>""}