Markitup upload plugin for Galleon

Add comments
SocialTwist Tell-a-Friend

         As you must know that  Galleon forum using Markitup editor to create HTML formatted posts. Markitup is a jQuery based easily configurable markup editor. It has "link to image" functionality which used to add URL of a image to show that image in the post. But it doesn't have facility to upload a file to server or browse a file which is already uploaded by that user. I thought, it is good idea to create a plug-in to do the same.

UI mockup for the file upload is

Markitup file upload

Once the user uploaded a file or click on browse button in markitup menu bar, a popup browse div will showed to the user to select their uploaded image. I made browse window as draggable using jQuery UI.  Browse uploaded files interface,

Markitup Browse file

We will see the step by step code changes to implement this. First we need to add new menu bar items. We can configure menu bar items in set.js file located in markitup\sets\default folder. You can change the icons in style.css in the same folder. Here modified version of set.js & style.css

      
{name:'Link to Photo Image', key:'P', replaceWith:'[img][![Url]!][/img]'},
// Added by CF Mitrah
{name:'Upload', key:'M',beforeInsert:function(markItUp){InlineUpload.display(markItUp,true)}},
{name:'Browse', key:'F',beforeInsert:function(markItUp){InlineUpload.display(markItUp,false)}},
// Added by CF Mitrah
{name:'Link', key:'L', openWith:'[url=[![Url]!]]', closeWith:'[/url]', placeHolder:'Your text to link here...'},

InlineUpload javascript class will take care of file upload ajax call & browse uploaded images. InlineUpload.js content is,

var upload = false;
var InlineUpload =
{
dialog: null,
block: '',
offset: {},
options: {
container_class: 'markItUpInlineUpload',
form_id: 'inline_upload_form',
action: 'imgUploader.cfm',
inputs: {
file: { label: 'File', id: 'inline_upload_file1', name: 'inline_upload_file1' }
},
submit: { id: 'inline_upload_submit', value: 'upload' },
close: 'inline_upload_close',
iframe: 'inline_upload_iframe'
},
display: function(hash,uploadOption)
{
if(uploadOption){
if( ! $('.markItUpInlineUpload').length)
{
var self = this;

/* Find position of toolbar. The dialog will inserted into the DOM elsewhere
* but has position: absolute. This is to avoid nesting the upload form inside
* the original. The dialog's offset from the toolbar position is adjusted in
* the stylesheet with the margin rule.
*/
this.offset = $(hash.textarea).prev('.markItUpHeader').offset();

/* We want to build this fresh each time to avoid ID conflicts in case of
* multiple editors. This also means the form elements don't need to be
* cleared out.
*/
this.dialog = $([
'
',

].join(''))
.appendTo(document.body)
.hide()
.css('top', this.offset.top)
.css('left', this.offset.left);


//init submit button

$('#'+this.options.submit.id).click(function()
{
if($('#inline_upload_file1').val() == ''){
alert('Please select a file to upload');
return false;
}
upload = true;
$('#'+self.options.form_id).submit().fadeTo('fast', 0.2);
});


// init cancel button

$('#'+this.options.close).click(this.cleanUp);


// form response will be sent to the iframe

$('#'+this.options.iframe).bind('load', function()
{
var result = document.getElementById(''+self.options.iframe)
.contentWindow.document.body.innerHTML;
if(upload){
$('#resultContainer').html(result);
$(".module .products a").click(function() {
src = $(this).attr("href");
alt = $(this).attr("title");
//$.markItUp( {replaceWith:''+alt+'' });
$.markItUp( {replaceWith:'[img]'+src+'[/img]' });
$("#linkPlugin").fadeOut().css("zIndex", 11);
return false;
});
InlineUpload.dialog.fadeOut().remove();

$("#linkPlugin").fadeIn().css('top', self.offset.top-80).css('left', self.offset.left+460).css("zIndex", 11);
upload = false;
}
});

// Finally, display the dialog
this.dialog.fadeIn('slow');
}

}else{
this.offset = $(hash.textarea).prev('.markItUpHeader').offset();
$('#resultContainer').load('imgUploader.cfm','',function() {
$(".module .products a").click(function() {
src = $(this).attr("href");
alt = $(this).attr("title");
//$.markItUp( {replaceWith:''+alt+'' });
$.markItUp( {replaceWith:'[img]'+src+'[/img]' });
$("#linkPlugin").fadeOut().css("zIndex", 11);
return false;
});
});

$("#linkPlugin").fadeIn().css('top', this.offset.top-80).css('left', this.offset.left+460).css("zIndex", 11);

}
},
cleanUp: function()
{
InlineUpload.dialog.fadeOut().remove();
}
};

For draggable functionality of browse window, we need following jQuery files  jquery.dimensions.js, ui.draggable.ext.js, ui.draggable.js, ui.mouse.js.  I added all this jQuery UI related JS files as well as InlineUpload.js in pagetemplates/common_header.cfm page.

        
<script src="/blog/markitup/jquery.pack.js" type="text/javascript"></script>
<script src="/blog/markitup/jquery.dimensions.js" type="text/javascript"></script>
<script src="/blog/markitup/ui.mouse.js" type="text/javascript"></script>
<script src="/blog/markitup/ui.draggable.js" type="text/javascript"></script>
<script src="/blog/markitup/ui.draggable.ext.js" type="text/javascript"></script>

