Posted on Leave a comment

jQuery Lights out Plugin

jQuery Logo

In current times, saving energy in all its variants is becoming more and more important each day. When it comes to websites one simple way to save energy is to dim the display when idle.

Both Interact has released a simple yet versatile cross-browser jQuery lights out plugin. In order to keep things simple you only need to make sure to include jQuery 1.3 and higher and the plugin itself. It will then do the magic of automatically adding the required DOM elements for the overlays and register some event handlers to track user interactions and idle times.

Feel free to download theย jQuery lights out plugin from Githubย and adjust it to your needs.

Posted on Leave a comment

Handling cookies in Magento with JavaScript

Magento Logo

In order to handle cookies in Magento refer to /js/mage/cookies.js. The functions for getting, settings and clearing cookies are:

  • Mage.Cookies.set
  • Mage.Cookies.get
  • Mage.Cookies.clear

Below you find the corresponding JavaScript functions from cookies.js:

Mage.Cookies.set = function(name, value) {
     var argv = arguments;
     var argc = arguments.length;
     var expires = (argc > 2) ? argv[2] : Mage.Cookies.expires;
     var path = (argc > 3) ? argv[3] : Mage.Cookies.path;
     var domain = (argc > 4) ? argv[4] : Mage.Cookies.domain;
     var secure = (argc > 5) ? argv[5] : Mage.Cookies.secure;
     document.cookie = name + "=" + escape (value) +
       ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) +
       ((path == null) ? "" : ("; path=" + path)) +
       ((domain == null) ? "" : ("; domain=" + domain)) +
       ((secure == true) ? "; secure" : "");
};

Mage.Cookies.get = function(name){
    var arg = name + "=";
    var alen = arg.length;
    var clen = document.cookie.length;
    var i = 0;
    var j = 0;
    while(i < clen){
        j = i + alen;
        if (document.cookie.substring(i, j) == arg)
            return Mage.Cookies.getCookieVal(j);
        i = document.cookie.indexOf(" ", i) + 1;
        if(i == 0)
            break;
    }
    return null;
};

Mage.Cookies.clear = function(name) {
  if(Mage.Cookies.get(name)){
    document.cookie = name + "=" +
    "; expires=Thu, 01-Jan-70 00:00:01 GMT";
  }
};

Generic cookie clear function

In case you are searching for a simple, generic function to clear (Magento) session cookies you might want to use the following snippet ($vhost is the current VHost determined by PHP’s globals, e.g. www.yoursite.com):

function clearCookie(name, domain, path) {
  var domain = domain || document.domain;
  var path = path || "/";
  console.debug(name + "=; expires=" + +new Date + "; domain=" + domain + "; path=" + path);
  document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;domain=" + domain + ";path=" + path;
}

try {
  console.debug('Removing session cookie...');
  clearCookie('frontend', '<!--?php echo $vhost; ?-->', '/');
  console.debug('Removed cookie');
} catch (Error) {
  console.error('Failed to remove cookie');
}
Posted on Leave a comment

Adding advanced formatting to Harshen’s jQuery countdown timer plugin

jQuery Logo

Harshen’s jQuery countdown timer plugin works great and is simple to use. In a recent project we needed to use special formatting for the countdown timer to be implemented. Although, Harshen’s solution offer to timeSeparator option to specify the separator string to be used this was not flexible enough. The customer wanted the countdown timer to display the remainder time in the format:

ddd / ddh / ddm / dds

Although, using the timeSeparator option it is possible to get the separating “/” to work, we needed the days(d), hours(h), minutes(m) and seconds(s) formatted using HTML.

The plugin extension

Having a quick look at the plugin to only thing to do was to overwrite the $this.html() functionality by a custom function that takes care of processing additional formatting rules. In order to keep the formatting as flexible as possible I opted to add regulare expression support through additional options:

  1. regexpMatchFormat
  2. regexpReplaceWith

regexpMatchFormat specifies the format to match the original output string produced by the plugin. regexpReplaceWith then takes care of replacing the original string with the desired regular expression format. Furthermore, an additional function called html was introduced:

/**
 * Replaces content by optional regular expression specified via options 
 * regexpMatchFormat and regexpReplaceWith.
 * @param Object $this
 * @param String content
 */  
