Virtual Keyboard in Odoo - javascript

I need to enable Virtual keyboard in Odoo and I made it almost. But the thing is when I click to a particular letter it comes on all the fields like below.
I have to resolve this.The entire code is just below including xml,javascript.
hotel.xml
<?xml version="1.0" encoding="utf-8"?>
<template xml:space="preserve">
<t t-name="HotelRegistrationMenu">
<div class="o_hr_attendance_kiosk_mode_container">
<div class="o_hr_attendance_kiosk_mode">
<h1>Welcome to Hotel California</h1>
<h2>We serve for your happiness</h2>
<button class="o_bi_hotel_button_registration btn btn-primary btn-sm">Book Now</button>
</div>
</div>
</t>
<t t-name="HotelRegistrationKeys">
<div class="o_hr_attendance_kiosk_mode_container">
<form>
<div class="o_form_view">
<table class="o_border" >
<tr>
<td class="col-xs-6 col-xs-offset-2"><label>Customer Name</label></td>
<td width="100"><input class="o_hr_attendance_PINbox" name="customer_name" minlength="1" autofocus="autofocus"/></td>
</tr>
<tr>
<td class="col-xs-6 col-xs-offset-2"><label>Phone Number</label></td>
<td width="100%"><input class="o_hr_attendance_PINbox" name="contact_number" minlength="1"/></td>
</tr>
<tr>
<td class="col-xs-6 col-xs-offset-2"><label>Number Of Persons</label></td>
<td width="100%"><input class="o_hr_attendance_PINbox" name="total_persons" minlength="1"/></td>
</tr>
<tr>
<td class="col-xs-6 col-xs-offset-2"><label>Required Date</label></td>
<td width="100%"><input class="o_hr_attendance_PINbox" name="required_date" minlength="1"/></td>
</tr>
<tr>
<td class="col-xs-6 col-xs-offset-2"><label>Required Time</label></td>
<td width="100%"><input class="o_hr_attendance_PINbox" name="required_time" minlength="1"/></td>
</tr>
</table>
</div>
</form>
<!-- <div class="o_hr_attendance_kiosk_mode"> -->
<div class="row">
<div class="align=center col-sm-8 col-sm-offset-2">
<div class="row" >
<div class="col-xs-4 col-xs-offset-2"></div>
</div>
<div class="row o_hr_attendance_pin_pad">
<t t-foreach="['A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z','1','2',
'3','4','5','6','7','8','9','0','-','OK','Del']" t-as="btn_name">
<div class="col-xs-1 o_hr_attendance_pin_pad_border">
<a t-attf-class="btn btn-primary btn-block btn-lg o_hr_attendance_btn-round-corners {{ 'o_hr_attendance_pin_pad_button_' + btn_name }}"><t t-esc="btn_name"/>
</a>
</div>
</t>
</div>
</div>
</div>
</div>
<!-- </div> -->
</t>
</template>
Javascript file
registration.js
odoo.define('bi_hotel.registration', function (require) {
"use strict";
// var BarcodeHandlerMixin = require('barcodes.BarcodeHandlerMixin');
var core = require('web.core');
var Widget = require('web.Widget');
var QWeb = core.qweb;
var _t = core._t;
var registration = Widget.extend({
template:'HotelRegistrationKeys',
events: {
"click .o_bi_hotel_button_registration": function(){
var self = this;
self.$el.html(QWeb.render('HotelRegistrationKeys', {widget: self}));},
'click .o_hr_attendance_pin_pad_button_A': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'A'); },
'click .o_hr_attendance_pin_pad_button_B': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'B'); },
'click .o_hr_attendance_pin_pad_button_C': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'C'); },
'click .o_hr_attendance_pin_pad_button_D': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'D'); },
'click .o_hr_attendance_pin_pad_button_E': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'E'); },
'click .o_hr_attendance_pin_pad_button_F': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'F'); },
'click .o_hr_attendance_pin_pad_button_G': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'G'); },
'click .o_hr_attendance_pin_pad_button_H': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'H'); },
'click .o_hr_attendance_pin_pad_button_I': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'I'); },
'click .o_hr_attendance_pin_pad_button_J': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'J'); },
'click .o_hr_attendance_pin_pad_button_K': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'K'); },
'click .o_hr_attendance_pin_pad_button_L': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'L'); },
'click .o_hr_attendance_pin_pad_button_M': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'M'); },
'click .o_hr_attendance_pin_pad_button_N': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'N'); },
'click .o_hr_attendance_pin_pad_button_O': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'O'); },
'click .o_hr_attendance_pin_pad_button_P': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'P'); },
'click .o_hr_attendance_pin_pad_button_Q': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'Q'); },
'click .o_hr_attendance_pin_pad_button_R': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'R'); },
'click .o_hr_attendance_pin_pad_button_S': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'S'); },
'click .o_hr_attendance_pin_pad_button_T': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'T'); },
'click .o_hr_attendance_pin_pad_button_U': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'U'); },
'click .o_hr_attendance_pin_pad_button_V': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'V'); },
'click .o_hr_attendance_pin_pad_button_W': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'W'); },
'click .o_hr_attendance_pin_pad_button_X': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'X'); },
'click .o_hr_attendance_pin_pad_button_Y': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'Y'); },
'click .o_hr_attendance_pin_pad_button_Z': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 'Z'); },
'click .o_hr_attendance_pin_pad_button_-': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + ' '); },
'click .o_hr_attendance_pin_pad_button_Del': function() { this.$('.o_hr_attendance_PINbox').val(''); },
'click .o_hr_attendance_pin_pad_button_0': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 0); },
'click .o_hr_attendance_pin_pad_button_1': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 1); },
'click .o_hr_attendance_pin_pad_button_2': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 2); },
'click .o_hr_attendance_pin_pad_button_3': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 3); },
'click .o_hr_attendance_pin_pad_button_4': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 4); },
'click .o_hr_attendance_pin_pad_button_5': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 5); },
'click .o_hr_attendance_pin_pad_button_6': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 6); },
'click .o_hr_attendance_pin_pad_button_7': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 7); },
'click .o_hr_attendance_pin_pad_button_8': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 8); },
'click .o_hr_attendance_pin_pad_button_9': function() { this.$('.o_hr_attendance_PINbox').val(this.$('.o_hr_attendance_PINbox').val() + 9); },
},
start: function (){
var self = this;
self.$el.html(QWeb.render('HotelRegistrationMenu', {widget: self}));
},
});
core.action_registry.add('bi_hotel_registration', registration);
return registration;
});
.less file
hotel.less
.o_hr_attendance_btn-round-corners {
border-radius: 10%;
}
.o_hr_attendance_pin_pad_border {
margin: 10px 0px 10px 0px;
}
.o_hr_attendance_PINbox {
background: #AEFF00;
border: 1px solid #d5d5d5;
text-align: left;
margin: 5px 0px 5px 0px;
}
.o_hr_attendance_kiosk_mode_container {
background: black;
.o-flex-display();
.o-flex-flow(column, nowrap);
.o-justify-content(center);
.o-align-items(center);
#media (min-width: #screen-xs-max) {
background: url("../../../../web_enterprise/static/src/img/application-switcher-bg.jpg") no-repeat center center fixed;
background-size: cover;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}
.o_hr_attendance_kiosk_mode {
width: 100%;
text-align: center;
position: relative;
background-color: #fff;
padding: 2em;
h1 {
margin: 0 0 2rem 0;
}
.message_demo_barcodes {
font-size: 0.9em;
margin: 0;
}
img {
overflow:hidden; // prevent margins colapsing with h1
margin-top: 3rem;
width: 200px;
}
p {
text-align: left;
margin: 3rem 0;
}
> button {
font-size: 1.2em;
margin-bottom: 2rem;
width: 100%;
}
> button:last-child {
margin-bottom: 0;
}
#media (min-width: #screen-xs-max) {
flex: 0 0 auto;
width: 550px;
border-radius: 10px;
background-color: rgba(255,255,255,0.8);
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.6);
font-size: 1.2em;
padding: 3em;
}
}
.o_border{
width: 500px;
height: 450;
text-align: left;
margin: 0 auto;
background : #ECECEC;
font-size: 1.5em;
margin-bottom: 50px;
}
.o_hr_attendance_PINbox_1 {
background: #AEFF00;
border: 1px solid #d5d5d5;
text-align: left;
margin: 5px 0px 5px 0px;
}
These above all are codes to enable the virtual keyboard but the issue is raised above.Can anybody please resolve it ?