<script src="/blog/markitup/jquery.markitup.js" type="text/javascript"></script>
<script src="/blog/markitup/InlineUpload.js" type="text/javascript"></script>
<script src="/blog/markitup/sets/default/set.js" type="text/javascript"></script>

I also modified the document ready function to support our functionalities.

<script>
$(document).ready(function() {
$('##markitup').markItUp(mySettings);
// make modules draggable
dragProp = { handle:".handle", zIndex:100, opacity:0.9, scroll:1 };
$('##linkPlugin').hide().draggable( dragProp );

$('.close').click(function() {
$(this).parent().parent().hide();
return false;
});
$('.handle').click(function() {
return false;
});


// use markItUp! features when clicking on "add to editor" link in a module
$(".module .products a").click(function() {
src = $(this).attr("href");
alt = $(this).attr("title");
$.markItUp( {replaceWith:''+alt+'' });
return false;
});
});
</script>

I have added new container div in that page. Once the user click on the browse button, this div will populate using ajax call.

<div id="linkPlugin">
        <div class="toolbar">
<a href="##" class="handle">Move</a>
<a href="##" class="close">Close</a>   
</div>
        <div id="resultContainer" class="module"> </div>
    </div>

ImgUploader.cfm is responsible for server side file upload & directory read operation for user's folder.It is a POC, So my CF code is not 100% optimized as well as I didn't coded for MIME/File upload security issue. It is a simple upload & Directory listing functionality, so please optimize yourself

<cfsilent>
<cfset uName = getAuthUser()>
<cfif uName neq ''>
<cfset userid = application.user.getUserID(getAuthUser())>
<cfset userDir = ExpandPath( './userfiles/#uName#' )>
<cfset userWebDir = "userfiles/#uName#">

<cfif not DirectoryExists(userDir)>
<cfdirectory action="create" mode="777" directory="#userDir#">
</cfif>
<cfif isDefined("form.fieldnames")>
<cfloop index="strFileIndex" from="1" to="#listlen(form.FIELDNAMES)#" step="1">
<cfset strField = "inline_upload_file#strFileIndex#" />
<cfif ( StructKeyExists( FORM, strField ) AND Len( FORM[ strField ] ) )>
<cffile action="upload" filefield="#strField#" destination="#userDir#" nameconflict="makeunique" result="upRes" />
</cfif>
</cfloop>
</cfif>
<cfdirectory action="list" name="qFiles" directory="#userDir#">
</cfif>
</cfsilent>
<cfif uName eq ''><h3>Login error</h3><div><br />Please login again<br /><br /></div><cfabort></cfif>
<h3>Pictures</h3>
<div style="display: block;" class="products slide">
<table width="100%" border="0" cellpadding="2" cellspacing="0">
<tbody>
<cfoutput query="qFiles">
<cfif qFiles.currentrow eq 0><tr></cfif>
<td scope="col" width="50">
<a href="#application.settings.rootURL#/#userWebDir#/#name#" title="#left(name,len(name)-4)#">
<img src="#userWebDir#/#name#" alt="Product 1" width="50" border="0" height="50">
</a>
</td>
<cfif qFiles.currentrow mod 4 eq 0 and qFiles.currentrow neq 0></tr><tr></tr></cfif>
</cfoutput>
</tbody></table>
</div>

You can download all modified files here

9 responses to “Markitup upload plugin for Galleon”

  1. René Pardon
    René Pardon Says:
    Hi,

    this plugin for markItUp is great!
    I'm going to use it in my new content management system.


    regards
    René
  2. Alex
    Alex Says:
    When user clicks upload icon i want that link to open in a new window. How can I add static url to the set.js.
  3. CF Mitrah
    CF Mitrah Says:
    In set.js, instead of calling InlineUpload.display function, you should wrote your own JS function which will open pop-up window. Then call that JS function in the beforeInsert event of upload icon.
    {name:'Upload', key:'M',beforeInsert:function(markItUp){CallYourJSFunctionWhichOpenPop-UpWindow()}}
  4. ikscher
    ikscher Says:
    i do it just as you said,but it doesn't work, i use php develop, what is the problem ,can you help me ?
  5. CF Mitrah
    CF Mitrah Says:
    what is the problem you are facing? contact me through email.
  6. ikscher
    ikscher Says:
    yes ,it is php code, it invoke php code thorough ajax call, it make errors from javascript code ,can you help me?i hava sent a email to your mailbox.thanks
  7. delock
    delock Says:
    Hi

    I have a linux/php5 server, what modification can i do in ImgUploader.cfm to work with my server ?
  8. CF Mitrah
    CF Mitrah Says:
    Markitup image upload plugin will submit all form fields to action page (in your case it is a PHP file) using post method. Please change action file handler name in to your php file in InlineUpload.js. Something like action: 'imgUploader.php'. And then do file upload operation in your PHP code. Sorry I don't have idea in PHP coding to provide you sample on that.
  9. ikscher
    ikscher Says:
    i need a sample of php code for upload image

Leave a Reply

*** Please do not post spam. All comments require moderation,
So it may take some time to post to this blog! ***



Powered by Mango Blog. Design and Icons by N.Design Studio