function html($this, content) {
  var processedContent = content;

  if (typeof window['regexpMatchFormat_' + $this.attr('id')] !== 'undefined' &&
      typeof window['regexpReplaceWith_' + $this.attr('id')] !== 'undefined') {
    var regexp = new RegExp(window['regexpMatchFormat_' + $this.attr('id')]);
    processedContent = content.replace(regexp,
      window['regexpReplaceWith_' + $this.attr('id')]);
  }

  $this.html(processedContent);
}

Handling of the addtional two options was added in the countdown function:

var regexpMatchFormat = "";
var regexpReplaceWith = "";
if (options.regexpMatchFormat != undefined && options.regexpReplaceWith != undefined) {
  window['regexpMatchFormat_' + $this.attr('id')] = options.regexpMatchFormat;
  window['regexpReplaceWith_' + $this.attr('id')] = options.regexpReplaceWith;
}

Below you find the regular expression used for this project’s requirements:

<script type="text/javascript">// <![CDATA[
jQuery(document).ready(function ($) {
    $('#future_date').countdowntimer({
      dateAndTime: "2015/01/01 00:00:00",
      size: "lg",
      regexpMatchFormat: "([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})",
      regexpReplaceWith: "$1<sup>d</sup> / $2<sup>h</sup> / $3<sup>m</sup> / $4<sup>s</sup>"
     });
    });
// ]]></script>

Thanks again to Harshen for the very nice plugin ๐Ÿ™‚

Posted on Leave a comment

Simple modal HTML dialog overlay

In case you don’t want to deploy full fledged JavaScript libraries, such as jQuery or Dojo, to implement a simple modal HTML dialog overlay here is a quick and easy way to do so based on plain HTML, CSS and JavaScript. It works on all modern browsers.

First, let’s have a look at the CSS code:

#DialogOverlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 99999;
    background: rgba(0, 0, 0, 0.5);
    display: none;
}
#DialogOverlayContent {
    position: absolute;
    top: 40%;
    left: 15%;
    color: #000;
    text-align: center;
    width: 70%;
    height: 200px;
    z-index: 999999;
    background: rgba(255, 255, 255, 1);
    border: 2px solid;
    border-radius: 25px;
}
#DialogOverlayContent > p {
    color: #000;
    margin-top: 50px;
}

And the corresponding JavaScript code:

function showFormDialog() {
    // using plain JavaScript
    document.getElementById('DialogOverlay').style.display = 'block';

    // using jQuery
    // $('#DialogOverlay').css('display', 'block');
}
function closeDialog() {
    // using plain JavaScript
    document.getElementById("DialogOverlay").style.display = 'none';

    // using jQuery
    // $("#DialogOverlay").css('display', 'none');
}

And finally the HTML code:

<div id="DialogOverlay">
  <div id="DialogOverlayContent">
    <p><img src="images/loading.gif" alt="" width="30" height="30" style="margin-right: 20px;"/>
    Please stand by while we process your request...<br/><br/>
    Please do not hit refresh, you will be redirected shortly!<br/><br/>
    <a href="#" onclick="closeDialog();">Close</a></p>
  </div>
</div>

A complete example can be found here:

<html>
<head>
<title>Simple modal HTML dialog overlay</title>
<script>
function showFormDialog() {
    // using plain JavaScript
    document.getElementById('DialogOverlay').style.display = 'block';

    // using jQuery
    // $('#DialogOverlay').css('display', 'block');
}
function closeDialog() {
    // using plain JavaScript
    document.getElementById("DialogOverlay").style.display = 'none';

    // using jQuery
    // $("#DialogOverlay").css('display', 'none');
}
</script>
<style>
#DialogOverlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 99999;
    background: rgba(0, 0, 0, 0.5);
    display: none;
}
#DialogOverlayContent {
    position: absolute;
    top: 40%;
    left: 15%;
    color: #000;
    text-align: center;
    width: 70%;
    height: 200px;
    z-index: 999999;
    background: rgba(255, 255, 255, 1);
    border: 2px solid;
    border-radius: 25px;
}
#DialogOverlayContent > p {
    color: #000;
    margin-top: 50px;
}
</style>
</head>
<body>

<div id="DialogOverlay">
  <div id="DialogOverlayContent">
    <p><img src="images/loading.gif" alt="" width="30" height="30" style="margin-right: 20px;"/>
    Please stand by while we process your request...<br/><br/>
    Please do not hit refresh, you will be redirected shortly!<br/><br/>
    <a href="#" onclick="closeDialog();">Close</a></p>
  </div>
