Browse Source

Image Upload Feature

Adding image upload to the markdown editor using
jQuery.AjaxFileUpload.js.
pull/189/head
Danang Probo Sayekti 10 years ago
parent
commit
4c6d8c1a31
9 changed files with 568 additions and 16 deletions
  1. +6
    -2
      COPYRIGHT.txt
  2. +1
    -1
      composer.json
  3. +164
    -0
      system/admin/editor/js/jquery.ajaxfileupload.js
  4. +70
    -2
      system/admin/views/add-page.html.php
  5. +71
    -3
      system/admin/views/add-post.html.php
  6. +70
    -2
      system/admin/views/edit-page.html.php
  7. +71
    -3
      system/admin/views/edit-post.html.php
  8. +70
    -3
      system/admin/views/edit-profile.html.php
  9. +45
    -0
      upload.php

+ 6
- 2
COPYRIGHT.txt View File

@ -1,4 +1,4 @@
Copyright (c) 2014 Danang Probo Sayekti.
Copyright (c) 2015 Danang Probo Sayekti.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -38,6 +38,10 @@ license, including:
jQuery - (c) The jQuery Foundation
jQuery UI - (c) The jQuery Foundation
Hub Updater - (c) Kanti.de <https://github.com/Kanti>
Password Compat - (c) Anthony Ferrara <https://github.com/ircmaxell>
Password Compat - (c) Anthony Ferrara <https://github.com/ircmaxell>
jQuery.AjaxFileUpload.js - (c) Jordan Feldstein <https://github.com/jfeldstein>

+ 1
- 1
composer.json View File

