Polymer 1.0 styling not working - css

I want to create category list with sub category. The sub category will open when user clicks on the parent category. This is like a multi level menu tree.
The functionality works fine, but the style for the child nodes is not applying. The reason is that I create the sub menu dynamically and I cannot set the style rules.
Here is my code:
<template>
<div id="cat_menu">
<!--<category-service id="service" categories="{{categories}}"></category-service>-->
<iron-ajax id="ajax"
auto
url="../api/index.php"
method="POST"
last-response="{{categories}}"
params='{"tag":"get_cat_list"}'
handleAs="json">
</iron-ajax>
<template is="dom-repeat" items="{{categories.cat_list}}" filter="getParent" id="t">
<paper-fab mini id="fab_{{item.category_id}}" icon="edit" class="p_fab"></paper-fab>
<paper-menu id="{{item.category_id}}" class="cat_item" on-click="selectAction">
<span >{{item.category_name}}</span>
</paper-menu>
</template>
<div>
</template>
selectAction: function (e, detail) {
var str = '';
if (detail) {
var selectedItem = e.currentTarget;
//Polymer.dom(selectedItem).childNodes[1].innerHTML = '';
for (var i = 0; i < this.categories.cat_list.length; i++) {
//var item = new Object;
var item = this.categories.cat_list[i];
if (selectedItem.id == item.parent_id) {
var container = document.createDocumentFragment();
var paper_submenu = document.createElement('paper-menu');
paper_submenu.id = item.category_id;
paper_submenu.innerText = item.category_name;
paper_submenu.className = 'cat_item';
//paper_submenu.classList.add('cat_item');
paper_submenu.onclick = 'selectAction';
Polymer.dom(selectedItem.childNodes[1]).appendChild(paper_submenu);
Polymer.updateStyles();
}
}
}
}
CSS Style:
.cat_item {
border: 1px solid #acdcd8;
margin: 5px;
background-color: rgb(255, 255, 255);
padding-left: 10px;
}
The element cannot see this class cat-item. Can someone please help me solve this?

Related

How can I make sematic-ui-react Tab responsive?