</div>

<a href="#" onclick="showFormDialog();">Open dialog</a>
</body>
</html>

That’s it, pretty simple but effective ๐Ÿ™‚

Posted on Leave a comment

Custom build script for GIT based projects

Git Logo

When managing smaller GIT based projects I find it helpful to opt for custom build scripts rather than having to deal with the overhead of setting up proper Jenkins (or-likewise) runtime environments.

In order to deal with this need I’ve created a simple build script that creates a compressed TAR file based on committed files.

Furthermore, since I use version numbers for e.g. JavaScript builds it’s always nice to have automatic file inclusion/exlusion based on this number, say, read from a config file.

In this particular example I want to read the version number from a variable called MY_VERSION in file config/base.php and include a special JavaScript build-folder in the target compressed TAR file. In addition, I only want to include files in the src-folder, as well as manually include other folders.

So, here it is:

#!/bin/sh
#
# REQUIREMENTS:
# - git
# - php
# - sed
# - xargs
# - tar
#

#(absolute) path to PHP, or simply 'php' if it is in the PATH
PHP_PATH="php"

#release number should be read from config/base.php
PHP_REQUIRE="require('$(pwd)/config/base.php');"
RELEASE_NUMBER=`$PHP_PATH -r "$PHP_REQUIRE echo MY_VERSION;"`

#hold list of files to be added to release tar.gz
TMP_SRC_FILE_LIST=$(pwd)/TMP_RELEASE_INCLUDE

#get list of git's tracked files
git ls-files > $TMP_SRC_FILE_LIST

#filter only SRC directory
sed -i '/^src./!d' $TMP_SRC_FILE_LIST

#manually include additional folders of your choice
sed -i '/^src\/js\/folder1/d' $TMP_SRC_FILE_LIST
sed -i '/^src\/js\/folder2/d' $TMP_SRC_FILE_LIST

#add RELEASE directory only
`echo "src/js/release/$RELEASE_NUMBER" >> $TMP_SRC_FILE_LIST`

# enclose lines in "" to enable spaces in file and folder names
sed -i 's/^/"/g' $TMP_SRC_FILE_LIST
sed -i 's/$/"/g' $TMP_SRC_FILE_LIST

#create compresse TAR
cat $TMP_SRC_FILE_LIST | xargs tar czf release_$RELEASE_NUMBER.tar.gz

#clean up
rm $TMP_SRC_FILE_LIST

That’s it – Feel free to adjust it to your needs.

Posted on Leave a comment

VideoJS Zeige Standbild Nach Abspielen von VideosVideoJS Show Poster Image after video stopped

By default, the video.js simply shows the last frame of the video once the end has been reached. Sometimes, it comes in handy to show the poster image again once the video has stopped. Luckily, this behavior can be easily achieved:

videojs('yourVideoContainer').ready(function() {
  var myPlayer = this;       

  myPlayer.on('ended', function() {
    myPlayer.posterImage.show(); 
  });
});

For the sake of completeness here is the HTML for the video container:

<video id="yourVideoContainer" class="video-js vjs-default-skin"  
  controls preload="auto" width="1098" height="515"
  poster="/img/video-poster.png" data-setup='{"example_option":true}'>
 <source src="/video/sample.mp4" type='video/mp4' />
 <source src="/video/sample.webm" type='video/webm' />
 <source src="/video/sample.ogv" type='video/ogg' />
</video>

Posted on Leave a comment

Update button text in JQuery Mobile

jQuery Logo

In case you wondered how it is possible to update the text of a <button> element created by markup in jQuery mobile (i.e. not a button generated using <a data-type=”button”>) you need to set the text and then call refresh on the node:

$('#someButton').text("Updated text");
$("#someButton").button("refresh");

refresh() actually causes the node to be reloaded, thus reflecting your changes.

Posted on Leave a comment

Generating optimized JavaScript Source Code using Dojo’s Build System

The Dojo Toolkit represents one of the most powerful and feature-rich JavaScript libraries to-date. Apart from its core functionality such as DOM manipulation (i.e. Dojo namespace) it provides developers with a vast range of widgets (Dijits, i.e. Dojo Widgets), lots of incubator code (DojoX) and numerous Utils classes. (More info can be found here: E-Learning Standards โ€“ Critical and Practical Perspectives.)