@ -6,7 +6,7 @@
"require": {
"michelf/php-markdown": "~1.4",
"suin/php-rss-writer": "~1",
"kanti/hub-updater": "~0.3",
"kanti/hub-updater": "~0.3",
"ircmaxell/password-compat": "^1.0"
},
"autoload": {


+ 164
- 0
system/admin/editor/js/jquery.ajaxfileupload.js View File

@ -0,0 +1,164 @@
/*
// jQuery Ajax File Uploader
//
// @author: Jordan Feldstein <jfeldstein.com>
//
// - Ajaxifies an individual <input type="file">
// - Files are sandboxed. Doesn't matter how many, or where they are, on the page.
// - Allows for extra parameters to be included with the file
// - onStart callback can cancel the upload by returning false
*/
(function($) {
$.fn.ajaxfileupload = function(options) {
var settings = {
params: {},
action: '',
onStart: function() { },
onComplete: function(response) { },
onCancel: function() { },
validate_extensions : true,
valid_extensions : ['gif','png','jpg','jpeg'],
submit_button : null
};
var uploading_file = false;
if ( options ) {
$.extend( settings, options );
}
// 'this' is a jQuery collection of one or more (hopefully)
// file elements, but doesn't check for this yet
return this.each(function() {
var $element = $(this);
// Skip elements that are already setup. May replace this
// with uninit() later, to allow updating that settings
if($element.data('ajaxUploader-setup') === true) return;
$element.change(function()
{
// since a new image was selected, reset the marker
uploading_file = false;
// only update the file from here if we haven't assigned a submit button
if (settings.submit_button == null)
{
upload_file();
}
});
if (settings.submit_button == null)
{
// do nothing
} else
{
settings.submit_button.click(function(e)
{
// Prevent non-AJAXy submit
e.preventDefault();
// only attempt to upload file if we're not uploading
if (!uploading_file)
{
upload_file();
}
});
}
var upload_file = function()
{
if($element.val() == '') return settings.onCancel.apply($element, [settings.params]);
// make sure extension is valid
var ext = $element.val().split('.').pop().toLowerCase();
if(true === settings.validate_extensions && $.inArray(ext, settings.valid_extensions) == -1)
{
// Pass back to the user
settings.onComplete.apply($element, [{status: false, message: 'The select file type is invalid. File must be ' + settings.valid_extensions.join(', ') + '.'}, settings.params]);
} else
{
uploading_file = true;
// Creates the form, extra inputs and iframe used to
// submit / upload the file
wrapElement($element);
// Call user-supplied (or default) onStart(), setting
// it's this context to the file DOM element
var ret = settings.onStart.apply($element, [settings.params]);
// let onStart have the option to cancel the upload
if(ret !== false)
{
$element.parent('form').submit(function(e) { e.stopPropagation(); }).submit();
}
}
};
// Mark this element as setup
$element.data('ajaxUploader-setup', true);
/*
// Internal handler that tries to parse the response
// and clean up after ourselves.
*/
var handleResponse = function(loadedFrame, element) {
var response, responseStr = $(loadedFrame).contents().text();
try {
//response = $.parseJSON($.trim(responseStr));
response = JSON.parse(responseStr);
} catch(e) {
response = responseStr;
}
// Tear-down the wrapper form
element.siblings().remove();
element.unwrap();
uploading_file = false;
// Pass back to the user
settings.onComplete.apply(element, [response, settings.params]);
};
/*
// Wraps element in a <form> tag, and inserts hidden inputs for each
// key:value pair in settings.params so they can be sent along with
// the upload. Then, creates an iframe that the whole thing is
// uploaded through.
*/
var wrapElement = function(element) {
// Create an iframe to submit through, using a semi-unique ID
var frame_id = 'ajaxUploader-iframe-' + Math.round(new Date().getTime() / 1000)
$('body').after('<iframe width="0" height="0" style="display:none;" name="'+frame_id+'" id="'+frame_id+'"/>');
$('#'+frame_id).get(0).onload = function() {
handleResponse(this, element);
};
// Wrap it in a form
element.wrap(function() {
return '<form action="' + settings.action + '" method="POST" enctype="multipart/form-data" target="'+frame_id+'" />'
})
// Insert <input type='hidden'>'s for each param
.before(function() {
var key, html = '';
for(key in settings.params) {
var paramVal = settings.params[key];
if (typeof paramVal === 'function') {
paramVal = paramVal();
}
html += '<input type="hidden" name="' + key + '" value="' + paramVal + '" />';
}
return html;
});
}
});
}
})( jQuery )

+ 70
- 2
system/admin/views/add-page.html.php View File

@ -1,7 +1,11 @@
<link rel="stylesheet" type="text/css" href="<?php echo site_url() ?>system/admin/editor/css/editor.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Converter.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Sanitizer.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Editor.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/jquery.ajaxfileupload.js"></script>
<?php if (isset($error)) { ?>
<div class="error-message"><?php echo $error ?></div>
<?php } ?>
@ -35,13 +39,77 @@
<input type="submit" name="submit" class="submit" value="Publish"/>
</form>
</div>
<div id="insertImageDialog" title="Insert Image">
<h4>URL</h4>
<input type="text" placeholder="Enter image URL" />
<h4>Upload</h4>
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="file" id="file" />
</form>
<style>
#insertImageDialog { display:none; padding: 10px; font-size:12px;}
.wmd-prompt-background {z-index:10!important;}
</style>
</div>
<div id="wmd-preview" class="wmd-panel wmd-preview"></div>
<script type="text/javascript">
(function () {
var converter = new Markdown.Converter();
var editor = new Markdown.Editor(converter);
var $dialog = $('#insertImageDialog').dialog({
autoOpen: false,
closeOnEscape: false,
open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); }
});
var $url = $('input[type=text]', $dialog);
var $file = $('input[type=file]', $dialog);
var base = '<?php echo site_url() ?>';
editor.hooks.set('insertImageDialog', function(callback) {
var dialogInsertClick = function() {
callback($url.val().length > 0 ? $url.val(): null);
dialogClose();
};
var dialogCancelClick = function() {
dialogClose();
callback(null);
};
var dialogClose = function() {
$url.val('');
$file.val('');
$dialog.dialog('close');
};
$dialog.dialog( 'option', 'buttons', {
'Insert': dialogInsertClick,
'Cancel': dialogCancelClick
});
var uploadComplete = function(response) {
if (response.error == '0') {
$url.val(base + response.path);
} else {
alert(response.error);
$file.val('');
}
};
$file.ajaxfileupload({
'action': '<?php echo site_url() ?>upload.php',
'onComplete': uploadComplete,
});
$dialog.dialog('open');
return true; // tell the editor that we'll take care of getting the image url
});
editor.run();
editor.run();
})();
</script>

+ 71
- 3
system/admin/views/add-post.html.php View File

@ -1,7 +1,11 @@
<link rel="stylesheet" type="text/css" href="<?php echo site_url() ?>system/admin/editor/css/editor.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Converter.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Sanitizer.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Editor.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/jquery.ajaxfileupload.js"></script>
<?php if (isset($error)) { ?>
<div class="error-message"><?php echo $error ?></div>
<?php } ?>
@ -48,13 +52,77 @@
<input type="submit" name="submit" class="submit" value="Publish"/>
</form>
</div>
<div id="insertImageDialog" title="Insert Image">
<h4>URL</h4>
<input type="text" placeholder="Enter image URL" />
<h4>Upload</h4>
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="file" id="file" />
</form>
<style>
#insertImageDialog { display:none; padding: 10px; font-size:12px;}
.wmd-prompt-background {z-index:10!important;}
</style>
</div>
<div id="wmd-preview" class="wmd-panel wmd-preview"></div>
<script type="text/javascript">
(function () {
var converter = new Markdown.Converter();
var editor = new Markdown.Editor(converter);
var $dialog = $('#insertImageDialog').dialog({
autoOpen: false,
closeOnEscape: false,
open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); }
});
var $url = $('input[type=text]', $dialog);
var $file = $('input[type=file]', $dialog);
var base = '<?php echo site_url() ?>';
editor.hooks.set('insertImageDialog', function(callback) {
var dialogInsertClick = function() {
callback($url.val().length > 0 ? $url.val(): null);
dialogClose();
};
var dialogCancelClick = function() {
dialogClose();
callback(null);
};
var dialogClose = function() {
$url.val('');
$file.val('');
$dialog.dialog('close');
};
$dialog.dialog( 'option', 'buttons', {
'Insert': dialogInsertClick,
'Cancel': dialogCancelClick
});
var uploadComplete = function(response) {
if (response.error == '0') {
$url.val(base + response.path);
} else {
alert(response.error);
$file.val('');
}
};
$file.ajaxfileupload({
'action': '<?php echo site_url() ?>upload.php',
'onComplete': uploadComplete,
});
$dialog.dialog('open');
return true; // tell the editor that we'll take care of getting the image url
});
editor.run();
editor.run();
})();
</script>
</script>