I'm developing a react application and I recently start to use semantic ui react module.
Unfortunately I'm not able to make the Tab object responsive...
A really simple script to show this is:
import React from 'react'
import { withRouter } from 'react-router-dom'
import {Tab} from 'semantic-ui-react';
// import NavSection from './NavSection'
var sections = ["SectionA","SectionB","SectionC","SectionD","SectionE","SectionF"]
const NavigatorHeader = () => (
<div>
<h1>Navigator</h1>
<div>
<Tab menu={{ pointing: true }} panes={getPanes(sections)} />
</div>
</div>
)
export default withRouter(NavigatorHeader)
function getPanes(sections){
return sections.map( function(section){
return {
menuItem: section,
render: () =>
<Tab.Pane attacched="false">
<div>
<p>
Some Text that we can change tab from tab. E.g. with the title: <b>{section}</b>
</p>
</div>
</Tab.Pane>
}
})
}
The tabs look great, inline, but if I reduce the screen they just overflow, while I was expecting they would have moved to a second line.
Look like that this is coming from the Selenium-ui css I'm using (https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css). Current version is 2.3.1 but if I go back to use a version before 2.0.0, it was responsive.. is there a way to obtain the same behavior with the new version?
Thanks,
Michele.
Thanks,
Michele.
Based on the previous answer I found an easier way to achieve this.
I defined a CSS with the values suggested:
.wrapped{
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
and then just passed that additional class to the menu
<Tab menu={{ pointing: true, className: "wrapped" }} panes={getPanes(sections)} />
That solved the problem without any additional javascript.
Here is a solution that I created some time ago in regular Semantic. It behaves like Bootstrap and does not require a second set of menu items. It requires just a tiny bit of JS and CSS.
The JS:
$(function() {
// Set up to handle wrapping of tab menu (tab actuator) items
$(window).resize(function() {
checkIfWrapped();
});
checkIfWrapped(); // Make sure the function is fired upon document ready
});
// Detect whether a Semantic UI tabular menu is wrapped
function checkIfWrapped() {
var pos_top_1st = $('.tabular.menu .item').first().position().top;
$('.tabular.menu .item:not(first-child)').each(function() {
var pos_top = $(this).position().top;
if (pos_top > pos_top_1st) {
$(this).parent().addClass('wrapped');
return;
} else if (pos_top == pos_top_1st) {
$(this).parent().removeClass('wrapped');
}
});
The HTML structure. (Note that placing the .tabular.menu .item-s inside a div within the overall .tabular.menu allows the use of a separate .right.menu within the .tabular.menu if desired) :
<div id="tabs-menu" class="ui top attached tabular menu">
<div id="qj-tabs">
<div class="tab item"></div>
<div class="tab item"></div>
<div class="tab item"></div>
</div>
<div class="right menu">
<a class="tab item"><i class="add icon"></i> Add Job</a>
<a class="tab item"><i class="copy icon"></i> Copy Item</a>
</div>
</div>
<div class="botttom attached tab segment"></div>
<div class="botttom attached tab segment"></div>
</div>
The CSS:
#qj-tabs {
display: flex !important; /* Will not work unless defined as display: flex */
flex-direction: row !important;
flex-wrap: wrap !important;
}
#tabs-menu .wrapped .item {
border-radius: 5px !important;
border: 1px lightgray solid !important; /* Just styling for the default theme here */
margin: 0 2px 2px 0 !important;
}
#tabs-menu .wrapped .active.item {
background-color: lightgray;
}
This is what i did some weeks ago in regular Semanitic-ui.
! function($) {
var WinReszier = (function() {
var registered = [];
var inited = false;
var timer;
var resize = function(ev) {
clearTimeout(timer);
timer = setTimeout(notify, 100);
};
var notify = function() {
for (var i = 0, cnt = registered.length; i < cnt; i++) {
registered[i].apply();
}
};
return {
register: function(fn) {
registered.push(fn);
if (inited === false) {
$(window).bind('resize', resize);
inited = true;
}
},
unregister: function(fn) {
for (var i = 0, cnt = registered.length; i < cnt; i++) {
if (registered[i] == fn) {
delete registered[i];
break;
}
}
}
};
}());
var TabDrop = function(element, options) {
this.element = $(element);
var $this = this;
this.dropdown = $('<div class="ui item right dropdown" data-popup data-content="' + options.text + '" data-position="bottom center">' +
options.icon +
'<div class="menu"></div>' +
'</div>').appendTo($this.element);
this.click = function() {
$this.element.removeClass("pointing");
$this.element.find("a.item").not(this).removeClass("active");
};
this.reverseclick = function(el) {
$this.element.find(".item.right.dropdown .menu a.item").removeClass("active selected");
$this.element.addClass("pointing");
};
WinReszier.register($.proxy(this.layout, this));
this.layout();
$(".ui.dropdown").dropdown();
$("[data-popup]").popup();
};
TabDrop.prototype = {
constructor: TabDrop,
layout: function() {
var $main = this;
var $this = this.element;
var $drpdwn = this.dropdown;
var $fullwidth = $this.width() - 25;
this.element
.append($drpdwn.find('.ui.item.right'))
.find('a.item')
.not('.item.right.dropdown')
.each(function() {
var $blockLenght = parseInt($(this).width());
var $space = $fullwidth - $blockLenght;
if ($space > $blockLenght) {
$(this).click($main.reverseclick)
if ($drpdwn.find('.menu a').length > 0) {
var $reverse = $drpdwn.find('.menu a:first-child');
$reverse.click($main.reverseclick).removeClass("selected")
$reverse.insertBefore($drpdwn);
}
} else {
var $dropItem = $(this)
$dropItem.click($main.click)
$drpdwn.find('.menu').append($dropItem);
}
$fullwidth = $space;
});
}
};
$.fn.tabdrop = function(option) {
return this.each(function() {
var $this = $(this),
data = $this.data('tabdrop'),
options = typeof option === 'object' && option;
if (!data) {
$this.data('tabdrop', (data = new TabDrop(this, $.extend({},
$.fn.tabdrop.defaults, options))));
}
if (typeof option == 'string') {
data[option]();
}
});
};
$.fn.tabdrop.defaults = {
text: 'More',
icon: '<i class="icon align justify m-0"></i>'
};
$.fn.tabdrop.Constructor = TabDrop;
}(window.jQuery);
var Tabs = {
tabDrop: function() {
setTimeout(function() {
$('.tabdrop').tabdrop({
text: 'More Configuration'
});
}, 1000)
}
};
$(document).on("ready", function() {
$('.menu .item').tab();
Tabs.tabDrop();
$(window).resize(function() {
Tabs.tabDrop();
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.3/semantic.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.3/semantic.min.js"></script>
<div class="ui top attached pointing menu tabdrop">
<a class="item" data-tab="tab1">Tab Item 1</a>
<a class="item" data-tab="tab2">Tab Item 2</a>
<a class="item" data-tab="tab3">Tab Item 3</a>
<a class="item" data-tab="tab4">Tab Item 4</a>
<a class="item" data-tab="tab5">Tab Item (A very long tab title)</a>
</div>

asp.net with bootstrap. table-responsive scrolling is broken in panel-body

I have a webpage with the following HTML:
<div class="panel panel-primary" style="width:auto;height:auto;">
<div class="panel-heading" id="ContentHeader" runat="server" style="width:auto;height:auto;">Table</div>
<div class="panel-body" runat="server" style="width:auto;height:auto;">
<div class="table-responsive">
<asp:GridView ID="ExcelContentView" runat="server" class="table table-bordered" >
<HeaderStyle CssClass="info" />
</asp:GridView>
</div>
</div>
</div>
i reference this pages answer.
it works fine only with overflow-x.
however, scroll bar is broken when overflow-x with overflow-y case.
About 53 rows and 15 columns:
vertical scrollbar is not working.
but Left Or Right Key is move scrollbar.
clicking scrollbar is broken i think.
how do i fix scroll bar in overflow x and y case?
here is additional c# code behind
on page load :
{
ExcelContentView.DataSource = ExcelViewManager.Instance.GetExcelViewTable(fileName, historyNum);
ExcelContentView.DataBind();
} // method
and GetExcelViewTable Method
{
DataTable stringTable = new DataTable();
var currType = GameDataFileManager.Instance.GetTypeFromFileName(fileName);
string historyPath = GameDataFileManager.Instance.GetHistoryPathByType(currType);
string fullPath = historyPath + fileName + revNum + ".xlsx";
FileInfo excelFileInfo = new FileInfo(fullPath);
ExcelPackage excel = new ExcelPackage(excelFileInfo);
var workSheet1 = excel.Workbook.Worksheets.First();
int colCount = 0;
//
for (int iCol = 1; iCol <= workSheet1.Dimension.End.Column; ++iCol )
{
stringTable.Columns.Add( workSheet1.Cells[1, iCol].Text, typeof(string) );
++colCount;
} // for
for (int iRow = 3; iRow <= workSheet1.Dimension.End.Row; ++iRow )
{
List<object> objList = new List<object>();
for (int iCol = 1; iCol <= workSheet1.Dimension.End.Column; ++iCol )
{
objList.Add( workSheet1.Cells[iRow, iCol].Text );
} // for
int objCount = objList.Count;
if (colCount != objCount)
{
DotNetMsgBox.Show("Debug");
}
stringTable.Rows.Add(objList.ToArray());
} // for
return stringTable;
}
I solved this.
table-responsive is broken scrollbar when using with simple sidebar
responsive broken when this code.
<li class="sidebar-footer">Made by Me</li>
so, this sidebar-footer code makes problem.
i dont know why this code broken table-responisve sidebar.
i open simple-sidbar.css, and see this codes
.sidebar-nav > .sidebar-footer {
display: block;
text-decoration: none;
color: #fff;
position: fixed;
height: 100px;
bottom: 0;
width: 100%;
}
and i delete code in { }, but still has problem.
so, i delete sidebar-footer in my Master Page. and yes. i solved problem.
anyone tell me why this sidebar-footer broken scrollbar.

Set animated html5 canvas as the background without interacting with other elements?

I got the canvas working, I'm having issues trying to position it.
Specifically I want to implement them to the same effect as:
html {
background: url(back.jpg) no-repeat center center fixed;
background-size: cover;
}
for static images. Basically no interaction with other elements, and positioned as low as possible with regards to the stacking context. Additionally, I'd like to have the canvas background as compartmentalized / as segmented as possible from the rest of the code.
By segmented, I mean something like this:
<body>
<div id="backgroundContainer">
<canvas id="myCanvas"></canvas>
</div>
<div id="everythingElseContainer">
....
</div>
<script src="canvasAnimation.js"></script>
</body>
or this:
<body>
<div id="container">
<canvas id="myCanvas"></canvas>
<div id="everythingElse">
....
</div>
</div>
<script src="canvasAnimation.js"></script>
</body>
to minimize the possibility of css conflicts.
var WIDTH;
var HEIGHT;
var canvas;
var con;
var g;
var pxs = new Array();
var rint = 60;
$(document).ready(function(){
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
canvas = document.getElementById('canvas');
$(canvas).attr('width', WIDTH).attr('height',HEIGHT);
con = canvas.getContext('2d');
for(var i = 0; i < 100; i++) {
pxs[i] = new Circle();
pxs[i].reset();
}
setInterval(draw,rint);
});
function draw() {
con.clearRect(0,0,WIDTH,HEIGHT);
for(var i = 0; i < pxs.length; i++) {
pxs[i].fade();
pxs[i].move();
pxs[i].draw();
}
}
function Circle() {
this.s = {ttl:8000, xmax:5, ymax:2, rmax:10, rt:1, xdef:960, ydef:540, xdrift:4, ydrift: 4, random:true, blink:true};
this.reset = function() {
this.x = (this.s.random ? WIDTH*Math.random() : this.s.xdef);
this.y = (this.s.random ? HEIGHT*Math.random() : this.s.ydef);
this.r = ((this.s.rmax-1)*Math.random()) + 1;
this.dx = (Math.random()*this.s.xmax) * (Math.random() < .5 ? -1 : 1);
this.dy = (Math.random()*this.s.ymax) * (Math.random() < .5 ? -1 : 1);
this.hl = (this.s.ttl/rint)*(this.r/this.s.rmax);
this.rt = Math.random()*this.hl;
this.s.rt = Math.random()+1;
this.stop = Math.random()*.2+.4;
this.s.xdrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
this.s.ydrift *= Math.random() * (Math.random() < .5 ? -1 : 1);
}
this.fade = function() {
this.rt += this.s.rt;
}
this.draw = function() {
if(this.s.blink && (this.rt <= 0 || this.rt >= this.hl)) this.s.rt = this.s.rt*-1;
else if(this.rt >= this.hl) this.reset();
var newo = 1-(this.rt/this.hl);
con.beginPath();
con.arc(this.x,this.y,this.r,0,Math.PI*2,true);
con.closePath();
var cr = this.r*newo;
g = con.createRadialGradient(this.x,this.y,0,this.x,this.y,(cr <= 0 ? 1 : cr));
g.addColorStop(0.0, 'rgba(255,255,255,'+newo+')');
g.addColorStop(this.stop, 'rgba(77,101,181,'+(newo*.6)+')');
g.addColorStop(1.0, 'rgba(77,101,181,0)');
con.fillStyle = g;
con.fill();
}
this.move = function() {
this.x += (this.rt/this.hl)*this.dx;
this.y += (this.rt/this.hl)*this.dy;
if(this.x > WIDTH || this.x < 0) this.dx *= -1;
if(this.y > HEIGHT || this.y < 0) this.dy *= -1;
}
this.getX = function() { return this.x; }
this.getY = function() { return this.y; }
}
html, body, div, button, canvas, .containr {
padding: 0;
border: none;
margin: 0;
}
html, body, .containr{
height: 100%;
width: 100%;
background: none;
}
html, body {
font-size: 13px;
text-decoration: none;
font-family: Verdana, Geneva, sans-serif !important;
}
button {
transition: all 0.24s ease;
}
h1 {
font-size: 4rem;
}
button {
font-size: 5.6rem;
}
#pixie {
position:fixed;
z-index: 0;
background: black;
}
.containr>div {
background: blue;
}
.containr {
overflow:hidden;
color: #ffffff;
z-index: 9;
font-size: 256%;
white-space: nowrap;
display: flex;
flex-flow: column nowrap;
justify-content: space-around;
align-items: center;
align-content: center;
}
.btnz {
margin-left: 2.4%;
margin-right: 2.4%;
background: #ffffff;
background: rgba(0, 0, 0, .36);
text-shadow: 1px 1px 3px #000;
padding: 2rem;
}
.btnz:hover {
background: #3cb0fd;
text-shadow: none;
text-decoration: none;
}
/* Outline Out */
.hvr {
display: inline-block;
vertical-align: middle;
-webkit-transform: translateZ(0);
transform: translateZ(0);
box-shadow: 0 0 1px rgba(0, 0, 0, 0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-moz-osx-font-smoothing: grayscale;
position: relative;
}
.hvr:before {
content: '';
position: absolute;
border: #e1e1e1 solid 5px;
top: -4px;
right: -4px;
bottom: -4px;
left: -4px;
-webkit-transition-duration: 0.3s;
transition-duration: 0.3s;
-webkit-transition-property: top, right, bottom, left;
transition-property: top, right, bottom, left;
}
.hvr:hover:before, .hvr:focus:before, .hvr:active:before {
top: -18px;
right: -18px;
bottom: -18px;
left: -18px;
border: #ffffff solid 8px;
}
<!doctype html>
<html lang="en">
<head datetime="2015-10-31">
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="containr">
<canvas id="canvas"></canvas>
<div>
<h1>Main Title</h1>
</div>
<div>
<button class="btnz hvr">
Button Butt
</button>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="js.js"></script>
</body>
</html>
To move objects down in the visual order use the CSS styling z-index smaller numbers move the element down under other elements, higher numbers bring it up.See MDN z-index for more info.
To set the background of an element to a canvas use
element.style.background= "url(" + canvas.toDataURL() + ")";
To isolate of compartmentalize some code the easiest way is to wrap it in a anonymous function and call it. Everything inside it is isolated. Use 'use strict' directive to ensure you do not accidentally create global scoped variables.
A normal anonymous function does nothing and can not be used.
function(){ console.log(42); }; // does nothing
But if you wrap it in () and then add the function call tokens to the end ( ) you can call it like any function.
(function(){ console.log(42); })(); // send the meaning of life,
// the universe, and everything
// to the console.
The function below wraps up a and nothing can get access to a outside the anonymous function.
(function(){
var a = 1;
})();
But you can easily forget to put var in front of a variable making the variable visible to the entire page.
(function(){
var a = 1;
outThere = 2; // Oh no this is has been placed in
// global scope because it is missing
// the var token.
})();
To stop this use the 'use strict' directive.
(function(){
"use strict"; // this must be the very first line of the function
var a = 1;
outThere = 2; // this will cause the javascript to throw a
// ReferenceError: outThere is not defined
})();
It throws an error and stop the function from running but at least you will know that you have a leak.
Everything inside the anonymous function will manage itself. Deleting itself when not needed any more. Or remaining in memory if the Javascript engine holds an internal reference.
The next function starts up and calls its own function doSomething then exits and is deleted completely including the big array.
(function(){
var bigArray = new Array(100000000);
function doSomething(){
console.log("Whats up?");
}
doSomething();
})();
The next one will create a big array and hold that array in memory for 10 seconds (lifeTime). This is because the setTimeout has given the javascript engine an internal reference to doSomething. As long as that reference exists the bigArray will remain (because of closure). After the timeout the reference his no longer need and thus disposed causing all associated referances to go as well and thus disappear. All done via the magic of garbage collection.
Info on Clouser
Info on Garbage collection MDN is out of date but I am sure a quick search on StackOverflow will help.
(function(){
var bigArray = new Array(100000000);
function doSomething(){
console.log("Big Array has had its time.");
}
setTimeout(doSomething,10000);
})();
Attaching an object to items outside the anonymous function scope will expose data in that object to the global scope.
The next function adds a property to a DOM element. This is visible to the global scope and also means that the lifetime of the function will be as long as that element exists.
(function(){
function Info(){
... create info ..
}
var element = document.getElementById("thisOutsideWorld");
var importantPrivateInfo = new Info();
element.keepThis = importantPrivateInfo;
})();
But this does not apply to primitive types as they are copied not referenced. These are Numbers, Strings, Booleans , Undefined, Null...
So to set the background to a canvas via a compartmentalized function see the following function
(function(){
'use strict';
var myCanvas = document.createElement("canvas");
myCanvas .width = 1024;
myCanvas .height =1024;
var ctx = canvas.getContext("2d");
// toDo
// draw the stuff you want.
var el = document.getElementById("myElement");
if(el !== null){
el.style.background = "url("+canvas.toDataURL()+")";
}
// all done
})(); // once run it will delete the canvas and ctx and leave only the copied dataURL
You may think that this exposes the canvas. But it is safe as the canvas is converted to a string and strings are copied not referenced.
If you need to keep the canvas for some period then use a timer to create an internal reference to the anonymous function
The following function will create a canvas and update it every second for 100 seconds. After that it will be deleted and completely gone.
(function(){
'use strict';
var myCanvas = document.createElement("canvas");
myCanvas .width = 1024;
myCanvas .height =1024;
var lifeCounter = 0;
var ctx = canvas.getContext("2d");
// toDo
// draw the stuff you want.
var el = document.getElementById("myElement");
function update(){
// draw stuff on the canvas
if(el !== null){
el.style.background = "url("+canvas.toDataURL()+")";
}
lifeCounter += 1;
if(lifeCounter < 100){
setTimeout(update,1000);
}
}
update(); //start the updates
// all done
})();
Hope this helps.

How can i position a dropdown at cursor position inside a textarea?

How can i position my dropdown at cursor position inside a textarea? I have found this question was already asked here many times but i cant able figure out the correct solution ..
this is the JSBIN
please help me with your suggestions
Thanks in advance
I know it isn't an exact answer on the question (this solution doesn't use a textarea, but a contentEditable div), but I don't think there is any way of getting x-y-coordinates using either the event, an attribute or function on the textarea or an attribute or function on the Selection object.
I have meshed up an example on JSBin. Please note that I haven't bothered testing for compatibility in other browsers and that it won't return the caret to where you left off. I can't figure out the code for that. I believe window.getSelection() will not work in IE, and in IE8- it would be completely different. You probably want to make sure too, that the menu will not be displayed right from the edge of the screen.
The HTML
<div id="target" contentEditable="true">Type # to see the dropdown.... </div>
<div class="dropdown">
<ul id="dropdown" class="dropdown-menu hide" role="menu" aria-labelledby="dropdownMenu">
<li><a>One</a> </li>
<li><a>Two</a></li>
<li><a>Three</a></li>
<li><a>Four</a> </li>
</ul>
</div>
The CSS
#target {
height: 100px;
border: 1px solid black;
margin-top: 50px;
}
#dummy {
display: inline-block;
}
.dropdown {
position: absolute;
top: 0;
left: 0;
}
The Javascript & JQuery
$("#target").keydown( function(e) {
if(e.which === 50 && e.shiftKey === true ) {
//Prevent this event from actually typing the #
e.preventDefault();
//console.log( window.getSelection() );
var sel = window.getSelection();
var offset = sel.baseOffset;
var node = sel.focusNode.parentNode;
//Get the text before and after the caret
var firsttext = node.innerHTML.substr(0,sel.baseOffset);
var nexttext = (sel.baseOffset != sel.focusNode.length ) ? node.innerHTML.substr( sel.baseOffset, sel.focusNode.length) : "";
//Add in # + dummy, because # is not in there yet on keydown
node.innerHTML = firsttext + '#<div id="dummy"></div>' + nexttext;
//Transfer all relevant data to the dropdown menu
$('.dropdown').css('left', $('#dummy')[0].offsetLeft).css('top', $('#dummy')[0].offsetTop).prop('x-custom-offset', offset + 1);
//Delete the dummy to keep it clean
//This will split the contents into two text nodes, which we don't want
//$('#dummy').remove();
node.innerHTML = firsttext + '#' + nexttext;
//Put the caret back in place where we left off
//...I can't seem to figure out how to correctly set the range correctly...
$('#dropdown').removeClass('hide').addClass('show');
} else {
$('#dropdown').removeClass('show').addClass('hide');
$('.dropdown').removeProp('x-custom-offset');
}
});
$('#dropdown').on( 'click', 'li a', function( e ) {
e.preventDefault();
$('#target').html( function( i, oldtext ) {
var firsttext = oldtext.substr( 0, $('.dropdown').prop('x-custom-offset') );
var nexttext = oldtext.substr( $('.dropdown').prop('x-custom-offset'), oldtext.length );
console.log( e );
var inserttext = e.target.innerText;
//Cleanup
$('#dropdown').removeClass('show').addClass('hide');
return firsttext + inserttext + nexttext;
} );
} );
The explanation
This example works based on that you can insert an element in a contentEditable and retrieve it's offset to the top and the left of the screen. When shift + key 50 is pressed, the event handler will prevent the # from being written and instead inserts the # + dummy object itself. Then we retrieve the offset from this object and move the dropdown menu to that offset. Furthermore, we save the character-offset as a custom property x-custom-offset of the menu, so that we can insert a value at that specific location. We then need to remove the dummy div, but if we would remove the dummy with $('#dummy').remove() the text node before the dummy and the text node behind the dummy will not merge. This will delete the last textnode if we were to put an other # somewhere and/or place it in the wrong location. Therefore, we simply replace the contents of the editable div again. Last, the caret must be set back to it's original position. I cannot figure out how to do this properly though.
The second handler is to insert text into the textbox. The code should be self-explanatory. The x-custom-offset property we set earlier is used here to insert the text into the correct place in the textbox. $('#dropdown').on( 'click', 'li a', function( e ) { ... } ); will attach the click event to the ul instead of the li's, so that it will keep working if you dynamically create the li's (but it will only fire if you click the link part).
You can get the position of the mouse and then move the drop-down list to this position.
You just need to ensure the popup content has a higher z-index than the element you'd like it occlude, and that it's position is set to absolute.
Here's a small test sample I wrote once.
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}
function toggleClass(element, newStr)
{
index=element.className.indexOf(newStr);
if ( index == -1)
element.className += ' '+newStr;
else
{
if (index != 0)
newStr = ' '+newStr;
element.className = element.className.replace(newStr, '');
}
}
function forEachNode(nodeList, func)
{
var i, n = nodeList.length;
for (i=0; i<n; i++)
{
func(nodeList[i], i, nodeList);
}
}
window.addEventListener('load', mInit, false);
function mInit()
{
}
function onShowBtn(e)
{
var element = byId('popup');
element.className = element.className.replace(' hidden', '');
var str = '';//'border-radius: 32px; border: solid 5px;';
e = e||event;
str += "left: " + e.pageX + "px; top:"+e.pageY+"px;"
element.setAttribute('style',str);
}
function onHideBtn()
{
var element = byId('popup');
if (element.className.indexOf(' hidden') == -1)
element.className += ' hidden';
}
</script>
<style>
#controls
{
display: inline-block;
padding: 16px;
border-radius: 6px;
border: solid 1px #555;
background: #AAA;
}
#popup
{
border: solid 1px #777;
border-radius: 4px;
padding: 12px;
background: #DDD;
display: inline-block;
z-index: 2;
position: absolute;
}
#popup.hidden
{
visibility: hidden;
}
</style>
</head>
<body>
<div id='controls'>
<input type='button' value='show' onclick='onShowBtn()'>
<input type='button' value='hide' onclick='onHideBtn()'>
</div>
<br>
<div id='popup'>
<p>This is some assorted
text</p>
<hr>
<ul>
<li>item a</li>
<li>item 2</li>
<li>item iii</li>
</ul>
</div>
</body>
</html>

