attempt to index local 'params' (a nil value) error - indexing

This is the full Error
src/states/game/PlayState.lua:21: attempt to index local 'params' (a nil value)
This is the Code where the error occurs, on the line where we call levelmaker.generate specificaly because of params.levelwidth.
function PlayState:enter(params)
self.level = LevelMaker.generate(params.levelwidth or 100, 10, self.levelcount)
self.tileMap = self.level.tileMap
self.levelcount = 1 or params.level
self.player = Player({
x = 0, y = 0,
width = 16, height = 20,
texture = 'green-alien',
stateMachine = StateMachine {
['idle'] = function() return PlayerIdleState(self.player) end,
['walking'] = function() return PlayerWalkingState(self.player) end,
['jump'] = function() return PlayerJumpState(self.player, self.gravityAmount) end,
['falling'] = function() return PlayerFallingState(self.player, self.gravityAmount) end
},
map = self.tileMap,
level = self.level,
score = params.score or 0
})
self:spawnEnemies()
self.player:changeState('falling')
end
The function is from called here and I also pass the params from here:
function generatePole(width, flagPoleColor, Ypos, Xpos, part)
return GameObject {
texture = 'flags',
x = (Xpos - 1) * TILE_SIZE,
y = (Ypos - 1) * TILE_SIZE - 4,
width = 6,
height = 16,
frame = flagPoleColor + part * FLAG_OFFSET,
collidable = true,
consumable = true,
solid = false,
onConsume = function(player, object)
gSounds['pickup']:play()
player.score = player.score + 250
gStateMachine:change('play', {
score = player.score,
levelwidth = levelwidth + 10,
level = levelcounter + 1
})
end
}
end
This is my state machine in which the function gstatemachine:change is written.
StateMachine = Class{}
function StateMachine:init(states)
self.empty = {
render = function() end,
update = function() end,
enter = function() end,
exit = function() end
}
self.states = states or {} -- [name] -> [function that returns states]
self.current = self.empty
end
function StateMachine:change(stateName, enterParams)
assert(self.states[stateName]) -- state must exist!
self.current:exit()
self.current = self.states[stateName]()
self.current:enter(enterParams)
end
function StateMachine:update(dt)
self.current:update(dt)
end
function StateMachine:render()
self.current:render()
end

Related

Inheritance parent-group child-group in Vue.js

How do I create a list of a parent-group (values will be passed from the database) with a child-group in it, which will have the same values as the parent-group.
For example a value called "assignment" which only allow objects.
// DB Set
// DB_table_field = value : [1, 2, 3 , 4, 5], parent_id : [2, 0, 4, 1, 1] // rand two field of id, and parent_id
// sample arr
var sampleArr = [1, 2, 3]
// find parent of parent array
var mergeArr = []
var arr = []
var oi = 2
var coi = oi
arr.push(oi)
while (oi > 0) {
var poi = sampleArr.find(status => status.value === parseInt(oi)).parent_id
if (poi === coi) {
oi = 0
} else {
oi = poi
if (oi > 0) {
arr.push(oi)
}
}
}
// find child of child array
var intialArrMyChild = []
var myId = 1
var myChild = sampleArr.filter(status => status.parent_id === parseInt(myId))
myChild.forEach(element => intialArrMyChild.push(element.value))
var rtnArr = []
var intialArr = []
var xChildArr = []
rtnArr = intialArrMyChild
intialArr = intialArrMyChild
while (rtnArr.length > 0) {
intialArr.forEach(service => {
xChildArr = []
var loopFindChild = sampleArr.filter(status => status.parent_id === parseInt(service))
loopFindChild.forEach(element => xChildArr.push(element.value))
loopFindChild.forEach(element => intialArr.push(element.value))
})
rtnArr = xChildArr
}
var childArr = intialArr.filter(function (item, pos) {
return intialArr.indexOf(item) === pos
})
mergeArr = arr.concat(childArr)
var arrc = mergeArr
var filteredArray = arrc.filter(function (item, pos) {
return arrc.indexOf(item) === pos
})
console.log(filteredArray, 'parentChildfilteredArray')

