URL.js или дружим JavaScript с обработкой ссылок

image

Доброго времени суток, уважаемые хабравчане!

Возникла передо мной сегодня задача генерации GET-параметров и всего URL в целом, на стороне клиента, прям вот щас, без возможности «поговорить» с сервером. Сразу оговорюсь, про этот пост я узнал вот прям перед написанием данной статьи ибо сначала закончил писать, а потом уже прибег к поиску, да и пост тот — не со всем про то же самое, что у меня.

Итак, к делу.

Задача и проблемы


Проблемы — те же что и в посте, который я привел выше:
  • Невозможность использовать window.location для «приготовления» URL;
  • Нельзя работать сразу с несколькими window.location в силу политики безопасности браузеров;
  • Отсутствие известных готовых решений ( да и сейчас, уже апосля, я не нашел подобного кода )

Задачи которые я поставил перед собой:
  • Удобный синтаксис
  • Возможность как читать части URL так и изменять их
  • Работа с GET-параметрами
  • Кроссбраузерность и универсальность


Писал я на чистейшем JavaScript, причем без использования prototype.__defineGetter__ или prototype.__defineSetter__ в угоду кроссбраузерности ибо IE < 9 такого не умеет. Более подробно про getters/setters написано в этом посте.

Для тех кому интересно — сядем разберем, а кому надо готовое решение — милости прошу в конец поста, ссылки на скачивание — там.

Приступим! Раньше сядем — раньше выйдем.


Конструктор


Код конструктора
var URL = function( param, param2 ){
	param = param || false;
	param2 = ( param2 === false ) ? false : true;
	
	this.urlEncode = param2;
	this.data = { scheme: false, user: false, pass: false, host: false, port: false, path: false, query: false, params: {}, fragment: false };
	
	if( typeof(param) == 'string' ){
		this.url = param;
		
		this.parse();
	} else if ( typeof(param) == 'object' ){
		for(var key in param){
			if( this.data.hasOwnProperty( key ) ){
				if( param[ key ] || ( key == 'params' && typeof(param.params) == 'object' ) )
					this.data[ key ] = param[ key ];
			}
		}
		
		this.update();
	}
}


Подробнее

  • Как я уже говорил — необходима универсальность. Т.е. возможность как работать с неполными урлами, так и вообще создавать оные с нуля, а поэтому мы можем как передать исходный URL в конструктор, передать туда хэш с нужными нам, соответствующими параметрами или же вовсе, не передавать ничего.
  • Все параметры урла хранятся в хэше ( в JS это просто объект с параметрами ), связано это с getters/setters о которых чуточку позже. Именованы они в стиле parse_url() из PHP, мне так просто удобнее.


Парсинг