When writing more complex client side applications you will soon realize that the overall loading time increases by a factor that significantly reduces the usability and responsiveness. Thus, it would be nice to have a build script that compresses relevant JavaScript source files into optimized code that you then can include in your frontend HTML files. Additionally, you will most definitely want to be able to create different releases of your code in a simple yet consistent way. That’s were Dojo’s build system comes in handy!

Dojo Build Layer System

Before explaining the bits and pieces needed for this build script you need to understand Dojo’s build layer system. Each layer represents a list of files that should be put together to produce a compressed and optimized version, much like a C include header file. Below you find an examplary layer file for a Login module:

dojo.provide("layerLogin.js");

dojo.require("dojo.i18n");
dojo.require("custom.Login");

Line 1 declares the layer file and must match the actual file name. Following the first line are all files included in this layer. For instance, dojo.i18n represents Dojo’s internationalization (i18n) functionality and is required by this layer. Furthermore, custom.Login on Line 3 represents a file named Login.js that resides in the custom namespace and contains the Login module’s core code:

/js/custom/Login.js

The source of Login.js:

dojo.require('dijit.form.Form');
dojo.require('dijit.form.Button');
dojo.require('dijit.form.TextBox');

dojo.provide('custom.Login');
dojo.declare('custom.Login', null, {

    /**
     * Default constructor
     */
    constructor: function() {
        this.init();
    },

    /**
     * Initializes Login module.
     */
    init : function() {
        dijit.byId('loginUser').focus();
    }
});

As you can see Login represents a Dojo “class”. Although you can use plain JavaScript code in any of the included layer files Dojo classes provide you with the power of encapsulating module specific code (as you are used to when writing object oriented code). You can find more information on Dojo’s classes here: Classy JavaScript with dojo.declare

Build Layer Profile

As you might have guessed correctly we could have multiple layer files in our Dojo based application. That’s why it is good to think of layer files as modules. Consequently, the next step would be to combine all modules into a configuration profile that Dojo then can use to compress into one optimized JavaScript file. Let’s have a look at an example profile file:

dependencies = {
    layers: [
    {
        // one of the stock layers. It builds a "roll up" for
        // dijit.dijit which includes most of the infrastructure needed to
        // build widgets in a single file. We explicitly ignore the string
        // stuff via the previous exclude layer.
        name: "../dijit/dijit.js",
        // what the module's name will be, i.e., what gets generated
        // for dojo.provide(<name here>);
        resourceName: "dijit.dijit",
        // modules *not* to include code for
        layerDependencies: ["string.discard"],
        // modules to use as the "source" for this layer
        dependencies: ["dijit.dijit"]
    },
    {
        name: "../custom/layerLogin.js",
        dependencies: ["custom.layerLogin"],
        copyrightFile: "../../../../COPYRIGHT"
    },
    {
        name: "../custom/layerMain.js",
        dependencies: ["custom.layerMain"],
        copyrightFile: "../../../../COPYRIGHT"
    }],
    prefixes: [
    ["dijit", "../dijit"],
    ["dojox", "../dojox"],
    // include COPYRIGHT
    ["custom", "../custom", "../../../../COPYRIGHT"]
    ]
}

The dependencies variable at the beginning is a JSON object holding all required layers of this profile. Additionally, it defines the core files (stock layers) needed to run Dojo afterwards.

The Build Script

Now that you have an overview of the structure of a Dojo build profile let’s have a look at the actual build script. Below you find a bash script that incorporates all required steps for generating optimized JavaScript source code based on a custom build profile using Dojo’s build layer:

#!/bin/sh
#
# Script for deploying the "release" version of the currently set JS layers via the profile file.
# It will create (or overwrite) the release folder in the JS_LIB/custom/ directory,
# i.e. JS_LIB/custom/release/RELEASE_VERSION
#
# @author Matthias Kerstner <matthias@kerstner.at>
#
 
#profile file should reside inside current directory
PROFILE_FILE=custom.profile.js
 
CWD="$(cygpath -aw $(pwd))"
#UNIX: $(pwd)
 
#(absolute) path to PHP, or simply 'php' if it is in the PATH
PHP_PATH="/cygdrive/c/xampp/php/php.exe"
#UNIX: "/opt/lampp/bin/php"
 