Button CreateJs

Can anyone help me. CanĀ“t make this button work... I used something similar before. I call this GameMenu as a scene inside another JS.
var scene = new game.GameMenu();
scene.on(game.GameStateEvents.GAME, this.onStateEvent, this, true, {state:game.GameStates.GAME});
stage.addChild(scene);
The button is here inside this code:
(function (window) {
window.game = window.game || {}
function GameMenu() {
this.initialize();
}
var p = GameMenu.prototype = new createjs.Container();
p.btnIniciar;
p.Container_initialize = p.initialize;
p.initialize = function () {
this.Container_initialize();
this.addTitle();
this.addButton();
}
p.addTitle = function () {
var titulo = new createjs.Sprite(spritesheet, 'titulo');
titulo.x = screen_width / 2 - titulo.getBounds().width/2;
titulo.y = screen_height / 2 - titulo.getBounds().height/2;
this.addChild(titulo);
}
p.addButton = function() {
this.btnIniciar = new createjs.Sprite(spritesheet, 'btnIniciar');
this.btnIniciar.mouseEnabled = true;
this.btnIniciar.cursor = 'pointer';
this.btnIniciar.x = screen_width / 2 - this.btnIniciar.getBounds().width/2;
this.btnIniciar.y = (screen_height / 2 - this.btnIniciar.getBounds().height/2) + 200;
stage.addChild(this.btnIniciar);
this.btnIniciar.addEventListener("click", function(event) {
console.log("Click not working");
});
}
window.game.GameMenu = GameMenu;
}(window));

Create Order in prestashop programmatically

