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 🙏

© 2024 – Pkg Stats / Ryan Hefner

oxm

v5.0.2

Published

Round-tripable Object-XML mapper. Using knockout.js observables, you can bind the values to your view too.

Downloads

8

Readme

OXM

Round-tripable Object-XML mapper. Using knockout.js observables, you can bind the values to your view too.

Terms

accessor

Function which sets or gets the value of a variable.

data

OXM wrapped accessor, storing a single value.

list

OXM wrapped accessor, storing a list of similar oxm objects.

complex

OXM wrapped accessor, storing an Object.

oxm object

A data, list or complex.

Exported methods

xml

xml(obj)

Returns the xml string representing the data stored in the obj oxm_object.

xml(obj, xml)

Parses the xml [string] and updates the value of the obj oxm_object.

data

data(acc, tag)

Extends the acc accessor, and sets the tagnName of its xml representation to tag. acc will be used as a data object.

list

list(acc, tag, Child)

Extends the acc accessor, and sets the tagnName of its xml representation to tag. acc will be used as a list object. Child is the constructor of the list items. Used when parsing.

complex

complex(acc, tag, items)

Extends the acc accessor, and sets the tagnName of its xml representation to tag. acc will be used as a complex object. items is an Array of keys used when serializing and parsing.

Methods on OXM Objects

xml

obj.xml() Returns the node (xmldom), representing the data of obj oxm_object.

obj.xml(node) Parses the node (xmldom) and updates the data in obj oxm_object.

js

This helper method makes it possible to recursively convert between oxm objects and unwrapped JS values.

data.js() Calls accessor() and returns it's value.

data.js(value) Calls accessor(value).

list.js() Maps oxm_object.js on the Array returned from accessor(), and returns the new Array.

list.js(array) Calls (new Child()).js(item) on each items in array, and stores the resulting array.

complex.js() Maps the stored Object's items (returned from accessor()) with oxm_object.js, and returns the new Object.

complex.js(obj) Maps obj's items and stores them in accessor.

Usage

  • In browser with browserify
  • In Node

Example

Shoppig cart



var oxm = require("../lib/index.js");
var ko = require("knockout");

// easy date handling
var moment = require("moment");

// pretty printing xml
var pd = require("pretty-data").pd;



// can store a date (mementjs)
var typeDate = function() {
    return ko.computed({
        "read": function() {
            var value = this();
            if (typeof value === "undefined" || value === null) {
                return null;
            } else {
                return value.format("YYYY.MM.DD");
            }
        },
        "write": function(v) {
            if (typeof v === "undefined" || v === null || v === "") {
                this(null);
            } else {
                var parsed = moment(v, "YYYY.MM.DD");

                if (!parsed.isValid()) {
                    throw "Cannot parse date: '" + v + "'";
                }

                this(parsed);
            }
        },
        "owner": ko.observable(null)
    });
};

// can store a double
var typeDouble = function() {
    return ko.computed({
        "read": function() {
            return this();
        },
        "write": function(v) {
            if (typeof v === "undefined" || v === null || v === "") {
                return this(null);
            } else {
                var parsed = parseFloat(v);
                if (isNaN(parsed)) {
                    throw new Error("Cannot parse number: '" + v + "'");
                }

                return this(parsed);
            }
        },
        "owner": ko.observable(null)
    });
};

// can store an integer
var typeInt = function() {
    return ko.computed({
        "read": function() {
            return this();
        },
        "write": function(v) {
            if (typeof v === "undefined" || v === null || v === "") {
                return this(null);
            } else {
                var parsed = parseInt(v, 10);
                if (isNaN(parsed)) {
                    throw new Error("Cannot parse number: '" + v + "'");
                }

                return this(parsed);
            }
        },
        "owner": ko.observable(null)
    });
};


// defining fields:

var Name = function() {
    return oxm.data(ko.observable(null), "name");
};

var Price = function() {
    return oxm.data(typeDouble(), "price");
};

var Product = function() {
    return oxm.complex(ko.observable({
        "name": new Name(),
        "price": new Price()
    }), "product", ["name", "price"]);
};

var Count = function() {
        return oxm.data(typeInt(), "count");
};

var Item = function() {
    return oxm.complex(ko.observable({
        "product": new Product(),
        "count": new Count()
    }), "item", ["product", "count"]);
};

var Items = function() {
    return oxm.list(ko.observableArray([]), "items", Item);
};

var OrderDate = function() {
    return oxm.data(typeDate(), "order-date");
};

var Cart = function() {
    var internal = {};
    var cart = oxm.complex(ko.observable(internal), "cart", ["order-date", "items", "sum"]);

    internal["order-date"] = new OrderDate();
    internal["items"] = new Items();

    // stores nothing, but calculetes the cart sum price on serialization

    internal["sum"] = oxm.data(function() {
        var items = internal["items"].js();

        var s = 0;

        for (var i = 0; i < items.length; i += 1) {
            s += items[i].count * items[i].product.price;
        }

        return s;
    }, "sum");

    return cart;
};

// Create a cart object

var cart1 = new Cart();

// Fill it with data
cart1.js({
    "order-date": "2017.01.21",
    "items": [
        {
            "product": {
                "name": "A fancy car",
                "price": 99999.99
            },
            "count": 2
        },
        {
            "product": {
                "name": "Bread",
                "price": 1.00
            },
            "count": 1
        }
    ]
});

// Create another cart
var cart2 = new Cart();

// Clone the data
cart2.js(cart1.js());

/*
You can duplicate data with the xml methods too:

cart2.xml(cart1.xml()); // serializing/parsing values as nodes (xmldom)
oxm.xml(cart2, oxm.xml(cart1)); // serializing/parsing values as xml string
*/

// Add a new item to the cart
var milk = new Item();

milk.js({"product": {"name": "Milk", "price": 2}, "count": 5});
cart2()["items"]().push(milk);


console.log(pd.xml(oxm.xml(cart1)));

/* output:

<cart>
  <order-date>2017.01.21</order-date>
  <items>
    <item>
      <product>
        <name>A fancy car</name>
        <price>99999.99</price>
      </product>
      <count>2</count>
    </item>
    <item>
      <product>
        <name>Bread</name>
        <price>1</price>
      </product>
      <count>1</count>
    </item>
  </items>
  <sum>200000.98</sum>
    </cart>

*/

console.log(JSON.stringify(cart1.js(), null, "\t"));

/* output:

{
        "order-date": "2017.01.21",
        "items": [
                {
                        "product": {
                                "name": "A fancy car",
                                "price": 99999.99
                        },
                        "count": 2
                },
                {
                        "product": {
                                "name": "Bread",
                                "price": 1
                        },
                        "count": 1
                }
        ],
        "sum": 200000.98
}

*/

console.log(pd.xml(oxm.xml(cart2)));

/* output:

<cart>
  <order-date>2017.01.21</order-date>
  <items>
    <item>
      <product>
        <name>A fancy car</name>
        <price>99999.99</price>
      </product>
      <count>2</count>
    </item>
    <item>
      <product>
        <name>Bread</name>
        <price>1</price>
      </product>
      <count>1</count>
    </item>
    <item>
      <product>
        <name>Milk</name>
        <price>2</price>
      </product>
      <count>5</count>
    </item>
  </items>
  <sum>200010.98</sum>
</cart>

*/

console.log("Cart 1 sum: " + cart1().sum()); // Cart 1 sum : 200000.98
console.log("Cart 2 sum: " + cart2().sum()); // Cart 1 sum : 200010.98