-
-
Save CatoTH/2029227 to your computer and use it in GitHub Desktop.
Proof-of-concept alpha of jQuery-oembed integrated with CKeditor on paste or when space is pressed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* CKEditor plugin to automatically embed oEmbed-Content | |
* CKEditor/jquery.oembed-integration proof of concept by Tobias Hößl | |
* | |
* Inspired by: | |
* Auto-Insertion plugin | |
* Copyright (c) 2010 Louis St-Amour, but multi-licensed as GPL/LGPL/MPL | |
* | |
* Embeds: | |
* jquery oembed plugin v1.1 | |
* Copyright (c) 2009 Richard Chamorro | |
* Licensed under the MIT license | |
* | |
* | |
* | |
*/ | |
(function ($) { | |
$.fn.oembed = function (url, options, embedAction) { | |
settings = $.extend(true, $.fn.oembed.defaults, options); | |
initializeProviders(); | |
return this.each(function () { | |
var container = $(this), | |
resourceURL = (url != null) ? url : container.attr("href"), | |
provider; | |
if (embedAction) { | |
settings.onEmbed = embedAction; | |
} else { | |
settings.onEmbed = function (oembedData) { | |
$.fn.oembed.insertCode(this, settings.embedMethod, oembedData); | |
}; | |
} | |
if (resourceURL != null) { | |
provider = $.fn.oembed.getOEmbedProvider(resourceURL); | |
if (provider != null) { | |
provider.params = getNormalizedParams(settings[provider.name]) || {}; | |
provider.maxWidth = settings.maxWidth; | |
provider.maxHeight = settings.maxHeight; | |
embedCode(container, resourceURL, provider); | |
} else { | |
settings.onProviderNotFound.call(container, resourceURL); | |
} | |
} | |
return container; | |
}); | |
}; | |
var settings, activeProviders = []; | |
// Plugin defaults | |
$.fn.oembed.defaults = { | |
maxWidth: null, | |
maxHeight: null, | |
embedMethod: "replace", // "auto", "append", "fill" | |
defaultOEmbedProvider: "oohembed", // "oohembed", "embed.ly", "none" | |
allowedProviders: null, | |
disallowedProviders: null, | |
customProviders: null, // [ new $.fn.oembed.OEmbedProvider("customprovider", null, ["customprovider\\.com/watch.+v=[\\w-]+&?"]) ] | |
defaultProvider: null, | |
greedy: true, | |
preferThumbnails: true, | |
onProviderNotFound: function () { }, | |
beforeEmbed: function () { }, | |
afterEmbed: function () { }, | |
onEmbed: function () { }, | |
onError: function() {}, | |
ajaxOptions: {} | |
}; | |
/* Private functions */ | |
function getRequestUrl(provider, externalUrl) { | |
var url = provider.apiendpoint, qs = "", callbackparameter = provider.callbackparameter || "callback", i; | |
if (url.indexOf("?") <= 0) | |
url = url + "?"; | |
else | |
url = url + "&"; | |
if (provider.maxWidth != null && provider.params["maxwidth"] == null) | |
provider.params["maxwidth"] = provider.maxWidth; | |
if (provider.maxHeight != null && provider.params["maxheight"] == null) | |
provider.params["maxheight"] = provider.maxHeight; | |
for (i in provider.params) { | |
// We don't want them to jack everything up by changing the callback parameter | |
if (i == provider.callbackparameter) | |
continue; | |
// allows the options to be set to null, don't send null values to the server as parameters | |
if (provider.params[i] != null) | |
qs += "&" + escape(i) + "=" + provider.params[i]; | |
} | |
if (url.search("\\?format=") == -1) url += "format=json&"; | |
url += provider.getUrlParameter(externalUrl) + qs + "&" + callbackparameter + "=?"; | |
return url; | |
}; | |
function embedCode(container, externalUrl, embedProvider) { | |
var requestUrl = getRequestUrl(embedProvider, externalUrl), | |
ajaxopts = $.extend({ | |
url: requestUrl, | |
type: 'get', | |
dataType: 'json', | |
// error: jsonp request doesnt' support error handling | |
success: function (data) { | |
var oembedData = $.extend({}, data); | |
switch (oembedData.type) { | |
case "photo": | |
oembedData.code = $.fn.oembed.getPhotoCode(externalUrl, oembedData); | |
break; | |
case "video": | |
oembedData.code = $.fn.oembed.getVideoCode(externalUrl, oembedData); | |
break; | |
case "rich": | |
oembedData.code = $.fn.oembed.getRichCode(externalUrl, oembedData); | |
break; | |
default: | |
if (oembedData.thumbnail_url) oembedData.code = $.fn.oembed.getPhotoCode(externalUrl, oembedData); | |
else oembedData.code = $.fn.oembed.getGenericCode(externalUrl, oembedData); | |
break; | |
} | |
settings.beforeEmbed.call(container, oembedData); | |
settings.onEmbed.call(container, oembedData); | |
settings.afterEmbed.call(container, oembedData); | |
}, | |
error: settings.onError.call(container, externalUrl, embedProvider) | |
}, settings.ajaxOptions || { } ); | |
$.ajax( ajaxopts ); | |
}; | |
function initializeProviders() { | |
activeProviders = []; | |
var defaultProvider, restrictedProviders = [], i, provider; | |
if (!isNullOrEmpty(settings.allowedProviders)) { | |
for (i = 0; i < $.fn.oembed.providers.length; i++) { | |
if ($.inArray($.fn.oembed.providers[i].name, settings.allowedProviders) >= 0) | |
activeProviders.push($.fn.oembed.providers[i]); | |
} | |
// If there are allowed providers, jquery-oembed cannot be greedy | |
settings.greedy = false; | |
} else { | |
activeProviders = $.fn.oembed.providers; | |
} | |
if (!isNullOrEmpty(settings.disallowedProviders)) { | |
for (i = 0; i < activeProviders.length; i++) { | |
if ($.inArray(activeProviders[i].name, settings.disallowedProviders) < 0) | |
restrictedProviders.push(activeProviders[i]); | |
} | |
activeProviders = restrictedProviders; | |
// If there are allowed providers, jquery-oembed cannot be greedy | |
settings.greedy = false; | |
} | |
if (!isNullOrEmpty(settings.customProviders)) { | |
$.each(settings.customProviders, function (n, customProvider) { | |
if (customProvider instanceof $.fn.oembed.OEmbedProvider) { | |
activeProviders.push(provider); | |
} else { | |
provider = new $.fn.oembed.OEmbedProvider(); | |
if (provider.fromJSON(customProvider)) | |
activeProviders.push(provider); | |
} | |
}); | |
} | |
// If in greedy mode, we add the default provider | |
defaultProvider = getDefaultOEmbedProvider(settings.defaultOEmbedProvider); | |
if (settings.greedy == true) { | |
activeProviders.push(defaultProvider); | |
} | |
// If any provider has no apiendpoint, we use the default provider endpoint | |
for (i = 0; i < activeProviders.length; i++) { | |
if (activeProviders[i].apiendpoint == null) | |
activeProviders[i].apiendpoint = defaultProvider.apiendpoint; | |
} | |
} | |
function getDefaultOEmbedProvider(defaultOEmbedProvider) { | |
var url = "http://oohembed.com/oohembed/"; | |
if (defaultOEmbedProvider == "embed.ly") | |
url = "http://api.embed.ly/v1/api/oembed?"; | |
return new $.fn.oembed.OEmbedProvider(defaultOEmbedProvider, null, null, url, "callback"); | |
} | |
function getNormalizedParams(params) { | |
if (params == null) | |
return null; | |
var key, normalizedParams = {}; | |
for (key in params) { | |
if (key != null) | |
normalizedParams[key.toLowerCase()] = params[key]; | |
} | |
return normalizedParams; | |
} | |
function isNullOrEmpty(object) { | |
if (typeof object == "undefined") | |
return true; | |
if (object == null) | |
return true; | |
if ($.isArray(object) && object.length == 0) | |
return true; | |
return false; | |
} | |
/* Public functions */ | |
$.fn.oembed.insertCode = function (container, embedMethod, oembedData) { | |
if (oembedData == null) | |
return; | |
switch (embedMethod) { | |
case "auto": | |
if (container.attr("href") != null) { | |
$.fn.oembed.insertCode(container, "append", oembedData); | |
} | |
else { | |
$.fn.oembed.insertCode(container, "replace", oembedData); | |
}; | |
break; | |
case "replace": | |
container.replaceWith(oembedData.code); | |
break; | |
case "fill": | |
container.html(oembedData.code); | |
break; | |
case "append": | |
var oembedContainer = container.next(); | |
if (oembedContainer == null || !oembedContainer.hasClass("oembed-container")) { | |
oembedContainer = container | |
.after('<div class="oembed-container"></div>') | |
.next(".oembed-container"); | |
if (oembedData != null && oembedData.provider_name != null) | |
oembedContainer.toggleClass("oembed-container-" + oembedData.provider_name); | |
} | |
oembedContainer.html(oembedData.code); | |
break; | |
} | |
}; | |
$.fn.oembed.getPhotoCode = function (url, oembedData) { | |
var code, alt = oembedData.title ? oembedData.title : ''; | |
alt += oembedData.author_name ? ' - ' + oembedData.author_name : ''; | |
alt += oembedData.provider_name ? ' - ' + oembedData.provider_name : ''; | |
var url = oembedData.url; | |
if (settings.preferThumbnails) { | |
if (oembedData.thumbnail_url_150) url = oembedData.thumbnail_url_150; | |
else if (oembedData.thumbnail_url) url = oembedData.thumbnail_url; | |
} | |
code = '<div><a href="' + url + '" target=\'_blank\'><img src="' + url + '" alt="' + alt + '"/></a></div>'; | |
if (oembedData.html) | |
code += "<div>" + oembedData.html + "</div>"; | |
return code; | |
}; | |
$.fn.oembed.getVideoCode = function (url, oembedData) { | |
var code = oembedData.html; | |
return code; | |
}; | |
$.fn.oembed.getRichCode = function (url, oembedData) { | |
var code = oembedData.html; | |
return code; | |
}; | |
$.fn.oembed.getGenericCode = function (url, oembedData) { | |
var title = (oembedData.title != null) ? oembedData.title : url, | |
code = '<a href="' + url + '">' + title + '</a>'; | |
if (oembedData.html) | |
code += "<div>" + oembedData.html + "</div>"; | |
return code; | |
}; | |
$.fn.oembed.isProviderAvailable = function (url) { | |
var provider = getOEmbedProvider(url); | |
return (provider != null); | |
}; | |
$.fn.oembed.getOEmbedProvider = function (url) { | |
for (var i = 0; i < activeProviders.length; i++) { | |
if (activeProviders[i].matches(url)) { | |
return activeProviders[i]; | |
} | |
} | |
return null; | |
}; | |
$.fn.oembed.OEmbedProvider = function (name, type, urlschemesarray, apiendpoint, callbackparameter, urlparameterfunction) { | |
this.name = name; | |
this.type = type; // "photo", "video", "link", "rich", null | |
this.urlschemes = getUrlSchemes(urlschemesarray); | |
this.apiendpoint = apiendpoint; | |
this.callbackparameter = callbackparameter; | |
this.maxWidth = 500; | |
this.maxHeight = 400; | |
this.urlparameterfunction = urlparameterfunction; | |
var i, property, regExp; | |
this.matches = function (externalUrl) { | |
for (i = 0; i < this.urlschemes.length; i++) { | |
regExp = new RegExp(this.urlschemes[i], "i"); | |
if (externalUrl.match(regExp) != null) | |
return true; | |
} | |
return false; | |
}; | |
this.fromJSON = function (json) { | |
for (property in json) { | |
if (property != "urlschemes") | |
this[property] = json[property]; | |
else | |
this[property] = getUrlSchemes(json[property]); | |
} | |
return true; | |
}; | |
this.getUrlParameter = function (externalUrl) { | |
if (this.urlparameterfunction) return this.urlparameterfunction(externalUrl); | |
else return "url=" + escape(externalUrl); | |
} | |
function getUrlSchemes(urls) { | |
if (isNullOrEmpty(urls)) | |
return ["."]; | |
if ($.isArray(urls)) | |
return urls; | |
return urls.split(";"); | |
} | |
}; | |
/* Native & common providers */ | |
$.fn.oembed.providers = [ | |
new $.fn.oembed.OEmbedProvider("youtube", "video", ["youtube\\.com/watch.+v=[\\w-]+&?"]), // "http://www.youtube.com/oembed" (no jsonp) | |
new $.fn.oembed.OEmbedProvider("flickr", "photo", ["flickr\\.com/photos/[-.\\w@]+/\\d+/?"], "http://flickr.com/services/oembed", "jsoncallback"), | |
new $.fn.oembed.OEmbedProvider("viddler", "video", ["viddler\.com"]), // "http://lab.viddler.com/services/oembed/" (no jsonp) | |
new $.fn.oembed.OEmbedProvider("blip", "video", ["blip\\.tv/.+"], "http://blip.tv/oembed/"), | |
new $.fn.oembed.OEmbedProvider("hulu", "video", ["hulu\\.com/watch/.*"], "http://www.hulu.com/api/oembed.json"), | |
new $.fn.oembed.OEmbedProvider("vimeo", "video", ["http:\/\/www\.vimeo\.com\/groups\/.*\/videos\/.*", "http:\/\/www\.vimeo\.com\/.*", "http:\/\/vimeo\.com\/groups\/.*\/videos\/.*", "http:\/\/vimeo\.com\/.*"], "http://vimeo.com/api/oembed.json"), | |
new $.fn.oembed.OEmbedProvider("dailymotion", "video", ["dailymotion\\.com/.+"]), // "http://www.dailymotion.com/api/oembed/" (callback parameter does not return jsonp) | |
new $.fn.oembed.OEmbedProvider("scribd", "rich", ["scribd\\.com/.+"]), // ", "http://www.scribd.com/services/oembed"" (no jsonp) | |
new $.fn.oembed.OEmbedProvider("slideshare", "rich", ["slideshare\.net"], "http://www.slideshare.net/api/oembed/1"), | |
new $.fn.oembed.OEmbedProvider("photobucket", "photo", ["photobucket\\.com/(albums|groups)/.*"], "http://photobucket.com/oembed/"), | |
new $.fn.oembed.OEmbedProvider("animexx", "rich", ["https?:\/\/([a-z0-9_-]+\\.animexx\\.de|animexx\\.onlinewelten\\.com)/.*"], "http://www.animexx.de/services/oembed.php"), | |
new $.fn.oembed.OEmbedProvider("deviantart", "photo", ["https?:\/\/[a-z0-9_-]+\\.deviantart\\.com/.*"], "http://backend.deviantart.com/oembed?format=jsonp"), | |
new $.fn.oembed.OEmbedProvider("soundcloud", "rich", ["https?:\/\/soundcloud\\.com/.*"], "http://soundcloud.com/oembed?format=js"), | |
new $.fn.oembed.OEmbedProvider("twitter", "photo", ["https?:\/\/twitter\\.com/.*"], "https://api.twitter.com/1/statuses/oembed.json", null, function(externalUrl) { | |
var id = externalUrl.match(/[0-9]{18}/); | |
return "id=" + id; | |
}) | |
// new $.fn.oembed.OEmbedProvider("vids.myspace.com", "video", ["vids\.myspace\.com"]), // "http://vids.myspace.com/index.cfm?fuseaction=oembed" (not working) | |
// new $.fn.oembed.OEmbedProvider("screenr", "rich", ["screenr\.com"], "http://screenr.com/api/oembed.json") (error) | |
// new $.fn.oembed.OEmbedProvider("qik", "video", ["qik\\.com/\\w+"], "http://qik.com/api/oembed.json"), | |
// new $.fn.oembed.OEmbedProvider("revision3", "video", ["revision3\.com"], "http://revision3.com/api/oembed/") | |
]; | |
})(jQuery); | |
(function() | |
{ | |
var autolinkCommand = | |
{ | |
exec : function( editor ) | |
{ | |
var d = editor.getData(); | |
var match; | |
while (match = CKEDITOR.plugins.registered.autoinsert.urlpattern.exec(d)) { | |
var url = match[1]; | |
console.log(url); | |
var cb = (match.index > 0 ? d[match.index - 1] : ""); | |
if (match.index == 0 || (cb != "\"" && cb != "'")) { | |
var $holder = $("<div><a></a></div>"); | |
$holder.find("a").attr("href", url).oembed(null, { afterEmbed: function() { | |
console.log(cb + url); | |
console.log(cb + $holder.html() + " "); | |
editor.setData(d.replace(cb + url, cb + $holder.html() + " ")); | |
} }); | |
} | |
} | |
} | |
}; | |
CKEDITOR.plugins.add( 'autoinsert', | |
{ | |
requires : [ 'keystrokes' ], | |
idcounter : 0, | |
urlpattern : /(https?:\/\/[-a-zäöü0-9\_]+[-a-zäöü0-9\_\$\.\:;\/\\?=\+\~@,&%#!\'\[\]]+[-a-zäöü0-9\_\$\:\/=\+\~@%#])/gi, | |
init : function( editor ) { | |
editor.on( 'key', function( ev ) { | |
if ( ev.data.keyCode == 32 ) // SPACE | |
{ | |
editor.execCommand( 'autolink' ); | |
} | |
}); | |
editor.on( 'paste', function( ev ) { | |
setTimeout(function() { | |
editor.execCommand( 'autolink' ); | |
}, 0); | |
}); | |
editor.addCommand( 'autolink', CKEDITOR.tools.extend( autolinkCommand ) ); | |
} | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment