npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ojx

v1.1.0

Published

OJET custom components and utilities

Readme

ojx: OJET eXtension - Custom Elements and Utilities

ojx is an extension to OJET (Oracle JET) - MVVM

Installation:


npm i ojx

or


yarn add ojx

Configuration:

Add the following block in project's src/js/path_mapping.json after "ojs" block.


"ojx": {
  "cwd": "node_modules/ojx",
  "debug": {
    "src":  ["dist/**"],
    "path": "libs/ojx",
    "pathSuffix": "/dist'"

  },
  "release": {
    "src":  ["dist/**"],
    "path": "libs/ojx",
    "pathSuffix": "/dist'"
  }
},

Usage:

import

Import ojx AMD modules in src/js/appController.js or src/js/root.js or any viewModel.js


define(['knockout', 'jquery',
  ..., ..., ..., ...,
  'ojx/bundle',      // load all modules

  'ojx/elements',    // for all ojx-elements: <ojx-bind-html>, <ojx-module>, ...
  'ojx/bind-html',   // for <ojx-bind-html> only
  'ojx/module',      // for <ojx-module> only
  'ojx/utils',       // for ojet util functions
  'ojx/dom',         // for DOM util functions
  'ojx/object',      // for object util functions
  'ojx/type',        // for type util functions
  'ojx/data-time',   // for date-time util functions
  'ojx/storage',     // for multi-user sessionStorage and localStorage
  'ojx/file-system', // for file system util functions
  'ojx/libs',        // to export ko, jquery($) to global

  ], function (ko, $, ...) {

});

ojx-elements - ojx/elements

NOTE: you need to import 'ojx/elements' or 'ojx/bind-html', 'ojx/module' in viewModel.js. Refer import guide in Usage section above.

In views/*.html


... ... ...
<!-- <ojx-bind-html> for <oj-bind-dom> -->

<ojx-bind-html value="<strong>HTML</strong> text"></ojx-bind-html>

<ojx-bind-html value="[[sectionTitle]]"></ojx-bind-html>

<!-- optionally use voidxss attribute to void XSS content in value -->
<ojx-bind-html value="[[sectionTitle]]" voidxss></ojx-bind-html>

... ... ...

<!-- <ojx-module> simplified wrapper for <oj-module> -->

<ojx-module
  path="customers/view-customer"
  data="[[customerRecord]]"
  render="[[toggleModuleRender]]"></ojx-module>

... ... ...

Utilities - ojx/utils

ojx.domConfig


// for view.html: <oj-bind-dom config="[[ titleConfig ]]"></oj-bind-dom>
// in viewModel.js
this.titleConfig = ojx.domConfig( '<strong>HTML</strong> Text' );

ojx.moduleConfig

// ... ... ... ... ... ... ... ... ... ... ...

// for view.html: <oj-module config="[[ editCustViewConfig ]]"></oj-module>
// in viewModel.js
let moduleName = 'customers/edit-view';
let params = {
  user: {
    firstName: 'Donal',
    lastName: 'Duck',
    email: '[email protected]'
  }
};
this.editCustViewConfig = ojx.moduleConfig( moduleName, params );

ojx.arrayDataProvider

returns oj ArrayDataProvider (ojs/ojarraydataprovider) for a given source array


/**
 * returns oj ArrayDataProvider (ojs/ojarraydataprovider) for a given source array
 * @param {Array}  srcArray      - The source array
 * @param {string} keyAttribute  - The key attribute (e.g., 'id', 'userId', 'departmentId', 'lastUpdated')
 * @param {string} sortOrder     - for ascending : 'asc' | 'ascending'
 *                                 for descending: any value other than ['asc', 'ascending'] (ex., 'desc', 'descending')
 * @param {string} sortBy        - The key to sort by if ohter than keyAttribute (e.g., 'departmentId', 'StartDate')
 * @param {string} isDateTime    - is sortBy field of type Date/Time?
 */
let ojTableDataProvider1 = ojx.arrayDataProvider( srcArray, keyAttributes, sortOrder, sortBy, isDateTime );

// auto-detect key field in source array for unique-key
let ojTableDataProvider2 = ojx.arrayDataProvider( srcArray );

// use 'DepartmentId' field as key, and only indicate sort as desc - but does not sort the source array
let ojTableDataProvider3 = ojx.arrayDataProvider( srcArray, 'DepartmentId', 'desc' );

// use 'DepartmentId' field as unique key, and re-sort the source array by DepartmentId (descending)
let ojTableDataProvider4 = ojx.arrayDataProvider( srcArray, 'DepartmentId', 'desc*' );

// use 'id' field as unique key, and re-sort the source array by 'firstName' (ascending)
let ojTableDataProvider5 = ojx.arrayDataProvider( srcArray, 'id', 'asc', 'firstName' );

// use 'id' field as unique key, and re-sort the source array by 'lastUpdatedOn' (descending) + auto-detects date/time field by its fieldname
let ojTableDataProvider6 = ojx.arrayDataProvider( srcArray, 'id', 'desc', 'lastUpdatedOn' );
// use 'id' field as unique key, and re-sort the source array by 'lastUpdatedOn' (descending) and consider 'lastUpdatedOn' as date-time field.
let ojTableDataProvider7 = ojx.arrayDataProvider( srcArray, 'id', 'desc', 'lastUpdatedOn', true );