#release number should be read from config/base.php
PHP_REQUIRE="require('$(cygpath -aw $(pwd)/../src/config/base.php)')"
#UNIX: "require('$(pwd)/../src/config/base.php');"
 
#get release version from config file
RELEASE_VERSION=`$PHP_PATH -r "$PHP_REQUIRE; echo MY_VERSION;"`
 
#determine release path
RELEASE_PATH="$(cygpath -aw $(pwd)/../src/web/js/release/)"
#UNIX: $(pwd)/../src/web/js/release/
 
# remove any previous releases
if [ -d $RELEASE_PATH ]; then
  echo "removing existing releases..."
  rm -r $RELEASE_PATH
fi
 
# create release directory again
mkdir $RELEASE_PATH
 
# path to dojo buildscript
DOJO_BUILDSCRIPT_PATH=$(pwd)/../src/web/js/util/buildscripts/
 
echo switching to buildscript path $DOJO_BUILDSCRIPT_PATH
 
#change to buildscripts folder as required by dojo's build.sh
cd $DOJO_BUILDSCRIPT_PATH
 
#call dojo's build script with profile specified above
#UNIX: build.sh
#WINDOWS: build.bat
exec ./build.bat profileFile=../../profile/"$PROFILE_FILE" \
action=release cssOptimize=comments optimize=shrinkSafe releaseName=$RELEASE_VERSION
 
#change to lib/js folder
cd $(cygpath -aw $(pwd)/../../)
#UNIX: $(pwd)/../../

This script basically does the following:

  1. Defines which profile file to use (line 11)
  2. Determines the current working directory (line 13)
  3. Sets path to PHP executable to read release version from base.php (line 17, 21 and 25)
  4. Sets release path based on release version (line 28)
  5. Removes any previous releases and creates release folder (line 32)
  6. Sets path to the build script (line 41)
  7. Executes build script from within its folder (line 51)
  8. Changes back to lib/js folder (line 55)

In order for this script to run your project needs to have a certain folder structure. I have created a reference setup which you can download from GitHub: Dojo Build Script.

Note: The script should be executed from within the scripts folder. Don’t panic if the scripts runs for a while, there are plenty of files that need to be processed during the building process. After all, you get a highly compressed layer file afterwards, right?

Feel free to customize the script to your needs ๐Ÿ™‚

Posted on 2 Comments

Draggable Pin Marker for Google Maps API V3

Google Logo

Google’s Maps API offer a vast range of functionality to interact with underlying maps. As opposed to statically setting markers (pins) programmatically sometimes you might want your users to be able to interact with the map by dragging existing markers around the map.

Google Maps API V3

Fortunately, Google’s JavaScript API offers this functionality out of the box. Below you’ll find an example based on Google Maps API V3. Basically, what we want to achieve is to be automatically notified when a user changes a marker’s position. Clearly, this can be done by registering a listener on the marker which will fire an event once the marker has been dropped on the destination coordinates. After all, we want to be given these coordinates in order to carry out further actions. But first of all we need to create a new map instance and bind it to a DOM container element, as explained in the official reference documentation:

var latLng = new google.maps.LatLng(lat,lng);

var options = {
  zoom: 13,
  center: latLng,
  scrollwheel: false,
  disableDoubleClickZoom: true,
  mapTypeId: google.maps.MapTypeId.ROADMAP,
  locale: LANG
}

var map = new google.maps.Map(document.getElementById(canvasDomId), options);

Once we have the map instance we are able to add markers, as shown in the following code snippet:

var marker = new google.maps.Marker({
  position: latLng, 
  map: map, 
  title: title,
  draggable: true
});

In order for the marker to be draggable across the map we need to set the attribute draggable to true. Finally, in order to be notified of changes of the marker’s position we need to add an event listener to the marker:

google.maps.event.addListener(marker, 'drag', function(event) {
  console.debug('new position is '+event.latLng.lat()+' / '+event.latLng.lng()); 
});

google.maps.event.addListener(marker, 'dragend', function(event) {
  console.debug('final position is '+event.latLng.lat()+' / '+event.latLng.lng()); 
});

Whereas the event drag is fired whenever the user drags the marker and slides it across the map, the dragend is triggered only when the marker is dropped.

Working example


<script src="https://maps.googleapis.com/maps/api/js?sensor=true"></script>
<script>