Moving items in Dual Listboxes

How can I move items from one list box control to another listbox control using JavaScript in ASP.NET?
If you're happy to use jQuery, it's very, very simple.
$('#firstSelect option:selected').appendTo('#secondSelect');
Where #firstSelect is the ID of the select box.
I've included a working example here:
http://jsbin.com/aluzu (to edit: http://jsbin.com/aluzu/edit)
This code assumes that you have an anchor or that will trigger to movement when it is clicked:
document.getElementById('moveTrigger').onclick = function() {
var listTwo = document.getElementById('secondList');
var options = document.getElementById('firstList').getElementsByTagName('option');
while(options.length != 0) {
listTwo.appendChild(options[0]);
}
}
A library-independent solution:
function Move(inputControl)
{
var left = document.getElementById("Left");
var right = document.getElementById("Right");
var from, to;
var bAll = false;
switch (inputControl.value)
{
case '<<':
bAll = true;
// Fall through
case '<':
from = right; to = left;
break;
case '>>':
bAll = true;
// Fall through
case '>':
from = left; to = right;
break;
default:
alert("Check your HTML!");
}
for (var i = from.length - 1; i >= 0; i--)
{
var o = from.options[i];
if (bAll || o.selected)
{
from.remove(i);
try
{
to.add(o, null); // Standard method, fails in IE (6&7 at least)
}
catch (e)
{
to.add(o); // IE only
}
}
}
}
HTML
<select id="Left" multiple="multiple" size="10">
<option>Some</option>
<option>List</option>
<option>Of</option>
<option>Items</option>
<option>To</option>
<option>Move</option>
<option>Around</option>
</select>
<div id="Toolbar">
<input type="button" value=">" onclick="Move(this)"/>
<input type="button" value=">>" onclick="Move(this)"/>
<input type="button" value="<<" onclick="Move(this)"/>
<input type="button" value="<" onclick="Move(this)"/>
</div>
<select id="Right" multiple="multiple" size="10">
</select>
CSS (example)
select { width: 200px; float: left; }
#Toolbar { width: 50px; float: left; text-align: center; padding-top: 30px; }
#Toolbar input { width: 40px; }
Quick test FF3 and IE6 & 7 only.

Resources