I am trying to create an order in prestashop programmatically,
Here are the steps I am following:
$billingAddress = $order->getBillingAddress();
$shippingAddress = $order->getShippingAddress();
if (empty($billingAddress)) {
continue;
}
$id_customer = $this->createPrestashopCustomer($billingAddress, $order->getEmail());
$lines = $order->getLines();
$AddressObject = new AddressCore();
$AddressObject->id_customer = $id_customer;
$AddressObject->firstname = $billingAddress->getfirstName();
$AddressObject->lastname = $billingAddress->getlastName();
$AddressObject->address1 = " " . $billingAddress->getHouseNr();
$AddressObject->address1.= " " . $billingAddress->getHouseNrAddition();
$AddressObject->address1.= " " . $billingAddress->getStreetName();
$AddressObject->address1.= " " . $billingAddress->getZipCode();
$AddressObject->address1.= " " . $billingAddress->getCity();
$AddressObject->city = $billingAddress->getCity();
$AddressObject->id_customer = $id_customer;
$AddressObject->id_country = CountryCore::getByIso($billingAddress->getCountryIso());
$AddressObject->alias = ($billingAddress->getcompanyName() != "") ? "Company" : "Home";
$AddressObject->add();
$currency_object = new CurrencyCore();
$default_currency_object = $currency_object->getDefaultCurrency();
$id_currency = $default_currency_object->id;
$id_address = $AddressObject->id;
$cart = new Cart();
$cart->id_customer = (int) $id_customer;
$cart->id_address_delivery = $id_address;
$cart->id_address_invoice = $id_address;
$cart->id_lang = 1;
$cart->id_currency = (int) $id_address;
$cart->id_carrier = 1;
$cart->recyclable = 0;
$cart->gift = 0;
$cart->add();
if (!empty($lines)) {
foreach ($lines as $item) {
$cart->updateQty(1, 5, 19);
}
}
$cart->update();
$order_object = new OrderCore();
$order_object->id_address_delivery = $id_address;
$order_object->id_address_invoice = $id_address;
$order_object->id_cart = $cart->id;
$order_object->id_currency = $id_currency;
$order_object->id_customer = $id_customer;
$CarrierObject = new CarrierCore();
$CarrierObject->delay[1] = "2-4";
$CarrierObject->active = 1;
$CarrierObject->name = "ChannelEngine Order2";
$CarrierObject->add();
$id_carrier = $CarrierObject->id;
$order_object->id_carrier = $id_carrier;
$order_object->payment = "Channel Engine Order";
$order_object->module = "1";
echo $order->getTotalInclVat();
$order_object->valid = 1;
$order_object->total_paid_tax_excl = $order->getTotalInclVat();
$order_object->total_discounts_tax_incl = $order->getTotalInclVat();
$order_object->total_paid = $order->getTotalInclVat();
$order_object->total_paid_real = $order->getTotalInclVat();
$order_object->total_products = $order->getSubTotalInclVat() - $order->getSubTotalVat();
$order_object->total_products_wt = $order->getSubTotalInclVat();
$order_object->conversion_rate = 1;
$order_object->id_shop = 1;
$order_object->id_lang = 1;
$order_object->secure_key = md5(uniqid(rand(), true));
$order_id = $order_object->add();
The Order is getting added to admin But somehow I can not see products in the order, Can anyone check and let me know what I am doing wrong here.
Also order total is also 0.
You should also create OrderDetail Objects for each product of this order.
Have a look at validateOrder() method of PaymentModule Class.
Here is an extract from this method:
$order = new Order();
$order->product_list = $package['product_list'];
if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') {
$address = new Address((int)$id_address);
$this->context->country = new Country((int)$address->id_country, (int)$this->context->cart->id_lang);
if (!$this->context->country->active) {
throw new PrestaShopException('The delivery address country is not active.');
}
}
$carrier = null;
if (!$this->context->cart->isVirtualCart() && isset($package['id_carrier'])) {
$carrier = new Carrier((int)$package['id_carrier'], (int)$this->context->cart->id_lang);
$order->id_carrier = (int)$carrier->id;
$id_carrier = (int)$carrier->id;
} else {
$order->id_carrier = 0;
$id_carrier = 0;
}
$order->id_customer = (int)$this->context->cart->id_customer;
$order->id_address_invoice = (int)$this->context->cart->id_address_invoice;
$order->id_address_delivery = (int)$id_address;
$order->id_currency = $this->context->currency->id;
$order->id_lang = (int)$this->context->cart->id_lang;
$order->id_cart = (int)$this->context->cart->id;
$order->reference = $reference;
$order->id_shop = (int)$this->context->shop->id;
$order->id_shop_group = (int)$this->context->shop->id_shop_group;
$order->secure_key = ($secure_key ? pSQL($secure_key) : pSQL($this->context->customer->secure_key));
$order->payment = $payment_method;
if (isset($this->name)) {
$order->module = $this->name;
}
$order->recyclable = $this->context->cart->recyclable;
$order->gift = (int)$this->context->cart->gift;
$order->gift_message = $this->context->cart->gift_message;
$order->mobile_theme = $this->context->cart->mobile_theme;
$order->conversion_rate = $this->context->currency->conversion_rate;
$amount_paid = !$dont_touch_amount ? Tools::ps_round((float)$amount_paid, 2) : $amount_paid;
$order->total_paid_real = 0;
$order->total_products = (float)$this->context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier);
$order->total_products_wt = (float)$this->context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier);
$order->total_discounts_tax_excl = (float)abs($this->context->cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier));
$order->total_discounts_tax_incl = (float)abs($this->context->cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier));
$order->total_discounts = $order->total_discounts_tax_incl;
$order->total_shipping_tax_excl = (float)$this->context->cart->getPackageShippingCost((int)$id_carrier, false, null, $order->product_list);
$order->total_shipping_tax_incl = (float)$this->context->cart->getPackageShippingCost((int)$id_carrier, true, null, $order->product_list);
$order->total_shipping = $order->total_shipping_tax_incl;
if (!is_null($carrier) && Validate::isLoadedObject($carrier)) {
$order->carrier_tax_rate = $carrier->getTaxesRate(new Address((int)$this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));
}
$order->total_wrapping_tax_excl = (float)abs($this->context->cart->getOrderTotal(false, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier));
$order->total_wrapping_tax_incl = (float)abs($this->context->cart->getOrderTotal(true, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier));
$order->total_wrapping = $order->total_wrapping_tax_incl;
$order->total_paid_tax_excl = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(false, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_);
$order->total_paid_tax_incl = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(true, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_);
$order->total_paid = $order->total_paid_tax_incl;
$order->round_mode = Configuration::get('PS_PRICE_ROUND_MODE');
$order->round_type = Configuration::get('PS_ROUND_TYPE');
$order->invoice_date = '0000-00-00 00:00:00';
$order->delivery_date = '0000-00-00 00:00:00';
if (self::DEBUG_MODE) {
PrestaShopLogger::addLog('PaymentModule::validateOrder - Order is about to be added', 1, null, 'Cart', (int)$id_cart, true);
}
// Creating order
$result = $order->add();
if (!$result) {
PrestaShopLogger::addLog('PaymentModule::validateOrder - Order cannot be created', 3, null, 'Cart', (int)$id_cart, true);
throw new PrestaShopException('Can\'t save Order');
}
// Amount paid by customer is not the right one -> Status = payment error
// We don't use the following condition to avoid the float precision issues : http://www.php.net/manual/en/language.types.float.php
// if ($order->total_paid != $order->total_paid_real)
// We use number_format in order to compare two string
if ($order_status->logable && number_format($cart_total_paid, _PS_PRICE_COMPUTE_PRECISION_) != number_format($amount_paid, _PS_PRICE_COMPUTE_PRECISION_)) {
$id_order_state = Configuration::get('PS_OS_ERROR');
}
$order_list[] = $order;
if (self::DEBUG_MODE) {
PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderDetail is about to be added', 1, null, 'Cart', (int)$id_cart, true);
}
// Insert new Order detail list using cart for the current order
$order_detail = new OrderDetail(null, null, $this->context);
$order_detail->createList($order, $this->context->cart, $id_order_state, $order->product_list, 0, true, $package_list[$id_address][$id_package]['id_warehouse']);
$order_detail_list[] = $order_detail;
if (self::DEBUG_MODE) {
PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderCarrier is about to be added', 1, null, 'Cart', (int)$id_cart, true);
}
// Adding an entry in order_carrier table
if (!is_null($carrier)) {
$order_carrier = new OrderCarrier();
$order_carrier->id_order = (int)$order->id;
$order_carrier->id_carrier = (int)$id_carrier;
$order_carrier->weight = (float)$order->getTotalWeight();
$order_carrier->shipping_cost_tax_excl = (float)$order->total_shipping_tax_excl;
$order_carrier->shipping_cost_tax_incl = (float)$order->total_shipping_tax_incl;
$order_carrier->add();
}
Create Order Programatically in prestashop, we need to use validate order function to create order manually in prestashop.
<?php
$cart = new Cart(Context::getContext()->cart);
$summary = $cart->getSummaryDetails($id_lang,true);
$total = (string) $summary['total_price'];
$cashondelivery = new CashOnDelivery();
if($cashondelivery->validateOrder((int) $cart->id,2, $total, $cashondelivery->displayName, null, array(),$id_currency, false, false)) {
$result['orderid']=(string)$cashondelivery->currentOrder;
return $result;
}

