From fd77374065102bfd20bfcf9dd6b5d90c32c74fcf Mon Sep 17 00:00:00 2001 From: Tom Rees Date: Thu, 1 Mar 2012 14:06:15 +0000 Subject: [PATCH] [#1506][js][l]: UrlEditor is a backbone model; various ux tweaks --- ckan/public/scripts/application.js | 204 ++++++++++--------- ckan/templates/group/new_group_form.html | 4 +- ckan/templates/js_strings.html | 1 + ckan/templates/package/new_package_form.html | 4 +- 4 files changed, 115 insertions(+), 98 deletions(-) diff --git a/ckan/public/scripts/application.js b/ckan/public/scripts/application.js index 915976197c8..c92b1270e9e 100644 --- a/ckan/public/scripts/application.js +++ b/ckan/public/scripts/application.js @@ -128,109 +128,125 @@ var CKAN = CKAN || {}; /* ============================== */ CKAN.View.UrlEditor = Backbone.View.extend({ initialize: function() { - var slugType = this.options.slugType; - var editMode = this.options.editMode; - - if (!editMode) var editMode = false; - // Page elements to hook onto - var titleInput = $('.js-title'); - var urlSuffix = $('.js-url-suffix'); - var urlInput = $('.js-url-input'); - var validMsg = $('.js-url-is-valid'); - - if (titleInput.length==0) throw "No titleInput found."; - if (urlSuffix.length==0) throw "No urlSuffix found."; - if (urlInput.length==0) throw "No urlInput found."; - if (validMsg.length==0) throw "No validMsg found."; - - var api_url = CKAN.SITE_URL + '/api/2/util/is_slug_valid'; - // (make length less than max, in case we need a few for '_' chars to de-clash slugs.) - var MAX_SLUG_LENGTH = 90; - - var titleChanged = function() { - var lastTitle = ""; - var regexToHyphen = [ new RegExp('[ .:/_]', 'g'), - new RegExp('[^a-zA-Z0-9-_]', 'g'), - new RegExp('-+', 'g')]; - var regexToDelete = [ new RegExp('^-*', 'g'), - new RegExp('-*$', 'g')]; - - var titleToSlug = function(title) { - var slug = title; - $.each(regexToHyphen, function(idx,regex) { slug = slug.replace(regex, '-'); }); - $.each(regexToDelete, function(idx,regex) { slug = slug.replace(regex, ''); }); - slug = slug.toLowerCase(); - - if (slug.length'+CKAN.Strings.urlIsAvailable+''); - } else { - validMsg.html(''+CKAN.Strings.urlIsNotAvailable+''); - } - } - }); - } + toEditMode: function(event) { + $('.js-url-viewmode').hide(); + $('.js-url-editmode').show(); + if (event) { + // If we clicked a link, highlight the input + event.preventDefault(); + this.urlInput.select(); + this.urlInput.focus(); + } + // Disable automatic slug generation + this.disableTitleChanged = true; + }, - return function() { - slug = urlInput.val(); - urlSuffix.html(''+slug+''); - if (timer) clearTimeout(timer); - if (slug.length<2) { - validMsg.html(''+CKAN.Strings.urlIsTooShort+''); - } - else { - validMsg.html(''+CKAN.Strings.checking+''); - timer = setTimeout(function () { - checkSlugValid(slug); - }, 200); - } - }; - }(); + titleToSlug: function(title) { + var slug = title; + $.each(this.regexToHyphen, function(idx,regex) { slug = slug.replace(regex, '-'); }); + $.each(this.regexToDelete, function(idx,regex) { slug = slug.replace(regex, ''); }); + slug = slug.toLowerCase(); - var editLink = $('.js-url-editlink'); - editLink.show(); - // Hook title changes to the input box - CKAN.Utils.bindInputChanges(titleInput, titleChanged); - CKAN.Utils.bindInputChanges(urlInput, urlChanged); - // Set up the form - urlChanged(); + if (slug.length'+slug+''); + if (this.updateTimer) clearTimeout(this.updateTimer); + if (slug.length<2) { + this.validMsg.html(''+CKAN.Strings.urlIsTooShort+''); + } + else if (this.options.editMode && slug==this.originalUrl) { + this.validMsg.html(''+CKAN.Strings.urlIsUnchanged+''); + } + else { + this.validMsg.html(''+CKAN.Strings.checking+''); + var self = this; + this.updateTimer = setTimeout(function () { + self.checkSlugIsValid(slug); + }, 200); + } + }, + + checkSlugIsValid: function(slug) { + $.ajax({ + url: this.options.apiUrl, + data: 'type='+this.options.slugType+'&slug=' + slug, + dataType: 'jsonp', + type: 'get', + jsonpCallback: 'callback', + success: this.apiCallback }); }, + + /* Called when the slug-validator gets back to us */ + apiCallback: function(data) { + if (data.valid) { + this.validMsg.html(''+CKAN.Strings.urlIsAvailable+''); + } else { + this.validMsg.html(''+CKAN.Strings.urlIsNotAvailable+''); + } + }, }); diff --git a/ckan/templates/group/new_group_form.html b/ckan/templates/group/new_group_form.html index 8a3b58a78a2..599cf6aa7a0 100644 --- a/ckan/templates/group/new_group_form.html +++ b/ckan/templates/group/new_group_form.html @@ -8,7 +8,7 @@

Errors in form

The form contains invalid entries:

    -
  • ${"%s: %s" % (key, error)}
  • +
  • ${"%s: %s" % (key if not key=='Name' else 'URL', error)}
@@ -19,7 +19,7 @@

Errors in form

- ${h.url(controller='group', action='index')+'/'}  + ${h.url(controller='group', action='index')+'/'} (edit)

 

diff --git a/ckan/templates/js_strings.html b/ckan/templates/js_strings.html index 6a00beee9fb..104f9f360ae 100644 --- a/ckan/templates/js_strings.html +++ b/ckan/templates/js_strings.html @@ -16,6 +16,7 @@ CKAN.Strings.helloWorld = "${_('Hello there, world!')}"; CKAN.Strings.checking = "${_('Checking...')}"; CKAN.Strings.urlIsTooShort = "${_('Type at least two characters...')}"; + CKAN.Strings.urlIsUnchanged = "${_('This is the current URL.')}"; CKAN.Strings.urlIsAvailable = "${_('This URL is available!')}"; CKAN.Strings.urlIsNotAvailable = "${_('This URL is already used, please use a different one.')}"; CKAN.Strings.bracketsNone = "${_('(none)')}"; diff --git a/ckan/templates/package/new_package_form.html b/ckan/templates/package/new_package_form.html index b6a2f3ffda1..7f653d079d8 100644 --- a/ckan/templates/package/new_package_form.html +++ b/ckan/templates/package/new_package_form.html @@ -9,7 +9,7 @@

Errors in form

The form contains invalid entries:

    -
  • ${"%s: %s" % (key, error)} +
  • ${"%s: %s" % (key if not key=='Name' else 'URL', error)}
      @@ -42,7 +42,7 @@

      Errors in form

      - ${h.url(controller='package', action='index')+'/'}  + ${h.url(controller='package', action='index')+'/'} (edit)