Related

How can I pull in specific number of elements from a JQuery function?

I have a JS function that pulls in all the data based on search results. However, I want to now limit it to the top 6 listings. What is the quickest way to do that? I'm drawing complete blanks on it.
jQuery(document).ready(function ($) {
// Your code here
var $properties = $(".properties");
myvr.properties().then(function (data) {
console.log(data);
data.results.forEach(function (property) {
console.log(property.name);
$properties.append(
'<div class="col-12 col-md-6 col-lg-4">'+
'<div class="min-height-smaller" style="background:url(' +
property.photo.url +
'); background-size:cover; background-position:center;"></div>' +
'<p class="sub-heading">' +
property.name +
"</p>" +
property.headline +
"<br><br>" +
' <a class="primary-btn booking-link" data-property-id="' +
property.key +
'" href="/property/?p=' +
property.slug+"&key="+property.key +
'">Pricing and Details</a> <br><br></div>'
);
});
});
});
You can use index to keep counter and add a condition if(index < 6) it will check if index value is less then 6 then only append values to div properties .
Demo Code :
//demo json datas
var data = {
"results": [{
"name": "something"
}, {
"name": "something1"
}, {
"name": "something3"
}, {
"name": "something4"
}, {
"name": "something5"
}, {
"name": "something6"
}, {
"name": "something7"
}, {
"name": "something8"
}]
}
jQuery(document).ready(function($) {
var $properties = $(".properties");
//add index
data.results.forEach(function(property, index) {
//only append top 6 values
if (index < 6) {
$properties.append(
"<p class='sub-heading'>" +
property.name +
"</p>"
);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="properties"></div>
you can use JQuery.slice():
var $properties = $(".properties").slice(0,6);
$properties.addClass("red");
.red{
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="properties">1</div>
<div class="properties">2</div>
<div class="properties">3</div>
<div class="properties">4</div>
<div class="properties">5</div>
<div class="properties">6</div>
<div class="properties">7</div>
<div class="properties">8</div>
<div class="properties">9</div>
<div class="properties">10</div>
You can do something like this:
const teams = document.querySelectorAll('.standings ol li');
teams.forEach((team, idx) => {
if(idx < 4) {
team.classList.add('champions-league');
}
if(idx == 4) {
team.classList.add('europa-league');
}
const relegationIdxs = Array.from({length: 3}, (_, i) => (teams.length - 1) - i);
if(relegationIdxs.includes(idx)) {
team.classList.add('relegation');
}
});
.standings {
--champions-league: #4285F4;
--europa-league: #FA7B17;
--relegation: #EA4335;
background: #F8F9FA;
padding: 10px;
margin: 5px;
border-radius: 5px;
border: solid 1px #EBEBEB;
}
.champions-league {
color: var(--champions-league);
}
.europa-league {
color: var(--europa-league);
}
.relegation {
color: var(--relegation);
}
.legend span {
display: block;
margin: 1px 3px 0px 0px;
font-size: 14px;
}
span:before {
content: "■";
display: inline-block;
width: 15px;
height: 15px;
margin-right: 5px;
}
span[status="champions-league"]:before {
color: var(--champions-league)
}
span[status="europa-league"]:before {
color: var(--europa-league)
}
span[status="relegation"]:before {
color: var(--relegation)
}
<div class="standings">
<div class="legend">
<span status="champions-league">UEFA Champions League</span>
<span status="europa-league">Europa League</span>
<span status="relegation">Relegation</span>
</div>
<ol>
<li>Real Madrid</li>
<li>Barcelona</li>
<li>Atletico Madrid</li>
<li>Valencia</li>
<li>Real Sociedad</li>
<li>Getafe</li>
<li>Sevilla</li>
<li>Levante</li>
<li>Eibar</li>
<li>Elche</li>
<li>Osasuna</li>
</ol>
</div>

Vue.js auto update computed

I am a beginner to Vue.js. I have 2 components, one as rows and the second one is the sum of all rows above. The problem is that the sums are not updated automatically, even if they are set as computed.
Find below my code :
let s = []
Vue.component('subitem-row', {
props: ['subitem', 'crt', 'si'],
template: `
<tr>
<td>
<div class="form-group" v-if="crt == si">
<label>EPE</label>
<input v-model="subitem.eprice" #change="calculateSubitem();">
</div>
<span v-else>{{subitem.eprice}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si" #change="parseExpresion(); calculateSubitem();">
<label>Anzahl</label>
<input v-model="subitem.qtytext">
</div>
<span v-else>{{subitem.qtytext}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>Faktor</label>
<input v-model="subitem.factor" #change="calculateSubitem();">
</div>
<span v-else>{{subitem.factor}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>EK</label>
<input v-model="subitem.tp1" readonly>
</div>
<span v-else>{{subitem.tp1}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>Marge</label>
<input v-model="subitem.margin" readonly>
</div>
<span v-else>{{subitem.margin}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>VK</label>
<input v-model="subitem.tp2" readonly>
</div>
<span v-else>{{subitem.tp2}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>Rabatt</label>
<input v-model="subitem.discount" #change="calculateSubitem();">
</div>
<span v-else>{{subitem.discount}}</span>
</td>
</tr>
`,
methods: {
calculateSubitem: function() {
if(this.subitem.hasOwnProperty('eprice') && !isNaN(this.subitem.eprice)) {
if(!this.subitem.hasOwnProperty('factor') || isNaN(this.subitem.factor))
this.subitem.factor = 1
if(!this.subitem.hasOwnProperty('discount') || isNaN(this.subitem.discount))
this.subitem.discount = 0
if(!this.subitem.hasOwnProperty('qty') || isNaN(this.subitem.qty))
this.subitem.qty = 0
let discount = 1 - (parseFloat(this.subitem.discount.toString().split(',').join('.')) / 100),
margin = 0
this.subitem.dprice = (this.subitem.eprice.split(',').join('.') * discount)
this.subitem.tp1 = (this.subitem.dprice * this.subitem.qty * this.subitem.factor)
this.subitem.margin = (this.subitem.tp1 * (parseFloat(margin) / 100))
this.subitem.tp2 = (this.subitem.tp1 + this.subitem.margin)
this.$forceUpdate()//{TODO} - find an alternative to $forceUpdate
}
},
parseExpresion: function() {
this.subitem.qty = parseFloat(this.subitem.qtytext.split(',').join('.')) || 0
this.$nextTick(function () {
this.calculateSubitem()
})
}
},
})
Vue.component('subitem-row-sum', {
props: ['sisum'],
template: `
<tr>
<td colspan="3">SUM</td>
<td>
<span>{{sisum.tp1}}</span>
</td>
<td>
<span>{{sisum.margin}}</span>
</td>
<td>
<span>{{sisum.tp2}}</span>
</td>
<td></td>
</tr>
`,
})
Vue.component('html-textarea',{
template: `<div class="html-textarea" contenteditable="true" #input="updateHTML" rows="3"></div>`,
props: ['value'],
mounted: function () {
this.$el.innerHTML = this.value;
},
methods: {
updateHTML: function(e) {
this.$emit('input', e.target.innerHTML)
}
}
})
const app = new Vue({
el: '#app',
data: {
obj: s, // main object for loading
ii: 0, // items index
si: 0, // subitems index
},
computed: {
items: function() {
return this.obj
},
row: function() {
if(!this.items.length)
this.items.push({})
return this.items[this.ii]
},
subitems: function() {
if(!this.row.hasOwnProperty('subitems'))
this.row.subitems = [{}]
return this.row.subitems
},
srow: function() {
if(!this.subitems.length)
this.subitems.push({})
return this.subitems[this.si]
},
sisum: function() {
let sisum = {
tp1: 0,
tp2: 0,
margin: 0
}
this.subitems.forEach(si => {
sisum.tp1 += si.tp1 || 0
sisum.tp2 += si.tp2 || 0
sisum.margin += si.margin || 0
})
return sisum
}
},
methods: {
setIi: function(i) {
this.ii = i
},
setSi: function(i) {
this.si = i
},
addItemRow: function() {
this.items.push({})
this.setIi(this.items.length - 1)
this.$nextTick(function () {
document.getElementById('items').scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"})
})
},
addSubitemRow: function() {
this.subitems.push({})
this.setSi(this.subitems.length - 1)
this.$nextTick(function () {
document.getElementById('subitems').scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"})
})
},
},
})
body {
padding: 0;
margin: 0;
font-size: 14px;
font-family: 'Courier New', monotype;
}
.tables-container {
display: flex;
flex-direction: column;
height: 100vh;
}
.table-container {
height: calc(50% - 2px);
overflow: auto;
margin: 0 0 30px 0;
background: #eee
}
.table-container td {
padding: 3px 6px;
width: 60px;
height: 30px;
border-bottom: 1px solid black;
vertical-align: middle;
font-size: 1.1rem;
}
.html-textarea-container {
position: relative;
}
.html-textarea {
background: white;
border: 1px solid black;
}
.btn-group-edit {
position: absolute;
right: 2px;
bottom: 2px;
/*display: none;*/
z-index: 1;
}
/*.html-textarea:hover + .btn-group-edit,
.html-textarea:focus + .btn-group-edit {
display: block;
}*/
.table-container .form-group > input,
.table-container .form-group > textarea,
.table-container .form-group > select,
.html-textarea {
width: calc(200px - 12px);
height: calc(30px - 6px);
font-size: 1.1rem;
font-family: 'Courier New', monotype;
word-wrap: break-word;
}
.table-container .form-group > textarea,
.html-textarea {
width: calc(600px - 12px);
}
/*.table-container .form-group > textarea:focus,
.html-textarea {
height: calc(150px - 6px);
}*/
.btn-add {
width: 30px;
height: 30px;
padding: 4px 0;
}
<div id="app">
<div class="tables-container">
<div class="table-container table-subitems">
<table id="subitems">
<tr is="subitem-row" v-for="(subitem, i) in subitems" v-bind:subitem="subitem" v-bind:key="i" v-bind:crt="i" v-bind:si="si" v-on:click.native="setSi(i)"></tr>
<tr is="subitem-row-sum" v-bind:sisum="sisum"></tr>
</table>
</div>
<button class="btn-add" v-on:click="addSubitemRow">+</button>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
Adding numbers to "EPE" and "Anzahl" fields the others are automatically filled, but the sums not. What is my mistake here? Being a computed property, I was thinking that it will be reactive and update itself, based on the current set of subitems.
Thank you.
Welcome to Stack Overflow. I've made an attempt at fixing your code, tbh I found it really difficult to understand and I think you're overusing computed properties, e.g.
items: function() {
return this.obj
},
You might as well just reference this.obj instead of this.items as you're over complicating your code.
Your main problem was initialising the data, Since Vue doesn’t allow dynamically adding root-level reactive properties, you have to initialize Vue instances by declaring all root-level reactive data properties upfront, even with an empty value Declaring Reactive Properties
So I initialised s like this:
let s = [{
subitems: [{
eprice: "0",
factor: 0,
discount: 0,
qty: 0,
dprice: 0,
tp1: 0,
margin: 0,
tp2: 0
}]
}];
let s = [{
subitems: [{
eprice: "0",
factor: 0,
discount: 0,
qty: 0,
dprice: 0,
tp1: 0,
margin: 0,
tp2: 0
}]
}];
Vue.component('subitem-row', {
props: ['subitem', 'crt', 'si'],
template: `
<tr>
<td>
<div class="form-group" v-if="crt == si">
<label>EPE</label>
<input v-model="subitem.eprice" #change="calculateSubitem();">
</div>
<span v-else>{{subitem.eprice}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si" #change="parseExpresion(); calculateSubitem();">
<label>Anzahl</label>
<input v-model="subitem.qtytext">
</div>
<span v-else>{{subitem.qtytext}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>Faktor</label>
<input v-model="subitem.factor" #change="calculateSubitem();">
</div>
<span v-else>{{subitem.factor}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>EK</label>
<input v-model="subitem.tp1" readonly>
</div>
<span v-else>{{subitem.tp1}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>Marge</label>
<input v-model="subitem.margin" readonly>
</div>
<span v-else>{{subitem.margin}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>VK</label>
<input v-model="subitem.tp2" readonly>
</div>
<span v-else>{{subitem.tp2}}</span>
</td>
<td>
<div class="form-group" v-if="crt == si">
<label>Rabatt</label>
<input v-model="subitem.discount" #change="calculateSubitem();">
</div>
<span v-else>{{subitem.discount}}</span>
</td>
</tr>
`,
methods: {
calculateSubitem: function() {
if (this.subitem.hasOwnProperty('eprice') && !isNaN(this.subitem.eprice)) {
if (!this.subitem.hasOwnProperty('factor') || isNaN(this.subitem.factor))
this.subitem.factor = 1
if (!this.subitem.hasOwnProperty('discount') || isNaN(this.subitem.discount))
this.subitem.discount = 0
if (!this.subitem.hasOwnProperty('qty') || isNaN(this.subitem.qty))
this.subitem.qty = 0
let discount = 1 - (parseFloat(this.subitem.discount.toString().split(',').join('.')) / 100),
margin = 0
this.subitem.dprice = (this.subitem.eprice.split(',').join('.') * discount)
this.subitem.tp1 = (this.subitem.dprice * this.subitem.qty * this.subitem.factor)
this.subitem.margin = (this.subitem.tp1 * (parseFloat(margin) / 100))
this.subitem.tp2 = (this.subitem.tp1 + this.subitem.margin)
this.$forceUpdate() //{TODO} - find an alternative to $forceUpdate
}
},
parseExpresion: function() {
this.subitem.qty = parseFloat(this.subitem.qtytext.split(',').join('.')) || 0
this.$nextTick(function() {
this.calculateSubitem()
})
}
},
})
Vue.component('subitem-row-sum', {
props: ['sisum'],
template: `
<tr>
<td colspan="3">SUM</td>
<td>
<span>{{sisum.tp1}}</span>
</td>
<td>
<span>{{sisum.margin}}</span>
</td>
<td>
<span>{{sisum.tp2}}</span>
</td>
<td></td>
</tr>
`,
})
Vue.component('html-textarea', {
template: `<div class="html-textarea" contenteditable="true" #input="updateHTML" rows="3"></div>`,
props: ['value'],
mounted: function() {
this.$el.innerHTML = this.value;
},
methods: {
updateHTML: function(e) {
this.$emit('input', e.target.innerHTML)
}
}
})
const app = new Vue({
el: '#app',
data: {
obj: s, // main object for loading
ii: 0, // items index
si: 0, // subitems index
},
computed: {
items: function() {
return this.obj
},
row: function() {
if (!this.items.length)
this.items.push({})
return this.items[this.ii]
},
subitems: function() {
return this.row.subitems
},
srow: function() {
if (!this.subitems.length)
this.subitems.push({})
return this.subitems[this.si]
},
sisum: function() {
debugger;
let sisum = {
tp1: 0,
tp2: 0,
margin: 0
}
this.subitems.forEach(si => {
sisum.tp1 += si.tp1 || 0
sisum.tp2 += si.tp2 || 0
sisum.margin += si.margin || 0
})
return sisum;
}
},
methods: {
setIi: function(i) {
this.ii = i
},
setSi: function(i) {
this.si = i
},
addItemRow: function() {
this.items.push({})
this.setIi(this.items.length - 1)
this.$nextTick(function() {
document.getElementById('items').scrollIntoView({
behavior: "smooth",
block: "end",
inline: "nearest"
})
})
},
addSubitemRow: function() {
this.subitems.push({})
this.setSi(this.subitems.length - 1)
this.$nextTick(function() {
document.getElementById('subitems').scrollIntoView({
behavior: "smooth",
block: "end",
inline: "nearest"
})
})
},
},
})
body {
padding: 0;
margin: 0;
font-size: 14px;
font-family: 'Courier New', monotype;
}
.tables-container {
display: flex;
flex-direction: column;
height: 100vh;
}
.table-container {
height: calc(50% - 2px);
overflow: auto;
margin: 0 0 30px 0;
background: #eee
}
.table-container td {
padding: 3px 6px;
width: 60px;
height: 30px;
border-bottom: 1px solid black;
vertical-align: middle;
font-size: 1.1rem;
}
.html-textarea-container {
position: relative;
}
.html-textarea {
background: white;
border: 1px solid black;
}
.btn-group-edit {
position: absolute;
right: 2px;
bottom: 2px;
/*display: none;*/
z-index: 1;
}
/*.html-textarea:hover + .btn-group-edit,
.html-textarea:focus + .btn-group-edit {
display: block;
}*/
.table-container .form-group>input,
.table-container .form-group>textarea,
.table-container .form-group>select,
.html-textarea {
width: calc(200px - 12px);
height: calc(30px - 6px);
font-size: 1.1rem;
font-family: 'Courier New', monotype;
word-wrap: break-word;
}
.table-container .form-group>textarea,
.html-textarea {
width: calc(600px - 12px);
}
/*.table-container .form-group > textarea:focus,
.html-textarea {
height: calc(150px - 6px);
}*/
.btn-add {
width: 30px;
height: 30px;
padding: 4px 0;
}
<div id="app">
<div class="tables-container">
<div class="table-container table-subitems">
<table id="subitems">
<tr is="subitem-row" v-for="(subitem, i) in subitems" v-bind:subitem="subitem" v-bind:key="i" v-bind:crt="i" v-bind:si="si" v-on:click.native="setSi(i)"></tr>
<tr is="subitem-row-sum" v-bind:sisum="sisum"></tr>
</table>
</div>
<button class="btn-add" v-on:click="addSubitemRow">+</button>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

Restoring GridstackJS Panels with Content (e.g. Highcharts)

I am building a Dashboard where you are able to add, delete, move and resize Panels within a grid using GridstackJS. I am filling these Panels with different things. In this Example I am using a Highchart. For saving and restoring the position and Size of the Panels I use the standard serialization of GridstackJS.
My problem now is to save and restore the Content inside the Panels.
Is there an elegant way to save the Content and apply it to the correct Panel when restoring?
JSFiddle
HTML
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gridstack#0.5.5/dist/gridstack.css" />
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/gridstack#0.5.5/dist/gridstack.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/gridstack#0.5.5/dist/jquery-ui.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/gridstack#0.5.5/dist/gridstack.jQueryUI.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<button id="save-grid" class="btn btn-primary">Save Grid</button>
<button id="load-grid" class="btn btn-primary">Load Grid</button>
<button id="delete-grid" class="btn btn-primary">Delete Grid</button>
<div class="row">
<div class="col-sm-12">
<div class="grid-stack ui-droppable">
<div class="dragbox grid-stack-item ui-draggable ui-resizable" data-gs-id="draggable">
<h2 class="dragbox-header">Chart 1</h2>
<div class="dragbox-content">
<div class="text-center"> Item 1</div>
</div>
</div>
<div class="dragbox grid-stack-item ui-draggable ui-resizable" data-gs-id="draggable">
<h2 class="dragbox-header">Chart 2</h2>
<div class="dragbox-content"></div>
</div>
<div class="dragbox grid-stack-item ui-draggable ui-resizable" data-gs-id="draggable" data-gs-width="4" data-gs-height="4">
<h2 class="dragbox-header" id="testChartHeader">Chart 3</h2>
<div class="text-center" id="testChart"></div>
</div>
</div>
</div>
</div>
CSS
.dragbox {
margin: 5px 2px 20px;
background: #fff;
position: absolute;
border: 1px solid #ddd;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
.dragbox-header {
margin: 0;
font-size: 12px;
padding: 5px;
background: #f0f0f0;
color: #000;
border-bottom: 1px solid #eee;
font-family: Verdana;
cursor: move;
position: relative;
}
.dragbox-content {
display: block;
background: #fff;
margin: 5px;
font-family: 'Lucida Grande', Verdana;
font-size: 0.8em;
line-height: 1.5em;
}
#testChart {
height: 200px;
}
.placeholder {
background: lightgray;
border: 1px dashed #ddd;
border-radius: 5px;
}
JavaScript
$(function() {
var options = {
draggable: {handle: '.dragbox-header', scroll: false, appendTo: 'body'},
placeholderClass: "placeholder",
acceptWidgets: true,
cellHeight: 60
};
$('.grid-stack').gridstack(options);
new function () {
this.serializedData = [
];
this.grid = $('.grid-stack').data('gridstack');
this.loadGrid = function () {
this.grid.removeAll();
var items = GridStackUI.Utils.sort(this.serializedData);
items.forEach(function (node, i) {
this.grid.addWidget($('<div class="grid-stack-item ui-draggable ui-resizable" data-gs-id="draggable"><div class="dragbox grid-stack-item-content ui-draggable-handle"><div class="dragbox-header">Chart ' + (i + 1) + '</div></div></div>'), node);
}, this);
return false;
}.bind(this);
this.saveGrid = function () {
this.serializedData = $('.grid-stack > .grid-stack-item').map(function (i, el) {
el = $(el);
var node = el.data('_gridstack_node');
return {
x: node.x,
y: node.y,
width: node.width,
height: node.height
};
}).toArray();
return false;
}.bind(this);
this.clearGrid = function () {
this.grid.removeAll();
return false;
}.bind(this);
$('#save-grid').click(this.saveGrid);
$('#load-grid').click(this.loadGrid);
$('#delete-grid').click(this.clearGrid);
};
});
var chart = Highcharts.chart('testChart', {
chart: {
animation: false,
type: 'bar'
},
plotOptions: {
series: {
animation: false,
}
},
title: {
text: 'Fruit Consumption'
},
xAxis: {
categories: ['Apples', 'Bananas', 'Oranges']
},
yAxis: {
title: {
text: 'Fruit eaten'
}
},
series: [{
name: 'Jane',
data: [1, 0, 4]
}, {
name: 'John',
data: [5, 7, 3]
}]
});
$('.grid-stack').on('change', function(event, items) {
var chartContainer = chart.renderTo;
$(chartContainer).css(
'height',
$(chartContainer.parentElement).height() - $('#testChartHeader').height()
);
chart.reflow();
});
You need to create a chart again in the loadGrid function:
this.loadGrid = function() {
this.grid.removeAll();
var items = GridStackUI.Utils.sort(this.serializedData);
items.forEach(function(node, i) {
this.grid.addWidget($('<div class="grid-stack-item ui-draggable ui-resizable" data-gs-id="draggable"><div class="dragbox grid-stack-item-content ui-draggable-handle"><div class="dragbox-header">Chart ' + (i + 1) + '</div>' + (i === 2 ? '<div id="testChart"></div>' : '') + '</div></div>'), node);
}, this);
chart = createChart();
return false;
}.bind(this);
Live demo: https://jsfiddle.net/BlackLabel/pjy8b950/

Jquery Fancybox How to add extra navigation buttons?

I am using fancybox 2 to display photo galleries on my website. The html has the links to galleries like photography & graphic design and the images are listed in a js-file.
In the picture in this link https://dl.dropboxusercontent.com/u/107031749/fancyboksi/help.JPG is what I have at the moment. I have already styled the navigation. I'm using a customized "simple dotted navigation". I need help with the orange arrows (The green next/previous & close buttons are working great, no problem with them). When clicked on an orange arrow, the next or previous 10 links should be displayed. There can be almost 50 images in one gallery, so I need this feature. (It's showing 19 links now because of the styling. I'll fix that later.)
I don't have much javascript skills, I copy & paste usually. Below is a part from the js code. The lines starting from "var karuselli_next =..." to the line "$("#oikea_btn").attr("title", karuselli_next);" are the ones that need fixing.
function addLinks() {
var list = $("#linksit");
if (!list.length) {
list = $('<ul id="linksit">');
for (var i = 0; i < this.group.length; i++) {
$('<li data-index="' + i + '"><label>' + (i+1) + '</label></li>').click(function() { $.fancybox.jumpto( $(this).data('index'));}).appendTo( list );
}
list.appendTo( 'body' );
$("#linksit").wrap('<div id="karuselli">' + '<div id="navi_linksit">' + '<div class="linksit">'); // Lisää divit + ul#linksit sisällä
$(".linksit").before('<a id="vasen_btn" class="vasen_btn" href="javascript:;" />'); // Lisää nuoli vasemmalle
$(".linksit").before('<a id="oikea_btn" class="oikea_btn" href="javascript:;" />'); // Lisää nuoli oikealle
}
list.find('li').removeClass('active').eq( this.index ).addClass('active');
var karuselli_next = $("#oikea_btn");
var karuselli_prev = $("#vasen_btn");
karuselli_next = $(".fancybox").eq( this.index + 10 ).attr("title");
karuselli_prev = $(".fancybox").eq( this.index - 10 ).attr("title");
$("#vasen_btn").attr("title", karuselli_prev);
$("#oikea_btn").attr("title", karuselli_next);
if (typeof this.title2 != 'undefined') {
this.title = '<span class="finkku"><p class="kieli_gall">Suomi</p>' + this.title + '</span>' + "<br>" + '<span class="enkku"><p class="kieli_gall">English</p>' + this.title2 + '</span>'+ "<br>" + '<span class="img_num">' + (this.index + 1) + '<span class="img_num2">' + '(' + this.group.length + ')' + '</span>' + '</span>';
} else {
this.title = '<span class="finkku">' + this.title + '</span>' + "<br>" + '<span class="img_num">' + (this.index + 1) + '<span class="img_num2">' + '(' + this.group.length + ')' + '</span>' + '</span>';
};
}
function removeLinks() {
$("#linksit").remove();
$("#karuselli").remove();
}
Thank you for the help!
Here's the jsFiddle http://jsfiddle.net/cattimir/gmqw37r3/1/
I haven't used your code at all, because I haven't had more code from you. A working jsFiddle was missing...
I have coded the pagination with simplePagination jQuery plugin.
I've commeted the fancybox (not sure if you really need the fancybox), because I haven't used any feature of the fancybox. Anyway if you need it, it should work like it is in the code.
You can find the demo at jsFiddle. (The code below is identical to the jsFiddle code.)
I think it should be what you are looking for, just add your css styling.
$(document).ready(function () {
var $pagination = $('#container').simplePagination({
previous_content: '<i class="fa fa-arrow-left"></i>', //e.g. '<'
next_content: '<i class="fa fa-arrow-right"></i>', //e.g. '>'
number_of_visible_page_numbers: 6,
items_per_page: 1,
pagination_container: 'ul',
html_prefix: 'simple-pagination',
navigation_element: 'a', //button, span, div, et cetera
});
/*
$.fancybox({
content: $pagination,
prevEffect: 'none',
nextEffect: 'none',
scrolling: 'no',
closeBtn: false,
type: 'image', // required for lorempixel to work
});
$(".fancybox-overlay").unbind(); // disable dismiss if overlay clicked
*/
});
a {
color: #216ed9;
text-decoration: none;
}
a h1 {
padding: 2rem;
color: #216ed9;
text-align: center;
}
a:hover {
text-decoration: underline;
}
/*
a[class^="simple-pagination-navigation-"] + a[class^="simple-pagination-navigation-"] {
margin-right: 0;
}*/
a[class*="simple-pagination-navigation-disabled"] {
color: black;
cursor: default;
}
/*
Styles used to page things look nice :)
*/
* {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0;
outline: 0;
}
body {
font: 1rem/1rem Helvetica, sans-serif;
background-color: #164B1f;
}
#header {
border-radius: .5rem;
}
.my-navigation div {
/*float: left;*/
display: inline-block;
}
.my-navigation {
text-align: center;
}
.nav-wrap {
padding-top: 0.5em;
margin: 0px auto;
}
.simple-pagination-page-numbers a {
width: 2rem;
padding: 0.5em;
text-align: center;
}
.simple-pagination-page-numbers {
}
.simple-pagination-previous, .simple-pagination-next {
padding-bottom: 0.5em;
}
#container {
text-align: center;
}
.gallery {
list-style: none;
margin: 0px auto;
}
.gallery img {
box-shadow: 5px 5px 2px rgba(0, 0, 0, 0.25);
}
/*
.simple-pagination-navigation-previous {
float: left;
}
.simple-pagination-navigation-next {
float: right;
}*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.css" rel="stylesheet"/>
<script src="https://cdn.rawgit.com/ddenhartog/jquery-simple-pagination/master/jquery-simple-pagination-plugin.js"></script>
<div id="container">
<div class="my-navigation">
<!--<div class="simple-pagination-first"></div>-->
<div class="nav-wrap">
<div class="simple-pagination-previous"></div>
<div class="simple-pagination-page-numbers"></div>
<div class="simple-pagination-next"></div>
<!--<div class="simple-pagination-last"></div>--></div>
</div>
<ul class="gallery">
<li>
<img src="http://farm8.staticflickr.com/7404/12868632153_b0a5718c22_m.jpg" alt="" />
</li>
<li>
<img src="http://farm6.staticflickr.com/5584/15276294205_5a7ffe793c_m.jpg" alt="" />
</li>
<li>
<img src="http://farm8.staticflickr.com/7412/8732133694_0c7e400022_m.jpg" alt="" />
</li>
<li>
<img src="http://farm3.staticflickr.com/2870/8985207189_01ea27882d_m.jpg" alt="" />
</li>
<li>
<img src="http://lorempixel.com/240/160/sports/1/" alt="" />
</li>
<li>
<img src="http://lorempixel.com/240/160/sports/2/" alt="" />
</li>
<li>
<img src="http://lorempixel.com/240/160/sports/3/" alt="" />
</li>
<li>
<img src="http://lorempixel.com/240/160/sports/4/" alt="" />
</li>
<li>
<img src="http://lorempixel.com/240/160/sports/5/" alt="" />
</li>
</ul>
<!-- not needed here <div class="simple-pagination-page-x-of-x"></div>
<div class="simple-pagination-showing-x-of-x"></div>
-->
</div>
Have you found a solution for your code? If not, here is your improved code with the pagination like you wanted it.
Just styling has to be improved but the js code is working now.
I have re-coded a lot that's why my answer comes pretty late.
I've added the function refreshPagination to manage the pagination. I have first tried to get the simplePagination jQuery plugin to work but with-out success.
If you'd like to increase the displayed page links count you'll only have to change the variable pagination_size.
The code could probably be improved by refactoring the pagination feature into a seperate object but it is working like it is.
I've also added that a single image next/prev click will check if the pagination needs to be modified if it's advancing to the next image in the afterLoad method.
That's what all the if conditions are checking before calling the addLinks.bind(this)(curPagination); function.
I'm binding the fancybox object to the addLinks call to have access to the fancybox index etc.
You could also add the addLinks method to the fancybox object, so you could call it with this.addLinks(curPagination) that would be cleaner. Any way, it's also working with binding.
You can find the demo below and here at jsFiddle.
(function($) {
//function galleriaGraafinen(graafinen){
var images = [{
href: 'http://fancyapps.com/fancybox/demo/1_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/2_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/3_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/1_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/2_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/3_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/1_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/2_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/3_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/1_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/2_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/3_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/1_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/2_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/3_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/1_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/2_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/3_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/1_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/2_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}, {
href: 'http://fancyapps.com/fancybox/demo/3_b.jpg',
title: 'Kuvateksti',
title2: 'Caption'
}];
var curPagination = 0, // current pagination position
pagination_size = 5, // constant for pagination
activeIndex = 0,
$listItems = []; // currently visible pagination items
$.fancybox.open(images, {
beforeShow: function () {
/* Disable right click */
$.fancybox.wrap.bind("contextmenu", function (e) {
return true;
});
},
openEffect: 'none',
closeEffect: 'none',
prevEffect: 'none',
nextEffect: 'none',
afterLoad: function (current, previous) {
// curPagination 0 5 10 ...
// index 01234 56789 10...
var lastIndex = (curPagination + pagination_size) - 1; // 4 9 14
//console.log(this.index, 'after load', curPagination, lastIndex);
// find correct pagination
// 0...4 --> pagination = 0
// 5...9 --> pagination = 5
// 10...14 --> pagination = 10
// check if pagination is required?
if (this.index < curPagination || this.index > lastIndex) {
// index is not in current pagination range --> adjust pagination
// increasing from 0
if (this.index > lastIndex) {
// check if we're at the end of the group?
if (curPagination <= this.group.length - 2 * pagination_size) curPagination += pagination_size; //next clicked
else curPagination = this.group.length - pagination_size;
} else {
// back navigation of pagination
if (this.index <= curPagination) {
if (this.index >= pagination_size) {
curPagination -= pagination_size;
} else {
curPagination = 0;
}
}
}
// decreasing from 0 --> roll-over to last element
if (this.index == this.group.length - 1) curPagination = this.group.length - pagination_size;
}
addLinks.bind(this)(curPagination);
},
beforeClose: removeLinks,
margin: [45, 15, 40, 15],
padding: 0,
helpers: {
title: {
type: 'outside'
},
/* thumbs : {
width : 20,
height : 20,
position : 'top'
},*/
overlay: {
locked: true,
closeClick: false
}
}
});
function addLinks(pos) {
var self = this;
curPagination = pos || 0;
activeIndex = this.index; // store currently active image index
function refresh_pagination(pos) {
var itemCount = 0;
$('#linksit').empty();
$listItems = [];
$.each(self.group, function (i, value) {
if (i >= pos && itemCount < pagination_size) {
itemCount++;
$listItems[i] = $('<li/>')
.attr('data-index', i)
.append($('<label/>')
.text(i + 1))
.click(function () {
$.fancybox.jumpto($(this).data('index'));
});
// check if current element is active?
if (i == activeIndex) {
//console.log('found index', i);
$listItems[i].addClass('active');
}
}
});
$('#linksit').html($listItems);
}
refresh_pagination(curPagination);
var $list = $('<ul/>')
.removeClass('active')
.attr('id', 'linksit')
.html($listItems);
//console.log($('#linksit').length);
if (!$('#linksit').length) {
// pagination not in DOM --> add it
$list.appendTo('body');
$("#linksit").wrap('<div id="karuselli">' + '<div id="navi_linksit">' + '<div class="linksit">'); // Lisää divit + ul#linksit sisällä
$(".linksit").before('<a id="vasen_btn" class="vasen_btn" href="javascript:;"></a>'); // Lisää nuoli vasemmalle --> back button
$(".linksit").after('<a id="oikea_btn" class="oikea_btn" href="javascript:;"></a>'); // Lisää nuoli oikealle --> next button
// click handlers for pagination
$('#vasen_btn').click(function () {
//back pagination
//console.log(curPagination);
if (curPagination > pagination_size) curPagination -= pagination_size;
else curPagination = 0;
refresh_pagination(curPagination);
});
$('#oikea_btn').click(function () {
//next pagination
//console.log(curPagination);
if (curPagination <= self.group.length - 2 * pagination_size) curPagination += pagination_size;
else curPagination = self.group.length - pagination_size;
refresh_pagination(curPagination);
});
} else {
// pagination links already in DOM --> update them
$('#linksit').html($listItems);
}
//console.log($listItems);
// add titles
if ( this.title2 ) {
this.title = '<span class="finkku"><p class="kieli_gall">Suomi</p>' + this.title + '</span>' + "<br>" + '<span class="enkku"><p class="kieli_gall">English</p>' + this.title2 + '</span>' + "<br>" + '<span class="img_num">' + (this.index + 1) + '<span class="img_num2">' + '(' + this.group.length + ')' + '</span>' + '</span>';
} else {
this.title = '<span class="finkku">' + this.title + '</span>' + "<br>" + '<span class="img_num">' + (this.index + 1) + '<span class="img_num2">' + '(' + this.group.length + ')' + '</span>' + '</span>';
};
}
function removeLinks() {
$("#linksit").remove();
$("#karuselli").remove();
}
//};
//window.galleriaTridmalli = galleriaGraafinen;
})(jQuery);
#import url(http://fonts.googleapis.com/css?family=Shadows+Into+Light+Two);
.fancybox-title, .fancybox-title a:link, .fancybox-title a:visited {
font-size: 18px !important;
font-family:'Shadows Into Light Two' !important;
color: #303030 !important;
}
.fancybox-title-outside-wrap {
margin-top: 20px !important;
}
.fancybox-wrap {
margin-top: 25px !important;
}
.fancybox-skin {
background-color: #ffffff !important;
padding: 10px !important;
border-radius: 8px !important;
}
.fancybox-overlay {
background: url("http://kaasimir.name/schaibaa/ruutu_bg.jpg") !important;
}
.fancybox-close, .fancybox-prev span, .fancybox-next span {
background-image: url("http://kaasimir.name/schaibaa/fancybox_sprite_oma.png") !important;
}
.fancybox-close {
top: -5px !important;
right: -93px !important;
width: 75px !important;
height: 50px !important;
}
.fancybox-nav span {
width: 100px !important;
height: 70px !important;
visibility: visible !important;
}
.fancybox-nav {
width: 200px !important;
}
.fancybox-prev {
left: -140px !important;
}
.fancybox-next {
right: -140px !important;
}
.fancybox-prev span {
background-position: 0 -50px !important;
}
.fancybox-next span {
background-position: 0 -128px !important;
}
#karuselli {
display: block;
position: relative;
top: -40px;
width: 40%;
height: auto;
margin: 0 auto;
z-index: 99999 !important;
}
/* added font-awesome icons at the end of css --> image is missing */
#navi_linksit a.vasen_btn {
cursor: pointer;
position: absolute !important;
left: -50px;
z-index: 99999 !important;
display: block !important;
/*width: 44px !important;
height: 22px !important;
content: url("http://kaasimir.name/schaibaa/nuoli_vasen.png") !important;
*/
float: left !important;
}
#navi_linksit a.oikea_btn {
cursor: pointer;
position: absolute !important;
right: -50px;
z-index: 99999 !important;
display: block !important;
/*width: 44px !important;
height: 22px !important;
content: url("http://kaasimir.name/schaibaa/nuoli_oikea.png") !important;
*/
float: right !important;
}
div.linksit {
position: absolute;
width: 80%;
height: 30px;
text-align: center;
z-index: 99991;
overflow: hidden;
padding: 0;
margin: 0;
}
ul#linksit {
position: relative;
overflow: hidden;
list-style: none;
text-align: center;
z-index: 99990;
line-height: 1.2;
padding: 0;
left: 0;
top: 0;
margin: 0;
display: inline-flex;
}
ul#linksit li {
display: inline;
padding: 0 4px !important;
}
ul#linksit li label {
width: 20px;
height: 20px;
border-radius: 100%;
display: inline-block;
background-color: rgba(179, 179, 179, 1);
cursor: pointer;
margin-bottom: 6px;
}
ul#linksit li.active label {
background-color: orange !important;
width: 20px;
height: 20px;
}
/* Caption */
.finkku {
color: #303030;
display: block;
padding-bottom: 5px;
}
.enkku {
color: #303030;
display: block;
}
p.kieli_gall {
color: #aa66aa;
margin: 0 15px 0 0;
display: inline;
}
/* Image number */
.img_num {
color: orange;
font-size: 40px;
position: absolute;
top: -80px;
left: 30px;
}
.img_num2 {
color: orange;
font-size: 20px;
position: absolute;
top: 8px;
right: -40px;
}
/* pagination next/prev link styling */
a.oikea_btn, a.vasen_btn {
width: 10%;
}
a.oikea_btn:link, a.vasen_btn:link {
text-decoration: none;
text-underline: none;
}
.oikea_btn:before {
font-family: FontAwesome;
content:"\f054";
}
.vasen_btn:before {
font-family: FontAwesome;
content:"\f053";
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.css" rel="stylesheet"/>
<script src="https://cdn.rawgit.com/ddenhartog/jquery-simple-pagination/master/jquery-simple-pagination-plugin.js"></script>
<script src="http://fancyapps.com/fancybox/source/jquery.fancybox.js"></script>
<link href="http://fancyapps.com/fancybox/source/jquery.fancybox.css" rel="stylesheet"/>
<div>Graphic design Link
</div>
<div>Photography Link
</div>
<div>Illustration Link
</div>

jQuery not appending a drag-and-drop to connected folders

Going for a sort-of Windows explorer-style drag-and-drop folder behavior here. The "// make chapter items droppable" block isn't working - specifically, it's not appending the draggable to the dragged folder's list.
<html>
<head>
<script src="js/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="js/jquery-ui-1.7.2.custom.min.js" type="text/javascript"></script>
<style>
ul
{
margin: 0;
padding: 0;
}
ul#chapter_list
{
background: #fff;
}
#chapter_list li
{
list-style-type: none;
position: relative;
}
#chapter_list li .sortable_handle
{
cursor: move;
padding: 2px .5em 5px 5px;
position: relative;
top: -2px;
left: -5px;
}
span.chapter_title
{
cursor: pointer;
padding-left: 36px !important;
background: url(http://www.openwebgraphics.com/resources/data/2296/22x22_folder_orange_open.png) no-repeat 8px 50%;
}
.comic_chapter div, .comic_page
{
border: 2px solid black;
margin-bottom: 1px;
padding: 3px 5px;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
}
li.comic_chapter ul
{
padding: 2px 2px 2px 1em;
margin: 3px;
}
#chapter_list li.drop_highlight div
{
background: darkBlue;
color: white;
}
.comic_chapter div
{
background: LightBlue;
}
.comic_page
{
background: #fff;
}
.chapter-placeholder
{
border: 2px dashed LightBlue;
margin: 2px;
}
.page-placeholder
{
height: 1.6em;
border: 2px dashed #666;
margin: 2px;
}
</style>
</head>
<body>
<script type="text/javascript" />
var chapter_list = {
0 : {
'chapter_title' : 'Un-Chaptered',
'chapter_pages' : {}
},
1 : {
'chapter_title' : 'Chapter 1',
'chapter_pages' : {
1 : {
'page_title' : 'Page 1'
},
2 : {
'page_title' : 'Page 2'
},
3 : {
'page_title' : 'Page 3'
},
4 : {
'page_title' : 'Page 4'
},
5 : {
'page_title' : 'Page 5'
},
6 : {
'page_title' : 'Page 6'
}
}
},
2 : {
'chapter_title' : 'Chapter 2',
'chapter_pages' : {
7 : {
'page_title' : 'Page 7'
},
8 : {
'page_title' : 'Page 8'
},
9 : {
'page_title' : 'Page 9'
},
10 : {
'page_title' : 'Page 10'
}
}
},
3 : {
'chapter_title' : 'Chapter 3',
'chapter_pages' : {
11 : {
'page_title' : 'Page 11'
},
12 : {
'page_title' : 'Page 12'
}
}
}
};
document.write('<ul id="chapter_list">');
for (i in chapter_list) {
chapter = chapter_list[i];
document.write('<li id="chapter_' + i + '" class="comic_chapter">' +
'<div>' +
'<span class="sortable_handle">||</span>');
if (i > 0) document.write('<input type="checkbox" />');
document.write('<span class="chapter_title">' + chapter.chapter_title + '</span>' +
'</div>' +
'<ul id="chapter_' + i + '_pages">');
for (n in chapter.chapter_pages) {
page = chapter.chapter_pages[n];
document.write('<li id="page_' + n + '" class="comic_page">' +
'<span class="sortable_handle">||</span>' +
'<label for="page_' + n + '_chk">' +
'<input type="checkbox" id="page_' + n + '_chk" />' +
' <span class="page_title">' + page.page_title + '</span>' +
'</label>' +
'</li>');
}
document.write('</ul>' +
'</li>');
}
document.write('</ul>');
</script>
<div id="debug"></div>
<script type="text/javascript">
// hide Chapter contents
$('.comic_chapter ul').hide();
// add onClick => toggle chapter-contents visibility
$('.chapter_title').bind('click', function(e){
$(this).parents('li.comic_chapter').children('ul').toggle();
});
// make Chapters sortable
$('#chapter_list').sortable({
handle: 'div .sortable_handle',
placeholder: 'chapter-placeholder',
forcePlaceholderSize: true
}).disableSelection();
// make Pages sortable
$('.comic_chapter ul').sortable({
handle: '.sortable_handle',
placeholder: 'page-placeholder',
connectWith: '.comic_chapter ul' // allow pages to be dragged between chapters
}).disableSelection();
$('.comic_chapter ul').droppable({
greedy: true
});
// make chapter items droppable
$('#chapter_list').children('li').droppable({
accept: '.comic_page',
hoverClass: 'drop_highlight',
drop: function(e, ui) {
$(this).children('ul').append(ui.draggable);
}
});
</script>
</body>
</html>
Thanks.
I see that you have droppables, but where are the draggables? Droppables accept draggables, not just static html (because, really, nothing is being dropped in that case)

Categories