<commit_before>// Import the page's CSS. Webpack will know what to do with it.
import "../stylesheets/app.css";
import "../stylesheets/bootstrap-grid.css";
// Import libraries we need.
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
import { SHA256 } from "../javascripts/asmcrypto.js";

// Import our contract artifacts and turn them into usable abstractions.
import chainsign_artifacts from '../../build/contracts/ChainSign.json'
import materai_artifacts from '../../build/contracts/DigitalMaterai.json'

// MetaCoin is our usable abstraction, which we'll use through the code below.
var ChainSign = contract(chainsign_artifacts);
var DigitalMaterai = contract(materai_artifacts);

// The following code is simple to show off interacting with your contracts.
// As your needs grow you will likely need to change its form and structure.
// For application bootstrapping, check out window.addEventListener below.
var accounts;
var account;
var file_hash;
var owner_info;
var use_materai;
var materai_amount;
var address_token_amount;

window.App = {
  start: function() {
    var self = this;
    ChainSign.setProvider(web3.currentProvider);
    DigitalMaterai.setProvider(web3.currentProvider);

    // Get the initial account balance so it can be displayed.
    web3.eth.getAccounts(function(err, accs) {
      if (err != null) {
        alert("There was an error fetching your accounts.");
        return;
      }

      if (accs.length == 0) {
        alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
        return;
      }

      var addresses = document.getElementById("addresses");
      var index = 0;
      accs.forEach(function(acc){
        var option = document.createElement("option");
        option.value= index;
        option.innerHTML = acc;

        addresses.appendChild(option);
        index++;
      });

      accounts = accs;
      account = accounts[0];

      document.getElementById('form1').reset();
      document.getElementById('by_address').value ='';

      self.refresh_balance();

      //CLEANING UP NEEDED
      function handleFile(){
        var f = document.getElementById("file").files[0];

        if (f) {
          var r = new FileReader();
          r.onload = function(e) {
            var hash_info = document.getElementById('hash_info');
            var contents = e.target.result;
            hash_info.value = "generating document hash..."
            file_hash = "0x" + SHA256.hex(contents);
            //alert(contents);
            self.show_doc_info();
          }

        r.readAsArrayBuffer(f);
        }
      }

      function changeAddress(){
        var f = document.getElementById("addresses").value;

        account = accounts[f];
        alert("Account changed to: \n" + account);

        self.refresh_balance();
      }

      document.getElementById('file').addEventListener('change', handleFile, false);
      document.getElementById('addresses').addEventListener('change', changeAddress, false);
    });
  },

  transfer_materai: function(){
    var self = this;
    var target_address = document.getElementById("target_address").value;
    var amount = document.getElementById("amount").value * 1e+18;
    DigitalMaterai.deployed().then(function(instance) {
      return instance.transfer(target_address, amount, {from: account});
    }).then(function(value) {
      self.refresh_balance();
      document.getElementById("transfer_status").innerHTML = "transfer success"
    }).catch(function(e) {
      console.log(e)
      document.getElementById("transfer_status").innerHTML = "transfer failed"
    });
  },

  mint_token: function(){
    var self = this;

    DigitalMaterai.deployed().then(function(instance) {
      return instance.mintToken(account, 1000000*1e+18, {from: account});
    }).then(function(value) {
      self.refresh_balance();
    }).catch(function(e) {
      console.log(e)
      alert("not authorized!")
    });
  },

  refresh_balance: function(){
    DigitalMaterai.deployed().then(function(instance) {
      return instance.balanceOf.call(account, {from: account});
    }).then(function(value) {
      document.getElementById("balance").innerHTML = "Materai Owned = Rp" + value.valueOf()/1e+18;
    }).catch(function(e) {
      console.log(e)
    });
  },

  show_doc_info: function(){
    var self = this;
    self.show_doc_hash();
    self.show_doc_owner();
    self.show_doc_registrant();
    self.show_doc_signed();
    self.show_doc_stamped();
  },

  show_doc_owner: function(){
    var self = this;
    var owner_info = document.getElementById('owner_info');
    var target_address = document.getElementById('target_address');
    var transfer_status = document.getElementById('transfer_status');
    ChainSign.deployed().then(function(instance) {
      return instance.get_owner.call(file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() == 0){
        owner_info.value = 'none'
      } else {
        owner_info.value = value.valueOf();
      }

      if(account == owner_info.value){
        target_address.readOnly = false;
        transfer_status.innerHTML = "You can transfer the ownership of this document."
      } else {
        target_address.readOnly = true;
        transfer_status.innerHTML = "You must own the document to transfer its ownership."
      }
    }).catch(function(e) {
      console.log(e);
      owner_info.value = 'error';
    });
  },

  show_doc_registrant: function(){
    var self = this;
    var registrant_info = document.getElementById('registrant_info');
    ChainSign.deployed().then(function(instance) {
      return instance.get_registrant.call(file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() == 0){
        registrant_info.value = 'none'
      } else {
        registrant_info.value = value.valueOf();
      }
    }).catch(function(e) {
      console.log(e);
      registrant_info.value = 'error';
    });
  },

  show_doc_hash: function(){
    var self = this;
    var hash_info = document.getElementById('hash_info');
    hash_info.value = file_hash;
  },

  set_html_doc_status: function(message){
    doc_status = document.getElementById('doc_status');
    doc_status.innerHTML = message;
  },

  show_doc_signed: function(){
    var self = this;
    ChainSign.deployed().then(function(instance) {
      return instance.get_signature_block.call(account, file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() != 0){
        self.set_html_doc_status('You have signed this document at block ' + value.valueOf() + "");
      } else {
        self.set_html_doc_status('You never signed this document.');
      }
    }).catch(function(e) {
      console.log(e);
      self.set_html_doc_status("error");
    });
  },

  show_doc_stamped: function(){
    DigitalMaterai.deployed().then(function(instance) {
      return instance.readStamped.call(file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() != 0){
        document.getElementById('stamped_status').innerHTML = "stamped with materai Rp" + value.valueOf()/1e+18;
      } else {
        document.getElementById('stamped_status').innerHTML = "";
      }
    }).catch(function(e) {
      console.log(e);
      alert("error");
    });
  },

  sign: function(){
    var self = this;
    if(use_materai){
      self.stamp_document();
    }
    self.sign_doc();
  },

  stamp_document: function(){
    var self = this;
    var amount = materai_amount*1e+18;
    DigitalMaterai.deployed().then(function(instance) {
      return instance.stampDocument(file_hash, amount, {from: account});
    }).then(function(value) {
      self.refresh_balance();
      alert("stamping success");
    }).catch(function(e) {
      console.log(e);
      alert("stamping failed");
    });
  },

  sign_doc: function(){
    var self = this;

    ChainSign.deployed().then(function(instance) {
      self.set_html_doc_status("signing...");
      return instance.sign(file_hash, {from: account});
    }).then(function(value) {
      self.show_doc_info();
      alert("signature recorded at: " + value.valueOf().tx);
    }).catch(function(e) {
      console.log(e);
      self.set_html_doc_status("err:

This address might have been signed this document before.
Click `refresh` to see which block");
    });
  },

  transfer_ownership: function(){
    var self = this;
    var target_address = document.getElementById('target_address');
    var transfer_status = document.getElementById('transfer_status');

    ChainSign.deployed().then(function(instance) {
      transfer_status.innerHTML = "transferring...";
      return instance.transfer_ownership(file_hash, target_address.value, {from: account});
    }).then(function(value) {
      self.show_doc_info();
      target_address.value = '';
      alert("transfer success, tx receipt:\n " + value.valueOf().tx);
    }).catch(function(e) {
      console.log(e);
      target_address.value = '';
      transfer_status.innerHTML = "err:

You must own the document to transfer its ownership.";
    });
  },

  verify_doc: function(){
    var self = this;
    var verify_status = document.getElementById('verify_status');
    var target_address = document.getElementById('by_address').value; //TODO: validate input

    ChainSign.deployed().then(function(instance) {
      verify_status.innerHTML = "verifying..."
      return instance.get_signature_block.call(target_address, file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() != 0){
        verify_status.innerHTML = 'This address signed this document at block ' + value.valueOf() + ".";
      } else {
        verify_status.innerHTML = 'This address never signed this document before.';
      }
    }).catch(function(e) {
      console.log(e);
      verify_status.innerHTML = 'error';
    });
  },

  copy_address: function(){
    var value = accounts[document.getElementById("addresses").value];

    var tempInput = document.createElement("input");
    tempInput.style = "position: absolute; left: -1000px; top: -1000px";
    tempInput.value = value;
    document.body.appendChild(tempInput);
    tempInput.select();
    document.execCommand("copy");
    document.body.removeChild(tempInput);
  },

  show_hide_materai: function(){
    var f = document.getElementById('use_materai').checked;
    var g = document.getElementById('materai').value;
    if(f){
      document.getElementById('materai').style.display = 'block';
      materai_amount = g;
      console.log(materai_amount);
    } else {
      document.getElementById('materai').style.display = 'none';
    }
    use_materai = f;
  },

  change_materai_amount: function(){
    materai_amount = document.getElementById('materai').value;
    console.log(materai_amount);
  }
};

window.addEventListener('load', function() {
  // Checking if Web3 has been injected by the browser (Mist/MetaMask)
  if (typeof web3 !== 'undefined') {
    console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
    // Use Mist/MetaMask's provider
    window.web3 = new Web3(web3.currentProvider);
  } else {

    console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
  }

  App.start();
});
<commit_msg>doc_status var<commit_after>// Import the page's CSS. Webpack will know what to do with it.
import "../stylesheets/app.css";
import "../stylesheets/bootstrap-grid.css";
// Import libraries we need.
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
import { SHA256 } from "../javascripts/asmcrypto.js";

// Import our contract artifacts and turn them into usable abstractions.
import chainsign_artifacts from '../../build/contracts/ChainSign.json'
import materai_artifacts from '../../build/contracts/DigitalMaterai.json'

// MetaCoin is our usable abstraction, which we'll use through the code below.
var ChainSign = contract(chainsign_artifacts);
var DigitalMaterai = contract(materai_artifacts);

// The following code is simple to show off interacting with your contracts.
// As your needs grow you will likely need to change its form and structure.
// For application bootstrapping, check out window.addEventListener below.
var accounts;
var account;
var file_hash;
var owner_info;
var use_materai;
var materai_amount;
var address_token_amount;

window.App = {
  start: function() {
    var self = this;
    ChainSign.setProvider(web3.currentProvider);
    DigitalMaterai.setProvider(web3.currentProvider);

    // Get the initial account balance so it can be displayed.
    web3.eth.getAccounts(function(err, accs) {
      if (err != null) {
        alert("There was an error fetching your accounts.");
        return;
      }

      if (accs.length == 0) {
        alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
        return;
      }

      var addresses = document.getElementById("addresses");
      var index = 0;
      accs.forEach(function(acc){
        var option = document.createElement("option");
        option.value= index;
        option.innerHTML = acc;

        addresses.appendChild(option);
        index++;
      });

      accounts = accs;
      account = accounts[0];

      document.getElementById('form1').reset();
      document.getElementById('by_address').value ='';

      self.refresh_balance();

      //CLEANING UP NEEDED
      function handleFile(){
        var f = document.getElementById("file").files[0];

        if (f) {
          var r = new FileReader();
          r.onload = function(e) {
            var hash_info = document.getElementById('hash_info');
            var contents = e.target.result;
            hash_info.value = "generating document hash..."
            file_hash = "0x" + SHA256.hex(contents);
            //alert(contents);
            self.show_doc_info();
          }

        r.readAsArrayBuffer(f);
        }
      }

      function changeAddress(){
        var f = document.getElementById("addresses").value;

        account = accounts[f];
        alert("Account changed to: \n" + account);

        self.refresh_balance();
      }

      document.getElementById('file').addEventListener('change', handleFile, false);
      document.getElementById('addresses').addEventListener('change', changeAddress, false);
    });
  },

  transfer_materai: function(){
    var self = this;
    var target_address = document.getElementById("target_address").value;
    var amount = document.getElementById("amount").value * 1e+18;
    DigitalMaterai.deployed().then(function(instance) {
      return instance.transfer(target_address, amount, {from: account});
    }).then(function(value) {
      self.refresh_balance();
      document.getElementById("transfer_status").innerHTML = "transfer success"
    }).catch(function(e) {
      console.log(e)
      document.getElementById("transfer_status").innerHTML = "transfer failed"
    });
  },

  mint_token: function(){
    var self = this;

    DigitalMaterai.deployed().then(function(instance) {
      return instance.mintToken(account, 1000000*1e+18, {from: account});
    }).then(function(value) {
      self.refresh_balance();
    }).catch(function(e) {
      console.log(e)
      alert("not authorized!")
    });
  },

  refresh_balance: function(){
    DigitalMaterai.deployed().then(function(instance) {
      return instance.balanceOf.call(account, {from: account});
    }).then(function(value) {
      document.getElementById("balance").innerHTML = "Materai Owned = Rp" + value.valueOf()/1e+18;
    }).catch(function(e) {
      console.log(e)
    });
  },

  show_doc_info: function(){
    var self = this;
    self.show_doc_hash();
    self.show_doc_owner();
    self.show_doc_registrant();
    self.show_doc_signed();
    self.show_doc_stamped();
  },

  show_doc_owner: function(){
    var self = this;
    var owner_info = document.getElementById('owner_info');
    var target_address = document.getElementById('target_address');
    var transfer_status = document.getElementById('transfer_status');
    ChainSign.deployed().then(function(instance) {
      return instance.get_owner.call(file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() == 0){
        owner_info.value = 'none'
      } else {
        owner_info.value = value.valueOf();
      }

      if(account == owner_info.value){
        target_address.readOnly = false;
        transfer_status.innerHTML = "You can transfer the ownership of this document."
      } else {
        target_address.readOnly = true;
        transfer_status.innerHTML = "You must own the document to transfer its ownership."
      }
    }).catch(function(e) {
      console.log(e);
      owner_info.value = 'error';
    });
  },

  show_doc_registrant: function(){
    var self = this;
    var registrant_info = document.getElementById('registrant_info');
    ChainSign.deployed().then(function(instance) {
      return instance.get_registrant.call(file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() == 0){
        registrant_info.value = 'none'
      } else {
        registrant_info.value = value.valueOf();
      }
    }).catch(function(e) {
      console.log(e);
      registrant_info.value = 'error';
    });
  },

  show_doc_hash: function(){
    var self = this;
    var hash_info = document.getElementById('hash_info');
    hash_info.value = file_hash;
  },

  set_html_doc_status: function(message){
    var doc_status = document.getElementById("doc_status");
    doc_status.innerHTML = message;
  },

  show_doc_signed: function(){
    var self = this;
    ChainSign.deployed().then(function(instance) {
      return instance.get_signature_block.call(account, file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() != 0){
        self.set_html_doc_status('You have signed this document at block ' + value.valueOf() + "");
      } else {
        self.set_html_doc_status('You never signed this document.');
      }
    }).catch(function(e) {
      console.log(e);
      self.set_html_doc_status("error");
    });
  },

  show_doc_stamped: function(){
    DigitalMaterai.deployed().then(function(instance) {
      return instance.readStamped.call(file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() != 0){
        document.getElementById('stamped_status').innerHTML = "stamped with materai Rp" + value.valueOf()/1e+18;
      } else {
        document.getElementById('stamped_status').innerHTML = "";
      }
    }).catch(function(e) {
      console.log(e);
      alert("error");
    });
  },

  sign: function(){
    var self = this;
    if(use_materai){
      self.stamp_document();
    }
    self.sign_doc();
  },

  stamp_document: function(){
    var self = this;
    var amount = materai_amount*1e+18;
    DigitalMaterai.deployed().then(function(instance) {
      return instance.stampDocument(file_hash, amount, {from: account});
    }).then(function(value) {
      self.refresh_balance();
      alert("stamping success");
    }).catch(function(e) {
      console.log(e);
      alert("stamping failed");
    });
  },

  sign_doc: function(){
    var self = this;

    ChainSign.deployed().then(function(instance) {
      self.set_html_doc_status("signing...");
      return instance.sign(file_hash, {from: account});
    }).then(function(value) {
      self.show_doc_info();
      alert("signature recorded at: " + value.valueOf().tx);
    }).catch(function(e) {
      console.log(e);
      self.set_html_doc_status("err:

This address might have been signed this document before.
Click `refresh` to see which block");
    });
  },

  transfer_ownership: function(){
    var self = this;
    var target_address = document.getElementById('target_address');
    var transfer_status = document.getElementById('transfer_status');

    ChainSign.deployed().then(function(instance) {
      transfer_status.innerHTML = "transferring...";
      return instance.transfer_ownership(file_hash, target_address.value, {from: account});
    }).then(function(value) {
      self.show_doc_info();
      target_address.value = '';
      alert("transfer success, tx receipt:\n " + value.valueOf().tx);
    }).catch(function(e) {
      console.log(e);
      target_address.value = '';
      transfer_status.innerHTML = "err:

You must own the document to transfer its ownership.";
    });
  },

  verify_doc: function(){
    var self = this;
    var verify_status = document.getElementById('verify_status');
    var target_address = document.getElementById('by_address').value; //TODO: validate input

    ChainSign.deployed().then(function(instance) {
      verify_status.innerHTML = "verifying..."
      return instance.get_signature_block.call(target_address, file_hash, {from: account});
    }).then(function(value) {
      if(value.valueOf() != 0){
        verify_status.innerHTML = 'This address signed this document at block ' + value.valueOf() + ".";
      } else {
        verify_status.innerHTML = 'This address never signed this document before.';
      }
    }).catch(function(e) {
      console.log(e);
      verify_status.innerHTML = 'error';
    });
  },

  copy_address: function(){
    var value = accounts[document.getElementById("addresses").value];

    var tempInput = document.createElement("input");
    tempInput.style = "position: absolute; left: -1000px; top: -1000px";
    tempInput.value = value;
    document.body.appendChild(tempInput);
    tempInput.select();
    document.execCommand("copy");
    document.body.removeChild(tempInput);
  },

  show_hide_materai: function(){
    var f = document.getElementById('use_materai').checked;
    var g = document.getElementById('materai').value;
    if(f){
      document.getElementById('materai').style.display = 'block';
      materai_amount = g;
      console.log(materai_amount);
    } else {
      document.getElementById('materai').style.display = 'none';
    }
    use_materai = f;
  },

  change_materai_amount: function(){
    materai_amount = document.getElementById('materai').value;
    console.log(materai_amount);
  }
};

window.addEventListener('load', function() {
  // Checking if Web3 has been injected by the browser (Mist/MetaMask)
  if (typeof web3 !== 'undefined') {
    console.warn("Using web3 detected from external source. If you find that your accounts don't appear or you have 0 MetaCoin, ensure you've configured that source properly. If using MetaMask, see the following link. Feel free to delete this warning. :) http://truffleframework.com/tutorials/truffle-and-metamask")
    // Use Mist/MetaMask's provider
    window.web3 = new Web3(web3.currentProvider);
  } else {

    console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
  }

  App.start();
});
<|endoftext|>


<commit_before>/*global OJ:true,$:true*/
(function () {

    OJ.makeSubNameSpace('node');

    OJ.node.lift('wrapper', function (OjNode, DomEl, options) {
            'use strict';
        if(!(OjNode && true === OjNode.isValid)) { //Don't try to wrap the same OjNode twice
            var OjInternal = {
                data: {},
                enabled: true,
                isValid: false
            };
            OjNode = OjNode || Object.create({ 0: null, $: $({}), isValid: false });

            (function _initConstructor() {
                //Validate and setup our Node instance
                if (OjNode[0] instanceof HTMLElement &&
                    OJ.is.jQuery(OjNode.$)) {
                    OjInternal.isValid = true;
                }
                else if (OJ.is.jQuery(DomEl)) {
                    Object.defineProperty(OjNode, '$', {
                        value: DomEl
                    });
                    Object.defineProperty(OjNode, '0', {
                        value: DomEl[0]
                    });
                    OjInternal.isValid = true;
                }
                else if (DomEl instanceof HTMLElement) {
                    Object.defineProperty(OjNode, '0', {
                        value: DomEl
                    });
                    Object.defineProperty(OjNode, '$', {
                        value: $('#' + DomEl.id)
                    });
                    OjInternal.isValid = true;
                } else {
                    OjInternal.isValid = false;
                    //No reason to continue. There is no juice to be had here.
                    throw new Error('Cannot make OJ without citrus fruit! OJ.node.wrapper was handed an invalid DOM handle.');
                }
            }()); //end initConstructor

            // No technical need to sequester the code in this way,
            // but it feels more readable in these blocks
            (function _postConstructor(){
                //We have a valid OjNode, let's build it out.
                Object.defineProperty(OjNode, 'isValid', {
                        value: OjInternal.isValid
                    });

                Object.defineProperty(OjNode, 'tagName', {
                    value: OjNode[0].tagName
                });

                Object.defineProperty(OjNode, 'childNodes', {
                        value: [],
                        writable: true
                    });

                // Keep this method safely enveloped in the closure.
                var buildChildNode = function(node, $element) {
                    node = node || Object.create(null);
                    // root and parent are safe assumptions
                    Object.defineProperty(node, 'root', {value: OjNode.root});
                    Object.defineProperty(node, 'parent', {value: OjNode });
                    if (OJ.is.jQuery($element)) {
                        // this is a valid child
                        Object.defineProperty(node, '$', {value: $element});
                        Object.defineProperty(node, '0', {value: $element[0]});

                    }
                    // Extend the child with the wrapper methods around itself
                    return  OJ.node.wrapper(node);
                };

                Object.defineProperty(OjInternal, 'chainChildNode', { value: function ($child) {
                    var newNode = Object.create(null);
                    buildChildNode(newNode, $child);
                    OjNode.childNodes.push(newNode);
                    return newNode;
                }});

                Object.defineProperty(OjInternal, 'wrapChildNode', { value: function ($child) {
                    var newNode = Object.create(null);
                    return buildChildNode(newNode, $child);
                }});

                /**
                 * Whether or no we have removed the node internally.
                 * This doesn't actually test the DOM,
                 * only our in-memory representation of the DOM.
                */
                Object.defineProperty(OjInternal, 'isNodeAlive', { value: function () {
                    return false === OJ.is.nullOrEmpty(OjNode);
                }});
            }());

            //Define some internal data methods
            Object.defineProperty(OjInternal, 'getDataProp', { value: function (propName) {
                var ret = null;
                if (OjInternal.isNodeAlive() &&
                    false === OJ.is.stringNullOrEmpty(propName)) {

                    if (OjNode[0] && OjNode[0].dataset && OjNode[0].dataset[propName]) {
                        ret = OjNode[0].dataset.propName;
                    }
                    if (OJ.is.stringNullOrEmpty(ret)) {
                        ret = OjInternal.data[propName] ||
                            OjNode.$.data(propName) ||
                            OJ.localStorage.getItem(propName + '_control_data_' + OjNode.getId());
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjInternal, 'setDataProp', { value: function (propName, value) {
                var ret = null;
                if (OjInternal.isNodeAlive() &&
                    false === OJ.is.stringNullOrEmpty(propName)) {
                    ret = value;
                    if (OjNode[0] && OjNode[0].dataset) {
                        OjNode[0].dataset[propName] = value;

                        OjInternal.data[propName] = value;
                    } else {
                        OjInternal.data[propName] = value;
                        OjNode.$.data(propName, value);
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjInternal, 'setDataProperties', { value: function (obj) {
                if(obj && Object.keys(obj)) {
                    Object.keys(obj).forEach(function (key, val) {
                        OjInternal.setDataProp(key, val);
                    });
                }
            }});

            /**
              OJ doesn't need many jQuery selectors,
              but when it does they are sequestered on this property to "try" to avoid confusion.
            */
            var el = Object.create(null);

            Object.defineProperty(el, 'children', {value: function (searchTerm, selector) {
                var ret = [];
                if (OjInternal.isNodeAlive()) {
                    var $children = OjNode.$.children(OJ.to.string(searchTerm), OJ.to.string(selector));
                    if($children) {
                        $children.each(function() {
                            var $child = $(this);
                            ret.push(OjInternal.chainChildNode($child));
                        });
                    }
                }
                return ret;
            }});

            Object.defineProperty(el, 'filter', { value: function (selector) {
                var ret = [];
                if (selector && OjInternal.isNodeAlive()) {
                    var $children = OjNode.$.filter(selector);
                    if($children.length > 0) {
                        $children.each(function() {
                            var $child = $(this);
                            ret.push(OjInternal.wrapChildNode($child));
                        });
                    }
                }
                return ret;
            }});

            Object.defineProperty(el, 'find', { value: function (selector) {
                var ret = [];
                if (selector && OjInternal.isNodeAlive()) {
                    var $children = OjNode.$.find(selector);
                    if($children.length > 0) {
                        $children.each(function() {
                            var $child = $(this);
                            ret.push(OjInternal.wrapChildNode($child));
                        });
                    }
                }
                return ret;
            }});

            Object.defineProperty(el, 'first', { value: function () {
                var ret = OjNode.childNodes[0] || OjNode.el.children[0];
                return ret;
            }});

            Object.defineProperty(el, 'parent', { value: function () {
                var ret = {};
                if (OjInternal.isNodeAlive()) {
                    var $parent = OjNode.$.parent();

                    if (false === OJ.is.nullOrEmpty($parent) && $parent.length > 0) {
                        ret = OJ.dom.nodeWrapper({}, $parent);
                    }
                }
                return ret;
            }});

            /**
                OJ implements these wrappers around jQuery methods to provide better chaining on OJ Nodes,
                as well as to make it easy to swap out the DOM framework without having to change the interfaces
            */
            Object.defineProperty(OjNode, 'addClass', { value: function (name) {
                if (name && OjInternal.isNodeAlive()) {
                    OjNode.$.addClass(name);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'append', { value: function (object) {
                var ret = OjNode;
                if (object && OjInternal.isNodeAlive()) {
                    OJ.tryThisThenThat(function _first() {
                        OjNode.$.append(object);
                        ret = OjInternal.chainChildNode(object);
                    }, function _second() {
                        //Probably attempted to append a string which matched a selector (e.g. 'a')
                        //which will attempt to (and fail to) append all <a> nodes to this one.
                        if (OJ.is.string(object)) {
                            OjNode.text(object);
                        }
                    });
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'attr', { value: function (name, value) {
                var ret = null;
                if (name && OjInternal.isNodeAlive()) {
                    ret = OjNode;

                    if(OJ.is.plainObject(name)) {
                        OjNode.$.attr(name);
                    } else  if(arguments.length === 1) {
                        ret = OjNode.$.attr(name);
                    } else {
                        OjNode.$.attr(name, value);
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'attach', { value: function (object) {
                var $child = null, ret;
                if (object && OjInternal.isNodeAlive()) {
                    OJ.tryThisThenThat(function _first() {
                        $child = $(object);
                        if (false === OJ.is.nullOrEmpty($child)) {
                            OjNode.append($child);
                            ret = OjInternal.chainChildNode($child);
                        }
                    }, function _second() {

                    });
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'bind', {value : function (eventName, event) {
                if (eventName && OjInternal.isNodeAlive()) {
                    OjNode.$.on(eventName, event);
                }
                return OjNode;
            }});
            Object.defineProperty(OjNode, 'on', {value : OJ.bind });

            Object.defineProperty(OjNode, 'clickOnEnter', {value: function (anOjNode) {
                if (anOjNode &&  OjInternal.isNodeAlive()) {
                    OjNode.$.clickOnEnter(anOjNode.$);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'css', { value: function (param1, param2) {
                var ret = OjNode;
                if (param1 && OjInternal.isNodeAlive()) {
                    if (OJ.is.plainObject(param1)) {
                        OjNode.$.css(param1);
                    } else if(arguments.length === 1) {
                        ret = OjNode.$.css(param1);
                    } else {
                        OjNode.$.css(param1, param2);
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'data', { value: function (prop, val) {
                var ret = '';
                if (prop && OjInternal.isNodeAlive()) {
                    if (OJ.is.plainObject(prop)) {
                        OjInternal.setDataProperties(prop);
                    } else {
                        switch (arguments.length) {
                            case 1:
                                ret = OjInternal.getDataProp(prop);
                                break;
                            case 2:
                                OjInternal.setDataProp(prop, val);
                                ret = OjNode;
                                break;
                        }
                    }
                }
                return ret;

            }});

            Object.defineProperty(OjNode, 'disable', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjInternal.enabled = false;
                    OjNode.addClass('OjDisabled');
                    OjNode.attr('disabled', 'disabled');
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'empty', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjNode.$.empty();
                    OjNode.childNodes = [];
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'enable', { value:  function () {
                if (OjInternal.isNodeAlive()) {
                    OjInternal.enabled = true;
                    OjNode.removeClass('OjDisabled');
                    OjNode.removeAttr('disabled');
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'getId', { value: function () {
                var ret = '';
                if (OjInternal.isNodeAlive()) {
                    ret = OjNode[0].id;
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'hide', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjNode.addClass('OjHidden');
                    OjNode.$.hide();
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'length', { value: function () {
                var ret = 0;
                if (OjInternal.isNodeAlive()) {
                    ret = OJ.to.number(OjNode.$.length);
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'prop', { value: function (name, value) {
                var ret = null;
                if (name && OjInternal.isNodeAlive()) {
                    ret = OjNode;

                    if(OJ.is.plainObject(name)) {
                        OjNode.$.prop(name);
                    } else  if(arguments.length === 1) {
                        ret = OjNode.$.prop(name);
                    } else {
                        OjNode.$.prop(name, value);
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'remove', { value: function () {
                if(OjNode && OjNode.$) {
                    OjNode.$.remove();
                    OjNode.childNodes = [];
                    //This will update the internal reference to the node,
                    //which will allow isNodeAlive() to work as expected;
                    //however, it won't delete outstanding references to the Node.
                    //But that's OK. The GC will clean-up just fine.
                    OjNode = null;
                }
                return null;
            }});

            Object.defineProperty(OjNode, 'removeClass', { value: function (name) {
                if (name && OjInternal.isNodeAlive()) {
                    OjNode.$.removeClass(name);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'removeProp', { value: function (name) {
                if (name && OjInternal.isNodeAlive()) {
                    OjNode.$.removeProp(name);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'removeAttr', { value: function (name) {
                if (name && OjInternal.isNodeAlive()) {
                    OjNode.$.removeAttr(name);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'show', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjNode.removeClass('OjHidden');
                    OjNode.$.show();
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'text', { value: function (text) {
                if (text && OjInternal.isNodeAlive()) {
                    if (arguments.length === 1 && false === OJ.is.nullOrUndefined(text)) {
                        OjNode.$.text(text);
                        return OjNode;
                    } else {
                        return OJ.to.string(OjNode.$.text());
                    }
                }
            }});

            Object.defineProperty(OjNode, 'toggle', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjNode.$.toggle();
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'toggleEnable', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    if (OjInternal.enabled) {
                        OjNode.disable();
                    } else {
                        OjNode.enable();
                    }
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'trigger', { value: function (eventName, eventOpts) {
                if (eventName && OjInternal.isNodeAlive()) {
                    OjNode.$.trigger(eventName, eventOpts);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'unbind', { value: function (eventName, event) {
                if (eventName && OjInternal.isNodeAlive()) {
                    OjNode.$.off(eventName, event);
                }
                return OjNode;
            }});
            Object.defineProperty(OjNode, 'off', { value:  OjNode.unbind });

            Object.defineProperty(OjNode, 'valueOf', { value: function () {
                return OjNode;
            }});

            /**
             * Individual DOM classes will need to override this method.
            */
            OjNode.val = OjNode.val || function (value) {
                if (OjInternal.isNodeAlive()) {
                    if (arguments.length === 1 && false === OJ.is.nullOrUndefined(value)) {
                        OjNode.$.val(value);
                        return OjNode;
                    } else {
                        return OJ.to.string(OjNode.$.val());
                    }
                }
            };

            /**
             * This is THE mechanism for building out the DOM.
             * OJ may later support *pend methods, but for now it's turtles all the way down.
             */
            Object.defineProperty(OjNode, 'addChild', { value: function (object) {
                return OjNode.append(object);
            }});

            //Finally! Return something.
            return OJ.node.factory(OjNode);
        }
    });

} ());

<commit_msg>jQuery should be hot swappable for any compatable tool. Don't persist $ naming conventions.<commit_after>/*global OJ:true,$:true*/
(function () {

    OJ.makeSubNameSpace('node');

    OJ.node.lift('wrapper', function (OjNode, DomEl, options) {
            'use strict';
        if(!(OjNode && true === OjNode.isValid)) { //Don't try to wrap the same OjNode twice
            var OjInternal = {
                data: {},
                enabled: true,
                isValid: false
            };
            OjNode = OjNode || Object.create({ 0: null, '?': $({}), isValid: false });

            (function _initConstructor() {
                //Validate and setup our Node instance
                if (OjNode[0] instanceof HTMLElement &&
                    OJ.is.jQuery(OjNode['?'])) {
                    OjInternal.isValid = true;
                }
                else if (OJ.is.jQuery(DomEl)) {
                    Object.defineProperty(OjNode, '?', {
                        value: DomEl
                    });
                    Object.defineProperty(OjNode, '0', {
                        value: DomEl[0]
                    });
                    OjInternal.isValid = true;
                }
                else if (DomEl instanceof HTMLElement) {
                    Object.defineProperty(OjNode, '0', {
                        value: DomEl
                    });
                    Object.defineProperty(OjNode, '?', {
                        value: $('#' + DomEl.id)
                    });
                    OjInternal.isValid = true;
                } else {
                    OjInternal.isValid = false;
                    //No reason to continue. There is no juice to be had here.
                    throw new Error('Cannot make OJ without citrus fruit! OJ.node.wrapper was handed an invalid DOM handle.');
                }
            }()); //end initConstructor

            // No technical need to sequester the code in this way,
            // but it feels more readable in these blocks
            (function _postConstructor(){
                //We have a valid OjNode, let's build it out.
                Object.defineProperty(OjNode, 'isValid', {
                        value: OjInternal.isValid
                    });

                Object.defineProperty(OjNode, 'tagName', {
                    value: OjNode[0].tagName
                });

                Object.defineProperty(OjNode, 'childNodes', {
                        value: [],
                        writable: true
                    });

                // Keep this method safely enveloped in the closure.
                var buildChildNode = function(node, $element) {
                    node = node || Object.create(null);
                    // root and parent are safe assumptions
                    Object.defineProperty(node, 'root', {value: OjNode.root});
                    Object.defineProperty(node, 'parent', {value: OjNode });
                    if (OJ.is.jQuery($element)) {
                        // this is a valid child
                        Object.defineProperty(node, '$', {value: $element});
                        Object.defineProperty(node, '0', {value: $element[0]});

                    }
                    // Extend the child with the wrapper methods around itself
                    return  OJ.node.wrapper(node);
                };

                Object.defineProperty(OjInternal, 'chainChildNode', { value: function ($child) {
                    var newNode = Object.create(null);
                    buildChildNode(newNode, $child);
                    OjNode.childNodes.push(newNode);
                    return newNode;
                }});

                Object.defineProperty(OjInternal, 'wrapChildNode', { value: function ($child) {
                    var newNode = Object.create(null);
                    return buildChildNode(newNode, $child);
                }});

                /**
                 * Whether or no we have removed the node internally.
                 * This doesn't actually test the DOM,
                 * only our in-memory representation of the DOM.
                */
                Object.defineProperty(OjInternal, 'isNodeAlive', { value: function () {
                    return false === OJ.is.nullOrEmpty(OjNode);
                }});
            }());

            //Define some internal data methods
            Object.defineProperty(OjInternal, 'getDataProp', { value: function (propName) {
                var ret = null;
                if (OjInternal.isNodeAlive() &&
                    false === OJ.is.stringNullOrEmpty(propName)) {

                    if (OjNode[0] && OjNode[0].dataset && OjNode[0].dataset[propName]) {
                        ret = OjNode[0].dataset.propName;
                    }
                    if (OJ.is.stringNullOrEmpty(ret)) {
                        ret = OjInternal.data[propName] ||
                            OjNode['?'].data(propName) ||
                            OJ.localStorage.getItem(propName + '_control_data_' + OjNode.getId());
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjInternal, 'setDataProp', { value: function (propName, value) {
                var ret = null;
                if (OjInternal.isNodeAlive() &&
                    false === OJ.is.stringNullOrEmpty(propName)) {
                    ret = value;
                    if (OjNode[0] && OjNode[0].dataset) {
                        OjNode[0].dataset[propName] = value;

                        OjInternal.data[propName] = value;
                    } else {
                        OjInternal.data[propName] = value;
                        OjNode['?'].data(propName, value);
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjInternal, 'setDataProperties', { value: function (obj) {
                if(obj && Object.keys(obj)) {
                    Object.keys(obj).forEach(function (key, val) {
                        OjInternal.setDataProp(key, val);
                    });
                }
            }});

            /**
              OJ doesn't need many jQuery selectors,
              but when it does they are sequestered on this property to "try" to avoid confusion.
            */
            var el = Object.create(null);

            Object.defineProperty(el, 'children', {value: function (searchTerm, selector) {
                var ret = [];
                if (OjInternal.isNodeAlive()) {
                    var $children = OjNode['?'].children(OJ.to.string(searchTerm), OJ.to.string(selector));
                    if($children) {
                        $children.each(function() {
                            var $child = $(this);
                            ret.push(OjInternal.chainChildNode($child));
                        });
                    }
                }
                return ret;
            }});

            Object.defineProperty(el, 'filter', { value: function (selector) {
                var ret = [];
                if (selector && OjInternal.isNodeAlive()) {
                    var $children = OjNode['?'].filter(selector);
                    if($children.length > 0) {
                        $children.each(function() {
                            var $child = $(this);
                            ret.push(OjInternal.wrapChildNode($child));
                        });
                    }
                }
                return ret;
            }});

            Object.defineProperty(el, 'find', { value: function (selector) {
                var ret = [];
                if (selector && OjInternal.isNodeAlive()) {
                    var $children = OjNode['?'].find(selector);
                    if($children.length > 0) {
                        $children.each(function() {
                            var $child = $(this);
                            ret.push(OjInternal.wrapChildNode($child));
                        });
                    }
                }
                return ret;
            }});

            Object.defineProperty(el, 'first', { value: function () {
                var ret = OjNode.childNodes[0] || OjNode.el.children[0];
                return ret;
            }});

            Object.defineProperty(el, 'parent', { value: function () {
                var ret = {};
                if (OjInternal.isNodeAlive()) {
                    var $parent = OjNode['?'].parent();

                    if (false === OJ.is.nullOrEmpty($parent) && $parent.length > 0) {
                        ret = OJ.dom.nodeWrapper({}, $parent);
                    }
                }
                return ret;
            }});

            /**
                OJ implements these wrappers around jQuery methods to provide better chaining on OJ Nodes,
                as well as to make it easy to swap out the DOM framework without having to change the interfaces
            */
            Object.defineProperty(OjNode, 'addClass', { value: function (name) {
                if (name && OjInternal.isNodeAlive()) {
                    OjNode['?'].addClass(name);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'append', { value: function (object) {
                var ret = OjNode;
                if (object && OjInternal.isNodeAlive()) {
                    OJ.tryThisThenThat(function _first() {
                        OjNode['?'].append(object);
                        ret = OjInternal.chainChildNode(object);
                    }, function _second() {
                        //Probably attempted to append a string which matched a selector (e.g. 'a')
                        //which will attempt to (and fail to) append all <a> nodes to this one.
                        if (OJ.is.string(object)) {
                            OjNode.text(object);
                        }
                    });
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'attr', { value: function (name, value) {
                var ret = null;
                if (name && OjInternal.isNodeAlive()) {
                    ret = OjNode;

                    if(OJ.is.plainObject(name)) {
                        OjNode['?'].attr(name);
                    } else  if(arguments.length === 1) {
                        ret = OjNode['?'].attr(name);
                    } else {
                        OjNode['?'].attr(name, value);
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'attach', { value: function (object) {
                var $child = null, ret;
                if (object && OjInternal.isNodeAlive()) {
                    OJ.tryThisThenThat(function _first() {
                        $child = $(object);
                        if (false === OJ.is.nullOrEmpty($child)) {
                            OjNode.append($child);
                            ret = OjInternal.chainChildNode($child);
                        }
                    }, function _second() {

                    });
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'bind', {value : function (eventName, event) {
                if (eventName && OjInternal.isNodeAlive()) {
                    OjNode['?'].on(eventName, event);
                }
                return OjNode;
            }});
            Object.defineProperty(OjNode, 'on', {value : OJ.bind });

            Object.defineProperty(OjNode, 'clickOnEnter', {value: function (anOjNode) {
                if (anOjNode &&  OjInternal.isNodeAlive()) {
                    OjNode['?'].clickOnEnter(anOjNode['?']);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'css', { value: function (param1, param2) {
                var ret = OjNode;
                if (param1 && OjInternal.isNodeAlive()) {
                    if (OJ.is.plainObject(param1)) {
                        OjNode['?'].css(param1);
                    } else if(arguments.length === 1) {
                        ret = OjNode['?'].css(param1);
                    } else {
                        OjNode['?'].css(param1, param2);
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'data', { value: function (prop, val) {
                var ret = '';
                if (prop && OjInternal.isNodeAlive()) {
                    if (OJ.is.plainObject(prop)) {
                        OjInternal.setDataProperties(prop);
                    } else {
                        switch (arguments.length) {
                            case 1:
                                ret = OjInternal.getDataProp(prop);
                                break;
                            case 2:
                                OjInternal.setDataProp(prop, val);
                                ret = OjNode;
                                break;
                        }
                    }
                }
                return ret;

            }});

            Object.defineProperty(OjNode, 'disable', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjInternal.enabled = false;
                    OjNode.addClass('OjDisabled');
                    OjNode.attr('disabled', 'disabled');
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'empty', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjNode['?'].empty();
                    OjNode.childNodes = [];
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'enable', { value:  function () {
                if (OjInternal.isNodeAlive()) {
                    OjInternal.enabled = true;
                    OjNode.removeClass('OjDisabled');
                    OjNode.removeAttr('disabled');
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'getId', { value: function () {
                var ret = '';
                if (OjInternal.isNodeAlive()) {
                    ret = OjNode[0].id;
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'hide', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjNode.addClass('OjHidden');
                    OjNode['?'].hide();
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'length', { value: function () {
                var ret = 0;
                if (OjInternal.isNodeAlive()) {
                    ret = OJ.to.number(OjNode['?'].length);
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'prop', { value: function (name, value) {
                var ret = null;
                if (name && OjInternal.isNodeAlive()) {
                    ret = OjNode;

                    if(OJ.is.plainObject(name)) {
                        OjNode['?'].prop(name);
                    } else  if(arguments.length === 1) {
                        ret = OjNode['?'].prop(name);
                    } else {
                        OjNode['?'].prop(name, value);
                    }
                }
                return ret;
            }});

            Object.defineProperty(OjNode, 'remove', { value: function () {
                if(OjNode && OjNode['?']) {
                    OjNode['?'].remove();
                    OjNode.childNodes = [];
                    //This will update the internal reference to the node,
                    //which will allow isNodeAlive() to work as expected;
                    //however, it won't delete outstanding references to the Node.
                    //But that's OK. The GC will clean-up just fine.
                    OjNode = null;
                }
                return null;
            }});

            Object.defineProperty(OjNode, 'removeClass', { value: function (name) {
                if (name && OjInternal.isNodeAlive()) {
                    OjNode['?'].removeClass(name);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'removeProp', { value: function (name) {
                if (name && OjInternal.isNodeAlive()) {
                    OjNode['?'].removeProp(name);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'removeAttr', { value: function (name) {
                if (name && OjInternal.isNodeAlive()) {
                    OjNode['?'].removeAttr(name);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'show', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjNode.removeClass('OjHidden');
                    OjNode['?'].show();
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'text', { value: function (text) {
                if (text && OjInternal.isNodeAlive()) {
                    if (arguments.length === 1 && false === OJ.is.nullOrUndefined(text)) {
                        OjNode['?'].text(text);
                        return OjNode;
                    } else {
                        return OJ.to.string(OjNode['?'].text());
                    }
                }
            }});

            Object.defineProperty(OjNode, 'toggle', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    OjNode['?'].toggle();
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'toggleEnable', { value: function () {
                if (OjInternal.isNodeAlive()) {
                    if (OjInternal.enabled) {
                        OjNode.disable();
                    } else {
                        OjNode.enable();
                    }
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'trigger', { value: function (eventName, eventOpts) {
                if (eventName && OjInternal.isNodeAlive()) {
                    OjNode['?'].trigger(eventName, eventOpts);
                }
                return OjNode;
            }});

            Object.defineProperty(OjNode, 'unbind', { value: function (eventName, event) {
                if (eventName && OjInternal.isNodeAlive()) {
                    OjNode['?'].off(eventName, event);
                }
                return OjNode;
            }});
            Object.defineProperty(OjNode, 'off', { value:  OjNode.unbind });

            Object.defineProperty(OjNode, 'valueOf', { value: function () {
                return OjNode;
            }});

            /**
             * Individual DOM classes will need to override this method.
            */
            OjNode.val = OjNode.val || function (value) {
                if (OjInternal.isNodeAlive()) {
                    if (arguments.length === 1 && false === OJ.is.nullOrUndefined(value)) {
                        OjNode['?'].val(value);
                        return OjNode;
                    } else {
                        return OJ.to.string(OjNode['?'].val());
                    }
                }
            };

            /**
             * This is THE mechanism for building out the DOM.
             * OJ may later support *pend methods, but for now it's turtles all the way down.
             */
            Object.defineProperty(OjNode, 'addChild', { value: function (object) {
                return OjNode.append(object);
            }});

            //Finally! Return something.
            return OJ.node.factory(OjNode);
        }
    });

} ());

<|endoftext|>


<commit_before>'use strict';
/*
 * Copyright 2013 Next Century Corporation
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

var tables = tables || {};
tables.LINKABLE = "linkable";

/**
 * Creates a new table
 * @class Table
 * @namespace tables
 * @param {String} tableSelector The selector for the component in which the table will be drawn
 * @param {Object} opts A collection of key/value pairs used for configuration parameters:
 *

 *
data (required) - An array of data to display in the table

 *
columns (optional) - A list of the fields to display in the table. If not specified, the table
 *     will iterate through all of the rows and get the unique column names. This can be a slow operation for
 *     large datasets.

 *
id (optional) - The name of the column with the unique id for the item. If this is not
 *     specified, an id field will be autogenerated and appended to the data (the original data
 *     will be modified)

 *
gridOptions (optional) - Slickgrid options may be set here.
 *

 *

 *
 * @constructor
 *
 * @example
 *     var data = [
 *                 {"field1": "aVal", "field2": 2},
 *                 {"field1": "bVal", "field2": 5, "anotherField" : "anotherVal"},
 *                ];
 *     var columns = [
 *                    {name: "field1"},
 *                    {name: "field2"},
 *                    {name: "field3", field: "anotherField", width: 20}
 *                   ];
 *     var opts = { "data" : data, "columns" : columns };
 *     var table = new tables.Table('#table', opts).draw();
 */
tables.Table = function(tableSelector, opts) {
    this.tableSelector_ = tableSelector;
    this.idField_ = opts.id;
    this.options_ = opts.gridOptions || {};

    var data = opts.data;
    var columns = opts.columns ? opts.columns : tables.createColumns(data);

    if(!this.idField_) {
        tables.Table.appendGeneratedId_(data);
        this.idField_ = tables.Table.AUTOGENERATED_ID_FIELD_NAME_;
    }

    this.dataView_ = this.createDataView_(data);
    this.columns_ = tables.Table.createSlickgridColumns_(columns);
    this.sortInfo_ = {};
};

tables.Table.AUTOGENERATED_ID_FIELD_NAME_ = '__autogenerated_id';

/**
 * Creates an array of objects containing the column names by iterating through the data and saving unique column names.
 * @param {Array} data The data being shown in the table
 * @return {Array} The objects containing column names
 * @method createColumns
 * @private
 */
tables.createColumns = function(data) {
    // just use an object to store the keys for faster lookup (basically a hash where we don't care about the value)
    var map = {};
    data.forEach(function(row) {
        var keys = Object.keys(row);
        keys.forEach(function(key) {
            map[key] = true;
        });
    });

    var columns = [];
    Object.keys(map).forEach(function(name) {
        columns.push({
            name: name
        });
    });
    return columns;
};

/**
 * Adds a CSS class to the given column definitions so the cells in those columns will be linkified.
 * @param {Array} The array of column definition objects.
 * @return {Array} The amended array.
 */
tables.addLinkabilityToColumns = function(columns) {
    for(var i = 0; i < columns.length; ++i) {
        if(columns[i].cssClass) {
            columns[i].cssClass += " " + tables.LINKABLE;
        } else {
            columns[i].cssClass = tables.LINKABLE;
        }
    }
    return columns;
};

/**
 * Creates the sort comparator to sort the data in the table
 * @param {String} field The field being sorted
 * @param {Boolean} sortAsc Whether to sort ascending
 * @return {Function} A function to perform the sort comparison
 * @method sortComparator_
 * @private
 */
tables.Table.sortComparator_ = function(field, sortAsc) {
    return function(a, b) {
        var result = 0;
        if(a[field] > b[field]) {
            result = 1;
        } else if(a[field] < b[field]) {
            result = -1;
        }
        return sortAsc ? result : -result;
    };
};

tables.Table.appendGeneratedId_ = function(data) {
    var id = 0;
    data.forEach(function(el) {
        el[tables.Table.AUTOGENERATED_ID_FIELD_NAME_] = id++;
    });
};

/**
 * Creates a slickgrid data view from the raw data
 * @param {Array} data Array of data to be displayed
 * @method createDataView_
 * @private
 */
tables.Table.prototype.createDataView_ = function(data) {
    var dataView = new Slick.Data.DataView();
    dataView.setItems(data, this.idField_);

    return dataView;
};

/**
 * Converts a list of column names to the format required by the slickgrids library
 * used to create the tables
 * @param {Array} columnNames A list of column names
 * @method createSlickgridColumns_
 * @private
 */
tables.Table.createSlickgridColumns_ = function(columnNames) {
    var slickgridColumns = [];
    columnNames.forEach(function(column) {
        var slickgridColumn = {};
        slickgridColumn.id = column.name;
        slickgridColumn.name = column.name;
        slickgridColumn.field = column.field ? column.field : column.name;
        slickgridColumn.focusable = true;
        slickgridColumn.sortable = true;
        slickgridColumn.formatter = tables.Table.defaultCellFormatter_;
        if(column.width) {
            slickgridColumn.width = column.width;
        }
        if(column.cssClass) {
            slickgridColumn.cssClass = column.cssClass;
        }
        if(column.ignoreClicks) {
            // This column and its cells will not become "active" on click.
            slickgridColumn.focusable = false;
        }
        slickgridColumns.push(slickgridColumn);
    });
    return slickgridColumns;
};

tables.Table.defaultCellFormatter_ = function(row, cell, value, columnDef, dataContext) {
    // most of this taken from slick.grid.js defaultFormatter but modified to support nested objects
    if(null === value || undefined === value) {
        return "";
    }

    // check if nested object. if it is, append each of the key/value pairs
    var keys = tables.Table.getObjectKeys_(value);

    if(0 === keys.length) {
        return value;
    }

    return tables.Table.createKeyValuePairsString_(value, keys, row, cell, columnDef, dataContext);
};

tables.Table.getObjectKeys_ = function(object) {
    var keys = [];
    if('object' === typeof object) {
        keys = Object.keys(object);
    }
    return keys;
};

tables.Table.createKeyValuePairsString_ = function(object, keys, row, cell, columnDef, dataContext) {
    var keyValueStrings = [];
    keys.forEach(function(key) {
        keyValueStrings.push(key + ': ' + tables.Table.defaultCellFormatter_(row, cell, object[key], columnDef, dataContext));
    });
    return keyValueStrings.join(', ');
};

tables.Table.prototype.addLinks_ = function() {
    // TODO:  Make this configurable based on the dataset.
    var linkyConfig = {
        mentions: true,
        hashtags: true,
        urls: true,
        linkTo: "twitter"
    };

    var cellSelector = this.tableSelector_;

    // Add initial links and update links on viewport changes.
    $(cellSelector).find(".slick-cell." + tables.LINKABLE).linky(linkyConfig);
    this.table_.onViewportChanged.subscribe(function() {
        $(cellSelector).find("slick-cell." + tables.LINKABLE).linky(linkyConfig);
    });
};

/**
 * Draws the table in the selector specified in the constructor
 * @method draw
 * @return {tables.Table} This table
 */
tables.Table.prototype.draw = function() {
    this.table_ = new Slick.Grid(this.tableSelector_, this.dataView_, this.columns_, this.options_);
    this.addSortSupport_();
    this.table_.registerPlugin(new Slick.AutoTooltips({
        enableForHeaderCells: true
    }));
    this.addLinks_();

    // Setup some event loggers.
    this.table_.onColumnsResized.subscribe(function() {
        XDATA.activityLogger.logUserActivity('Grid - user resized columns', 'resize',
            XDATA.activityLogger.WF_EXPLORE);
    });

    // Setup some event loggers.
    this.table_.onColumnsReordered.subscribe(function() {
        XDATA.activityLogger.logUserActivity('Grid - user reordered columns', 'reorder',
            XDATA.activityLogger.WF_EXPLORE);
    });

    // Setup some event loggers.
    this.table_.onScroll.subscribe(function() {
        XDATA.activityLogger.logUserActivity('Grid - user scrolled data view', 'scroll',
            XDATA.activityLogger.WF_EXPLORE);
    });

    // Setup some event loggers.
    this.table_.onSort.subscribe(function(e, args) {
        XDATA.activityLogger.logUserActivity('Grid - user sorted column', 'sort',
            XDATA.activityLogger.WF_EXPLORE, {
                column: args.sortCol.field,
                sortAsc: args.sortAsc,
                multicolumnSort: args.multiColumnSort
            });
    });

    return this;
};

tables.Table.prototype.refreshLayout = function() {
    // the table may not be drawn yet when this is called (this method can be used as a hook to resize a table, but
    // if the browser is resized before the table is drawn, the table will be undefined here)
    if(this.table_) {
        this.table_.resizeCanvas();
    }
};

tables.Table.prototype.registerSelectionListener = function(callback) {
    if(!callback || 'function' !== typeof callback) {
        return;
    }
    var rowModel = new Slick.RowSelectionModel();
    this.table_.setSelectionModel(rowModel);

    var me = this;
    rowModel.onSelectedRangesChanged.subscribe(function() {
        if(me.idField_ === tables.Table.AUTOGENERATED_ID_FIELD_NAME_) {
            return;
        }

        var selectedRowData = [];
        _.each(me.table_.getSelectedRows(), function(rowIndex) {
            selectedRowData.push(me.table_.getDataItem(rowIndex));
        });
        callback(me.idField_, selectedRowData);
    });
    return this;
};

tables.Table.prototype.sortColumn = function(field, sortAsc) {
    var data = this.dataView_.getItems();
    // Use a stable sorting algorithm as opposed to the built-in
    // dataView sort which may not be stable.
    data = data.mergeSort(tables.Table.sortComparator_(field, sortAsc));
    this.dataView_.setItems(data);
    this.table_.invalidateAllRows();
    this.table_.render();
    this.sortInfo_ = {
        field: field,
        sortAsc: sortAsc
    };
};

tables.Table.prototype.addSortSupport_ = function() {
    var me = this;
    this.table_.onSort.subscribe(function(event, args) {
        me.sortColumn(args.sortCol.field, args.sortAsc);
    });
};

tables.Table.prototype.sortColumnAndChangeGlyph = function(sortInfo) {
    // Sort the data in the column.
    this.sortColumn(sortInfo.field, sortInfo.sortAsc);
    // Change the sort glyph in the column header.
    this.table_.setSortColumn(sortInfo.field, sortInfo.sortAsc);
};

/**
 * Adds an onClick listener to the SlickGrid table using the given callback with
 * arguments for the array of column definitions and the selected row object.
 * @param {Function} The callback function
 */
tables.Table.prototype.addOnClickListener = function(callback) {
    var me = this;
    this.table_.onClick.subscribe(function(event, args) {
        if(me.columns_[args.cell].focusable) {
            callback(me.table_.getColumns(), me.dataView_.getItem(args.row));
        }
    });
};

/**
 * Deselects the active elements in the table.
 */
tables.Table.prototype.deselect = function() {
    this.table_.resetActiveCell();
};

/**
 * Sets the active cell in this table to the column and row containing the given
 * field and value, if it exists.
 * @param {String} The field matching a column name
 * @param {String} The value matching a cell's text
 */
tables.Table.prototype.setActiveCellIfMatchExists = function(field, value) {
    for(var i = 0; i < this.columns_.length; ++i) {
        if(this.columns_[i].field === field) {
            for(var j = 0; j < this.table_.getDataLength(); ++j) {
                if(this.table_.getCellNode(j, i).innerHTML === value) {
                    this.table_.setActiveCell(j, i);
                }
            }
        }
    }
};
<commit_msg>NEON-1366 SlickGrid tables now calculate their width based on the width of the text they contain during creation of column definitions.<commit_after>'use strict';
/*
 * Copyright 2013 Next Century Corporation
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

var tables = tables || {};
tables.LINKABLE = "linkable";

/**
 * Creates a new table
 * @class Table
 * @namespace tables
 * @param {String} tableSelector The selector for the component in which the table will be drawn
 * @param {Object} opts A collection of key/value pairs used for configuration parameters:
 *

 *
data (required) - An array of data to display in the table

 *
columns (optional) - A list of the fields to display in the table. If not specified, the table
 *     will iterate through all of the rows and get the unique column names. This can be a slow operation for
 *     large datasets.

 *
id (optional) - The name of the column with the unique id for the item. If this is not
 *     specified, an id field will be autogenerated and appended to the data (the original data
 *     will be modified)

 *
gridOptions (optional) - Slickgrid options may be set here.
 *

 *

 *
 * @constructor
 *
 * @example
 *     var data = [
 *                 {"field1": "aVal", "field2": 2},
 *                 {"field1": "bVal", "field2": 5, "anotherField" : "anotherVal"},
 *                ];
 *     var columns = [
 *                    {name: "field1"},
 *                    {name: "field2"},
 *                    {name: "field3", field: "anotherField", width: 20}
 *                   ];
 *     var opts = { "data" : data, "columns" : columns };
 *     var table = new tables.Table('#table', opts).draw();
 */
tables.Table = function(tableSelector, opts) {
    this.tableSelector_ = tableSelector;
    this.idField_ = opts.id;
    this.options_ = opts.gridOptions || {};

    var data = opts.data;
    var columns = opts.columns ? opts.columns : tables.createColumns(data);

    if(!this.idField_) {
        tables.Table.appendGeneratedId_(data);
        this.idField_ = tables.Table.AUTOGENERATED_ID_FIELD_NAME_;
    }

    this.dataView_ = this.createDataView_(data);
    this.columns_ = tables.Table.createSlickgridColumns_(columns);
    this.sortInfo_ = {};
};

tables.Table.AUTOGENERATED_ID_FIELD_NAME_ = '__autogenerated_id';

/**
 * Creates an array of column definition objects containing the column names and widths by iterating through the data
 * and saving unique column names and the longest text within those columns.
 * @param {Array} data The data being shown in the table
 * @return {Array} The objects containing column names and widths
 * @method createColumns
 * @private
 */
tables.createColumns = function(data) {
    // Store each column name and the longest text contained within the column (including its name).
    var columnNameToLongestText = {};

    data.forEach(function(row) {
        var keys = Object.keys(row);
        keys.forEach(function(key) {
            if(columnNameToLongestText[key] === undefined) {
                columnNameToLongestText[key] = key;
            }
            // This is slightly incorrect since we're using variable-width font but calculating the width of each cell
            // by inserting it into a DOM element using jQuery costs too much time.
            if(columnNameToLongestText[key].length < row[key].length) {
                columnNameToLongestText[key] = row[key];
            }
        });
    });

    // Use a hidden jQuery element with the same style as a SlickGrid header to calculate the column width.
    var element = $("
")
        .attr("class", "ui-widget ui-state-default slick-header-column")
        .css({"white-space": "nowrap", "visibility": "hidden"})
        .appendTo("body");

    // Include elements contained within SlickGrid headers to ensure our width calculations will fit the header text.
    var sortElement = $("")
        .attr("class", "slick-sort-indicator slick-sort-indicator-desc");
    var resizeElement = $("
")
        .attr("class", "slick-resizable-handle");

    // Create the SlickGrid column definitions.
    var columns = [];
    Object.keys(columnNameToLongestText).forEach(function(name) {
        element.html(columnNameToLongestText[name]).append(sortElement).append(resizeElement);
        columns.push({
            name: name,
            width: element.outerWidth()
        });
    });

    element.remove();

    return columns;
};

/**
 * Adds a CSS class to the given column definitions so the cells in those columns will be linkified.
 * @param {Array} The array of column definition objects.
 * @return {Array} The amended array.
 */
tables.addLinkabilityToColumns = function(columns) {
    for(var i = 0; i < columns.length; ++i) {
        if(columns[i].cssClass) {
            columns[i].cssClass += " " + tables.LINKABLE;
        } else {
            columns[i].cssClass = tables.LINKABLE;
        }
    }
    return columns;
};

/**
 * Creates the sort comparator to sort the data in the table
 * @param {String} field The field being sorted
 * @param {Boolean} sortAsc Whether to sort ascending
 * @return {Function} A function to perform the sort comparison
 * @method sortComparator_
 * @private
 */
tables.Table.sortComparator_ = function(field, sortAsc) {
    return function(a, b) {
        var result = 0;
        if(a[field] > b[field]) {
            result = 1;
        } else if(a[field] < b[field]) {
            result = -1;
        }
        return sortAsc ? result : -result;
    };
};

tables.Table.appendGeneratedId_ = function(data) {
    var id = 0;
    data.forEach(function(el) {
        el[tables.Table.AUTOGENERATED_ID_FIELD_NAME_] = id++;
    });
};

/**
 * Creates a slickgrid data view from the raw data
 * @param {Array} data Array of data to be displayed
 * @method createDataView_
 * @private
 */
tables.Table.prototype.createDataView_ = function(data) {
    var dataView = new Slick.Data.DataView();
    dataView.setItems(data, this.idField_);

    return dataView;
};

/**
 * Converts a list of column names to the format required by the slickgrids library
 * used to create the tables
 * @param {Array} columnNames A list of column names
 * @method createSlickgridColumns_
 * @private
 */
tables.Table.createSlickgridColumns_ = function(columnNames) {
    var slickgridColumns = [];
    columnNames.forEach(function(column) {
        var slickgridColumn = {};
        slickgridColumn.id = column.name;
        slickgridColumn.name = column.name;
        slickgridColumn.field = column.field ? column.field : column.name;
        slickgridColumn.focusable = true;
        slickgridColumn.sortable = true;
        slickgridColumn.formatter = tables.Table.defaultCellFormatter_;
        if(column.width) {
            slickgridColumn.width = column.width;
        }
        if(column.cssClass) {
            slickgridColumn.cssClass = column.cssClass;
        }
        if(column.ignoreClicks) {
            // This column and its cells will not become "active" on click.
            slickgridColumn.focusable = false;
        }
        slickgridColumns.push(slickgridColumn);
    });
    return slickgridColumns;
};

tables.Table.defaultCellFormatter_ = function(row, cell, value, columnDef, dataContext) {
    // most of this taken from slick.grid.js defaultFormatter but modified to support nested objects
    if(null === value || undefined === value) {
        return "";
    }

    // check if nested object. if it is, append each of the key/value pairs
    var keys = tables.Table.getObjectKeys_(value);

    if(0 === keys.length) {
        return value;
    }

    return tables.Table.createKeyValuePairsString_(value, keys, row, cell, columnDef, dataContext);
};

tables.Table.getObjectKeys_ = function(object) {
    var keys = [];
    if('object' === typeof object) {
        keys = Object.keys(object);
    }
    return keys;
};

tables.Table.createKeyValuePairsString_ = function(object, keys, row, cell, columnDef, dataContext) {
    var keyValueStrings = [];
    keys.forEach(function(key) {
        keyValueStrings.push(key + ': ' + tables.Table.defaultCellFormatter_(row, cell, object[key], columnDef, dataContext));
    });
    return keyValueStrings.join(', ');
};

tables.Table.prototype.addLinks_ = function() {
    // TODO:  Make this configurable based on the dataset.
    var linkyConfig = {
        mentions: true,
        hashtags: true,
        urls: true,
        linkTo: "twitter"
    };

    var cellSelector = this.tableSelector_;

    // Add initial links and update links on viewport changes.
    $(cellSelector).find(".slick-cell." + tables.LINKABLE).linky(linkyConfig);
    this.table_.onViewportChanged.subscribe(function() {
        $(cellSelector).find("slick-cell." + tables.LINKABLE).linky(linkyConfig);
    });
};

/**
 * Draws the table in the selector specified in the constructor
 * @method draw
 * @return {tables.Table} This table
 */
tables.Table.prototype.draw = function() {
    this.table_ = new Slick.Grid(this.tableSelector_, this.dataView_, this.columns_, this.options_);
    this.addSortSupport_();
    this.table_.registerPlugin(new Slick.AutoTooltips({
        enableForHeaderCells: true
    }));
    this.addLinks_();

    // Setup some event loggers.
    this.table_.onColumnsResized.subscribe(function() {
        XDATA.activityLogger.logUserActivity('Grid - user resized columns', 'resize',
            XDATA.activityLogger.WF_EXPLORE);
    });

    // Setup some event loggers.
    this.table_.onColumnsReordered.subscribe(function() {
        XDATA.activityLogger.logUserActivity('Grid - user reordered columns', 'reorder',
            XDATA.activityLogger.WF_EXPLORE);
    });

    // Setup some event loggers.
    this.table_.onScroll.subscribe(function() {
        XDATA.activityLogger.logUserActivity('Grid - user scrolled data view', 'scroll',
            XDATA.activityLogger.WF_EXPLORE);
    });

    // Setup some event loggers.
    this.table_.onSort.subscribe(function(e, args) {
        XDATA.activityLogger.logUserActivity('Grid - user sorted column', 'sort',
            XDATA.activityLogger.WF_EXPLORE, {
                column: args.sortCol.field,
                sortAsc: args.sortAsc,
                multicolumnSort: args.multiColumnSort
            });
    });

    return this;
};

tables.Table.prototype.refreshLayout = function() {
    // the table may not be drawn yet when this is called (this method can be used as a hook to resize a table, but
    // if the browser is resized before the table is drawn, the table will be undefined here)
    if(this.table_) {
        this.table_.resizeCanvas();
    }
};

tables.Table.prototype.registerSelectionListener = function(callback) {
    if(!callback || 'function' !== typeof callback) {
        return;
    }
    var rowModel = new Slick.RowSelectionModel();
    this.table_.setSelectionModel(rowModel);

    var me = this;
    rowModel.onSelectedRangesChanged.subscribe(function() {
        if(me.idField_ === tables.Table.AUTOGENERATED_ID_FIELD_NAME_) {
            return;
        }

        var selectedRowData = [];
        _.each(me.table_.getSelectedRows(), function(rowIndex) {
            selectedRowData.push(me.table_.getDataItem(rowIndex));
        });
        callback(me.idField_, selectedRowData);
    });
    return this;
};

tables.Table.prototype.sortColumn = function(field, sortAsc) {
    var data = this.dataView_.getItems();
    // Use a stable sorting algorithm as opposed to the built-in
    // dataView sort which may not be stable.
    data = data.mergeSort(tables.Table.sortComparator_(field, sortAsc));
    this.dataView_.setItems(data);
    this.table_.invalidateAllRows();
    this.table_.render();
    this.sortInfo_ = {
        field: field,
        sortAsc: sortAsc
    };
};

tables.Table.prototype.addSortSupport_ = function() {
    var me = this;
    this.table_.onSort.subscribe(function(event, args) {
        me.sortColumn(args.sortCol.field, args.sortAsc);
    });
};

tables.Table.prototype.sortColumnAndChangeGlyph = function(sortInfo) {
    // Sort the data in the column.
    this.sortColumn(sortInfo.field, sortInfo.sortAsc);
    // Change the sort glyph in the column header.
    this.table_.setSortColumn(sortInfo.field, sortInfo.sortAsc);
};

/**
 * Adds an onClick listener to the SlickGrid table using the given callback with
 * arguments for the array of column definitions and the selected row object.
 * @param {Function} The callback function
 */
tables.Table.prototype.addOnClickListener = function(callback) {
    var me = this;
    this.table_.onClick.subscribe(function(event, args) {
        if(me.columns_[args.cell].focusable) {
            callback(me.table_.getColumns(), me.dataView_.getItem(args.row));
        }
    });
};

/**
 * Deselects the active elements in the table.
 */
tables.Table.prototype.deselect = function() {
    this.table_.resetActiveCell();
};

/**
 * Sets the active cell in this table to the column and row containing the given
 * field and value, if it exists.
 * @param {String} The field matching a column name
 * @param {String} The value matching a cell's text
 */
tables.Table.prototype.setActiveCellIfMatchExists = function(field, value) {
    for(var i = 0; i < this.columns_.length; ++i) {
        if(this.columns_[i].field === field) {
            for(var j = 0; j < this.table_.getDataLength(); ++j) {
                if(this.table_.getCellNode(j, i).innerHTML === value) {
                    this.table_.setActiveCell(j, i);
                }
            }
        }
    }
};
<|endoftext|>


<commit_before>'use strict';

/**
Magicka Wizard Wars spell parser function.
Recieves a string.
Outputs a Array of spellMatch objects.
spellMatch = {
	start, // position in the original string where spell begins
	end,   // position in the original string where spell ends
	spell, // string containing the spell (modifiers included)
}
**/

function spellParser(str) {
	var filter = ['FAQ'];
	var result = [];
	var re = /((!|c)?([QWERASDFX]{2,3}|[QWERASDFX]\[[QWERASDFX][QWERASDFX]\]|\[[QWERASDFX][QWERASDFX]\][QWERASDFX]|\[[QWERASDFX]{2,3}\])|(!|c)([QWERASDFX]))(:[0-9]{1,3})?/g;
	var match = re.exec(str);
	while (match != null) {
		var s = {
			start : match.index,
			end   : re.lastIndex,
			spell : str.substring(match.index, re.lastIndex)
		};
		if (filter.indexOf(s.spell) < 0 &&
			(s.start == 0 || str[s.start-1].match(/[\W\s]/) != null) &&
			(s.end == str.length || str[s.end].match(/[\W\s]/) != null)
			)
			result.push(s);
		else
			console.log(str.substring(s.start-1, s.end +1));
		match = re.exec(str);
	}
	return result;
}
<commit_msg>added a very special cases checker<commit_after>'use strict';

/**
Magicka Wizard Wars spell parser function.
Recieves a string.
Outputs a Array of spellMatch objects.
spellMatch = {
	start, // position in the original string where spell begins
	end,   // position in the original string where spell ends
	spell, // string containing the spell (modifiers included)
}
**/

function isVerySpecialCase(spell, str) {
	if (str.substring(spell.start-2, spell.end) == 'M:WW')
		return true;
	return false;
}

function spellParser(str) {
	var filter = ['FAQ'];
	var result = [];
	var re = /((!|c)?([QWERASDFX]{2,3}|[QWERASDFX]\[[QWERASDFX][QWERASDFX]\]|\[[QWERASDFX][QWERASDFX]\][QWERASDFX]|\[[QWERASDFX]{2,3}\])|(!|c)([QWERASDFX]))(:[0-9]{1,3})?/g;
	var match = re.exec(str);
	while (match != null) {
		var s = {
			start : match.index,
			end   : re.lastIndex,
			spell : str.substring(match.index, re.lastIndex)
		};
		if (filter.indexOf(s.spell) < 0 &&
			(s.start == 0 || str[s.start-1].match(/[\W\s]/) != null) &&
			(s.end == str.length || str[s.end].match(/[\W\s]/) != null) &&
			!isVerySpecialCase(s, str))
			result.push(s);
		else
			console.log(str.substring(s.start-1, s.end +1));
		match = re.exec(str);
	}
	return result;
}
<|endoftext|>


<commit_before>import Wall from './../maze/wall';
import Maze from './../maze/mazen';
import Player from './../maze/player';
import * as WallTexture from './wallTexture';

function load(name) {
    return fetch('configuration/' + name + '.json').then(configurationResponse => {

        return configurationResponse.json().then(configuration => {
            let maze = Maze.create({
                length: configuration.length,
                width: configuration.width,
                cellSize: configuration.cellSize
            });

            let walls = configuration.walls.map((w, i) => {
                w = Object.assign(w);
                w.texture = i % 2 ? WallTexture.SIMPLE : WallTexture.DEVOXX_4_KIDS;
                return Wall.create(w, configuration.cellSize);
            });
            maze.addWalls(walls);

            let player = Player.create(configuration.player.name, configuration.player.position, {});
            maze.addPlayer(player);

            return maze;
        });
    });
}

export default {load}
<commit_msg>mazeloader uses new wallTexture constants<commit_after>import Wall from './../maze/wall';
import Maze from './../maze/mazen';
import Player from './../maze/player';
import * as WallTexture from './wallTexture';

function load(name) {
    return fetch('configuration/' + name + '.json').then(configurationResponse => {

        return configurationResponse.json().then(configuration => {
            let maze = Maze.create({
                length: configuration.length,
                width: configuration.width,
                cellSize: configuration.cellSize
            });

            let walls = configuration.walls.map((w, i) => {
                w = Object.assign(w);
                w.texture = i % 2 ? WallTexture.STONE : WallTexture.STONE_LAMP;
                return Wall.create(w, configuration.cellSize);
            });
            maze.addWalls(walls);

            let player = Player.create(configuration.player.name, configuration.player.position, {});
            maze.addPlayer(player);

            return maze;
        });
    });
}

export default {load}
<|endoftext|>


<commit_before>import DS from 'ember-data';
import OsfModel from 'ember-osf/models/osf-model';

/**
 * @module ember-preprints
 * @submodule models
 */

/**
 * Model for OSF APIv2 preprints. This model may be used with one of several API endpoints. It may be queried directly,
 *  or accessed via relationship fields.
 * For field and usage information, see:
 * https://api.osf.io/v2/docs/#!/v2/Preprint_List_GET
 * https://api.osf.io/v2/docs/#!/v2/Preprint_Detail_GET
 * https://api.osf.io/v2/docs/#!/v2/User_Preprints_GET
 * @class Preprint
 */
export default OsfModel.extend({
    title: DS.attr('string'),
    subjects: DS.attr(),
    provider: DS.attr('string'),
    date_created: DS.attr('date'),
    date_modified: DS.attr('date'),
    abstract: DS.attr('string'),
    tags: DS.attr(),

    // Relationships:
    // 1. Primary file
    // 2. files
    // 3. Authors (basically contributors)

    primaryFile: DS.belongsTo('file'),
    files: DS.hasMany('file-provider'),

    // REALLY BIG TODO: All preprints must re-implement all contributors behavior from the node model (authors are contributors by another name)
    authors: DS.hasMany('authors', {
        allowBulkUpdate: true,
        allowBulkRemove: true,
        inverse: null
    }),

    // authors: DS.attr(),
    // date: DS.attr(),
    // abstract: DS.attr(),
    // publisher: DS.attr(),
    // project: DS.attr(),
    // supplementalMaterials: DS.attr(),
    // figures: DS.attr(),
    // license: DS.attr(),
    // path: DS.attr(),
    // tags: DS.attr(),
    // doi: DS.attr(),
});
<commit_msg>Quick small tweaks<commit_after>import Ember from 'ember';
import DS from 'ember-data';
import OsfModel from 'ember-osf/models/osf-model';

/**
 * @module ember-preprints
 * @submodule models
 */

/**
 * Model for OSF APIv2 preprints. This model may be used with one of several API endpoints. It may be queried directly,
 *  or accessed via relationship fields.
 * For field and usage information, see:
 * https://api.osf.io/v2/docs/#!/v2/Preprint_List_GET
 * https://api.osf.io/v2/docs/#!/v2/Preprint_Detail_GET
 * https://api.osf.io/v2/docs/#!/v2/User_Preprints_GET
 * @class Preprint
 */
export default OsfModel.extend({
    title: DS.attr('string'),
    subjects: DS.attr(),
    provider: DS.attr('string'),
    date_created: DS.attr('date'),
    date_modified: DS.attr('date'),
    abstract: DS.attr('string'),
    tags: DS.attr(),

    // Relationships:
    // 1. Primary file
    // 2. files
    // 3. Authors (basically contributors)

    primaryFile: DS.belongsTo('file'),
    files: DS.hasMany('file-provider'),

    // REALLY BIG TODO: All preprints must re-implement all contributors behavior from the node model (authors are contributors by another name)
    authors: DS.hasMany('authors', {
        allowBulkUpdate: true,
        allowBulkRemove: true,
        inverse: null
    }),

    // TODO: Will this be enough to let NodeActionsMixin methods that track contributors work?
    //  (tagging @pattisdr)
    contributors: Ember.computed.alias('authors')

    // TODO: Verify that each of these fields is unnecessary, then remove
    // authors: DS.attr(),
    // date: DS.attr(),
    // abstract: DS.attr(),
    // publisher: DS.attr(),
    // project: DS.attr(),
    // supplementalMaterials: DS.attr(),
    // figures: DS.attr(),
    // license: DS.attr(),
    // path: DS.attr(),
    // tags: DS.attr(),
    // doi: DS.attr(),
});
<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular
    .module('app')
    .run(run);

  run.$inject = ['$ionicPlatform'];

  function run($ionicPlatform) {
    $ionicPlatform.ready(function() {
      if(window.cordova && window.cordova.plugins.Keyboard) {
        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      }
      if(window.StatusBar) {
        StatusBar.styleDefault();
      }
    });
  }
})();
<commit_msg>Remove file<commit_after><|endoftext|>


<commit_before>exports = module.exports = function(sd) {

  return function(service, username, password, cb) {
    var conn = sd.createConnection(service.type, service);
    conn.verify(username, password, function(err, user) {
      if (err) { return cb(err); }
      if (!user) { return cb(null, false); }
      return cb(null, user);
    });
  };
};

exports['@require'] = [
  'http://i.bixbyjs.org/sd'
];
<commit_msg>Add options.<commit_after>exports = module.exports = function(sd) {

  return function(url, username, password, options, cb) {
    if (typeof options == 'function') {
      cb = options;
      options = undefined;
    }
    options = options || {};

    var type = options.type;
    var conn = sd.createConnection(type, { url: url });
    conn.verify(username, password, function(err, user) {
      if (err) { return cb(err); }
      if (!user) { return cb(null, false); }
      return cb(null, user);
    });
  };
};

exports['@require'] = [
  'http://i.bixbyjs.org/sd'
];
<|endoftext|>