Friday, September 15, 2017

Pagination, Search and Filter

Often times developers will implement a pagination to reduce the number of results.  However, it is always important to remember that pagination must be coupled with a search feature.  Otherwise, people lose one of the best capabilities that is available when all the results are available.

Today, I will add code based on https://www.w3schools.com/howto/howto_js_filter_table.asp and https://ebay.gitbooks.io/mindpatterns/content/navigation/pagination.html .


This design includes the following:

  • A function is provided to filter given the row from the table and the filter string
  • A label is added after the pagination to show which results are being displayed
  • Query parameters allowed for a filter string, page number to display and results per page
  • Disabled or hidden pagination elements when not applicable
  • The current page is always in the middle of the pagination module
  • The table holds the source of truth for the page and resultsPerPage attributes
  • The input holds the source of truth for the filter string
  • 5 numbers and 2 arrows are allowed in the pagination module

Saturday, July 23, 2016

Find longest sublist of distinct words

package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Assert;

public class LongestDistinctWords {
    public static void main(String[] args) {

        List<String> resultA = new LongestDistinctWords().occurences(new ArrayList<String>());
        System.err.println("resultA:"+resultA);
        Assert.assertEquals(resultA, Arrays.asList());
        
        List<String> resultB = new LongestDistinctWords().occurences(Arrays.asList("My","My","House","House","Time","Time","Time","Jeep","Jeep","Jeep","Jeep","Jeep","Jeep","Jeep","Jeep","Cat"));
        System.err.println("resultB:"+resultB);
        Assert.assertEquals(resultB, Arrays.asList("My","House"));
        
        List<String> resultC = new LongestDistinctWords().occurences(Arrays.asList("My","Test","My","My","Test","My","Hello","Dog","Hello"));
        System.err.println("resultC:"+resultC);
        Assert.assertEquals(resultC, Arrays.asList("Test""My""Hello""Dog"));
        
        List<String> resultD = new LongestDistinctWords().occurences(Arrays.asList("My","Test","My","Test","Hello","My","Test","Hello","Dog"));
        System.err.println("resultD:"+resultD);
        Assert.assertEquals(resultD, Arrays.asList("My","Test","Hello","Dog"));

        List<String> resultE = new LongestDistinctWords().occurences(Arrays.asList("My","My","And","My","And","My","Hi","How","Are","Hi","Yes","We"));
        System.err.println("resultE:"+resultE);
        Assert.assertEquals(resultE, Arrays.asList("And","My","Hi","How","Are"));

        List<String> resultF = new LongestDistinctWords().occurences(Arrays.asList("My","My","And","My","And","My","Hi","How","Are","Hi","My","We","Can","See"));
        System.err.println("resultF:"+resultF);
        Assert.assertEquals(resultF, Arrays.asList("How","Are","Hi","My","We","Can","See"));
    }
    
    /**
     * Find longest sublist of distinct words
     * @param words
     * @return
     */

    public List<String> occurences(List<String> words) {
        Integer longestStart = 0;
        Integer longestEnd = 0;
        Map<String, Integer> indexAfterWordLastSeenMap = new HashMap<String, Integer>();
        Integer currentStart = 0;
        Integer currentEnd = 0;
        for(String word: words) {
            Integer lastSeen = indexAfterWordLastSeenMap.get(word);
            if(lastSeen != null && lastSeen > currentStart) {
                if(currentEnd - currentStart > longestEnd - longestStart) {
                    longestStart = currentStart;
                    longestEnd = currentEnd;
                }
                currentStart = lastSeen;
            } 
            currentEnd++;
            indexAfterWordLastSeenMap.put(word, currentEnd);
        }
        if(currentEnd - currentStart > longestEnd - longestStart) {
            longestStart = currentStart;
            longestEnd = currentEnd;
        }
        return words.subList(longestStart, longestEnd);
    }
}

Parsing a list of words and searching for most common occurences