var iconBase = 'http://base-url-to-your-icon';

function initialize() {
var map_canvas = document.getElementById('map_canvas');
var map_options = {
center: new google.maps.LatLng(TODO_LAT, TODO_LNG),
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(map_canvas, map_options);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(TODO_LAT, TODO_LNG),
map: map,
icon: iconBase + 'TODO_img.png'
});

var features = [{
position: new google.maps.LatLng(TODO_LAT, TODO_LNG),
type: 'info'
}];

map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(legend);

google.maps.event.addListener(marker, 'drag', function(event) {
console.debug('new position is '+event.latLng.lat()+' / '+event.latLng.lng());
});

google.maps.event.addListener(marker, 'dragend', function(event) {
console.debug('final position is '+event.latLng.lat()+' / '+event.latLng.lng());
});
}

google.maps.event.addDomListener(window, 'load', initialize);

</script>

<div id="map_canvas" style="width: 500px;height: 400px;"></div>

Posted on Leave a comment

jQuery Multi File Upload

jQuery Logo

A couple of days ago I accidently discovered https://blueimp.net/‘s jQuery File Upload.

Update
Finally I found some time to post back on jQuery File Upload. As of this writing I have successfully integrated blueimp’s jQuery multi file uploader plugin into a Zend-based web application. The plugin has proven to be quite valuable as it provides a bunch of out of the box functionality, such as handling chunked uploads using a simple PHP script. Of course this script only serves as a starting point for more serious projects, but still it is quite helpful.

The API and the corresponding documentation for the plugin is available via the project’s homepage (https://github.com/blueimp/jQuery-File-Upload/wiki). They are both very well written and easy to understand. Furthermore, in case you are interested in the code, the inline documentation is also pretty exhaustive. Details on the file upload can be managed on both sides of the application, i.e. using the JavaScript code during instantiation of the plugin and on the server side when processing upload requests.

Styling of the plugin can be extended pretty easy too. The author has provided template stylesheets that can be overwritten and extended. One of the core aspects of this plugin is the templating plugin used to display uploaded files. The JSON used to update these templates can be altered on the server side, thus making it possible to add further functionality to the UI, such as adding checkboxes to select certain files. The event hooks provided by the UI part of the plugin allow to modify the uploader’s behavior even more.

All in all, I am glad I stumbled across the well written and documented jQuery plugin, available from the project’s homepage: http://aquantum-demo.appspot.com/file-upload.

Posted on Leave a comment

html is null” error using set(‘value’) for dijit.Editor

Be aware of the fact the using editorDijit.set('value', null) will result in an error (“html is null”) rather than setting an empty value.

I’ve experienced this behavior when trying to update a dijit.Editor using dijit.form.Form generated data. It seems like only an empty string can be set for an empty value and not null. You might want to keep that in mind when retrieving data from a database that by default uses NULL-values.

Posted on 1 Comment

Scrollbar in dijit.layout.ContentPane aktivierenActivate scrollbar in dijit.layout.ContentPane

It seems that if dijit.layout.ContentPanes are nested inside other containers, such as dijit.layout.BorderContainer they do not automatically display the scrollbar when content overflows their visible area.

In order to force a scrollbar simply specifiy the CSS directive overflow:auto, e.g.

<div dojoType="dijit.layout.ContentPane" style="height:300px;overflow:auto;">

Posted on Leave a comment

dojo.dnd Elemente programmatisch zwischen Containern verschiebenProgrammatically move dojo.dnd items between containers

In order to programmatically move dojo.dnd items (dojo.dnd.Item) between containers (dojo.dnd.Container) you only need to insert existing nodes from the source container into the target container, delete any moved nodes from the source container and finally sync() both containers to update the underlying metadata.

The following code snippet should clarify this principle. It demonstrates that items are only moved from the source container if their value does not match an expected value:

//only moving items if expected value is not met
if (srcContainer.getItem(node.id).data != expectedValue) {                    
  targetContainer.insertNodes(false, [dojo.byId(node.id)]);
  targetContainer.sync();

  srcContainer.delItem(node.id);
  srcContainer.sync(); //sync nodes and metadata
}

Hint: dojo.dnd underlying principle is a separation between data and nodes. So whenever you alter one part of an dndItem (data or node) be sure to synchronize its state by calling sync(). See the official reference guide for more information: dojo.dnd package