Code Monkey home page Code Monkey logo

domurl's Introduction

domurl 2.x (former jsurl)

Build Status GitHub license

Lightweight URL manipulation with JavaScript for both DOM and server JavaScript.

Goal

To have a convenient way working with URLs in JavaScript. From time to time there are usual tasks when it is required to add or remove some parameters to some basic URL or change some other URL parts.

There is no easy standard way to do it in JavaScript.

This small library intended to fix that problem

Supported Browsers

This library was tested under:

  • IE 7+
  • Chrome 25+
  • Opera 12.15+
  • Firefox 20+
  • Android browser 2.3+
  • NodeJS 0.10+

Theoretically it should work fine with newer or older versions of these browsers, but it was not fully tested yet. If you'll find any compatibility issues, please, let me know by leaving a bug report here: https://github.com/Mikhus/domurl/issues

You can run basic tests for your browser here: https://rawgit.com/Mikhus/domurl/master/test/url.html or run test.html from this repository locally. If any test has not been passed, please, open a bug report as described above providing browser and OS version on each test which has been failed.

How To Use

First of all it is required to include Url class on the page. It can be simply done as

<script src="url.min.js"></script>

Then any time it's required to do some work over the URL string, it's just required to instantiate the Url object and work with that object instead of initial string. See API description below to get a clue.

Install with JAM