package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.junit.Assert;

public class KthOccurence {
    public static void main(String[] args) {

        List<String> resultA = new KthOccurence().occurences(4, new ArrayList<String>());
        System.err.println("resultA:"+resultA);
        Assert.assertEquals(resultA, Arrays.asList(nullnullnullnull));
        
        List<String> resultB = new KthOccurence().occurences(4, Arrays.asList("My","My","House","House","Time","Time","Time","Jeep","Jeep","Jeep","Jeep","Jeep","Jeep","Jeep","Jeep","Cat"));
        System.err.println("resultB:"+resultB);
        Assert.assertEquals(resultB, Arrays.asList("My","House","Time","Jeep"));
        
        List<String> resultC = new KthOccurence().occurences(1, Arrays.asList("My","Test","My","My","Test","My","Hello","Dog","Hello"));
        System.err.println("resultC:"+resultC);
        Assert.assertEquals(resultC, Arrays.asList("My"));
        
        List<String> resultD = new KthOccurence().occurences(2, Arrays.asList("My","Test","My","My","Test","My","Hello","Dog","Hello"));
        System.err.println("resultD:"+resultD);
        Assert.assertEquals(resultD, Arrays.asList("Hello","My"));

        List<String> resultE = new KthOccurence().occurences(3, Arrays.asList("My","Test","My","My","Test","My","Hello","Dog","Hello"));
        System.err.println("resultE:"+resultE);
        Assert.assertEquals(resultE, Arrays.asList("Test","Hello","My"));
    }
    
    /**
     * Example: Find the 50 most common words from a book
     * @param K - Number of distinct words to return with highest redundancy
     * @param words - List of words with repeated words
     * @return - Ordered list of highest repeated words
     */

    public List<String> occurences(Integer K, List<String> words) {
        Map<String, Integer> countMap = new HashMap<String, Integer>();
        
        LinkedList<String> trackedList = new LinkedList<String>(); // smallest to largest count in list
        for(int i=0; i<K; i++) {
            trackedList.add(null);
        }
        countMap.put(null, 0);

        for(String currentWord: words) {
            Integer currentCount = countMap.get(currentWord);
            if(currentCount == null) {
                currentCount = 1;
            } else {
                currentCount++;
            }
            countMap.put(currentWord, currentCount);
            
            ListIterator<String> iterator = trackedList.listIterator();
            while(iterator.hasNext()) { // O(K) to walk through linked list
                String nextIteration = iterator.next();
                
                if(currentCount < countMap.get(nextIteration)) { // If 
                    iterator.previous();
                    break;
                }
                
                if(currentWord.equals(nextIteration)) { // if come across word, remove it
                    iterator.remove(); // O(1) to remove from linked list
                }
            }
            // location of iterator is insertion point
            iterator.add(currentWord); // O(1) to add to linked list
            if(trackedList.size() > K) { // An insertion occurred without a remove
                trackedList.removeFirst(); // O(1) to remove first from linked list
            }
        }
        
        return trackedList;
    }
}

Tuesday, April 19, 2016

Hello World Javascript Extension for Chrome and Firefox

Developing a Chrome Extension

The folder structure will be as follows:
  • src
    • content
      • HelloWorld.js
      • rightClickMenuForGoogleChrome.js
    • manifest.json

HelloWorld.js

// Main function
HelloWorld=function() {
  alert('Hello World');
};

rightClickMenuForGoogleChrome.js

HelloWorldImportJS = "content/HelloWorld.js";

// To get all these menus to work, there are a few differences between Firefox and Chrome Extensions
// gContextMenu is defined when using Firefox extension and in this case, DocumentFunction should return gContextMenu.gContextMenu.target.ownerDocument instead of document

