Skip to content

Commit

Permalink
Add Web Action Handler
Browse files Browse the repository at this point in the history
  • Loading branch information
dshanske committed Apr 28, 2015
1 parent 251b994 commit cc41c46
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 2 deletions.
47 changes: 45 additions & 2 deletions indie-webactions.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@ public static function init() {
add_action('comment_form_before', array('Web_Actions', 'comment_form_before'), 0);
add_action('comment_form_after', array('Web_Actions', 'after'), 0);
}
add_action('wp_enqueue_scripts', array('Web_Actions', 'enqueue_scripts') );
add_filter('query_vars', array('Web_Actions', 'query_var'));
add_action('parse_query', array('Web_Actions', 'parse_query'));
// If Post Kinds isn't activated show a basic bookmark display
if (!taxonomy_exists('kind') ) {
add_filter('the_content', array('Web_Actions', 'the_content'));
}
}

public static function enqueue_scripts() {
wp_enqueue_script( 'indieconfig', plugin_dir_url( __FILE__ ) . 'js/indieconfig.js', array(), '1.0.0', true );
wp_enqueue_script( 'webaction', plugin_dir_url( __FILE__ ) . 'js/webaction.js', array(), '1.0.0', true );
}

/**
* add webaction to the reply links in the comment section
Expand Down Expand Up @@ -78,11 +84,11 @@ public static function query_var($vars) {
return $vars;
}
public static function kind_actions() {
$actions = array('like', 'favorite', 'bookmark', 'repost', 'note', 'reply');
$actions = array('config', 'like', 'favorite', 'bookmark', 'repost', 'note', 'reply');
return apply_filters('supported_webactions', $actions);
}
public static function unkind_actions() {
$actions = array('bookmark', 'note');
$actions = array('bookmark', 'note', 'config');
return apply_filters('supported_webactions', $actions);
}

Expand Down Expand Up @@ -115,6 +121,10 @@ public static function parse_query($wp) {
_e ('Unsupported or Disabled Action', 'Web Actions');
exit;
}
if ($action=='config') {
Web_Actions::indie_config();
exit;
}
if ( !isset($data['url'])&&!isset($data['postform']) ) {
Web_Actions::form_header();
Web_Actions::post_form($action, $data['test']);
Expand Down Expand Up @@ -255,6 +265,39 @@ public static function form_footer() {
</html>
<?php
}
public static function indie_config() {
?>
<!DOCTYPE html>
<html>
<head>
</head>
<body>

<form id="confForm">
<input type="Submit" value="Register web+action handler"/>
</form>
<script>
(function () {
if (window.parent !== window) {
window.parent.postMessage(JSON.stringify({
// The config of your endpoint
reply: '<?php echo site_url(); ?>?indie-action=reply&url={url}',
like: '<?php echo site_url(); ?>?indie-action=like&url={url}',
favorite: '<?php echo site_url(); ?>?indie-action=favorite&url={url}',
repost: '<?php echo site_url(); ?>?indie-action=repost&url={url}',
}), '*');
}
// Pick a way to invoke the registerProtocolHandler, through a submit handler in admin or something
document.getElementById('confForm').addEventListener('submit', function (e) {
e.preventDefault();
window.navigator.registerProtocolHandler('web+action', '/?indie-action=config&url=%s', 'Indie Config');
});
}());
</script>
</body>
</html>
<?php
}
public static function post_form($action, $test=null) {
?>
<form action="<?php echo site_url();?>/?indie-action=<?php echo $action;?>" method="post">
Expand Down
70 changes: 70 additions & 0 deletions js/indieconfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*jslint browser: true, plusplus: true, vars: true, indent: 2 */
window.loadIndieConfig = (function () {
'use strict';

// Indie-Config Loading script
// by Pelle Wessman, voxpelli.com
// MIT-licensed
// http://indiewebcamp.com/indie-config

var config, configFrame, configTimeout,
callbacks = [],
handleConfig, parseConfig;

// When the configuration has been loaded – deregister all loading mechanics and call all callbacks
handleConfig = function () {
config = config || {};

configFrame.parentNode.removeChild(configFrame);
configFrame = undefined;

window.removeEventListener('message', parseConfig);

clearTimeout(configTimeout);

while (callbacks[0]) {
callbacks.shift()(config);
}
};

// When we receive a message, check if the source is right and try to parse it
parseConfig = function (message) {
var correctSource = (configFrame && message.source === configFrame.contentWindow);

if (correctSource && config === undefined) {
try {
config = JSON.parse(message.data);
} catch (ignore) {}

handleConfig();
}
};

return function (callback) {
// If the config is already loaded, call callback right away
if (config) {
callback(config);
return;
}

// Otherwise add the callback to the queue
callbacks.push(callback);

// Are we already trying to load the Indie-Config, then wait
if (configFrame) {
return;
}

// Create the iframe that will load the Indie-Config
configFrame = document.createElement('iframe');
configFrame.src = 'web+action:load';
document.getElementsByTagName('body')[0].appendChild(configFrame);
configFrame.style.display = 'none';

// Listen for messages so we will catch the Indie-Config message
window.addEventListener('message', parseConfig);

// And if no such Indie-Config message has been loaded in a while, abort the loading
configTimeout = setTimeout(handleConfig, 3000);
};
}());
72 changes: 72 additions & 0 deletions js/webaction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*jslint browser: true, plusplus: true, vars: true, indent: 2 */
(function () {
'use strict';

var loadingClassRegexp = /(^|\s)indieconfig-loading(\s|$)/;

var doTheAction = function (indieConfig) {
var href, action, anchors;

// Don't block the tag anymore as the queued action is now handled
this.className = this.className.replace(loadingClassRegexp, ' ');

// Pick the correct endpoint for the correct action
action = this.getAttribute('do');

if ((action === 'reply' || action === 'post') && indieConfig.reply) {
href = indieConfig.reply;
} else if (action === 'like' && indieConfig.like) {
href = indieConfig.like;
} else if (action === 'repost' && indieConfig.repost) {
href = indieConfig.repost;
} else if (action === 'tip' && indieConfig.tip) {
href = indieConfig.tip;
}

// If no endpoint is found, try the URL of the first a-tag within it
if (!href) {
anchors = this.getElementsByTagName('a');
if (anchors[0]) {
href = anchors[0].href;
}
}

// We have found an endpoint!
if (href) {
//Resolve a relative target
var target = document.createElement('a');
target.href = this.getAttribute('with');
target = target.href;

// Insert the target into the endpoint
href = href.replace('{url}', encodeURIComponent(target || window.location.href));

// And redirect to it
window.location = href;
}
};

// Event handler for a click on an indie-action tag
var handleTheAction = function (e) {
// Prevent the default of eg. any a-tag fallback within the indie-action tag
e.preventDefault();

// Make sure this tag hasn't already been queued for the indieconfig-load
if (!loadingClassRegexp.test(this.className)) {
this.className += ' indieconfig-loading';
// Set "doTheAction" to be called when the indie-config has been loaded
window.loadIndieConfig(doTheAction.bind(this));
}
};

// Once the page is loased add click event listeners to all indie-action tags
window.addEventListener('DOMContentLoaded', function () {
var actions = document.querySelectorAll('indie-action'),
i,
length = actions.length;

for (i = 0; i < length; i++) {
actions[i].addEventListener('click', handleTheAction);
}
});
}());

0 comments on commit cc41c46

Please sign in to comment.