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

proxymity

v2.0.4

Published

Proxymity is a 1 way binding library that can be used to render and renderer complex views with fast updates.

Downloads

12

Readme

About

Proxymity is a 1 way data binding library with the aim to keep everything as simple and close to vanilla javascript and html as possible. Because it's a library and not a framework, you are in control the whole way through.

Quickstart

script.js

var view = proxymity(document.querySelector("body"), {}, "controller")
var controller = view.controller
var sequence = [0, 1]
controller.fibonacci = function(n){
	if (n < 0){
		return 0;
	}
	return sequence[n] || (sequence[n] = controller.fibonacci(n - 2) + controller.fibonacci(n - 1))
}

index.html

<!DOCTYPE html>
<html>

	<head>
		<script src="/path/to/proxymity.min.js"></script>
		<style>
			body.this {
				opacity: 0;
			}
		</style>
	</head>

	<body class="{: void this :}">
		<h1>Welcome {:this.controller.user.name:}|{user.name}|</h1>
		<div>
			name: <input type="text" onkeyup="this.controller.user.name = this.value" data-value="{:this.controller.user.name:}|{user.name}|">
		</div>
		<div>
			age: <input type="number" onkeyup="this.controller.user.age = this.valueAsNumber" data-value="{:this.controller.user.age:}|{user.age}|">
		</div>
		<p>
			The Fibonacci number associated with your age is {:this.controller.fibonacci(parseInt(this.controller.user.age)):}|{user.age}|
		</p>

		<script src="script.js"></script>
	</body>
</html>

lets go through this chunks at a time

Head

<head>
	<script src="/path/to/proxymity.min.js"></script>
	<style>
		body.this {
			opacity: 0;
		}
	</style>
</head>

The script tag is pretty self explanatory, you may be wondering why we have a selector for body.this. The reason for this class is to hide the html from view before we're actually ready to go since the view is inlined rather than loaded in via ajax. Because anything separated by a space on both sides is recognized as a class to css, we can select for any pre-rendered elements this way as long as we space things right. you get the idea. Be creative and you'll find interesting solutions to problems!

Body

<body class="{: void this :}">
	...
</body>

The body element is the first instance of when we see how we render out data from our controller to the view. the syntax for this is {: code :} and in this case the code that we are running is " void this " which runs in the global scope with this being a reference of the current element that the code is attached to. This means that you can call any method/variable that you'd normally be able to call from the global scope

When the code gets executed the whole part will get replaced but until then, as far as the html parser is concerned, the body element has a class of "{:", "void", "this", and ":}" meaning we can take advantage of it

Body Continued

<h1>Welcome {:this.controller.user.name:}|{user.name}|</h1>
<div>
	name: <input type="text" onkeyup="this.controller.user.name = this.value" data-value="{:this.controller.user.name:}|{user.name}|">
</div>
<div>
	age: <input type="number" onkeyup="this.controller.user.age = this.valueAsNumber" data-value="{:this.controller.user.age:}|{user.age}|">
</div>
<p>
	The Fibonacci number associated with your age is {:this.controller.fibonacci(parseInt(this.controller.user.age)):}|{user.age}|
</p>

Here we see the data binding in action. The name of each input element on the input is also used to denote where on the controller object the item should look for. Because it can only be connected to the controller object, we do not need to define this.controller on it.

You may also be noticing that the binding syntax is slightly different that there's 2 chunks. the first chunk that's wrapped inside {: ... :}. This chunk is the chunk that you execute. The next chunk is the chunk that is wrapped inside |{ ... }| which is the chunk that watches a specific path for changes. This path always starts at the root so you do not need to include this.controller in it. It specifies that the code within {: ... :} should be reran when a change to |{ ... }| happens.

However none of this actually works unless the body gets initialized.

Javascript Initialization

var view = proxymity(document.querySelector("body"), {}, "controller")
var controller = view.controller

Would you look at that, the first thing we do is initialize the html with the proxymity function. Next, we save the controller into our current run time.

Fibonacci

var sequence = [0, 1]
controller.fibonacci = function(n){
	if (n < 0){
		return 0;
	}
	return sequence[n] || (sequence[n] = controller.fibonacci(n - 2) + controller.fibonacci(n - 1))
}

We could put this in a number of different places and we can implement this in a bunch of different ways such as the global scope or with true recursion but we're putting it here in the controller and caching our pre-calculated numbers in a variable called sequence

Why

"Isn't there already a plethora of frameworks and libraries out there that does exactly this and more? Why are you re-inventing the wheel?" you may ask. The answer is, simplicity. Majority of other libraries that accomplish this take one of 2 routs because of the nature of this problem. The first rout is to create an all encompassing framework that is in control the whole way through (eg: angular) and your code is called when it sees fit. This means that it will always knows when it calls your code and when to (re)render when needed. The other approach to solving this problem is to use a pre-compiler and specialized languages which will accomplish a similar effect of knowing where and when you're updating the data. Both of these approaches works but both will take you some distance from the native JavaScript and HTML that most beginners and even many experts are more familiar with.

In the case of an all encompassing framework (like angular) issue arises when your code needs to do something that's not a part of the framework's supported operations (eg: Web sockets and WebAssembly) and you spend time trying to get it to play nice with your framework of choice (fortunately, angular has $apply). In the case of a pre-compiled solution, the problem is you are stuck with an overhead of learning the new language that your pre-compiler uses and whatever dev you bring onto your team either needs to learn how to work with this new intermediary language and also the overhead of trying to set everything up just right the first time around (we all know how much this sucks)

Proxymity takes a different approach to both sides where it does not use a pre compiler nor does it run your code inside an all encompassing framework. Instead, it runs it's own render cycle and as long as your code is modifying data that proxymity is keeping tabs on, it will know when to re-render. This means that there is no pre-compiler in the mix and the library that connects everything only handles one thing, converting data => view. You are in control of everything else meaning there's no restrictions of what kind of other tech you can use in conjunction nor is there a major learning process associated to working with the code base.

How??

Proxymity tries to be as small and as out of the way as possible letting you be as close to the native JavaScript and HTML. Earlier iterations accomplished this by using the Proxy API in JavaScript which is where this library gets it's name. however, as of version 2.0.0, this is no longer the case.

the magic happens in the templating language of the library where you define what the action is and what that specific segment of template should react to if anything and using this info, Proxymity's able to reconstruct the paths to watch as watchable and then watch for changes on those paths.

docs

Docs are work in progress but here you go :)

License

MIT = free for all yay :D?

Get it on NPM

npm i proxymity