chrome.contextMenus.create({
  id: 'helloWorldTool',
  title: "Hello World Tool",
  contexts:["all"]
});
  chrome.contextMenus.create({
    id: 'helloWorld',
    parentId: 'helloWorldTool',
    title: "Run Hello World",
    contexts:["all"],
    onclick: function(info, tab){
      chrome.tabs.executeScript(tab.id, {file:HelloWorldImportJS}, function() {
        chrome.tabs.executeScript(tab.id, {code:"HelloWorld();"});
      });
    }
  });

manifest.json

{
  "manifest_version": 2,
  "name""Hello World Tool",
  "short_name""HWT",
  "description""Hello World Tool Description.",
  "version""1.0",
  "minimum_chrome_version""38",
  "permissions": [
    "contextMenus"
    "tabs",
    "http://*/*", 
    "https://*/*" ],

  "background": {
    "scripts": [
      "content/rightClickMenuForGoogleChrome.js"
    ]
  }
}

Chrome Web Store Publishing

Try It Out

  • Go to the link to the Published Extension and click "Add to Chrome"
  • Add to Chrome
  • Right click pages and test "Run Hello World"

Developing a Firefox Extension

The folder structure will be as follows:
  • src
    • content
      • HelloWorld.js
      • rightClickMenuForFirefox.xul
    • chrome.manifest
    • install.rdf

HelloWorld.js

See above.

rightClickMenuForFirefox.xul

<?xml version="1.0"?>
<overlay id="helloWorldToolOverlay"
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <statusbar id="status-bar">
        <statusbarpanel id="mypanel" label=""/>
    </statusbar>
    <script type="application/x-javascript" src="chrome://helloWorld/content/HelloWorld.js"/>
    // This is for the right click menu.
    <popup id="contentAreaContextMenu">
        <menuseparator id="helloWorldSeparator" insertafter="context-stop"/>  
        <menu id="helloWorldTool" label="Hello World Tool" insertafter="context-stop">            
            <menupopup> 
                <menuitem id="helloWorld" label="Run Hello World" oncommand="HelloWorld();"/> 
            </menupopup> 
        </menu>
    </popup>
</overlay>

chrome.manifest

content    helloWorld content/ contentaccessible=yes
overlay    chrome://browser/content/browser.xul    chrome://helloWorld/content/rightClickMenuForFirefox.xul

install.rdf

<?xml version="1.0"?>
<RDF:RDF xmlns:em="http://www.mozilla.org/2004/em-rdf#"
         xmlns:NC="http://home.netscape.com/NC-rdf#"
         xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  <RDF:Description RDF:about="urn:mozilla:install-manifest"
                   em:id="helloWorldTool@helloWorld.com"
                   em:version="1.0"
                   em:name="Hello World Tool"
                   em:type="2"
                   em:unpack="true"
                   em:description="Hello World Tool Description."
                   em:creator="scottizu@gmail.com"
                   em:homepageURL="http://www.ebay.com"
                   >
    <em:targetApplication RDF:resource="rdf:#$RI.6J3"/>
  </RDF:Description>
  <RDF:Description RDF:about="rdf:#$RI.6J3"
                   em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
                   em:minVersion="1.5"
                   em:maxVersion="45.*" />
</RDF:RDF>

Firefox Web Store Publishing

  • Zip content, chrome.manifest and install.rdf
  • Rename as "HelloWorldTool.Firefox.pre.xpi"
  • Login to https://addons.mozilla.org/en-US/developers/
  • Submit an Add-on
  • Choose File, HelloWorldTool.Firefox.pre.xpi, Upload
  • Category: Web Development, Mozilla Public License, version 2.0, Preliminary Review
If you want to distribute by yourself, you can install the extension.  Then go to the installation folder: (C:\Users\sizu\AppData\Roaming\Mozilla\Firefox\Profiles\2xrz9a7g.default-1451441818907\extensions\helloWorldTool@helloWorld.com ).  If it has a META-INF folder, this contains the digital signature for the Firefox Extension.  Zip the content, META-INF, chrome.manifest, install.rdf file and rename "HelloWorldTool.Firefox.xpi".  You can go to 'about:addons' in Firefox, click the settings wheel, Install Add on and select this file.  The extension will then show in 'about:addons'.

