HomeHome ArchiveArchive

Understanding what’s going on in ExtJS

Recently I had to pre-select a Node inside a TreePanel ExtJS widget. I tried many ways but failed because most of the time when I tried to:

  node.select();

that node would not yet be rendered into the browser’s DOM and so the select would fail somewhere inside the extjs.js blob with something like "this ... undefined ...". What I needed was a "rendered" event, but there doesn’t seem to be such an event for neither TreePanel not TreeNode or any of their superclasses. Diving into ExtJS code was not really very helpful because it’s a framework that does things through layers and layers and as such is not trivial to understand quickly.

Thus, the same ole problem with JavaScript as ever: “show me all the events there are”. However, surprisingly, in contrast to standard JavaScript, ExtJS has an easy standard way to accomplish this:

 
  Ext.util.Observable.capture( myTree, function(event) {                                                                                                        
                                         console.log("got an event in myTree");
                                         console.log(event); });

And quickly I discovered that there indeed is an obscure event that I can, out of alternatives, missuse to do what I want, which is expandnode.

Aparently, after a node is exapanded, all its children are put into the DOM and seem to be manipulable then. Thus:

        /*
         * select node with real_id - this is only called once
         * after the tree is rendered for the first time.
         * After that the listener itself is unregistered.
         */
        function select_node(node) {
          node.eachChild( function(child) { 
            if(child.attributes.real_id == real_id ) {
              child.select();
              categories_panel.un('expandnode', select_node);
            }
          });
        };
        myTree.on('expandnode', select_node);

Tomáš Pospíšek

Logging un-translated strings in rails

Problem statement:

Which of our strings are not translated yet in our Ruby on Rails app?

Unfortunately there’s no easy way to know for sure. One solution is to log untranslated strings as soon as they appear - the following solution applies to the spree-i18n extension but should be easily adaptable to other contexts.

What we do here is monkey patching I18n#t, to check whether the original I18n#t told us that there’s no translation and log it in that case. Then we return whatever the original I18n#t gave us:

I18n.class_eval do                                                                                    
                                                                                                      
      class << self                                                                                   
        alias_method :alias_for_t, :t                                                                 
      end                                                                                             
                                                                                                      
      # make t log missing translations                                                               
      def self.t( keyz, options = {})                                                                 
        translation = self.alias_for_t( keyz, options )                                               
        if translation =~ /translation missing:/                                                      
          MISSING_TRANSLATION.info translation                                                        
        end                                                                                           
        return translation                                                                            
      end                                                                                             
    end                                                                                               

end

To initialize the logger:

class MissingTranslationLogger < Logger
  def format_message(severity, timestamp, progname, msg)
    "#{msg}\n" 
  end 
end

logfile = File.open('log/missing_translations.log', 'a')    
# optional: # logfile.sync = true
MISSING_TRANSLATION = MissingTranslationLogger.new(logfile)

You’ll need to place those two code snipplets in apropriate places. I’ve put the first one in vendor/extensions/site/site_extension.rb and the second one into config/initializers/missing_translation_logger.rb.

Hope somebody’ll find this snippet useful.

Tomáš Pospíšek

Update 31.10.2012: Alain Lafon writes: “This is how I do it”:

$(document).ready(function() {
  $(".translation_missing").parent().css("border", "1px solid red");
});