Raphael-js drag and click events inaccurate after browser resize

I've created a radial dial using the Raphael-js library and it works as should on page load. It's embedded in a responsive layout so I want it to resize according to it's container, which it does. However, the new container size makes the mouse events inaccurate. When I resize it back to what it was on page load, it works fine.
function RadialDial(paperId, opts) {
var thisObj = this;
this.dialParent = document.querySelector(paperId);
this.divPaper = this.dialParent.querySelector('.radialDial');
this.divPaperW = this.divPaper.clientWidth;
this.scaleRatio = this.divPaperW / 250;
this.outputEle = this.dialParent.querySelector('.dialOutput .val');
this.btnPlus = this.dialParent.querySelector('.btnPlus');
this.btnMinus = this.dialParent.querySelector('.btnMinus');
this.debug = this.dialParent.querySelector('.debug');
this.opts = {
dialCenter: this.divPaperW / 2,
dialRadius: this.divPaperW / 2,
startA: 155,
endA: 25,
arcCentralA: 230,
maxRange: 12,
minRange: 3,
postText: false,
rangeSteps: 3
}
this.currNeedleA;
this.rangeAngles = [];
this.setOptions(opts);
this.paper = Raphael(this.divPaper, this.opts.dialRadius * 2, this.opts.dialRadius * 2);
this.rangeDivisions = Raphael.rad(this.opts.arcCentralA / (this.opts.maxRange - this.opts.minRange));
this.arcStartX = (this.opts.dialCenter + ((this.opts.dialRadius - (30 * this.scaleRatio)) * Math.cos(Raphael.rad(this.opts.startA)))).toString();
this.arcStartY = (this.opts.dialCenter + ((this.opts.dialRadius - (30 * this.scaleRatio)) * Math.sin(Raphael.rad(this.opts.startA)))).toString();
var currSectorX = this.arcStartX;
var currSectorY = this.arcStartY;
var dialFaceAtts = (Raphael.svg) ? {fill: "r#ffffff-#ffffff:85-#999999:75-#cccccc:57-#999999", stroke: "none"} : {fill: "#ffffff", stroke: "#999999", "stroke-width": (1 * this.scaleRatio)};
this.dialFace = this.paper.circle(this.opts.dialCenter, this.opts.dialCenter, this.opts.dialRadius).attr(dialFaceAtts);
var dialFaceRim = this.paper.circle(this.opts.dialCenter, this.opts.dialCenter, (102 * this.scaleRatio)).attr({fill: "none", "stroke-width": (8 * this.scaleRatio), stroke: "#eeeeee", "stroke-opacity": 0.4});
var currSectorAngle = Raphael.rad(this.opts.startA);
var rangeSet = this.paper.set();
for (var i = this.opts.minRange; i <= (this.opts.maxRange); i++) {
currSectorX = (this.opts.dialCenter + ((this.opts.dialRadius - (40 * this.scaleRatio)) * Math.cos(currSectorAngle))).toString();
currSectorY = (this.opts.dialCenter + ((this.opts.dialRadius - (40 * this.scaleRatio)) * Math.sin(currSectorAngle))).toString();
if (i % this.opts.rangeSteps == 0) {
var rangeTxt = this.paper.text(currSectorX, currSectorY, i).attr({fill: "#00a2d8", "font-size": (22 * this.scaleRatio).toString()});
rangeSet.push(rangeTxt);
this.rangeAngles[i] = Raphael.deg(this.rangeDivisions * (i - (this.opts.minRange)));
}
currSectorAngle = currSectorAngle + this.rangeDivisions;
}
this.clickArea = this.paper.circle(this.opts.dialCenter, this.opts.dialCenter, this.opts.dialRadius).attr({fill: "red", "fill-opacity": 0, stroke: "none"});
this.needle = this.paper.path("M" + (this.arcStartX).toString() + "," + (this.arcStartY).toString() +
"L" + (this.opts.dialCenter * (138.89401 / this.opts.dialCenter) * this.scaleRatio).toString() + "," + (this.opts.dialCenter * (107.45764 / this.opts.dialCenter) * this.scaleRatio).toString() +
"L" + (this.opts.dialCenter * (147.34637 / this.opts.dialCenter) * this.scaleRatio).toString() + "," + (this.opts.dialCenter * (125.5838 / this.opts.dialCenter) * this.scaleRatio).toString() + "z").attr({fill: '#0058b6', stroke: "none"});/* */
var needleLine = this.paper.path("M" + (this.opts.dialCenter + (18 * this.scaleRatio)).toString() + ' ' + (this.opts.dialCenter - (8 * this.scaleRatio)).toString() + ", L" + this.arcStartX + "," + this.arcStartY).attr({stroke: "#ffffff", "stroke-width": .7});
var centerCircle = this.paper.circle(this.opts.dialCenter, this.opts.dialCenter, (12 * this.scaleRatio)).attr({fill: "#0058b6", stroke: "none"});
this.needleSet = this.paper.set();
this.needleSet.push(this.needle, needleLine);
this.dialSet = this.paper.set();
this.dialSet.push(dialFaceRim, this.dialFace, this.clickArea, this.needleSet, rangeSet, centerCircle, needleLine);
this.paper.setViewBox(0, 0, this.opts.dialRadius * 2, this.opts.dialRadius * 2, true);
this.paper.canvas.setAttribute('preserveAspectRatio', 'none');
this.needleSet.push(this.needle);
this.needleSet.data('thisObj', thisObj);
this.needleSet.data('paperObj', this.paper.canvas);
this.setNeedleDrag();
this.dialFaceClick();
}
RadialDial.prototype = {
constructor: RadialDial,
setOptions: function (opts) {
for (key in opts) {
if (!opts.hasOwnProperty(key)) {
continue;
}
this.opts[key] = opts[key];
}
},
drawDial: function () {
},
elePosition: function (ele) {
var eleX = 0;
var eleY = 0;
while (ele) {
eleX += (ele.offsetLeft - ele.scrollLeft + ele.clientLeft);
eleY += (ele.offsetTop - ele.scrollTop + ele.clientTop);
ele = ele.offsetParent;
}
return {x: eleX, y: eleY};
},
moveNeedle: function (dx, dy, x, y, e) {
var classObj = this.data('thisObj');
var rectObject = classObj.divPaper.getBoundingClientRect();
var paperXY = classObj.elePosition(classObj.divPaper);
var mouseX, mouseY;
mouseX = e.clientX - rectObject.left;
mouseY = e.clientY - rectObject.top;
var needleA = Raphael.angle(classObj.opts.dialCenter, classObj.opts.dialCenter, classObj.needle.getPointAtLength(classObj.needle.getTotalLength())['x'], classObj.needle.getPointAtLength(classObj.needle.getTotalLength())['y']);
var newA = Raphael.angle(classObj.opts.dialCenter, classObj.opts.dialCenter, mouseX, mouseY);
var rotateAngle = (360 - needleA) + newA;
if (!(newA > (360 - classObj.opts.startA) && newA < (360 - classObj.opts.endA))) {
classObj.needleSet.transform('r' + rotateAngle + "," + classObj.opts.dialCenter + "," + classObj.opts.dialCenter);
}
},
setNeedleDrag: function () {
var startDrag = function () {
}, dragger = this.moveNeedle,
endDrag = this.findNearestStep;
this.needleSet.drag(dragger, startDrag, endDrag);
},
dialFaceClick: function () {
var classObj = this;
this.clickArea.node.onclick = function (e) {
var e = e || window.event;
var rectObject = classObj.divPaper.getBoundingClientRect();
var mouseX, mouseY;
mouseX = e.clientX - rectObject.left;
mouseY = e.clientY - rectObject.top;
var needleA = Raphael.angle(classObj.opts.dialCenter, classObj.opts.dialCenter, classObj.needle.getPointAtLength(classObj.needle.getTotalLength())['x'], classObj.needle.getPointAtLength(classObj.needle.getTotalLength())['y']);
var newA = Raphael.angle(classObj.opts.dialCenter, classObj.opts.dialCenter, mouseX, mouseY);
var rotateAngle = (360 - needleA) + newA;
if (!(newA > (360 - classObj.opts.startA) && newA < (360 - classObj.opts.endA))) {
classObj.needleSet.transform('r' + rotateAngle + "," + classObj.opts.dialCenter.toString() + "," + classObj.opts.dialCenter.toString());
}
classObj.findNearestStep(classObj);
return false;
}
},
findNearestStep: function (obj) {
var classObj = (obj.target || obj.srcElement) ? this.data('thisObj') : obj;
var currVal = Math.round((Raphael.rad(classObj.needle.matrix.split().rotate) * ((classObj.opts.maxRange - classObj.opts.minRange) / Raphael.rad(classObj.opts.arcCentralA))) + classObj.opts.minRange);
var nextVal = currVal;
var prevVal, newA, index;
if (currVal % classObj.opts.rangeSteps != 0) {
while (nextVal % classObj.opts.rangeSteps != 0) {
nextVal = nextVal + 1;
}
if ((nextVal - currVal) > (classObj.opts.rangeSteps / 2)) {
nextVal = nextVal - classObj.opts.rangeSteps;
}
index = nextVal;
} else {
index = currVal;
}
newA = classObj.rangeAngles[index];
classObj.needleSet.transform('r' + (newA) + "," + classObj.opts.dialCenter + "," + classObj.opts.dialCenter);
}
}
Here is my fiddle, http://jsfiddle.net/fiddle_fish/rvLo1cuy/ , dragging the needle makes it follow the mouse pointer closely. Now click the "Resize container" link, whilst the needle still moves it doesn't follow the pointer closely. It seems the resize has created an offset for the mouse event target area.
I've tried changing the viewbox settings, width/height values,removing events and reapplying them, deleting the dial on resize and redrawing the dial but nothing works.
Tried, raphael js, calculate setViewBox width height to fix window
and, raphael js, resize canvas then setViewBox to show all elements
Neither works. :(
I sussed this out. I've multiplied the mouse x-y coordinates with a ratio based on the paper size onload/resize. Works a treat :)
I just encountered the same issue. Basically, on window resize I recalculate the "scale" i.e. the ratio of the svg element's viewBox to its current height/width.
Here's my solution:
var scale = {
x:1,
y:1
}
$(window).resize(function(){
scale = getScale(paper);
})
function getScale(paper){
var x = paper.canvas.viewBox.baseVal.width/$(paper.canvas).width();
var y = paper.canvas.viewBox.baseVal.height/$(paper.canvas).height();
return {
x:x,
y:y
}
}
and then in my "move" function, I added a multiplier to dx and dy:
var move = function (dx, dy,x,y) {
var X = this.cx + dx * scale.x,
Y = this.cy + dy * scale.y;
this.attr({cx: X, cy: Y});
}
For context, the move function is used like so:
var start = function(){
this.cx = this.attr("cx"),
this.cy = this.attr("cy");
}, move = function (dx, dy,x,y) {
var X = this.cx + dx * scale.x,
Y = this.cy + dy * scale.y;
this.attr({cx: X, cy: Y});
}
raphael_element.drag(move,start);
Note that there's some JQuery thrown in here that you could easily do without.

How best to traverse API information with iOS

Is there any easier way of traversing array/dictionaries without creating a lot of separate NSArrays/NSDictionaries? I know you can traverse nested dictionaries with dot notation and value at keypath, but what about when arrays are involved?
For example:
At the moment if I want to get at the object at feed.entry.link[4].href in the API result below, I have to define an array at keypath "feed.entry", then assign its first entry as a dictionary, then define an array at keypath "link" and access its fourth entry as a dictionary, and then access its value at "href".
Is this normal?
received {
encoding = "UTF-8";
feed = {
entry = (
{
author = (
{
name = {
"$t" = swdestiny;
};
uri = {
"$t" = "https://gdata.youtube.com/feeds/api/users/swdestiny";
};
}
);
category = (
{
scheme = "http://schemas.google.com/g/2005#kind";
term = "http://gdata.youtube.com/schemas/2007#video";
},
{
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
term = Entertainment;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Star;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Wars;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Episode;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = 3;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Revenge;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = of;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = the;
},
{
scheme = "http://gdata.youtube.com/schemas/2007/keywords.cat";
term = Sith;
}
);
content = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = text;
};
"gd$comments" = {
"gd$feedLink" = {
countHint = 1567;
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/comments";
rel = "http://gdata.youtube.com/schemas/2007#comments";
};
};
"gd$rating" = {
average = "4.7729683";
max = 5;
min = 1;
numRaters = 1132;
rel = "http://schemas.google.com/g/2005#overall";
};
id = {
"$t" = "http://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
};
link = (
{
href = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata";
rel = alternate;
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/responses";
rel = "http://gdata.youtube.com/schemas/2007#video.responses";
type = "application/atom+xml";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc/related";
rel = "http://gdata.youtube.com/schemas/2007#video.related";
type = "application/atom+xml";
},
{
href = "https://m.youtube.com/details?v=9kdEsZH5ohc";
rel = "http://gdata.youtube.com/schemas/2007#mobile";
type = "text/html";
},
{
href = "https://gdata.youtube.com/feeds/api/videos/9kdEsZH5ohc";
rel = self;
type = "application/atom+xml";
}
);
"media$group" = {
"media$category" = (
{
"$t" = Entertainment;
label = Entertainment;
scheme = "http://gdata.youtube.com/schemas/2007/categories.cat";
}
);
"media$content" = (
{
duration = 151;
expression = full;
isDefault = true;
medium = video;
type = "application/x-shockwave-flash";
url = "https://www.youtube.com/v/9kdEsZH5ohc?version=3&f=videos&app=youtube_gdata";
"yt$format" = 5;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache4.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 1;
},
{
duration = 151;
expression = full;
medium = video;
type = "video/3gpp";
url = "rtsp://v2.cache5.c.youtube.com/CiILENy73wIaGQkXovmRsURH9hMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp";
"yt$format" = 6;
}
);
"media$description" = {
"$t" = "sw-destiny.net Trailer for Revenge of the Sith";
type = plain;
};
"media$keywords" = {
"$t" = "Star, Wars, Episode, 3, Revenge, of, the, Sith";
};
"media$player" = (
{
url = "https://www.youtube.com/watch?v=9kdEsZH5ohc&feature=youtube_gdata_player";
}
);
"media$thumbnail" = (
{
height = 360;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/0.jpg";
width = 480;
},
{
height = 90;
time = "00:00:37.750";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/1.jpg";
width = 120;
},
{
height = 90;
time = "00:01:15.500";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/2.jpg";
width = 120;
},
{
height = 90;
time = "00:01:53.250";
url = "http://i.ytimg.com/vi/9kdEsZH5ohc/3.jpg";
width = 120;
}
);
"media$title" = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = plain;
};
"yt$duration" = {
seconds = 151;
};
};
published = {
"$t" = "2007-05-23T03:31:54.000Z";
};
title = {
"$t" = "Star Wars Episode 3 Revenge of the Sith Trailer";
type = text;
};
updated = {
"$t" = "2012-02-20T17:14:37.000Z";
};
"yt$statistics" = {
favoriteCount = 763;
viewCount = 796719;
};
}
);
xmlns = "http://www.w3.org/2005/Atom";
"xmlns$gd" = "http://schemas.google.com/g/2005";
"xmlns$media" = "http://search.yahoo.com/mrss/";
"xmlns$yt" = "http://gdata.youtube.com/schemas/2007";
};
version = "1.0";
}