Merge pull request #2262 from 7wonders/djs

Adding django.js
This commit is contained in:
Thomas Davis
2013-12-04 07:08:07 -08:00
3 changed files with 289 additions and 0 deletions
+245
View File
@@ -0,0 +1,245 @@
(function($){
"use strict";
function DjangoJsError(message) {
this.name = "DjangoJsError";
this.message = (message || "");
}
DjangoJsError.prototype = new Error();
DjangoJsError.prototype.constructor = DjangoJsError;
var Django = window.Django = {
token_regex: /<\w*>/g,
named_token_regex: /<(\w+)>/g,
/**
* Initialize required attributes
*/
initialize: function(params) {
params = params || {};
if (typeof params.urls === 'string' || params.urls instanceof String) {
$.get(params.urls, function(urls) {
Django.urls = urls;
});
} else {
this.urls = params.urls || window.DJANGO_JS_URLS;
}
if (typeof params.context === 'string' || params.context instanceof String) {
$.get(params.context, function(context) {
Django.set_context(context);
});
} else {
this.set_context(params.context || window.DJANGO_JS_CONTEXT);
}
},
set_context: function(context) {
this.context = context;
this.user = context.user;
if (this.user) {
/**
* Equivalent to ``User.has_perm`` function.
*/
this.user.has_perm = function(permission) {
return this.permissions.indexOf(permission) > -1;
};
}
},
/**
* Reload context and user
*/
reload: function(callback) {
$.get(this.url('django_js_context'), function(context) {
Django.set_context(context);
if (callback instanceof Function) {
callback();
}
});
},
/**
* Equivalent to ``reverse`` function and ``url`` template tag.
*/
url: function(name, args) {
var pattern = this.urls[name] || false,
url = pattern,
key, regex, token, parts;
if (!url) {
throw new DjangoJsError('URL for view "' + name + '" not found');
}
if (args === undefined) {
return url;
}
if ($.isArray(args)) {
return this._url_from_array(name, pattern, args);
}
else if ($.isPlainObject(args)) {
return this._url_from_object(name, pattern, args);
}
else {
var argsArray = Array.prototype.slice.apply(arguments, [1, arguments.length]);
return this._url_from_array(name, pattern, argsArray);
}
return url;
},
_url_from_array: function(name, pattern, array) {
var matches = pattern.match(this.token_regex),
parts = pattern.split(this.token_regex),
url = parts[0];
if (!matches && array.length === 0) {
return url;
}
if (matches && matches.length != array.length) {
throw new DjangoJsError('Wrong number of argument for pattern "' + name + '"');
}
for (var idx=0; idx < array.length; idx++) {
url += array[idx] + parts[idx + 1];
}
return url;
},
_url_from_object: function(name, pattern, object) {
var url = pattern,
tokens = pattern.match(this.token_regex);
if (!tokens) {
return url;
}
for (var idx=0; idx < tokens.length; idx++) {
var token = tokens[idx],
prop = token.slice(1, -1),
value = object[prop];
if (value === undefined) {
throw new DjangoJsError('Property "' + prop + '" not found');
}
url = url.replace(token, value);
}
return url;
},
/**
* Equivalent to ``static`` template tag.
*/
file: function(filename) {
return this.context.STATIC_URL + filename;
},
/**
* Equivalent to ``static`` template tag.
*/
'static': function(filename) {
return this.context.STATIC_URL + filename;
},
/**
* Return cookie value by name.
* cf. https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
*/
_getCookie: function(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = $.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
},
/**
* Get the CSRF token from the cookie.
*/
csrf_token: function() {
return this._getCookie('csrftoken');
},
/**
* Equivalent to ``{% csrf_token %}`` template tag.
*/
csrf_element: function() {
var token = this.csrf_token(),
elem = [
'<input type="hidden" name="csrfmiddlewaretoken" value="',
token ? token : '',
'">'
];
return elem.join('');
},
/**
* Fix ajax request with CSRF Django middleware.
*/
jquery_csrf: function() {
var getCookie = this._getCookie;
$(document).ajaxSend(function(event, xhr, settings) {
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') || (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
},
absolute: function(name, args) {
if (!this.context.hasOwnProperty('ABSOLUTE_ROOT')) {
throw new DjangoJsError('django-absolute needed to call absolute()');
}
return this.context.ABSOLUTE_ROOT + this.url(name, args);
},
site: function(name, args) {
if (!this.context.hasOwnProperty('SITE_ROOT')) {
throw new DjangoJsError('django-absolute needed to call site()');
}
return this.context.SITE_ROOT + this.url(name, args);
}
};
if (window.DJANGO_JS_INIT) {
Django.initialize();
}
if (window.DJANGO_JS_CSRF) {
Django.jquery_csrf();
}
return Django;
}(window.jQuery));
+1
View File
@@ -0,0 +1 @@
(function(e){"use strict";function t(e){this.name="DjangoJsError",this.message=e||""}t.prototype=new Error,t.prototype.constructor=t;var n=window.Django={token_regex:/<\w*>/g,named_token_regex:/<(\w+)>/g,initialize:function(t){t=t||{},typeof t.urls=="string"||t.urls instanceof String?e.get(t.urls,function(e){n.urls=e}):this.urls=t.urls||window.DJANGO_JS_URLS,typeof t.context=="string"||t.context instanceof String?e.get(t.context,function(e){n.set_context(e)}):this.set_context(t.context||window.DJANGO_JS_CONTEXT)},set_context:function(e){this.context=e,this.user=e.user,this.user&&(this.user.has_perm=function(e){return this.permissions.indexOf(e)>-1})},reload:function(t){e.get(this.url("django_js_context"),function(e){n.set_context(e),t instanceof Function&&t()})},url:function(n,r){var i=this.urls[n]||!1,s=i,o,u,a,f;if(!s)throw new t('URL for view "'+n+'" not found');if(r===undefined)return s;if(e.isArray(r))return this._url_from_array(n,i,r);if(e.isPlainObject(r))return this._url_from_object(n,i,r);var l=Array.prototype.slice.apply(arguments,[1,arguments.length]);return this._url_from_array(n,i,l)},_url_from_array:function(e,n,r){var i=n.match(this.token_regex),s=n.split(this.token_regex),o=s[0];if(!i&&r.length===0)return o;if(i&&i.length!=r.length)throw new t('Wrong number of argument for pattern "'+e+'"');for(var u=0;u<r.length;u++)o+=r[u]+s[u+1];return o},_url_from_object:function(e,n,r){var i=n,s=n.match(this.token_regex);if(!s)return i;for(var o=0;o<s.length;o++){var u=s[o],a=u.slice(1,-1),f=r[a];if(f===undefined)throw new t('Property "'+a+'" not found');i=i.replace(u,f)}return i},file:function(e){return this.context.STATIC_URL+e},"static":function(e){return this.context.STATIC_URL+e},_getCookie:function(t){var n=null;if(document.cookie&&document.cookie!==""){var r=document.cookie.split(";");for(var i=0;i<r.length;i++){var s=e.trim(r[i]);if(s.substring(0,t.length+1)==t+"="){n=decodeURIComponent(s.substring(t.length+1));break}}}return n},csrf_token:function(){return this._getCookie("csrftoken")},csrf_element:function(){var e=this.csrf_token(),t=['<input type="hidden" name="csrfmiddlewaretoken" value="',e?e:"",'">'];return t.join("")},jquery_csrf:function(){var t=this._getCookie;e(document).ajaxSend(function(e,n,r){function i(e){var t=document.location.host,n=document.location.protocol,r="//"+t,i=n+r;return e==i||e.slice(0,i.length+1)==i+"/"||e==r||e.slice(0,r.length+1)==r+"/"||!/^(\/\/|http:|https:).*/.test(e)}function s(e){return/^(GET|HEAD|OPTIONS|TRACE)$/.test(e)}!s(r.type)&&i(r.url)&&n.setRequestHeader("X-CSRFToken",t("csrftoken"))})},absolute:function(e,n){if(!this.context.hasOwnProperty("ABSOLUTE_ROOT"))throw new t("django-absolute needed to call absolute()");return this.context.ABSOLUTE_ROOT+this.url(e,n)},site:function(e,n){if(!this.context.hasOwnProperty("SITE_ROOT"))throw new t("django-absolute needed to call site()");return this.context.SITE_ROOT+this.url(e,n)}};return window.DJANGO_JS_INIT&&n.initialize(),window.DJANGO_JS_CSRF&&n.jquery_csrf(),n})(window.jQuery);
+43
View File
@@ -0,0 +1,43 @@
{
"name": "django.js",
"filename": "django.min.js",
"description": "Django.js provides tools for JavaScript development with Django.",
"homepage": "https://github.com/noirbizarre/django.js/",
"author": {
"name": "Axel Haustant",
"url": "http://noirbizarre.info/"
},
"repository": {
"type": "git",
"url": "https://github.com/noirbizarre/django.js.git"
},
"licenses": [
{
"type": "LGPL 3",
"url": "http://www.gnu.org/licenses/lgpl-3.0.txt"
}
],
"version": "0.8.1",
"main": [
"djangojs/static/js/djangojs/django.js",
"djangojs/static/js/djangojs/django.min.js"
],
"dependencies": {
"jquery": ">=1.8"
},
"ignore": [
"**/.*",
"**/*.py",
"**/*.sh",
"**/*.rc",
"**/*.pip",
"**/*.po",
"node_modules",
"bower_components",
"test",
"tests",
"requirements",
"templates",
"tox.ini"
]
}