1 | /*
|
2 | * Copyright (c) 2012 VMware, Inc. All Rights Reserved.
|
3 | *
|
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 | * of this software and associated documentation files (the "Software"), to
|
6 | * deal in the Software without restriction, including without limitation the
|
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
8 | * sell copies of the Software, and to permit persons to whom the Software is
|
9 | * furnished to do so, subject to the following conditions:
|
10 | *
|
11 | * The above copyright notice and this permission notice shall be included in
|
12 | * all copies or substantial portions of the Software.
|
13 | *
|
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
20 | * IN THE SOFTWARE.
|
21 | */
|
22 |
|
23 | (function (define, document) {
|
24 | ;
|
25 |
|
26 | define(function (require) {
|
27 |
|
28 | var beget, absoluteUrlRE, urlEncodedBraceOpenRE, urlEncodedBraceCloseRE;
|
29 |
|
30 | beget = require('./util/beget');
|
31 |
|
32 | absoluteUrlRE = /^https?:\/\//i;
|
33 | urlEncodedBraceOpenRE = /%7b/i;
|
34 | urlEncodedBraceCloseRE = /%7d/i;
|
35 |
|
36 | /**
|
37 | * Apply params to the template to create a URL.
|
38 | *
|
39 | * Parameters that are not applied directly to the template, are appended
|
40 | * to the URL as query string parameters.
|
41 | *
|
42 | * @param {string} template the URI template
|
43 | * @param {Object} params parameters to apply to the template
|
44 | * @return {string} the resulting URL
|
45 | */
|
46 | function buildUrl(template, params) {
|
47 | // internal builder to convert template with params.
|
48 | var url, name, queryStringParams, re;
|
49 |
|
50 | url = template;
|
51 | queryStringParams = {};
|
52 |
|
53 | if (params) {
|
54 | for (name in params) {
|
55 | /*jshint forin:false */
|
56 | re = new RegExp('\\{' + name + '\\}');
|
57 | if (re.test(url)) {
|
58 | url = url.replace(re, encodeURIComponent(params[name]), 'g');
|
59 | }
|
60 | else {
|
61 | queryStringParams[name] = params[name];
|
62 | }
|
63 | }
|
64 | for (name in queryStringParams) {
|
65 | url += url.indexOf('?') === -1 ? '?' : '&';
|
66 | url += encodeURIComponent(name);
|
67 | if (queryStringParams[name] !== null && queryStringParams[name] !== undefined) {
|
68 | url += '=';
|
69 | url += encodeURIComponent(queryStringParams[name]);
|
70 | }
|
71 | }
|
72 | }
|
73 | return url;
|
74 | }
|
75 |
|
76 | /**
|
77 | * Create a new URL Builder
|
78 | *
|
79 | * @param {string|UrlBuilder} template the base template to build from, may be another UrlBuilder
|
80 | * @param {Object} [params] base parameters
|
81 | * @constructor
|
82 | */
|
83 | function UrlBuilder(template, params) {
|
84 | if (template instanceof UrlBuilder) {
|
85 | this._template = template.template;
|
86 | this._params = beget(this._params, params);
|
87 | }
|
88 | else {
|
89 | this._template = (template || '').toString();
|
90 | this._params = params;
|
91 | }
|
92 | }
|
93 |
|
94 | UrlBuilder.prototype = {
|
95 |
|
96 | /**
|
97 | * Create a new UrlBuilder instance that extends the current builder.
|
98 | * The current builder is unmodified.
|
99 | *
|
100 | * @param {string} [template] URL template to append to the current template
|
101 | * @param {Object} [params] params to combine with current params. New params override existing params
|
102 | * @return {UrlBuilder} the new builder
|
103 | */
|
104 | append: function (template, params) {
|
105 | // TODO consider query strings and fragments
|
106 | return new UrlBuilder(this._template + template, beget(this._params, params));
|
107 | },
|
108 |
|
109 | /**
|
110 | * Create a new UrlBuilder with a fully qualified URL based on the
|
111 | * window's location or base href and the current templates relative URL.
|
112 | *
|
113 | * Path variables are preserved.
|
114 | *
|
115 | * *Browser only*
|
116 | *
|
117 | * @return {UrlBuilder} the fully qualified URL template
|
118 | */
|
119 | absolute: function () {
|
120 | if (!document || absoluteUrlRE.test(this._template)) { return this; }
|
121 |
|
122 | var a, template;
|
123 |
|
124 | a = document.createElement('a');
|
125 | a.href = this._template;
|
126 | template = a.href.replace(urlEncodedBraceOpenRE, '{').replace(urlEncodedBraceCloseRE, '}');
|
127 |
|
128 | return new UrlBuilder(template, this._params);
|
129 | },
|
130 |
|
131 | /**
|
132 | * Expand the template replacing path variables with parameters
|
133 | *
|
134 | * @param {Object} [params] params to combine with current params. New params override existing params
|
135 | * @return {string} the expanded URL
|
136 | */
|
137 | build: function (params) {
|
138 | return buildUrl(this._template, beget(this._params, params));
|
139 | },
|
140 |
|
141 | /**
|
142 | * @see build
|
143 | */
|
144 | toString: function () {
|
145 | return this.build();
|
146 | }
|
147 |
|
148 | };
|
149 |
|
150 | return UrlBuilder;
|
151 | });
|
152 |
|
153 | }(
|
154 | typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); },
|
155 | this.document
|
156 | // Boilerplate for AMD and Node
|
157 | ));
|