DOM utilities - ojx/dom

DOM selector

// instead of document.querySelector( '#pgHeader' );
let secHeaderA = _$( '#sectionHeader' );
// OR
let secHeaderB = ojx.$( '#pgHeader' );

// instead of document.querySelectorAll( '.menu-items' );
let menuItemsA = _$$( '.menu-items' );
// OR
let menuItemsB = ojx.$$( '.menu-items' );

Sanitize XSS in HTML and JSON Object


sanitizeXSS( '<script>alert("Hi")</script>' ); // '<xss-script>alert("Hi")</xss-script>'

sanitizeXSS( '<button onclick="doSomething()">Click Me</button>' ); // '<button xss-onclick="doSomething()">Click Me</button>'

sanitizeXSS( { note: '<button onclick="doSomething()">Click Me</button>' } ); // { note: '<button xss-onclick="doSomething()">Click Me</button>' }

// OR
ojx.sanitizeXSS( '<script>alert("Hi")</script>' ); // '<xss-script>alert("Hi")</xss-script>'

Object - ojx/object

{ }.__keys( deep? )

To get keys


let testObjA = {
  name: 'Javascript',
  altName: 'ECMA Script',
  active: true
};

console.log( testObjA.__keys() ); // ['name', 'altName', 'active']
// OR
console.log( ojx.keysOf(testObjA) ); // ['name', 'altName', 'active']

// ----------------------------------------------------------------

const testObjB = {
  company: "TechCorp",
  employees: [
    { name: "Tom", role: "Dev" },
    { name: "Jerry", role: "Design" }
  ]
};

testObjB.__keys( true ); // ["company", "employees", "employees[0].name", "employees[0].role"]
// OR
ojx.keysOf(testObjB, true ); // ["company", "employees", "employees[0].name", "employees[0].role"]

{ }.__merge( ObjX1, ObjX2, ...) | ojx.merge( targetObj, ObjX1, ObjX2, ... )

High-performance JSON-object merge.


const user    = { profile: { name: 'JavaScript' } };
const update1 = { profile: { age: 30 }, settings: { dark: true } };
const update2 = { profile: { location: 'everywhere' } };

user.__merge(update1, update2);

// OR

ojx.merge(user, update1, update2)

// Result:
// user = {
//   profile: { name: 'JavaScript', age: 30, location: 'everywhere' },
//   settings: { dark: true }
// }

{ }.__ofClass()

To find the object's Class


// ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...

// <h1 id="sectionTitle">Section Title</h1>
document.getElementById('sectionTitle').__ofClass(); // 'HTMLHeadingElement'
document.querySelector('h1').__ofClass();            // 'HTMLHeadingElement'

/* HTML
  <ul>
    <li class="menu-items">menu item 01</li>
    <li class="menu-items">menu item 02</li>
    <li class="menu-items">menu item 03</li>
    <li class="menu-items">menu item 04</li>
    <li class="menu-items">menu item 05</li>
  </ul>
*/
document.getElementsByClassName('menu-item').__ofClass(); // 'HTMLCollection'
document.querySelectorAll('.menu-item').__ofClass();      // 'NodeList'

[ ].__sortBy | ojx.sortBy

Sorts an array of objects based on a specific field and order.


/**
 * Sorts an array of objects based on a specific field and order.
 * @param {Array}  srcArray    - The source array
 * @param {string} sortByField - The keyField to sort by (e.g., 'id', 'userId', 'lastUpdated', 'address.shipping.zip')
 * @param {string} orderBy     - for ascending : 'asc' | 'ascending'
 *                               for descending: any value other than ['asc', 'ascending'] (ex., 'desc', 'descending')
 * @param {string} isDateTime  - is sortByField of type Date/Time?
 */
ojx.sortBy(srcArray, sortByField, orderBy, isDateTime);

let sortedArray1 = ojx.sortBy( [...srcArray], sortByField, orderBy, isDateTime );
let sortedArray2 = ojx.sortBy( [...srcArray], 'lastUpdatedOn', 'desc', true );
let sortedArray3 = ojx.sortBy( [...srcArray], 'itemPrice', 'desc' );
let sortedArray4 = ojx.sortBy( [...srcArray], 'firstName' );

// also you can
let sortedArray5 = [ ...srcArray ];
sortedArray5.__sortBy('firstName');

console.log( sortedArray5 );

{ }.__valueOfPath | ojx.valueOfPath

Deeply retrieves a value from an object/array using a string path.


/**
 * Deeply retrieves a value from an object/array using a string path.
 * Supports: "address.city", "tags[0]", "orders.0.id"
 */
// ojx.valueOfPath(obj, path);
//-------------------------------------------------------------