Try It Out

  • Go to the link to the Published Extension in Firefox and click Add to Firefox
    • https://addons.mozilla.org/en-US/developers/addon/hello-world-tool/versions/1850966
    • https://addons.mozilla.org/en-US/firefox/addon/hello-world-tool/
  • Add to Firefox
  • Right click pages and test "Run Hello World"

Thursday, January 14, 2016

Firefox and Chrome Extensions and Automatic Updates

https://developer.mozilla.org/en-US/docs/Extension_Versioning,_Update_and_Compatibility
https://developer.mozilla.org/en-US/Add-ons/Distribution
https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm
C:\Users\sizu\AppData\Roaming\npm\node_modules\jpm\bin\jpm
https://addons.mozilla.org/en-US/developers/addon/api/key/

TOPIC 1 - XPI SIGNATURE CREATION

To digitally sign the Firefox extension, you will need to get some Firefox credentials: JWT issuer, JWT secret.  These can be received after signing up by...

https://addons.mozilla.org/en-US/firefox/users/login?to=/en-US/developers/addon/api/key/ Tools->Manage API Keys->Generate New Credentials (JWT issuer, JWT secret)

 To create the .xpi file (extension file), you can do so with the jpm tool.  You should first download NPM, which you can use in Git Bash (needs to be downloaded too).

STEP 1: Then, you can run 'npm install jpm --global' in Git Bash.

STEP 2: After, you may create a package.json file using 'jpm init'.  After this is created, you should add additional fields beyond title, name, etc.  I added an id (@my_izu_extension), homepage, icon and main (picked a random js file in my content folder).

ERROR 1: I had an error with "Using existing install.rdf", since I had manually created this.  I just moved this into a backup folder after copying its contents to the package.json file, in the appropriate format.

ERROR 2: I had an Invalid addon ID.  You can use a GUID or any string with '@'.  I chose the later and used the ID '@my_izu_extension'.

STEP 3: Run 'jpm sign --api-key ${JWTissuer} --api-secret ${JWT secret}'.

