← Back to team overview

savoirfairelinux-openerp team mailing list archive

[Merge] lp:~savoirfairelinux-openerp/knowledge-addons/add_document_multiple_records into lp:knowledge-addons/7.0

 

El Hadji Dem (http://www.savoirfairelinux.com) has proposed merging lp:~savoirfairelinux-openerp/knowledge-addons/add_document_multiple_records into lp:knowledge-addons/7.0.

Requested reviews:
  Holger Brunn (Therp) (hbrunn)
  Sandy Carter (http://www.savoirfairelinux.com) (sandy-carter)

For more details, see:
https://code.launchpad.net/~savoirfairelinux-openerp/knowledge-addons/add_document_multiple_records/+merge/206953

Added document_multiple_records module: It allows to manage a document with a multiple records.
-- 
https://code.launchpad.net/~savoirfairelinux-openerp/knowledge-addons/add_document_multiple_records/+merge/206953
Your team Savoir-faire Linux' OpenERP is subscribed to branch lp:~savoirfairelinux-openerp/knowledge-addons/add_document_multiple_records.
=== added directory 'document_multiple_records'
=== added file 'document_multiple_records/__init__.py'
--- document_multiple_records/__init__.py	1970-01-01 00:00:00 +0000
+++ document_multiple_records/__init__.py	2014-02-18 15:06:41 +0000
@@ -0,0 +1,26 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2014 Savoir-faire Linux
+#    (<http://www.savoirfairelinux.com>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+
+from . import document
+import wizard
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'document_multiple_records/__openerp__.py'
--- document_multiple_records/__openerp__.py	1970-01-01 00:00:00 +0000
+++ document_multiple_records/__openerp__.py	2014-02-18 15:06:41 +0000
@@ -0,0 +1,55 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2014 Savoir-faire Linux
+#    (<http://www.savoirfairelinux.com>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+    'name': 'Document Management System for Multiple Records',
+    'version': '0.1',
+    'category': 'Knowledge Management',
+    'summary': 'Document Management System for Multiple Records',
+    'description': """
+Document Management System for Multiple Records
+==============================================
+
+Contributors
+------------
+* El Hadji Dem (elhadji.dem@xxxxxxxxxxxxxxxxxxxx)
+""",
+    'author': 'Savoir-faire Linux',
+    'website': 'www.savoirfairelinux.com',
+    'license': 'AGPL-3',
+    'depends': [
+        'document',
+    ],
+    'data': [
+        'document_view.xml',
+        'wizard/document_wizard_view.xml',
+    ],
+    'js': ['static/src/js/document.js'],
+    'qweb': ['static/src/xml/document.xml'],
+    'test': [],
+    'demo': [
+    ],
+    'installable': True,
+    'auto_install': False,
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'document_multiple_records/document.py'
--- document_multiple_records/document.py	1970-01-01 00:00:00 +0000
+++ document_multiple_records/document.py	2014-02-18 15:06:41 +0000
@@ -0,0 +1,66 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2014 Savoir-faire Linux
+#    (<http://www.savoirfairelinux.com>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+
+
+class document_file(orm.Model):
+    _inherit = 'ir.attachment'
+
+    _columns = {
+        'attachmentdocument_ids': fields.one2many('ir.attachment.document', 'attachment_id', 'Records'),
+    }
+
+    def unlink(self, cr, uid, ids, context=None, check=True):
+        ir_attach_doc_obj = self.pool.get('ir.attachment.document')
+        if context is None:
+            context = {}
+        for line in self.browse(cr, uid, ids, context=context):
+            if line.attachmentdocument_ids:
+                first_id = min(line.attachmentdocument_ids)
+
+                result = self.write(cr, uid, ids, {'res_id': first_id.res_id,
+                                                   'res_model': first_id.res_model,
+                                                   'res_name': first_id.res_name, }, context=context)
+                ir_attach_doc_obj.unlink(cr, uid, min(line.attachmentdocument_ids).id, context=context)
+            else:
+                result = super(document_file, self).unlink(cr, uid, ids, context=context)
+        return result
+
+
+class ir_attachment_document(orm.Model):
+    _description = 'Attachment Documents'
+    _name = 'ir.attachment.document'
+
+    _columns = {
+        'res_id': fields.integer('Resource ID', readonly=True,
+                                 help="The record id this is attached to."),
+        'res_model': fields.char('Resource Model', size=64,
+                                 readonly=True,
+                                 help="The database object this attachment will be attached to"),
+        'res_name': fields.char('Resource Name', type='char',
+                                size=128,
+                                readonly=True),
+        'attachment_id': fields.many2one('ir.attachment', 'Attachment'),
+    }
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'document_multiple_records/document_view.xml'
--- document_multiple_records/document_view.xml	1970-01-01 00:00:00 +0000
+++ document_multiple_records/document_view.xml	2014-02-18 15:06:41 +0000
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<openerp>
+<data>
+    <!--Add model list field-->
+    <record model="ir.ui.view" id="view_document_file_multiple_models_form">
+      <field name="name">ir.attachment.multiple.models</field>
+      <field name="model">ir.attachment</field>
+      <field name="inherit_id" ref="document.view_document_file_form"/>
+      <field name="arch" type="xml">
+        <group string="Indexed Content" position="after">
+          <group col="2" colspan="4">
+            <field name="attachmentdocument_ids" nolabel="1">
+              <tree string="AttachmentDocumentTree" create="false" version="7.0">
+                <field name="res_model"/>
+                <field name="res_id"/>
+                <field name="res_name"/>
+              </tree>
+              <form string="AttachmentDocumentForm">
+                <field name="res_model"/>
+                <field name="res_id"/>
+                <field name="res_name"/>
+              </form>
+            </field>
+          </group>
+        </group>
+      </field>
+    </record>
+</data>
+</openerp>
+

=== added directory 'document_multiple_records/i18n'
=== added file 'document_multiple_records/i18n/document_multiple_records.pot'
--- document_multiple_records/i18n/document_multiple_records.pot	1970-01-01 00:00:00 +0000
+++ document_multiple_records/i18n/document_multiple_records.pot	2014-02-18 15:06:41 +0000
@@ -0,0 +1,140 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# 	* document_multiple_records
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-02-06 19:28+0000\n"
+"PO-Revision-Date: 2014-02-06 14:29-0500\n"
+"Last-Translator: EL Hadji DEM <elhadji.dem@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: \n"
+"X-Generator: Poedit 1.5.4\n"
+
+#. module: document_multiple_records
+#: field:ir.attachment.document,res_id:0
+msgid "Resource ID"
+msgstr ""
+
+#. module: document_multiple_records
+#: view:ir.attachment.wizard:0
+msgid "Select document(s)"
+msgstr ""
+
+#. module: document_multiple_records
+#. openerp-web
+#: code:addons/document_multiple_records/static/src/xml/document.xml:7
+#, python-format
+msgid "Add existing Doc..."
+msgstr ""
+
+#. module: document_multiple_records
+#: field:ir.attachment.document,attachment_id:0
+msgid "Attachment"
+msgstr ""
+
+#. module: document_multiple_records
+#: view:ir.attachment.wizard:0
+msgid "AttachmentDocumentWizardTree"
+msgstr ""
+
+#. module: document_multiple_records
+#. openerp-web
+#: code:addons/document_multiple_records/static/src/js/document.js:26
+#: model:ir.actions.act_window,name:document_multiple_records.action_view_document
+#: view:ir.attachment.wizard:0
+#, python-format
+msgid "Add Document"
+msgstr ""
+
+#. module: document_multiple_records
+#: field:ir.attachment.document,res_name:0
+msgid "Resource Name"
+msgstr ""
+
+#. module: document_multiple_records
+#: model:ir.model,name:document_multiple_records.model_ir_attachment_document
+msgid "Attachment Documents"
+msgstr ""
+
+#. module: document_multiple_records
+#: field:ir.attachment,attachmentdocument_ids:0
+msgid "Records"
+msgstr ""
+
+#. module: document_multiple_records
+#: view:ir.attachment:0
+msgid "AttachmentDocumentTree"
+msgstr ""
+
+#. module: document_multiple_records
+#: model:ir.model,name:document_multiple_records.model_ir_attachment
+msgid "ir.attachment"
+msgstr ""
+
+#. module: document_multiple_records
+#: view:ir.attachment:0
+msgid "Indexed Content"
+msgstr ""
+
+#. module: document_multiple_records
+#: model:ir.model,name:document_multiple_records.model_ir_attachment_wizard
+msgid "Attachment wizard"
+msgstr ""
+
+#. module: document_multiple_records
+#: view:ir.attachment:0
+msgid "AttachmentDocumentForm"
+msgstr ""
+
+#. module: document_multiple_records
+#: code:addons/document_multiple_records/wizard/document_wizard.py:46
+#, python-format
+msgid "Error"
+msgstr ""
+
+#. module: document_multiple_records
+#: help:ir.attachment.document,res_model:0
+msgid "The database object this attachment will be attached to"
+msgstr ""
+
+#. module: document_multiple_records
+#: help:ir.attachment.document,res_id:0
+msgid "The record id this is attached to."
+msgstr ""
+
+#. module: document_multiple_records
+#: field:ir.attachment.wizard,attachment_ids:0
+msgid "Attachments"
+msgstr ""
+
+#. module: document_multiple_records
+#: field:ir.attachment.document,res_model:0
+msgid "Resource Model"
+msgstr ""
+
+#. module: document_multiple_records
+#: view:ir.attachment.wizard:0
+msgid "Cancel"
+msgstr ""
+
+#. module: document_multiple_records
+#: view:ir.attachment.wizard:0
+msgid "Apply"
+msgstr ""
+
+#. module: document_multiple_records
+#: view:ir.attachment.wizard:0
+msgid "or"
+msgstr ""
+
+#. module: document_multiple_records
+#: code:addons/document_multiple_records/wizard/document_wizard.py:47
+#, python-format
+msgid "You have to select at least 1 Document. And try again"
+msgstr ""

=== added directory 'document_multiple_records/static'
=== added directory 'document_multiple_records/static/src'
=== added directory 'document_multiple_records/static/src/js'
=== added file 'document_multiple_records/static/src/js/document.js'
--- document_multiple_records/static/src/js/document.js	1970-01-01 00:00:00 +0000
+++ document_multiple_records/static/src/js/document.js	2014-02-18 15:06:41 +0000
@@ -0,0 +1,39 @@
+openerp.document_multiple_records = function(instance, m) {
+var _t = instance.web._t,
+    QWeb = instance.web.qweb;
+
+    instance.web.Sidebar.include({
+        redraw: function() {
+            var self = this;
+            this._super.apply(this, arguments);
+            self.$el.find('.oe_sidebar_add_attachment').after(QWeb.render('AddDocfromserver', {widget: self}))
+            self.$el.find('.open').on('click', function (e) {
+                self.on_call_new_view_function();
+                //this.$('.oe_btn_class_name').on('click', this.on_call_new_view_function);
+            });
+        },
+        on_call_new_view_function: function(state) {
+            var self = this;
+            var view = self.getParent();
+            var ids = ( view.fields_view.type != "form" )? view.groups.get_selection().ids : [ view.datarecord.id ];
+            // you can pass in other data using the context dictionary variable
+            var context = {
+            'model': view.dataset.model,
+            'ids': ids,
+            };
+            // the action dictionary variable sends data in the "self.do_action" method
+            var action = {
+                name: _t("Add Document"),
+                type: 'ir.actions.act_window',
+                res_model: 'ir.attachment.wizard',
+                view_mode: 'form',
+                view_type: 'form',
+                views: [[false, 'form']],
+                target: 'new',
+                context: context,
+            };
+            // self.do_action accepts the action parameter and opens the new view
+            self.do_action(action);
+        }
+    });
+};

=== added directory 'document_multiple_records/static/src/xml'
=== added file 'document_multiple_records/static/src/xml/document.xml'
--- document_multiple_records/static/src/xml/document.xml	1970-01-01 00:00:00 +0000
+++ document_multiple_records/static/src/xml/document.xml	2014-02-18 15:06:41 +0000
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vim:fdl=1:
+-->
+<templates id="template" xml:space="preserve">
+
+<t t-name="AddDocfromserver">
+     <li class="open"><span><b>Add existing Doc...</b></span></li>
+</t>
+
+</templates>

=== added directory 'document_multiple_records/wizard'
=== added file 'document_multiple_records/wizard/__init__.py'
--- document_multiple_records/wizard/__init__.py	1970-01-01 00:00:00 +0000
+++ document_multiple_records/wizard/__init__.py	2014-02-18 15:06:41 +0000
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2014 Savoir-faire Linux
+#    (<http://www.savoirfairelinux.com>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from . import document_wizard
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'document_multiple_records/wizard/document_wizard.py'
--- document_multiple_records/wizard/document_wizard.py	1970-01-01 00:00:00 +0000
+++ document_multiple_records/wizard/document_wizard.py	2014-02-18 15:06:41 +0000
@@ -0,0 +1,56 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2014 Savoir-faire Linux
+#    (<http://www.savoirfairelinux.com>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+from openerp.tools.translate import _
+
+
+class document_wizard(orm.Model):
+    _name = "ir.attachment.wizard"
+    _description = "Attachment wizard"
+    _columns = {
+        'attachment_ids': fields.many2many('ir.attachment',
+                                           'document_attachment_rel',
+                                           'wizard_id', 'attachment_id', 'Attachments'),
+    }
+
+    def action_apply(self, cr, uid, ids, context=None):
+        if context is None:
+            context = {}
+        ir_attach_obj = self.pool.get('ir.attachment')
+        ir_attach_doc_obj = self.pool.get('ir.attachment.document')
+        ir_model_obj = self.pool.get(context['model'])
+
+        name = ir_model_obj.browse(cr, uid, context['ids'], context=context)[0]['name']
+        data = self.read(cr, uid, ids, [], context=context)[0]
+        if not data['attachment_ids']:
+            raise orm.except_orm(_('Error'),
+                                 _('You have to select at least 1 Document. And try again'))
+        for attach in ir_attach_obj.browse(cr, uid, data['attachment_ids'], context=context):
+            data_attach = {
+                'res_model': context['model'],
+                'res_id': context['ids'][0],
+                'res_name': name,
+                'attachment_id': attach.id,
+            }
+            ir_attach_doc_obj.create(cr, uid, data_attach, context=context)
+        return {'type': 'ir.actions.act_window_close'}

=== added file 'document_multiple_records/wizard/document_wizard_view.xml'
--- document_multiple_records/wizard/document_wizard_view.xml	1970-01-01 00:00:00 +0000
+++ document_multiple_records/wizard/document_wizard_view.xml	2014-02-18 15:06:41 +0000
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<openerp>
+<data>
+
+  <record id="document_form_view" model="ir.ui.view">
+    <field name="name">Add Document</field>
+    <field name="model">ir.attachment.wizard</field>
+    <field name="arch" type="xml">
+      <form string="Add Document" version="7.0">
+        <group string="Select document(s)" colspan="4">
+          <field name="attachment_ids" nolabel="1">
+            <tree string="AttachmentDocumentWizardTree">
+                <field name="name"/>
+                <field name="create_uid"/>
+                <field name="create_date"/>
+                <field name="type"/>
+            </tree>
+          </field>
+        </group>
+        <footer>
+            <button string="Apply" name="action_apply" type="object" class="oe_highlight"/>
+            or
+            <button string="Cancel" class="oe_link" special="cancel" />
+        </footer>
+      </form>
+    </field>
+  </record>
+
+  <!-- Actions -->
+  <record model="ir.actions.act_window" id="action_view_document">
+    <field name="name">Add Document</field>
+    <field name="res_model">ir.attachment.wizard</field>
+    <field name="view_type">form</field>
+    <field name="view_mode">tree,form</field>
+    <field name="view_id" ref="document_form_view"/>
+    <field name="target">new</field>
+  </record>
+
+</data>
+</openerp>
+

=== added directory 'wiki_wikimedia'
=== added file 'wiki_wikimedia/__init__.py'
--- wiki_wikimedia/__init__.py	1970-01-01 00:00:00 +0000
+++ wiki_wikimedia/__init__.py	2014-02-18 15:06:41 +0000
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2012 Therp BV (<http://therp.nl>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added file 'wiki_wikimedia/__openerp__.py'
--- wiki_wikimedia/__openerp__.py	1970-01-01 00:00:00 +0000
+++ wiki_wikimedia/__openerp__.py	2014-02-18 15:06:41 +0000
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    OpenERP, Open Source Management Solution
+#    This module copyright (C) 2012 Therp BV (<http://therp.nl>).
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU Affero General Public License as
+#    published by the Free Software Foundation, either version 3 of the
+#    License, or (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU Affero General Public License for more details.
+#
+#    You should have received a copy of the GNU Affero General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{
+    'name': 'Wiki - wikimedia syntax',
+    'version': '1.0',
+    'category': 'Knowledge Management',
+    'complexity': "normal",
+    'description': """
+    Replace the standard parser by one that understands (more) wikimedia syntax
+    """,
+    'author': 'Therp BV',
+    'website': 'http://therp.nl',
+    'depends': ['wiki'],
+    'init_xml': [],
+    'installable': True,
+    'auto_install': False,
+    'js': ['static/src/lib/instaview.js', 'static/src/js/wiki_wikimedia.js'],
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

=== added directory 'wiki_wikimedia/static'
=== added directory 'wiki_wikimedia/static/src'
=== added directory 'wiki_wikimedia/static/src/js'
=== added file 'wiki_wikimedia/static/src/js/wiki_wikimedia.js'
--- wiki_wikimedia/static/src/js/wiki_wikimedia.js	1970-01-01 00:00:00 +0000
+++ wiki_wikimedia/static/src/js/wiki_wikimedia.js	2014-02-18 15:06:41 +0000
@@ -0,0 +1,9 @@
+openerp.wiki_wikimedia = function (openerp) {
+    openerp.wiki.FieldWikiReadonly = openerp.web.page.FieldCharReadonly.extend({
+        set_value: function (value) {
+            var show_value = InstaView.convert(value || '');
+            this.$element.find('div').html(show_value);
+            return show_value;
+        }
+    });
+};

=== added directory 'wiki_wikimedia/static/src/lib'
=== added file 'wiki_wikimedia/static/src/lib/instaview.js'
--- wiki_wikimedia/static/src/lib/instaview.js	1970-01-01 00:00:00 +0000
+++ wiki_wikimedia/static/src/lib/instaview.js	2014-02-18 15:06:41 +0000
@@ -0,0 +1,989 @@
+/* <pre><nowiki>
+This is a copy of InstaView for use in other applications like [[User:Cacycle/wikEd|wikEd]].
+ 
+Changes made:
+	Fixed code duplication, fixed "doubled article name" bug in links. Cacycle 00:56, 9 September 2007 (UTC)
+	The "Script to embed InstaView in MediaWiki's edit page" has been commented out
+	added: // get values from MediaWiki global variables (Cacycle)
+ 
+Installation:
+	if (typeof(InstaView) != 'object')) {
+		var script = document.createElement('script');
+		script.type = 'text/javascript';
+		script.src  = 'http://en.wikipedia.org/w/index.php?title=User:Pilaf/dev/instaview.js&action=raw&ctype=text/javascript&dontcountme=s';
+		document.getElementsByTagName('head')[0].appendChild(script);
+	}
+ 
+*/
+ 
+// Last update: Cacycle 22:26, 22 November 2008 (UTC)
+ 
+/*
+// Script to embed InstaView in MediaWiki's edit page
+addOnloadHook(function(){
+  if (document.getElementById('editpage-copywarn')) {
+    var oldPreview = document.getElementById('wpPreview');
+    var newPreview = document.createElement('input');
+    newPreview.setAttribute('type', 'button');
+    newPreview.setAttribute('style', 'font-style: italic');
+    newPreview.setAttribute('value', 'InstaView');
+    newPreview.setAttribute('id', 'InstaView');
+    newPreview.setAttribute('name', 'InstaView');
+    newPreview.setAttribute('onclick', "InstaView.dump('wpTextbox1', 'InstaViewDump')");
+    oldPreview.parentNode.insertBefore(newPreview, oldPreview);
+    oldPreview.parentNode.innerHTML += '<div style="margin: 5px 0 5px 0; padding: 5px; border: 2px solid orange;" id="InstaViewDump"></div>';
+    oldPreview.value = 'Classic Preview';
+    }
+});
+*/
+ 
+/*
+ * InstaView - a Mediawiki to HTML converter in JavaScript
+ * Version 0.6.1
+ * Copyright (C) Pedro Fayolle 2005-2006
+ * http://en.wikipedia.org/wiki/User:Pilaf
+ * Distributed under the BSD license
+ *
+ * Changelog:
+ *
+ * 0.6.1
+ * - Fixed problem caused by \r characters
+ * - Improved inline formatting parser
+ *
+ * 0.6
+ * - Changed name to InstaView
+ * - Some major code reorganizations and factored out some common functions
+ * - Handled conversion of relative links (i.e. [[/foo]])
+ * - Fixed misrendering of adjacent definition list items
+ * - Fixed bug in table headings handling
+ * - Changed date format in signatures to reflect Mediawiki's
+ * - Fixed handling of [[:Image:...]]
+ * - Updated MD5 function (hopefully it will work with UTF-8)
+ * - Fixed bug in handling of links inside images
+ *
+ * To do:
+ * - Better support for <math>
+ * - Full support for <nowiki>
+ * - Parser-based (as opposed to RegExp-based) inline wikicode handling (make it one-pass and bullet-proof)
+ * - Support for templates (through AJAX)
+ * - Support for coloured links (AJAX)
+ */
+ 
+ 
+var InstaView = {}
+ 
+// options
+InstaView.conf =
+{
+	user: {},
+ 
+	wiki: {
+		lang: 'en',
+		interwiki: 'ab|aa|af|ak|sq|als|am|ang|ar|an|arc|hy|roa-rup|as|ast|av|ay|az|bm|ba|eu|be|bn|bh|bi|bs|br|bg|my|ca|ch|ce|chr|chy|ny|zh|zh-tw|zh-cn|cho|cv|kw|co|cr|hr|cs|da|dv|nl|dz|en|eo|et|ee|fo|fj|fi|fr|fy|ff|gl|ka|de|got|el|kl|gn|gu|ht|ha|haw|he|hz|hi|ho|hu|is|io|ig|id|ia|ie|iu|ik|ga|it|ja|jv|kn|kr|csb|ks|kk|km|ki|rw|rn|tlh|kv|kg|ko|kj|ku|ky|lo|la|lv|li|ln|lt|jbo|nds|lg|lb|mk|mg|ms|ml|mt|gv|mi|minnan|mr|mh|zh-min-nan|mo|mn|mus|nah|na|nv|ne|se|no|nn|oc|or|om|pi|fa|pl|pt|pa|ps|qu|ro|rm|ru|sm|sg|sa|sc|gd|sr|sh|st|tn|sn|scn|simple|sd|si|sk|sl|so|st|es|su|sw|ss|sv|tl|ty|tg|ta|tt|te|th|bo|ti|tpi|to|tokipona|ts|tum|tr|tk|tw|uk|ur|ug|uz|ve|vi|vo|wa|cy|wo|xh|ii|yi|yo|za|zu',
+		default_thumb_width: 180
+	},
+ 
+	paths: {
+		articles: '/wiki/',
+		math: '/math/',
+		images: '',
+		images_fallback: 'http://upload.wikimedia.org/wikipedia/commons/',
+		magnify_icon: 'skins/common/images/magnify-clip.png'
+	},
+ 
+	locale: {
+		user: 'User',
+		image: 'Image',
+		category: 'Category',
+		months: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
+	}
+}
+ 
+ 
+// get values from MediaWiki global variables (Cacycle)
+if (typeof(wgArticlePath) != 'undefined') { InstaView.conf.paths.articles = wgArticlePath.replace(/\$1/, ''); }
+if (typeof(wgContentLanguage) != 'undefined') { InstaView.conf.wiki.lang = wgContentLanguage; }
+ 
+// options with default values or backreferences
+with (InstaView.conf) {
+	user.name = user.name || 'Wikipedian'
+	user.signature = '[['+locale.user+':'+user.name+'|'+user.name+']]'
+	paths.images = 'http://upload.wikimedia.org/wikipedia/' + wiki.lang + '/'
+}
+ 
+// define constants
+InstaView.BLOCK_IMAGE = new RegExp('^\\[\\['+InstaView.conf.locale.image+':.*?\\|.*?(?:frame|thumbnail|thumb|none|right|left|center)', 'i');
+ 
+InstaView.dump = function(from, to)
+{
+	if (typeof from == 'string') from = document.getElementById(from)
+	if (typeof to == 'string') to = document.getElementById(to)
+	to.innerHTML = this.convert(from.value)
+}
+ 
+InstaView.convert = function(wiki)
+{
+	var 	ll = (typeof wiki == 'string')? wiki.replace(/\r/g,'').split(/\n/): wiki, // lines of wikicode
+		o='',	// output
+		p=0,	// para flag
+		$r	// result of passing a regexp to $()
+ 
+	// some shorthands
+	function remain() { return ll.length }
+	function sh() { return ll.shift() } // shift
+	function ps(s) { o+=s } // push
+ 
+	function f() // similar to C's printf, uses ? as placeholders, ?? to escape question marks
+	{
+		var i=1,a=arguments,f=a[0],o='',c,p
+		for (;i<a.length; i++) if ((p=f.indexOf('?'))+1) {
+			// allow character escaping
+			i -= c=f.charAt(p+1)=='?'?1:0
+			o += f.substring(0,p)+(c?'?':a[i])
+			f=f.substr(p+1+c)
+		} else break;
+		return o+f
+	}
+ 
+	function html_entities(s) { return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;") }
+ 
+	function max(a,b) { return (a>b)?a:b }
+	function min(a,b) { return (a<b)?a:b }
+ 
+	// return the first non matching character position between two strings
+	function str_imatch(a, b)
+	{
+		for (var i=0, l=min(a.length, b.length); i<l; i++) if (a.charAt(i)!=b.charAt(i)) break
+		return i
+	}
+ 
+	// compare current line against a string or regexp
+	// if passed a string it will compare only the first string.length characters
+	// if passed a regexp the result is stored in $r
+	function $(c) { return (typeof c == 'string') ? (ll[0].substr(0,c.length)==c) : ($r = ll[0].match(c)) }
+ 
+	function $$(c) { return ll[0]==c } // compare current line against a string
+	function _(p) { return ll[0].charAt(p) } // return char at pos p
+ 
+	function endl(s) { ps(s); sh() }
+ 
+	function parse_list()
+	{
+		var prev='';
+ 
+		while (remain() && $(/^([*#:;]+)(.*)$/)) {
+ 
+			var l_match = $r
+ 
+			sh()
+ 
+			var ipos = str_imatch(prev, l_match[1])
+ 
+			// close uncontinued lists
+			for (var i=prev.length-1; i >= ipos; i--) {
+ 
+				var pi = prev.charAt(i)
+ 
+				if (pi=='*') ps('</ul>')
+				else if (pi=='#') ps('</ol>')
+				// close a dl only if the new item is not a dl item (:, ; or empty)
+				else switch (l_match[1].charAt(i)) { case'':case'*':case'#': ps('</dl>') }
+			}
+ 
+			// open new lists
+			for (var i=ipos; i<l_match[1].length; i++) {
+ 
+				var li = l_match[1].charAt(i)
+ 
+				if (li=='*') ps('<ul>')
+				else if (li=='#') ps('<ol>')
+				// open a new dl only if the prev item is not a dl item (:, ; or empty)
+				else switch(prev.charAt(i)) { case'':case'*':case'#': ps('<dl>') }
+			}
+ 
+			switch (l_match[1].charAt(l_match[1].length-1)) {
+ 
+				case '*': case '#':
+					ps('<li>' + parse_inline_nowiki(l_match[2])); break
+ 
+				case ';':
+					ps('<dt>')
+ 
+					var dt_match
+ 
+					// handle ;dt :dd format
+					if (dt_match = l_match[2].match(/(.*?) (:.*?)$/)) {
+ 
+						ps(parse_inline_nowiki(dt_match[1]))
+						ll.unshift(dt_match[2])
+ 
+					} else ps(parse_inline_nowiki(l_match[2]))
+ 
+					break
+ 
+				case ':':
+					ps('<dd>' + parse_inline_nowiki(l_match[2]))
+			}
+ 
+			prev=l_match[1]
+		}
+ 
+		// close remaining lists
+		for (var i=prev.length-1; i>=0; i--)
+			ps(f('</?>', (prev.charAt(i)=='*')? 'ul': ((prev.charAt(i)=='#')? 'ol': 'dl')))
+	}
+ 
+	function parse_table()
+	{
+		endl(f('<table?>', $(/^\{\|( .*)$/)? $r[1]: ''))
+ 
+		for (;remain();) if ($('|')) switch (_(1)) {
+			case '}': endl('</table>'); return
+			case '-': endl(f('<tr ?>', $(/\|-*(.*)/)[1])); break
+			default: parse_table_data()
+		}
+		else if ($('!')) parse_table_data()
+		else sh()
+	}
+ 
+	function parse_table_data()
+	{
+		var td_line, match_i
+ 
+		// 1: "|+", '|' or '+'
+		// 2: ??
+		// 3: attributes ??
+		// TODO: finish commenting this regexp
+		var td_match = sh().match(/^(\|\+|\||!)((?:([^[|]*?)\|(?!\|))?(.*))$/)
+ 
+		if (td_match[1] == '|+') ps('<caption');
+		else ps('<t' + ((td_match[1]=='|')?'d':'h'))
+ 
+		if (typeof td_match[3] != 'undefined') {
+ 
+			ps(' ' + td_match[3])
+			match_i = 4
+ 
+		} else match_i = 2
+ 
+		ps('>')
+ 
+		if (td_match[1] != '|+') {
+ 
+			// use || or !! as a cell separator depending on context
+			// NOTE: when split() is passed a regexp make sure to use non-capturing brackets
+			td_line = td_match[match_i].split((td_match[1] == '|')? '||': /(?:\|\||!!)/)
+ 
+			ps(parse_inline_nowiki(td_line.shift()))
+ 
+			while (td_line.length) ll.unshift(td_match[1] + td_line.pop())
+ 
+		} else ps(td_match[match_i])
+ 
+		var tc = 0, td = []
+ 
+		for (;remain(); td.push(sh()))
+		if ($('|')) {
+			if (!tc) break // we're at the outer-most level (no nested tables), skip to td parse
+			else if (_(1)=='}') tc--
+		}
+		else if (!tc && $('!')) break
+		else if ($('{|')) tc++
+ 
+		if (td.length) ps(InstaView.convert(td))
+	}
+ 
+	function parse_pre()
+	{
+		ps('<pre>')
+		do endl(parse_inline_nowiki(ll[0].substring(1)) + "\n"); while (remain() && $(' '))
+		ps('</pre>')
+	}
+ 
+	function parse_block_image()
+	{
+		ps(parse_image(sh()))
+	}
+ 
+	function parse_image(str)
+	{
+		// get what's in between "[[Image:" and "]]"
+		var tag = str.substring(InstaView.conf.locale.image.length + 3, str.length - 2);
+ 
+		var width;
+		var attr = [], filename, caption = '';
+		var thumb=0, frame=0, center=0;
+		var align='';
+ 
+		if (tag.match(/\|/)) {
+			// manage nested links
+			var nesting = 0;
+			var last_attr;
+			for (var i = tag.length-1; i > 0; i--) {
+				if (tag.charAt(i) == '|' && !nesting) {
+					last_attr = tag.substr(i+1);
+					tag = tag.substring(0, i);
+					break;
+				} else switch (tag.substr(i-1, 2)) {
+					case ']]':
+						nesting++;
+						i--;
+						break;
+					case '[[':
+						nesting--;
+						i--;
+				}
+			}
+ 
+			attr = tag.split(/\s*\|\s*/);
+			attr.push(last_attr);
+			filename = attr.shift();
+ 
+			var w_match;
+ 
+			for (;attr.length; attr.shift())
+			if (w_match = attr[0].match(/^(\d*)px$/)) width = w_match[1]
+			else switch(attr[0]) {
+				case 'thumb':
+				case 'thumbnail':
+					thumb=true;
+				case 'frame':
+					frame=true;
+					break;
+				case 'none':
+				case 'right':
+				case 'left':
+					center=false;
+					align=attr[0];
+					break;
+				case 'center':
+					center=true;
+					align='none';
+					break;
+				default:
+					if (attr.length == 1) caption = attr[0];
+			}
+ 
+		} else filename = tag;
+ 
+ 
+		var o='';
+ 
+		if (frame) {
+ 
+			if (align=='') align = 'right';
+ 
+			o += f("<div class='thumb t?'>", align);
+ 
+			if (thumb) {
+				if (!width) width = InstaView.conf.wiki.default_thumb_width;
+ 
+				o += f("<div style='width:?px;'>?", 2+width*1, make_image(filename, caption, width)) +
+					f("<div class='thumbcaption'><div class='magnify' style='float:right'><a href='?' class='internal' title='Enlarge'><img src='?'></a></div>?</div>",
+						InstaView.conf.paths.articles + InstaView.conf.locale.image + ':' + filename,
+						InstaView.conf.paths.magnify_icon,
+						parse_inline_nowiki(caption)
+					)
+			} else {
+				o += '<div>' + make_image(filename, caption) + f("<div class='thumbcaption'>?</div>", parse_inline_nowiki(caption))
+			}
+ 
+			o += '</div></div>';
+ 
+		} else if (align != '') {
+			o += f("<div class='float?'><span>?</span></div>", align, make_image(filename, caption, width));
+		} else {
+			return make_image(filename, caption, width);
+		}
+ 
+		return center? f("<div class='center'>?</div>", o): o;
+	}
+ 
+	function parse_inline_nowiki(str)
+	{
+		var start, lastend=0
+		var substart=0, nestlev=0, open, close, subloop;
+		var html='';
+ 
+		while (-1 != (start = str.indexOf('<nowiki>', substart))) {
+			html += parse_inline_wiki(str.substring(lastend, start));
+			start += 8;
+			substart = start;
+			subloop = true;
+			do {
+				open = str.indexOf('<nowiki>', substart);
+				close = str.indexOf('</nowiki>', substart);
+				if (close<=open || open==-1) {
+					if (close==-1) {
+						return html + html_entities(str.substr(start));
+					}
+					substart = close+9;
+					if (nestlev) {
+						nestlev--;
+					} else {
+						lastend = substart;
+						html += html_entities(str.substring(start, lastend-9));
+						subloop = false;
+					}
+				} else {
+					substart = open+8;
+					nestlev++;
+				}
+			} while (subloop)
+		}
+ 
+		return html + parse_inline_wiki(str.substr(lastend));
+	}
+ 
+	function make_image(filename, caption, width)
+	{
+		// uppercase first letter in file name
+		filename = filename.charAt(0).toUpperCase() + filename.substr(1);
+		// replace spaces with underscores
+		filename = filename.replace(/ /g, '_');
+ 
+		caption = strip_inline_wiki(caption);
+ 
+		var md5 = hex_md5(filename);
+ 
+		var source = md5.charAt(0) + '/' + md5.substr(0,2) + '/' + filename;
+ 
+		if (width) width = "width='" + width + "px'";
+ 
+		var img = f("<img onerror=\"this.onerror=null;this.src='?'\" src='?' ? ?>", InstaView.conf.paths.images_fallback + source, InstaView.conf.paths.images + source, (caption!='')? "alt='" + caption + "'" : '', width);
+ 
+		return f("<a class='image' ? href='?'>?</a>", (caption!='')? "title='" + caption + "'" : '', InstaView.conf.paths.articles + InstaView.conf.locale.image + ':' + filename, img);
+	}
+ 
+	function parse_inline_images(str)
+	{
+		var start, substart=0, nestlev=0;
+		var loop, close, open, wiki, html;
+ 
+		while (-1 != (start=str.indexOf('[[', substart))) {
+			if(str.substr(start+2).match(RegExp('^' + InstaView.conf.locale.image + ':','i'))) {
+				loop=true;
+				substart=start;
+				do {
+					substart+=2;
+					close=str.indexOf(']]',substart);
+					open=str.indexOf('[[',substart);
+					if (close<=open||open==-1) {
+						if (close==-1) return str;
+						substart=close;
+						if (nestlev) {
+							nestlev--;
+						} else {
+							wiki=str.substring(start,close+2);
+							html=parse_image(wiki);
+							str=str.replace(wiki,html);
+							substart=start+html.length;
+							loop=false;
+						}
+					} else {
+						substart=open;
+						nestlev++;
+					}
+				} while (loop)
+ 
+			} else break;
+		}
+ 
+		return str;
+	}
+ 
+	// the output of this function doesn't respect the FILO structure of HTML
+	// but since most browsers can handle it I'll save myself the hassle
+	function parse_inline_formatting(str)
+	{
+		var em,st,i,li,o='';
+		while ((i=str.indexOf("''",li))+1) {
+			o += str.substring(li,i);
+			li=i+2;
+			if (str.charAt(i+2)=="'") {
+				li++;
+				st=!st;
+				o+=st?'<strong>':'</strong>';
+			} else {
+				em=!em;
+				o+=em?'<em>':'</em>';
+			}
+		}
+		return o+str.substr(li);
+	}
+ 
+	function parse_inline_wiki(str)
+	{
+		var aux_match;
+ 
+		str = parse_inline_images(str);
+		str = parse_inline_formatting(str);
+ 
+		// math
+		while (aux_match = str.match(/<(?:)math>(.*?)<\/math>/i)) {
+			var math_md5 = hex_md5(aux_match[1]);
+			str = str.replace(aux_match[0], f("<img src='?.png'>", InstaView.conf.paths.math+math_md5));
+		}
+ 
+		// Build a Mediawiki-formatted date string
+		var date = new Date;
+		var minutes = date.getUTCMinutes();
+		if (minutes < 10) minutes = '0' + minutes;
+		var date = f("?:?, ? ? ? (UTC)", date.getUTCHours(), minutes, date.getUTCDate(), InstaView.conf.locale.months[date.getUTCMonth()], date.getUTCFullYear());
+ 
+		// text formatting
+		return str.
+			// signatures
+			replace(/~{5}(?!~)/g, date).
+			replace(/~{4}(?!~)/g, InstaView.conf.user.name+' '+date).
+			replace(/~{3}(?!~)/g, InstaView.conf.user.name).
+ 
+			// [[:Category:...]], [[:Image:...]], etc...
+			replace(RegExp('\\[\\[:((?:'+InstaView.conf.locale.category+'|'+InstaView.conf.locale.image+'|'+InstaView.conf.wiki.interwiki+'):.*?)\\]\\]','gi'), "<a href='"+InstaView.conf.paths.articles+"$1'>$1</a>").
+			replace(RegExp('\\[\\[(?:'+InstaView.conf.locale.category+'|'+InstaView.conf.wiki.interwiki+'):.*?\\]\\]','gi'),'').
+ 
+			// [[/Relative links]]
+			replace(/\[\[(\/[^|]*?)\]\]/g, f("<a href='?$1'>$1</a>", location)).
+ 
+			// [[/Replaced|Relative links]]
+			replace(/\[\[(\/.*?)\|(.+?)\]\]/g, f("<a href='?$1'>$2</a>", location)).
+ 
+			// [[Common links]]
+			replace(/\[\[([^|]*?)\]\](\w*)/g, f("<a href='?$1'>$1$2</a>", InstaView.conf.paths.articles)).
+ 
+			// [[Replaced|Links]]
+			replace(/\[\[(.*?)\|([^\]]+?)\]\](\w*)/g, f("<a href='?$1'>$2$3</a>", InstaView.conf.paths.articles)).
+ 
+			// [[Stripped:Namespace|Namespace]]
+			replace(/\[\[([^\]]*?:)?(.*?)( *\(.*?\))?\|\]\]/g, f("<a href='?$1$2$3'>$2</a>", InstaView.conf.paths.articles)).
+ 
+			// External links
+			replace(/\[(https?|news|ftp|mailto|gopher|irc):(\/*)([^\]]*?) (.*?)\]/g, "<a href='$1:$2$3'>$4</a>").
+			replace(/\[http:\/\/(.*?)\]/g, "<a href='http://$1'>[#]</a>").
+			replace(/\[(news|ftp|mailto|gopher|irc):(\/*)(.*?)\]/g, "<a href='$1:$2$3'>$1:$2$3</a>").
+			replace(/(^| )(https?|news|ftp|mailto|gopher|irc):(\/*)([^ $]*)/g, "$1<a href='$2:$3$4'>$2:$3$4</a>").
+ 
+			replace('__NOTOC__','').
+			replace('__NOEDITSECTION__','');
+	}
+ 
+	function strip_inline_wiki(str)
+	{
+		return str
+			.replace(/\[\[[^\]]*\|(.*?)\]\]/g,'$1')
+			.replace(/\[\[(.*?)\]\]/g,'$1')
+			.replace(/''(.*?)''/g,'$1');
+	}
+ 
+	// begin parsing
+	for (;remain();) if ($(/^(={1,6})(.*)\1(.*)$/)) {
+		p=0
+		endl(f('<h?>?</h?>?', $r[1].length, parse_inline_nowiki($r[2]), $r[1].length, $r[3]))
+ 
+	} else if ($(/^[*#:;]/)) {
+		p=0
+		parse_list()
+ 
+	} else if ($(' ')) {
+		p=0
+		parse_pre()
+ 
+	} else if ($('{|')) {
+		p=0
+		parse_table()
+ 
+	} else if ($(/^----+$/)) {
+		p=0
+		endl('<hr>')
+ 
+	} else if ($(InstaView.BLOCK_IMAGE)) {
+		p=0
+		parse_block_image()
+ 
+	} else {
+ 
+		// handle paragraphs
+		if ($$('')) {
+			if (p = (remain()>1 && ll[1]==(''))) endl('<p><br>')
+		} else {
+			if(!p) {
+				ps('<p>')
+				p=1
+			}
+			ps(parse_inline_nowiki(ll[0]) + ' ')
+		}
+ 
+		sh();
+	}
+ 
+	return o
+}
+ 
+ 
+/*
+ * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
+ * Digest Algorithm, as defined in RFC 1321.
+ * Version 2.2-alpha Copyright (C) Paul Johnston 1999 - 2005
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for more info.
+ */
+ 
+/*
+ * Configurable variables. You may need to tweak these to be compatible with
+ * the server-side, but the defaults work in most cases.
+ */
+var hexcase = 0;   /* hex output format. 0 - lowercase; 1 - uppercase        */
+var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
+ 
+/*
+ * These are the functions you'll usually want to call
+ * They take string arguments and return either hex or base-64 encoded strings
+ */
+function hex_md5(s)    { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
+function b64_md5(s)    { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
+function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
+function hex_hmac_md5(k, d)
+  { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function b64_hmac_md5(k, d)
+  { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
+function any_hmac_md5(k, d, e)
+  { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
+ 
+/*
+ * Calculate the MD5 of a raw string
+ */
+function rstr_md5(s)
+{
+  return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
+}
+ 
+/*
+ * Calculate the HMAC-MD5, of a key and some data (raw strings)
+ */
+function rstr_hmac_md5(key, data)
+{
+  var bkey = rstr2binl(key);
+  if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
+ 
+  var ipad = Array(16), opad = Array(16);
+  for(var i = 0; i < 16; i++)
+  {
+    ipad[i] = bkey[i] ^ 0x36363636;
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;
+  }
+ 
+  var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
+  return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
+}
+ 
+/*
+ * Convert a raw string to a hex string
+ */
+function rstr2hex(input)
+{
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var output = "";
+  var x;
+  for(var i = 0; i < input.length; i++)
+  {
+    x = input.charCodeAt(i);
+    output += hex_tab.charAt((x >>> 4) & 0x0F)
+           +  hex_tab.charAt( x        & 0x0F);
+  }
+  return output;
+}
+ 
+/*
+ * Convert a raw string to a base-64 string
+ */
+function rstr2b64(input)
+{
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  var output = "";
+  var len = input.length;
+  for(var i = 0; i < len; i += 3)
+  {
+    var triplet = (input.charCodeAt(i) << 16)
+                | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
+                | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
+    for(var j = 0; j < 4; j++)
+    {
+      if(i * 8 + j * 6 > input.length * 8) output += b64pad;
+      else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
+    }
+  }
+  return output;
+}
+ 
+/*
+ * Convert a raw string to an arbitrary string encoding
+ */
+function rstr2any(input, encoding)
+{
+  var divisor = encoding.length;
+  var remainders = Array();
+  var i, q, x, quotient;
+ 
+  /* Convert to an array of 16-bit big-endian values, forming the dividend */
+  var dividend = Array(input.length / 2);
+  for(i = 0; i < dividend.length; i++)
+  {
+    dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
+  }
+ 
+  /*
+   * Repeatedly perform a long division. The binary array forms the dividend,
+   * the length of the encoding is the divisor. Once computed, the quotient
+   * forms the dividend for the next step. We stop when the dividend is zero.
+   * All remainders are stored for later use.
+   */
+  while(dividend.length > 0)
+  {
+    quotient = Array();
+    x = 0;
+    for(i = 0; i < dividend.length; i++)
+    {
+      x = (x << 16) + dividend[i];
+      q = Math.floor(x / divisor);
+      x -= q * divisor;
+      if(quotient.length > 0 || q > 0)
+        quotient[quotient.length] = q;
+    }
+    remainders[remainders.length] = x;
+    dividend = quotient;
+  }
+ 
+  /* Convert the remainders to the output string */
+  var output = "";
+  for(i = remainders.length - 1; i >= 0; i--)
+    output += encoding.charAt(remainders[i]);
+ 
+  return output;
+}
+ 
+/*
+ * Encode a string as utf-8.
+ * For efficiency, this assumes the input is valid utf-16.
+ */
+function str2rstr_utf8(input)
+{
+  var output = "";
+  var i = -1;
+  var x, y;
+ 
+  while(++i < input.length)
+  {
+    /* Decode utf-16 surrogate pairs */
+    x = input.charCodeAt(i);
+    y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
+    if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
+    {
+      x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
+      i++;
+    }
+ 
+    /* Encode output as utf-8 */
+    if(x <= 0x7F)
+      output += String.fromCharCode(x);
+    else if(x <= 0x7FF)
+      output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
+                                    0x80 | ( x         & 0x3F));
+    else if(x <= 0xFFFF)
+      output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
+                                    0x80 | ((x >>> 6 ) & 0x3F),
+                                    0x80 | ( x         & 0x3F));
+    else if(x <= 0x1FFFFF)
+      output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
+                                    0x80 | ((x >>> 12) & 0x3F),
+                                    0x80 | ((x >>> 6 ) & 0x3F),
+                                    0x80 | ( x         & 0x3F));
+  }
+  return output;
+}
+ 
+/*
+ * Encode a string as utf-16
+ */
+function str2rstr_utf16le(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length; i++)
+    output += String.fromCharCode( input.charCodeAt(i)        & 0xFF,
+                                  (input.charCodeAt(i) >>> 8) & 0xFF);
+  return output;
+}
+ 
+function str2rstr_utf16be(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length; i++)
+    output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
+                                   input.charCodeAt(i)        & 0xFF);
+  return output;
+}
+ 
+/*
+ * Convert a raw string to an array of little-endian words
+ * Characters >255 have their high-byte silently ignored.
+ */
+function rstr2binl(input)
+{
+  var output = Array(input.length >> 2);
+  for(var i = 0; i < output.length; i++)
+    output[i] = 0;
+  for(var i = 0; i < input.length * 8; i += 8)
+    output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
+  return output;
+}
+ 
+/*
+ * Convert an array of little-endian words to a string
+ */
+function binl2rstr(input)
+{
+  var output = "";
+  for(var i = 0; i < input.length * 32; i += 8)
+    output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
+  return output;
+}
+ 
+/*
+ * Calculate the MD5 of an array of little-endian words, and a bit length.
+ */
+function binl_md5(x, len)
+{
+  /* append padding */
+  x[len >> 5] |= 0x80 << ((len) % 32);
+  x[(((len + 64) >>> 9) << 4) + 14] = len;
+ 
+  var a =  1732584193;
+  var b = -271733879;
+  var c = -1732584194;
+  var d =  271733878;
+ 
+  for(var i = 0; i < x.length; i += 16)
+  {
+    var olda = a;
+    var oldb = b;
+    var oldc = c;
+    var oldd = d;
+ 
+    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
+    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
+    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
+    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
+    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
+    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
+    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
+    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
+    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
+    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
+    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
+    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
+    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
+    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
+    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
+    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
+ 
+    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
+    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
+    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
+    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
+    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
+    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
+    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
+    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
+    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
+    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
+    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
+    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
+    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
+    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
+    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
+    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
+ 
+    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
+    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
+    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
+    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
+    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
+    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
+    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
+    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
+    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
+    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
+    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
+    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
+    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
+    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
+    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
+    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
+ 
+    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
+    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
+    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
+    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
+    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
+    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
+    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
+    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
+    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
+    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
+    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
+    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
+    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
+    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
+    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
+    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
+ 
+    a = safe_add(a, olda);
+    b = safe_add(b, oldb);
+    c = safe_add(c, oldc);
+    d = safe_add(d, oldd);
+  }
+  return Array(a, b, c, d);
+}
+ 
+/*
+ * These functions implement the four basic operations the algorithm uses.
+ */
+function md5_cmn(q, a, b, x, s, t)
+{
+  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
+}
+function md5_ff(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
+}
+function md5_gg(a, b, c, d, x, s, t)
+{
+  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
+}
+function md5_hh(a, b, c, d, x, s, t)
+{
+  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
+}
+function md5_ii(a, b, c, d, x, s, t)
+{
+  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
+}
+ 
+/*
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
+ * to work around bugs in some JS interpreters.
+ */
+function safe_add(x, y)
+{
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+ 
+/*
+ * Bitwise rotate a 32-bit number to the left.
+ */
+function bit_rol(num, cnt)
+{
+  return (num << cnt) | (num >>> (32 - cnt));
+}
\ No newline at end of file


Follow ups