const testDataX = {
  name: 'Unknown',
  age: 10,
  address: {
    billing: {
      address: 'billing address line',
      city: 'billing city',
      state: 'billing state',
      zip: '111111'
    },
    shipping: {
      address: 'shipping address line',
      city: 'shipping city',
      state: 'shipping state',
      zip: '222222'
    }
  }
};

ojx.valueOfPath(testDataX, 'address.shipping.zip');   // 222222

// OR

testDataX.__valueOfPath('address.shipping.zip');      // 222222

//-------------------------------------------------------------

const testDataY = [
    { id: 2, info: { name: "Beta", date: "2023-01-01" } },
    { id: 1, info: { name: "Alpha 10", date: "2021-01-01" } },
    { id: 3, info: { name: "Alpha 2", date: "2022-01-01" } },
    { id: 4, info: null }
  ];

ojx.valueOfPath(testDataY, '[0].id');        // 2

ojx.valueOfPath(testDataY, '1.info.name');   // "Alpha 10"

ojx.valueOfPath(testDataY, '[2].info.date'); // "2022-01-01"

ojx.valueOfPath(testDataY, 'info.name');     // undefined

ojx.valueOfPath(testDataY, '[3].info');      // null

//-------------------------------------------------------------

const testDataZ = [{ x: { y: [ { z: "found" } ] } }];

ojx.valueOfPath(testDataZ, "0.x.y[0].z"); // "found"
ojx.valueOfPath(testDataZ, "0.x.y.0.z");  // "found"

Type - ojx/type

Check type with ofType | ojx.ofType


// instead of typeof xyz === 'type'
// use ofType which returns / checks exact variable type; particularly for array and null.
let testNull   = null;
let testArray  = [];
let testString = '';
let testObject = {};

ofType( testNull );           // returns 'null'
ofType( testArray );          // returns 'array'
ofType( testArray, 'array' ); // returns true : alternate to Array.isArray(testArray)

ofType( document.getElementsByClassName('menu-item') ); // returns 'array-like'

function fx () {
  console.log(typeof arguments, ofType(arguments), ofClass(arguments) ); // object array-like Arguments
};

Get Class with ofClass | ojx.ofClass


ofClass( document.querySelectorAll('h1') );     // 'NodeList'
ofClass( document.getElementsByTagName('h1') ); // 'HTMLCollection'
ofClass( document.querySelector('h1') );        // 'HTMLHeadingElement'

Test Empty with isEmpty


let testArrayX  = [];
let testStringX = '';
let testObjectX = {};

isEmpty( testArrayX );  //returns true
isEmpty( testStringX ); //returns true
isEmpty( testObjectX ); //returns true

Date/Time - ojx/data-time

dateYYYYMMDD | ojx.dateYYYYMMDD


now();                            // returns current timestamp

dateYYYYMMDD();                   // returns current date in YYYYMMDD   - ex: 20031206
dateYYYYMMDD( '-' );              // returns current date in YYYY-MM-DD - ex: 2003-12-06
dateYYYYMMDD( '/' );              // returns current date in YYYY/MM/DD - ex: 2003/12/06
dateYYYYMMDD( '/', dateObj );     // returns given date in YYYY/MM/DD

timeHHMMSS | ojx.timeHHMMSS


timeHHMMSS();                     // returns current time in HHMMSS   - ex: 141030
timeHHMMSS( ':' );                // returns current time in HH:MM:SS - ex: 14:10:30
timeHHMMSS( ':', dateObj );       // returns given time in HH:MM:SS

Storage - ojx/storage for sessionStorage and localStorage utils


let storage = sessionStorage; // or localStorage

storage.user();                         // get current userStoreToken
storage.user( 'userID' );               // set current userStoreToken

storage.getUserItemStr( 'key' );        // get raw value as string
storage.getUserItem( 'key' );           // get parsed value

storage.setUserItemStr( 'key', value ); // store value as raw string
storage.setUserItem( 'key', value );    // store value as JSON String;

storage.removeUserItem( 'key' );        // remove user key-value

storage.entries();                      // return all entries (value:string)
storage.entries( true );                // return all entries (parsed=true) as js object
storage.userEntries();                  // return only current user entries (value:string)
storage.userEntries( true );            // return current user entries (parsed=true) as js object

File system - ojx/file-system

fs.readFileContent | ojx.readFileContent


function callbackFnOnSuccess ( fileContent ) {
  // ... ... ...
}
function callbackFnOnError ( error ) {
  // ... ... ...
}

fs.readFileContent( callbackFnOnSuccess );
fs.readFileContent( callbackFnOnSuccess, callbackFnOnError );
fs.readFileContent( callbackFnOnSuccess, callbackFnOnError, fileTypes );
fs.readFileContent( callbackFnOnSuccess, fileTypes );

// fileTypes: any text file extensions - Ex: '.txt,.html,.css,.js,.json,.yaml,.yml,.csv'

fs.saveToDisk | ojx.saveToDisk

// ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...

fs.saveToDisk(fileContent, fileName);

Libs - ojx/libs

Export ko and jQuery($) to window, so you don't have to require in every modules with ['knockout', 'jquery'].


Write less, done fast 🚀

Happy coding until your company replaces you with AI Agents!