Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014 Mohamed Kamal Kamaly
Copyright (c) 2014 Mohamed Kamal Kamaly, David Eberlein

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,24 @@ relativePathsInPartial uses angular.element (jqLite and doesn't depend on JQuery
# How to use

just include the "relative-paths-in-partial.js" and add a dependency on "relativePathsInPartial" module.

# Configuring a URL prefix
You can configure a URL prefix to restrict the replacements be to only done to HTML files which URLs start with the given prefix.
This can be done using the ```relativePathsInterceptorProvider``` in your ```module.configure()``` function.
This functionality requires the support of String.startsWith or a polyfill (e.g. https://github.com/MathRobin/string.startsWith)

Example

```javascript
angular.module('myApp', ['relativePathsInPartial'])
.config(['relativePathsInterceptorProvider', function (relativePathsInterceptorProvider) {
relativePathsInterceptorProvider.setInteceptionPrefix('/intercept/urls/');
// other setup
});
```

This will result in all html files starting with the URLs ```'/intercept/urls/'``` to be intercepted:
- ```'/intercept/urls/myhtml.html'``` --> intercepted
- ```'/intercept/urls/subdir/myhtml.html'``` --> intercepted
- ```'/templates/urls/other.html'``` --> not intercepted (other prefix)
- ```'/intercept/urls/subdir/myhtml'``` --> not intercepted (no .html extention)
127 changes: 86 additions & 41 deletions relative-paths-in-partial.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
'use strict';

(function(){

/**
* JS equivalent of Java hash codo function.
* source: http://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
**/
function hashCode(string) {
var hash = 0, i, chr, len;
if (string.length == 0) return hash;
for (i = 0, len = string.length; i < len; i++) {
chr = string.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}

/**
* @name isAbsoluteUrl
* @author Mohamed Kamal Kamaly
Expand Down Expand Up @@ -75,7 +91,7 @@ function insertRestOfPath(attributeName, parentUrl) {

/**
* @name relativePathsInPartial
* @author Mohamed Kamal Kamaly
* @author Mohamed Kamal Kamaly, David Eberlein
* @description
*
* # relativePathsInPartial
Expand All @@ -94,49 +110,78 @@ function insertRestOfPath(attributeName, parentUrl) {
* and returns in a response, relativePathsInPartial intercepts this response, modify all the paths to have full
* path relative to parent.
*
* relativePathsInPartial uses angular.element (jqLite and doesn't depend on JQuery
* You can configure a url prefix to restrict the replacements to only be done on url's that start with the given prefix.
* This can be done using the relativePathsInterceptorProvider in your module.configure() function.
* This functionality requires the support of String.startsWith or a polyfill
* (e.g. https://github.com/MathRobin/string.startsWith)
*
* relativePathsInPartial uses angular.element (jqLite and doesn't depend on JQuery)
*
*/
angular.module('relativePathsInPartial', [])
.config(function($httpProvider) {
$httpProvider.interceptors.push(function() {
return {
response : function(response) {
var url = response.config.url;

/*
* TODO: check if the request is sent with template
* cache to be sure that it is an angular template
*
* put the template after processing
* into the cache and do not process it again
*/
if (url.lastIndexOf('.html') === url.length - 5) {
var elem = new angular.element(response.data);

var myOperations = [{
matcherFunc: propertyMatcher('tagName', 'LINK'),
applyFunc: insertRestOfPath('href', url)
},{
matcherFunc: propertyMatcher('tagName', 'SCRIPT'),
applyFunc: insertRestOfPath('src', url)
},{
matcherFunc: propertyMatcher('tagName', 'IMG'),
applyFunc: insertRestOfPath('src', url)
}];

// TODO: find an efficient way to process 'src' attribute of 'ng-include'
// elem.find('ng-include').each(replaceUrlFunc('src'));
searchAndApply(elem, myOperations);

response.data = angular.element('<div />').append(elem).html();
}

return response;
}
};
});
});
.provider("relativePathsInterceptor", function () {

var prefix = "";
var processedHashCache = {};

function _isProcessedYet(url, data) {
var cacheHash = processedHashCache[url];
if (cacheHash === undefined) return false;
var dataHash = hashCode(data);
return dataHash === cacheHash;
}

function _isHtml(url) {
return url.lastIndexOf('.html') === url.length - 5;
}

return {
/**
* Only include urls with the given prefix.
* @param value @type {string}
*/
setInteceptionPrefix: function (value) {
prefix = value;
},
$get: function () {
return {
response: function (response) {
var url = response.config.url;

if (_isHtml(url) && url.startsWith(prefix) && !_isProcessedYet(url, response.data)) {

var elem = new angular.element(response.data);

var myOperations = [{
matcherFunc: propertyMatcher('tagName', 'LINK'),
applyFunc: insertRestOfPath('href', url)
}, {
matcherFunc: propertyMatcher('tagName', 'SCRIPT'),
applyFunc: insertRestOfPath('src', url)
}, {
matcherFunc: propertyMatcher('tagName', 'IMG'),
applyFunc: insertRestOfPath('src', url)
}];

// TODO: find an efficient way to process 'src' attribute of 'ng-include'
// elem.find('ng-include').each(replaceUrlFunc('src'));
searchAndApply(elem, myOperations);
response.data = angular.element('<div />').append(elem).html();

// Since angular caches our intercepted data we save a hash of the data
// to be able to check if data has already been processed or not
processedHashCache[url] = hashCode(response.data);
}

return response;
}
};
}
};
})
.config(["$httpProvider", function ($httpProvider) {
$httpProvider.interceptors.push("relativePathsInterceptor");
}]);


})();