+ 70
- 2
system/admin/views/edit-page.html.php View File

@ -22,9 +22,13 @@ $delete = $p->url . '/delete?destination=' . $destination;
?>
<link rel="stylesheet" type="text/css" href="<?php echo site_url() ?>system/admin/editor/css/editor.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Converter.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Sanitizer.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Editor.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/jquery.ajaxfileupload.js"></script>
<?php if (isset($error)) { ?>
<div class="error-message"><?php echo $error ?></div>
<?php } ?>
@ -54,13 +58,77 @@ $delete = $p->url . '/delete?destination=' . $destination;
<input type="submit" name="submit" class="submit" value="Save"/> <a href="<?php echo $delete ?>">Delete</a>
</form>
</div>
<div id="insertImageDialog" title="Insert Image">
<h4>URL</h4>
<input type="text" placeholder="Enter image URL" />
<h4>Upload</h4>
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="file" id="file" />
</form>
<style>
#insertImageDialog { display:none; padding: 10px; font-size:12px;}
.wmd-prompt-background {z-index:10!important;}
</style>
</div>
<div id="wmd-preview" class="wmd-panel wmd-preview"></div>
<script type="text/javascript">
(function () {
var converter = new Markdown.Converter();
var editor = new Markdown.Editor(converter);
var $dialog = $('#insertImageDialog').dialog({
autoOpen: false,
closeOnEscape: false,
open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); }
});
var $url = $('input[type=text]', $dialog);
var $file = $('input[type=file]', $dialog);
var base = '<?php echo site_url() ?>';
editor.hooks.set('insertImageDialog', function(callback) {
var dialogInsertClick = function() {
callback($url.val().length > 0 ? $url.val(): null);
dialogClose();
};
var dialogCancelClick = function() {
dialogClose();
callback(null);
};
var dialogClose = function() {
$url.val('');
$file.val('');
$dialog.dialog('close');
};
$dialog.dialog( 'option', 'buttons', {
'Insert': dialogInsertClick,
'Cancel': dialogCancelClick
});
var uploadComplete = function(response) {
if (response.error == '0') {
$url.val(base + response.path);
} else {
alert(response.error);
$file.val('');
}
};
$file.ajaxfileupload({
'action': '<?php echo site_url() ?>upload.php',
'onComplete': uploadComplete,
});
$dialog.dialog('open');
return true; // tell the editor that we'll take care of getting the image url
});
editor.run();
editor.run();
})();
</script>

+ 71
- 3
system/admin/views/edit-post.html.php View File

@ -37,9 +37,13 @@ $delete = site_url() . date('Y/m', $postdate) . '/' . $oldmd . '/delete?destinat
?>
<link rel="stylesheet" type="text/css" href="<?php echo site_url() ?>system/admin/editor/css/editor.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Converter.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Sanitizer.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Editor.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/jquery.ajaxfileupload.js"></script>
<?php if (isset($error)) { ?>
<div class="error-message"><?php echo $error ?></div>
<?php } ?>
@ -78,13 +82,77 @@ $delete = site_url() . date('Y/m', $postdate) . '/' . $oldmd . '/delete?destinat
<input type="submit" name="submit" class="submit" value="Save"/> <a href="<?php echo $delete ?>">Delete</a>
</form>
</div>
<div id="insertImageDialog" title="Insert Image">
<h4>URL</h4>
<input type="text" placeholder="Enter image URL" />
<h4>Upload</h4>
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="file" id="file" />
</form>
<style>
#insertImageDialog { display:none; padding: 10px; font-size:12px;}
.wmd-prompt-background {z-index:10!important;}
</style>
</div>
<div id="wmd-preview" class="wmd-panel wmd-preview"></div>
<script type="text/javascript">
(function () {
var converter = new Markdown.Converter();
var editor = new Markdown.Editor(converter);
var $dialog = $('#insertImageDialog').dialog({
autoOpen: false,
closeOnEscape: false,
open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); }
});
var $url = $('input[type=text]', $dialog);
var $file = $('input[type=file]', $dialog);
var base = '<?php echo site_url() ?>';
editor.hooks.set('insertImageDialog', function(callback) {
var dialogInsertClick = function() {
callback($url.val().length > 0 ? $url.val(): null);
dialogClose();
};
var dialogCancelClick = function() {
dialogClose();
callback(null);
};
var dialogClose = function() {
$url.val('');
$file.val('');
$dialog.dialog('close');
};
$dialog.dialog( 'option', 'buttons', {
'Insert': dialogInsertClick,
'Cancel': dialogCancelClick
});
var uploadComplete = function(response) {
if (response.error == '0') {
$url.val(base + response.path);
} else {
alert(response.error);
$file.val('');
}
};
$file.ajaxfileupload({
'action': '<?php echo site_url() ?>upload.php',
'onComplete': uploadComplete,
});
$dialog.dialog('open');
return true; // tell the editor that we'll take care of getting the image url
});
editor.run();
editor.run();
})();
</script>
</script>