Note: Here replace the ${xxx} with the credentials from the Firefox site (https://addons.mozilla.org/en-US/developers/addon/api/key/)

TOPIC 2 - AUTOMATIC UPDATES FOR FIREFOX EXTENSION

STEP 1: Firefox Updates over http.  Download McCoy from https://developer.mozilla.org/en-US/docs/Mozilla/Projects/McCoy.  Keys->Create New Key.  Right Click New Key->Copy Public Key.

STEP 2: This goes into the Firefox install.rdf file as updateKey. (put this in package JSON as updateKey, right along with id, title, name, etc).

Note: If using an install.rdf file, this can be done automatically with Extension->Add Key to Install Manifest and finding install.rdf file.

STEP 3:

To create an FirefoxUpdates.rdf file by copying it from here:
https://developer.mozilla.org/en-US/docs/Extension_Versioning,_Update_and_Compatibility

Delete the first <RDF:li> tag since you will use the second one which since the updateLink will be over http.  Change the id to match yours (mine was '@my_izu_extension').

Add an updateLink and updateInfoURL (these will need to be hosted somewhere).

You can generate the updateHash with openssl as follows 'openssl dgst -sha256 @my_izu_extension.xpi > updateHash.txt'

STEP 4:

This will run openssl and create a hash in the file updateHash.txt.  Something like this...

SHA256(my_izu_extension.xpi)= 2aefcd04c56f060bcfc53acfe96a87af120ed05933ab7969c91642847aa445df

Copy the hash and add it to the updateHash field but add the prefix 'sha256:'.  Something like this...

<em:updateHash>sha256:2aefcd04c56f060bcfc53acfe96a87af120ed05933ab7969c91642847aa445df</em:updateHash>

STEP 5: Then, add the updateHash into the FirefoxUpdates.rdf file by Update->Sign Update Manifest.

STEP 6: Upload the new @my_izu_extension.xpi file and FirefoxUpdates.rdf file appropriately.

RECAP.  Here's my setup.  I have a package.json with a my updateURL (pointing to where I will store the FirefoxUpdates.rdf file) and updateKey (generated by McCoy).  After adding these, I use jpm to create the @my_izu_extension.xpi file.

I create/modify the update.rdf file to include updateLink (pointing to where I will store the .xpi file).  I create a hash of the @my_izu_extension.xpi file (using openssl), then modify the updateHash field in FirefoxUpdates.rdf.  Finally, I digitally sign the FirefoxUpdates.rdf file using McCoy which adds the digital signature.

Last, I upload both the @my_izu_extension.xpi file and the FirefoxUpdates.rdf file to their appropriate locations.  I host them both in the same folder, both hosted by a Tomcat Server.

TOPIC 3 - AUTOMATIC UPDATES FOR GOOGLE CHROME EXTENSION

STEP 1: Modify the manifest.json file to add an update_url field right along side the name, description, etc.

STEP 2: Create an update.xml file like the one shown here: https://developer.chrome.com/extensions/autoupdate

I get the app id by using the chrome://extensions page, with Developer mode checked and use 'Load unpacked extension' which loads the extension and gives me the ID (aka appID).

STEP 3: Upload the update.xml file to where the update_url points.

Tuesday, January 12, 2016

Running Javascript in Firefox and Google Chrome

Suppose I want to run the printHelloWorldError function from this code in Firefox or Google Chrome. There are several ways to do it.

This code will add a div tag to the body tag of the page with the message 'Hello World'.

var err=function(e){
  var s=e.description;
  if(!s){
    s=String(e);
  }
  var d=DocumentFunction().createElement("div");
  d.id="print_err";
  d.innerHTML=s;
  d.style.color="red";
  DocumentFunction().body.appendChild(d);
};
var DocumentFunction;
var printHelloWorldError=function(){
  DocumentFunction = function() {
    return document;
  };
  err('HelloWorld');
};

Option 1 - From Firefox/Google Chrome Console

Edit the code above to add a line with this at the end: 'printHelloWorldError();' (don't include the single quotes).  Right click any page, Inspect (the element), Find the Console.  Paste the modified code in the console and hit Enter.  You should see the words 'Hello World' at the bottom of the page.

Option 2 - From the Firefox/Google Chrome Browser

Edit the code above to add a line with this at the beginning: 'javascript:' and this at the end 'printHelloWorldError();'.  Add it to Notepadd++.  Highlight the code and either drag it onto the Firefox address bar or right above the Google Chrome tab.

Option 3 - From the Firefox/Google Chrome Bookmark

If you drag and drop the edited code (with 'javascript:' at the beginning and 'printHelloWorldError();' at the end) into the Firefox address bar from Notepad++, it will reformat the Notepadd++ code into a single line like this:

javascript:var err=function(e){  var s=e.description;  if(!s){    s=String(e);  }  var d=DocumentFunction().createElement("div");  d.id="print_err";  d.innerHTML=s;  d.style.color="red";  DocumentFunction().body.appendChild(d);};var DocumentFunction;var printHelloWorldError=function(){  DocumentFunction = function() {    return document;  };  err('Hello World');};printHelloWorldError();

You can right click the Firefox Brower, show the Bookmark Toolbar, create a New Bookmark with the name 'Print Error' and for the location enter the above code.  Then, anytime you hit this bookmark, the code will execute.

In Google Chrome, Add a new bookmark by using 'Bookmark this page' from the hamburger menu.  Then, edit the bookmark and change the url to the code above (condensed one liner code with javascript: to indicate to run javascript code and printHelloWorldError(); to actually call the function).

Option 4a - From a Right Click Menu added through a Firefox Extension

Create an install.rdf file.

For other options like hompageURL, optionsURL, aboutURL, iconURL (ie em:iconURL="chrome://mypackage/content/myicon.png") which use the chrome.manifest file, see developer.mozilla.org

<?xml version="1.0"?>
<RDF:RDF xmlns:em="http://www.mozilla.org/2004/em-rdf#"
         xmlns:NC="http://home.netscape.com/NC-rdf#"
         xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

  <RDF:Description RDF:about="urn:mozilla:install-manifest"
                   em:id="scottizu@gmail.com"
                   em:version="0.1"
                   em:name="Print Error"
                   em:unpack="true"
                   em:description="Prints an error on the page."
                   em:creator="scottizu">
    <em:targetApplication RDF:resource="rdf:#$RI.6J3"/>
  </RDF:Description>
    <RDF:Description RDF:about="rdf:#$RI.6J3"
                   em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
                   em:minVersion="1.5"
                   em:maxVersion="*.*" />
</RDF:RDF>


Note: The ID needs to either be an e-mail address or a GUID.  See link above for more details.

Create a chrome.manifest file.

content mypackage mycontent/ contentaccessible=yes
overlay chrome://browser/content/browser.xul chrome://mypackage/content/rightClickMenuForFirefox.xul

Create a folder called mycontent.  In it, create a file called rightClickMenuForFirefox.xul

<?xml version="1.0"?>
<overlay id="myoverlay"
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  
    <script type="application/x-javascript" src="chrome://mypackage/content/printError.js"/>
    
    // This is for the right click menu.
    <popup id="contentAreaContextMenu">
        <menuitem id="printError" label="Print Error" insertafter="context-stop" oncommand="printHelloWorldErrorForRightClick();"/>
    </popup>
</overlay>


Modify the printError.js file to add a method printHelloWorldErrorForRightClick.  The challenge in the right click menu for Firefox and Chrome is getting access to the document for the page.  This is why there is a function named DocumentFunction whose job is to return the document for the page.  This way, we can see the change on the web page we are looking at.


var err=function(e){
  var s=e.description;
  if(!s){
    s=String(e);
  }
  var d=DocumentFunction().createElement("div");
  d.id="print_err";
  d.innerHTML=s;
  d.style.color="red";
  DocumentFunction().body.appendChild(d);
};
var DocumentFunction;
var printHelloWorldError=function(){
  DocumentFunction = function() {
    return document;
  };
  err('Hello World');
};
var printHelloWorldErrorForRightClick=function(){
  DocumentFunction = function() {
    return gContextMenu.target.ownerDocument;
  };
  err('Hello World (RC)');
};

Here is the file structure.

- install.rdf
- chrome.manifest
- mycontent
   - rightClickMenuForFirefox.xul
   - printError.js

Highlight, install.rdf, chrome.manifest, mycontent, right click, send to, Compressed (zipped) folder.  Rename the new file as RightClickMenuForFirefox.xpi.  Go to Firefox 'about:config', 'I'll be careful, I promise', search for xpinstall.signatures.required, set to false so the new extension won't need signing.  Go to Firefox address bar and type 'about:addons', click Extensions and drag the file RightClickMenuForFirefox.xpi on this page.  Firefox will install this unsigned Extension, restart.  From there, you should be able to right click any page and select 'Print Error'.

There are many other things that you can do with the Firefox Extension such as adding an icon, adding a skin, etc.

You can also configure menus as well as menu items.  Just add something like this with appropriate closing menu and menupopup closing tags.

 <menu id="mymenu" label="Error Menu" insertafter="context-stop">            
            <menupopup>
                                   
                    <menu id="Error Sub Menu" label="Print Error Menu">
                        <menupopup>
                            <menuitem id="printError1" label="Print Error 1" oncommand="printHelloWorldErrorForRightClick();"/>
                            <menuitem id="printError2" label="Print Error 2" oncommand="printHelloWorldErrorForRightClick2();"/>

Option 4b - From a Right Click Menu added through a Google Chrome Extension

In the mycontent folder, create a file called manifest.json

Note: I debated whether to store this in the same directory as install.rdf, but the Chrome packager uses a folder, which in this case will be mycontent, so that the .crx file created will be at the same level as install.rdf.  This is unfortunate and the only difference is that the scripts value would be mycontent/rightClickMenuForGoogleChrome.js instead of rightClickMenuForGoogleChrome.js and execute script command would have to have mycontent/printError.js instead of printError.js if the manifest.json was up one level.

{
  "manifest_version": 2,
  "name""Print Error",
  "description""Prints an error on the page.",
  "version""0.1",
  "minimum_chrome_version""38",
  "permissions": [
    "contextMenus"
    "tabs",
    "http://*/*", 
    "https://*/*" ],

  "background": {
    "scripts": [
      "rightClickMenuForGoogleChrome.js"
    ]
  }
}


Create a file rightClickMenuForGoogleChrome.js

printErrorMenu = function(info, tab){
  chrome.tabs.executeScript(tab.id, {file:"printError.js"}, function() {
    chrome.tabs.executeScript(tab.id, {code:"printHelloWorldError();"});
  });
};

chrome.contextMenus.create({
  id: 'printError',
  title: "Print Error",
  contexts:["all"],
  onclick: printErrorMenu
});

Here is the file structure.
- mycontent
   - rightClickMenuForGoogleChrome.js
   - printError.js
   - manifest.json

Go to Google Chrome, in address bar type 'chrome://extensions', select Developer mode, Load unpacked extension, select the mycontent folder.

You can also package with the Pack extension (Developer mode must be checked).  Browse to mycontent folder as extension root directory (leave private key field empty).  This will create a .crx file and .pem file.  The .pem file is a private key file but is not needed if the field was left empty.  Later, you can drag and drop this .crx file directly onto the 'chrome://extensions' page.

You can also add other menu options to run more code.  Just make sure the appropriate onclick methods are defined.

chrome.contextMenus.create({
  id: 'parentMenu',
  title: "Error Menu",
  contexts:["all"]
});
chrome.contextMenus.create({
  id: 'printError1',
  parentId: 'parentMenu',
  title: "Print Error 1",
  contexts:["all"],
  onclick: printErrorMenu
});
chrome.contextMenus.create({
  id: 'printError2',
  parentId: 'parentMenu',
  title: "Print Error 2",
  contexts:["all"],
  onclick: printErrorMenu2
});

Sunday, January 3, 2016

Field Programmable Gate Arrays and Other Space Tech Initiatives

I am reading the book "Elon Musk" a biography and several things hit me well. One is that our industrial might has long since been gone from the 1940's. As such, I went to New Mexico attracted to strengthening that industrial might.

Also, our talented engineers are focused rather than solving world problems, on making money, often drawn to software and financial industries.

Here are some posting based on reconfiguring satellites in space, based on small payloads rather than large payloads.

Unfortunately, my experience with the industry is that a person could wait 7 years to launch their work, and their work might be part of phase 12 of 17. If phase 1, failed or the launch failed, that person would have to wait another 7 years for a next launch. Elon Musk seems to be determined to bring the agility of Silicon Valley to the aerospace industry. A noble quest.

I also saw a large amount of fluff, with no substantial technology behind it, which was a turn off to this industry. Real break throughs and transparency are important to me.

Abstract
Implementing Data Reduction Techniques in Recon…gurable Computing Platforms
Orbital Mechanics
Polarization

As far as solar technologies, while at ITT, in 2008, I worked with peers to create a proposal for a Broad Agency Announcement (BAA). We created a satellite design exploring capabilities of hybrid power systems involving solar power and electromagnetic tethers. We proposed methods for propelling the satellite using electromagenetic and momentum tether configurations to avoid the need for rocket fuel.