It is possible also to install domurl via JAM repository (http://jamjs.org/). Could be simply done as:

$ jam install domurl

Install with Bower

It is also possible now to install domurl using Bower package repository. Could be done simply as:

$ bower install domurl

Install with NPM

Domurl is available on NPM and is now works well for both server and browser:

$ npm install domurl

API

Methods:

Url({string} [url], {boolean} [noTransform]) -> {Url}

Constructor. If url argument is not passed, current document URL will be used. If second argument bypassed as true value it will try to do no transforms on a given source URL to keep it form as it was initially given. Otherwise, by default, it will try to resolve given URL to an absolute form.

Url.toString() -> {string}

Converts URL to string representation. As far as it's special method, any time string operations is performed over Url objects this method is automatically called

Url.paths({Array} [pathStrings])

Returns Url.path representation as array or sets it via array representation if optional array of pathStrings was provided.

Url.encode({string} urlPart) -> {string}

Performs URI-compatible encoding of the given urlPart component. It works not the same as native encodeURIComponent()!

Url.decode({string} encUrlPart) -> {string}

Performs decoding of URI-encoded component. It works not the same as native decodeURIComponent()!

Url.clearQuery() -> {Url}

Removes all query string parameters from the URL

Url.queryLength() -> {Number}

Returns total count of the query string parameters.

Url.isEmptyQuery() -> {boolean}

Returns true if query string contains no parameters, false otherwise.

Properties:

Url.protocol - protocol part of URL, everything between the beginning of the URL string and "://" delimiter (if specified)

Url.user - auth user name (if specified)

Url.pass - auth user password (if specified)

Url.host - host name (if specified)

Url.port - port number (if specified)

Url.path - document path

Url.query - QueryString object. It's a simple Javascript object with automatic string mapping. String representation contains everything after "?" and to the end of QueryString

Url.hash - Anchor part of the URL. Everything after "#" and to the end of anchor

Usage Examples

var u  = new Url; // current document URL will be used
// or we can instantiate as
var u2 = new Url( "http://example.com/some/path?a=b&c=d#someAnchor");
// it should support relative URLs also
var u3 = new Url( "/my/site/doc/path?foo=bar#baz");

// get the value of some query string parameter
alert( u2.query.a);
// or
alert( u3.query["foo"]);

// Manupulating query string parameters
u.query.a = [1, 2, 3]; // adds/replaces in query string params a=1&a=2&a=3
u.query.b = 'woohoo';  // adds/replaces in query string param b=woohoo

if (u.query.a instanceof Array) { // the way to add a parameter
  u.query.a.push(4); // now it's "a=1&a=2&a=3&a=4&b=woohoo"
}

else { // if not an array but scalar value here is a way how to convert to array
  u.query.a = [u.query.a];
  u.query.a.push(8)
}

// The way to remove the parameter:
delete u.query.a
// or:
delete u.query["a"]

// If you need to remove all query string params:
u.clearQuery();
alert( u);

// Lookup URL parts:
alert(
    'protocol = ' + u.protocol + '\n' +
    'user = ' + u.user + '\n' +
    'pass = ' + u.pass + '\n' +
    'host = ' + u.host + '\n' +
    'port = ' + u.port + '\n' +
    'path = ' + u.path + '\n' +
    'query = ' + u.query + '\n' +
    'hash = ' + u.hash
);

// Manipulating URL parts
u.path = '/some/new/path'; // the way to change URL path
console.log(u.paths());
u.paths(['some', 'new', 'path']); // change path by array of strings
console.log(u.path);
u.protocol = 'https' // the way to force https protocol on the source URL

// inject into string
var str = '<a href="' + u + '">My Cool Link</a>';

// or use in DOM context
var a = document.createElement('a');
a.href = u;
a.innerHTML = 'test';
document.body.appendChild( a);

// Stringify
u += '';
String(u);
u.toString();
// NOTE, that usually it will be done automatically, so only in special
//       cases direct stringify is required

License

This code is available under MIT license. Feel free to do what you want.

domurl's People

Contributors

alexkeysmith avatar besfahbod avatar dudeofprosper avatar esroyo avatar jdeniau avatar joelbesada avatar joker-777 avatar jsteunou avatar leoriviera avatar longzheng avatar mikhus avatar reiz avatar timgates42 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

domurl's Issues

Relative protocol not honoured in IE

(Found in IE10)

new Url('//url-with-relative-protocol.co.uk/blah').toString();
// actual     ->  'url-with-relative-protocol.co.uk/blah'
// expected 1 ->  '//url-with-relative-protocol.co.uk/blah'
// expected 2 ->  [current page's protocol] + '//url-with-relative-protocol.co.uk/blah'

URL Path is over-escaped for *special characters* such as SEMICOLON, COLON, EQUALS SIGN

Last paragraph of https://tools.ietf.org/html/rfc3986#section-3.3 says:

Aside from dot-segments in hierarchical paths, a path segment is
considered opaque by the generic syntax. URI producing applications
often use the reserved characters allowed in a segment to delimit
scheme-specific or dereference-handler-specific subcomponents. For
example, the semicolon (";") and equals ("=") reserved characters are
often used to delimit parameters and parameter values applicable to
that segment. The comma (",") reserved character is often used for
similar purposes. For example, one URI producer might use a segment
such as "name;v=1.1" to indicate a reference to version 1.1 of
"name", whereas another might use a segment such as "name,1.1" to
indicate the same. Parameter types may be defined by scheme-specific
semantics, but in most cases the syntax of a parameter is specific to
the implementation of the URI's dereferencing algorithm.

This means, these special characters can be present in path, carrying special information.

In other words, they are supposed to be escaped only if they are expected not to carry the special information, like if they appear in a directory name on the file-system.

On Chrome, these comparisons are all truthful:

String(new URL("http://example.com/alice=bob")) == "http://example.com/alice=bob"
String(new URL("http://example.com/alice;bob")) == "http://example.com/alice;bob"
String(new URL("http://example.com/alice,bob")) == "http://example.com/alice,bob"

I think domurl should be able to parse and re-gen those values as well. Wdyt?

add to bower

Very nice peace of code, it will be cool and useful to add it as bower package!

Query parameters are not decoded when using lowercase hex codes

This code gives proper result:

>>> new Url('http://localhost/?a=%3F').query.a
"?"
>>> new Url('http://localhost/?a=%3F').toString()
"http://localhost/?a=%3F"

And this does not decode query parameters, resulting in double-encoding when using toString():

>>> new Url('http://localhost/?a=%3f').query.a
"%3f"
>>> new Url('http://localhost/?a=%3f').toString()
"http://localhost/?a=%253f"

Array/object url is encoded/decoded in the wrong way

This u.query.a = [1, 2, 3]; creates a=1&a=2&a=3 while the correct is a[0]=1&a[1]=2&a[2]=3
The currently generated URL can lead to query overload, which depends on the server (apache, lighttpd or Microsoft) understand differently. While the second one is the correct array GET structure.
In languages where associative array exists, the following is also valid:
For u.query.a = ['key1' => 1, 'key5' => 2, 'key3' => 3]; represented as a[key1]=1&a[key5]=2&a[key3]=3, this is most probably represented in JS as an object like u.query.a = {"key1": 1, "key5": 2, "key3": 3};.
Also, servers support multidimensional array/objects, which's not supported here.
u.query.a = [1, [2, 5], 3]; as a[0]=1&a[1][0]=2&a[1][1]=5&a[2]=3
u.query.a = {"key1": 1, "key5": [2, 5], "key3": 3}; as a[key1]=1&a[key5][0]=2&a[key5][1]=5&a[key3]=3
u.query.a = {"key1": 1, "key5": {"key1": 2, "key6": 5}, "key3": 3}; as a[key1]=1&a[key5][key1]=2&a[key5][key6]=5&a[key3]=3

"A security problem occurred" in Edge with @

In MS Edge, if you pass a malformed url like http://Photo@ to the Url constructor of this library, you get a mysterious exception "A security problem occurred". You can see the same error by just running var link = document.createElement("a"); link.href = "http://Photot@"; link["protocol"]; in console. It would be better if domurl caught this and raised a more understandable error.

Does not work with arrays (e.g. https://example.com/?computer[desktop]=Mac)

var u2 = new Url("https://example.com/");
u2.query["computer"] = {};
u2.query["computer"]["desktop"] = "Mac";	
alert(u2); 

The result should be this...
https://example.com/?computer[desktop]=Mac

Instead, I get this...
https://example.com/?computer=%5Bobject%20Object%5D

Also, when I parse a URL that looks like....
https://example.com/?computer[desktop]=Mac

...Inspecting the object in the console should look like return something like...

Computer: Object
	desktop: "Mac"

Instead I get this...
computer[desktop]: "Mac"

"desktop" isn't recognized as an object inside of "computer". "computer[desktop]" is simply used as the key like any other string.

Bower: no versions available

Some tools that use Bower expect a package to have versions associated with it. Bower can't find any versions for the jsurl package because there are no git tags pushed for this repo. See:
screen shot 2014-07-17 at 10 24 41 am

Please push a git tag for this project. See here for more information: http://stackoverflow.com/a/20055632

When passing a relative url into Url() and converting to string, the current pages path is included

I've written a simple function that cleans some query strings out of any provide url string:
function sanitizeURL(url) { var url = new Url(url); if(url.query["reload"]) { delete url.query["reload"] } if(url.query["forceReload"]) { delete url.query["forceReload"] } if(url.query["device"]) { delete url.query["device"] } if(url.query["testwebid"]) { delete url.query["testwebid"] } if(url.query["testWebId"]) { delete url.query["testWebId"] } if(url.query["testWebID"]) { delete url.query["testWebID"] } if(url.query["timetravel"]) { delete url.query["timetravel"] } return url.toString(); }
but when I add run with a relative url string the whole pages path is returned:
sanitizeURL("SearchResults?search=new&make=Buick&year=2016&forceReload=true")

What's returned:
"file:///Volumes/Macintosh%20HD/Users/brooksg/SearchResults?search=new&make=Buick&year=2016"

Expecting:
"SearchResults?search=new&make=Buick&year=2016"

Is there anyway around this or is this a bug?

Support TypeScript

Hello!
You didn't think about language support for TypeScript? I could write a file jsurl.d.ts, and push it to the DefinitelyTyped repository which would be a description of the library functions.

Consider adding tags for the repo.

Hi @Mikhus

Your great work had been recommend being added in CDNJS.
However, we need tags for repo to specify points in history and mark release points.
It's helpful for users to know the version and status of repository, and would enable wider distribution of the library.
Would you please consider on using tags?

Thank you!
Piicksarn
#6428

localhost:port not supported

var url = new Url("localhost:9001");
console.log(url, '' + url);
Url {protocol: "localhost", host: "", port: "", path: "/9001", query: QueryString…}
hash:""
host:""
pass:""
path:"/9001"
port:""
protocol:"localhost"
query:QueryString
user:""
__proto__:Object

localhost:///9001

Small issues in encoding URLs with param values null and undefined

Looks like the changes in 1a605a5 have made some of the decoding and encoding behaviors asymmetric.

First, a loop on a valid URL causes value-less params to get lost. So, this doesn't pass:

const urlString1 = "/?alice=123&bob=&carol";
const url1 = new Url(urlString1);
expect(String(url1)).toEqual(urlString1);

with error:

    Expected: "/?alice=123&bob=&carol"
    Received: "/?alice=123&bob="

After decoding, this does pass:

const urlString1 = "/?alice=123&bob=&carol";
const url1 = new Url(urlString1);
expect(url1.query["alice"]).toEqual("123");
expect(url1.query["bob"]).toEqual("");
expect(url1.query["carol"]).toBe(null);
expect(url1.query["dave"]).toBe(undefined);

So, the problem lays on the encoding side. With changing the encoding logic to:

  • drop param if value is undefined, and
  • keep param without value if the value is null,
    then we can make sure using values returned from .query to reconstruct the URL would result in the original URL, hence passing the initial test.

What do you think?

Current url, once initialized, is cached forever and never reflects changes to window.location.href

When initializing with new Url(), this module uses the current window.location.href by default, and then caches it forever in the module's closure/namespace. After that, even when the window.location.href changes, the module will still use the old/incorrect cached value on new Url() invocations:

var url = new Url();
url.hash = "somehash";
window.location.href = url.toString()
var url2 = new Url();
url2.hash // empty, should be "somehash"

Also note that in apps using pushState (i.e. most SPAs these days), much more than the hash will change. The above is just one way to demonstrate the bug in a non-pushState navigation without causing a page reload.

Undefined variables included in query string

Variables with a value of undefined are included in the query string.

For example:

var url = new Url();
var url2 = new Url();
url2.clearQuery();
url2.query["var"] = url.query["var"];

ur2.query.toString()

If "var" doesn't exist in the query string, this will print out "var=undefined". Could undefined variables be ignored?

Support Protocol-relative URL (PRL)

Levels of support can be like:

  1. Parsing PRL strings into an object and then back to the string should work out of the box.
  2. Allow generation of PRL from a relative URL.
  3. Allow downgrading a URL with protocol into a PRL.

Specifically, (1) is very important when using the library on href values, which can be intentionally kept as PRL, for better client support.

References:

What do you think?

TypeError thrown when used inside a srcdoc iframe

Hi,

I've found an issue when one of our scripts that use domurl was injected inside a srcdoc iframe.

That is an strange case, but I though It may be worth mentioning it.

Here there is a minimal example:

<!doctype html>
<html>
<body>
<iframe srcdoc='<script src="https://cdn.jsdelivr.net/npm/[email protected]/url.js" integrity="sha256-4NOatzFOPdRvADrRwu+TbGMS2LQNQ0ZEseTjM1sdFj4=" crossorigin="anonymous"></script><script>var url = new Url("/robots.txt");</script>'></iframe>
</body>
</html>

Output:

TypeError: getCurrUrl(...).match(...) is null

What do you think? It feels like something that should be "gracefully" handled? A bit difficult may be.

Thanks

Doesn't actually manipulate the URL?

Was looking for something similar to your library. I'm looking through the code and just want to confirm, this only allows you to update the object created by instantiating the class. This doesn't actually update the URL when changes to the class are made? If this is the case it would be interesting to add some HTML5 history support to update the actual URL when changes are made to the domurl object. Reading the description of the project I assumed this was what it actually did.

I'm going to be modifying the library for my own use, to update the URL, if you're interested I'll try to form a complete solution and submit a pull request when I'm done. If not I'll just add the stuff I need in my project.

Thanks for taking the time to make this thing and sharing it 👍

How to use correctly in order to add to the URL

Hi, I'm trying to load UTM codes into the URL on page load; the alert pops up that it has successfully done so, but the URL in the browser doesn't reflect that... how do I do that?

I am calling the js file, then this is my script:

<script type="text/javascript"> var url = new Url('?utm_medium=dm&utm_source=cnst&utm_campaign=q114b&utm_content=ja14ml'); alert( url); </script>

Thanks!

Hash is encoded but...

I dont know if it's the right behavior. I'm actually using backbone and the way to describe routes (like many front-end framework) is with hash like foo/1 which become foo%2F1 when using domurl to manipulate query parameters.

Incorrect URL encoding

When init with url like this new Url('http://www.example.com/hello world here.jpg').toString()

returns: http://www.example.com/hello%2520world%2520here.jpg

expected result: 'http://www.example.com/hello%20world%20here.jpg'

Not sure why the space got encoded into %2520

When remove the protocol it works correctly:

new Url('www.example.com/hello world here.jpg').toString()
=> 'www.example.com/hello%20world%20here.jpg'

Problem with full URL

Attempt to parse the following URL causes the wrong result

var feed = new Url('https://www.google.com/calendar/feeds/test/private-t42423424234/full?start-index=1&max-results=20');
feed.toString() ->> returns
"https://www.google.com:443calendar/feeds/test/private-t42423424234/full?start-index=1&max-results=20"

There are two problems:

  • missing '/' after the host name
  • default port is present in the result url (not nice)

I have fixed it by changing toString() function to the following. Haven't tested it in all scenarios, by with full URL works fine

this.toString = function () {
return (
(this.protocol && (this.protocol + '://')) +
(this.user && (this.user + (this.pass && (':' + this.pass)) + '@')) +
(this.host && this.host) +
((this.port && !(this.port == 443 && this.protocol == 'https') && !(this.port == 80 && this.protocol == 'http')) ? this.port : '') +
(this.path && ('/' + this.path)) +
(this.query.toString() && ('?' + this.query)) +
(this.hash && ('#' + this.hash))
);
};

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.