+ 70
- 3
system/admin/views/edit-profile.html.php View File

@ -16,11 +16,14 @@ if (file_exists($filename)) {
}
?>
<link rel="stylesheet" type="text/css" href="<?php echo site_url() ?>system/admin/editor/css/editor.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Converter.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Sanitizer.js"></script>
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/Markdown.Editor.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src="<?php echo site_url() ?>system/admin/editor/js/jquery.ajaxfileupload.js"></script>
<?php if (isset($error)) { ?>
<div class="error-message"><?php echo $error ?></div>
<?php } ?>
@ -44,13 +47,77 @@ if (file_exists($filename)) {
<input type="submit" name="submit" class="submit" value="Save"/>
</form>
</div>
<div id="insertImageDialog" title="Insert Image">
<h4>URL</h4>
<input type="text" placeholder="Enter image URL" />
<h4>Upload</h4>
<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="file" id="file" />
</form>
<style>
#insertImageDialog { display:none; padding: 10px; font-size:12px;}
.wmd-prompt-background {z-index:10!important;}
</style>
</div>
<div id="wmd-preview" class="wmd-panel wmd-preview"></div>
<script type="text/javascript">
(function () {
var converter = new Markdown.Converter();
var editor = new Markdown.Editor(converter);
var $dialog = $('#insertImageDialog').dialog({
autoOpen: false,
closeOnEscape: false,
open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); }
});
var $url = $('input[type=text]', $dialog);
var $file = $('input[type=file]', $dialog);
var base = '<?php echo site_url() ?>';
editor.hooks.set('insertImageDialog', function(callback) {
var dialogInsertClick = function() {
callback($url.val().length > 0 ? $url.val(): null);
dialogClose();
};
var dialogCancelClick = function() {
dialogClose();
callback(null);
};
var dialogClose = function() {
$url.val('');
$file.val('');
$dialog.dialog('close');
};
$dialog.dialog( 'option', 'buttons', {
'Insert': dialogInsertClick,
'Cancel': dialogCancelClick
});
var uploadComplete = function(response) {
if (response.error == '0') {
$url.val(base + response.path);
} else {
alert(response.error);
$file.val('');
}
};
$file.ajaxfileupload({
'action': '<?php echo site_url() ?>upload.php',
'onComplete': uploadComplete,
});
$dialog.dialog('open');
return true; // tell the editor that we'll take care of getting the image url
});
editor.run();
editor.run();
})();
</script>

+ 45
- 0
upload.php View File

@ -0,0 +1,45 @@
<?php
$whitelist = array('jpg', 'jpeg', 'png', 'gif');
$name = null;
$dir = 'content/images/';
$error = null;
$timestamp = date('YmdHis');
$path = null;
if (is_dir($dir)) {
} else {
mkdir($dir, 0644, true);
}
if (isset($_FILES)) {
if (isset($_FILES['file'])) {
$tmp_name = $_FILES['file']['tmp_name'];
$name = basename($_FILES['file']['name']);
$error = $_FILES['file']['error'];
$path = $dir . $timestamp . '-' . $name;
$check = getimagesize($tmp_name);
if($check !== false) {
if ($error === UPLOAD_ERR_OK) {
$extension = pathinfo($timestamp . '-' . $name, PATHINFO_EXTENSION);
if (!in_array($extension, $whitelist)) {
$error = 'Invalid file type uploaded.';
} else {
move_uploaded_file($tmp_name, $dir . $timestamp . '-' . $name);
}
}
}
else {
$error = "File is not an image.";
}
}
}
echo json_encode(array(
'path' => $path,
'name' => $name,
'error' => $error,
));
die();

Loading…
Cancel
Save