UNPKG

4.9 kBJavaScriptView Raw
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 'use strict';
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));