Надо парсить уже имеющийся URL, делать мы это будем при помощи RegExp. Нет, можно конечно все обрабатывать при помощи str.split(), но это, как мне кажется — особый вид фетишизма.
regExp = /^(?:([a-z0-9_\-\.]+):\/\/)*(?:([a-z0-9_\-\.]+)(?:\:)*([a-z0-9_\-\.]+)*\@)*([a-z0-9][a-z0-9_\-\.]+)(?:\:([\d]+))*(?:\/([^?#]*))*(?:\?([^?#]*))*(?:\#([^?#]*))*/gi;

И по частям
  • (?:([a-z0-9_\-\.]+):\/\/)* — SCHEME, если верить википедии, то схема имеет вид ххх:// причем, там могут быть и - и _. В угоду универсальности, установлен * т.е. схема может быть и не указана.
  • (?:([a-z0-9_\-\.]+)(?:\:)*([a-z0-9_\-\.]+)*\@)* — USER:PASSWORD, пароля без юзернейма не бывает, а юзернейм без пароля бывает.
  • ([a-z0-9][a-z0-9_\-\.]+) — HOST, насколько я знаю, начинаться доменное имя может только с буквы/цифры, а дальше уже могут идти и — и _ и. Более того, не бывает доменных имен короче 6 символов, но ведь ссылки то бывают и внутрисетевые, где хостнеймами как хочешь так и рулишь, та что сойдет и 1+ символ.
  • (?:\:([\d]+))* — PORT, данный параметр опционален,: а далее цифры
  • (?:\/([^?#]*))* — PATH, путь до файла, в общем-то, по-идее, это любое количество любых символов, но, отсечем? и # дабы не спарсить в путь GET-параметры или фрагментарный указатель. Путь может быть и неуказан.
  • (?:\?([^?#]*))* — QUERY, набор GET-параметров, пар ключ=значение. Так же может быть и не указан.
  • (?:\#([^?#]*))* — FRAGMENT, фрагментарный указатель. Если кто не знает — то /index.html#fragment дает команду браузеру проскроллить к DOM-элементу с id="fragment"


Работать, ясное дело, будет на всех языках, понимающих RegExp. Пользуйтесь, не стесняйтесь.

Парсер
	parse: function(){
		this.res = /^(?:([a-z0-9_\-\.]+):\/\/)*(?:([a-z0-9_\-\.]+)(?:\:)*([a-z0-9_\-\.]+)*\@)*([a-z0-9][a-z0-9_\-\.]+)(?:\:([\d]+))*(?:\/([^?#]*))*(?:\?([^?#]*))*(?:\#([^?#]*))*/gi.exec( this.url );
		
		this.data.scheme = this.res[ 1 ] || false;
		this.data.user = this.res[ 2 ] || false;
		this.data.pass = this.res[ 3 ] || false;
		this.data.host = this.res[ 4 ] || false;
		this.data.port = this.res[ 5 ] || false;
		this.data.path = this.res[ 6 ] || false;
		this.data.query = this.res[ 7 ] || false;
		this.data.fragment = this.res[ 8 ] || false;
		
		if( this.data.query ){
			this.parts = this.data.query.split( '&' );
			for(  var i = 0; i < this.parts.length; i++ ){
				param = this.parts[ i ].split( '=' );
				this.data.params[ param[ 0 ] ] = decodeURIComponent( param[ 1 ] );
			}
		}
		

		delete this.res;	
		delete this.parts;	
	}


Тут ничего ничего сложного: разбиение по указанному выше regExp и сохранение данных в хеш this.data
Разве что, я упоминал ранее — необходима удобная работа с GET-параметрами урла, а посему разбиваем query при помощи split ( split() в данном случае «дешевле» чем regExp ) и сохраняем это в тот же пресловутый хэш. Стоит отметить использование decodeURIComponent, ведь GET-параметры могут быть urlencoded.

Вариант 1. «По красоте»


Getters/Setters


Для удобной работы с чтением/изменением параметров я решил выбрать JS way геттеры и сеттеры. T.e. метод по названию свойства и если метод вызывается с указанием параметра — это setter, если без параметра — это getter.
Объявлять я их буду через URL.prototype = { } дабы не плодить в памяти избыточные экземпляры метода.
В пример приведу один метод, в силу того что они похожи:
	scheme: function( param ){	
		if( typeof( param ) != 'undefined' ){
			this.data.scheme = param;
			
			return this.update();
		} else {
			return this.data.scheme ? this.data.scheme : false;
		}
	}

Замечу, что в случае изменения значения возвращается не String, а Object сделано это для того, чтобы можно было писать цепочки сеттеров:
var url = new URL();

url.scheme('https').host('example.com').path('index.php').params({'p1':"v1", 'p2':"в2"}).url;
// вернет: https://example.com/index.php?p1=v1&p2=%D0%B22


Отдельно остановимся на геттер/сеттере для свойства params
	params: function( param1, param2 ){
		if( typeof( param1 ) != 'undefined' ){
			if( typeof( param1 ) == 'string' ){
				if( typeof( param2 ) != 'undefined' && ( param2 == '' || param2 === false ) ){
					if( this.data.params.hasOwnProperty( param1 ) ){
						delete this.data.params[ param1 ];
					}
				} else if( typeof( param2 ) != 'undefined' ){
					this.data.params[ param1 ] = param2;
				} else{
					return this.data.params[ param1 ] ? this.data.params[ param1 ] : false;
				}
			} else if( typeof( param1 ) == 'object' ){
				for( var key in param1 ){
					if( typeof( param1[ key ] ) != 'undefined' && ( param1[ key ] == '' || param1[ key ] === false ) ){
						if( this.data.params.hasOwnProperty( key ) )
							delete this.data.params[ key ];
					} else{
						this.data.params[ key ] = param1[ key ];
					}
				}
			}
			
			return this.update();
		} else {
			return this.data.params ? this.data.params : false;
		}
	}

Как видим — оба параметра опциональные.
И как я говорил — я ставил перед собой целью — удобство работы с GET-параметрами, а значит мы должны уметь:
  • Читать
  • Изменять
  • Удалять

как отдельно взятый параметр так и группы параметров.

Соответственно синтаксис будет таков:
  • Не передается ни один параметр — читаем все GET-параметры
  • Передается только первый параметр — читаем один GET-параметр
  • Передается два параметра — пишем GET-параметр с именем param1 и значением param2
  • В качестве значения параметра передается пустое значение или false — указанный GET-параметр удаляется


Собираем URL обратно


Как вы заметили, в геттерах вызывается this.update() выполняет он 2 функции:
  • Собирает URL воедино, в свойстве url
  • Обновляет свойство query при манипуляциях с GET-параметрами

Код сборщика
	update: function(){
		this.data.query = '';
		for( var key in this.data.params ){
			this.data.query += this.urlEncode ? key+'='+encodeURIComponent( this.data.params[ key ] )+'&' : key+'='+this.data.params[ key ]+'&';
		}
		
		if( this.data.query )
			this.data.query = this.data.query.slice( 0, -1 );
		
		this.url = '';
		this.url += this.data.scheme ? this.data.scheme+'://' : '';
		this.url += this.data.user ? this.data.user+':' : '';
		this.url += this.data.pass ? this.data.pass+'@' : '';
		this.url += this.data.host ? this.data.host+'/' : '';
		this.url += this.data.path ? this.data.path : '';
		this.url += this.data.query ? '?'+this.data.query : '';
		this.url += this.data.fragment ? '#'+this.data.fragment : '';
		
		return this;
	}


Стоит отметить, что при сборке GET-параметров, значения параметров преобразуются в escape-последовательность.
Во-первых: это правильно.
Во-вторых: если мы GET-параметром передаем данные вводимые пользователем, то вставленный юзером амперсанд разрушит последовательность ключ-значение и все покатится в тартарары.

Ну, а если уж, прям кровь из носу, вам не нужна urlencoded строка — у вас два варианта:
Передаем вторым параметром в конструкторе false
  1. Вручную ставим свойство URL.urlEncode=false;
  2. Вызываем метод URL.update();

test = new URL({"path":"index.php", "params":{"param1":"value1", "param2":"значение параметра&"}}, false);
test.url;
//index.php?param1=value1¶m2=значение параметра&

test2 = new URL({"path":"index.php", "params":{"param1":"value1", "param2":"значение параметра&"}});
test2.url;
//index.php?param1=value1¶m2=%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D0%B0%26

test2.urlEncode=false;
test2.update().url;
//index.php?param1=value1¶m2=значение параметра&


Ну и чтобы было удобно — метод для перехода по сгенерированной ссылке:
	go: function(){
		if(!this.data.scheme && this.data.host)
			this.data.scheme = 'http';
		
		window.location.href = this.update().url;
	}

Как видно: если не указана схема, но указан хост — автоматически подставляется схема http как самая распространенная.
Далее происходит обновление ссылки и переход по оной.

Расширяем объект String


По идее, на этом можно было бы закончить. Но, мне показалось что было бы удобно работать прямо со строковыми переменными без явного создания экземпляра объекта (как бы странно это не звучало, но, в JS нет классов, как таковых).

Как обычно приведу пример одного метода:
String.prototype.scheme = function( param ){
	var url = new URL( this.valueOf() );
	
	if( typeof( param ) != 'undefined' ){
		url.scheme( param );
		result = url.url;
	} else{
		result = url.scheme();
	}
	delete url;
	
	return result;
}

В общем-то код просто передает параметры в соответствующий метод объекта URL.
Но некоторым может показаться странным тот момент, что я каждый вызов по-новой создаю и удаляю объекты URL и делаю только одно действие, причем это действие не меняет значения переменной над которой оно производится.
Вот тут то и кроется самое главное неудобство объекта String, нельзя менять значение существующей переменной. С ней вообще ничего нельзя сделать, ВСЕГДА создается новая переменная. А по-этому каждый раз создается новый объект и возвращается переменная типа String.
Цепочки конечно же поддерживаются:
url = 'example.com';

url.scheme('https').path('index.php').params({'p1':"v1", 'p2':"в2"});
// вернет: https://example.com/index.php?p1=v1&p2=%D0%B22


Вариант 2. «По Фен-Шуй»


Если предыдущий вариант, скажем так, был «красив»в использовании, то данный вариант, будет лаконичен. как с точки зрения кода, так и с точки зрения использования.

Getters/Setters


Так вот, getter/setter в данном случае будет один на всё, ну то есть совсем.
	val: function( key, param, param2 ){		
		if( this.data.hasOwnProperty( key ) ){
			if( typeof( param ) == 'undefined' ){
				return this.data[ key ] ? this.data[ key ] : false;
			} else if( typeof( param ) != 'undefined' ){
				if( key == 'params' ){
					if( typeof( param ) == 'string' ){
						if( typeof( param2 ) != 'undefined' ){
							this.data[ key ][ param ] = param2;
						} else{
							return this.data[ key ][ param ] ? this.data[ key ][ param ] : false;
						}
					} else if( typeof( param ) == 'object' ){
						for( var keys in param ){
							if( typeof( param[ keys ] ) != 'undefined' && ( param[ keys ] == '' || param[ keys ] === false ) ){
								if( this.data[ key ].hasOwnProperty( keys ) ){
									delete this.data[ key ][ keys ];
								}
							} else{
								this.data[ key ][ keys ] = param[ keys ];
							}
						}
					}
				} else{
					this.data[ key ] = param;
				}
				
				return this.update();
			}
		} else
			return 'undefined';
	}


Расширяем объект String


Идентичная ситуация и с расширением объекта String, только кода поменьше, т.к. этот метод всего лишь транспортирует параметры в URL.val();

Подведение итогов


Итак, на выходе мы имеем либу, дающую нам возможность адекватно работать с URL, причем не просто парсить, но и менять отдельные участи URL. Это уже не говоря о весьма удобном, на мой взгляд, инструменте для работы с GET-параметрами.

Плюсы и минусы подходов

Вариант 1

Плюсы:
  • Хорошая читаемость
  • Удобно применять

Минусы:
  • 8,75кб ( без сжатия и удаления разрядки )
  • 360 строк кода для в общем-то небольшого расширения функционала
  • Если можно так выразиться — громоздкость по сравнению с вариантом 2


Вариант 2

Плюсы:
  • Всего 144 строчки кода
  • Вес 4.25кб ( без сжатия и удаления разрядки )
  • Простота и лаконичность конструкций

Минусы:
  • Немножко сложно читать


Скачать исходники обоих вариантов можно тут: [ Вариант 1 || Вариант 2 ]. смысла выкладывать на гитхаб не вижу, ибо всего 1 файл.
Поддержка:
  • Да в общем-то абсолютно везде где работает JavaSript, ибо плагин написан на чистом, нативном JS, без использования magic функций, которые не поддерживаются старыми браузерами.


А за сим — откланяюсь, искренне надеюсь что мой пост принесет кому-то пользу.
Всем хорошего кода, больше сна и чтобы IE не портил жизнь.
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 60

    +3
    typeof( param1 )

    Это не очевидный момент, но typeof — это унарный оператор, а не функция. То есть скобки в данном случае не нужны и их можно опустить.
      +4
      Так читается лучше, ну по крайней мере на мой взгляд. Это уже из оперы coding standards — у каждого свои тараканы.
        –2
        Не припомню ни в одном coding standard для JS такого правила. И они как раз создаются, чтобы тараканы были общие:)
          0
          так-то можно развернуть холивары на тему

          function(){
          }
          

          и

          function()
          {
          }
          


          Ну или
          if($case1)
              return 1;
          else
              return 2;
          

          и

          if($case1){
              return 1;
          } else{
              return 2;
          }
          


          Я это к тому, что по какому ману/гайду учился — так и пишешь на протяжении долгого-долгого времени, покуда не появится таск «Переучиться»
          А я так вообще зеленый, воспоминания о первом учебнике слишком свежи%) А по сему к первому комменту — впитал, усвоил, исправлюсь =)
      0
      "* т.е. схема может быть и не указана."
      То есть схем может быть сколько угодно?)
        +1
        ну… если криво указать начальный урл — например https://http://habrahabr.ru/post/232073/
        регулярка обработает его как http://habrahabr.ru/post/232073/, т.е. учтет последнюю схему. А насчет сколько угодно — завтыкал, каюсь. Доберусь до контупера — поправлю.
        Сделаю валидацию всех свойств.
        +2
        >([a-z0-9][a-z0-9_\-\.]+) — HOST, насколько я знаю, начинаться доменное имя может только с буквы/цифры, а дальше уже могут идти и — и _ и. Более того, не бывает доменных имен короче 6 символов, но ведь ссылки то бывают и внутрисетевые, где хостнеймами как хочешь так и рулишь, та что сойдет и 1+ символ.

        «яндекс.рф» под вашу регулярку не подходит, в другой статье регулярка удачнее, с поддержкой IDN.
        ya.ru — домен из 5 символов, непонятно, почему вы считаете, что короче 6 не бывает.
          –5
          Насчет 6 — обсчитался, дело было в 4 утра, математика начала подводить. 2 + 2 + точка почему-то посчитал 6%)

          Насчет IDN — ну вот тут не сказать что не знал об этом… Я их не признаю, вообще никак..рф за домен не считаю. Может эта точка зрения неверна, но осталась она еще с тех времен когда в seo работал, тогда они только появились и вообще не продвигались.ну да не о том речь!
          Коли надо — сделаем.
            +2
            x.co — тоже рабочий домен.
              –7
              хохо. а вот этого не знал. на практике не встречал такие короткие. чисто для теста забил b.com/ — выдало dnserror, забил на это дело. что ж, будем знать.
              • UFO just landed and posted this here
                +3
                да и i.ua не только рабочий, но весьма раскрученный в Украине, еще и почта халявная на этом домене висит.
                  0
                  а на твиттере все ссылки переписываются через t.co
                    –2
                    Это другое. t.co — серверсайд сервис шортлинков.
                    Здесь же задача на стороне клиента, без общения с сервером — обрабатывать ссылки.

                    Сейчас я переписываю все.
                      0
                      не, я всё ещё о 6 символах
              +4
              Ещё одно решение: В ноде есть url. Он адаптирован для браузера в составе node-browser-builtins.
                –1
                Тут, к сожалению, я не могу сказать вообще ничего. Ибо с нодой дела пока не имел, не до нее.
                Таск был именно с тем что есть( JS ) сделать.
                +3
                Регулярка не работает с URL вида
                //habr.ru

                Такое часто нужно, когда требуется, чтобы ресурс подгружался с той же schema, что и сама страничка.
                  –4
                  на практике не сталкивался. учтем.
                    +7
                    Таким образом происходит загрузка JavaScript библиотек с CDN.
                  +4
                  Возможно кому-нибудь понадобится: URI.js — лучшая библиотека из тех, что я видел для работы с URI на JS.
                  Из плюсов можно отменить:
                  1. Xорошая документация
                  2. Обработка сложных случаев
                  3. Модульность
                  4. Нет зависимостей от других библиотек
                  5. Есть плагин для jQuery

                    0
                    Где был гугл, когда она мне была нужна=)
                      0
                      И вот тут появляется дилемма. Написать все то же самое только самому или перейти на эту либу %)
                        +6
                        Есть еще вариант написать все то же самое самому но в продакшн взять эту либу.
                          –1
                          ну это неуважение к себе самому получается=)
                          Написать то же самое и не использовать.
                      +2
                      [жалуюсь] В любом браузере есть внутренние классы, которые предназначены для разбора URL и для обратного составления строки с адресом. Почему не добавить в стандартную библиотеку JavaScript нормальный API для работы с URI? Такое ощущение, что авторам браузеров намного важнее реализовать 3D графику с аппаратным ускорением, чем добавить один единственный класс для нормальной работы с URL. В результате имеем несколько разных pure-JavaScript библиотек, которые не всегда попадают в спецификацию, и работают заведомо медленней, чем нативная реализация. [/жалуюсь]
                      Спасибо автору за очень полезную библиотеку. А почему нет ссылки на Github/Bitbucket репозиторий?
                        +10
                        А зачем юзать один windows.location, когда можно просто создать:
                        var el = document.createElement('a');
                        el.href = 'http://habrahabr.ru/post/232073/#comment_7837811';
                        alert(el.pathname); // '/post/232073/'
                        
                          0
                          Опередили, тоже хотел автору предложить этот способ))) у ссылки только нет query, но всё решается применением split к el.search.
                            0
                            Вот примерно так можно из el.search получить query:
                            var query = {};
                            
                            '?sd=fdg&fd=&&sd=8'.substring(1).split('&').forEach(function(value) {
                                value = value.split('=');
                            
                                if (value[0] in query) {
                                    if (!(query[value[0]] instanceof Array))
                                        query[value[0]] = [query[value[0]]];
                            
                                    query[value[0]].push(value[1]);
                                } else
                                    query[value[0]] = value[1];
                            });
                            
                            query;
                            

                            Написал так, чтобы в консоль можно было вставить и сразу проверить.
                              0
                              Про document.createElement('a') — знал, но не хотелось использовать этот способ. Сейчас не вспомню но что-то было с этим способом не так.
                              +1
                              да я его только в 1 месте использую, для перехода по сгенерированному URL
                              	go: function(){
                              		if(!this.data.scheme && this.data.host)
                              			this.data.scheme = 'http';
                              		
                              		window.location.href = this.update().url;
                              	}
                              


                              Или вы в принципе про использование document.createElement('a') вместо window.location?
                                0
                                Да причем здесь вообще location, там просто находятся данные по текущему урлу страницы и методы для перехода на другую.

                                А document.createElement('a') создает элемент ссылки, который прекрасно может распарсить урл именно так как сделал бы браузер, зачем делать то что уже продумано людьми, которые создавали браузер.

                                Да и вам следует почитать теории, потому то странно сравнивать такие вещи, если вы к примеру установить у location свойство pathname то перейдете на другую страницу, а если это же свойство установить ссылке, то никуда вы не перейдете, а спокойно сможете взять получившийся урл из свойства href ссылки.
                                  –2
                                  Ну это ясное дело что переход по ссылке будет.

                                  И самая большая проблема заключается как раз в том, что каждый разработчик, делая свой браузер «Делает свой интернет» и что работает в одном — не факт что будет работать в другом, а если и будет работать не обязательно будет работать так же. Примеров весь инет.

                                  Собственно это и есть причина моего нежелания использовать document.createElement('a')
                                    +2
                                    Только делая очередную библиотеку, вы делаете очередной «свой интернет», со своими глюками. Поэтому, странно, не полагаться на логику парсинга URL браузером, но при этом полагаться на логику регулярных выражений, предоставляемых тем же браузером. Да и вообще, с чего вы решили, что они делают эту задачу хуже, чем ваша библиотека?
                                      –1
                                      Ни в коем случае не претендую на «лучшее» решение.
                                      Просто на мой взгляд — регэксп надежнее. И это не «уперся лбом», а просто мнение, которое легко изменить любыми пруфами обратного.

                                      Для меня это в первую очередь «спортивны интерес», а данный пост — расшаривание личного опыта, да и самого кода (что полезно, ибо что может быть лучше конструктивной критики?) который будет перепиливаться. Точнее вот прям щас он уже перепиливается.

                                      Вот например на текущий момент я уже получил по меньшей мере альтернативный вариант парсинга урла.
                                        0
                                        Простейший пример:
                                        var link = document.createElement('a');
                                        link.href = 'ya.ru';
                                        return link.hostname;
                                        // -> 
                                        
                                        
                                          +2
                                          А ваша библиотека работает только с абсолютным URL? Потому как браузер работает и с относительными ссылками тоже, и в данном случае он корректно посчитает данный пример, как указание на элемент «ya.ru» относительно текущего пути. Следует четко понять, с каким стандартом вы работаете.
                                            0
                                            Это, я бы сказал, неоднозначность.
                                            Ибо hosthame имеет ровно ту же структуру, что и filename, например,, и достоверно по неполному/неправильному линку не всегда можно определить домен это или путь.

                                            В текущем случае, ya.ru, по-правилам, является filename, т.е. относительной ссылкой на файл ya.ru лежащий в той же директории.
                                            НО! я то например подразумевал домен, в данном случае.

                                            как обрабатывать такие непонятки — пока не определился.
                                              +2
                                              Стоп-стоп, неоднозначности здесь нет: «ya.ru» — вполне корректный относительный адрес, и если ваша библиотека поддерживает RFC{№ лень искать} относительных URI, то тут однозначно ya.ru — это pathname.
                                              Некорректность тут может быть, если вы поддерживаете другой стандарт, который не предполагает относительных ссылок, т. к. «ya.ru» — это неправильный формат для URL, и минимально, он должен быть "//ya.ru", чтобы трактовать его как hostname. То что вы подразумеваете «ya.ru» как домен, вы лишь подразумеваете исходя из знакомого наименования и не следуя стандартам. Следует поменять немного строку на «index.html», и вы уже будете подразумевать из логики совершенно противоположное.
                                                0
                                                Совершенно верно.

                                                Неоднозначность я имел в виду — по RFC 1738 это path, но я то имел в виду домен.
                                                А если я укажу строку index.com, ресурса такого я не помню, но однако видя .com лично я воспринимаю ее как домен, а некоторые воспримут его как исполняемый windows файл.

                                                Неоднозначность как раз в том, что нельзя выдернуть некий линк ( даже не полный, не являющийся линком по RFC ) из контекста и однозначно сказать домен это или путь.

                                                Я то предполагал мочь обрабатывать всё.
                                  0
                                  Если попытаться подытожить, то реализации поддержки методов для работы с URL в браузерах есть (или планируется) в:

                                  В большинстве случаев этого, наверно, будет достаточно для того, чтобы создать объект с методами и свойствами для удобного разбора и работы с URL. Плюс получается максимальная приближенность к стандартам работы с URL в браузерах.

                                  Вообще достаточно легко найти даже на Github множество либ для работы с URL. Вот к примеру Polymer/URL, тут небольшой список, и множество других.
                                    0
                                    Ну там часть для ноды.

                                    А так, как я уже говорил — основной интерес в том, чтобы сделать самому. Хоть на текущий момент я уже и знаю по меньше мере 4-5 библиотек.
                                  +11
                                  Прежде чем выкладывать код в открытый доступ, причесали бы его для приличия, да узнали бы как работает `delete`:

                                  26 warnings
                                  26 warnings
                                   7	Redefinition of 'URL'.
                                   207	The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.
                                   248	Variables should not be deleted.
                                   261	Variables should not be deleted.
                                   274	Variables should not be deleted.
                                   287	Variables should not be deleted.
                                   300	Variables should not be deleted.
                                   313	Variables should not be deleted.
                                   326	Variables should not be deleted.
                                   339	Variables should not be deleted.
                                   352	Variables should not be deleted.
                                  

                                  Two undefined variables
                                   196	param
                                   197	param
                                   197	param
                                   244	result
                                   246	result
                                   250	result
                                   257	result
                                   259	result
                                   263	result
                                   270	result
                                   272	result
                                   276	result
                                   283	result
                                   285	result
                                   289	result
                                   296	result
                                   298	result
                                   302	result
                                   309	result
                                   311	result
                                   315	result
                                   322	result
                                   324	result
                                   328	result
                                   335	result
                                   337	result
                                   341	result
                                   348	result
                                   350	result
                                   354	result
                                  

                                  По мимо этого, такие утилитарные вещи, обязательно нужно покрывать тестами, чтобы они не падали от простого URL:
                                  var url1 = "//domain.com/path/to.html";
                                  var url2 = "http://domain.com/path/to.html?foo=%";
                                  

                                    +5
                                    На вскидку:

                                    Regular Expression for matching Urls as in the RFC
                                    In search of the perfect URL validation regex
                                    RFC 3987
                                    URI.js
                                    Unicode regular expressions
                                    url3.pl

                                    Правильная регулярка
                                    (?:http://(?:(?:(?:(?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?)\.
                                    )*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:\.(?:\d+)
                                    ){3}))(?::(?:\d+))?)(?:/(?:(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F
                                    \d]{2}))|[;:@&=])*)(?:/(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{
                                    2}))|[;:@&=])*))*)(?:\?(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{
                                    2}))|[;:@&=])*))?)?)|(?:ftp://(?:(?:(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?
                                    :%[a-fA-F\d]{2}))|[;?&=])*)(?::(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-
                                    fA-F\d]{2}))|[;?&=])*))?@)?(?:(?:(?:(?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-
                                    )*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?
                                    :\d+)(?:\.(?:\d+)){3}))(?::(?:\d+))?))(?:/(?:(?:(?:(?:[a-zA-Z\d$\-_.+!
                                    *'(),]|(?:%[a-fA-F\d]{2}))|[?:@&=])*)(?:/(?:(?:(?:[a-zA-Z\d$\-_.+!*'()
                                    ,]|(?:%[a-fA-F\d]{2}))|[?:@&=])*))*)(?:;type=[AIDaid])?)?)|(?:news:(?:
                                    (?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[;/?:&=])+@(?:(?:(
                                    ?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?:[
                                    a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:\.(?:\d+)){3})))|(?:[a-zA-Z](
                                    ?:[a-zA-Z\d]|[_.+-])*)|\*))|(?:nntp://(?:(?:(?:(?:(?:[a-zA-Z\d](?:(?:[
                                    a-zA-Z\d]|-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d
                                    ])?))|(?:(?:\d+)(?:\.(?:\d+)){3}))(?::(?:\d+))?)/(?:[a-zA-Z](?:[a-zA-Z
                                    \d]|[_.+-])*)(?:/(?:\d+))?)|(?:telnet://(?:(?:(?:(?:(?:[a-zA-Z\d$\-_.+
                                    !*'(),]|(?:%[a-fA-F\d]{2}))|[;?&=])*)(?::(?:(?:(?:[a-zA-Z\d$\-_.+!*'()
                                    ,]|(?:%[a-fA-F\d]{2}))|[;?&=])*))?@)?(?:(?:(?:(?:(?:[a-zA-Z\d](?:(?:[a
                                    -zA-Z\d]|-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d]
                                    )?))|(?:(?:\d+)(?:\.(?:\d+)){3}))(?::(?:\d+))?))/?)|(?:gopher://(?:(?:
                                    (?:(?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:
                                    (?:[a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:\.(?:\d+)){3}))(?::(?:\d+
                                    ))?)(?:/(?:[a-zA-Z\d$\-_.+!*'(),;/?:@&=]|(?:%[a-fA-F\d]{2}))(?:(?:(?:[
                                    a-zA-Z\d$\-_.+!*'(),;/?:@&=]|(?:%[a-fA-F\d]{2}))*)(?:%09(?:(?:(?:[a-zA
                                    -Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[;:@&=])*)(?:%09(?:(?:[a-zA-Z\d$
                                    \-_.+!*'(),;/?:@&=]|(?:%[a-fA-F\d]{2}))*))?)?)?)?)|(?:wais://(?:(?:(?:
                                    (?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?:
                                    [a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:\.(?:\d+)){3}))(?::(?:\d+))?
                                    )/(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))*)(?:(?:/(?:(?:[a-zA
                                    -Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))*)/(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(
                                    ?:%[a-fA-F\d]{2}))*))|\?(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]
                                    {2}))|[;:@&=])*))?)|(?:mailto:(?:(?:[a-zA-Z\d$\-_.+!*'(),;/?:@&=]|(?:%
                                    [a-fA-F\d]{2}))+))|(?:file://(?:(?:(?:(?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]
                                    |-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:
                                    (?:\d+)(?:\.(?:\d+)){3}))|localhost)?/(?:(?:(?:(?:[a-zA-Z\d$\-_.+!*'()
                                    ,]|(?:%[a-fA-F\d]{2}))|[?:@&=])*)(?:/(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(
                                    ?:%[a-fA-F\d]{2}))|[?:@&=])*))*))|(?:prospero://(?:(?:(?:(?:(?:[a-zA-Z
                                    \d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)
                                    *[a-zA-Z\d])?))|(?:(?:\d+)(?:\.(?:\d+)){3}))(?::(?:\d+))?)/(?:(?:(?:(?
                                    :[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[?:@&=])*)(?:/(?:(?:(?:[a-
                                    zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[?:@&=])*))*)(?:(?:;(?:(?:(?:[
                                    a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[?:@&])*)=(?:(?:(?:[a-zA-Z\d
                                    $\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[?:@&])*)))*)|(?:ldap://(?:(?:(?:(?:
                                    (?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?:
                                    [a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:\.(?:\d+)){3}))(?::(?:\d+))?
                                    ))?/(?:(?:(?:(?:(?:(?:(?:[a-zA-Z\d]|%(?:3\d|[46][a-fA-F\d]|[57][Aa\d])
                                    )|(?:%20))+|(?:OID|oid)\.(?:(?:\d+)(?:\.(?:\d+))*))(?:(?:%0[Aa])?(?:%2
                                    0)*)=(?:(?:%0[Aa])?(?:%20)*))?(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F
                                    \d]{2}))*))(?:(?:(?:%0[Aa])?(?:%20)*)\+(?:(?:%0[Aa])?(?:%20)*)(?:(?:(?
                                    :(?:(?:[a-zA-Z\d]|%(?:3\d|[46][a-fA-F\d]|[57][Aa\d]))|(?:%20))+|(?:OID
                                    |oid)\.(?:(?:\d+)(?:\.(?:\d+))*))(?:(?:%0[Aa])?(?:%20)*)=(?:(?:%0[Aa])
                                    ?(?:%20)*))?(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))*)))*)(?:(
                                    ?:(?:(?:%0[Aa])?(?:%20)*)(?:[;,])(?:(?:%0[Aa])?(?:%20)*))(?:(?:(?:(?:(
                                    ?:(?:[a-zA-Z\d]|%(?:3\d|[46][a-fA-F\d]|[57][Aa\d]))|(?:%20))+|(?:OID|o
                                    id)\.(?:(?:\d+)(?:\.(?:\d+))*))(?:(?:%0[Aa])?(?:%20)*)=(?:(?:%0[Aa])?(
                                    ?:%20)*))?(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))*))(?:(?:(?:
                                    %0[Aa])?(?:%20)*)\+(?:(?:%0[Aa])?(?:%20)*)(?:(?:(?:(?:(?:[a-zA-Z\d]|%(
                                    ?:3\d|[46][a-fA-F\d]|[57][Aa\d]))|(?:%20))+|(?:OID|oid)\.(?:(?:\d+)(?:
                                    \.(?:\d+))*))(?:(?:%0[Aa])?(?:%20)*)=(?:(?:%0[Aa])?(?:%20)*))?(?:(?:[a
                                    -zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))*)))*))*(?:(?:(?:%0[Aa])?(?:%2
                                    0)*)(?:[;,])(?:(?:%0[Aa])?(?:%20)*))?)(?:\?(?:(?:(?:(?:[a-zA-Z\d$\-_.+
                                    !*'(),]|(?:%[a-fA-F\d]{2}))+)(?:,(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-f
                                    A-F\d]{2}))+))*)?)(?:\?(?:base|one|sub)(?:\?(?:((?:[a-zA-Z\d$\-_.+!*'(
                                    ),;/?:@&=]|(?:%[a-fA-F\d]{2}))+)))?)?)?)|(?:(?:z39\.50[rs])://(?:(?:(?
                                    :(?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?)\.)*(?:[a-zA-Z](?:(?
                                    :[a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:\.(?:\d+)){3}))(?::(?:\d+))
                                    ?)(?:/(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))+)(?:\+(?:(?:
                                    [a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))+))*(?:\?(?:(?:[a-zA-Z\d$\-_
                                    .+!*'(),]|(?:%[a-fA-F\d]{2}))+))?)?(?:;esn=(?:(?:[a-zA-Z\d$\-_.+!*'(),
                                    ]|(?:%[a-fA-F\d]{2}))+))?(?:;rs=(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA
                                    -F\d]{2}))+)(?:\+(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))+))*)
                                    ?))|(?:cid:(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[;?:@&=
                                    ])*))|(?:mid:(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[;?:@
                                    &=])*)(?:/(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[;?:@&=]
                                    )*))?)|(?:vemmi://(?:(?:(?:(?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z
                                    \d])?)\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:\
                                    .(?:\d+)){3}))(?::(?:\d+))?)(?:/(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a
                                    -fA-F\d]{2}))|[/?:@&=])*)(?:(?:;(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a
                                    -fA-F\d]{2}))|[/?:@&])*)=(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d
                                    ]{2}))|[/?:@&])*))*))?)|(?:imap://(?:(?:(?:(?:(?:(?:(?:[a-zA-Z\d$\-_.+
                                    !*'(),]|(?:%[a-fA-F\d]{2}))|[&=~])+)(?:(?:;[Aa][Uu][Tt][Hh]=(?:\*|(?:(
                                    ?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[&=~])+))))?)|(?:(?:;[
                                    Aa][Uu][Tt][Hh]=(?:\*|(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2
                                    }))|[&=~])+)))(?:(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[
                                    &=~])+))?))@)?(?:(?:(?:(?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])
                                    ?)\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:\.(?:
                                    \d+)){3}))(?::(?:\d+))?))/(?:(?:(?:(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:
                                    %[a-fA-F\d]{2}))|[&=~:@/])+)?;[Tt][Yy][Pp][Ee]=(?:[Ll](?:[Ii][Ss][Tt]|
                                    [Ss][Uu][Bb])))|(?:(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))
                                    |[&=~:@/])+)(?:\?(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[
                                    &=~:@/])+))?(?:(?:;[Uu][Ii][Dd][Vv][Aa][Ll][Ii][Dd][Ii][Tt][Yy]=(?:[1-
                                    9]\d*)))?)|(?:(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[&=~
                                    :@/])+)(?:(?:;[Uu][Ii][Dd][Vv][Aa][Ll][Ii][Dd][Ii][Tt][Yy]=(?:[1-9]\d*
                                    )))?(?:/;[Uu][Ii][Dd]=(?:[1-9]\d*))(?:(?:/;[Ss][Ee][Cc][Tt][Ii][Oo][Nn
                                    ]=(?:(?:(?:[a-zA-Z\d$\-_.+!*'(),]|(?:%[a-fA-F\d]{2}))|[&=~:@/])+)))?))
                                    )?)|(?:nfs:(?:(?://(?:(?:(?:(?:(?:[a-zA-Z\d](?:(?:[a-zA-Z\d]|-)*[a-zA-
                                    Z\d])?)\.)*(?:[a-zA-Z](?:(?:[a-zA-Z\d]|-)*[a-zA-Z\d])?))|(?:(?:\d+)(?:
                                    \.(?:\d+)){3}))(?::(?:\d+))?)(?:(?:/(?:(?:(?:(?:(?:[a-zA-Z\d\$\-_.!~*'
                                    (),])|(?:%[a-fA-F\d]{2})|[:@&=+])*)(?:/(?:(?:(?:[a-zA-Z\d\$\-_.!~*'(),
                                    ])|(?:%[a-fA-F\d]{2})|[:@&=+])*))*)?)))?)|(?:/(?:(?:(?:(?:(?:[a-zA-Z\d
                                    \$\-_.!~*'(),])|(?:%[a-fA-F\d]{2})|[:@&=+])*)(?:/(?:(?:(?:[a-zA-Z\d\$\
                                    -_.!~*'(),])|(?:%[a-fA-F\d]{2})|[:@&=+])*))*)?))|(?:(?:(?:(?:(?:[a-zA-
                                    Z\d\$\-_.!~*'(),])|(?:%[a-fA-F\d]{2})|[:@&=+])*)(?:/(?:(?:(?:[a-zA-Z\d
                                    \$\-_.!~*'(),])|(?:%[a-fA-F\d]{2})|[:@&=+])*))*)?)))
                                    

                                      0
                                      О_О убейте меня сразу… а если ошибся где-то в ней, или поправить чего-нибудь надо ( ._.)
                                      Жаль плюсомета пока нету.
                                        0
                                        Есть дебаггеры для регулярок (например, RegexBuddy). Так, что если вы не состоите в секте «Любителей Блокнота» (вместо Блокнота может быть любой простой текстовый редактор), то особых проблем не будет.
                                        0
                                        Мне вот интересно, это сверхчеловек написал или как-то сгенерировано?
                                        0
                                        param1, param2

                                        Не называйте переменные больше так. Старайтесь давать им осмысленные названия.

                                        Кроме того, в функции update, в моменте сбора query — зачем нужен цикл конкатенации, если можно воспользоваться Array.prototype.join?
                                          –2
                                          Вполне осмысленное название… parameter1, parameter2 , я же не знаю что точно придет в parameter1.
                                          — его может не прийти вовсе.
                                          — а может прийти строка, тогда имело бы смысл назвать эту переменную value ( ибо если param1 указан, то это сеттер )
                                          — а для метода params это был бы key ( читаем параметр с указанным ключом )
                                          — а если пришла строка в param2, тогда param1 стоило бы назвать key, а param2value
                                          — а если в param1 пришел хэш, то тогда param1 надо назвать hash
                                          Как посоветуете быть в этом случае?

                                          Что же касается Array.prototype.join то array.join склеивает весь массив с 1 сепаратором.
                                          А у меня:
                                          1) Не массив, а хэш, Т.е. объект, а не массив.( хотя вот если память не изменяет join и у хешей есть )
                                          2) Мне надо склеивать значения с разными сепараторами.
                                            –2
                                            Меня прям умиляют эти минусёры…
                                            Вот за что минус этому комменту?
                                          0
                                          Мне всегда было интересно, а как решать задаче роутинга с помощью js. И что если сайт динамический и количество роутингов добавляется? Предлагаете конструировать js файл на сервере ?(хотя он может стать просто адских размеров)
                                            0
                                            А что именно за задача и в чём проблема сделать роутинг на js? Если сайт динамический, то делать какой-то фиксированный предгенерённый js-файл для роутинга бессмысленно же. Пусть оно динамически и обрабатывается. Я вот на прошлом месте работы сделал веб-приложение, которое, фактически, состоит из одной html-странички, а все внутренние переходы – на js. В общем виде никакой проблемы нет, насколько я понимаю.
                                              0
                                              У меня сейчас есть такое же приложение, роутинг делается правда в angular точнее в ui-router.
                                              Однако, что будет если количество страниц перевалит за 1000 ?)
                                              Нужно делать какой-то «умный» роутинг, который подгружал бы нужные js постепенно по мере разбирания url
                                                +1
                                                С angular работал мало, так что спорить не буду. У меня была такая схема (грубо говоря) – 1 шаблон = 1 страница, адрес страницы совпадает с именем шаблона. Соответственно, абсолютно неважно, сколько страниц, 5 или 5000 – роутинг от этого ни разу не усложняется и не увеличивается.
                                                  0
                                                  Это если он совпадает, то да. А что делать если нет совпадения.
                                                    0
                                                    Советую пост: http://habrahabr.ru/post/200662/
                                                    Аккурат роутинг в ангуляе
                                                      0
                                                      Там сделано, через routeProvider. Вот вопрос о том, что будет если в нем появится около милиона ссылок? Строк кода будет еще больше, потому что нужно прописать ссылку на темлеит и контроллер.
                                                        0
                                                        Просто привел пост о котором знаю=)
                                                        как там сделано уже не помню.

                                                        а о быстрых решениях написал и я и норлин, сообщения норлина не видел, у него там развернутее
                                                      +1
                                                      Ну если у вас в приложении сотни и тысячи уникальных страниц – это выглядит, мягко говоря, странно.
                                                      Можно к каждой странице прикладывать мини-конфиг, состоящий из пары «адрес»: «имя шаблона», далее при «компиляции» приложения все эти конфиги склеивать в одну табличку роутинга и использовать её.
                                                      По возможности – организовать иерархическую структуру страниц, чтоб не надо было сразу подгружать вообще всё.

                                                      Ещё раз – я смотрю на проблему с точки зрения «вообще», а не конкретно Angular.
                                                        –1
                                                        как вариант передавать в урле либо ?template=xxx, либо #template_name
                                                        если оны не заняты под другие нужды

                                              Only users with full accounts can post comments. Log in, please.